def add_template_data(self, req, data, tickets): data['batch_modify'] = True data['query_href'] = req.session['query_href'] or req.href.query() data['action_controls'] = self._get_action_controls(req, tickets) batch_list_modes = [ { 'name': _("add"), 'value': "+" }, { 'name': _("remove"), 'value': "-" }, { 'name': _("add / remove"), 'value': "+-" }, { 'name': _("set to"), 'value': "=" }, ] add_script_data(req, batch_list_modes=batch_list_modes, batch_list_properties=self._get_list_fields())
def filter_stream(self, req, method, filename, stream, data): if req.path_info.startswith('/ticket'): button = tag.div( tag.input(type="submit", title=_("Translate to %s") % req.locale.get_display_name(), value=_("Translate"), forward=_("Translate"), backward=_("Untranslate"), working=_("Working"), name="translate", class_="translate")) button(class_="inlinebuttons") script = tag.script('') script(src='https://www.google.com/jsapi?key=' + self.googleApiKey) script(type='text/javascript') stream |= Transformer('//head').prepend(script) stream |= Transformer( '//div[@id="content"]/div[@id="ticket"]/div[@class="description"]/h3' ).after(button) stream |= Transformer( '//div[@id="content"]/div/div[@id="changelog"]/div[@class="change"]/h3' ).after(button) add_stylesheet(req, 'translate/translate.css') add_script_data(req, {'googleApiKey': self.googleApiKey}) add_script_data(req, {'sessionLanguage': req.locale.language}) add_script(req, 'translate/translate.js') return stream
def post_process_request(self, req, template, data, content_type): if data is None: return js_data = { 'comments_rest_url': req.href(CommentsREST.href), 'formatting_help_url': req.href.wiki('WikiFormatting'), 'delete_url': req.href(DeleteCommentForm.href), 'preview_url': req.href(WikiPreview.href), 'templates': self.templates_js_data(), 'active_comment_id': req.args.get('codecomment'), 'username': req.authname, 'is_admin': 'TRAC_ADMIN' in req.perm, } original_return_value = template, data, content_type if req.path_info.startswith('/changeset/'): js_data.update(self.changeset_js_data(req, data)) elif req.path_info.startswith('/browser'): js_data.update(self.browser_js_data(req, data)) elif re.match(r'/attachment/ticket/\d+/.*', req.path_info): js_data.update(self.attachment_js_data(req, data)) else: return original_return_value add_script(req, 'code-comments/json2.js') add_script(req, 'code-comments/underscore-min.js') add_script(req, 'code-comments/backbone-min.js') # jQuery UI includes: UI Core, Interactions, Button & Dialog Widgets, Core Effects, custom theme add_script(req, 'code-comments/jquery-ui/jquery-ui.js') add_stylesheet(req, 'code-comments/jquery-ui/trac-theme.css') add_script(req, 'code-comments/jquery.ba-throttle-debounce.min.js') add_script(req, 'code-comments/code-comments.js') add_script_data(req, {'CodeComments': js_data}) return original_return_value
def post_process_request(self, req, template, data, content_type): match = re.match(r'^/browser/?$', req.path_info) if match: config = self.config.options('folded-repository-index') add_script_data(req, { 'fri_config' : dict(config) }) add_script(req, 'fri/folded_repository_index.js') return template, data, content_type
def render_admin_panel(self, req, cat, page, path_info): req.perm.assert_permission('TRAC_ADMIN') if req.method == 'POST': self._parse_request(req) action, status = self._conf_to_inner_format(self.config) operations = self.operations permissions = self._get_permissions(req) add_stylesheet(req, 'tracworkflowadmin/themes/base/jquery-ui.css') add_stylesheet(req, 'tracworkflowadmin/css/tracworkflowadmin.css') add_stylesheet(req, 'tracworkflowadmin/css/jquery.multiselect.css') add_script(req, 'tracworkflowadmin/scripts/jquery-ui.js') add_script(req, 'tracworkflowadmin/scripts/jquery.json-2.2.js') add_script(req, 'tracworkflowadmin/scripts/jquery.multiselect.js') add_script(req, 'tracworkflowadmin/scripts/main.js') add_script_data(req, {'auto_update_interval': int(self.auto_update_interval)}) if req.locale and str(req.locale) in self.msgjs_locales: add_script(req, 'tracworkflowadmin/scripts/messages/%s.js' % req.locale) data = { 'actions': action, 'status': status, 'perms': permissions, 'operations': operations, 'editor_mode': req.args.get('editor_mode') or self.default_editor, 'text': self._conf_to_str(self.config) } return 'tracworkflowadmin.html', data
def process_request(self, req): req.perm.assert_permission('TICKET_VIEW') req.send_header('X-UA-Compatible', 'IE=edge') if req.path_info == '/ticketcalendar-ticket': return self._process_ticket_detail(req) self._add_header_contents(req) calendar = TicketCalendar(self.env, req) query = calendar.get_query(calendar.get_constraints()) data = calendar.template_data(req, query) data['query_form_filters'] = self._render_query_form_filters(req, data) properties = dict((name, dict((key, field[key]) for key in ('type', 'label', 'options', 'optgroups') if key in field)) for name, field in data['fields'].iteritems()) add_script_data(req, {'properties': properties, 'modes': self._get_modes(data)}) redirect = 'update' in req.args if req.path_info == '/ticketcalendar-box': month = _parse_month_arg(req.args.get('_month'), req.tz) if redirect: req.redirect(calendar.get_box_href(query, month)) return self._process_box(req, query, data, month) if req.path_info == '/ticketcalendar-list': start, period = _parse_duration_arg(req.args.getfirst('_duration'), req.tz) if redirect: req.redirect(calendar.get_list_href(query, start, period)) return self._process_list(req, query, data, start, period)
def post_process_request(self, req, template, data, content_type): add_script(req, 'wikicomments/wikicomments.js') add_script_data(req, { '_wikicomments_author': req.authname, '_wikicomments_base': "%s/chrome/wikicomments" % req.base_path }) return template, data, content_type
def add_template_data(self, req, data, tickets): if isinstance(self.env, ProductEnvironment): super(ProductBatchModifyModule, self).add_template_data(req, data, tickets) return data['batch_modify'] = True data['query_href'] = req.session['query_href'] or req.href.query() tickets_by_product = {} for t in tickets: tickets_by_product.setdefault(t['product'], []).append(t) data['action_controls'] = [] global_env = ProductEnvironment.lookup_global_env(self.env) cache = {} for k, v in tickets_by_product.iteritems(): batch_module = cache.get(k or '') if batch_module is None: env = ProductEnvironment(global_env, k) if k else global_env cache[k] = batch_module = ProductBatchModifyModule(env) data['action_controls'] += batch_module._get_action_controls(req, v) batch_list_modes = [ {'name': _("add"), 'value': "+"}, {'name': _("remove"), 'value': "-"}, {'name': _("add / remove"), 'value': "+-"}, {'name': _("set to"), 'value': "="}, ] add_script_data(req, batch_list_modes=batch_list_modes, batch_list_properties=self._get_list_fields())
def render_admin_panel(self, req, cat, page, path_info): req.perm('admin', 'ticket/workflowadmin').require('TICKET_ADMIN') if req.method == 'POST': self._parse_request(req) action, status = self._conf_to_inner_format(self.config) operations = self.operations permissions = self._get_permissions(req) add_stylesheet(req, 'tracworkflowadmin/css/tracworkflowadmin.css') self._add_jquery_ui(req) add_stylesheet(req, 'tracworkflowadmin/css/jquery.multiselect.css') add_script(req, 'tracworkflowadmin/scripts/jquery.json-2.2.js') add_script(req, self._jquery_multiselect) add_script(req, 'tracworkflowadmin/scripts/main.js') add_script_data( req, {'auto_update_interval': int(self.auto_update_interval)}) if req.locale and str(req.locale) in self.msgjs_locales: add_script(req, 'tracworkflowadmin/scripts/messages/%s.js' % req.locale) data = { 'actions': action, 'status': status, 'perms': permissions, 'operations': operations, 'editor_mode': req.args.get('editor_mode') or self.default_editor, 'text': self._conf_to_str(self.config), } if _use_jinja2: data['help'] = _help(req.href) return 'tracworkflowadmin.html', data
def post_process_request(self, req, template, data, content_type): mine = ["/newticket", "/ticket", "/simpleticket"] if self.use_milestone: mine.append("/milestone") mine.append("/admin/ticket/milestones") match = False for target in mine + self.match_req: if req.path_info.startswith(target): match = True break if match: format = {"dmy": "dd%smm%syy", "mdy": "mm%sdd%syy", "ymd": "yy%smm%sdd"}.get( self.date_format, "dd%smm%syy" ) % (self.date_sep, self.date_sep) add_script_data( req, { "datefield": { "calendar": req.href.chrome("common", "ics.png"), "format": format, "first_day": self.first_day, "show_week": self.show_week, "show_panel": self.show_panel, "num_months": self.num_months, "change_month": self.change_month, "change_year": self.change_year, } }, ) add_script(req, "datefield/js/jquery-ui-1.8.16.custom.min.js") add_script(req, "datefield/js/datefield.js") add_stylesheet(req, "datefield/css/jquery-ui-1.8.16.custom.css") return template, data, content_type
def filter_stream(self, req, method, filename, stream, data): selector = ['.user-field'] page_map = { "ticket.html": ["#field-owner", "#field-reporter"], "query.html": ["#mods-filters input[name$='_" + field + "']" for field in ("owner", "reporter")], "admin_components.html": ["input[name='owner']"], "taskboard.html": ["input[class='user-field']"] } page_map["hours_timeline.html"] = page_map["query.html"] def _template_filenames(): for plugin in self.extra_templates: for filename in plugin.get_templates(): yield filename if filename in page_map: if filename == "ticket.html": selector.extend('#field-' + n for n in self._user_fields()) if self.transform_owner_reporter: selector.extend(page_map[filename]) if filename in page_map or filename in _template_filenames(): self._add_groups_data(req) add_script_data(req, {'userfieldSelector': ','.join(selector) }) add_script(req, 'userfield/js/userfield.js') return stream
def _add_groups_data(self, req, allow_manual=False): perms = sorted(PermissionSystem(self.env).get_all_permissions()) autocomplete = AutoCompleteGroup(self.env) all_groups = set(Group.groupsBy(self.env)) # TODO: we should remove the autocomplete plugin, at least # once userfield can handle "cc style" fields (e.g., multiple # users selected) and then I think userfieldplugin should take over ownership # of the "shown_groups" settings shown_groups = autocomplete.get_autocomplete_values('shown_groups') groups = {} for group_name in shown_groups: group = Group(self.env, group_name) groups[group_name] = { 'label': group.label } if not group.external_group: groups[group_name]['members'] = [] for subject, permission in perms: if permission == group_name and subject not in all_groups: subject_data = {'id': subject} session = DetachedSession(self.env, subject) if 'name' in session: subject_data['name'] = session['name'] groups[group_name]['members'].append(subject_data) add_script_data(req, {'userGroups': groups })
def _add_milestones_maps(self, req, ticket_data): milestone = ticket_data.get_value_or_default('milestone') project = ticket_data.get_value_or_default('project') allProjects = self.__SmpModel.get_all_projects() initialProjectMilestone = [project, milestone] milestonesForProject = {} milestonesForProject[""] = {"Please, select a project!": ""} for project in sorted(allProjects, key=itemgetter(1)): milestones = self.__SmpModel.get_milestones_of_project(project[1]) milestonesForProject[project[1]] = {"": ""} for milestone in sorted(milestones, key=itemgetter(0)): milestonesForProject[project[1]][milestone[0]] = milestone[0] smp_milestonesForProject = { 'smp_milestonesForProject': milestonesForProject } smp_initialProjectMilestone = { 'smp_initialProjectMilestone': initialProjectMilestone } add_script_data(req, smp_initialProjectMilestone) add_script_data(req, smp_milestonesForProject)
def post_process_request(self, req, template, data, content_type): """Do any post-processing the request might need; typically adding values to the template `data` dictionary, or changing template or mime type. `data` may be update in place. Always returns a tuple of (template, data, content_type), even if unchanged. Note that `template`, `data`, `content_type` will be `None` if: - called when processing an error page - the default request handler did not return any result (Since 0.11) """ if template == 'ticket.html': add_stylesheet(req, '%s/css/autocomplete.css' % self.prefix) add_script(req, '%s/js/autocomplete.js' % self.prefix) if req.path_info.rstrip() == '/newticket': add_script_data(req, {'KEYWORDS_AC_PATH': 'ac-keywords'}) else: add_script_data(req, {'KEYWORDS_AC_PATH': '../ac-keywords'}) add_script(req, '%s/js/autocomplete_ticket_keywords.js' % self.prefix) return (template, data, content_type)
def _make_graph(self, req, repos, info): # Generate graph data graph = {} threads, vertices, columns = \ make_log_graph(repos, (item['rev'] for item in info)) graph.update(threads=threads, vertices=vertices, columns=columns, colors=self.graph_colors, line_width=0.04, dot_radius=0.1) add_script(req, 'revisiongraph/js/excanvas.js') add_script(req, 'revisiongraph/js/log_graph.js') add_script_data(req, {'graph': graph}) script = Markup("//<![CDATA[") + """ jQuery(document).ready(function($) { $('th.trac-graph, td.trac-graph').show(); var canvas = $('""" + Markup("<canvas>") + """').css({width: '%dem', height: '%dem'}) .appendTo('td.trac-graph')[0]; canvas.width = $(canvas).width(); canvas.height = $(canvas).height(); if (typeof(G_vmlCanvasManager) != 'undefined') canvas = G_vmlCanvasManager.initElement(canvas); $.paintLogGraph(graph, canvas); }); """ % (graph['columns'] * 2, len(info) * 2) + Markup("//]]>") th = tag.th('Graph', class_='trac-graph') td = tag.td(class_='trac-graph', rowspan='%d' % len(info)) script_filter = Transformer('//head').append(tag.script(script, type="text/javascript")) table_filter = Transformer('//table[@class="listing chglist"]').attr('class', 'listing chglist trac-graph') th_filter = Transformer('//table/thead/tr/th[@class="diff"]').before(th) td_filter = Transformer('//table/tbody/tr[1]/td[@class="diff"]').before(td) return [script_filter, table_filter, th_filter, td_filter]
def post_process_request(self, req, template, data, content_type): if data and req.path_info == '/timeline' and \ 'TAGS_VIEW' in req.perm(Resource('tags')): def realm_handler(_, node, context): return query.match(node, [context.realm]) query_str = req.args.getfirst(self.key) if query_str is None and req.args.get('format') != 'rss': query_str = req.session.get('timeline.%s' % self.key) else: query_str = (query_str or '').strip() # Record tag query expression between visits. req.session['timeline.%s' % self.key] = query_str if data.get('events') and query_str: tag_system = TagSystem(self.env) try: query = Query(query_str, attribute_handlers={'realm': realm_handler}) except InvalidQuery as e: add_warning(req, _("Tag query syntax error: %s" % e)) else: all_realms = tag_system.get_taggable_realms(req.perm) query_realms = set() for m in REALM_RE.finditer(query.as_string()): query_realms.add(m.group(1)) # Don't care about resources from non-taggable realms. realms = not query_realms and all_realms or \ query_realms.intersection(all_realms) events = [] self.log.info("Filtering timeline events by tags '%s'", query_str) for event in data['events']: resource = resource_from_event(event) if resource and resource.realm in realms: # Shortcut view permission checks here. tags = tag_system.get_tags(None, resource) if query(tags, context=resource): events.append(event) # Overwrite with filtered list. data['events'] = events if query_str: # Add current value for next form rendering. data[self.key] = query_str elif self.key in req.session: del req.session[self.key] filter_lst = [] # xpath = '//form[@id="prefs"]/div[1]' xform = JTransformer('form#prefs > div:nth-of-type(1)') insert = builder(Markup('<br />'), tag_("matching tags "), builder.input(type='text', name=self.key, value=data.get(self.key))) filter_lst.append(xform.append(Markup(insert))) add_script_data(req, {'tags_filter': filter_lst}) add_script(req, 'tags/js/tags_jtransform.js') return template, data, content_type
def workflow_graph(self, req, name): res, scr_data, graph = create_graph_data(self, req, name) # add_script(req, 'multipleworkflow/js/excanvas.js', ie_if='IE') add_script(req, 'multipleworkflow/js/workflow_graph.js') add_script_data(req, scr_data) return res
def post_process_request(self, req, template, data, content_type): add_script(req, 'wikicomments/wikicomments.js') add_script_data( req, { '_wikicomments_author': req.authname, '_wikicomments_base': "%s/chrome/wikicomments" % req.base_path }) return template, data, content_type
def filter_stream(self, req, method, filename, stream, data): if filename in [ 'ticket.html', # /ticket/{\d} or /newticket ]: add_script(req, "contextchrome/js/ticketvalidatordecolator.js") status = 'ticket' in data and data['ticket'].values['status'] or 'sentinel' add_script_data(req, {"contextchrome_tracstatus": status}) return stream
def post_process_request(self, req, template, data, content_type): if not req or not template or not isinstance(data, dict): return template, data, content_type model = None resource = None attachments = None if template in ('wiki_view.html', 'wiki_edit.html'): model = data.get('page') elif template == 'ticket.html': model = data.get('ticket') elif template in ('milestone_view.html', 'milestone_edit.html'): model = data.get('milestone') elif template == 'attachment.html': attachments = data.get('attachments') if attachments: resource = attachments['parent'] if not resource and model and model.exists: resource = model.resource if not resource: return template, data, content_type if not attachments: attachments = data.get('attachments') if not attachments and model and resource: context = web_context(req, resource) attachments = AttachmentModule(self.env).attachment_data(context) data['attachments'] = attachments if template in ('wiki_edit.html', 'milestone_edit.html'): self._add_overlayview(req) add_stylesheet(req, 'tracdragdrop/tracdragdrop.css') if hasattr(req, 'locale'): locale = str(req.locale) if locale in self.messages_files: add_script(req, 'tracdragdrop/messages/%s.js' % locale) add_script(req, 'common/js/folding.js') add_script(req, 'tracdragdrop/tracdragdrop.js') script_data = { '_tracdragdrop': { 'base_url': req.href().rstrip('/') + '/', 'new_url': req.href('tracdragdrop', 'new', resource.realm, resource.id), 'can_create': attachments.get('can_create') or False, 'max_size': AttachmentModule(self.env).max_size, }, 'form_token': req.form_token, } if add_script_data: add_script_data(req, script_data) else: setattr(req, '_tracdragdrop_data', script_data) return template, data, content_type
def filter_stream(self, req, method, filename, stream, data): self.log.debug("ckintegration: template %s" % (filename)) # Act only when enabled, and editor_source defined, and current template has wiki-textareas if self.editor_source and self._check_editor_type(filename): # Some javascript global variable to add to the response to assist to tracwiki plugin add_script_data( req, { "ck_editor_type": self.editor_type, "ck_code_styles": self.get_styles_list(), "trac_base_url": req.href.base, "ck_tracwiki_path": req.href.chrome("ckintegration"), "ck_resource_realm": "wiki", "ck_resource_id": "", "form_token": req.form_token, }, ) # Load the needed scripts (CKEditor itself, and the tracwiki plugin add_script(req, self.editor_source) add_script(req, "ckintegration/tracwiki.js") add_script(req, "ckintegration/pastecode.js") # Inject a script that adds the tracwiki plugin as an external plugin to CKEditor # @todo: Perform init with a dedicated loader script # @todo: Use the init to modify the CKEditor toolbar ck_plugin_init = '<script type="text/javascript">CKEDITOR.plugins.addExternal("tracwiki", ck_tracwiki_path, "tracwiki.js");\n' ck_plugin_init += 'CKEDITOR.plugins.addExternal("pastecode", ck_tracwiki_path, "pastecode.js");</script>' stream |= Transformer(".//body").prepend(HTML(ck_plugin_init)) # add_script(req, 'ckintegration/ckloader.js') # Replace all relevant textarea fields in the template with CKEditor instances for field_name in self.template_fields[lower(filename)]: self.log.debug('Replacing textarea "%s" with CKEditor instance' % (field_name)) add_editor = """<script type="text/javascript"> CKEDITOR.replace("%s", { extraPlugins : "tracwiki,pastecode" }); </script>""" % ( field_name ) # self.log.debug ("add_editor is %s" % add_editor) stream |= Transformer('.//textarea[@name="%s"]' % (field_name)).after(HTML(add_editor)) # Also replace custom textarea fields in the ticket template that have wiki format if "ticket.html" == lower(filename) and "fields" in data: for f in data["fields"]: if ( f["skip"] or not lower(f["type"]) == "textarea" or not f.has_key("format") or not "wiki" == lower(f["format"]) ): continue field_name = "field_%s" % f["name"] self.log.debug('Replacing textarea "%s" with CKEditor instance' % (field_name)) add_editor = """<script type="text/javascript"> CKEDITOR.replace("%s", { extraPlugins : "tracwiki,pastecode" }); </script>""" % ( field_name ) stream |= Transformer('.//textarea[@name="%s"]' % (field_name)).after(HTML(add_editor)) return stream
def post_process_request(self, req, template, data, content_type): """ Add global javascript data on post-processing phase """ # When processing template, add global javascript json into scripts if template: add_script_data(req, {'multiproject': self._get_published_data(req)}) return template, data, content_type
def test_add_script_data(self): req = MockRequest(self.env) add_script_data(req, {'var1': 1, 'var2': 'Testing'}) add_script_data(req, var2='More testing', var3=3) self.assertEqual({ 'var1': 1, 'var2': 'More testing', 'var3': 3 }, req.chrome['script_data'])
def post_process_request(self, req, template, data, metadata): if template in ('ticket.html', 'ticket_preview.html'): ticket = data.get('ticket') if (ticket and ticket.exists and 'TICKET_ADMIN' in req.perm(ticket.resource)): add_script(req, 'ticketopt/ticketdeleter.js') add_script_data( req, ui={'use_symbols': req.session.get('ui.use_symbols')}) return template, data, metadata
def test_add_script_data(self): req = Request(href=Href('/trac.cgi')) add_script_data(req, {'var1': 1, 'var2': 'Testing'}) add_script_data(req, var2='More testing', var3=3) self.assertEqual({ 'var1': 1, 'var2': 'More testing', 'var3': 3 }, req.chrome['script_data'])
def post_process_request(self, req, template, data, content_type): if template == 'ticket.html': fields = data.get('fields') filtered_fields = [] append_fields = [] remove_fields = [] groups = [] group_order = [] options = self.config.options('group-ticket-fields') for option in self.config.options('group-ticket-fields'): if option[0] == 'group_order': group_order = self.config.getlist('group-ticket-fields', 'group_order') elif option[0].find('.') == -1: group = {'name': option[0], 'label': option[1]} if self.config.has_option('group-ticket-fields', '%s.fields' % option[0]): group['fields'] = self.config.getlist( 'group-ticket-fields', '%s.fields' % option[0]) if self.config.has_option('group-ticket-fields', '%s.properties' % option[0]): group['properties'] = self.config.getlist( 'group-ticket-fields', '%s.properties' % option[0]) if self.config.has_option('group-ticket-fields', '%s.columns' % option[0]): group['columns'] = self.config.getint( 'group-ticket-fields', '%s.columns' % option[0]) groups.append(group) remove_fields.extend(group['fields']) for field in data.get('fields'): if field['name'] not in remove_fields: filtered_fields.append(field) else: append_fields.append(field) filtered_fields.extend(append_fields) groups_list = {'field_groups': groups} group_order = {'field_groups_order': group_order} data['fields'] = filtered_fields data['field_groups'] = groups add_script_data(req, groups_list) add_script_data(req, group_order) add_script(req, 'groupticketfields/group_ticket_fields.js') add_stylesheet(req, 'groupticketfields/css/ticket.css') return template, data, content_type
def render_admin_panel(self, req, category, page, path_info): data = { 'id': req.args.get('id', ''), 'name': req.args.get('name', ''), 'description': req.args.get('description', ''), 'enabled': req.args.get('enabled', '0') == '1', 'field_name': req.args.get('field_name', ''), 'field_value': req.args.get('field_value', ''), 'template': req.args.get('template', ''), 'fields': self.get_ticket_fields(), } self.log.debug( 'request to the admin page of ticket_template. ' 'category: %s, page: %s, path_info: %s', category, page, path_info) if req.method == 'POST': tid = data['id'] if not tid: add_warning(req, _('ID is required.')) elif not re.match(r'^[\w\-]+$', tid): add_warning(req, _('ID contains invalid character(s).')) elif req.args.get('save') or req.args.get('update'): template_path = os.path.join(self.env.path, 'htdocs', 'ticket_templates', tid) with open(template_path, 'w') as fd: fd.write(data['template']) section = self.config['ticket-template'] section.set(tid, data['enabled'] and 'enabled' or 'disabled') section.set(tid + '.name', data['name']) section.set(tid + '.description', data['description']) section.set(tid + '.field_name', data['field_name']) section.set(tid + '.field_value', data['field_value']) section.set(tid + '.file', template_path) self.config.save() add_notice(req, _('Your changes have been saves.')) elif req.args.get('remove'): template_path = self.config.get('ticket-template', tid + '.file') if template_path and os.path.exists(template_path): os.remove(template_path) for i, suffix in ('', '.name', '.description', '.field_name', '.field_value', '.file'): self.config.remove('ticket-template', tid + suffix) self.config.save() for key in data.keys(): data[key] = '' add_notice(req, _('Your changes have been saves.')) data['base_url'] = self.env.base_url.rstrip('/') add_script_data( req, { 'chrome_site_base_url': self.env.abs_href('/chrome/site'), }) add_stylesheet(req, 'ticket_template/admin.css') add_stylesheet(req, 'common/css/wiki.css') Chrome(self.env).add_wiki_toolbars(req) return 'admin_ticket_template.html', data
def post_process_request(self, req, template, data, metadata): if template == 'ticket.html': ticket = data.get('ticket') if ticket and ticket.exists: add_script(req, 'ticketopt/ticketclone.js') add_script_data(req, newticket_href=req.href('newticket'), ui={'use_symbols': req.session.get('ui.use_symbols')}) return template, data, metadata
def post_process_request(self, req, template, data, content_type): if data is None: return template, data, content_type if req.path_info.startswith('/changeset') and \ data.get('changeset') is not False and \ 'CODEREVIEWER_MODIFY' in req.perm: changeset = data['changeset'] repos = changeset.repos reponame, rev = repos.reponame, repos.db_rev(changeset.rev) review = CodeReview(self.env, reponame, rev) tickets = req.args.getlist('tickets') if req.method == 'POST': status_changed = \ review.encode(req.args['status']) != review.status if review.save(req.authname, req.args['status'], req.args['summary']): self._update_tickets(changeset, review, status_changed) tickets = review.tickets req.redirect(req.href(req.path_info, tickets=tickets)) ctx = web_context(req) format_summary = functools.partial(format_to_html, self.env, ctx, escape_newlines=True) format_time = functools.partial(user_time, req, format_datetime) add_stylesheet(req, 'coderev/coderev.css') add_script(req, 'coderev/coderev.js') add_script_data( req, { 'review': { 'status': review.status, 'encoded_status': review.encode(review.status), 'summaries': [ dict([ ('html_summary', format_summary(r['summary'])), ('pretty_when', format_time(r['when'])), ('pretty_timedelta', pretty_timedelta( r['when'])), ('reviewer', r['reviewer']), ('status', r['status']) ]) for r in CodeReview.select(self.env, reponame, rev) ], }, 'tickets': tickets, 'statuses': self.statuses, 'form_token': req.form_token, }) req.send_header('Cache-Control', 'no-cache') elif req.path_info.startswith('/ticket/'): add_stylesheet(req, 'coderev/coderev.css') return template, data, content_type
def expand_macro(self, formatter, name, text, args): if not text: raw_actions = self.config.options('ticket-workflow') else: if args is None: text = '\n'.join([line.lstrip() for line in text.split(';')]) if '[ticket-workflow]' not in text: text = '[ticket-workflow]\n' + text parser = RawConfigParser() try: parser.readfp(StringIO(text)) except ParsingError as e: return system_message(_("Error parsing workflow."), unicode(e)) raw_actions = list(parser.items('ticket-workflow')) actions = parse_workflow_config(raw_actions) states = list( set([ state for action in actions.itervalues() for state in action['oldstates'] ] + [action['newstate'] for action in actions.itervalues()])) action_labels = [attrs['label'] for attrs in actions.values()] action_names = actions.keys() edges = [] for name, action in actions.items(): new_index = states.index(action['newstate']) name_index = action_names.index(name) for old_state in action['oldstates']: old_index = states.index(old_state) edges.append((old_index, new_index, name_index)) args = args or {} width = args.get('width', 800) height = args.get('height', 600) graph = { 'nodes': states, 'actions': action_labels, 'edges': edges, 'width': width, 'height': height } graph_id = '%012x' % id(graph) req = formatter.req add_script(req, 'common/js/excanvas.js', ie_if='IE') add_script(req, 'common/js/workflow_graph.js') add_script_data(req, {'graph_%s' % graph_id: graph}) return tag( tag.div('', class_='trac-workflow-graph trac-noscript', id='trac-workflow-graph-%s' % graph_id, style="display:inline-block;width:%spx;height:%spx" % (width, height)), tag.noscript( tag.div(_("Enable JavaScript to display the workflow graph."), class_='system-message')))
def add_autocomplete_script(field, help_href=None): match_from_start = '' if self.match_contains_opt else '"^" +' add_script_data(req, tags={ 'autocomplete_field': field, 'keywords': keywords, 'match_from_start': match_from_start, 'separator': self.separator, 'help_href': help_href, 'help_new_window': self.help_new_window_opt, }) add_script(req, 'tags/js/autocomplete_tags.js')
def post_process_request(self, req, template, data, content_type): # remove script (jquery aggiornato caricato via fanstatic) del_script(req, 'common/js/jquery.js') # fanstatic dashboard.need() add_script(req, 'por/por.js') field_descriptions = dict([(field['name'], field['descriptions']) \ for field in TicketSystem(self.env).get_custom_fields() \ if field.get('descriptions')]) add_script_data(req, {'fielddescriptions': field_descriptions}) return template, data, content_type
def post_process_request(self, req, template, data, content_type): if template in ('timeline.html', 'wiki_view.html', 'ticket.html', 'milestone_view.html', 'attachment.html'): add_stylesheet(req, 'common/css/code.css') add_stylesheet(req, 'overlayview/base.css') add_script(req, 'common/js/folding.js') add_script(req, 'overlayview/jquery.colorbox.js') add_script(req, 'overlayview/base.js') script_data = {} script_data['baseurl'] = req.href().rstrip('/') + '/' add_script_data(req, {'overlayview': script_data}) return template, data, content_type
def post_process_request(self, req, template, data, content_type): if data and (not self.has_pretty_dateinfo or data.get('dateinfo')): add_script(req, 'tractimedeltaupdator/main.js') if self.has_pretty_dateinfo: dateinfo = req.session.get( 'dateinfo', Chrome(self.env).default_dateinfo_format) script_data = self._get_script_data(req, data, dateinfo) self._set_dateinfo_funcs(req, data, dateinfo) else: script_data = self._get_script_data(req, data, 'relative') add_script_data(req, {'tractimedeltaupdator': script_data}) return template, data, content_type
def post_process_request(self, req, template, data, content_type): if template: script_data = {'url': req.href('wikiautocomplete')} context = data.get('context') if context and context.resource: script_data['realm'] = context.resource.realm script_data['id'] = context.resource.id add_script_data(req, {'wikiautocomplete': script_data}) add_script(req, 'wikiautocomplete/js/jquery.textcomplete.min.js') add_script(req, 'wikiautocomplete/js/wikiautocomplete.js') add_stylesheet(req, 'wikiautocomplete/css/jquery.textcomplete.css') return template, data, content_type
def post_process_request(self, req, template, data, content_type): if req.path_info.startswith('/browser'): # see if the user has seen the tortoise svn dialog before # we use this data in the javascript to tell if we should # show a dialog which asks the user if they have TSVN installed if 'tortoise_svn_message' in req.session: add_script_data(req, {'tortoise_svn_message': True}) else: add_script_data(req, {'tortoise_svn_message': False}) add_script(req, 'contextmenu/js/tortoise-svn-message.js') return template, data, content_type
def add_template_data(self, req, data, tickets): data['batch_modify'] = True data['query_href'] = req.session['query_href'] or req.href.query() data['action_controls'] = self._get_action_controls(req, tickets) batch_list_modes = [ {'name': _("add"), 'value': "+"}, {'name': _("remove"), 'value': "-"}, {'name': _("add / remove"), 'value': "+-"}, {'name': _("set to"), 'value': "="}, ] add_script_data(req, batch_list_modes=batch_list_modes, batch_list_properties=self._get_list_fields())
def post_process_request(self, req, template, data, content_type): if (req.path_info.startswith('/wiki') or req.path_info.startswith('/ticket') or req.path_info.startswith('/newticket')): if req.method == 'GET' or req.method == 'POST': self.env.log.info('Injecting wikiautocomplete javascript') add_script_data(req, { 'wikiautocomplete_url': req.href('wikiautocomplete'), }) add_script(req, 'wikiautocomplete/js/jquery.textcomplete.min.js') add_script(req, 'wikiautocomplete/js/wikiautocomplete.js') add_stylesheet(req, 'wikiautocomplete/css/jquery.textcomplete.css') return (template, data, content_type)
def post_process_request(self, req, template, data, content_type): if req.perm.has_permission('QUIET_MODE') and \ (req.path_info.startswith('/ticket') or req.path_info.startswith('/newticket') or req.path_info.startswith('/query') or req.path_info.startswith('/report')): href = req.href(MODE, 'toggle') a = tag.a(_(self._get_label(req)), href=href, id=MODE) add_ctxtnav(req, a) add_script(req, 'quiet/quiet.js') add_stylesheet(req, 'quiet/quiet.css') add_script_data(req, {'quiet': {'toggle': MODE, 'listen': LISTEN}}) return template, data, content_type
def post_process_request(self, req, template, origData, content_type): if req.path_info.startswith('/newticket'): mode = 'new' elif req.path_info.startswith('/ticket/'): mode = 'view' else: return template, origData, content_type fieldData = {} fieldData['condfields'] = {} all_fields = [] standard_fields = set() for f in TicketSystem(self.env).get_ticket_fields(): all_fields.append(f['name']) if not f.get('custom'): standard_fields.add(f['name']) if 'owner' in all_fields: curr_idx = all_fields.index('owner') if 'cc' in all_fields: insert_idx = all_fields.index('cc') else: insert_idx = len(all_fields) if curr_idx < insert_idx: all_fields.insert(insert_idx, all_fields[curr_idx]) del all_fields[curr_idx] for t in self.types: fieldData['condfields'][t] = self.get_fields(t, all_fields, standard_fields) # fields = set(getattr(self, t+'_fields')) # if self.include_std: # fields.update(standard_fields) # fields.update(self.forced_fields) # fieldData['condfields'][t] = dict([ # (f, f in fields) for f in all_fields # ]) self.log.debug(all_fields) self.log.info(standard_fields) fieldData['mode'] = mode fieldData['all_fields'] = list(all_fields) fieldData['ok_view_fields'] = sorted(set(all_fields) - self.forced_fields, key=lambda x: all_fields.index(x)) fieldData['ok_new_fields'] = sorted((set(all_fields) - self.forced_fields) - set(['owner']), key=lambda x: all_fields.index(x)) add_script_data(req, fieldData) add_script(req, '/condfields.js') return template, origData, content_type
def post_process_request(self, req, template, data, content_type): if template == 'ticket.html': fields = data.get('fields') filtered_fields = [] append_fields = [] remove_fields = [] groups = [] group_order = [] options = self.config.options('group-ticket-fields') for option in self.config.options('group-ticket-fields'): if option[0] == 'group_order': group_order = self.config.getlist('group-ticket-fields', 'group_order') elif option[0].find('.') == -1: group = { 'name' : option[0], 'label': option[1] } if self.config.has_option('group-ticket-fields', '%s.fields' % option[0]): group['fields'] = self.config.getlist('group-ticket-fields', '%s.fields' % option[0]) if self.config.has_option('group-ticket-fields', '%s.properties' % option[0]): group['properties'] = self.config.getlist('group-ticket-fields', '%s.properties' % option[0]) if self.config.has_option('group-ticket-fields', '%s.columns' % option[0]): group['columns'] = self.config.getint('group-ticket-fields', '%s.columns' % option[0]) groups.append(group) remove_fields.extend(group['fields']) for field in data.get('fields'): if field['name'] not in remove_fields: filtered_fields.append(field) else: append_fields.append(field) filtered_fields.extend(append_fields) groups_list = { 'field_groups': groups } group_order = { 'field_groups_order': group_order } data['fields'] = filtered_fields data['field_groups'] = groups add_script_data(req, groups_list) add_script_data(req, group_order) add_script(req, 'groupticketfields/group_ticket_fields.js') add_stylesheet(req, 'groupticketfields/css/ticket.css') return template, data, content_type
def filter_stream(self, req, method, filename, stream, data): if req.path_info.startswith('/ticket'): button = tag.div(tag.input(type="submit", title=_("Translate to %s") % req.locale.get_display_name(), value=_("Translate"), forward=_("Translate"), backward=_("Untranslate"), working=_("Working"), name="translate", class_="translate")) button(class_="inlinebuttons") script = tag.script(''); script(src = 'https://www.google.com/jsapi?key='+self.googleApiKey) script(type = 'text/javascript') stream |= Transformer('//head').prepend(script) stream |= Transformer('//div[@id="content"]/div[@id="ticket"]/div[@class="description"]/h3').after(button) stream |= Transformer('//div[@id="content"]/div/div[@id="changelog"]/div[@class="change"]/h3').after(button) add_stylesheet(req, 'translate/translate.css') add_script_data(req, {'googleApiKey': self.googleApiKey}) add_script_data(req, {'sessionLanguage': req.locale.language}) add_script(req, 'translate/translate.js') return stream
def post_process_request(self, req, template, data, content_type): if hasattr(req, '_tracdeveloper_hdlr'): add_script(req, 'developer/js/log.js') first_time = 0 if req._tracdeveloper_hdlr.buf: first_time = req._tracdeveloper_hdlr.buf[0].created add_script_data(req, log_data=[(int((r.created - first_time) * 1000), r.module, r.levelname, r.getMessage()) for r in req._tracdeveloper_hdlr.buf]) req._tracdeveloper_hdlr.formatter = None del req._tracdeveloper_hdlr.buf[:] self.log.removeHandler(req._tracdeveloper_hdlr) del req._tracdeveloper_hdlr return template, data, content_type
def _enable_treesearch_for_page(self, req, stream, fields): project_name = req.environ.get('SCRIPT_NAME') add_script(req, 'treesearch/js/treesearch.js') add_stylesheet(req, 'treesearch/css/treesearch.css') add_script_data(req,(('selector',','.join(fields)),('params',{'SERVER_URL': project_name + '/diff'}))) stream = stream | Transformer('head').append(tag.script(''' jQuery(document).ready(function() { jQuery(selector).each(function() { $(this).addClass('treesearch'); $(this).tree(params); }); });''')) return stream
def expand_macro(self, formatter, name, text, args): if not text: raw_actions = self.config.options('ticket-workflow') else: if args is None: text = '\n'.join([line.lstrip() for line in text.split(';')]) if '[ticket-workflow]' not in text: text = '[ticket-workflow]\n' + text parser = RawConfigParser() try: parser.readfp(StringIO(text)) except ParsingError as e: return system_message(_("Error parsing workflow."), unicode(e)) raw_actions = list(parser.items('ticket-workflow')) actions = parse_workflow_config(raw_actions) states = list(set( [state for action in actions.itervalues() for state in action['oldstates']] + [action['newstate'] for action in actions.itervalues()])) action_labels = [attrs['label'] for attrs in actions.values()] action_names = actions.keys() edges = [] for name, action in actions.items(): new_index = states.index(action['newstate']) name_index = action_names.index(name) for old_state in action['oldstates']: old_index = states.index(old_state) edges.append((old_index, new_index, name_index)) args = args or {} width = args.get('width', 800) height = args.get('height', 600) graph = {'nodes': states, 'actions': action_labels, 'edges': edges, 'width': width, 'height': height} graph_id = '%012x' % id(graph) req = formatter.req add_script(req, 'common/js/excanvas.js', ie_if='IE') add_script(req, 'common/js/workflow_graph.js') add_script_data(req, {'graph_%s' % graph_id: graph}) return tag( tag.div('', class_='trac-workflow-graph trac-noscript', id='trac-workflow-graph-%s' % graph_id, style="display:inline-block;width:%spx;height:%spx" % (width, height)), tag.noscript( tag.div(_("Enable JavaScript to display the workflow graph."), class_='system-message')))
def filter_stream(self, req, method, filename, stream, data): if filename == 'ticket.html': add_stylesheet(req, "tasklist/jquery.modal.css") add_script(req, "tasklist/jquery.modal.min.js") add_stylesheet(req, "tasklist/tasklist-ticket.css") add_script(req, "tasklist/tasklist-ticket.js") add_script_data(req, {"ToDoList": { "ticket": { data['ticket'].id: { "tasklists": [ tasklist.to_json() for tasklist in TaskList.containing_ticket(self.env, data['ticket'].id) ] }} }}) return stream
def filter_stream(self, req, method, filename, stream, data): self.log.debug("ckintegration: template %s" % (filename)) # Act only when enabled, and editor_source defined, and current template has wiki-textareas if self.editor_source and self._check_editor_type(filename): # Some javascript global variable to add to the response to assist to tracwiki plugin add_script_data(req, { 'ck_editor_type': self.editor_type, 'ck_code_styles': self.get_styles_list(), 'trac_base_url': req.href.base, 'ck_tracwiki_path': req.href.chrome('ckintegration'), 'ck_resource_realm': 'wiki', 'ck_resource_id': '', 'form_token': req.form_token, }) # Load the needed scripts (CKEditor itself, and the tracwiki plugin add_script(req, self.editor_source) add_script(req, 'ckintegration/tracwiki.js') add_script(req, 'ckintegration/pastecode.js') # Inject a script that adds the tracwiki plugin as an external plugin to CKEditor # @todo: Perform init with a dedicated loader script # @todo: Use the init to modify the CKEditor toolbar ck_plugin_init = '<script type="text/javascript">CKEDITOR.plugins.addExternal("tracwiki", ck_tracwiki_path, "tracwiki.js");\n' ck_plugin_init += 'CKEDITOR.plugins.addExternal("pastecode", ck_tracwiki_path, "pastecode.js");</script>' stream |= Transformer('.//body').prepend(HTML(ck_plugin_init)) #add_script(req, 'ckintegration/ckloader.js') # Replace all relevant textarea fields in the template with CKEditor instances for field_name in self.template_fields[lower(filename)]: self.log.debug('Replacing textarea "%s" with CKEditor instance' % (field_name)) add_editor = '''<script type="text/javascript"> CKEDITOR.replace("%s", { extraPlugins : "tracwiki,pastecode" }); </script>''' % (field_name) #self.log.debug ("add_editor is %s" % add_editor) stream |= Transformer('.//textarea[@name="%s"]' % (field_name)).after(HTML(add_editor)) # Also replace custom textarea fields in the ticket template that have wiki format if 'ticket.html' == lower(filename) and 'fields' in data: for f in data['fields']: if f['skip'] or not lower(f['type']) == 'textarea' or \ not f.has_key('format') or not 'wiki' == lower(f['format']): continue field_name = 'field_%s' % f['name'] self.log.debug('Replacing textarea "%s" with CKEditor instance' % (field_name)) add_editor = '''<script type="text/javascript"> CKEDITOR.replace("%s", { extraPlugins : "tracwiki,pastecode" }); </script>''' % (field_name) stream |= Transformer('.//textarea[@name="%s"]' % (field_name)).after(HTML(add_editor)) return stream
def post_process_request(self, req, template, data, content_type): if template == 'ticket.html': all_components = model.Component.select(self.env) component_children = {} for comp in all_components: comp_children = self._ChModel.get_direct_children(comp.name) if comp_children: component_children[comp.name] = comp_children component_children = {'component_children': component_children} add_script_data(req, component_children) add_stylesheet(req, 'componenthierarchy/css/component_hierarchy.css') add_script(req, 'componenthierarchy/create_component_hierarchy.js') return template, data, content_type
def filter_stream(self, req, method, filename, stream, data): if filename == "ticket.html" and data.get("ticket") and data["ticket"].id: add_stylesheet(req, "jquery.modal/jquery.modal.css") add_script(req, "jquery.modal/jquery.modal.min.js") add_stylesheet(req, "workflow_actionbuttons/actionbuttons.css") add_script(req, "workflow_actionbuttons/actionbuttons.js") add_stylesheet(req, "fontawesome/css/font-awesome.css") manager = WorkflowManager(self.env) actions = manager.allowed_actions(None, req, data["ticket"]) buttons = [] for action in actions: buttons.append(manager.render_action_button(req, data["ticket"], action)) add_script_data(req, {"WorkflowActionButtonsPlugin": {"action_buttons": buttons}}) return stream
def filter_stream(self, req, method, filename, stream, data): self.log.debug("ckintegration: template %s" % (filename)) # Act only when enabled, and editor_source defined, and current template has wiki-textareas if 'none' != self.editor_type and self.editor_source and lower(filename) in self.template_fields: # Some javascript global variable to add to the response to assist to tracwiki plugin add_script_data(req, { 'ck_editor_type': self.editor_type, 'ck_render_url': req.href.ck_wiki_render(), 'ck_tracwiki_path': req.href.chrome('ckintegration'), 'ck_resource_realm': 'wiki', 'ck_resource_id': '', 'form_token': req.form_token, }) # Load the needed scripts (CKEditor itself, and the tracwiki plugin add_script(req, self.editor_source) add_script(req, 'ckintegration/tracwiki.js') # Inject a script that adds the tracwiki plugin as an external plugin to CKEditor # @todo: Perform init with a dedicated loader script # @todo: Use the init to modify the CKEditor toolbar ck_plugin_init = '<script type="text/javascript">CKEDITOR.plugins.addExternal("tracwiki", ck_tracwiki_path, "tracwiki.js");</script>' stream |= Transformer('.//body').prepend(HTML(ck_plugin_init)) #add_script(req, 'ckintegration/ckloader.js') # Replace all relevant textarea fields in the template with CKEditor instances for field_name in self.template_fields[lower(filename)]: self.log.info('Replacing textarea "%s" with CKEditor instance' % (field_name)) add_editor = '''<script type="text/javascript"> CKEDITOR.replace("%s", { extraPlugins : "tracwiki" }); </script>''' % (field_name) #self.log.debug ("add_editor is %s" % add_editor) stream |= Transformer('.//textarea[@name="%s"]' % (field_name)).after(HTML(add_editor)) # Also replace custom textarea fields in the ticket template that have wiki format if 'ticket.html' == lower(filename) and 'fields' in data: for f in data['fields']: if f['skip'] or not lower(f['type']) == 'textarea' or \ not f.has_key('format') or not 'wiki' == lower(f['format']): continue field_name = 'field_%s' % f['name'] self.log.info('Replacing textarea "%s" with CKEditor instance' % (field_name)) add_editor = '''<script type="text/javascript"> CKEDITOR.replace("%s", { extraPlugins : "tracwiki" }); </script>''' % (field_name) stream |= Transformer('.//textarea[@name="%s"]' % (field_name)).after(HTML(add_editor)) return stream
def expand_macro(self, formatter, name, content): args, kw = parse_args(content) args = [arg.strip() for arg in args] stack_names = kw.get('stack', '').split('|') if not stack_names: raise TracError('Missing stack names') stacks = CardStack.select_by_names(self.env, stack_names) cards = Card.select_by_stacks(self.env, stack_names) labels = [label for label in kw.get('label', '').split('|') if label] labels = dict(zip(stack_names, labels + stack_names[len(labels):])) width = int(kw.get('width', 400)) req = formatter.req context = formatter.context board_data = { 'form_token': req.form_token, 'api_url': formatter.href('card'), 'cards_by_id': serialized_cards_by_id(cards, self.env, context), 'stacks_by_name': serialized_stacks_by_name(stacks, stack_names), 'auto_refresh': self.auto_refresh, 'auto_refresh_interval': self.auto_refresh_interval, } board_data_id = '%012x' % id(board_data) chrome = Chrome(self.env) add_stylesheet(req, 'cards/css/cards.css') chrome.add_jquery_ui(req) add_script_data(req, {'cards_%s' % board_data_id: board_data}) add_script(req, 'cards/js/cards.js') data = { 'board_data_id': board_data_id, 'stack_names': stack_names, 'labels': labels, 'width': width, } return chrome.render_template(req, 'cards_macro.html', data, 'text/html', True)