def filter_stream(self, req, method, filename, stream, data): """This extension point is used to make hidden duplicates of depselect fields in the ticket template. We do this to get around some CSS difficulties in Internet Explorer, see the comments in the ticket_depselect_fettler.js for more details.""" if not filename == 'ticket.html': return stream # Iterate through the list of all the depselect fields for d in [f for f in data['fields'] if f['type'] == 'depselect']: # Add a hidden select for every depselect field elm = tag.select(style="display: none", id='field-%s%s' % (d['parent'], d['name'])) if d['optional']: elm(tag.option) ticket_val = data['ticket'].get_value_or_default(d['name']) for val, parent_val in d['options']: if ticket_val == val: elm(tag.option(val, class_=parent_val, selected='selected')) else: elm(tag.option(val, class_=parent_val)) stream |= Transformer('.//body').append(elm) add_script(req, 'multiproduct/js/ticket_depselect_fettler.js') return stream
def _projects_field_input(self, req, selectedcomps): cursor = self.__SmpModel.get_all_projects() sorted_project_names_list = sorted(cursor, key=itemgetter(1)) number_displayed_entries = len( sorted_project_names_list) + 1 # +1 for special entry 'All' if number_displayed_entries > 15: number_displayed_entries = 15 select = tag.select(name="filter-projects", id="Filter-Projects", multiple="multiple", size=("%s" % number_displayed_entries), style="overflow:auto;") select.append(tag.option("All", value="All")) for component in sorted_project_names_list: project = component[1] if selectedcomps and project in selectedcomps: select.append( tag.option(project, value=project, selected="selected")) else: select.append(tag.option(project, value=project)) return select
def __new_project(self): all_projects = self.__SmpModel.get_all_projects() return tag.div(tag.label( 'Project:', tag.br(), tag.select(tag.option(), [ tag.option(row[1], value=row[0]) for row in sorted(all_projects, key=itemgetter(1)) ], name="project")), class_="field")
def __new_project(self): all_projects = self.__SmpModel.get_all_projects() return tag.div( tag.label( 'Project:', tag.br(), tag.select( tag.option(), [tag.option(row[1], value=row[0]) for row in sorted(all_projects, key=itemgetter(1))], name="project") ), class_="field")
def _components_field_input(self, req): db = self.env.get_db_cnx() cursor = db.cursor() cursor.execute("SELECT name FROM component ORDER BY name") select = tag.select(name="filter-components", id="filter-components", multiple="multiple", size="10") selectedcomps = req.args.get('filter-components') selectedcomps = type(selectedcomps) is unicode and (selectedcomps,) or selectedcomps for component in cursor: if selectedcomps and component[0] in selectedcomps: select.append(tag.option(component[0], value=component[0], selected="selected")) else: select.append(tag.option(component[0], value=component[0])) return select
def _projects_field_ticket_input(self, req, ticket_data): all_projects = [project[1] for project in sorted(self.__SmpModel.get_all_projects(), key=itemgetter(1))] select = tag.select(name="field_project", id="field-project", onchange="smp_onProjectChange(this.value)") cur_project = ticket_data.get_value_or_default('project') select.append(tag.option("", value="")) for project in all_projects: if cur_project and project == cur_project: select.append(tag.option(project, value=project, selected="selected")) else: select.append(tag.option(project, value=project)) return select
def _create_select(label_text, id, name, options, selected_name=None, default_selection=None): select = tag.select(id=id, name=name) if selected_name is None and default_selection is not None: selected_name = default_selection for option_name in options: if option_name == selected_name: select.append(tag.option(option_name, value=option_name, selected='selected')) else: select.append(tag.option(option_name, value=option_name)) insert = tag(label_text) insert( tag.br(), select ) insert = tag.div(tag.label(insert), class_='field') return insert
def filter_stream(self, req, method, filename, stream, data): if 'ticket' in data and 'remote_sites' in data: add_script(req, 'tracremoteticket/js/remoteticket.js') transf = Transformer('//select[@id="linked-end"]') label = tag.label(' in ', for_='remote-site') local = tag.option('this project', value=req.href.newticket(), selected='selected') remotes = [tag.option(rs['title'], value=Href(rs['url']).newticket()) for rs in data['remote_sites']] select = tag.select([local] + remotes, id='remote-site') content = label + select stream |= transf.after(content) return stream
def render_ticket_action_control(self, req, ticket, action): id, grade = self._get_grade(req, action) review_options = self._get_review_options(action) actions = ConfigurableTicketWorkflow(self.env).actions selected_value = grade or review_options[0][0] label = actions[action]['name'] control = tag([ "as: ", tag.select([ tag.option(option, selected=(option == selected_value or None)) for option, status in review_options ], name=id, id=id) ]) if grade: new_status = self._get_new_status(req, ticket, action, review_options) hint = "Next status will be '%s'" % new_status else: hint = "Next status will be one of " + \ ', '.join(["'%s'" % status for option, status in review_options]) return (label, control, hint)
def render_ticket_action_control(self, req, ticket, action): id, grade = self._get_grade(req, action) review_options = self._get_review_options(action) actions = ConfigurableTicketWorkflow(self.env).actions selected_value = grade or review_options[0][0] label = actions[action]["name"] control = tag( [ "as: ", tag.select( [ tag.option(option, selected=(option == selected_value or None)) for option, status in review_options ], name=id, id=id, ), ] ) if grade: new_status = self._get_new_status(req, ticket, action, review_options) hint = "Next status will be '%s'" % new_status else: hint = "Next status will be one of " + ", ".join(["'%s'" % status for option, status in review_options]) return (label, control, hint)
def _projects_field_input(self, req, selectedcomps): cursor = self.__SmpModel.get_all_projects() sorted_project_names_list = sorted(cursor, key=itemgetter(1)) number_displayed_entries = len(sorted_project_names_list)+1 # +1 for special entry 'All' if number_displayed_entries > 15: number_displayed_entries = 15 select = tag.select(name="filter-projects", id="filter-projects", multiple="multiple", size=("%s" % number_displayed_entries), style="overflow:auto;") select.append(tag.option("All", value="All")) for component in sorted_project_names_list: project = to_unicode(component[1]) if selectedcomps and project in selectedcomps: select.append(tag.option(project, value=project, selected="selected")) else: select.append(tag.option(project, value=project)) return select
def render_ticket_action_control(self, req, ticket, action): id = 'vote_%s_result' % (action, ) selected_value = req.args.get(id, 'for') options = ['for', 'against'] return ("vote", tag.select([tag.option(x, selected=(x == selected_value or None)) for x in options], name=id, id=id), "Vote on the issue, raising or lowering its priority")
def filter_stream(self, req, method, filename, stream, formdata): if (filename == 'ticket.html'): add_stylesheet(req, 'multiselectlist/css/jquery-ui.css') add_stylesheet(req, 'multiselectlist/css/jquery.multiselect.css') add_script(req, 'multiselectlist/js/jquery-ui-1.8.16.custom.min.js') add_script(req, 'multiselectlist/js/jquery.multiselect.min.js') for item in self.multilist: values = self.env.config.get('multiselectlist', '%s.values' % item) if values: key = 'field_%s' % unicode(item) # 既存のチケットの場合はDBに格納されている値を取得する inputvalues = [] if key in req.args: # チケット登録時のバリデーションで引っかかった場合 # なお、DBに保管されている値より優先しなければならない inputvalues = req.args.get(key) elif req.path_info.startswith('/ticket'): ticketno = req.path_info[8:] db = self.env.get_db_cnx() cursor = db.cursor() sql = "select value from ticket_custom where ticket=%s and name='%s'" % ( ticketno, item) cursor.execute(sql) row = cursor.fetchone() if row and row[0]: inputvalues = row[0].split(',') self.env.log.info(inputvalues) value = values.split(',') xpath = '//input[@id="field-%s"]' % item # input要素をselect/option要素に置き換える。 # タグの繰り返しを行う場合は、配列で指定すればいいようだ。 script = """ jQuery(function(){ jQuery("#field-%s").multiselect({ selectedList: 3 }); }); """ % item stream |= Transformer(xpath).replace( tag.select([ tag.option(v, selected=(v in inputvalues or None)) for v in value ], id='field-%s' % item, name='field_%s' % item, size='%d' % len(value), multiple='true')) stream |= Transformer('//head').append( tag.script(script, type="text/javascript")) return stream
def __edit_project(self, data): component = data.get('component').name all_projects = self.__SmpModel.get_all_projects() id_project_component = self.__SmpModel.get_id_projects_component(component) id_projects_selected = [] for id_project in id_project_component: id_projects_selected.append(id_project[0]) return tag.div( tag.label( 'Available in Project(s):', tag.br(), tag.select( tag.option("All", value="0"), [tag.option(row[1], selected=(row[0] in id_projects_selected or None), value=row[0]) for row in sorted(all_projects, key=itemgetter(1))], name="project", multiple="multiple", size="10") ), class_="field")
def __edit_project(self, data): version = data.get('version').name all_projects = self.__SmpModel.get_all_projects() id_project_version = self.__SmpModel.get_id_project_version(version) if id_project_version != None: id_project_selected = id_project_version[0] else: id_project_selected = None return tag.div(tag.label( 'Project:', tag.br(), tag.select(tag.option(), [ tag.option(row[1], selected=(id_project_selected == row[0] or None), value=row[0]) for row in sorted(all_projects, key=itemgetter(1)) ], name="project")), class_="field")
def __edit_project(self, data): milestone = data.get('milestone').name all_projects = self.__SmpModel.get_all_projects() id_project_milestone = self.__SmpModel.get_id_project_milestone(milestone) if id_project_milestone != None: id_project_selected = id_project_milestone[0] else: id_project_selected = None return tag.div( tag.label( 'Project:', tag.br(), tag.select( tag.option(), [tag.option(row[1], selected=(id_project_selected == row[0] or None), value=row[0]) for row in sorted(all_projects, key=itemgetter(1))], name="project") ), class_="field")
def _projects_field_ticket_input(self, req, ticket_data): all_projects = [ project[1] for project in sorted(self.__SmpModel.get_all_projects(), key=itemgetter(1)) ] select = tag.select(name="field_project", id="field-project", onchange="smp_onProjectChange(this.value)") cur_project = ticket_data.get_value_or_default('project') select.append(tag.option("", value="")) for project in all_projects: if cur_project and project == cur_project: select.append( tag.option(project, value=project, selected="selected")) else: select.append(tag.option(project, value=project)) return select
def render_ticket_action_control(self, req, ticket, action): # Need to use the list of all status so you can't manually set # something to an invalid state. selected_value = req.args.get('force_status_value', 'new') all_status = TicketSystem(self.env).get_all_status() render_control = tag.select( [tag.option(x, selected=(x == selected_value and 'selected' or None)) for x in all_status], id='force_status_value', name='force_status_value') return ("force status to:", render_control, "The next status will be the selected one")
def _version_edit(self, data): milestone = data.get('milestone').name db = self.env.get_db_cnx() cursor = db.cursor() cursor.execute("SELECT version FROM milestone_version WHERE milestone=%s", (milestone,)) row = cursor.fetchone() value = row and row[0] cursor.execute("SELECT name FROM version WHERE time IS NULL OR time = 0 OR time>%s " "OR name = %s ORDER BY name", (to_timestamp(None), value)) return tag.div( tag.label( 'Version:', tag.br(), tag.select( tag.option(), [tag.option(row[0], selected=(value == row[0] or None)) for row in cursor], name="version")), class_="field")
def __edit_project(self, data): component = data.get('component').name all_projects = self.__SmpModel.get_all_projects() id_project_component = self.__SmpModel.get_id_projects_component( component) id_projects_selected = [] for id_project in id_project_component: id_projects_selected.append(id_project[0]) return tag.div(tag.label( 'Available in Project(s):', tag.br(), tag.select(tag.option("All", value="0"), [ tag.option(row[1], selected=(row[0] in id_projects_selected or None), value=row[0]) for row in sorted(all_projects, key=itemgetter(1)) ], name="project", multiple="multiple", size="10")), class_="field")
def _version_edit(self, data): milestone = data.get('milestone').name db = self.env.get_db_cnx() cursor = db.cursor() cursor.execute( "SELECT version FROM milestone_version WHERE milestone=%s", (milestone, )) row = cursor.fetchone() value = row and row[0] cursor.execute( "SELECT name FROM version WHERE time IS NULL OR time = 0 OR time>%s " "OR name = %s ORDER BY name", (to_timestamp(None), value)) return tag.div(tag.label( 'Version:', tag.br(), tag.select(tag.option(), [ tag.option(row[0], selected=(value == row[0] or None)) for row in cursor ], name="version")), class_="field")
def filter_stream(self, req, method, filename, stream, data): """This is a filter stream for the project request ticket type on the dashboard project. We examine the filter stream and look to find the Project Template text input markup. We then replace this with a select list, and generate the values using the API get_all_templates() method. We don't have these options in the trac.ini file as they are dynamic, and don't use a select list by default as this will cause validation issues.""" try: ticket_type = data['ticket']['type'] except KeyError: ticket_type = None if (filename == 'ticket.html' and ticket_type == 'projectrequest' and self.env.is_component_enabled('define.dashboard.DashboardDisplayModule')): # get a list of available templates templates = ProjectTemplateAPI(self.env).get_all_templates() # we need a None option for the default templates.insert(0, 'None') # generate the select list markup select = tag.select(name='field_template') for template in templates: if template == 'None': select.append(tag.option(template, value=template, selected='selected')) else: select.append(tag.option(template, value=template)) # replace the text input with a select list stream = stream | Transformer("//*[@id='field-template']").replace(select) return stream
def filter_stream(self, req, method, filename, stream, data): if filename == "customfieldadmin.html": add_script(req, 'datefield/js/customfield-admin.js') add_stylesheet(req, 'datefield/css/customfield-admin.css') stream = stream | Transformer('.//select[@id="type"]').append( tag.option('Date', value='date', id="date_type_option")) stream = stream | Transformer( './/form[@id="addcf"]/fieldset/div[@class="buttons"]').before( tag.div(tag.input( id="date_empty", type="checkbox", name="date_empty"), tag.label('Allow empty date'), for_="date_empty", class_="field", id="date_empty_option")) return stream
def handle_catalogs(self, req): project_id = req.args.get('q') project = session(self.env).query(Project).get(int(project_id)) if not project: raise TracError if not project.catalogs: req.write(tag.em('No catalogs available')) raise RequestDone req.write('<select name="catalog_template">') for catalog in project.catalogs: req.write(tag.option(catalog.fpath, value=catalog.id)) req.write('</select>') raise RequestDone
def filter_stream(self, req, method, filename, stream, formdata): if (filename == 'ticket.html'): add_stylesheet(req, 'multiselectlist/css/jquery-ui.css') add_stylesheet(req, 'multiselectlist/css/jquery.multiselect.css') add_script(req, 'multiselectlist/js/jquery-ui-1.8.16.custom.min.js') add_script(req, 'multiselectlist/js/jquery.multiselect.min.js') for item in self.multilist: values = self.env.config.get('multiselectlist', '%s.values' % item) if values: key = 'field_%s' % unicode(item) # 既存のチケットの場合はDBに格納されている値を取得する inputvalues = [] if key in req.args: # チケット登録時のバリデーションで引っかかった場合 # なお、DBに保管されている値より優先しなければならない inputvalues = req.args.get(key) elif req.path_info.startswith('/ticket'): ticketno = req.path_info[8:] db = self.env.get_db_cnx() cursor = db.cursor() sql = "select value from ticket_custom where ticket=%s and name='%s'" % (ticketno, item) cursor.execute(sql) row = cursor.fetchone() if row and row[0]: inputvalues = row[0].split(',') self.env.log.info(inputvalues) value = values.split(',') xpath = '//input[@id="field-%s"]' % item # input要素をselect/option要素に置き換える。 # タグの繰り返しを行う場合は、配列で指定すればいいようだ。 script = """ jQuery(function(){ jQuery("#field-%s").multiselect({ selectedList: 3 }); }); """ % item stream |= Transformer(xpath).replace( tag.select( [tag.option(v, selected=(v in inputvalues or None)) for v in value], id='field-%s' % item, name='field_%s' % item, size='%d' % len(value), multiple='true')) stream |= Transformer('//head').append(tag.script(script, type="text/javascript")) return stream
def filter_stream(self, req, method, filename, stream, data): if filename == "customfieldadmin.html": add_script(req, "datefield/js/customfield-admin.js") add_stylesheet(req, "datefield/css/customfield-admin.css") stream = stream | Transformer('.//select[@id="type"]').append( tag.option("Date", value="date", id="date_type_option") ) stream = stream | Transformer('.//form[@id="addcf"]/fieldset/div[@class="buttons"]').before( tag.div( tag.input(id="date_empty", type="checkbox", name="date_empty"), tag.label("Allow empty date"), for_="date_empty", class_="field", id="date_empty_option", ) ) return stream
def render_ticket_action_control(self, req, ticket, action): this_action = ConfigurableTicketWorkflow(self.env).actions[action] status = this_action['newstate'] operations = this_action['operations'] control = [] # default to nothing hints = [] if 'set_evaluation' in operations: evaluations = self._get_evaluation_options() if not evaluations: raise TracError( _('Your workflow attempts to set an evaluation ' 'but none is defined (configuration issue, ' 'please contact your Trac admin).')) id = 'action_%s_evaluate_evaluation' % action if len(evaluations) == 1: evaluation = tag.input(type='hidden', id=id, name=id, value=evaluations[0]) control.append( tag_('as %(evaluation)s', evaluation=tag(evaluations[0], evaluation))) hints.append( _('The evaluation will be set to %(name)s', name=evaluations[0])) else: selected_option = 1 control.append( tag_( 'as %(evaluation)s', evaluation=tag.select([ tag.option(x, value=x, selected=(x == selected_option or None)) for x in evaluations ], id=id, name=id))) hints.append(_('The evaluation will be set')) #if 'del_evaluation' in operations: # hints.append(_('The evaluation will be deleted')) return (this_action['name'], tag(*control), '. '.join(hints) + '.' if hints else '')
def filter_stream(self, req, method, filename, stream, data): if filename == 'ticket.html': for field in list(self._multi_select_fields()): options = self.config.get('ticket-custom', field + '.options').split('|') options_html = tag() for option in options: options_html(tag.option(option)) stream = stream | Transformer('//input[@name="field_' + field + '"]' ).attr( 'style', 'display:none;' ).after( tag.select(multiple="multiple", class_="multiselect", style="width:200px;")(options_html) ) return stream
def _build_select(self, req, nextActionName, nextActionObj): """ Takes a request object, the name of the next action (as a string), and the next action object itself. Calls each registered IValidOwnerProvider and builds a dictionary of user_objs using usernames as keys (which is why usernames are required). Calls _ensure_user_data to insert user data into session_attribute if the "ensure user data" capability has been enabled. Returns a complete select tag object, ready for rendering. """ # get a list of data about owners valid for this next state # use an intermediate dict to ensure uniqueness by username user_objs = {} for voc in self.valid_owner_controllers: tmpusers = voc.getUsers(nextActionObj) [ user_objs.update({str(u.getUsername()).strip(): u}) for u in tmpusers ] user_objs = user_objs.values() if self.ensureUserData: self._ensure_user_data(user_objs) id = 'action_' + nextActionName + '_reassign_owner' # check to see if the current owner is in the list of valid owners; # if so, pre-select them in the select control selected_owner = req.args.get(id, req.authname) # build the actual options tag objects option_tags = [] for u in sorted(user_objs): username = u.getUsername() isselected = (username == selected_owner or None) option_tags.append( tag.option(u.getOptionDisplay(), selected=isselected, value=u.getOptionValue())) # build the final select control -- minus the assumed "to" _tag = tag.select(option_tags, id=id, name=id) return _tag
def _filter_resolutions(self, req, items): for item in items: if item[0] != 'resolve': yield item return resolutions = [ val.name for val in Resolution.select(self.env) if int(val.value) > 0 ] ts = TicketSystem(self.env) selected_option = req.args.get('action_resolve_resolve_resolution', ts.default_resolution) control = tag.select([ tag.option(x, value=x, selected=(x == selected_option or None)) for x in resolutions ], id='action_resolve_resolve_resolution', name='action_resolve_resolve_resolution') yield ('resolve', tag_('as %(resolution)s', resolution=control), item[2])
def _build_select(self, req, nextActionName, nextActionObj): """ Takes a request object, the name of the next action (as a string), and the next action object itself. Calls each registered IValidOwnerProvider and builds a dictionary of user_objs using usernames as keys (which is why usernames are required). Calls _ensure_user_data to insert user data into session_attribute if the "ensure user data" capability has been enabled. Returns a complete select tag object, ready for rendering. """ # get a list of data about owners valid for this next state # use an intermediate dict to ensure uniqueness by username user_objs = {} for voc in self.valid_owner_controllers: tmpusers = voc.getUsers(nextActionObj) [user_objs.update({str(u.getUsername()).strip():u}) for u in tmpusers] user_objs = user_objs.values() if self.ensureUserData: self._ensure_user_data(user_objs) # check to see if the current owner is in the list of valid owners; # if so, pre-select them in the select control #id = nextActionName + '_reassign_owner' ## updated for changed control name (0.11 release and higher) - thanks to chris on http://trac-hacks.org/ticket/3494 id = 'action_' + nextActionName + '_reassign_owner' selected_owner = req.args.get(id, req.authname) # build the actual options tag objects option_tags = [] for u in sorted(user_objs): username = u.getUsername() isselected = (username == selected_owner or None) option_tags.append(tag.option(u.getOptionDisplay(), selected=isselected, value=u.getOptionValue())) # build the final select control -- minus the assumed "to" _tag = tag.select(option_tags, id=id, name=id) return _tag
def render_ticket_action_control(self, req, ticket, action): this_action = ConfigurableTicketWorkflow(self.env).actions[action] status = this_action['newstate'] operations = this_action['operations'] control = [] # default to nothing hints = [] if 'set_evaluation' in operations: evaluations = self._get_evaluation_options() if not evaluations: raise TracError(_('Your workflow attempts to set an evaluation ' 'but none is defined (configuration issue, ' 'please contact your Trac admin).')) id = 'action_%s_evaluate_evaluation' % action if len(evaluations) == 1: evaluation = tag.input(type='hidden', id=id, name=id, value=evaluations[0]) control.append(tag_('as %(evaluation)s', evaluation=tag(evaluations[0], evaluation))) hints.append(_('The evaluation will be set to %(name)s', name=evaluations[0])) else: selected_option = 1 control.append(tag_('as %(evaluation)s', evaluation=tag.select( [tag.option(x, value=x, selected=(x == selected_option or None)) for x in evaluations], id=id, name=id))) hints.append(_('The evaluation will be set')) #if 'del_evaluation' in operations: # hints.append(_('The evaluation will be deleted')) return (this_action['name'], tag(*control), '. '.join(hints) + '.' if hints else '')
def filter_stream(self, req, method, filename, stream, formdata): """Modifies query page to add modifiable components""" self.log.debug("GridModifyModule: filter_stream entered") # We create an invisible storage div in the document for the default tag values. # JQuery then uses this information to update the relevant fields on the page. if (filename == 'query.html' or filename == 'report_view.html') and (req.perm.has_permission('TICKET_ADMIN') or req.perm.has_permission('TICKET_GRID_MODIFY')): add_script(req, 'gridmod/gridmod.js') xpath = '//div[@id="content"]' div = tag.div(id="table_inits_holder", style="display:none;") div.append("\n") for field in TicketSystem(self.env).get_ticket_fields(): #debug self.log.debug("filter_stream: field: " + str(field)) # SELECT tags if (field['type'] == 'select') and ((field['name'] in self.fields) or (len(self.fields) == 0)): select = tag.select(name=field['name'], class_="gridmod_form") self.log.debug("SELECT INPUT '%s' (%s)", field['name'], field['label']) if (field.has_key('value')): self.log.debug(" SELECT HAS DEFAULT VALUE '%s'", field['value']) else: self.log.debug(" SELECT HAS NO DEFAULT VALUE") # HACK: For some reason custom fields that have a blank value # as a valid option don't actually have that blank # value among the options in field['options'] so # we force a blank option in in the case where the # _default_ value is blank. select.append("\n") if(field.has_key('value') and field['value'] == '' and not ('' in field['options'])): select.append(tag.option()) for option in field['options']: select.append(tag.option(option, value=option)) select.append("\n") div.append(select) # INPUT TEXT tags elif ((field['type'] == 'text') and (field['name'] in self.fields)): text = tag.input(type='text', name=field['name'], class_='gridmod_form') if(field.has_key('value')): self.log.debug("TEXT INPUT '%s' (%s) HAS DEFAULT VALUE '%s'", field['name'], field['label'], field['value']) text.append(field['value']) else: text.append('') div.append(text) # INPUT DATE tags elif ((field['type'] == 'date') and (field['name'] in self.fields)): text = tag.input(type='text', name=field['name'], class_='gridmod_form datepick') if(field.has_key('value')): self.log.debug("TEXT INPUT '%s' (%s) HAS DEFAULT VALUE '%s'", field['name'], field['label'], field['value']) text.append(field['value']) else: text.append('') div.append(text) # INPUT CHECKBOX tags elif ((field['type'] == 'checkbox') and (field['name'] in self.fields)): checkbox = tag.input(type='checkbox', name=field['name'], class_='gridmod_form') if(field.has_key('value')): self.log.debug("CHECKBOX INPUT '%s' (%s) HAS DEFAULT VALUE '%s'", field['name'], field['label'], field['value']) checkbox.append(field['value']) if (field['value'] == 1 or field['value'] == True): checkbox(checked="checked") else: checkbox.append('0'); div.append(checkbox) # INPUT RADIO tags elif ((field['type'] == 'radio') and (field['name'] in self.fields)): # This is slightly complicated. # We convert the radio values into a SELECT tag for screen real estate reasons. # It gets handled as a SELECT at the server end of the AJAX call, which appears to work fine. # Note: If none of the RADIO buttons is checked, we default here to checking the first one, for code safety. # That should never happen. default_decided = False; radio_select = tag.select(name=field['name'], class_="gridmod_form") if(field.has_key('value')): self.log.debug("RADIO INPUT '%s' (%s) HAS DEFAULT VALUE '%s'", field['name'], field['label'], field['value']) default_val = field['value'] default_decided = True; for option in field['options']: self.log.debug(" doing radio option '%s'", option); select_option = tag.option(option, value=option) if (option == default_val) or (not default_decided): self.log.debug(" SELECTED '%s'", option); select_option(selected="selected") default_decided = True; radio_select.append(select_option) radio_select.append("\n") div.append(radio_select) div.append("\n"); # INPUT TEXTAREA tags # We are ignoring TextArea for now, as there are several complications including: # * Rendering is handled differently to other fields in the report form # * TextAreas support Wiki formatting so would need to use the Wiki engine stream |= Transformer(xpath).append(div) return stream
def render_ticket_action_control(self, req, ticket, action): self.log.debug('render_ticket_action_control: action "%s"', action) this_action = self.actions[action] status = this_action['newstate'] operations = this_action['operations'] current_owner = ticket._old.get('owner', ticket['owner']) author = get_reporter_id(req, 'author') author_info = partial(Chrome(self.env).authorinfo, req, resource=ticket.resource) format_author = partial(Chrome(self.env).format_author, req, resource=ticket.resource) formatted_current_owner = author_info(current_owner) exists = ticket._old.get('status', ticket['status']) is not None control = [] # default to nothing hints = [] if 'reset_workflow' in operations: control.append(_("from invalid state")) hints.append(_("Current state no longer exists")) if 'del_owner' in operations: hints.append(_("The ticket will be disowned")) if 'set_owner' in operations or 'may_set_owner' in operations: if 'set_owner' in this_action: owners = self._to_users(this_action['set_owner'], ticket) elif self.config.getbool('ticket', 'restrict_owner'): perm = PermissionSystem(self.env) owners = perm.get_users_with_permission('TICKET_MODIFY') owners = [user for user in owners if 'TICKET_MODIFY' in PermissionCache(self.env, user, ticket.resource)] owners = sorted(owners) else: owners = None if 'set_owner' in operations: default_owner = author elif 'may_set_owner' in operations: if not exists: default_owner = TicketSystem(self.env).default_owner else: default_owner = ticket._old.get('owner', ticket['owner'] or None) if owners is not None and default_owner not in owners: owners.insert(0, default_owner) else: # Protect against future modification for case that another # operation is added to the outer conditional raise AssertionError(operations) id = 'action_%s_reassign_owner' % action if not owners: owner = req.args.get(id, default_owner) control.append( tag_("to %(owner)s", owner=tag.input(type='text', id=id, name=id, value=owner))) if not exists or current_owner is None: hints.append(_("The owner will be the specified user")) else: hints.append(tag_("The owner will be changed from " "%(current_owner)s to the specified " "user", current_owner=formatted_current_owner)) elif len(owners) == 1: owner = tag.input(type='hidden', id=id, name=id, value=owners[0]) formatted_new_owner = author_info(owners[0]) control.append(tag_("to %(owner)s", owner=tag(formatted_new_owner, owner))) if not exists or current_owner is None: hints.append(tag_("The owner will be %(new_owner)s", new_owner=formatted_new_owner)) elif ticket['owner'] != owners[0]: hints.append(tag_("The owner will be changed from " "%(current_owner)s to %(new_owner)s", current_owner=formatted_current_owner, new_owner=formatted_new_owner)) else: selected_owner = req.args.get(id, default_owner) control.append(tag_("to %(owner)s", owner=tag.select( [tag.option(format_author(x), value=x if x is not None else '', selected=(x == selected_owner or None)) for x in owners], id=id, name=id))) if not exists or current_owner is None: hints.append(_("The owner will be the selected user")) else: hints.append(tag_("The owner will be changed from " "%(current_owner)s to the selected user", current_owner=formatted_current_owner)) elif 'set_owner_to_self' in operations and \ ticket._old.get('owner', ticket['owner']) != author: formatted_author = author_info(author) if not exists or current_owner is None: hints.append(tag_("The owner will be %(new_owner)s", new_owner=formatted_author)) else: hints.append(tag_("The owner will be changed from " "%(current_owner)s to %(new_owner)s", current_owner=formatted_current_owner, new_owner=formatted_author)) if 'set_resolution' in operations: if 'set_resolution' in this_action: resolutions = this_action['set_resolution'] else: resolutions = [r.name for r in Resolution.select(self.env)] if not resolutions: raise TracError(_("Your workflow attempts to set a resolution " "but none is defined (configuration issue, " "please contact your Trac admin).")) id = 'action_%s_resolve_resolution' % action if len(resolutions) == 1: resolution = tag.input(type='hidden', id=id, name=id, value=resolutions[0]) control.append(tag_("as %(resolution)s", resolution=tag(resolutions[0], resolution))) hints.append(tag_("The resolution will be set to %(name)s", name=resolutions[0])) else: selected_option = req.args.get(id, TicketSystem(self.env).default_resolution) control.append(tag_("as %(resolution)s", resolution=tag.select( [tag.option(x, value=x, selected=(x == selected_option or None)) for x in resolutions], id=id, name=id))) hints.append(_("The resolution will be set")) if 'del_resolution' in operations: hints.append(_("The resolution will be deleted")) if 'leave_status' in operations: control.append(tag_("as %(status)s", status=ticket._old.get('status', ticket['status']))) if len(operations) == 1: hints.append(tag_("The owner will remain %(current_owner)s", current_owner=formatted_current_owner) if current_owner else _("The ticket will remain with no owner")) else: if ticket['status'] is None: hints.append(tag_("The status will be '%(name)s'", name=status)) elif status != '*': hints.append(tag_("Next status will be '%(name)s'", name=status)) return (this_action['label'], tag(separated(control, ' ')), tag(separated(hints, '. ', '.') if hints else ''))
def filter_stream(self, req, method, filename, stream, data): if req.path_info.startswith('/register') and ( req.method == 'GET' or 'registration_error' in data or 'captcha_error' in req.session): if not (self.private_key or self.private_key): return stream captcha_opts = tag.script("""\ var RecaptchaOptions = { theme: "%s", lang: "%s" }""" % (self.theme, self.lang), type='text/javascript') captcha_js = captcha.displayhtml( self.public_key, use_ssl=True, error='reCAPTCHA incorrect. Please try again.' ) # First Fieldset of the registration form XPath match xpath_match = '//form[@id="acctmgr_registerform"]/fieldset[1]' return stream | Transformer(xpath_match). \ append(captcha_opts + tag(Markup(captcha_js))) # Admin Configuration elif req.path_info.startswith('/admin/accounts/config'): api_html = tag.div( tag.label("Public Key:", for_="recaptcha_public_key") + tag.input(class_="textwidget", name="recaptcha_public_key", value=self.public_key, size=40) ) + tag.div( tag.label("Private Key:", for_="recaptcha_private_key") + tag.input(class_="textwidget", name="recaptcha_private_key", value=self.private_key, size=40) ) if not (self.private_key or self.public_key): api_html = tag.div( tag.a("Generate a reCAPTCHA API key for this Trac " "instance domain.", target="_blank", href="https://recaptcha.net/api/getkey?domain=%s&" "app=TracRecaptchaRegister" % req.environ.get('SERVER_NAME') ) ) + tag.br() + api_html theme_html = tag.div( tag.label("reCPATCHA theme:", for_='recaptcha_theme') + tag.select( tag.option("Black Glass", value="blackglass", selected=self.theme=='blackglass' or None) + tag.option("Clean", value="clean", selected=self.theme=='clean' or None) + tag.option("Red", value="red", selected=self.theme=='red' or None) + tag.option("White", value="white", selected=self.theme=='white' or None), name='recaptcha_theme' ) ) language_html = tag.div( tag.label("reCAPTCHA language:", for_='recaptcha_lang') + tag.select( tag.option("Dutch", value="nl", selected=self.lang=='nl' or None) + tag.option("English", value="en", selected=self.lang=='en' or None) + tag.option("French", selected=self.lang=='fr' or None) + tag.option("German", value="de", selected=self.lang=='de' or None) + tag.option("Portuguese", value="pt", selected=self.lang=='pt' or None) + tag.option("Russian", value="ru", selected=self.lang=='ru' or None) + tag.option("Spanish", value="es", selected=self.lang=='es' or None) + tag.option("Turkish", value="tr", selected=self.lang=='tr' or None), name='recaptcha_lang')) # First fieldset of the Account Manager config form xpath_match = '//form[@id="accountsconfig"]/fieldset[1]' return stream | Transformer(xpath_match). \ before(tag.fieldset(tag.legend("reCAPTCHA") + api_html + tag.br() + theme_html + language_html)) return stream
def render_ticket_action_control(self, req, ticket, action): self.log.debug('render_ticket_action_control: action "%s"' % action) this_action = self.actions[action] status = this_action['newstate'] operations = this_action['operations'] current_owner = ticket._old.get('owner', ticket['owner'] or '(none)') if not (Chrome(self.env).show_email_addresses or 'EMAIL_VIEW' in req.perm(ticket.resource)): format_user = obfuscate_email_address else: format_user = lambda address: address current_owner = format_user(current_owner) control = [] # default to nothing hints = [] if 'reset_workflow' in operations: control.append(tag("from invalid state ")) hints.append(_("Current state no longer exists")) if 'del_owner' in operations: hints.append(_("The ticket will be disowned")) if 'set_owner' in operations: id = 'action_%s_reassign_owner' % action selected_owner = req.args.get(id, req.authname) if this_action.has_key('set_owner'): owners = [x.strip() for x in this_action['set_owner'].split(',')] elif self.config.getbool('ticket', 'restrict_owner'): perm = PermissionSystem(self.env) owners = perm.get_users_with_permission('TICKET_MODIFY') owners.sort() else: owners = None if owners == None: owner = req.args.get(id, req.authname) control.append(tag_('to %(owner)s', owner=tag.input(type='text', id=id, name=id, value=owner))) hints.append(_("The owner will be changed from " "%(current_owner)s", current_owner=current_owner)) elif len(owners) == 1: owner = tag.input(type='hidden', id=id, name=id, value=owners[0]) formatted_owner = format_user(owners[0]) control.append(tag_('to %(owner)s ', owner=tag(formatted_owner, owner))) if ticket['owner'] != owners[0]: hints.append(_("The owner will be changed from " "%(current_owner)s to %(selected_owner)s", current_owner=current_owner, selected_owner=formatted_owner)) else: control.append(tag_('to %(owner)s', owner=tag.select( [tag.option(x, value=x, selected=(x == selected_owner or None)) for x in owners], id=id, name=id))) hints.append(_("The owner will be changed from " "%(current_owner)s", current_owner=current_owner)) if 'set_owner_to_self' in operations and \ ticket._old.get('owner', ticket['owner']) != req.authname: hints.append(_("The owner will be changed from %(current_owner)s " "to %(authname)s", current_owner=current_owner, authname=req.authname)) if 'set_resolution' in operations: if this_action.has_key('set_resolution'): resolutions = [x.strip() for x in this_action['set_resolution'].split(',')] else: resolutions = [val.name for val in Resolution.select(self.env)] if not resolutions: raise TracError(_("Your workflow attempts to set a resolution " "but none is defined (configuration issue, " "please contact your Trac admin).")) id = 'action_%s_resolve_resolution' % action if len(resolutions) == 1: resolution = tag.input(type='hidden', id=id, name=id, value=resolutions[0]) control.append(tag_('as %(resolution)s', resolution=tag(resolutions[0], resolution))) hints.append(_("The resolution will be set to %(name)s", name=resolutions[0])) else: selected_option = req.args.get(id, TicketSystem(self.env).default_resolution) control.append(tag_('as %(resolution)s', resolution=tag.select( [tag.option(x, value=x, selected=(x == selected_option or None)) for x in resolutions], id=id, name=id))) hints.append(_("The resolution will be set")) if 'del_resolution' in operations: hints.append(_("The resolution will be deleted")) if 'leave_status' in operations: control.append(_('as %(status)s ', status= ticket._old.get('status', ticket['status']))) else: if status != '*': hints.append(_("Next status will be '%(name)s'", name=status)) return (this_action['name'], tag(*control), '. '.join(hints))
def render_milestone_action_control(self, req, milestone, action): self.log.debug('render_milestone_action_control: action "%s"' % action) this_action = self.actions[action] status = this_action['newstate'] operations = this_action['operations'] current_owner = milestone._old.get('owner', milestone['owner'] or '(none)') control = [] # default to nothing hints = [] if 'reset_workflow' in operations: control.append(tag("from invalid state ")) hints.append(_("Current state no longer exists")) if 'del_owner' in operations: hints.append(_("The milestone will be disowned")) if 'set_owner' in operations: id = 'action_%s_reassign_owner' % action selected_owner = req.args.get(id, req.authname) if this_action.has_key('set_owner'): owners = [x.strip() for x in this_action['set_owner'].split(',')] elif self.config.getbool('ticket', 'restrict_owner'): perm = PermissionSystem(self.env) owners = perm.get_users_with_permission('MILESTONE_MODIFY') owners.sort() else: owners = None if owners == None: owner = req.args.get(id, req.authname) control.append(tag(['to ', tag.input(type='text', id=id, name=id, value=owner)])) hints.append(_("The owner will change from %(current_owner)s", current_owner=current_owner)) elif len(owners) == 1: control.append(tag('to %s ' % owners[0])) if milestone['owner'] != owners[0]: hints.append(_("The owner will change from " "%(current_owner)s to %(selected_owner)s", current_owner=current_owner, selected_owner=owners[0])) else: control.append(tag([_("to "), tag.select( [tag.option(x, selected=(x == selected_owner or None)) for x in owners], id=id, name=id)])) hints.append(_("The owner will change from %(current_owner)s", current_owner=current_owner)) if 'set_owner_to_self' in operations and \ milestone._old.get('owner', milestone['owner']) != req.authname: hints.append(_("The owner will change from %(current_owner)s " "to %(authname)s", current_owner=current_owner, authname=req.authname)) if 'set_resolution' in operations: if this_action.has_key('set_resolution'): resolutions = [x.strip() for x in this_action['set_resolution'].split(',')] else: resolutions = [val.name for val in model.Resolution.select(self.env)] if not resolutions: raise TracError(_("Your workflow attempts to set a resolution " "but none is defined (configuration issue, " "please contact your Trac admin).")) if len(resolutions) == 1: control.append(tag('as %s' % resolutions[0])) hints.append(_("The resolution will be set to %s") % resolutions[0]) else: id = 'action_%s_resolve_resolution' % action selected_option = req.args.get(id, self.config.get('milestone', 'default_resolution')) control.append(tag(['as ', tag.select( [tag.option(x, selected=(x == selected_option or None)) for x in resolutions], id=id, name=id)])) hints.append(_("The resolution will be set")) if 'leave_status' in operations: control.append('as %s ' % milestone._old.get('status', milestone['status'])) else: if status != '*': hints.append(_("Next status will be '%s'") % status) return (this_action['name'], tag(*control), '. '.join(hints))
def get_operation_control(self, req, action, operation, res_wf_state, resource): self.log.debug(">>> WorkflowStandardOperations - get_operation_control: %s" % operation) id = 'action_%s_operation_%s' % (action, operation) # A custom field named "owner" is required in the ResourceWorkflowState # class for this operation to be available self.env.log.debug(res_wf_state.fields) if operation == 'set_owner' and self._has_field_named('owner', res_wf_state.fields): self.log.debug("Creating control for setting owner.") current_owner = res_wf_state['owner'] or '(none)' if not (Chrome(self.env).show_email_addresses or 'EMAIL_VIEW' in req.perm(resource)): format_user = obfuscate_email_address else: format_user = lambda address: address current_owner = format_user(current_owner) self.log.debug("Current owner is %s." % current_owner) selected_owner = req.args.get(id, req.authname) control = None hint = '' owners = None available_owners = self.config.get(resource.realm, 'available_owners') if available_owners is not None and not available_owners == '': owners = [x.strip() for x in available_owners.split(',')] elif self.config.getbool(resource.realm, 'restrict_owner'): target_permission = self.config.get(resource.realm, 'restrict_owner_to_permission') if target_permission is not None and not target_permission == '': perm = PermissionSystem(self.env) owners = perm.get_users_with_permission(target_permission) owners.sort() if owners == None: owner = req.args.get(id, req.authname) control = tag('Assign to ', tag.input(type='text', id=id, name=id, value=owner)) hint = "The owner will be changed from %s" % current_owner elif len(owners) == 1: owner = tag.input(type='hidden', id=id, name=id, value=owners[0]) formatted_owner = format_user(owners[0]) control = tag('Assign to ', tag(formatted_owner, owner)) if res_wf_state['owner'] != owners[0]: hint = "The owner will be changed from %s to %s" % (current_owner, formatted_owner) else: control = tag('Assign to ', tag.select( [tag.option(format_user(x), value=x, selected=(x == selected_owner or None)) for x in owners], id=id, name=id)) hint = "The owner will be changed from %s" % current_owner return control, hint elif operation == 'set_owner_to_self' and self._has_field_named('owner', res_wf_state.fields) and \ res_wf_state['owner'] != req.authname: current_owner = res_wf_state['owner'] or '(none)' if not (Chrome(self.env).show_email_addresses or 'EMAIL_VIEW' in req.perm(resource)): format_user = obfuscate_email_address else: format_user = lambda address: address current_owner = format_user(current_owner) control = tag('') hint = "The owner will be changed from %s to %s" % (current_owner, req.authname) self.log.debug("<<< WorkflowStandardOperations - get_operation_control - set_owner_to_self") return control, hint elif operation == 'std_notify': pass self.log.debug("<<< WorkflowStandardOperations - get_operation_control") return None, ''
def render_ticket_action_control(self, req, ticket, action): self.log.debug('render_ticket_action_control: action "%s"' % action) this_action = self.actions[action] status = this_action['newstate'] operations = this_action['operations'] current_owner = ticket._old.get('owner', ticket['owner'] or '(none)') if not (Chrome(self.env).show_email_addresses or 'EMAIL_VIEW' in req.perm(ticket.resource)): format_user = obfuscate_email_address else: format_user = lambda address: address current_owner = format_user(current_owner) control = [] # default to nothing hints = [] if 'reset_workflow' in operations: control.append(tag("from invalid state ")) hints.append(_("Current state no longer exists")) if 'del_owner' in operations: hints.append(_("The ticket will be disowned")) if 'set_owner' in operations: id = 'action_%s_reassign_owner' % action selected_owner = req.args.get(id, req.authname) if this_action.has_key('set_owner'): owners = [x.strip() for x in this_action['set_owner'].split(',')] elif self.config.getbool('ticket', 'restrict_owner'): perm = PermissionSystem(self.env) owners = perm.get_users_with_permission('TICKET_MODIFY') owners.sort() else: owners = None if owners == None: owner = req.args.get(id, req.authname) control.append(tag_('to %(owner)s', owner=tag.input(type='text', id=id, name=id, value=owner))) hints.append(_("The owner will be changed from " "%(current_owner)s", current_owner=current_owner)) elif len(owners) == 1: owner = tag.input(type='hidden', id=id, name=id, value=owners[0]) formatted_owner = format_user(owners[0]) control.append(tag_('to %(owner)s ', owner=tag(formatted_owner, owner))) if ticket['owner'] != owners[0]: hints.append(_("The owner will be changed from " "%(current_owner)s to %(selected_owner)s", current_owner=current_owner, selected_owner=formatted_owner)) else: control.append(tag_('to %(owner)s', owner=tag.select( [tag.option(x, value=x, selected=(x == selected_owner or None)) for x in owners], id=id, name=id))) hints.append(_("The owner will be changed from " "%(current_owner)s to the selected user", current_owner=current_owner)) elif 'set_owner_to_self' in operations and \ ticket._old.get('owner', ticket['owner']) != req.authname: hints.append(_("The owner will be changed from %(current_owner)s " "to %(authname)s", current_owner=current_owner, authname=req.authname)) if 'set_resolution' in operations: if this_action.has_key('set_resolution'): resolutions = [x.strip() for x in this_action['set_resolution'].split(',')] else: resolutions = [val.name for val in Resolution.select(self.env)] if not resolutions: raise TracError(_("Your workflow attempts to set a resolution " "but none is defined (configuration issue, " "please contact your Trac admin).")) id = 'action_%s_resolve_resolution' % action if len(resolutions) == 1: resolution = tag.input(type='hidden', id=id, name=id, value=resolutions[0]) control.append(tag_('as %(resolution)s', resolution=tag(resolutions[0], resolution))) hints.append(_("The resolution will be set to %(name)s", name=resolutions[0])) else: selected_option = req.args.get(id, TicketSystem(self.env).default_resolution) control.append(tag_('as %(resolution)s', resolution=tag.select( [tag.option(x, value=x, selected=(x == selected_option or None)) for x in resolutions], id=id, name=id))) hints.append(_("The resolution will be set")) if 'del_resolution' in operations: hints.append(_("The resolution will be deleted")) if 'leave_status' in operations: control.append(_('as %(status)s ', status= ticket._old.get('status', ticket['status']))) else: if status != '*': hints.append(_("Next status will be '%(name)s'", name=status)) return (this_action['name'], tag(*control), '. '.join(hints) + ".")
def render_ticket_action_control(self, req, ticket, action): self.log.debug('render_ticket_action_control: action "%s"', action) this_action = self.actions[action] status = this_action['newstate'] operations = this_action['operations'] current_owner = ticket._old.get('owner', ticket['owner']) author = get_reporter_id(req, 'author') format_author = partial(Chrome(self.env).format_author, req) formatted_current_owner = format_author(current_owner or _("(none)")) control = [] # default to nothing hints = [] if 'reset_workflow' in operations: control.append(_("from invalid state")) hints.append(_("Current state no longer exists")) if 'del_owner' in operations: hints.append(_("The ticket will be disowned")) if 'set_owner' in operations: id = 'action_%s_reassign_owner' % action if 'set_owner' in this_action: owners = [x.strip() for x in this_action['set_owner'].split(',')] elif self.config.getbool('ticket', 'restrict_owner'): perm = PermissionSystem(self.env) owners = perm.get_users_with_permission('TICKET_MODIFY') owners.sort() else: owners = None if owners is None: owner = req.args.get(id, author) control.append(tag_("to %(owner)s", owner=tag.input(type='text', id=id, name=id, value=owner))) hints.append(_("The owner will be changed from " "%(current_owner)s to the specified user", current_owner=formatted_current_owner)) elif len(owners) == 1: owner = tag.input(type='hidden', id=id, name=id, value=owners[0]) formatted_new_owner = format_author(owners[0]) control.append(tag_("to %(owner)s", owner=tag(formatted_new_owner, owner))) if ticket['owner'] != owners[0]: hints.append(_("The owner will be changed from " "%(current_owner)s to %(selected_owner)s", current_owner=formatted_current_owner, selected_owner=formatted_new_owner)) else: selected_owner = req.args.get(id, req.authname) control.append(tag_("to %(owner)s", owner=tag.select( [tag.option(x, value=x, selected=(x == selected_owner or None)) for x in owners], id=id, name=id))) hints.append(_("The owner will be changed from " "%(current_owner)s to the selected user", current_owner=formatted_current_owner)) elif 'set_owner_to_self' in operations and \ ticket._old.get('owner', ticket['owner']) != author: hints.append(_("The owner will be changed from %(current_owner)s " "to %(authname)s", current_owner=formatted_current_owner, authname=format_author(author))) if 'set_resolution' in operations: if 'set_resolution' in this_action: resolutions = [x.strip() for x in this_action['set_resolution'].split(',')] else: resolutions = [r.name for r in Resolution.select(self.env)] if not resolutions: raise TracError(_("Your workflow attempts to set a resolution " "but none is defined (configuration issue, " "please contact your Trac admin).")) id = 'action_%s_resolve_resolution' % action if len(resolutions) == 1: resolution = tag.input(type='hidden', id=id, name=id, value=resolutions[0]) control.append(tag_("as %(resolution)s", resolution=tag(resolutions[0], resolution))) hints.append(_("The resolution will be set to %(name)s", name=resolutions[0])) else: selected_option = req.args.get(id, TicketSystem(self.env).default_resolution) control.append(tag_("as %(resolution)s", resolution=tag.select( [tag.option(x, value=x, selected=(x == selected_option or None)) for x in resolutions], id=id, name=id))) hints.append(_("The resolution will be set")) if 'del_resolution' in operations: hints.append(_("The resolution will be deleted")) if 'leave_status' in operations: control.append(_("as %(status)s", status= ticket._old.get('status', ticket['status']))) if len(operations) == 1: hints.append(_("The owner will remain %(current_owner)s", current_owner=formatted_current_owner) if current_owner else _("The ticket will remain with no owner")) else: if status != '*': hints.append(_("Next status will be '%(name)s'", name=status)) return (this_action.get('name', action), tag(separated(control, ' ')), '. '.join(hints) + '.' if hints else '')
def render_ticket_action_control(self, req, ticket, action): from trac.ticket import model self.log.debug('render_ticket_action_control: action "%s"' % action) tipo_ticket = ticket._old.get('type', ticket['type']) self.actions = get_workflow_config_by_type(self.config, tipo_ticket) if len(self.actions) < 1: self.actions = get_workflow_config_default(self.config) this_action = self.actions[action] status = this_action['newstate'] operations = this_action['operations'] current_owner = ticket._old.get('owner', ticket['owner'] or '(none)') control = [] # default to nothing hints = [] if 'reset_workflow' in operations: control.append(tag("from invalid state ")) hints.append(_("Current state no longer exists")) if 'del_owner' in operations: hints.append(_("The ticket will be disowned")) if 'set_owner' in operations: id = 'action_%s_reassign_owner' % action selected_owner = req.args.get(id, req.authname) if this_action.has_key('set_owner'): owners = [ x.strip() for x in this_action['set_owner'].split(',') ] elif self.config.getbool('ticket', 'restrict_owner'): perm = PermissionSystem(self.env) owners = perm.get_users_with_permission('TICKET_MODIFY') owners.sort() else: owners = None if owners == None: owner = req.args.get(id, req.authname) control.append( tag([ 'to ', tag.input(type='text', id=id, name=id, value=owner) ])) hints.append( _("The owner will change from %(current_owner)s", current_owner=current_owner)) elif len(owners) == 1: control.append(tag('to %s ' % owners[0])) if ticket['owner'] != owners[0]: hints.append( _( "The owner will change from " "%(current_owner)s to %(selected_owner)s", current_owner=current_owner, selected_owner=owners[0])) else: control.append( tag([ _("to "), tag.select([ tag.option(x, selected=(x == selected_owner or None)) for x in owners ], id=id, name=id) ])) hints.append( _("The owner will change from %(current_owner)s", current_owner=current_owner)) if 'set_owner_to_self' in operations and \ ticket._old.get('owner', ticket['owner']) != req.authname: hints.append( _( "The owner will change from %(current_owner)s " "to %(authname)s", current_owner=current_owner, authname=req.authname)) if 'set_resolution' in operations: if this_action.has_key('set_resolution'): resolutions = [ x.strip() for x in this_action['set_resolution'].split(',') ] else: resolutions = [ val.name for val in model.Resolution.select(self.env) ] if not resolutions: raise TracError( _("Your workflow attempts to set a resolution " "but none is defined (configuration issue, " "please contact your Trac admin).")) if len(resolutions) == 1: control.append(tag('as %s' % resolutions[0])) hints.append( _("The resolution will be set to %s") % resolutions[0]) else: id = 'action_%s_resolve_resolution' % action selected_option = req.args.get( id, self.config.get('ticket', 'default_resolution')) control.append( tag([ 'as ', tag.select([ tag.option(x, selected=(x == selected_option or None)) for x in resolutions ], id=id, name=id) ])) hints.append(_("The resolution will be set")) if 'leave_status' in operations: control.append('as %s ' % ticket._old.get('status', ticket['status'])) else: if status != '*': hints.append(_("Next status will be '%s'") % status) return (this_action['name'], tag(*control), '. '.join(hints))
def render_ticket_action_control(self, req, ticket, action): if ticket['type'] != 'pull request': items = [ controller.render_ticket_action_control(req, ticket, action) for controller in self.action_controllers ] return chain.from_iterable(self._filter_resolutions(req, items)) rm = RepositoryManager(self.env) repo = rm.get_repository_by_id(ticket['pr_dstrepo'], True) current_status = ticket._old.get('status', ticket['status']) or 'new' current_owner = ticket._old.get('owner', ticket['owner']) control = [] hints = [] if action == 'leave': control.append(_('as %(status)s ', status=current_status)) if current_owner: hints.append( _("The owner will remain %(current_owner)s", current_owner=current_owner)) else: hints.append( _("The ticket will remain with no owner", owner=current_owner)) if action == 'accept': if repo.has_node('', ticket['pr_srcrev']): hints.append(_("The request will be accepted")) hints.append(_("Next status will be '%(name)s'", name='closed')) else: hints.append( _("The changes must be merged into '%(repo)s' " "first", repo=repo.reponame)) if action == 'reject': if not repo.has_node('', ticket['pr_srcrev']): hints.append(_("The request will be rejected")) hints.append(_("Next status will be '%(name)s'", name='closed')) else: hints.append( _("The changes are already present in '%(repo)s'", repo=repo.reponame)) if action == 'reassign': maintainers = (set([repo.owner]) | repo.maintainers()) maintainers -= set([current_owner]) selected_owner = req.args.get('action_reassign_reassign_owner', req.authname) control.append( tag.select([ tag.option( x, value=x, selected=(x == selected_owner or None)) for x in maintainers ], id='action_reassign_reassign_owner', name='action_reassign_reassign_owner')) hints.append( _( "The owner will be changed from %(old)s to the " "selected user. Next status will be 'assigned'", old=current_owner)) if action == 'review': if current_owner != req.authname: hints.append( _( "The owner will be changes from " "%(current_owner)s to %(authname)s", current_owner=current_owner, authname=req.authname)) hints.append( _("Next status will be '%(name)s'", name='under review')) if action == 'reopen': hints.append(_("The resolution will be deleted")) hints.append(_("Next status will be '%(name)s'", name='reopened')) return (action, tag(control), '. '.join(hints) + '.')
def get_operation_control(self, req, action, operation, res_wf_state, resource): self.log.debug( ">>> WorkflowStandardOperations - get_operation_control: %s" % operation) id = 'action_%s_operation_%s' % (action, operation) # A custom field named "owner" is required in the ResourceWorkflowState # class for this operation to be available self.env.log.debug(res_wf_state.fields) if operation == 'set_owner' and self._has_field_named( 'owner', res_wf_state.fields): self.log.debug("Creating control for setting owner.") current_owner = res_wf_state['owner'] or '(none)' if not (Chrome(self.env).show_email_addresses or 'EMAIL_VIEW' in req.perm(resource)): format_user = obfuscate_email_address else: format_user = lambda address: address current_owner = format_user(current_owner) self.log.debug("Current owner is %s." % current_owner) selected_owner = req.args.get(id, req.authname) control = None hint = '' owners = None available_owners = self.config.get(resource.realm, 'available_owners') if available_owners is not None and not available_owners == '': owners = [x.strip() for x in available_owners.split(',')] elif self.config.getbool(resource.realm, 'restrict_owner'): target_permission = self.config.get( resource.realm, 'restrict_owner_to_permission') if target_permission is not None and not target_permission == '': perm = PermissionSystem(self.env) owners = perm.get_users_with_permission(target_permission) owners.sort() if owners == None: owner = req.args.get(id, req.authname) control = tag( 'Assign to ', tag.input(type='text', id=id, name=id, value=owner)) hint = "The owner will be changed from %s" % current_owner elif len(owners) == 1: owner = tag.input(type='hidden', id=id, name=id, value=owners[0]) formatted_owner = format_user(owners[0]) control = tag('Assign to ', tag(formatted_owner, owner)) if res_wf_state['owner'] != owners[0]: hint = "The owner will be changed from %s to %s" % ( current_owner, formatted_owner) else: control = tag( 'Assign to ', tag.select([ tag.option(format_user(x), value=x, selected=(x == selected_owner or None)) for x in owners ], id=id, name=id)) hint = "The owner will be changed from %s" % current_owner return control, hint elif operation == 'set_owner_to_self' and self._has_field_named('owner', res_wf_state.fields) and \ res_wf_state['owner'] != req.authname: current_owner = res_wf_state['owner'] or '(none)' if not (Chrome(self.env).show_email_addresses or 'EMAIL_VIEW' in req.perm(resource)): format_user = obfuscate_email_address else: format_user = lambda address: address current_owner = format_user(current_owner) control = tag('') hint = "The owner will be changed from %s to %s" % (current_owner, req.authname) self.log.debug( "<<< WorkflowStandardOperations - get_operation_control - set_owner_to_self" ) return control, hint elif operation == 'std_notify': pass self.log.debug( "<<< WorkflowStandardOperations - get_operation_control") return None, ''
def filter_stream(self, req, method, filename, stream, formdata): """Modifies query page to add modifiable components""" self.log.debug("GridModifyModule: filter_stream entered") # We create an invisible storage div in the document for the default tag values. # JQuery then uses this information to update the relevant fields on the page. if (filename == 'query.html' or filename == 'report_view.html') and \ (req.perm.has_permission('TICKET_ADMIN') or req.perm.has_permission('TICKET_GRID_MODIFY')): add_script(req, 'gridmod/gridmod.js') xpath = '//div[@id="content"]' div = tag.div(id="table_inits_holder", style="display:none;") div.append("\n") for field in TicketSystem(self.env).get_ticket_fields(): #debug self.log.debug("filter_stream: field: " + str(field)) # SELECT tags if field['type'] == 'select' and (field['name'] in self.fields or len(self.fields) == 0): select = tag.select(name=field['name'], class_="gridmod_form") self.log.debug("SELECT INPUT '%s' (%s)", field['name'], field['label']) if (field.has_key('value')): self.log.debug( " SELECT HAS DEFAULT VALUE '%s'", field['value']) else: self.log.debug(" SELECT HAS NO DEFAULT VALUE") # HACK: For some reason custom fields that have a blank value # as a valid option don't actually have that blank # value among the options in field['options'] so # we force a blank option in in the case where the # _default_ value is blank. select.append("\n") if (field.has_key('value') and field['value'] == '' and not ('' in field['options'])): select.append(tag.option()) for option in field['options']: select.append(tag.option(option, value=option)) select.append("\n") div.append(select) # INPUT TEXT tags elif field['type'] == 'text' and field['name'] in self.fields: text = tag.input(type='text', name=field['name'], class_='gridmod_form') if (field.has_key('value')): self.log.debug( "TEXT INPUT '%s' (%s) HAS DEFAULT VALUE '%s'", field['name'], field['label'], field['value']) text.append(field['value']) else: text.append('') div.append(text) # INPUT CHECKBOX tags elif field['type'] == 'checkbox' and field[ 'name'] in self.fields: checkbox = tag.input(type='checkbox', name=field['name'], class_='gridmod_form') if (field.has_key('value')): self.log.debug( "CHECKBOX INPUT '%s' (%s) HAS DEFAULT VALUE '%s'", field['name'], field['label'], field['value']) checkbox.append(field['value']) if (field['value'] == 1 or field['value'] == True): checkbox(checked="checked") else: checkbox.append('0') div.append(checkbox) # INPUT RADIO tags elif field['type'] == 'radio' and field['name'] in self.fields: # This is slightly complicated. # We convert the radio values into a SELECT tag for screen real estate reasons. # It gets handled as a SELECT at the server end of the AJAX call, which appears to work fine. # Note: If none of the RADIO buttons is checked, we default here to checking the first one, for code safety. # That should never happen. default_decided = False radio_select = tag.select(name=field['name'], class_="gridmod_form") if (field.has_key('value')): self.log.debug( "RADIO INPUT '%s' (%s) HAS DEFAULT VALUE '%s'", field['name'], field['label'], field['value']) default_val = field['value'] default_decided = True for option in field['options']: self.log.debug(" doing radio option '%s'", option) select_option = tag.option(option, value=option) if (option == default_val) or (not default_decided): self.log.debug(" SELECTED '%s'", option) select_option(selected="selected") default_decided = True radio_select.append(select_option) radio_select.append("\n") div.append(radio_select) div.append("\n") # INPUT TEXTAREA tags # We are ignoring TextArea for now, as there are several complications including: # * Rendering is handled differently to other fields in the report form # * TextAreas support Wiki formatting so would need to use the Wiki engine stream |= Transformer(xpath).append(div) return stream
def filter_stream(self, req, method, filename, stream, data): if req.path_info.startswith('/register') and ( req.method == 'GET' or 'registration_error' in data or 'captcha_error' in req.session): if not (self.private_key or self.private_key): return stream captcha_opts = tag.script("""\ var RecaptchaOptions = { theme: "%s", lang: "%s" }""" % (self.theme, self.lang), type='text/javascript') captcha_js = captcha.displayhtml( self.public_key, use_ssl=req.scheme == 'https', error='reCAPTCHA incorrect. Please try again.') # First Fieldset of the registration form XPath match xpath_match = '//form[@id="acctmgr_registerform"]/fieldset[1]' return stream | Transformer(xpath_match). \ append(captcha_opts + tag(Markup(captcha_js))) # Admin Configuration elif req.path_info.startswith('/admin/accounts/config'): api_html = tag.div( tag.label("Public Key:", for_="recaptcha_public_key") + tag.input(class_="textwidget", name="recaptcha_public_key", value=self.public_key, size=40) ) + tag.div( tag.label("Private Key:", for_="recaptcha_private_key") + tag.input(class_="textwidget", name="recaptcha_private_key", value=self.private_key, size=40)) if not (self.private_key or self.public_key): api_html = tag.div( tag.a( "Generate a reCAPTCHA API key for this Trac " "instance domain.", target="_blank", href="http://recaptcha.net/api/getkey?domain=%s&" "app=TracRecaptchaRegister" % req.environ.get('SERVER_NAME'))) + tag.br() + api_html theme_html = tag.div( tag.label("reCPATCHA theme:", for_='recaptcha_theme') + tag.select( tag.option("Black Glass", value="blackglass", selected=self.theme == 'blackglass' or None) + tag.option("Clean", value="clean", selected=self.theme == 'clean' or None) + tag.option("Red", value="red", selected=self.theme == 'red' or None) + tag.option("White", value="white", selected=self.theme == 'white' or None), name='recaptcha_theme')) language_html = tag.div( tag.label("reCAPTCHA language:", for_='recaptcha_lang') + tag.select(tag.option( "Dutch", value="nl", selected=self.lang == 'nl' or None ) + tag.option( "English", value="en", selected=self.lang == 'en' or None ) + tag.option("French", selected=self.lang == 'fr' or None) + tag.option("German", value="de", selected=self.lang == 'de' or None) + tag.option("Portuguese", value="pt", selected=self.lang == 'pt' or None) + tag.option("Russian", value="ru", selected=self.lang == 'ru' or None) + tag.option("Spanish", value="es", selected=self.lang == 'es' or None) + tag.option("Turkish", value="tr", selected=self.lang == 'tr' or None), name='recaptcha_lang')) # First fieldset of the Account Manager config form xpath_match = '//form[@id="accountsconfig"]/fieldset[1]' return stream | Transformer(xpath_match). \ before(tag.fieldset(tag.legend("reCAPTCHA") + api_html + tag.br() + theme_html + language_html)) return stream
def render_ticket_action_control(self, req, ticket, action): self.log.debug('render_ticket_action_control: action "%s"', action) this_action = self.actions[action] status = this_action['newstate'] operations = this_action['operations'] current_owner = ticket._old.get('owner', ticket['owner']) author = get_reporter_id(req, 'author') author_info = partial(Chrome(self.env).authorinfo, req, resource=ticket.resource) format_author = partial(Chrome(self.env).format_author, req, resource=ticket.resource) formatted_current_owner = author_info(current_owner) exists = ticket._old.get('status', ticket['status']) is not None control = [] # default to nothing hints = [] if 'reset_workflow' in operations: control.append(_("from invalid state")) hints.append(_("Current state no longer exists")) if 'del_owner' in operations: hints.append(_("The ticket will be disowned")) if 'set_owner' in operations or 'may_set_owner' in operations: if 'set_owner' in this_action: owners = self._to_users(this_action['set_owner'], ticket) elif self.config.getbool('ticket', 'restrict_owner'): perm = PermissionSystem(self.env) owners = perm.get_users_with_permission('TICKET_MODIFY') owners = [ user for user in owners if 'TICKET_MODIFY' in PermissionCache( self.env, user, ticket.resource) ] owners = sorted(owners) else: owners = None if 'set_owner' in operations: default_owner = author elif 'may_set_owner' in operations: if not exists: default_owner = TicketSystem(self.env).default_owner else: default_owner = ticket._old.get('owner', ticket['owner'] or None) if owners is not None and default_owner not in owners: owners.insert(0, default_owner) else: # Protect against future modification for case that another # operation is added to the outer conditional raise AssertionError(operations) id = 'action_%s_reassign_owner' % action if not owners: owner = req.args.get(id, default_owner) control.append( tag_("to %(owner)s", owner=tag.input(type='text', id=id, name=id, value=owner))) if not exists or current_owner is None: hints.append(_("The owner will be the specified user")) else: hints.append( tag_( "The owner will be changed from " "%(current_owner)s to the specified " "user", current_owner=formatted_current_owner)) elif len(owners) == 1: owner = tag.input(type='hidden', id=id, name=id, value=owners[0]) formatted_new_owner = author_info(owners[0]) control.append( tag_("to %(owner)s", owner=tag(formatted_new_owner, owner))) if not exists or current_owner is None: hints.append( tag_("The owner will be %(new_owner)s", new_owner=formatted_new_owner)) elif ticket['owner'] != owners[0]: hints.append( tag_( "The owner will be changed from " "%(current_owner)s to %(new_owner)s", current_owner=formatted_current_owner, new_owner=formatted_new_owner)) else: selected_owner = req.args.get(id, default_owner) control.append( tag_("to %(owner)s", owner=tag.select([ tag.option( label, value=value if value is not None else '', selected=(value == selected_owner or None)) for label, value in sorted( (format_author(owner), owner) for owner in owners) ], id=id, name=id))) if not exists or current_owner is None: hints.append(_("The owner will be the selected user")) else: hints.append( tag_( "The owner will be changed from " "%(current_owner)s to the selected user", current_owner=formatted_current_owner)) elif 'set_owner_to_self' in operations and \ ticket._old.get('owner', ticket['owner']) != author: formatted_author = author_info(author) if not exists or current_owner is None: hints.append( tag_("The owner will be %(new_owner)s", new_owner=formatted_author)) else: hints.append( tag_( "The owner will be changed from " "%(current_owner)s to %(new_owner)s", current_owner=formatted_current_owner, new_owner=formatted_author)) if 'set_resolution' in operations: if 'set_resolution' in this_action: resolutions = this_action['set_resolution'] else: resolutions = [r.name for r in Resolution.select(self.env)] if not resolutions: raise TracError( _("Your workflow attempts to set a resolution " "but none is defined (configuration issue, " "please contact your Trac admin).")) id = 'action_%s_resolve_resolution' % action if len(resolutions) == 1: resolution = tag.input(type='hidden', id=id, name=id, value=resolutions[0]) control.append( tag_("as %(resolution)s", resolution=tag(resolutions[0], resolution))) hints.append( tag_("The resolution will be set to %(name)s", name=resolutions[0])) else: selected_option = req.args.get( id, TicketSystem(self.env).default_resolution) control.append( tag_( "as %(resolution)s", resolution=tag.select([ tag.option(x, value=x, selected=(x == selected_option or None)) for x in resolutions ], id=id, name=id))) hints.append(_("The resolution will be set")) if 'del_resolution' in operations: hints.append(_("The resolution will be deleted")) if 'leave_status' in operations: control.append( tag_("as %(status)s", status=ticket._old.get('status', ticket['status']))) if len(operations) == 1: hints.append( tag_("The owner will remain %(current_owner)s", current_owner=formatted_current_owner) if current_owner else _("The ticket will remain with no owner" )) elif not operations: if status != '*': if ticket['status'] is None: hints.append( tag_("The status will be '%(name)s'", name=status)) else: hints.append( tag_("Next status will be '%(name)s'", name=status)) return (this_action['label'], tag(separated(control, ' ')), tag(separated(hints, '. ', '.') if hints else ''))
def filter_stream(self, req, method, filename, stream, data): if filename in ['customfieldadmin.html']: stream = stream | Transformer('//select[@id="format"]').append( tag.option('Epoch', value='epoch') ) return stream
def filter_stream(self, req, method, filename, stream, data): select = tag.select( id="select-user-groups", multiple="multiple", name="user_groups", ) edit_name = req.path_info.replace("/admin/ticket/customfields", "")[1:] valid_edit = re.search('^[a-zA-Z][a-zA-Z0-9_]+$', edit_name) currently_editing = edit_name and valid_edit if currently_editing: groups = self.config.get("ticket-custom", edit_name+".groups") groups = groups.split("|") else: groups = [] is_manual = self.config.getbool("ticket-custom", edit_name+".manual") manual = tag.div( tag.label( "Allow typing a name which is not in the list:", for_="manual_selection", class_="fixed-width-label" ), tag.input( value="manual", checked="checked" if is_manual else None, type_="checkbox", name="manual_selection" ), class_="field" ) radios = tag( tag.label( "All ", tag.input( type="radio", value="all", name="all_or_selection", checked=("checked" if "*" in groups else None), ) ), tag.span( " or ", class_="color-muted" ), tag.label( "Selection ", tag.input( type="radio", value="selection", name="all_or_selection", checked=(None if "*" in groups else "checked"), ), style="padding-right: 5px" )) autocomplete = AutoCompleteGroup(self.env) for sid in autocomplete.get_autocomplete_values('shown_groups'): select.append(tag.option( Group(self.env, sid).label, value=sid, selected=("selected" if sid in groups or "*" in groups else None) )) if filename == "customfieldadmin.html": add_script(req, 'userfield/js/customfield-admin.js') selected = None customfield = data['cfadmin'].get('customfield', None) if customfield: if customfield['type'] == 'user': selected = 'selected' stream = stream | Transformer('.//select[@id="type"]').append( tag.option('User List', value='user', id="user_type_option", selected=selected) ) stream = stream | Transformer( './/div[@id="field-label"]' ).after( tag.div( tag.div( tag.label( 'Included groups:', for_="user-groups", class_="fixed-width-label", ), radios, select, class_="field", ), tag.div( tag.label(class_="fixed-width-label"), tag.span('To have more groups listed here, check "Show by default in user drop down boxes" in ', tag.a("Manage Access and Groups", target="_blank", href=req.href.admin('access', 'access_and_groups')), ' administration page.'), id="group-selection-help" ), manual, id="user-groups", class_="hidden" ) ) return stream
def filter_stream(self, req, method, filename, stream, data): if filename in ['customfieldadmin.html']: stream = stream | Transformer('//select[@id="format"]').append( tag.option('Epoch', value='epoch')) return stream