Mercurial > p > roundup > code
comparison roundup/template_funcs.py @ 936:57d09949380e
cleanup
| author | Richard Jones <richard@users.sourceforge.net> |
|---|---|
| date | Thu, 15 Aug 2002 00:40:10 +0000 |
| parents | fdcf16b444a9 |
| children | d435bf1ecd8d |
comparison
equal
deleted
inserted
replaced
| 935:2abb6b2697b6 | 936:57d09949380e |
|---|---|
| 1 # | |
| 2 # $Id: template_funcs.py,v 1.2 2002-08-15 00:40:10 richard Exp $ | |
| 3 # | |
| 1 import hyperdb, date, password | 4 import hyperdb, date, password |
| 2 from i18n import _ | 5 from i18n import _ |
| 3 import htmltemplate | 6 import htmltemplate |
| 4 import cgi, os, StringIO, urllib, types | 7 import cgi, os, StringIO, urllib, types |
| 5 | 8 |
| 6 | 9 def do_plain(client, classname, cl, props, nodeid, filterspec, property, |
| 7 def do_plain(client, classname, cl, props, nodeid, filterspec, property, escape=0, lookup=1): | 10 escape=0, lookup=1): |
| 8 ''' display a String property directly; | 11 ''' display a String property directly; |
| 9 | 12 |
| 10 display a Date property in a specified time zone with an option to | 13 display a Date property in a specified time zone with an option to |
| 11 omit the time from the date stamp; | 14 omit the time from the date stamp; |
| 12 | 15 |
| 50 | 53 |
| 51 if escape: | 54 if escape: |
| 52 value = cgi.escape(value) | 55 value = cgi.escape(value) |
| 53 return value | 56 return value |
| 54 | 57 |
| 55 def do_stext(client, classname, cl, props, nodeid, filterspec, property, escape=0): | 58 def do_stext(client, classname, cl, props, nodeid, filterspec, property, |
| 59 escape=0): | |
| 56 '''Render as structured text using the StructuredText module | 60 '''Render as structured text using the StructuredText module |
| 57 (see above for details) | 61 (see above for details) |
| 58 ''' | 62 ''' |
| 59 s = do_plain(client, classname, cl, props, nodeid, filterspec, property, escape=escape) | 63 s = do_plain(client, classname, cl, props, nodeid, filterspec, property, |
| 64 escape=escape) | |
| 60 if not StructuredText: | 65 if not StructuredText: |
| 61 return s | 66 return s |
| 62 return StructuredText(s,level=1,header=0) | 67 return StructuredText(s,level=1,header=0) |
| 63 | 68 |
| 64 def determine_value(cl, props, nodeid, filterspec, property): | 69 def determine_value(cl, props, nodeid, filterspec, property): |
| 93 sort_on = linkcl.labelprop() | 98 sort_on = linkcl.labelprop() |
| 94 def sortfunc(a, b, linkcl=linkcl, sort_on=sort_on): | 99 def sortfunc(a, b, linkcl=linkcl, sort_on=sort_on): |
| 95 return cmp(linkcl.get(a, sort_on), linkcl.get(b, sort_on)) | 100 return cmp(linkcl.get(a, sort_on), linkcl.get(b, sort_on)) |
| 96 return sortfunc | 101 return sortfunc |
| 97 | 102 |
| 98 def do_field(client, classname, cl, props, nodeid, filterspec, property, size=None, showid=0): | 103 def do_field(client, classname, cl, props, nodeid, filterspec, property, |
| 104 size=None, showid=0): | |
| 99 ''' display a property like the plain displayer, but in a text field | 105 ''' display a property like the plain displayer, but in a text field |
| 100 to be edited | 106 to be edited |
| 101 | 107 |
| 102 Note: if you would prefer an option list style display for | 108 Note: if you would prefer an option list style display for |
| 103 link or multilink editing, use menu(). | 109 link or multilink editing, use menu(). |
| 121 value = cgi.escape(str(value)) | 127 value = cgi.escape(str(value)) |
| 122 value = '"'.join(value.split('"')) | 128 value = '"'.join(value.split('"')) |
| 123 s = '<input name="%s" value="%s" size="%s">'%(property, value, size) | 129 s = '<input name="%s" value="%s" size="%s">'%(property, value, size) |
| 124 elif isinstance(propclass, hyperdb.Boolean): | 130 elif isinstance(propclass, hyperdb.Boolean): |
| 125 checked = value and "checked" or "" | 131 checked = value and "checked" or "" |
| 126 s = '<input type="radio" name="%s" value="yes" %s>Yes'%(property, checked) | 132 s = '<input type="radio" name="%s" value="yes" %s>Yes'%(property, |
| 133 checked) | |
| 127 if checked: | 134 if checked: |
| 128 checked = "" | 135 checked = "" |
| 129 else: | 136 else: |
| 130 checked = "checked" | 137 checked = "checked" |
| 131 s += '<input type="radio" name="%s" value="no" %s>No'%(property, checked) | 138 s += '<input type="radio" name="%s" value="no" %s>No'%(property, |
| 139 checked) | |
| 132 elif isinstance(propclass, hyperdb.Number): | 140 elif isinstance(propclass, hyperdb.Number): |
| 133 s = '<input name="%s" value="%s" size="%s">'%(property, value, size) | 141 s = '<input name="%s" value="%s" size="%s">'%(property, value, size) |
| 134 elif isinstance(propclass, hyperdb.Password): | 142 elif isinstance(propclass, hyperdb.Password): |
| 135 s = '<input type="password" name="%s" size="%s">'%(property, size) | 143 s = '<input type="password" name="%s" size="%s">'%(property, size) |
| 136 elif isinstance(propclass, hyperdb.Link): | 144 elif isinstance(propclass, hyperdb.Link): |
| 176 s = '<input name="%s" size="%s" value="%s">'%(property, size, value) | 184 s = '<input name="%s" size="%s" value="%s">'%(property, size, value) |
| 177 else: | 185 else: |
| 178 s = _('Plain: bad propclass "%(propclass)s"')%locals() | 186 s = _('Plain: bad propclass "%(propclass)s"')%locals() |
| 179 return s | 187 return s |
| 180 | 188 |
| 181 def do_multiline(client, classname, cl, props, nodeid, filterspec, property, rows=5, cols=40): | 189 def do_multiline(client, classname, cl, props, nodeid, filterspec, property, |
| 190 rows=5, cols=40): | |
| 182 ''' display a string property in a multiline text edit field | 191 ''' display a string property in a multiline text edit field |
| 183 ''' | 192 ''' |
| 184 if not nodeid and client.form is None and filterspec is None: | 193 if not nodeid and client.form is None and filterspec is None: |
| 185 return _('[Multiline: not called from item]') | 194 return _('[Multiline: not called from item]') |
| 186 | 195 |
| 197 | 206 |
| 198 # display | 207 # display |
| 199 return '<textarea name="%s" rows="%s" cols="%s">%s</textarea>'%( | 208 return '<textarea name="%s" rows="%s" cols="%s">%s</textarea>'%( |
| 200 property, rows, cols, value) | 209 property, rows, cols, value) |
| 201 | 210 |
| 202 def do_menu(client, classname, cl, props, nodeid, filterspec, property, size=None, height=None, showid=0, | 211 def do_menu(client, classname, cl, props, nodeid, filterspec, property, |
| 203 additional=[], **conditions): | 212 size=None, height=None, showid=0, additional=[], **conditions): |
| 204 ''' For a Link/Multilink property, display a menu of the available | 213 ''' For a Link/Multilink property, display a menu of the available |
| 205 choices | 214 choices |
| 206 | 215 |
| 207 If the additional properties are specified, they will be | 216 If the additional properties are specified, they will be |
| 208 included in the text of each option in (brackets, with, commas). | 217 included in the text of each option in (brackets, with, commas). |
| 292 l.append('</select>') | 301 l.append('</select>') |
| 293 return '\n'.join(l) | 302 return '\n'.join(l) |
| 294 return _('[Menu: not a link]') | 303 return _('[Menu: not a link]') |
| 295 | 304 |
| 296 #XXX deviates from spec | 305 #XXX deviates from spec |
| 297 def do_link(client, classname, cl, props, nodeid, filterspec, property=None, is_download=0, showid=0): | 306 def do_link(client, classname, cl, props, nodeid, filterspec, property=None, |
| 307 is_download=0, showid=0): | |
| 298 '''For a Link or Multilink property, display the names of the linked | 308 '''For a Link or Multilink property, display the names of the linked |
| 299 nodes, hyperlinked to the item views on those nodes. | 309 nodes, hyperlinked to the item views on those nodes. |
| 300 For other properties, link to this node with the property as the | 310 For other properties, link to this node with the property as the |
| 301 text. | 311 text. |
| 302 | 312 |
| 362 else: | 372 else: |
| 363 if value in ('', None, []): | 373 if value in ('', None, []): |
| 364 value = _('[no %(propname)s]')%{'propname':property.capitalize()} | 374 value = _('[no %(propname)s]')%{'propname':property.capitalize()} |
| 365 return '<a href="%s%s">%s</a>'%(classname, nodeid, value) | 375 return '<a href="%s%s">%s</a>'%(classname, nodeid, value) |
| 366 | 376 |
| 367 def do_count(client, classname, cl, props, nodeid, filterspec, property, **args): | 377 def do_count(client, classname, cl, props, nodeid, filterspec, property, |
| 378 **args): | |
| 368 ''' for a Multilink property, display a count of the number of links in | 379 ''' for a Multilink property, display a count of the number of links in |
| 369 the list | 380 the list |
| 370 ''' | 381 ''' |
| 371 if not nodeid: | 382 if not nodeid: |
| 372 return _('[Count: not called from item]') | 383 return _('[Count: not called from item]') |
| 378 # figure the length then... | 389 # figure the length then... |
| 379 value = cl.get(nodeid, property) | 390 value = cl.get(nodeid, property) |
| 380 return str(len(value)) | 391 return str(len(value)) |
| 381 | 392 |
| 382 # XXX pretty is definitely new ;) | 393 # XXX pretty is definitely new ;) |
| 383 def do_reldate(client, classname, cl, props, nodeid, filterspec, property, pretty=0): | 394 def do_reldate(client, classname, cl, props, nodeid, filterspec, property, |
| 395 pretty=0): | |
| 384 ''' display a Date property in terms of an interval relative to the | 396 ''' display a Date property in terms of an interval relative to the |
| 385 current date (e.g. "+ 3w", "- 2d"). | 397 current date (e.g. "+ 3w", "- 2d"). |
| 386 | 398 |
| 387 with the 'pretty' flag, make it pretty | 399 with the 'pretty' flag, make it pretty |
| 388 ''' | 400 ''' |
| 406 if not nodeid: | 418 if not nodeid: |
| 407 return _('now') | 419 return _('now') |
| 408 return interval.pretty() | 420 return interval.pretty() |
| 409 return str(interval) | 421 return str(interval) |
| 410 | 422 |
| 411 def do_download(client, classname, cl, props, nodeid, filterspec, property, **args): | 423 def do_download(client, classname, cl, props, nodeid, filterspec, property, |
| 424 **args): | |
| 412 ''' show a Link("file") or Multilink("file") property using links that | 425 ''' show a Link("file") or Multilink("file") property using links that |
| 413 allow you to download files | 426 allow you to download files |
| 414 ''' | 427 ''' |
| 415 if not nodeid: | 428 if not nodeid: |
| 416 return _('[Download: not called from item]') | 429 return _('[Download: not called from item]') |
| 417 return do_link(client, classname, cl, props, nodeid, filterspec, property, is_download=1) | 430 return do_link(client, classname, cl, props, nodeid, filterspec, property, |
| 418 | 431 is_download=1) |
| 419 | 432 |
| 420 def do_checklist(client, classname, cl, props, nodeid, filterspec, property, sortby=None): | 433 def do_checklist(client, classname, cl, props, nodeid, filterspec, property, |
| 434 sortby=None): | |
| 421 ''' for a Link or Multilink property, display checkboxes for the | 435 ''' for a Link or Multilink property, display checkboxes for the |
| 422 available choices to permit filtering | 436 available choices to permit filtering |
| 423 | 437 |
| 424 sort the checklist by the argument (+/- property name) | 438 sort the checklist by the argument (+/- property name) |
| 425 ''' | 439 ''' |
| 496 # TODO: pull the value from the form | 510 # TODO: pull the value from the form |
| 497 return '<textarea name="__note" wrap="hard" rows=%s cols=%s>'\ | 511 return '<textarea name="__note" wrap="hard" rows=%s cols=%s>'\ |
| 498 '</textarea>'%(rows, cols) | 512 '</textarea>'%(rows, cols) |
| 499 | 513 |
| 500 # XXX new function | 514 # XXX new function |
| 501 def do_list(client, classname, cl, props, nodeid, filterspec, property, reverse=0, xtracols=None): | 515 def do_list(client, classname, cl, props, nodeid, filterspec, property, |
| 516 reverse=0, xtracols=None): | |
| 502 ''' list the items specified by property using the standard index for | 517 ''' list the items specified by property using the standard index for |
| 503 the class | 518 the class |
| 504 ''' | 519 ''' |
| 505 propcl = props[property] | 520 propcl = props[property] |
| 506 if not isinstance(propcl, hyperdb.Multilink): | 521 if not isinstance(propcl, hyperdb.Multilink): |
| 521 fp = StringIO.StringIO() | 536 fp = StringIO.StringIO() |
| 522 try: | 537 try: |
| 523 write_save = client.write | 538 write_save = client.write |
| 524 client.write = fp.write | 539 client.write = fp.write |
| 525 client.listcontext = ('%s%s' % (classname, nodeid), property) | 540 client.listcontext = ('%s%s' % (classname, nodeid), property) |
| 526 index = htmltemplate.IndexTemplate(client, client.instance.TEMPLATES, propcl.classname) | 541 index = htmltemplate.IndexTemplate(client, client.instance.TEMPLATES, |
| 542 propcl.classname) | |
| 527 index.render(nodeids=value, show_display_form=0, xtracols=xtracols) | 543 index.render(nodeids=value, show_display_form=0, xtracols=xtracols) |
| 528 finally: | 544 finally: |
| 529 client.listcontext = None | 545 client.listcontext = None |
| 530 client.write = write_save | 546 client.write = write_save |
| 531 | 547 |
| 532 return fp.getvalue() | 548 return fp.getvalue() |
| 533 | 549 |
| 534 # XXX new function | 550 # XXX new function |
| 535 def do_history(client, classname, cl, props, nodeid, filterspec, direction='descending'): | 551 def do_history(client, classname, cl, props, nodeid, filterspec, |
| 552 direction='descending'): | |
| 536 ''' list the history of the item | 553 ''' list the history of the item |
| 537 | 554 |
| 538 If "direction" is 'descending' then the most recent event will | 555 If "direction" is 'descending' then the most recent event will |
| 539 be displayed first. If it is 'ascending' then the oldest event | 556 be displayed first. If it is 'ascending' then the oldest event |
| 540 will be displayed first. | 557 will be displayed first. |
| 692 if nodeid or client.form is not None: | 709 if nodeid or client.form is not None: |
| 693 return _('<input type="submit" name="submit" value="%s">' % value) | 710 return _('<input type="submit" name="submit" value="%s">' % value) |
| 694 else: | 711 else: |
| 695 return _('[Submit: not called from item]') | 712 return _('[Submit: not called from item]') |
| 696 | 713 |
| 697 def do_classhelp(client, classname, cl, props, nodeid, filterspec, clname, properties, label='?', width='400', | 714 def do_classhelp(client, classname, cl, props, nodeid, filterspec, clname, |
| 698 height='400'): | 715 properties, label='?', width='400', height='400'): |
| 699 '''pop up a javascript window with class help | 716 '''pop up a javascript window with class help |
| 700 | 717 |
| 701 This generates a link to a popup window which displays the | 718 This generates a link to a popup window which displays the |
| 702 properties indicated by "properties" of the class named by | 719 properties indicated by "properties" of the class named by |
| 703 "classname". The "properties" should be a comma-separated list | 720 "classname". The "properties" should be a comma-separated list |
| 708 ''' | 725 ''' |
| 709 return '<a href="javascript:help_window(\'classhelp?classname=%s&' \ | 726 return '<a href="javascript:help_window(\'classhelp?classname=%s&' \ |
| 710 'properties=%s\', \'%s\', \'%s\')"><b>(%s)</b></a>'%(clname, | 727 'properties=%s\', \'%s\', \'%s\')"><b>(%s)</b></a>'%(clname, |
| 711 properties, width, height, label) | 728 properties, width, height, label) |
| 712 | 729 |
| 713 def do_email(client, classname, cl, props, nodeid, filterspec, property, escape=0): | 730 def do_email(client, classname, cl, props, nodeid, filterspec, property, |
| 731 escape=0): | |
| 714 '''display the property as one or more "fudged" email addrs | 732 '''display the property as one or more "fudged" email addrs |
| 715 ''' | 733 ''' |
| 716 | 734 |
| 717 if not nodeid and client.form is None: | 735 if not nodeid and client.form is None: |
| 718 return _('[Email: not called from item]') | 736 return _('[Email: not called from item]') |
| 736 value = _('[Email: not a string]')%locals() | 754 value = _('[Email: not a string]')%locals() |
| 737 if escape: | 755 if escape: |
| 738 value = cgi.escape(value) | 756 value = cgi.escape(value) |
| 739 return value | 757 return value |
| 740 | 758 |
| 741 def do_filterspec(client, classname, cl, props, nodeid, filterspec, classprop, urlprop): | 759 def do_filterspec(client, classname, cl, props, nodeid, filterspec, classprop, |
| 760 urlprop): | |
| 761 | |
| 742 qs = cl.get(nodeid, urlprop) | 762 qs = cl.get(nodeid, urlprop) |
| 743 classname = cl.get(nodeid, classprop) | 763 classname = cl.get(nodeid, classprop) |
| 744 filterspec = {} | 764 filterspec = {} |
| 745 query = cgi.parse_qs(qs) | 765 query = cgi.parse_qs(qs) |
| 746 for k,v in query.items(): | 766 for k,v in query.items(): |
| 749 search_text = query.get('search_text', [''])[0] | 769 search_text = query.get('search_text', [''])[0] |
| 750 search_text = urllib.unquote(search_text) | 770 search_text = urllib.unquote(search_text) |
| 751 for k,v in query.items(): | 771 for k,v in query.items(): |
| 752 if k[0] != ':': | 772 if k[0] != ':': |
| 753 filterspec[k] = v | 773 filterspec[k] = v |
| 754 ixtmplt = htmltemplate.IndexTemplate(client, client.instance.TEMPLATES, classname) | 774 ixtmplt = htmltemplate.IndexTemplate(client, client.instance.TEMPLATES, |
| 775 classname) | |
| 755 qform = '<form onSubmit="return submit_once()" action="%s%s">\n'%( | 776 qform = '<form onSubmit="return submit_once()" action="%s%s">\n'%( |
| 756 classname,nodeid) | 777 classname,nodeid) |
| 757 qform += ixtmplt.filter_form(search_text, | 778 qform += ixtmplt.filter_form(search_text, |
| 758 query.get(':filter', []), | 779 query.get(':filter', []), |
| 759 query.get(':columns', []), | 780 query.get(':columns', []), |
| 762 query.get(':sort',[]), | 783 query.get(':sort',[]), |
| 763 filterspec, | 784 filterspec, |
| 764 pagesize) | 785 pagesize) |
| 765 return qform + '</table>\n' | 786 return qform + '</table>\n' |
| 766 | 787 |
| 767 def do_href(client, classname, cl, props, nodeid, filterspec, property, prefix='', suffix='', label=''): | 788 def do_href(client, classname, cl, props, nodeid, filterspec, property, |
| 789 prefix='', suffix='', label=''): | |
| 790 ''' Generate a link to the value of the property, with the form: | |
| 791 | |
| 792 <a href="[prefix][value][suffix]">[label]</a> | |
| 793 | |
| 794 where the [value] is the specified property value. | |
| 795 ''' | |
| 768 value = determine_value(cl, props, nodeid, filterspec, property) | 796 value = determine_value(cl, props, nodeid, filterspec, property) |
| 769 return '<a href="%s%s%s">%s</a>' % (prefix, value, suffix, label) | 797 return '<a href="%s%s%s">%s</a>'%(prefix, value, suffix, label) |
| 770 | 798 |
| 771 def do_remove(client, classname, cl, props, nodeid, filterspec): | 799 def do_remove(client, classname, cl, props, nodeid, filterspec): |
| 772 ''' put a remove href for an item in a list ''' | 800 ''' put a remove href for an item in a list ''' |
| 773 if not nodeid: | 801 if not nodeid: |
| 774 return _('[Remove not called from item]') | 802 return _('[Remove not called from item]') |
| 775 try: | 803 try: |
| 776 parentdesignator, mlprop = client.listcontext | 804 parentdesignator, mlprop = client.listcontext |
| 777 except (AttributeError, TypeError): | 805 except (AttributeError, TypeError): |
| 778 return _('[Remove not called form listing of multilink]') | 806 return _('[Remove not called form listing of multilink]') |
| 779 return '<a href="remove?:target=%s%s&:multilink=%s:%s">[Remove]</a>' % (classname, nodeid, parentdesignator, mlprop) | 807 return '<a href="remove?:target=%s%s&:multilink=%s:%s">[Remove]</a>'%( |
| 780 | 808 classname, nodeid, parentdesignator, mlprop) |
| 781 | 809 |
| 782 | 810 # |
| 811 # $Log: not supported by cvs2svn $ | |
| 812 # | |
| 813 # | |
| 814 # vim: set filetype=python ts=4 sw=4 et si |
