re-work coupons to allow multiple coupon types
[bse.git] / site / templates / preload.tmpl
1 <:# see preload.pod for documentation -:>
2 <:.set dist_image_uri = cfg.entryIfVar("uri", "dist_images", "/images") -:>
3 <:# utility definitions :>
4 <:-.define make_select; groups: 0, grouplabel: "label", groupid: "id",
5            itemgroupid: "groupid", attr: {} -:>
6   <:-.if !default.defined -:>
7     <:-.set default = "" -:>
8   <:.end if:>
9   <select name="<:= name | html :>"<:.call "elementextra", extra:attr:>>
10   <:- .if groups -:>
11     <:-.for i in list -:>
12       <:.if i.$itemgroupid eq "" -:>
13     <option value="<:= i.$id | html :>"
14           <:- .if i.$id eq default :> selected="selected"<:.end if -:>
15     >
16         <:-= i.$desc | html -:>
17       <:.end if -:>
18     <:.end for -:>
19     <:-.for g in groups -:>
20     <optgroup label="<:= g.$grouplabel | html -:>">
21       <:-.for i in list -:>
22         <:.if i.$itemgroupid == g.$groupid -:>
23       <option value="<:= i.$id | html :>"
24           <:- .if i.$id eq default :> selected="selected"<:.end if -:>
25       >
26           <:-= i.$desc | html -:>
27         <:.end if -:>
28       <:.end for -:>
29     </optgroup>
30     <:-.end for -:>
31   <:- .else -:>
32     <:-.for i in list -:>
33     <option value="<:= i.$id | html :>"
34         <:- .if i.$id eq default :> selected="selected"<:.end if -:>
35     >
36       <:-= i.$desc | html -:>
37     <:-.end for-:>
38   <:-.end if -:>
39   </select>
40 <:-.end define -:>
41 <:#
42 make_multicheck expects:
43   values - list of hashes
44   default - a list of ids of checks to be checked
45   id - the name of the id field
46   desc - the name of the description field.
47   name - the name of the input elements
48   readonly - true to make it readonly
49   attr - extra attributes to set on the generated inputs
50 -:>
51 <:-.define make_multicheck; readonly: 0, attr: {}-:>
52   <:.if !readonly -:>
53   <input type="hidden" name="_save_<:= name -:>" value="1">
54   <:.end if -:>
55   <:-.if !default.defined -:>
56     <:-.set default = [] -:>
57   <:.end if:>
58   <:.set checked = {} -:>
59   <:.for v in default -:>
60     <:% checked.set(v, 1) -:>
61   <:.end for -:>
62   <ul>
63   <:-.for i in values -:>
64     <li>
65     <:.set element_id = name _ "-" _ i.$id -:>
66     <input type="checkbox" name="<:= name :>" <:= checked[i.$id] ? 'checked ' : '' -:>
67       id="<:= element_id -:>" value="<:= i.$id :>"
68 <:-# readonly attribute isn't valid for checkboxes -:>
69 <:-= readonly ? " disabled" : "" -:>
70 <:-.call "elementextra", extra: attr -:>
71     >
72     <label for="<:= element_id :>"><:= i.$desc -:></label>
73     </li>
74   <:-.end for -:>
75   </ul>
76 <:-.end define -:>
77 <:#
78 page_list expects:
79 base - base url for links
80 pages - the result of the bse.pages call
81  :>
82 <:-.define page_list-:>
83 <:.set sep = base =~ /\?/ ? "&" : "?" -:>
84 <:.set base = base _ sep :>
85 <div class="pagelist">
86 Page <:= pages.page :> of <:= pages.pagecount :>
87 <:.if pages.previous_page -:>
88 <a href="<:= base |html:><:= pages.pname | uri :>=1&amp;<:= pages.ppname | uri :>=<:= pages.pp | uri :>">&lt;&lt</a>
89 <a href="<:= base |html:><:= pages.pname | uri :>=<:= pages.previous_page |uri:>&amp;<:= pages.ppname | uri :>=<:= pages.pp | uri :>">&lt;</a>
90 <:.else -:>
91 <span>&lt&lt</span>
92 <span>&lt</span>
93 <:.end if -:>
94 <:.for p in pages.pages :>
95 <:.if p.link -:>
96 <a href="<:= base |html :><:= pages.pname | uri:>=<:= p.page | uri :>&amp;<:=pages.ppname | uri :>=<:= pages.pp | uri :>"><:= p.page |html :></a>
97 <:.else -:>
98 <span><:= p.page |html:></span>
99 <:.end if -:>
100 <:.end for:>
101 <:.if pages.next_page -:>
102 <a href="<:= base |html:><:= pages.pname | uri :>=<:= pages.next_page |uri:>&amp;<:= pages.ppname | uri :>=<:= pages.pp | uri :>">&gt;</a>
103 <a href="<:= base |html:><:= pages.pname | uri :>=<:= pages.pagecount |uri:>&amp;<:= pages.ppname | uri :>=<:= pages.pp | uri :>">&gt;&gt</a>
104 <:.else -:>
105 <span>&gt&gt</span>
106 <span>&gt</span>
107 <:.end if -:>
108 </div>
109 <:-.end define -:>
110
111 <:.define old; default: "", index: 0 -:>
112 <:# parameters: field, default, index  -:>
113 <:  .set vals = [ cgi.param(field) ] -:>
114 <:  .if index < vals.size -:>
115 <:= vals[index] -:>
116 <:  .else -:>
117 <:= default | html -:>
118 <:  .end if -:>
119 <:.end define-:>
120
121 <:.define error_img_n -:>
122 <:# parameters:
123    field - name of field
124    index - index of field
125    errors - hash of error messages (should be set by code)
126 -:>
127   <:.if errors.$field -:>
128     <:.set msg = errors.$field -:>
129     <:.set msg = msg.is_list ? msg[index] : msg -:>
130     <:.if msg.defined -:>
131       <:.set image = cfg.entry("error_img", "image", dist_image_uri _ "/admin/error.gif") -:>
132       <:.set width = cfg.entry("error_img", "width", 16) -:>
133       <:.set height = cfg.entry("error_img", "height", 16) -:>
134     <img src="<:= image -:>" alt="<:= msg :>" title="<:= msg :>" width="<:= width :>" height="<:= height :>" class="error_img">
135     <:.end if -:>
136   <:.end if -:>
137 <:.end define -:>
138
139 <:.define error_img -:>
140 <:.call "error_img_n", index:0 -:>
141 <:.end define -:>
142
143 <:.define elementextra -:>
144 <:  .set extratext = "" -:>
145 <:  .if extra.defined -:>
146 <:    .for n in extra.keys -:>
147 <:      .set extratext = extratext _ " " _ n _ '="' _ extra[n].escape("html") _ '"' -:>
148 <:    .end for -:>
149 <:  .end if -:>
150 <:= extratext |raw -:>
151 <:.end define -:>
152
153 <:.define input; options: {} -:>
154 <:# parameters:
155   name - field name
156   field - entry from fields
157   object - source for defaults in edit mode
158 -:>
159 <:  .set default = options.default -:>
160 <:  .if !default.defined -:>
161 <:    .if object -:>
162 <:       .set default = object.$name -:>
163 <:    .elsif field.default -:>
164 <:       .set default = field.default -:>
165 <:    .else -:>
166 <:       .set default = "" -:>
167 <:    .end if -:>
168 <:  .end if -:>
169 <:  .if field.type and field.type eq "date" and default ne "" -:>
170 <:    .set default = default.replace(/(\d+)\D+(\d+)\D+(\d+)/, "$3/$2/$1") -:>
171 <:  .elsif field.type and field.type eq "time" and default ne "" -:>
172 <:    .set default = bse.date(default =~ /:00$/ ? "%I:%M%p" : "%I:%M:%S%p", default).replace(/^0/, "").lower() -:>
173 <:  .elsif field.type and field.type eq "money" and default ne "" -:>
174 <:    .set default = bse.number("money", default) -:>
175 <:  .end if -:>
176 <:  .if cgi.param(name).defined -:>
177 <:     .set default = cgi.param(name) -:>
178 <:  .end if -:>
179 <:  .if field.htmltype eq "textarea" -:>
180 <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 :>>
181 <:-= default | html -:>
182 </textarea>
183 <:  .elsif field.htmltype eq "checkbox" -:>
184 <:.set is_checked = cgi.param("_save_" _ name) ? cgi.param(name).defined : default -:>
185 <input type="hidden" name="_save_<:= name -:>" value="1">
186 <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 :> />
187 <:  .elsif field.htmltype eq "multicheck" -:>
188 <:# we expect default to be a list of selected checks -:>
189 <:.set values = field.select["values"] -:>
190 <:.set values = values.is_code ? values() : values -:>
191 <:.set default = cgi.param("_save_" _ name) ? [ cgi.param(name) ] : default -:>
192 <:.call "make_multicheck",
193   id:field.select.id,
194   desc:field.select.label,
195   attr: options.inputattr -:>
196 <:  .elsif field.htmltype eq "select" -:>
197 <:.set values = field.select["values"] -:>
198 <:.set values = values.is_code ? values() : values -:>
199 <:.call "make_select",
200     name: name,
201     default: default,
202     list: values,
203     id: field.select.id,
204     desc: field.select.label,
205     groupid : (field.select.groupid or "id"),
206     itemgroupid: (field.select.itemgroupid or "groupid"),
207     groups: field.select.groups ? (field.select.groups.is_code ? (field.select.groups)() : field.select.groups ) : 0,
208     grouplabel: (field.select.grouplabel or "label"),
209     attr: options.inputattr
210 -:>
211 <:  .elsif field.htmltype eq 'file' -:>
212 <:   .if default.length -:>
213 <span class="filename"><:= default :></span>
214 <:   .end if -:>
215 <input id="<:= name :>" type="file" name="<:= name :>"<:.call "elementextra", extra: options.inputattr :> />
216 <:- .else -:>
217 <input id="<:= name | html :>" type="text" name="<:= name | html :>" value="<:=  default | html :>" 
218 <:-= field.maxlength ? ' maxlength="' _ field.maxlength _ '"' : '' |raw:>
219 <:-= field.width ? ' size="' _ field.width _ '"' : '' | raw :><:.call "elementextra", extra: options.inputattr :> />
220 <:  .end if -:>
221 <:.end define -:>
222
223 <:.define field; options: {} -:>
224 <:# parameters:
225   name - field name
226   fields - hash of fields (may be set by page instead)
227   object - object containing defaults (can be set globally instead)
228   default - a default value not dependent on object (overrides object)
229 :>
230   <:.if fields.is_hash -:>
231     <:.set f = fields[name] -:>
232     <:.if f -:>
233       <:.call "inlinefield", field:f, name:name, options: options -:>
234     <:.else -:>
235 <p>Unknown field id '<b><:= name :></b>', available fields are '<:= fields.keys.join("', '") :>'</p>
236     <:.end if -:>
237   <:.else -:>
238 <p>fields isn't a hash, something is wrong.</p>
239   <:.end if -:>
240 <:.end define -:>
241
242 <:.define inlinefield; options: {} -:>
243 <:# parameters:
244   name - the field name
245   field - a field, as an entry in fields
246   options - various options, including:
247      note - display this text as a note below the field
248      delete - add a delete checkbox
249      default - a custom default value, overrides object
250      htmlattr - attributes for the wrapper div
251      inputattr - attributes for the input/select generated
252 -:>
253   <:.if field.is_hash -:>
254   <:.set divextra = "" -:>
255   <:.if options.htmlattr :>
256     <:.for n in options.htmlattr.keys -:>
257       <:.set divextra = divextra _ " " _ n _ '="' _ options.htmlattr[n].escape("html") _ '"' -:>
258     <:.end for -:>
259   <:.end if -:>
260 <div<:= divextra |raw:>>
261   <label for="<:= name :>"><:= field.nolabel ? "" : field.description | html :>:</label>
262   <span>
263     <:-.if field.readonly -:>
264 <:-.call "display", name:name, options: options -:>
265     <:.else -:>
266 <:-.call "input", name:name, options: options -:><:.call "error_img", field:name :>
267     <:-.end if -:>
268     <:-.if field.units -:>
269       <:-= field.units | html -:>
270     <:-.end if -:>
271     <:-.if options.note -:>
272 <br /><:= options.note | raw :>
273     <:-.end if -:>
274     <:-.if options["delete"] -:>
275 <br /><input type="checkbox" name="delete_<:= name :>" value="1" id="delete_<:= name :>"><label for="delete_<:= name :>">Delete</label>
276     <:-.end if -:>
277 </span>
278 </div>
279   <:.end if -:>
280 <:.end define -:>
281
282 <:.define fieldset -:>
283 <:# like field, but wrap in a per-field field set.
284 parameters:
285   name - field name
286   fields - hash of fields (may be set by page instead)
287 :>
288   <:.set f = fields[name] -:>
289   <:.if f.is_hash -:>
290 <fieldset>
291     <:.if !f.nolabel -:>
292   <legend><:= f.description :></legend>
293     <:.end if -:>
294   <:.call "input", name: name, field: f -:>
295 </fieldset>
296   <:.elsif fields.is_hash -:>
297 <p>Unknown field id '<b><:= name :></b>', available fields are '<:= fields.keys.join("', '") :>'</p>
298   <:.else -:>
299 <p>fields isn't a hash, something is wrong.</p>
300   <:.end if -:>
301 <:.end define -:>
302
303 <:.define display -:>
304 <:# paramaters:
305   name - field name
306   field - entry from fields
307   object - source for defaults in edit mode
308 :>
309 <:  .if object -:>
310 <:     .set default = object.$name -:>
311 <:  .end if -:>
312 <:  .if field.type and field.type eq "date" and default ne "" -:>
313 <:    .set default = default.replace(/(\d+)\D+(\d+)\D+(\d+)/, "$3/$2/$1") -:>
314 <:  .elsif field.type and field.type eq "time" and default ne "" -:>
315 <:    .set default = bse.date(default =~ /:00$/ ? "%I:%M%p" : "%I:%M:%S%p", default).replace(/^0/, "").lower() -:>
316 <:  .end if -:>
317 <:  .if field.htmltype eq "textarea" -:>
318 <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>
319 <:-= default | html -:>
320 </textarea>
321 <:  .elsif field.htmltype eq "checkbox" -:>
322 <input id="<:= name | html :>" type="checkbox" name="<:= name | html :>"<:= is_checked ? ' checked="checked"' : '' :> value="<:= field.value ? field.value : 1 | html :>" readonly>
323 <:  .elsif field.htmltype eq "multicheck" -:>
324 <:# we expect default to be a list of selected checks -:>
325 <:.set values = field.select["values"] -:>
326 <:.set values = values.is_code ? values() : values -:>
327 <:.call "make_multicheck",
328   id: field.select.id,
329   desc: field.select.label,
330   readonly: 1 -:>
331 <:  .elsif field.htmltype eq "select" -:>
332 <:.set values = field.select["values"] -:>
333 <:.set values = values.is_code ? values() : values -:>
334 <:# find the selected value and display it's label -:>
335 <:.set sid = field.select.id -:>
336 <:.set sdesc = field.select.label -:>
337 <:.for value in values -:>
338   <:.if value.$id eq default -:>
339     <:= value.$desc -:>
340   <:.end if -:>
341 <:.end for -:>
342 <:  .else -:>
343 <input id="<:= name  :>" type="text" name="<:= name :>" value="<:=  default :>"
344 <:-= field.width ? ' size="' _ field.width _ '"' : '' | raw :> readonly>
345 <:  .end if -:>
346 <:.end define -:>
347
348 <:.define inlinefieldro -:>
349 <:# parameters:
350   name - the field name
351   field - a field, as an entry in fields
352 -:>
353   <:.if field.is_hash -:>
354 <div>
355   <label for="<:= name :>"><:= field.nolabel ? "" : field.description :>:</label>
356   <span><:.call "display", name:name -:>
357     <:-.if field.units -:>
358       <:-= field.units -:>
359     <:-.end if -:>
360   <:.end if -:>
361 </span>
362 </div>
363 <:.end define -:>
364
365 <:.define fieldro -:>
366 <:# like field, but for display, not editing -:>
367   <:.if fields.is_hash -:>
368     <:.set f = fields[name] -:>
369     <:.if f -:>
370       <:.call "inlinefieldro", field:f, name:name -:>
371     <:.else -:>
372 <p>Unknown field id '<b><:= name :></b>', available fields are '<:= fields.keys.join("', '") :>'</p>
373     <:.end if -:>
374   <:.else -:>
375 <p>fields isn't a hash, something is wrong.</p>
376   <:.end if -:>
377 <:.end define -:>
378
379 <:.define fieldsetro -:>
380 <:# like fieldro, but wrap in a per-field field set.
381 parameters:
382   name - field name
383   fields - hash of fields (may be set by page instead)
384 :>
385   <:.set f = fields[name] -:>
386   <:.if f.is_hash -:>
387 <fieldset>
388     <:.if !f.nolabel -:>
389   <legend><:= f.description :></legend>
390     <:.end if -:>
391   <:.call "display", "name":name, "field":f -:>
392 </fieldset>
393   <:.elsif fields.is_hash -:>
394 <p>Unknown field id '<b><:= name :></b>', available fields are '<:= fields.keys.join("', '") :>'</p>
395   <:.else -:>
396 <p>fields isn't a hash, something is wrong.</p>
397   <:.end if -:>
398 <:.end define -:>
399
400 <:.define messages -:>
401 <:  .if request.messages.size -:>
402 <div class="messages">
403 <:     .for m in request.messages -:>
404   <div class="<:= m.class :>"><:= m.html |raw :></div>
405 <:     .end for -:> 
406 </div>
407 <:  .end if -:>
408 <:.end define -:>
409
410 <:.define mover -:>
411 <:# expects loop, request, parent
412   which in most cases means you can just supply parent
413 -:>
414 <:.if request.user_can("bse_edit_reorder_children", parent) -:>
415   <:.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 -:>
416   <:.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 -:>
417   <:.set class = cfg.entry("arrows", "class", "bse_arrows") -:>
418   <span class="<:= m.class :>">
419     <:-.call "make_arrows", "down_url":down_url, "up_url":up_url -:>
420   </span>
421 <:.end if -:>
422 <:.end define -:>
423
424 <:.define make_arrows -:>
425 <:# expects down_url, up_url
426 -:>
427   <:.set width = cfg.entry("arrows", "image_width", 17) -:>
428   <:.set height = cfg.entry("arrows", "image_height", 13) -:>
429   <:.set extras = 'width="' _ width _ '" height="' _ height _ '"' -:>
430   <:.set blank_img = '<img src="' _ (dist_image_uri _ "/trans_pixel.gif").escape("html") _ '" alt="" ' _ extras _ ' />' -:>
431   <:.set down_img = '<img src="' _ cfg.entry("arrows", "downimg", dist_image_uri _ "/admin/move_down.gif").escape("html") _ '" alt="Down" ' _ extras _ ' />' -:>
432   <:.set up_img = '<img src="' _ cfg.entry("arrows", "upimg", dist_image_uri _ "/admin/move_up.gif").escape("html") _ '" alt="Up" ' _ extras _ ' />' -:>
433   <:-.if down_url -:>
434   <a href="<:= down_url :>"><:= down_img |raw:></a>
435   <:-.else -:>
436     <:= blank_img |raw:>
437   <:-.end if -:>
438   <:-.if up_url -:>
439   <a href="<:= up_url :>"><:= up_img |raw:></a>
440   <:-.else -:>
441     <:= blank_img |raw:>
442   <:-.end if -:>
443
444 <:.end define -:>
445
446 <:.define word_wrap; text: @undef, prefix:"", noncontin: "", contin:"", escape1: "", escape2: "", width: 70 -:>
447 <:# Word wrap "text" at width columns, following settings:
448 width - word wrap width (default 70)
449 prefix - prefix to add to all lines
450 noncontin - prefix to additionally add to first line of each paragraph
451 contin - prefix to additionally add to lines that have been wrapped
452 escape1 - suffix to add to lines wrapped on a non-word
453 escape2 - suffix to add to lines wrapped on a word boundary
454 -:>
455 <:.set re = "^.{1," _ width _ "}\\s+" -:>
456 <:.set paras = text.split(/\n/) -:>
457 <:.for para in paras -:>
458 <:  .set work = para -:>
459 <:  .set first = 1 -:>
460 <:  .while work.length -:>
461 <:    .if !first -:>
462 <:      .set work = work.replace(/^\s+/, "") -:>
463 <:    .end if -:>
464 <:    .if work.length < 70 -:>
465 <:      .set line = work -:>
466 <:      .set work = "" -:>
467 <:    .else -:>
468 <:      .set m = work.match(re) -:>
469 <:      .if m -:>
470 <:        .set line = work.substring(0, m.length).replace(/\s+$/, "") _ escape2 -:>
471 <:        .set work = work.substring(m.length) -:>
472 <:      .else -:>
473 <:        .set line = work.substring(0, width) _ escape1 -:>
474 <:        .set work = work.substring(width) -:>
475 <:      .end if -:>
476 <:    .end if -:>
477 <:= prefix _ (first ? noncontin : contin) _ line.replace(/\s+$/, "") |raw:>
478 <:    .set first = 0 -:>
479 <:  .end while -:>
480 <:.end for -:>
481 <:.end define -:>
482
483 <:- include includes/custom/preload.tmpl optional -:>