def filter_stream(self, req, method, filename, stream, data): if filename != 'query.html': return stream query_string = 'query:' + '&'.join(['%s=%s' % (key, '|'.join([cond for cond in values])) for constraint in data['query'].constraints for key, values in constraint.items()]) page_name = 'report_resource' in data and \ 'report:%s' % data['report_resource'].id or query_string if 'page_name' in req.args: page_name = req.args['page_name'] query_string += '&page_name=%s' % page_name page = WikiPage(self.env, page_name) if 'WIKI_MODIFY' not in req.perm(page.resource): return stream cols = [header['name'] for header in data['headers']] text = '= Snapshot of [%s the query]: =\n' % query_string text += '{{{#!QueryResults(group=%s) \n' % data['query'].group text += '||= href =||= %s\n' % ' =||= '.join(cols) for (group_name, tickets) in data['groups']: text += '|| group: %s\n' % group_name for ticket in tickets: text += '|| %s || %s\n' % (ticket['href'], ' || '.join([self.formatter(ticket[col]) for col in cols])) text += '}}}' div = tag.div(tag.input(value='Save as wiki:', type='submit'), tag.input(name='action', value='edit', type='hidden'), tag.input(name='text', value=text, type='hidden'), tag.input(name='page', value=page_name)) return stream | Transformer('//div[@id="content"]/div[@class="buttons"]') \ .append(tag.form(div, action=get_resource_url(self.env, Resource('wiki'), self.env.href)))
def _clone_form(self, req, ticket, data): fields = {} for f in data.get('fields', []): name = f['name'] if name == 'summary': fields['summary'] = _("%(summary)s (cloned)", summary=ticket['summary']) elif name == 'description': fields['description'] = \ _("Cloned from #%(id)s:\n----\n%(description)s", id=ticket.id, description=ticket['description']) else: fields[name] = ticket[name] return tag.form(tag.div(tag.input( type="submit", name="clone", value=captioned_button(req, '+#', _("Clone")), title=_("Create a copy of this ticket")), [ tag.input(type="hidden", name='field_' + n, value=v) for n, v in fields.iteritems() ], tag.input(type="hidden", name='preview', value=''), class_="inlinebuttons"), method="post", action=req.href.newticket())
def filter_stream(self, req, method, filename, stream, data): """ Returns changed stream for `prefs_general.html` template with notification opt-out preference option. `req` is the current request object, `method` is the Genshi render method (xml, xhtml or text), `filename` is the filename of the template to be rendered, `stream` is the event stream and `data` is the data for the current template. """ if filename == 'prefs_general.html' and req.authname != 'anonymous': stream |= Transformer('.//table').append( tag.tr( tag.th( tag.label('Ticket notifications opt-out:', **{'for': 'ticket-notification-optout'}), ), tag.td( tag.input(type="hidden", name="ticket-notification-optout_cb", value=""), tag.input(type="checkbox", id="ticket-notification-optout", name="ticket-notification-optout", checked=req.session.get('ticket-notification-optout') or None), ), **{'class': 'field'} ), ) return stream
class Aggregator(Component): implements(ITemplateStreamFilter, IRequestFilter) # IRequestFilter methods def pre_process_request(self, req, handler): return handler def post_process_request(self, req, template, data, content_type): if not 'aggregate' in req.args \ or not data \ or not 'ticket' in data \ or not 'changes' in data: return template, data, content_type ticket = data['ticket'] if not 'TICKET_MODIFY' in req.perm(ticket.resource): return template, data, content_type cnum = int(req.args['aggregate']) changes = iter(data['changes']) for change in changes: if 'cnum' in change and change['cnum'] == cnum: self._aggregate(ticket.id, change, changes.next()) req.redirect(req.href.ticket(ticket.id) + '#comment:%d' % cnum) return template, data, content_type # ITemplateStreamFilter methods def filter_stream(self, req, method, filename, stream, data): if filename != 'ticket.html': return stream if 'cnum_edit' in req.args: # comment editing return stream ticket = data.get('ticket') if not 'TICKET_MODIFY' in req.perm(ticket.resource): return stream transformer = Transformer() if data.has_key('changes'): changes = data['changes'] # 前のコメントと, field の重複がなく, authorが一致していて, 時間が離れていない場合, Aggregateボタンを出す aggregatable = set() last = {'date': datetime.now(), 'fields': {}, 'author': None} for change in changes: try: delta = change['date'].replace(tzinfo=None) - last['date'].replace(tzinfo=None) if last['author'] == change['author'] \ and len(set(last['fields'].keys()) & set(change['fields'].keys())) == 0 \ and delta.days == 0 and delta.seconds <= 3600: aggregatable.add(last['cnum']) except KeyError, e: pass except AttributeError, e: pass last = change self.log.debug('aggregatable: %s' % aggregatable) # Build transformer for cnum in aggregatable: transformer = transformer \ .select('//div[@id="changelog"]/div[@id="trac-change-%s"]/h3[@class="change"])' % cnum) \ .after(tag.form(tag.input(type='hidden', name='aggregate', value=cnum), tag.div(tag.input(type='submit', value='Aggregate', title="to next"), class_='inlinebuttons'))) \ .end()
def filter_stream(self, req, method, filename, stream, data): if filename != 'report_view.html': return stream page_name = 'report:%s' % data['context'].resource.id page_label = data['title'] page = WikiPage(self.env, page_name) if 'WIKI_MODIFY' not in req.perm(page.resource): return stream text = '= Snapshot of [%s %s]: =\n' % (page_name, page_label) text += '{{{#!QueryResults\n' cols = [header['col'] for header in data.get('header_groups', [[]])[0] if not header['hidden']] cols_work = [t for t in cols] # copy if 'ticket' in cols_work: cols_work[cols_work.index('ticket')] = 'id' # replace 'ticket' to 'id' text += '||= href =||= %s\n' % ' =||= '.join(cols_work) for groupindex, row_group in data.get('row_groups', []): text += '|| group: %s\n' % groupindex for row in row_group: row = row['cell_groups'][0] ticket = {} for value in row: ticket[value['header']['col']] = value['value'] ticket['href'] = get_resource_url(self.env, Resource('ticket', ticket.get('ticket', 0)), self.env.href) text += '|| %s || %s\n' % (ticket['href'], ' || '.join([self.formatter(col, ticket[col]) for col in cols])) text += '}}}' div = tag.div(tag.input(value='Save as wiki:', type='submit'), tag.input(name='action', value='edit', type='hidden'), tag.input(name='text', value=text, type='hidden'), tag.input(name='page', value=page_name)) return stream | Transformer('//div[@id="content"]/div[@class="buttons"]') \ .append(tag.form(div, action=get_resource_url(self.env, Resource('wiki'), self.env.href)))
def filter_stream(self, req, method, filename, stream, data): # Get path if filename == 'browser.html': # self.req_han = SupoSERequestHandler() path = data.get('created_path') repo = self.env.get_repository(authname=req.authname) node = get_existing_node(req, repo, path, repo.youngest_rev) file = "" if node: if node.isfile: file = posixpath.basename(path) path = posixpath.dirname(path) #raise Exception( path ) filter = Transformer('//div[@id="jumprev"]') search = tag.div( tag.form( # tag.div( "Repository search" ), tag.input( type = "text", id = "suquery", name = "q", size = 13, value = ""), tag.input( type = "hidden", id = "suquerypath", name = "p", size = 13, value = path), tag.input( type = "hidden", id = "suqueryfile", name = "f", size = 13, value = file), tag.input( type = "submit", value="Repo Search"), action=req.href.reposearch(), method="get", id="reposearch" ) ) return stream | filter.after(search) return stream
def filter_stream(self, req, method, filename, stream, data): if filename != 'query.html': return stream query_string = 'query:' + '&'.join([ '%s=%s' % (key, '|'.join([cond for cond in values])) for constraint in data['query'].constraints for key, values in constraint.items() ]) page_name = 'report_resource' in data and \ 'report:%s' % data['report_resource'].id or query_string if 'page_name' in req.args: page_name = req.args['page_name'] query_string += '&page_name=%s' % page_name page = WikiPage(self.env, page_name) if 'WIKI_MODIFY' not in req.perm(page.resource): return stream cols = [header['name'] for header in data['headers']] text = '= Snapshot of [%s the query]: =\n' % query_string text += '{{{#!QueryResults(group=%s) \n' % data['query'].group text += '||= href =||= %s\n' % ' =||= '.join(cols) for (group_name, tickets) in data['groups']: text += '|| group: %s\n' % group_name for ticket in tickets: text += '|| %s || %s\n' % (ticket['href'], ' || '.join( [self.formatter(ticket[col]) for col in cols])) text += '}}}' div = tag.div(tag.input(value='Save as wiki:', type='submit'), tag.input(name='action', value='edit', type='hidden'), tag.input(name='text', value=text, type='hidden'), tag.input(name='page', value=page_name)) return stream | Transformer('//div[@id="content"]/div[@class="buttons"]') \ .append(tag.form(div, action=get_resource_url(self.env, Resource('wiki'), self.env.href)))
def render_registration_fields(self, req, data): """Add a hidden text input field to the registration form, and a visible one with mandatory input as well, if token is configured. """ if self.reg_basic_token: # Preserve last input for editing on failure instead of typing # everything again. old_value = req.args.get('basic_token', '') # TRANSLATOR: Hint for visible bot trap registration input field. hint = tag.p(Markup( _("""Please type [%(token)s] as verification token, exactly replicating everything within the braces.""", token=tag.b(self.reg_basic_token))), class_='hint') insert = tag( tag.label( _("Parole:"), tag.input(type='text', name='basic_token', size=20, class_='textwidget', value=old_value)), hint) else: insert = None # TRANSLATOR: Registration form hint for hidden bot trap input field. insert = tag( insert, tag.input(type='hidden', name='sentinel', title=_("Better do not fill this field."))) return insert, data
def _clone_form(self, req, ticket, data): fields = {} for f in data.get("fields", []): name = f["name"] if name == "summary": fields["summary"] = _("%(summary)s (cloned)", summary=ticket["summary"]) elif name == "description": fields["description"] = _( "Cloned from #%(id)s:\n----\n%(description)s", id=ticket.id, description=ticket["description"] ) else: fields[name] = ticket[name] return tag.form( tag.div( tag.input( type="submit", name="clone", value=captioned_button(req, "+#", _("Clone")), title=_("Create a copy of this ticket"), ), [tag.input(type="hidden", name="field_" + n, value=v) for n, v in fields.iteritems()], tag.input(type="hidden", name="preview", value=""), class_="inlinebuttons", ), method="post", action=req.href.newticket(), )
def filter_stream(self, req, method, filename, stream, data): if req.get_header("X-Moz") == "prefetch": return stream if filename == "ticket.html": if not self.check_permissions(req): return stream chrome = Chrome(self.env) filter = Transformer('//fieldset[@id="properties"]') # add a hidden div to hold the ticket_fields input snippet = tag.div(style="display:none;") snippet = tag.input(type="hidden", id="field-ticket_fields", name="field_ticket_fields", value=','.join(data['ticket_fields'])) stream = stream | filter.after(snippet) if req.path_info != '/newticket': # insert the ticket field groups after the standard trac 'Change Properties' field group stream = stream | filter.after(chrome.render_template(req, 'ticket_fields_datatable.html', data, fragment=True)) elif filename == "admin_enums.html": if not self.check_permissions(req) or not req.args.get('path_info'): return stream for k,v in {'cat_id':'ticket', 'panel_id':'type'}.iteritems(): if k not in req.args or req.args.get(k) != v: return stream if 'ticket_fields' in data: chrome = Chrome(self.env) filter = Transformer('//div[@class="buttons"]') # add a hidden div to hold the ticket_fields input snippet = tag.div(style="display:none;") snippet = tag.input(type="hidden", id="field-ticket_fields", name="field_ticket_fields", value=','.join(data['ticket_fields'])) stream = stream | filter.before(snippet) stream = stream | filter.before(chrome.render_template(req, 'ticket_fields_datatable.html', data, fragment=True)) return stream
def filter_stream(self, req, method, filename, stream, data): # Add delete buttons to the ticket form ticket = data.get('ticket') if filename == 'ticket.html' and 'TICKET_ADMIN' in req.perm(ticket.resource): # Add Delete button to ticket description if data['ticket'].values['description']: # Reply button and associated elements are present filter = Transformer("//div[@class='description']//div[@class='inlinebuttons']") stream |= filter.append(tag.input(type='submit', name='delete', title="Delete this ticket", value='Delete')) else: # Reply button and associated elements not present filter = Transformer("//div[@class='description']/h3") stream |= filter.after( \ tag.form(tag.div(tag.input(type='submit', name='delete', title="Delete this ticket", value='Delete'), class_='inlinebuttons' ), name='addreply', method='get', action='#comment') ) # Add Delete buttons to ticket comments stream |= Transformer("//div[@id='changelog']//div[@class='inlinebuttons']") \ .append(tag.input(type='submit', name='delete', title="Delete this comment", value='Delete')) return stream
def render_registration_fields(self, req, data): """Add a hidden text input field to the registration form, and a visible one with mandatory input as well, if token is configured. """ if self.reg_basic_token: # Preserve last input for editing on failure instead of typing # everything again. old_value = req.args.get('basic_token', '') # TRANSLATOR: Hint for visible bot trap registration input field. hint = tag.p(Markup(_( """Apologies for the inconvenience, but please use the Sugarlabs Wiki, find the page referring to find the gold in the pot, and insert here the four words on the second line, or send mail to systems mailing list.""", token=tag.b(self.reg_basic_token))), class_='hint') insert = tag( tag.label(_("Parole:"), tag.input(type='text', name='basic_token', size=20, class_='textwidget', value=old_value)), hint ) else: insert = None # TRANSLATOR: Registration form hint for hidden bot trap input field. insert = tag(insert, tag.input(type='hidden', name='sentinel', title=_("Better do not fill this field.")) ) return insert, data
def render_registration_fields(self, req, data): """Add a hidden text input field to the registration form, and a visible one with mandatory input as well, if token is configured. """ if self.reg_basic_token: # Preserve last input for editing on failure instead of typing # everything again. old_value = req.args.get('basic_token', '') # TRANSLATOR: Hint for visible bot trap registration input field. hint = tag.p(Markup(_( """Please type [%(token)s] as verification token, exactly replicating everything within the braces.""", token=tag.b(self.reg_basic_token))), class_='hint') insert = tag( tag.label(_("Parole:"), tag.input(type='text', name='basic_token', size=20, class_='textwidget', value=old_value)), hint ) else: insert = None # TRANSLATOR: Registration form hint for hidden bot trap input field. insert = tag(insert, tag.input(type='hidden', name='sentinel', title=_("Better do not fill this field.")) ) return insert, data
def filter_stream(self, req, method, filename, stream, data): # check preconditions if filename != 'ticket.html': return stream transformer = Transformer() # build 'Hide these fields' Area hide_names = req.session.get('hidefieldchanges', []) hide_fields = [] for field in data['fields']: name = field['name'] checkbox = name in hide_names \ and tag.input(type='checkbox', checked=True, name=name) \ or tag.input(type='checkbox', name=name) hide_fields.append(tag.label(checkbox, field['label'])) hide_fields.append(tag.br) hide_fields.append(tag.input(name='submit', type='submit', value='Hide these fields')) transformer = transformer \ .select('//div[@id="changelog"]') \ .before(tag.form(tag.input(value='hide changes', id='hidechangesbutton', type='button', style_='float: right;'), tag.div(hide_fields, style='display: none', id='hidefields'), action='#', class_='inlinebuttons hidechanges')).end() # build 'show all changes' button # showallbutton = tag.input(value='show all', name='showall', class_='showallbutton', type='submit', style_='float: right;') # showallbutton = tag.form(showallbutton, action='#', method='get', class_='inlinebuttons hidechanges') # transformer = transformer.select('//div[@id="changelog"]').before(showallbutton).end() # build 'hide customfield' buttons hidebutton = tag.input(value='hide', name="hide", class_='hidebutton', style_='display: none', type='submit') hidebutton = tag.form(hidebutton, action='#', method='get', class_='inlinebuttons hidefieldchanges') transformer = transformer \ .select('//div[@id="changelog"]/div[@class="change"]/ul[@class="changes"]/li') \ .prepend(hidebutton).end() # return filtered stream return stream | transformer
def filter_stream(self, req, method, filename, stream, data): # Add delete buttons to the ticket form ticket = data.get("ticket") if filename == "ticket.html" and "TICKET_ADMIN" in req.perm(ticket.resource): # Add Delete button to ticket description if data["ticket"].values["description"]: # Reply button and associated elements are present filter = Transformer("//div[@class='description']//div[@class='inlinebuttons']") stream |= filter.append( tag.input(type="submit", name="delete", title="Delete this ticket", value="Delete") ) else: # Reply button and associated elements not present filter = Transformer("//div[@class='description']/h3") stream |= filter.after( tag.form( tag.div( tag.input(type="submit", name="delete", title="Delete this ticket", value="Delete"), class_="inlinebuttons", ), name="addreply", method="get", action="#comment", ) ) # Add Delete buttons to ticket comments stream |= Transformer("//div[@id='changelog']//div[@class='inlinebuttons']").append( tag.input(type="submit", name="delete", title="Delete this comment", value="Delete") ) return stream
def delete_ticket(): return tag.form( tag.div( tag.input(type='hidden', name='action', value='delete'), tag.input(type='submit', value=_('Delete'), title=_('Delete ticket')), class_='inlinebuttons'), action='#', method='get')
def _toggleBox(self, req, label, name, default): if self._session(req, name, default) == 'true': checkbox = tag.input(type='checkbox', name=name, value='true', checked='checked') else: checkbox = tag.input(type='checkbox', name=name, value='true') return checkbox + ' ' + tag.label(label, for_=name)
def delete_ticket(): return tag.form(tag.div(tag.input(type='hidden', name='action', value='delete'), tag.input(type='submit', value=_('Delete'), title=_('Delete ticket')), class_='inlinebuttons'), action='#', method='get')
def _toggleBox(self, req, label, name, default): if self._session(req, name, default) == 'true': checkbox= tag.input(type= 'checkbox', name= name, value='true', checked='checked') else: checkbox= tag.input(type= 'checkbox', name= name, value= 'true') return checkbox + ' ' + tag.label(label, for_= name)
def delete_ticket(): return tag.form( tag.div( tag.input(type='hidden', name='action', value='delete'), tag.input(type='submit', value=captioned_button(req, u'–', # 'EN DASH' _("Delete")), title=_('Delete ticket'), class_="trac-delete"), class_="inlinebuttons"), action='#', method='get')
def _clone_form(self, req, ticket, data): fields = self.ticket_cloner.build_clone_form(req, ticket, data) return tag.form( tag.div( tag.input(type="submit", name="clone", value=_("Clone"), title=_("Create a copy of this ticket")), [tag.input(type="hidden", name='field_' + n, value=v) for n, v in fields.iteritems()], tag.input(type="hidden", name='preview', value=''), class_="inlinebuttons"), method="post", action=req.href.newticket())
def _ccme_form(self, req, ticket, data): # pylint: disable=no-self-use return tag.form(tag.div(tag.input( type="submit", name="ccme", value=captioned_button(req, u'\u2709', _("Cc Me!")), title=_("Add/remove yourself to/from the Cc list")), tag.input(type="hidden", name='ticket', value=ticket.id), class_="inlinebuttons"), method="post", action=req.href('/ccme'))
def delete_comment(): for event in buffer: cnum = event[1][1].get('id')[12:] return tag.form( tag.div( tag.input(type='hidden', name='action', value='delete-comment'), tag.input(type='hidden', name='cnum', value=cnum), tag.input(type='submit', value=_('Delete'), title=_('Delete comment %(num)s', num=cnum)), class_='inlinebuttons'), action='#', method='get')
def _reminder_add_form(self, req): if 'TICKET_REMINDER_MODIFY' not in req.perm and 'TICKET_ADMIN' not in req.perm: return None return \ tag.form( tag.div( tag.input(type="hidden", name="action", value="addreminder"), tag.input(type="submit", value="Add reminder"), ), method="get", action="", id="addreminder", )
def _reminder_delete_form(self, req, reminder_id): if 'TICKET_REMINDER_MODIFY' not in req.perm and 'TICKET_ADMIN' not in req.perm: return None return \ tag.form( tag.div( tag.input(type="hidden", name="action", value="deletereminder"), tag.input(type="hidden", name="reminder", value=reminder_id), tag.input(type="submit", value="Delete"), class_="inlinebuttons", ), method="get", action="", )
def _process_edit(self, req, stream, method, tags): stage = 1 elm = tag.div([ tag.label('Tag under: (', tag.a('view all tags', href=req.href.tags()), ')', for_='tags'), tag.br(), tag.input(title='Comma separated list of tags', type='text', id='tags', size='30', name='tags', value=', '.join(tags)), ], class_='field') for kind, data, pos in stream: yield kind, data, pos if stage == 1 and \ kind is START and \ data[0].localname == 'input' and \ data[1].get('id') == 'comment': stage = 2 elif stage == 2 and \ kind is END and \ data.localname == 'div': for e in elm.generate(): yield e stage = None
def delete_comment(): for event in buffer: cnum, cdate = event[1][1].get('id')[12:].split('-', 1) return tag.form( tag.div( tag.input(type='hidden', name='action', value='delete-comment'), tag.input(type='hidden', name='cnum', value=cnum), tag.input(type='hidden', name='cdate', value=cdate), tag.input(type='submit', value=captioned_button(req, u'–', # 'EN DASH' _("Delete")), title=_('Delete comment %(num)s', num=cnum), class_="trac-delete"), class_="inlinebuttons"), action='#', method='get')
def _process_edit(self, req, stream, method, tags): stage = 1 elm = tag.div([tag.label('Tag under: (', tag.a('view all tags', href=req.href.tags()), ')', for_='tags'), tag.br(), tag.input(title='Comma separated list of tags', type='text', id='tags', size='30', name='tags', value=', '.join(tags) ), ], class_='field') for kind, data, pos in stream: yield kind, data, pos if stage == 1 and \ kind is START and \ data[0].localname == 'input' and \ data[1].get('id') == 'comment': stage = 2 elif stage == 2 and \ kind is END and \ data.localname == 'div': for e in elm.generate(): yield e stage = None
def render_registration_fields(self, req, data): """Add an email address text input field to the registration form.""" # Preserve last input for editing on failure instead of typing # everything again. old_value = req.args.get('email', '').strip() insert = tag.label(_("Email:"), tag.input(type='text', name='email', size=20, class_='textwidget', value=old_value) ) # Deferred import required to aviod circular import dependencies. from acct_mgr.web_ui import AccountModule reset_password = AccountModule(self.env).reset_password_enabled verify_account = is_enabled(self.env, EmailVerificationModule) and \ EmailVerificationModule(self.env).verify_email if verify_account: # TRANSLATOR: Registration form hints for a mandatory input field. hint = tag.p(_("""The email address is required for Trac to send you a verification token."""), class_='hint') if reset_password: hint = tag(hint, tag.p(_( """Entering your email address will also enable you to reset your password if you ever forget it."""), class_='hint') ) return tag(insert, hint), data elif reset_password: # TRANSLATOR: Registration form hint, if email input is optional. hint = tag.p(_("""Entering your email address will enable you to reset your password if you ever forget it."""), class_='hint') return dict(optional=tag(insert, hint)), data else: # Always return the email text input itself as optional field. return dict(optional=insert), data
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 render_ticket_action_control(self, req, ticket, action): config = self.parse_config() assert action in config control = [] hints = [] data = config[action] action_name = action # @@TODO: config'able label/name chrome = Chrome(self.env) from trac.ticket.web_ui import TicketModule prepared_fields = TicketModule(self.env)._prepare_fields(req, ticket) for field in data.get('fields', []): id = "action_%s_%s" % (action, field) operation = data.get('operations', {}).get(field, "change") assert operation in ["change", "unset"] if operation == "unset": hints.append("%s will be unset" % field) # @@TODO: i18n continue assert operation == "change" current_value = ticket._old.get(field, ticket[field]) or "" rendered_control = '' prepared_field = [pfield for pfield in prepared_fields if pfield['name'] == field] if len(prepared_field): prepared_field = prepared_field[0] # we can't use chrome.render_template here, or it will blow away # key scripts like jquery.js and trac.js in the eventual 'primary' template # that's rendered by process_request template = chrome.load_template("ticket_fields.html", method="xhtml") rendered_control = template.generate(ticket=ticket, field=prepared_field) if rendered_control: rendered_control = Markup(rendered_control) control.append(tag.label(field, rendered_control or tag.input( name=id, id=id, type='text', value=current_value))) current_status = ticket._old.get('status', ticket['status']) new_status = data['status'].get(current_status) or \ data['status']['*'] if new_status != '*': hints.append("Next status will be %s" % new_status) # @@TODO: i18n add_script(req, "workflow_ticketfields/workflow_ticketfields.js") return (action_name, tag.div(*[tag.div(element, style=("display: inline-block; " "margin-right: 1em")) for element in control], class_="workflow_ticket_fields", style="margin-left: 2em; display: none"), '. '.join(hints) + '.' if hints else '')
def get_stream(self, req, method, filename, stream, original_data): if 'linkinfo' in req.args: link_info = tag.input(name="linkinfo", value=req.args['linkinfo'], type="hidden") else: link_info = tag.comment('no link') return Transformer('//form[@id="propertyform"]').prepend(link_info)
def filter_stream(self, req, method, filename, stream, data): if req.path_info == '/timeline': insert = builder(Markup('<br />'), tag_("matching tags "), builder.input(type='text', name=self.key, value=data.get(self.key))) xpath = '//form[@id="prefs"]/div[1]' stream = stream | Transformer(xpath).append(insert) return stream
def delete_comment(): for event in buffer: cnum = event[1][1].get('id')[12:] return tag.form(tag.div(tag.input(type='hidden', name='action', value='delete-comment'), tag.input(type='hidden', name='cnum', value=cnum), tag.input(type='submit', value=_('Delete'), title=_( 'Delete comment %(num)s', num=cnum)), class_='inlinebuttons'), action='#', method='get')
def helper(field_stream): s = Stream(field_stream) value = s.select('@value').textOf() name = s.select('@name').textOf() for kind,data,pos in tag.span(value, id=("field-%s"%field)).generate(): yield kind,data,pos for kind,data,pos in tag.input(value=value, name=name, type="hidden").generate(): yield kind,data,pos
def filter_stream(self, req, method, filename, stream, data): if req.get_header("X-Moz") == "prefetch": return stream if filename == "ticket.html": if not self.check_permissions(req): return stream chrome = Chrome(self.env) filter = Transformer('//fieldset[@id="properties"]') # add a hidden div to hold the ticket_fields input snippet = tag.div(style="display:none;") snippet = tag.input(type="hidden", id="field-ticket_fields", name="field_ticket_fields", value=','.join(data['ticket_fields'])) stream = stream | filter.after(snippet) if req.path_info != '/newticket': # insert the ticket field groups after the standard trac 'Change Properties' field group stream = stream | filter.after( chrome.render_template(req, 'ticket_fields_datatable.html', data, fragment=True)) elif filename == "admin_enums.html": if not self.check_permissions(req) or not req.args.get( 'path_info'): return stream for k, v in {'cat_id': 'ticket', 'panel_id': 'type'}.iteritems(): if k not in req.args or req.args.get(k) != v: return stream if 'ticket_fields' in data: chrome = Chrome(self.env) filter = Transformer('//div[@class="buttons"]') # add a hidden div to hold the ticket_fields input snippet = tag.div(style="display:none;") snippet = tag.input(type="hidden", id="field-ticket_fields", name="field_ticket_fields", value=','.join(data['ticket_fields'])) stream = stream | filter.before(snippet) stream = stream | filter.before( chrome.render_template(req, 'ticket_fields_datatable.html', data, fragment=True)) return stream
def filter_stream(self, req, method, filename, stream, data): if req.path_info.startswith('/browser') and not data.get('tortoise-svn-message'): # add a hidden dialog div for the tortoisve svn message message = tag.p("TortoiseSVN is a Windows explorer client you can use to browse your Subversion repository.", tag.p("If you have not installed TortoiseSVN, you can download it now from the ", tag.a("TortoiseSVN website.", href="http://tortoisesvn.net/downloads.html", target="_blank" ), ), tag.p("If you have installed TortoiseSVN, please select continue.", ), tag.p("If your local network requires a proxy to access the Internet, note that ", tag.a("TortoiseSVN has proxy settings ", href="http://tortoisesvn.net/docs/nightly/TortoiseSVN_en/tsvn-dug-settings.html#tsvn-dug-settings-network" ), "which are configured separately to your normal Windows browser proxy.", class_="info-light" ), tag.p("This message will not appear again if you click continue.", class_="info-light" ), ) form = tag.form( tag.div( tag.input( type="hidden", name="__FORM_TOKEN", value=req.form_token ), ), tag.input( name="tortoise-svn-message", value="True", ), id_="tortoise-svn-message-form", class_="hidden" ) stream = stream | Transformer("//*[@id='dirlist']").after(tag.div(message, form, id_='tortoise-svn-message-dialog', class_='hidden' ) ) return stream
def _clone_form(self, req, ticket, data): fields = self.ticket_cloner.build_clone_form(req, ticket, data) action = self.ticket_clone_form_action or req.href.newticket() method = self.ticket_clone_form_method if method == "GET": field_name_fn = lambda name: name else: field_name_fn = lambda name: "field_%s" % name return tag.form( tag.div( tag.input(type="submit", name="clone", value=_("Clone"), title=_("Create a copy of this ticket")), [tag.input(type="hidden", name=field_name_fn(n), value=v) for n, v in fields.iteritems()], tag.input(type="hidden", name='preview', value=''), class_="inlinebuttons"), method=method, action=action)
def prepend_ctxtnav(req, elm_or_label, href): """Prepend an entry to the current page's ctxtnav bar. add_ctxtnav(), sadly, always appends to the right side of the (right-aligned by default) context nav, changing the onscreen locations of the links people are already used to. """ elm = tag(tag.label(elm_or_label, for_='rev'), ' ', tag.input(type='text', id='rev', readonly='readonly', value=href, size=len(href))) req.chrome.setdefault('ctxtnav', []).insert(0, elm)
def _build_renamechildren_field(self): return tag.div(tag.label( tag.input(_("Also rename children"), \ type='checkbox', id='rename_children', \ name='rename_children', checked='checked') \ ), \ class_='field')
def _create_button(self, b, req, ticket, data): # Text for button label=self.config.get('ticket-create-buttons','%s.label' % b) title=self.config.get('ticket-create-buttons','%s.title' % b) # Field values for new ticket fields = {} # Values inherited from the current ticket # No setting: all, blank setting: none, Otherwise: the fields listed inherit=self.config.getlist('ticket-create-buttons', '%s.inherit' % b, default=data.keys()) for f in inherit: fields[f]=ticket[f] # Fields that link the new ticket to the current ticket # Missing or empty, no links. link=self.config.getlist('ticket-create-buttons','%s.link' % b, default=[]) for l in link: to, fr = l.split(':') if fr == 'id': fields[to] = ticket.id else: fields[to]=ticket[fr] # Specific value assignments. E.g., a button could always create a test set=self.config.getlist('ticket-create-buttons','%s.set' % b, default=[]) for s in set: n, v = s.split(':') fields[n]=v # Build the form with the values set up above. return tag.form( tag.div( tag.input(type="submit", name="create_"+b, value=label, title=title), # With name='field_'+n here the field prefilled for post but not for get [tag.input(type="hidden", name=n, value=v) for n, v in fields.items()], class_="inlinebuttons"), # With "post" here instead of "get" the ticket is previewed and # we get a warning about the missing summary. method="get", action=req.href.newticket())
def get_content(self, req): """Returns the Genshi tags for the new HTML elements representing the Captcha. """ values = {} values['ip'] = req.remote_addr values['submitted'] = int(time.time()) math_problem_text = self.create_math_problem(values) values['author'] = req.args.get('author') values['summary'] = req.args.get('field_summary') values['text'] = self.get_failed_attempt_text(req) values['href'] = req.path_info # Save the problem so that the post request of the web server knows # which request to process. This is required on FCGI and mod_python # web servers, because there may be many different processes handling # the request and there's no guarantee that the same web server will # handle both the form display and the form submit. db = self.env.get_db_cnx() cursor = db.cursor() fields = values.keys() cursor.execute( "INSERT INTO mathcaptcha_history (%s) VALUES (%s)" % (','.join(fields), ','.join(['%s'] * len(fields))), [values[name] for name in fields]) id = db.get_last_id(cursor, 'mathcaptcha_history') db.commit() self.env.log.debug( "%s %s %s%s: generating math solution: id=%d, %d %s %d = %d" % (req.remote_addr, req.remote_user, req.base_path, req.path_info, id, values['left_operand'], values['operator'], values['right_operand'], values['solution'])) # Obfuscating the names of the input variables to trick spam harvesters # to put other data in the solutions field. The math solution is # named "email" in the hopes that it will attract email addresses # instead of numbers. The database key is named "url" to try to # attract non-numbers content = tag.div( )(tag.label('Anonymous users are allowed to post by %s ' % math_problem_text) + tag.input(type='text', name='email', class_='textwidget', size='5') + tag.input(type='hidden', name='url', value=str(id + self.id_offset))) return content
def filter_stream(self, req, method, filename, stream, data): if 'TICKET_ADMIN' in req.perm: if req.path_info == '/admin/ticket/components' or req.path_info == '/admin/ticket/components/': components = data.get('components') # 'components' will be None if component with specified name already exists. if not components: return stream default_ccs = DefaultCC.select(self.env) stream = stream | Transformer('//table[@id="complist"]/thead/tr') \ .append(tag.th('Default CC')) filter = Transformer('//table[@id="complist"]/tbody') default_comp = self.config.get('ticket', 'default_component') for comp in components: if default_comp == comp.name: default_tag = tag.input(type='radio', name='default', value=comp.name, checked='checked') else: default_tag = tag.input(type='radio', name='default', value=comp.name) if comp.name in default_ccs: default_cc = default_ccs[comp.name] else: default_cc = '' filter = filter.append(tag.tr(tag.td(tag.input(type='checkbox', name='sel', value=comp.name), class_='sel'), tag.td(tag.a(comp.name, href=req.href.admin('ticket', 'components') + '/' + comp.name), class_='name'), tag.td(comp.owner, class_='owner'), tag.td(default_tag, class_='default'), tag.td(default_cc, class_='defaultcc'))) return stream | filter elif req.path_info.startswith('/admin/ticket/components/') and data.get('component'): cc = DefaultCC(self.env, data.get('component').name) filter = Transformer('//form[@id="modcomp"]/fieldset/div[@class="buttons"]') filter = filter.before(tag.div("Default CC:", tag.br(), tag.input(type="text", name="defaultcc", value=cc.cc), class_="field")) \ .before(tag.input(type='hidden', name='old_name', value=cc.name)) return stream | filter return stream
def render_ticket_action_control(self, req, ticket, action): """Returns the action control""" id = 'action_%s_xref' % action ticketnum = req.args.get(id, '') actions = ConfigurableTicketWorkflow(self.env).actions label = actions[action]['name'] hint = actions[action].get('xref_hint', 'The specified ticket will be cross-referenced with this ticket') control = tag.input(type='text', id=id, name=id, value=ticketnum) return (label, control, hint)
def filter_stream(self, req, method, filename, stream, data): if req.path_info == '/timeline': insert = builder( Markup('<br />'), tag_("matching tags "), builder.input(type='text', name=self.key, value=data.get(self.key))) xpath = '//form[@id="prefs"]/div[1]' stream = stream | Transformer(xpath).append(insert) return stream
def helper(field_stream): s = Stream(field_stream) value = s.select('@value').textOf() name = s.select('@name').textOf() for kind, data, pos in tag.span(value, id=("field-%s" % field)).generate(): yield kind, data, pos for kind, data, pos in tag.input(value=value, name=name, type="hidden").generate(): yield kind, data, pos
def render_ticket_action_control(self, req, ticket, action): """Returns the action control""" id = 'action_%s_xref' % action ticketnum = req.args.get(id, '') actions = self.get_configurable_workflow().actions label = actions[action]['name'] hint = actions[action].get('xref_hint', 'The specified ticket will be cross-referenced with this ticket') control = tag.input(type='text', id=id, name=id, value=ticketnum) return (label, control, hint)
def select_helper(stream): s = Stream(stream) name = s.select('@name').textOf() opt = s.select('//option[@selected]') if not opt: s.select('//option[position()=1]') text = opt.select("text()").textOf() value = s.select('@value').textOf() if not value: value = text for kind, data, pos in tag.input(value=value, name=name, type="hidden").generate(): yield kind, data, pos
def _user_field_input(self, req): return tag.div(tag.label("Include users: ", tag.input(type="text", name="inc_users", value=req.session.get('timeline.filter.inc_users',''), style_="width:60%" ) ) + tag.br() + tag.label("Exclude users: ", tag.input(type="text", name="exc_users", value=req.session.get('timeline.filter.exc_users',''), style_="width:60%" ) ) )
def _filterBox(self, req, label, name): return tag.label( label, tag.input( type="text", name=name, value=self._session(req, name, ''), style_="width:60%", title= _('available prefixes: contains: ~, starts with: ^, ends with: $' )))
def filter_stream(self, req, method, filename, stream, data): # check preconditions if filename != 'ticket.html': return stream transformer = Transformer() # build 'Hide these fields' Area hide_names = req.session.get('hidefieldchanges', []) hide_fields = [] for field in data['fields']: name = field['name'] checkbox = name in hide_names \ and tag.input(type='checkbox', checked=True, name=name) \ or tag.input(type='checkbox', name=name) hide_fields.append(tag.label(checkbox, field['label'])) hide_fields.append(tag.br) hide_fields.append( tag.input(name='submit', type='submit', value='Hide these fields')) transformer = transformer \ .select('//div[@id="changelog"]') \ .before(tag.form(tag.input(value='hide changes', id='hidechangesbutton', type='button', style_='float: right;'), tag.div(hide_fields, style='display: none', id='hidefields'), action='#', class_='inlinebuttons hidechanges')).end() # build 'show all changes' button # showallbutton = tag.input(value='show all', name='showall', class_='showallbutton', type='submit', style_='float: right;') # showallbutton = tag.form(showallbutton, action='#', method='get', class_='inlinebuttons hidechanges') # transformer = transformer.select('//div[@id="changelog"]').before(showallbutton).end() # build 'hide customfield' buttons hidebutton = tag.input(value='hide', name="hide", class_='hidebutton', style_='display: none', type='submit') hidebutton = tag.form(hidebutton, action='#', method='get', class_='inlinebuttons hidefieldchanges') transformer = transformer \ .select('//div[@id="changelog"]/div[@class="change"]/ul[@class="changes"]/li') \ .prepend(hidebutton).end() # return filtered stream return stream | transformer
def filter_stream(self, req, method, filename, stream, data): if 'TICKET_ADMIN' in req.perm and \ req.path_info.startswith('/admin/ticket/components'): if data.get('component'): cc = DefaultCC(self.env, data.get('component').name) filter = Transformer('//form[@class="mod"]/fieldset' '/div[@class="field"][2]') filter = filter.after(tag.div("Default CC:", tag.br(), tag.input(type='text', name='defaultcc', value=cc.cc), class_='field')) \ .before(tag.input(type='hidden', name='old_name', value=cc.name)) return stream | filter else: filter = Transformer('//form[@id="addcomponent"]' '/fieldset/div[@class="buttons"]') stream |= filter.before( tag.div("Default CC:", tag.br(), tag.input(type='text', name='defaultcc'), class_='field')) default_ccs = DefaultCC.select(self.env) stream |= Transformer('//table[@id="complist"]/thead' '/tr/th[3]') \ .after(tag.th('Default CC')) components = data.get('components') if components: func = self._inject_default_cc_cols( default_ccs, components) stream |= Transformer('//table[@id="complist"]' '/tbody/tr').apply(func) return stream return stream