]> git.imager.perl.org - bse.git/blobdiff - site/templates/preload.tmpl
re-work coupons to allow multiple coupon types
[bse.git] / site / templates / preload.tmpl
index e5d368455c89ad1b30b4e21ecea48bbbeaa2d98e..f7b1811acf87438ff210bd9bec4c2294a6cefd85 100644 (file)
@@ -1,18 +1,80 @@
+<:# see preload.pod for documentation -:>
+<:.set dist_image_uri = cfg.entryIfVar("uri", "dist_images", "/images") -:>
 <:# utility definitions :>
-<:-.define make_select-:>
+<:-.define make_select; groups: 0, grouplabel: "label", groupid: "id",
+          itemgroupid: "groupid", attr: {} -:>
   <:-.if !default.defined -:>
     <:-.set default = "" -:>
   <:.end if:>
-  <select name="<:= name | html :>">
-  <:-.for i in list -:>
+  <select name="<:= name | html :>"<:.call "elementextra", extra:attr:>>
+  <:- .if groups -:>
+    <:-.for i in list -:>
+      <:.if i.$itemgroupid eq "" -:>
     <option value="<:= i.$id | html :>"
-      <:- .if i.$id eq default :> selected="selected"<:.end if -:>
+          <:- .if i.$id eq default :> selected="selected"<:.end if -:>
     >
-    <:= i.$desc | html :>
-  <:-.end for-:>
+        <:-= i.$desc | html -:>
+      <:.end if -:>
+    <:.end for -:>
+    <:-.for g in groups -:>
+    <optgroup label="<:= g.$grouplabel | html -:>">
+      <:-.for i in list -:>
+        <:.if i.$itemgroupid == g.$groupid -:>
+      <option value="<:= i.$id | html :>"
+          <:- .if i.$id eq default :> selected="selected"<:.end if -:>
+      >
+          <:-= i.$desc | html -:>
+        <:.end if -:>
+      <:.end for -:>
+    </optgroup>
+    <:-.end for -:>
+  <:- .else -:>
+    <:-.for i in list -:>
+    <option value="<:= i.$id | html :>"
+        <:- .if i.$id eq default :> selected="selected"<:.end if -:>
+    >
+      <:-= i.$desc | html -:>
+    <:-.end for-:>
+  <:-.end if -:>
   </select>
 <:-.end define -:>
 <:#
+make_multicheck expects:
+  values - list of hashes
+  default - a list of ids of checks to be checked
+  id - the name of the id field
+  desc - the name of the description field.
+  name - the name of the input elements
+  readonly - true to make it readonly
+  attr - extra attributes to set on the generated inputs
+-:>
+<:-.define make_multicheck; readonly: 0, attr: {}-:>
+  <:.if !readonly -:>
+  <input type="hidden" name="_save_<:= name -:>" value="1">
+  <:.end if -:>
+  <:-.if !default.defined -:>
+    <:-.set default = [] -:>
+  <:.end if:>
+  <:.set checked = {} -:>
+  <:.for v in default -:>
+    <:% checked.set(v, 1) -:>
+  <:.end for -:>
+  <ul>
+  <:-.for i in values -:>
+    <li>
+    <:.set element_id = name _ "-" _ i.$id -:>
+    <input type="checkbox" name="<:= name :>" <:= checked[i.$id] ? 'checked ' : '' -:>
+      id="<:= element_id -:>" value="<:= i.$id :>"
+<:-# readonly attribute isn't valid for checkboxes -:>
+<:-= readonly ? " disabled" : "" -:>
+<:-.call "elementextra", extra: attr -:>
+    >
+    <label for="<:= element_id :>"><:= i.$desc -:></label>
+    </li>
+  <:-.end for -:>
+  </ul>
+<:-.end define -:>
+<:#
 page_list expects:
 base - base url for links
 pages - the result of the bse.pages call
@@ -29,7 +91,7 @@ Page <:= pages.page :> of <:= pages.pagecount :>
 <span>&lt&lt</span>
 <span>&lt</span>
 <:.end if -:>
-<:.for p in pcats.pages :>
+<:.for p in pages.pages :>
 <:.if p.link -:>
 <a href="<:= base |html :><:= pages.pname | uri:>=<:= p.page | uri :>&amp;<:=pages.ppname | uri :>=<:= pages.pp | uri :>"><:= p.page |html :></a>
 <:.else -:>
@@ -46,86 +108,376 @@ Page <:= pages.page :> of <:= pages.pagecount :>
 </div>
 <:-.end define -:>
 
-<:.define old -:>
-<:# parameters: field, default -:>
-<:  .if cgi.param(field).defined -:>
-<:= cgi.param(field) -:>
+<:.define old; default: "", index: 0 -:>
+<:# parameters: field, default, index  -:>
+<:  .set vals = [ cgi.param(field) ] -:>
+<:  .if index < vals.size -:>
+<:= vals[index] -:>
 <:  .else -:>
 <:= default | html -:>
 <:  .end if -:>
 <:.end define-:>
 
+<:.define error_img_n -:>
+<:# parameters:
+   field - name of field
+   index - index of field
+   errors - hash of error messages (should be set by code)
+-:>
+  <:.if errors.$field -:>
+    <:.set msg = errors.$field -:>
+    <:.set msg = msg.is_list ? msg[index] : msg -:>
+    <:.if msg.defined -:>
+      <:.set image = cfg.entry("error_img", "image", dist_image_uri _ "/admin/error.gif") -:>
+      <:.set width = cfg.entry("error_img", "width", 16) -:>
+      <:.set height = cfg.entry("error_img", "height", 16) -:>
+    <img src="<:= image -:>" alt="<:= msg :>" title="<:= msg :>" width="<:= width :>" height="<:= height :>" class="error_img">
+    <:.end if -:>
+  <:.end if -:>
+<:.end define -:>
+
 <:.define error_img -:>
-<:# parameters: field -:>
-<:# this implementation should probably change -:>
-<:= ("error_img " _ field).evaltag -:>
+<:.call "error_img_n", index:0 -:>
 <:.end define -:>
 
-<:.define input -:>
-<:# paramaters:
+<:.define elementextra -:>
+<:  .set extratext = "" -:>
+<:  .if extra.defined -:>
+<:    .for n in extra.keys -:>
+<:      .set extratext = extratext _ " " _ n _ '="' _ extra[n].escape("html") _ '"' -:>
+<:    .end for -:>
+<:  .end if -:>
+<:= extratext |raw -:>
+<:.end define -:>
+
+<:.define input; options: {} -:>
+<:# parameters:
   name - field name
-  fields - hash of fields (may be set by page instead)
+  field - entry from fields
   object - source for defaults in edit mode
-:>
-<:  .set f = fields[name] -:>
-<:  .if object -:>
-<:     .set default = object.get(name) -:>
-<:  .elsif f.default -:>
-<:     .set default = f.default -:>
-<:  .else -:>
-<:     .set default = "" -:>
+-:>
+<:  .set default = options.default -:>
+<:  .if !default.defined -:>
+<:    .if object -:>
+<:       .set default = object.$name -:>
+<:    .elsif field.default -:>
+<:       .set default = field.default -:>
+<:    .else -:>
+<:       .set default = "" -:>
+<:    .end if -:>
+<:  .end if -:>
+<:  .if field.type and field.type eq "date" and default ne "" -:>
+<:    .set default = default.replace(/(\d+)\D+(\d+)\D+(\d+)/, "$3/$2/$1") -:>
+<:  .elsif field.type and field.type eq "time" and default ne "" -:>
+<:    .set default = bse.date(default =~ /:00$/ ? "%I:%M%p" : "%I:%M:%S%p", default).replace(/^0/, "").lower() -:>
+<:  .elsif field.type and field.type eq "money" and default ne "" -:>
+<:    .set default = bse.number("money", default) -:>
 <:  .end if -:>
-<:  .if f.htmltype eq "textarea" -:>
-<textarea id="<:= name | html :>" name="<:= name | html :>" rows="<:= f.height ? f.height : cfg.entry("forms", "textarea_rows", 10) :>" cols=<:= f.width ? f.width : cfg.entry("textarea_cols", 60) | html :>>
-<:-    .call "old", "field":name, "default":default -:>
+<:  .if cgi.param(name).defined -:>
+<:     .set default = cgi.param(name) -:>
+<:  .end if -:>
+<:  .if field.htmltype eq "textarea" -:>
+<textarea id="<:= name | html :>" name="<:= name | html :>" rows="<:= field.height ? field.height : cfg.entry("forms", "textarea_rows", 10) :>" cols=<:= field.width ? field.width : cfg.entry("forms", "textarea_cols", 60) | html :><:.call "elementextra", extra: options.inputattr :>>
+<:-= default | html -:>
 </textarea>
-<:  .elsif f.htmltype eq "checkbox" -:>
-<:.set is_checked = request.method() eq 'post' ? cgi.param(name).defined : default -:>
-<input id="<:= name | html :>" type="checkbox" name="<:= name | html :>"<:= is_checked ? ' checked="checked"' : '' :> value="<:= f.value ? f.value : 1 | html :>" />
-<:  .elsif f.htmltype eq "select" -:>
-<:.set values = f.select["values"] -:>
+<:  .elsif field.htmltype eq "checkbox" -:>
+<:.set is_checked = cgi.param("_save_" _ name) ? cgi.param(name).defined : default -:>
+<input type="hidden" name="_save_<:= name -:>" value="1">
+<input id="<:= name | html :>" type="checkbox" name="<:= name | html :>"<:= is_checked ? ' checked="checked"' : '' :> value="<:= field.value ? field.value : 1 | html :>"<:.call "elementextra", extra: options.inputattr :> />
+<:  .elsif field.htmltype eq "multicheck" -:>
+<:# we expect default to be a list of selected checks -:>
+<:.set values = field.select["values"] -:>
+<:.set values = values.is_code ? values() : values -:>
+<:.set default = cgi.param("_save_" _ name) ? [ cgi.param(name) ] : default -:>
+<:.call "make_multicheck",
+  id:field.select.id,
+  desc:field.select.label,
+  attr: options.inputattr -:>
+<:  .elsif field.htmltype eq "select" -:>
+<:.set values = field.select["values"] -:>
 <:.set values = values.is_code ? values() : values -:>
 <:.call "make_select",
-    "name":name,
-    "default":default,
-    "list":values,
-    "id":f.select.id,
-    "desc":f.select.label
+    name: name,
+    default: default,
+    list: values,
+    id: field.select.id,
+    desc: field.select.label,
+    groupid : (field.select.groupid or "id"),
+    itemgroupid: (field.select.itemgroupid or "groupid"),
+    groups: field.select.groups ? (field.select.groups.is_code ? (field.select.groups)() : field.select.groups ) : 0,
+    grouplabel: (field.select.grouplabel or "label"),
+    attr: options.inputattr
 -:>
-<:  .else -:>
-<:    .if f.type and f.type eq "date" and default ne "" -:>
-<:      .set default = default.replace(/(\d+)\D+(\d+)\D+(\d+)/, "$3/$2/$1") -:>
-<:    .end if -:>
-<input id="<:= name | html :>" type="text" name="<:= name | html :>" value="<:.call "old", "field":name, "default":default :>" 
-<:-= f.maxlength ? ' maxlength="' _ f.maxlength _ '"' : '' :>
-<:= f.width ? 'size="' _ f.width _ '"' : '' :> />
+<:  .elsif field.htmltype eq 'file' -:>
+<:   .if default.length -:>
+<span class="filename"><:= default :></span>
+<:   .end if -:>
+<input id="<:= name :>" type="file" name="<:= name :>"<:.call "elementextra", extra: options.inputattr :> />
+<:- .else -:>
+<input id="<:= name | html :>" type="text" name="<:= name | html :>" value="<:=  default | html :>" 
+<:-= field.maxlength ? ' maxlength="' _ field.maxlength _ '"' : '' |raw:>
+<:-= field.width ? ' size="' _ field.width _ '"' : '' | raw :><:.call "elementextra", extra: options.inputattr :> />
 <:  .end if -:>
 <:.end define -:>
 
-<:.define field -:>
-<:# paramaters:
+<:.define field; options: {} -:>
+<:# parameters:
+  name - field name
+  fields - hash of fields (may be set by page instead)
+  object - object containing defaults (can be set globally instead)
+  default - a default value not dependent on object (overrides object)
+:>
+  <:.if fields.is_hash -:>
+    <:.set f = fields[name] -:>
+    <:.if f -:>
+      <:.call "inlinefield", field:f, name:name, options: options -:>
+    <:.else -:>
+<p>Unknown field id '<b><:= name :></b>', available fields are '<:= fields.keys.join("', '") :>'</p>
+    <:.end if -:>
+  <:.else -:>
+<p>fields isn't a hash, something is wrong.</p>
+  <:.end if -:>
+<:.end define -:>
+
+<:.define inlinefield; options: {} -:>
+<:# parameters:
+  name - the field name
+  field - a field, as an entry in fields
+  options - various options, including:
+     note - display this text as a note below the field
+     delete - add a delete checkbox
+     default - a custom default value, overrides object
+     htmlattr - attributes for the wrapper div
+     inputattr - attributes for the input/select generated
+-:>
+  <:.if field.is_hash -:>
+  <:.set divextra = "" -:>
+  <:.if options.htmlattr :>
+    <:.for n in options.htmlattr.keys -:>
+      <:.set divextra = divextra _ " " _ n _ '="' _ options.htmlattr[n].escape("html") _ '"' -:>
+    <:.end for -:>
+  <:.end if -:>
+<div<:= divextra |raw:>>
+  <label for="<:= name :>"><:= field.nolabel ? "" : field.description | html :>:</label>
+  <span>
+    <:-.if field.readonly -:>
+<:-.call "display", name:name, options: options -:>
+    <:.else -:>
+<:-.call "input", name:name, options: options -:><:.call "error_img", field:name :>
+    <:-.end if -:>
+    <:-.if field.units -:>
+      <:-= field.units | html -:>
+    <:-.end if -:>
+    <:-.if options.note -:>
+<br /><:= options.note | raw :>
+    <:-.end if -:>
+    <:-.if options["delete"] -:>
+<br /><input type="checkbox" name="delete_<:= name :>" value="1" id="delete_<:= name :>"><label for="delete_<:= name :>">Delete</label>
+    <:-.end if -:>
+</span>
+</div>
+  <:.end if -:>
+<:.end define -:>
+
+<:.define fieldset -:>
+<:# like field, but wrap in a per-field field set.
+parameters:
   name - field name
   fields - hash of fields (may be set by page instead)
 :>
   <:.set f = fields[name] -:>
+  <:.if f.is_hash -:>
+<fieldset>
+    <:.if !f.nolabel -:>
+  <legend><:= f.description :></legend>
+    <:.end if -:>
+  <:.call "input", name: name, field: f -:>
+</fieldset>
+  <:.elsif fields.is_hash -:>
+<p>Unknown field id '<b><:= name :></b>', available fields are '<:= fields.keys.join("', '") :>'</p>
+  <:.else -:>
+<p>fields isn't a hash, something is wrong.</p>
+  <:.end if -:>
+<:.end define -:>
+
+<:.define display -:>
+<:# paramaters:
+  name - field name
+  field - entry from fields
+  object - source for defaults in edit mode
+:>
+<:  .if object -:>
+<:     .set default = object.$name -:>
+<:  .end if -:>
+<:  .if field.type and field.type eq "date" and default ne "" -:>
+<:    .set default = default.replace(/(\d+)\D+(\d+)\D+(\d+)/, "$3/$2/$1") -:>
+<:  .elsif field.type and field.type eq "time" and default ne "" -:>
+<:    .set default = bse.date(default =~ /:00$/ ? "%I:%M%p" : "%I:%M:%S%p", default).replace(/^0/, "").lower() -:>
+<:  .end if -:>
+<:  .if field.htmltype eq "textarea" -:>
+<textarea id="<:= name | html :>" name="<:= name | html :>" rows="<:= field.height ? field.height : cfg.entry("forms", "textarea_rows", 10) :>" cols=<:= field.width ? field.width : cfg.entry("textarea_cols", 60) | html :> readonly>
+<:-= default | html -:>
+</textarea>
+<:  .elsif field.htmltype eq "checkbox" -:>
+<input id="<:= name | html :>" type="checkbox" name="<:= name | html :>"<:= is_checked ? ' checked="checked"' : '' :> value="<:= field.value ? field.value : 1 | html :>" readonly>
+<:  .elsif field.htmltype eq "multicheck" -:>
+<:# we expect default to be a list of selected checks -:>
+<:.set values = field.select["values"] -:>
+<:.set values = values.is_code ? values() : values -:>
+<:.call "make_multicheck",
+  id: field.select.id,
+  desc: field.select.label,
+  readonly: 1 -:>
+<:  .elsif field.htmltype eq "select" -:>
+<:.set values = field.select["values"] -:>
+<:.set values = values.is_code ? values() : values -:>
+<:# find the selected value and display it's label -:>
+<:.set sid = field.select.id -:>
+<:.set sdesc = field.select.label -:>
+<:.for value in values -:>
+  <:.if value.$id eq default -:>
+    <:= value.$desc -:>
+  <:.end if -:>
+<:.end for -:>
+<:  .else -:>
+<input id="<:= name  :>" type="text" name="<:= name :>" value="<:=  default :>"
+<:-= field.width ? ' size="' _ field.width _ '"' : '' | raw :> readonly>
+<:  .end if -:>
+<:.end define -:>
+
+<:.define inlinefieldro -:>
+<:# parameters:
+  name - the field name
+  field - a field, as an entry in fields
+-:>
+  <:.if field.is_hash -:>
 <div>
-  <label for="<:= name | html :>"><:= f.nolabel ? "" : f.description | html :>:</label>
-  <span><:.call "input", "name":name -:><:.call "error_img", "field":name :>
-  <:-.if f.units -:>
-    <:-= f.units | html -:>
-  <:-.end if -:>
+  <label for="<:= name :>"><:= field.nolabel ? "" : field.description :>:</label>
+  <span><:.call "display", name:name -:>
+    <:-.if field.units -:>
+      <:-= field.units -:>
+    <:-.end if -:>
+  <:.end if -:>
 </span>
 </div>
 <:.end define -:>
 
+<:.define fieldro -:>
+<:# like field, but for display, not editing -:>
+  <:.if fields.is_hash -:>
+    <:.set f = fields[name] -:>
+    <:.if f -:>
+      <:.call "inlinefieldro", field:f, name:name -:>
+    <:.else -:>
+<p>Unknown field id '<b><:= name :></b>', available fields are '<:= fields.keys.join("', '") :>'</p>
+    <:.end if -:>
+  <:.else -:>
+<p>fields isn't a hash, something is wrong.</p>
+  <:.end if -:>
+<:.end define -:>
+
+<:.define fieldsetro -:>
+<:# like fieldro, but wrap in a per-field field set.
+parameters:
+  name - field name
+  fields - hash of fields (may be set by page instead)
+:>
+  <:.set f = fields[name] -:>
+  <:.if f.is_hash -:>
+<fieldset>
+    <:.if !f.nolabel -:>
+  <legend><:= f.description :></legend>
+    <:.end if -:>
+  <:.call "display", "name":name, "field":f -:>
+</fieldset>
+  <:.elsif fields.is_hash -:>
+<p>Unknown field id '<b><:= name :></b>', available fields are '<:= fields.keys.join("', '") :>'</p>
+  <:.else -:>
+<p>fields isn't a hash, something is wrong.</p>
+  <:.end if -:>
+<:.end define -:>
+
 <:.define messages -:>
 <:  .if request.messages.size -:>
 <div class="messages">
 <:     .for m in request.messages -:>
-  <div class="<:= m.class :>"><:= m.html :></div>
+  <div class="<:= m.class :>"><:= m.html |raw :></div>
 <:     .end for -:> 
 </div>
 <:  .end if -:>
 <:.end define -:>
 
+<:.define mover -:>
+<:# expects loop, request, parent
+  which in most cases means you can just supply parent
+-:>
+<:.if request.user_can("bse_edit_reorder_children", parent) -:>
+  <:.set down_url = loop.next ? cfg.admin_url("move", { "stepparent":parent.id, "d":"swap", "id":loop.current.id, "other":loop.next.id, "r":top.admin }) : 0 -:>
+  <:.set up_url = loop.prev ? cfg.admin_url("move", { "stepparent":parent.id, "d":"swap", "id":loop.current.id, "other":loop.prev.id, "r":top.admin }) : 0 -:>
+  <:.set class = cfg.entry("arrows", "class", "bse_arrows") -:>
+  <span class="<:= m.class :>">
+    <:-.call "make_arrows", "down_url":down_url, "up_url":up_url -:>
+  </span>
+<:.end if -:>
+<:.end define -:>
+
+<:.define make_arrows -:>
+<:# expects down_url, up_url
+-:>
+  <:.set width = cfg.entry("arrows", "image_width", 17) -:>
+  <:.set height = cfg.entry("arrows", "image_height", 13) -:>
+  <:.set extras = 'width="' _ width _ '" height="' _ height _ '"' -:>
+  <:.set blank_img = '<img src="' _ (dist_image_uri _ "/trans_pixel.gif").escape("html") _ '" alt="" ' _ extras _ ' />' -:>
+  <:.set down_img = '<img src="' _ cfg.entry("arrows", "downimg", dist_image_uri _ "/admin/move_down.gif").escape("html") _ '" alt="Down" ' _ extras _ ' />' -:>
+  <:.set up_img = '<img src="' _ cfg.entry("arrows", "upimg", dist_image_uri _ "/admin/move_up.gif").escape("html") _ '" alt="Up" ' _ extras _ ' />' -:>
+  <:-.if down_url -:>
+  <a href="<:= down_url :>"><:= down_img |raw:></a>
+  <:-.else -:>
+    <:= blank_img |raw:>
+  <:-.end if -:>
+  <:-.if up_url -:>
+  <a href="<:= up_url :>"><:= up_img |raw:></a>
+  <:-.else -:>
+    <:= blank_img |raw:>
+  <:-.end if -:>
+
+<:.end define -:>
+
+<:.define word_wrap; text: @undef, prefix:"", noncontin: "", contin:"", escape1: "", escape2: "", width: 70 -:>
+<:# Word wrap "text" at width columns, following settings:
+width - word wrap width (default 70)
+prefix - prefix to add to all lines
+noncontin - prefix to additionally add to first line of each paragraph
+contin - prefix to additionally add to lines that have been wrapped
+escape1 - suffix to add to lines wrapped on a non-word
+escape2 - suffix to add to lines wrapped on a word boundary
+-:>
+<:.set re = "^.{1," _ width _ "}\\s+" -:>
+<:.set paras = text.split(/\n/) -:>
+<:.for para in paras -:>
+<:  .set work = para -:>
+<:  .set first = 1 -:>
+<:  .while work.length -:>
+<:    .if !first -:>
+<:      .set work = work.replace(/^\s+/, "") -:>
+<:    .end if -:>
+<:    .if work.length < 70 -:>
+<:      .set line = work -:>
+<:      .set work = "" -:>
+<:    .else -:>
+<:      .set m = work.match(re) -:>
+<:      .if m -:>
+<:        .set line = work.substring(0, m.length).replace(/\s+$/, "") _ escape2 -:>
+<:        .set work = work.substring(m.length) -:>
+<:      .else -:>
+<:        .set line = work.substring(0, width) _ escape1 -:>
+<:        .set work = work.substring(width) -:>
+<:      .end if -:>
+<:    .end if -:>
+<:= prefix _ (first ? noncontin : contin) _ line.replace(/\s+$/, "") |raw:>
+<:    .set first = 0 -:>
+<:  .end while -:>
+<:.end for -:>
+<:.end define -:>
+
 <:- include includes/custom/preload.tmpl optional -:>