This is a combination of a reactor that creates a static template file including all the users and an example how to make use of the created template. It is designed to speed up display of user and other dropdowns. Another way to handle dropdowns is to use filter_sql in TAL to select a subset of users for display.
The solution was initially developed by Marcus Priesch -- I'm just documenting it, since the mailinglist archives::
* http://sourceforge.net/mailarchive/message.php?msg_id=12295188
* http://roundup.1086182.n5.nabble.com/Practical-Roundup-Limitations-td3708.html
are unavailable from time to time::
import os import shutil pjoin = os.path.join from roundup.cgi.TranslationService import get_translation from tempfile import mkstemp from roundup.date import Date from roundup.exceptions import Reject USER_SINGLE = """ <tal:block metal:define-macro="%(macro_name)s"> <tal:block tal:condition="python:not context [name].is_edit_ok ()" tal:replace="python: context [name]"/> <select tal:attributes="name name" tal:condition="python: context [name].is_edit_ok ()"> <option value="" tal:content="dont_care"></option> <!-- autogenerated --> %(option_list)s <!-- autogenerated --> </select> <disabled script language="javascript" tal:content="structure string: <!-- select_box = document.${form}.${name}; for (i = 0; i < select_box.length; i++) { if (select_box.options [i].value == ${selected}) select_box.options [i].selected = true; else select_box.options [i].selected = false; } --> "><disabled /script>; </tal:block> """ USER_MULTI = """ <tal:block metal:define-macro="%(macro_name)s"> <tal:block tal:condition="python:not %(condition)s" tal:replace="python: context [name]"/> <select multiple tal:condition="python: %(condition)s" tal:attributes="size size; name name"> <option value="" tal:content="dont_care"></option> <!-- autogenerated --> %(option_list)s <!-- autogenerated --> </select> <disabled script language="javascript" tal:content="structure string: <!-- select_box = document.${form}.${name}; selected = new Array (${selected}); for (i = 0; i < select_box.length; i++) { for (j = 0; j < selected.length; j++) { if (select_box.options [i].value == selected [j]) select_box.options [i].selected = true; } } --> "><disabled /script> </tal:block> """ OPTION_FMT = """ <option value="%s">%s</option>""" def update_userlist_html (db, cl, nodeid, old_values) : """newly create user_list.html macro page """ root = pjoin (db.config.TRACKER_HOME, "html") userlist = "userlist.html" changed = False for i in 'username', 'status', 'roles' : if ( not old_values or i not in old_values or old_values [i] != cl.get (nodeid, i) ) : changed = True if not changed : return f, tmpname = mkstemp (".html", "userlist", root) f = os.fdopen (f, "w") # all 'real' users spec = {} if 'status' in cl.properties : valid = db.user_status.lookup ('valid') spec = { 'status' : [valid] } users = cl.filter ( None # full text search , filterspec = spec , sort = ("+", "username") ) if users : options = [OPTION_FMT % (id, cl.get (id, "username")) for id in users] f.write (USER_SINGLE % { "macro_name" : "user" , "option_list" : "\n".join (options) } ) f.write (USER_MULTI % { "macro_name" : "user_multi" , "option_list" : "\n".join (options) , "condition" : "context [name].is_edit_ok ()" } ) f.write (USER_MULTI % { "macro_name" : "user_multi_read" , "option_list" : "\n".join (options) , "condition" : "True" } ) # all users (incl. mail alias users) # RSC: now there are no mail alias users -- and we don't want # invalid users here, so use the same filterspec. spec = {} if 'status' in cl.properties : status = [db.user_status.lookup (s) for s in 'valid', 'system'] spec = {"status" : status} users = cl.filter ( None # full text search , filterspec = spec , sort = ("+", "username") ) if users : options = [OPTION_FMT % (id, cl.get (id, "username")) for id in users] f.write (USER_MULTI % { "macro_name" : "nosy_multi" , "option_list" : "\n".join (options) , "condition" : "True" } ) f.close () shutil.move (tmpname, pjoin (root, userlist)) # end def update_userlist_html
- Note that the example above assumes a "status" attribute of the user class that is not present in the standard tracker. Furthermore we originally hat special alias-users that were permitted on the nosy-list but not permitted as the responsible person for an issue. So if anybody simplifies this code to work with the roundup standard tracker, it would be nice if the result is shared on this page. How to use it in html templates, the macro has four parameters: - name: the name of the cgi variable - form: the name of the form - dont_care: whats displayed as "dont care which user" - selected: the id which gets automatically selected
The following example is a roundup link-attribute, the "supervisor" field of the user class (the utils.fieldname utility function creates the localised field name with a link to a documentation popup in our implementation)::
<tr> <th tal:content="structure python:utils.fieldname('user', 'supervisor')"/> <td> <tal:block tal:define="name string:supervisor; form string:user_form; dont_care string:don't care; selected context/supervisor/id | string:0"> <tal:block metal:use-macro="templates/userlist/macros/user"></tal:block> </tal:block> </td> </tr>
The following example is for a multilink-property called 'authors'::
<tr> <th class="required" tal:content="structure python:utils.fieldname (classname, 'authors')" /> <td colspan="3"> <tal:block tal:define="size string:3; name string:authors; form string:itemSynopsis; dont_care string:don't care; selected python:str([u.id for u in context.authors.reverse ()] or [''])[1:-1]"> <tal:block metal:use-macro="templates/userlist/macros/user_multi"></tal:block> </tal:block> </td> </tr>
John Rouillard 2013-03-26 added links to relevent mailing list messages, removed encoding of > and < signs from code blocks. Formatted code blocks as pre sections to make reading easier.