def render_comment(self, h, comp, model, *args): with h.div(class_='comment'): with h.div(class_='left'): h << self.author.render(h, model='avatar') with h.div(class_='right'): h << self.author.render(h, model='fullname') h << ' ' << _('wrote') << ' ' h << h.span( _(u'on'), ' ', format_datetime(self.creation_date), class_="date") if security.has_permissions('delete_comment', self): onclick = ( u"if (confirm(%(message)s)){%(action)s;}return false" % { 'action': h.a.action( comp.answer, comp ).get('onclick'), 'message': ajax.py2js( _(u'Your comment will be deleted. Are you sure?') ).decode('UTF-8') } ) h << h.a(h.i(class_='icon-cross'), title=_('Delete'), class_="comment-delete", onclick=onclick, href='') h << self.comment_label.render(h.AsyncRenderer()) return h.root
def render(p, r, comp, *args): # finds out the currently selected page index and the total page count current = p.get_current_page() page_count = p.find_page_count() if page_count <= 1: return r.root # finds out the items that are not ellipsizable unellipsizable = set(xrange(current - p.radius, current + p.radius + 1)) unellipsizable.add(0) unellipsizable.add(page_count - 1) with r.ul(class_='pager'): # renders the 'previous' link render_page_item(r, _(u'Previous'), current - 1, 'disabled' if current == 0 else 'unselected', p) last_was_ellipsized = False for i in xrange(page_count): if i in unellipsizable: type = 'selected' if i == current else 'unselected' render_page_item(r, unicode(1 + i), i, type, p) elif not last_was_ellipsized: render_page_item(r, u'\N{HORIZONTAL ELLIPSIS}', None, 'disabled', p) last_was_ellipsized = True # renders the 'next' link render_page_item(r, _(u'Next'), current + 1, 'disabled' if current >= page_count - 1 else 'unselected', p) return r.root
def render_Kansha_resync(self, h, comp, model): with h.div(id="resync", style='display:none'): h << h.h2(_(u'Synchronization error'), class_='title') with h.div(class_='content'): link = h.a(_(u'click here to resync'), id='resync-action').action(self.initialization) h << h.p(_(u'Your board is out of sync, please '), link, '.') return h.root
def validate_file(data, max_size=None, msg=_('Size must be less than %d KB')): """Validate a 'file' input data against the max size in KB""" # check against the first roundtrip with the client if data is None or isinstance(data, basestring): return None if data.done == -1: raise ValueError(_('Transfer was interrupted')) # gets the file size (it's a StringIO) data.file.seek(0, 2) # 0 from EOF filesize = data.file.tell() data.file.seek(0) if max_size is not None and filesize > max_size * 1024: raise ValueError(msg % max_size) filedata = data.file.read() data.file.seek(0) # some browsers (i.e. Internet Explorer) send the full path of the file # instead of the filename # so, we remove the path from the filename filename = ntpath.basename(unicode(data.filename)) return {'filename': filename, 'data': filedata, 'content_type': unicode(data.type)}
def render_poll_votes(self, h, comp, *args): # title # with h.h1: # if self.is_poll_finished(): # h << _(u'Poll results') # else: # h << self.poll.title # question with h.h2: h << self.poll.question with h.ul(class_="votes"): for index, (choice, ratio) in enumerate(self.get_votes_ratios_per_choice()): with h.li(class_='item_%d' % index): h << h.p(choice.label) with h.div(class_='bar'): h << h.div(class_='bar-inner', style="width: %d%%;" % ratio) h << h.div('%d%%' % ratio, class_="percentage") with h.p(class_="votes-totals"): h << _(u'Vote Total') << " " << self.nb_voters h << ' ' << _(u'voter') return h.root
def render_gallery_cropper(self, h, comp, *args): h << h.p(_('Use the controls below to create the cover of your card.')) form_id = h.generate_id() img_id = h.generate_id() with h.form: for crop_name in 'crop_left', 'crop_top', 'crop_width', 'crop_height': h << h.input(type='hidden', id=form_id + '_' + crop_name).action(getattr(self, crop_name)) h << h.p(render_image(self.asset, h, comp, 'medium', id=img_id)) h << h.script( "YAHOO.util.Event.onContentReady(%s," "function(){YAHOO.kansha.app.initCrop(%s, %s, %s, %s)})" % ( ajax.py2js(img_id), ajax.py2js(img_id), ajax.py2js(form_id), ajax.py2js(self.crop_width()), ajax.py2js(self.crop_height()) ) ) with h.div(class_='buttons'): h << h.button(_('Create cover'), class_='btn btn-primary').action(self.commit, comp) if self.asset.is_cover: h << ' ' h << h.button(_('Remove cover'), class_='btn delete').action(self.remove_cover, comp) h << ' ' h << h.button(_('Cancel'), class_='btn').action(self.cancel, comp) return h.root
def confirm_delete(self, image, comp): """Confirms the deletion of the specified image.""" confirm = Confirmation(_(u'This image will be removed from the gallery. You must confirm the removal.'), _(u'Delete'), _(u'Cancel')) if comp.call(confirm): self.delete_image(image)
def render_ideas_by_fi_list(self, h, comp, *args): ideas_count_by_fi = self.get_ideas_count_by_fi() with h.table(class_='phantom'): with h.thead: with h.tr: h << h.th(_(u'Facilitator')) h << h.th(_(u'Ideas count')) h << h.th(_(u'To process')) with h.tfoot: total_ideas = sum(map(operator.itemgetter(2), ideas_count_by_fi)) total_ideas_to_review = sum( map(operator.itemgetter(3), ideas_count_by_fi)) with h.tr(class_='totals'): h << h.th(_(u"Totals"), class_='label') h << h.td(str(total_ideas), class_='value') h << h.td(str(total_ideas_to_review), class_='value') with h.tbody: days = 15 latecomer_fi = self.get_latecomer_fi(days) for uid, fullname, ideas, ideas_to_review in ideas_count_by_fi: with h.tr(class_='highlight' if uid in latecomer_fi else ''): h << h.td(h.a(fullname).action( lambda user_uid=uid: event_management._emit_signal( self, "VIEW_FI_IDEA_SELECTOR", user_uid=user_uid)), class_='label') h << h.td(str(ideas), class_='value') h << h.td(str(ideas_to_review), class_='value') h << h.p(_(u'In red, facilitators that have ideas ' u'to process older than %d days.') % days, class_='legend') return h.root
def get_article_type_translation(type): Translation = { ArticleType.News: _(u'News'), ArticleType.Ongoing: _(u'Ongoing projects'), ArticleType.Headline: _(u'Headlines'), } return Translation.get(type, '')
def render(self, h, comp, *args): """Render description component in edit mode""" text = var.Var(self.text) with h.div(class_="description"): with h.form(class_='description-form'): txt_id, btn_id, buttons_id = h.generate_id( ), h.generate_id(), h.generate_id() h << h.textarea(text(), id_=txt_id, placeholder=_("Add description."), onfocus="YAHOO.kansha.app.show('%s', true);" % buttons_id, class_="expanded", style="resize:none").action(text) with h.div(id=buttons_id, class_="hidden"): h << h.button(_('Save'), class_='btn btn-primary btn-small', id=btn_id).action(lambda: comp.answer(text())) h << ' ' h << h.button( _('Cancel'), class_='btn btn-small').action(comp.answer) h.head.javascript(h.generate_id(), 'YAHOO.kansha.app.addCtrlEnterHandler(%r, %r)' % (txt_id, btn_id)) h.head.javascript( h.generate_id(), 'YAHOO.kansha.app.autoHeight(%r)' % (txt_id)) # Put the focus on the text area h << h.script("""document.getElementById('%s').focus()""" % txt_id, type="text/javascript", language="javascript") return h.root
def send_notifications(from_user, idea, state, event, new_state, context, comment, notify, **kw): # PROGRES a7 for author in idea.authors: mail_notification.send('mail-idea-deployed.html', to=author, idea=idea) _report_state_changed(from_user, idea, new_state) notify(u'%s → %s' % (_(state), _(new_state)))
def render_article_list_item(self, h, comp, *args): limit = 500 date = format_datetime(self.article.creation_date, format='short') if len(self.article.content) > limit: if self.display_full_description(): content = html(h, self.article.content) else: content = html(h, self.article.content, limit) display_more = True else: content = html(h, self.article.content) display_more = False with h.li: with h.h1: h << h.a(self.article.title, href=self.url) h << h.span(self.article.topic.label or '', class_='thematic') h << h.span(date, class_='date') with h.div: h << content if display_more and not self.display_full_description(): h << h.a(_(u'Read more'), class_='more').action(lambda: self.display_full_description(True)) elif display_more and self.display_full_description(): h << h.a(_(u'Read less'), class_='more').action(lambda: self.display_full_description(False)) return h.root
def render_comments_form(self, h, comp, *args): """Add a comment to the current card""" if security.has_permissions('comment', self): text = var.Var() with h.form: txt_id, buttons_id = h.generate_id(), h.generate_id() sub_id = h.generate_id() kw = { "id": txt_id, "placeholder": _("Add comment."), "onfocus": "YAHOO.kansha.app.show('%s', true);YAHOO.util.Dom.addClass(this, 'expanded'); " % buttons_id, } h << h.textarea(**kw).action(text) h.head.javascript( h.generate_id(), 'YAHOO.kansha.app.addCtrlEnterHandler(%s, %s)' % ( ajax.py2js(txt_id), ajax.py2js(sub_id) ) ) with h.div(id=buttons_id, class_="buttons hidden"): h << h.input(value=_("Save"), id=sub_id, type='submit', class_="btn btn-primary").action(lambda: comp.answer(text())) h << ' ' h << h.input(value=_("Cancel"), type='submit', class_="btn").action(lambda: comp.answer('')) return h.root
def render_SaveTemplateEditor_saved(self, h, comp, *args): with h.div(class_='success'): h << h.i(class_='icon-checkmark') h << _(u'Template saved!') with h.div(class_='buttons'): h << h.SyncRenderer().a(_(u'OK'), class_='btn btn-primary').action(comp.answer) return h.root
def render_CardsCounter_edit(self, h, comp, *args): """Render the title of the associated object""" text = var.Var(self.text) with h.form(class_='title-form'): id_ = h.generate_id() h << h.input(id=id_, type='text', value=self.column.nb_max_cards or '').action(text) h << h.script( """YAHOO.util.Event.on(%s, 'keyup', function (e) { var result =this.value.replace(/[^0-9]/g, '') if (this.value !=result) { this.value = result; } });""" % ajax.py2js(id_) ) h << h.button(_('Save'), class_='btn btn-primary btn-small').action( lambda: self.validate(text(), comp)) h << ' ' h << h.button(_('Cancel'), class_='btn btn-small').action(self.cancel, comp) if self.error is not None: with h.div(class_='nagare-error-message'): h << self.error h << h.script( "YAHOO.kansha.app.selectElement(%s);" "YAHOO.kansha.app.hideOverlay()" % ajax.py2js(id_) ) return h.root
def init_app__new_mail(self, url, comp, http_method, request): username, token = (url[1], url[2]) get_user = lambda: UserManager.get_by_username(username) confirmation = self._services( forms.EmailConfirmation, self.app_title, self.app_banner, self.custom_css, get_user ) if confirmation.confirm_email_address(token): log.debug(_('Change email success for user %s') % get_user().username) comp.becomes(self._services( forms.ChangeEmailConfirmation, self.app_title, self.app_banner, self.custom_css, request.application_url ), model='success' ) confirmation.reset_token(token) else: log.debug(_('Change email failure for user %s') % get_user().username) comp.becomes( self._services( forms.ChangeEmailConfirmation, self.app_title, self.app_banner, self.custom_css, request.application_url ), model='failure' )
def render_idea_wf_comment_table_row(self, h, comp, *args): with h.td(class_='date'): h << format_datetime(self.data.submission_date, format='short') with h.td(class_='change'): h << _(self.data.from_state.label) h << h.div(u" ⬇ ") h << _(self.data.to_state.label) with h.td(class_='author'): # FIXME: we should use a specific "di" view to render the author name author = self.data.created_by di = self.data.idea_wf.assignated_di if author is not di or security.has_permissions('view_di', self): h << author.fullname else: h << _(u'Expert') with h.td(class_='comment'): if security.has_permissions('edit_comment', self): h << self.content_editor.render(h.AsyncRenderer()) else: h << self.data.content return h.root
def write(self): sty = '' header_sty = xlwt.easyxf(sty + 'font: bold on; align: wrap on, vert centre, horiz center;') sty = xlwt.easyxf(sty) ws = self.workbook.add_sheet(self.sheet_name) titles = [_(u'Column'), _(u'Title')] + self.extension_titles for col, title in enumerate(titles): ws.write(0, col, title, style=header_sty) row = 1 for column in self.board.columns: column = column() colname = _('Archived cards') if column.is_archive else column.get_title() for card in column.cards: card = card() ws.write(row, 0, colname, sty) ws.write(row, 1, card.get_title(), sty) card_extensions = dict(card.extensions) for col, key in enumerate(self.extensions, 2): ext = card_extensions[key]() write_extension_data(ext, ws, row, col, sty) row += 1 for col in xrange(len(titles)): ws.col(col).width = 0x3000 ws.set_panes_frozen(True) ws.set_horz_split_pos(1)
def render_di_editor_update_di_business_area(self, h, comp, *args): def commit(): if self.update_di_business_area(): comp.answer() with h.h1: h << _(u"Expert's Business Area") with h.form: with h.p: h << _(u"Please enter the expert's business area") with h.div(class_='fields'): h << h.input(type='text', class_='text wide', value=self.di_business_area()).action(self.di_business_area).error(self.di_business_area.error) if self.user.specialty: with h.p: h << _("For your information, here is the specialty defined in the expert's profile:") << h.br h << self.user.specialty with h.div(class_='buttons'): h << h.input(type="submit", value=_(u'Validate')).action(commit) return h.root
def render_BoardDescription(self, h, comp, *args): """Render description component in edit mode""" text = var.Var(self.text) with h.form(class_='description-form'): txt_id, btn_id = h.generate_id(), h.generate_id() h << h.label(_(u'Description'), for_=txt_id) ta = h.textarea(text(), id_=txt_id).action(text) if not security.has_permissions('edit', self): ta(disabled='disabled') h << ta with h.div: if security.has_permissions('edit', self): h << h.button(_('Save'), class_='btn btn-primary btn-small', id=btn_id).action(remote.Action(lambda: self.change_text(text()))) h << ' ' h << h.button( _('Cancel'), class_='btn btn-small').action(remote.Action(lambda: self.change_text(None))) h.head.javascript( h.generate_id(), 'YAHOO.kansha.app.addCtrlEnterHandler(%s, %s)' % ( ajax.py2js(txt_id), ajax.py2js(btn_id) ) ) return h.root
def render_Board_item(self, h, comp, *args): def answer(): comp.answer(self.data.id) url = self.data.url with h.li(class_="row-fluid"): with h.a(self.data.title, href=url, class_="boardItemLabel").action(answer): if self.data.description: h << {'data-tooltip': self.data.description} h << {'onmouseover': """YAHOO.kansha.app.highlight(this, 'members', false); YAHOO.kansha.app.highlight(this, 'archive', false); YAHOO.kansha.app.highlight(this, 'leave', false);""", 'onmouseout': """YAHOO.kansha.app.highlight(this, 'members', true); YAHOO.kansha.app.highlight(this, 'archive', true); YAHOO.kansha.app.highlight(this, 'leave', true);"""} h << self.comp_members.render(h.AsyncRenderer(), 'members') if security.has_permissions('manage', self): h << h.a(class_='archive', title=_(u'Archive this board')).action(self.archive_board) else: h << h.a(class_='leave', title=_(u'Leave this board'), onclick='return confirm("%s")' % _("You won't be able to access this board anymore. Are you sure you want to leave it anyway?") ).action(self.leave) return h.root
def commit(self, application_url): """ Commit method If email changes, send confirmation mail to user If password changes, check passwords rules """ if not self.is_validated(self.fields): return # Test if email_to_confirm has changed if (self.target.email_to_confirm != self.email_to_confirm() and self.target.email != self.email_to_confirm()): # Change target email_to_confirm (need it to send mail) self.target.email_to_confirm = self.email_to_confirm() confirmation = self._create_email_confirmation(application_url) confirmation.send_email(self.mail_sender) self.email_to_confirm.info = _( 'A confirmation email has been sent.') # Test if password has changed if (len(self.password()) > 0 and not(self.old_password.error) and not(self.password_repeat.error)): user = security.get_user() user.data.change_password(self.password()) user.update_password(self.password()) self.password_repeat.info = _('The password has been changed') super(BasicUserForm, self).commit(self.fields)
def render_workflow_event_editor_choose_di(self, h, comp, *args): def developer_option(user): di_business_area = ellipsize(user.di_business_area, 40) if user.di_business_area else _(u'N/A') ideas_count = len(user.assignated_di_ideas) label = '%s - %s (%d)' % (di_business_area, user.fullname, ideas_count) option = h.option(label, value=user.uid) if self.current_di: option = option.selected(self.current_di.uid) return option h << h.label(_(u'Expert:')) with h.select().action(self.di): sort_key = lambda user: (user.di_business_area or _(u'N/A')) challenge_developers = sorted(self.challenge_developers(), key=sort_key) other_developers = sorted((user for user in self.all_developers() if user not in challenge_developers), key=sort_key) if challenge_developers: h << h.option('-- %s --' % _("Challenge developers"), disabled=True) for user in challenge_developers: h << developer_option(user) h << h.option('-- %s --' % _("Other developers"), disabled=True) for user in other_developers: h << developer_option(user) return h.root
def render_Board_item(self, h, comp, *args): reload_search = ajax.Update(component_to_update='show_results', render=lambda renderer: comp.render(renderer, 'search_results')) h << h.script(u'''$(window).on('reload_search', function() { %s; })''' % reload_search.generate_action(41, h)) with h.div(id='switch_zone'): if self.model == 'columns': search_cb = ajax.Update( action=self.search, component_to_update='show_results', render=lambda renderer: comp.render(renderer, 'search_results') ).generate_action(1, h).replace('this', 'elt') oninput = 'debounce(this, function(elt) { %s; }, 500)' % search_cb with h.div(id_='show_results'): h << comp.render(h, 'num_matches') if self.card_matches: if None in self.card_matches: klass = 'nomatches' else: klass = 'highlight' else: klass = '' h << h.input(type='text', id_='search', placeholder=_(u'search'), value=self.last_search, oninput=oninput, class_=klass) #h << h.a(h.i(class_='icon-search', title=_('search')), class_='btn unselected') h << h.SyncRenderer().a(h.i(class_='icon-calendar'), title=_('Calendar mode'), class_='btn unselected').action(self.switch_view) h << h.SyncRenderer().a(h.i(class_='icon-list'), title=_('Board mode'), class_='btn disabled') else: h << h.SyncRenderer().a(h.i(class_='icon-calendar'), title=_('Calendar mode'), class_='btn disabled') h << h.SyncRenderer().a(h.i(class_='icon-list'), title=_('Board mode'), class_='btn unselected').action(self.switch_view) return h.root
def render_profile_box_profile_view(self, h, comp, *args): user = self.user # expert's business area if user.di_business_area and security.has_permissions('view_di_business_area', self): with h.h2: h << _(u"Expert's Business Area") with h.p: h << user.di_business_area or '' with h.div(class_='group'): h << h.h2(_(u'Who am I?')) if user.description: with h.p: h << '"%s"' % user.description with h.div(class_='group'): with h.table: with h.tbody: with h.tr: with h.td: h << h.h2(_(u'Skills')) if user.competencies: h << text_to_html_elements(h, user.competencies) with h.td: h << h.h2(_(u'Expertises')) if user.expertises: h << text_to_html_elements(h, user.expertises) with h.td: h << h.h2(_(u'Hobbies')) if user.hobbies: h << text_to_html_elements(h, user.hobbies) return h.root
def render_card_actions(self, h, comp, *args): with h.div(class_='span2 cardactions'): with h.form: with h.ul(): with h.li(class_="buttonAddChecklist"): h << self.checklists.render(h, 'button') with h.li(class_="buttonAddFile"): h << self.gallery.render(h, 'download') with h.li(class_="buttonVote"): h << self.votes.render(h.AsyncRenderer(), 'edit') with h.li(class_="buttonDueDate"): h << self.due_date.render(h.AsyncRenderer(), 'button') with h.li(class_="buttonDeleteCard"): if security.has_permissions('edit', self) and not self.column.is_archive: action = h.a.action(lambda: comp.answer('delete')).get('onclick') close_func = 'function (){%s;}' % (action) h << h.button(h.i(class_='icon-remove icon-grey'), _('Delete'), class_='btn btn-small', onclick=("if (confirm(\"%(confirm_msg)s\"))" " { YAHOO.kansha.app.archiveCard(%(close_func)s, '%(id)s', '%(col_id)s', '%(archive_col_id)s'); }return false;" % dict(close_func=close_func, id=self.id, col_id=self.column.id, archive_col_id=self.column.board.archive_column.id, confirm_msg=_(u'This card will be deleted. Are you sure ?')))) if self.board.weighting_cards: with h.li(class_="actionWeight"): h << self._weight.on_answer(lambda v: self._weight.call(model='edit_weight' if v else None)) h << comp.render(h, 'members') return h.root
def get_2months_chart(self, width, height): today = datetime.today().date() start_date = today - timedelta(days=today.weekday(), weeks=7) ideas = {} for item in self.get_ideas_count_day_by_day(start_date): week_number = item.date.isocalendar()[1] ideas.setdefault(week_number, 0) ideas[week_number] += item.count connections = {} for item in self.get_connection_count_day_by_day(start_date): week_number = item.date.isocalendar()[1] connections.setdefault(week_number, 0) connections[week_number] += item.count # last 2 months labels week_numbers = [(start_date + timedelta(weeks=n)).isocalendar()[1] for n in range(0, 8)] data = [(ideas.get(item, 0), connections.get(item, 0)) for item in week_numbers] labels = [u'%s %s' % (_(u'week'), n) for n in week_numbers] legend_labels = [_(u'Ideas count'), _(u'Connections count')] chart = DoubleHorizontalLineChart(labels, zip(*data), width=width, height=height, legend=True, legendlabels=legend_labels) return chart.get_png()
def get_2weeks_chart(self, width, height): start_date = datetime.today().date() - timedelta(days=14) ideas = {} for item in self.get_ideas_count_day_by_day(start_date): ideas[item.formatted_date] = item.count connections = {} for item in self.get_connection_count_day_by_day(start_date): connections[item.formatted_date] = item.count labels = [ format_date(start_date + timedelta(days=days), format="short") for days in range(0, 14)] data = [(ideas.get(item, 0), connections.get(item, 0)) for item in labels] legend_labels = [_(u'Ideas count'), _(u'Connections count')] chart = DoubleHorizontalLineChart(labels, zip(*data), width=width, height=height, legend=True, legendlabels=legend_labels) return chart.get_png()
def render_profile_box_points(self, h, comp, *args): # display a shop button if I'm looking my own profile if self.is_mine: h << component.Component(self.online_shop).render(h, model='link_box') with h.div(class_='point-details'): # finds out the points points_by_label = self.user.get_points_by_category() used_point_labels = points_by_label.keys() # no points? if len(points_by_label) == 0: h << h.h2(_(u'You do not have any point yet.')) return h.root # renders the available points h << h.h2(_(u'Available points: %d') % self.user.available_points) # renders the acquired points h << h.h2(_(u'Acquired points: %d') % self.user.acquired_points) labels = [l for l in get_acquired_point_categories() if l in used_point_labels] render_point_labels(self, h, comp, labels, points_by_label) # renders the spent points h << h.h2(_(u'Spent points: %d') % self.user.spent_points) labels = [l for l in get_sorted_spent_point_categories() if l in used_point_labels] render_point_labels(self, h, comp, labels, points_by_label) return h.root
def render_idea_basket_dsig(self, h, comp, *args): labels = dict(default_states_labels()) with h.div(class_="state_selector rounded"): sorted_ideas = self.get_sorted_ideas() if len(sorted_ideas) == 0: h << _(u'No idea in basket') else: with h.ul(class_="ideaBoard"): for state, nb in sorted_ideas: label = labels.get(state, None) if label: with h.li(class_='ideas-list'): if self.state_id == state: h << h.a( '[-] ', label % nb, class_="selected_link" ).action(lambda: event_management._emit_signal(self, "HIDE_IDEAS")) with h.table: with h.tbody: with h.tr(class_='filter'): h << h.td h << h.td(_('Comments')) h << h.td(_('Votes')) h << self.pager else: h << h.a( '[+] ', label % nb ).action(lambda v=state: event_management._emit_signal(self, "VIEW_DSIG_IDEAS", state=v)) return h.root
def render_members_many_user(self, h, comp, *args): number = len(self.members) - self.MAX_SHOWN_MEMBERS return h.span(h.i(class_='ico-btn icon-user'), h.span(number, class_='count'), title=_('%s more...') % number)
def render_userboards(self, h, comp, *args): template = var.Var(u'') h.head << h.head.title(self.app_title) h.head.css_url('css/themes/home.css') h.head.css_url('css/themes/%s/home.css' % self.theme) with h.div(class_='new-board'): with h.form: h << h.SyncRenderer().button( _(u'Create'), type='submit', class_='btn btn-primary').action( lambda: self.create_board(template(), comp)) h << (u' ', _(u'a new'), u' ') if len(self.templates) > 1: with h.select.action(template): with h.optgroup(label=_(u'Shared templates')): h << [ h.option(tpl, value=id_) for id_, tpl in self.templates['public'] ] if self.templates['private']: with h.optgroup(label=_(u'My templates')): h << [ h.option(tpl, value=id_) for id_, tpl in self.templates['private'] ] else: id_, tpl = self.templates.items()[0] template(id_) h << tpl h << (u' ', _(u'board')) if self.last_modified_boards: h << h.h1(_(u'Last modified boards')) with h.ul(class_='board-labels'): h << [ b.on_answer(self.handle_event).render(h, 'item') for b in self.last_modified_boards.itervalues() ] h << h.h1(_(u'My boards')) with h.ul(class_='board-labels'): h << [ b.on_answer(self.handle_event).render(h, 'item') for b in self.my_boards.itervalues() ] if self.guest_boards: h << h.h1(_(u'Guest boards')) with h.ul(class_='board-labels'): h << [ b.on_answer(self.handle_event).render(h, 'item') for b in self.guest_boards.itervalues() ] if len(self.archived_boards): h << h.h1(_('Archived boards')) with h.ul(class_='board-labels'): h << [ b.on_answer(self.handle_event).render(h, 'archived_item') for b in self.archived_boards.itervalues() ] with h.form: h << h.button(_('Delete'), class_='delete', onclick='return confirm(%s)' % ajax.py2js( _('These boards will be destroyed. Are you sure?' )).decode('UTF-8'), type='submit').action(self.purge_archived_boards) h << h.script( 'YAHOO.kansha.app.hideOverlay();' 'function reload_boards() { %s; }' % h.AsyncRenderer().a.action( ajax.Update(action=self.load_user_boards, render=0)).get('onclick')) return h.root
def render_board_background_edit(self, h, comp, *args): """Render the background configuration panel""" if self._changed(): h.head.javascript( h.generate_id(), "YAHOO.kansha.app.setBoardBackgroundImage(%s, %s);" "YAHOO.kansha.app.setTitleColor(%s)" % (ajax.py2js(self.board.background_image_url or '', h), ajax.py2js(self.board.background_image_position, h), ajax.py2js(self.board.title_color or u'', h))) self._changed(False) with h.div(class_='panel-section background'): h << h.div(_(u'Background image'), class_='panel-section-title') with h.div: with h.div: v_file = var.Var() submit_id = h.generate_id("attach_submit") input_id = h.generate_id("attach_input") h << h.label((h.i(class_='icon-file'), _("Choose an image")), class_='btn', for_=input_id) with h.form(class_='hidden'): h << h.script( u''' function valueChanged(e) { if (YAHOO.kansha.app.checkFileSize(this, %(max_size)s)) { YAHOO.util.Dom.get(%(submit_id)s).click(); } else { alert(%(error)s); } } YAHOO.util.Event.onDOMReady(function() { YAHOO.util.Event.on(%(input_id)s, 'change', valueChanged); });''' % { 'max_size': ajax.py2js(self.board.background_max_size, h), 'input_id': ajax.py2js(input_id, h), 'submit_id': ajax.py2js(submit_id, h), 'error': ajax.py2js(_(u'Max file size exceeded'), h).decode('UTF-8') }) h << h.input( id=input_id, class_='hidden', type="file", name="file", multiple="multiple", maxlength="100", ).action(v_file) h << h.input(id=submit_id, class_='hidden', type="submit").action( lambda: self.set_background(v_file())) with h.div: h << _('or') << ' ' h << h.a(_(u'Reset background')).action(self.reset_background) with h.div: with h.span(class_='text-center'): h << component.Component(self.board, model='background_image') with h.div: input_id = h.generate_id() submit_id = h.generate_id("image_position_submit") h << h.script( u'''YAHOO.util.Event.onDOMReady(function() { YAHOO.util.Event.on(%(input_id)s, 'change', function() { YAHOO.util.Dom.get(%(submit_id)s).click(); }); });''' % { 'input_id': ajax.py2js(input_id, h), 'submit_id': ajax.py2js(submit_id, h) }) with h.form: h << h.label(_(u'Image position'), for_=input_id) with h.select(id_=input_id).action(self.background_position): for value, name in self.get_available_background_positions( ): h << h.option(name, value=value).selected( self.background_position()) h << h.input(class_='hidden', id_=submit_id, type="submit").action( self.set_background_position) with h.div(class_='panel-section background'): h << h.div(_(u'Board title color'), class_='panel-section-title') with h.div: with h.div: h << comp.render(h, model='title-color-edit') with h.div: h << _('or') << ' ' h << h.a(_('Reset to default color')).action(self.reset_color) return h.root
def render_board_background_menu(self, h, comp, *args): return h.a(_('Background image')).action(comp.answer)
def render_BoardProfile(self, h, comp, *args): """Render the board profile form""" if security.has_permissions('manage', self.board): with h.div(class_='panel-section'): h << h.div(_(u'Card Visibility'), class_='panel-section-title') h << h.p(_(u'Choose whether the board is private or public.')) with h.form: with h.div(class_='btn-group'): active = 'active btn-primary' if self.board.visibility == BOARD_PRIVATE else '' h << h.button( _('Private'), class_='btn %s' % active).action( lambda: self.board.set_visibility(BOARD_PRIVATE)) active = 'active btn-primary' if self.board.visibility == BOARD_PUBLIC else '' h << h.button( _('Public'), class_='btn %s' % active).action( lambda: self.board.set_visibility(BOARD_PUBLIC)) with h.div(class_='panel-section'): h << h.div(_(u'Comments'), class_='panel-section-title') h << h.p( _('Commenting allows members to make short messages on cards. You can enable or disable this feature.' )) with h.form: with h.div(class_='btn-group'): active = 'active btn-primary' if self.board.comments_allowed == COMMENTS_OFF else '' h << h.button( _('Disabled'), class_='btn %s' % active).action( lambda: self.allow_comments(COMMENTS_OFF)) active = 'active btn-primary' if self.board.comments_allowed == COMMENTS_MEMBERS else '' h << h.button( _('Members'), class_='btn %s' % active).action( lambda: self.allow_comments(COMMENTS_MEMBERS)) kw = {} if self.board.visibility == BOARD_PUBLIC else { "disabled": "disabled" } active = 'active btn-primary' if self.board.comments_allowed == COMMENTS_PUBLIC else '' h << h.button( _('Public'), class_='btn %s' % active, **kw).action( lambda: self.allow_comments(COMMENTS_PUBLIC)) with h.div(class_='panel-section'): h << h.div(_(u'Votes'), class_='panel-section-title') h << h.p(_(u'Allow votes')) with h.form: with h.div(class_='btn-group'): active = 'active btn-primary' if self.board.votes_allowed == VOTES_OFF else '' h << h.button( _('Disabled'), class_='btn %s' % active).action(lambda: self.allow_votes(VOTES_OFF)) active = 'active btn-primary' if self.board.votes_allowed == VOTES_MEMBERS else '' h << h.button( _('Members'), class_='btn %s' % active).action(lambda: self.allow_votes(VOTES_MEMBERS)) kw = {} if self.board.visibility == BOARD_PUBLIC else { "disabled": "disabled" } active = 'active btn-primary' if self.board.votes_allowed == VOTES_PUBLIC else '' h << h.button( _('Public'), class_='btn %s' % active, ** kw).action(lambda: self.allow_votes(VOTES_PUBLIC)) with h.div(class_='panel-section'): h << h.div(_(u'Archive'), class_='panel-section-title') h << h.p(_(u'View archive column')) with h.form: with h.div(class_='btn-group'): if self._changed(): h << h.script('reload_columns();') self._changed(False) active = 'active btn-primary' if self.board.show_archive else '' h << h.button(_('Show'), class_='btn %s' % active).action(lambda: self.set_archive(1)) active = 'active btn-primary' if not self.board.show_archive else '' h << h.button(_('Hide'), class_='btn %s' % active).action(lambda: self.set_archive(0)) with h.div(class_='panel-section'): h << h.div(_(u'Notifications'), class_='panel-section-title') h << h.p( _(u'You will be notified by email of changes made in this board to cards' )) with h.form: with h.div(class_='btn-group'): active = 'active btn-primary' if self.notifications_allowed == notifications.NOTIFY_OFF else '' h << h.button(_('None'), class_='btn %s' % active).action( self.allow_notifications, notifications.NOTIFY_OFF) active = 'active btn-primary' if self.notifications_allowed == notifications.NOTIFY_MINE else '' h << h.button( _('Affected to me'), class_='btn %s' % active).action( self.allow_notifications, notifications.NOTIFY_MINE) active = 'active btn-primary' if self.notifications_allowed == notifications.NOTIFY_ALL else '' h << h.button(_('All'), class_='btn %s' % active).action( self.allow_notifications, notifications.NOTIFY_ALL) return h.root
def render_event_card_add_member(action, data): return _(u'User %(user)s has been assigned to card "%(card)s"') % data
def render_event(action, data): return _( u'User %(author)s has deleted the checklist "%(list)s" from card "%(card)s"' ) % data
def render_event_card_remove_member(action, data): return _(u'User %(user)s has been unassigned from card "%(card)s"') % data
def render_event_card_add_list(action, data): return _( u'User %(author)s has added the checklist "%(list)s" to card "%(card)s"' ) % data
def render_login(self, h, comp, with_cancel, with_forgot_password, with_help): def login(): if self.commit(): comp.answer(LoginEvent()) def cancel(): self.form_opened(False) comp.answer(CancelLoginEvent()) def reset_password(): comp.answer(ResetPasswordEvent()) with h.div(class_='connect'): with h.form: with h.div(class_='fields'): with h.div(class_='login-field field'): field_id = h.generate_id('field') help = _( u"Enter you login: first letter of your firstname + your name (e.g. jdoe)" ) h << h.input(id=field_id, type='text', class_='text', title=help, name='__ac_name', placeholder=_(u'Login')) with h.div(class_='password-field field'): field_id = h.generate_id('field') help = _( u"Enter your password: on first connection, enter the one you received by email" ) h << h.input(id=field_id, type='password', class_='text', title=help, name='__ac_password', placeholder=_(u'Password')) with h.div(class_='buttons'): if with_forgot_password: label = _(u'Forgot your password?') h << h.a(label, title=label, class_='forgot-password').action(reset_password) with h.div: label = _(u'Connect') h << h.input(type='submit', value=label, title=label).action(login) if with_cancel: # WARNING: this is not a submit button, otherwise __ac # fields are submitted and the login is performed label = _(u'Cancel') cancel_url = h.a.action(cancel).get('href') h << h.input( type='submit', onclick='window.location="%s";return false' % cancel_url, value=label, title=label).action(cancel) if with_help: with h.div(class_='help rounded'): with h.h2: h << _(u"First connection?") with h.p: h << _( u"Enter you login: first letter of your firstname + your name (e.g. jdoe)" ) with h.p: h << _( u"Enter the temporary password that have been sent to you by email" )
def render_event(action, data): return _( u'User %(author)s has checked the item %(item)s from the checklist "%(list)s", on card "%(card)s"' ) % data
def render_articles_tab(self, h, comp, *args): with h.div(class_='articles-tab'): with h.table(class_='datatable'): with h.thead: with h.tr: h << h.th(_(u'Article title'), class_='title') h << h.th(_(u'Published'), class_='publication-status') h << h.th(_(u'Actions'), class_='actions') with h.tbody: for article in self.articles: with h.tr(class_='published' if article. published else 'unpublished'): with h.td(class_='title'): with h.a(title=_(u'Edit article')).action( lambda id=article.id: self.edit_article(id )): h << article.title with h.td(class_='publication-status'): if article.published: h << h.a(_(u'Yes'), title=_(u'Unpublish'), class_='yes').action( lambda id=article.id: self. set_publish(id, False)) else: h << h.a( _(u'No'), title=_(u'Publish'), class_='no' ).action(lambda id=article.id: self. set_publish(id, True)) with h.td(class_='actions'): # preview label = _(u'Preview the article') h << h.a( label, title=label, class_='preview-article' ).action( lambda id=article.id: self.preview_article(id)) # delete title = _(u'Confirm delete?') message = _( u'The article will be deleted. Are you sure?') js = 'return yuiConfirm(this.href, "%s", "%s", "%s", "%s")' % ( title, message, _(u'Delete'), _(u'Cancel')) label = _(u'Delete the article') h << h.a( label, title=label, class_='delete-article', onclick=js).action(lambda id=article.id: self. delete_article(id)) with h.div(class_='buttons'): h << h.a(_(u'Add an article'), class_='confirm-button').action( lambda: self.create_article(self.type)) return h.root
def export(idea_ids, permission=None, filename_prefix='export'): # gets the information to export columns = [ (_(u'Id'), 1500), (_(u'Title'), 20000), (_(u'Challenge'), 10000), (_(u'Description'), 15000), (_(u'Origin'), 10000), (_(u'Impact'), 10000), (_(u'Submission date'), 5000), (_(u'Author name'), 7000), (_(u'Position'), 3000), (_(u'Corporation'), 7000), (_(u'Direction'), 7000), (_(u'Service'), 7000), (_(u'Site'), 7000), (_(u'Votes count'), 5000), (_(u'Comments count'), 5000), (_(u'Domain'), 8000), (_(u'State'), 5000), (_(u'Url'), 8000), (_(u'Facilitator'), 5000), (_(u'Developer'), 5000), (_(u'Benefit_department'), 5000), ] # launches the query # FIXME: don't create a query: use the appropriate IdeaRepository's method instead AuthorUser = aliased(UserData) FIUser = aliased(UserData) DIUser = aliased(UserData) Corporation = aliased(OrganizationData) Direction = aliased(OrganizationData) Service = aliased(OrganizationData) Site = aliased(OrganizationData) SubSite = aliased(OrganizationData) q = session.query( IdeaData.id, IdeaData.submission_date, IdeaData.challenge_id, ChallengeData.title.label('challenge'), IdeaData.title, IdeaData.description, IdeaData.origin, IdeaData.impact, IdeaData.benefit_department, AuthorUser.uid, AuthorUser.firstname, AuthorUser.lastname, AuthorUser.position, Corporation.label.label('corporation'), Direction.label.label('direction'), Service.label.label('service'), Site.label.label('site'), DomainData.label.label('domain'), FIUser.uid.label('fi_uid'), FIUser.firstname.label('fi_firstname'), FIUser.lastname.label('fi_lastname'), DIUser.uid.label('di_uid'), DIUser.firstname.label('di_firstname'), DIUser.lastname.label('di_lastname'), StateData.label.label('state'), IdeaData.total_votes, IdeaData.total_comments, IdeaEvalContextData.target_date.label('target_date'), IdeaEvalContextData.goal.label('goal'), IdeaEvalContextData.revenues_first_year.label('revenues_first_year'), IdeaEvalContextData.revenues_first_year_value.label( 'revenues_first_year_value'), IdeaEvalContextData.revenues_second_year.label('revenues_second_year'), IdeaEvalContextData.revenues_second_year_value.label( 'revenues_second_year_value'), IdeaEvalContextData.expenses_first_year.label('expenses_first_year'), IdeaEvalContextData.expenses_first_year_value.label( 'expenses_first_year_value'), IdeaEvalContextData.expenses_second_year.label('expenses_second_year'), IdeaEvalContextData.expenses_second_year_value.label( 'expenses_second_year_value'), IdeaEvalContextData.evaluation_impact.label('evaluation_impact'), ).outerjoin(AuthorData) q = q.join((AuthorUser, AuthorData.user)) q = q.outerjoin((Corporation, AuthorUser.corporation)) q = q.outerjoin((Direction, AuthorUser.direction)) q = q.outerjoin((Service, AuthorUser.service)) q = q.outerjoin((Site, AuthorUser.site)) q = q.outerjoin((SubSite, AuthorUser.subsite)) q = q.outerjoin(IdeaData.wf_context) q = q.outerjoin(IdeaData.eval_context) q = q.outerjoin(IdeaData.domain) q = q.outerjoin(IdeaWFContextData.state) q = q.outerjoin((DIUser, IdeaWFContextData.assignated_di)) q = q.outerjoin((FIUser, IdeaWFContextData.assignated_fi)) q = q.outerjoin(IdeaData.challenge) q = q.filter(IdeaData.id.in_(idea_ids)) years_revenues = [] years_expenses = [] if permission in ('dsig', 'developer'): columns = columns + [(_(u'target_date'), 5000), (_(u'goal'), 5000)] for row in q: years_revenues = years_revenues + [ row.revenues_first_year, row.revenues_second_year ] years_revenues = list(set(years_revenues)) years_revenues = [y for y in years_revenues if y] years_revenues.sort() years_expenses = years_expenses + [ row.expenses_first_year, row.expenses_second_year ] years_expenses = list(set(years_expenses)) years_expenses = [y for y in years_expenses if y] years_expenses.sort() columns = columns + [(_(u'Revenue %s') % y, 5000) for y in years_revenues] columns = columns + [(_(u'Expenses %s') % y, 5000) for y in years_expenses] columns = columns + [(_(u'CF/MSCV'), 3000)] authors = {} for id, ideas in itertools.groupby(q, key=lambda row: row.id): for idea in ideas: authors.setdefault(id, []).append('%s %s' % (idea.firstname, idea.lastname)) # creates the workbook wb = xlwt.Workbook(encoding='utf-8') ws = wb.add_sheet(u'Export') f = xlwt.Formatting.Font() f.underline = xlwt.Formatting.Font.UNDERLINE_SINGLE f.colour_index = 4 # built-in blue link_style = xlwt.Style.XFStyle() link_style.font = f date_style = xlwt.easyxf(num_format_str='DD-MM-YYYY HH:MM') # write header row & define columns width for col_index, (name, width) in enumerate(columns): ws.write(0, col_index, unicode(name)) ws.col(col_index).width = width # write ideas duplicates = set() row_index = 1 for row in q: # Remove duplicates # EV 592 : all author names in the same cell if row.id in duplicates: continue else: duplicates.add(row.id) idea_url = get_url_service().expand_url(['idea', row.id], relative=False) row_data = [ unicode(row.id), row.title, u'%s (%s)' % (row.challenge, row.challenge_id) if row.challenge_id else u'', row.description, row.origin, row.impact, (row.submission_date, date_style), '; '.join(authors.get(row.id, [])), row.position, row.corporation, row.direction, row.service, row.site, unicode(row.total_votes), unicode(row.total_comments), _(row.domain), _(row.state), (xlwt.Formula(u'HYPERLINK("%s";"%s")' % (idea_url, idea_url)), link_style), u'%s %s' % (row.fi_firstname, row.fi_lastname) if row.fi_uid else u'', u'%s %s' % (row.di_firstname, row.di_lastname) if row.di_uid else u'', row.benefit_department, ] if permission in ('dsig', 'developer'): row_data = row_data + [ row.target_date.strftime('%d/%m/%Y') if row.target_date else '', row.goal, ] row_year_revenues = ['' for y in years_revenues] row_year_expenses = ['' for y in years_expenses] if row.revenues_first_year: index = years_revenues.index(row.revenues_first_year) row_year_revenues[index] = row.revenues_first_year_value if row.revenues_second_year: index = years_revenues.index(row.revenues_second_year) row_year_revenues[index] = row.revenues_second_year_value if row.expenses_first_year: index = years_expenses.index(row.expenses_first_year) row_year_expenses[index] = row.expenses_first_year_value if row.expenses_second_year: index = years_expenses.index(row.expenses_second_year) row_year_expenses[index] = row.expenses_second_year_value row_data = row_data + row_year_revenues + row_year_expenses row_data = row_data + [row.evaluation_impact] for col_index, data in enumerate(row_data): if hasattr(data, '__iter__'): ws.write(row_index, col_index, *data) else: ws.write(row_index, col_index, data) row_index += 1 # saves it in a memory buffer stream = StringIO() wb.save(stream) content = stream.getvalue() stream.close() timestamp = datetime.now().strftime('%Y-%m-%d') filename = filename_prefix + '_' + timestamp + '.xls' return content, filename
def get_extension_title_DueDate(card_extension): return _(u'Due date')
def show_dsig_ideas_basket(self, user=None): uid = self._uid(user) basket = IdeaBasket(self, uid, StateData.get_ideas_count_by_states, _(u'DSIG basket')) return self._show(basket, model='DSIG', selected_tab='dsig_basket')
def validate_password_confirm(self, v): if self.password.value and self.password.value != v: raise ValueError( _(u'The password confirmation is different from the password')) return v
def show_fi_dsig_ideas_basket(self, user=None): uid = self._uid(user) basket = IdeaBasket(self, uid, get_fi_ideas_count(uid), _(u'Facilitator basket')) return self._show(basket, model='FI_DSIG', selected_tab='fi_basket')
def search_users(self, pattern): pager = UserBrowser(self, pattern) box = PagerBox(pager, title=_(u'Search results for %s') % pattern) return self._show(box, selected_tab='search')
def show_reset_password(self): self._show_modal(ResetPassword(), title=_('Reset my password'))
def show_di_dsig_ideas_basket(self, user=None): uid = self._uid(user) basket = IdeaBasket(self, uid, get_di_ideas_count(uid), _(u'Developer basket')) return self._show(basket, model='DI_DSIG', selected_tab='di_basket')
def initial_setup(self): poll = get_all_enabled_polls().first() if poll: self.poll = component.Component(Poll(poll.id)) else: self.poll = component.Component(None) self.locale_box.becomes(LocaleChoice()) self.idea_submit.becomes(SubmitIdeaBox(self)) self.search.becomes(SearchBlock(self)) self.idea_chart.becomes(IdeaBarChart(self)) self.welcome.becomes(Welcome(self)) self.online_shop.becomes(OnlineShop(self)) self.faq.becomes(FAQ(self)) self.terms_of_use.becomes(TermsOfUse(self)) self.login_box.becomes(Login()) # Note: setup done here because we need to access the current user and check the # permissions in order to setup the component but they are not available when # the Portal component is created. # password change modal dialog current_user = get_current_user() if current_user and current_user.should_change_password(): self.show_password_editor(current_user) current_user = get_current_user() if current_user: self.login_box.becomes(User(self, current_user), model='login_status') self.menu_items = [ (_(u'home'), _(u"Go to the home page"), 'home', self.show_home), (_(u'news'), None, 'news', self.show_articles_by_type), (_(u'challenge'), _(u"View, comment and vote for challenge ideas"), 'challenges', self.show_challenge_ideas), (_(u'ideas'), _(u"View, comment and vote for ideas"), 'ideas', self.show_ideas), ] self.menu_items.extend([ (_(u"discover eurêka"), None, 'welcome', self.show_welcome), (_(u'gifts'), None, 'shop', self.show_shop), (_(u'help'), None, 'help', self.show_help), (_(u'contact us'), None, 'contact_us', self.show_contact) ]) self.menu.becomes(Menu(self.menu_items), model='list') self.footer_menu_items = [ (_(u'Help'), None, 'help', self.show_help), (_(u'Suggestions'), None, 'improvements', self.show_suggestions), (_(u'Terms of use'), None, 'terms_of_use', self.show_terms_of_use), ] self.footer_menu.becomes(Menu(self.footer_menu_items), model='links') # initial the content if necessary (that is, when no presentation.init_for rule was # called) if not self.content(): self.select_tab(0)
def show_user_ideas_basket(self, user=None): uid = self._uid(user) basket = IdeaBasket(self, uid, get_user_ideas_count(uid), _(u'My Ideas')) return self._show(basket, selected_tab='my')
class UserForm(BasicUserForm): def __init__(self, app_title, app_banner, theme, target, assets_manager_service, mail_sender_service): """ In: - ``target`` -- DataUser instance - ``mail_sender_service`` -- MailSender service """ super(UserForm, self).__init__(app_title, app_banner, theme, target, self.fields) self.app_title = app_title self.app_banner = app_banner self.theme = theme self.mail_sender = mail_sender_service self.assets_manager = assets_manager_service self.username.validate(self.validate_username) self.fullname.validate(validator.validate_non_empty_string) # Add other properties (email to confirm, passwords...) self.email_to_confirm = editor.Property( target.email).validate(validator.validate_email) self.old_password = editor.Property( '').validate(self.validate_old_password) self.password = editor.Property('').validate(self.validate_password) self.password_repeat = editor.Property( '').validate(self.validate_passwords_match) self.user_manager = UserManager() def validate_username(self, value): """Check username In: - ``value`` -- username (must be unique) Return: - username value if username is unique (else raise an exception) """ value = validator.validate_identifier(value) # check that this user name does not exist user = self.user_manager.get_by_username(value) if user: raise ValueError(_('Username %s is not available. Please choose another one.') % value) return value def validate_password(self, value): """Check new password In: - ``value`` -- new password (must be greater than 6 chars) Return: - password value if password is ok (else raise an exception) """ # check password complexity min_len = 6 if len(value) < min_len and len(value) > 0: raise ValueError(_('Password too short: should have at least %d characters') % min_len) return value def validate_old_password(self, value): """Check old password In: - ``value`` -- old password Return: - password value if value is the old password """ if len(value) == 0 or security.get_user().data.check_password(value): return self.validate_password(value) raise ValueError(_('''This password doesn't match the old one.''')) def validate_passwords_match(self, value): """Check if confirmation password and password are equals In: - ``value`` -- confirmation password Return: - password value if confirmation password and password are equals """ if self.password.value == value: return value else: raise ValueError(_('''The two passwords don't match''')) def _create_email_confirmation(self, application_url): """Create email confirmation""" confirmation_url = '/'.join( (application_url, 'new_mail', self.username())) return registation_forms.EmailConfirmation(self.app_title, self.app_banner, self.theme, lambda: security.get_user().data, confirmation_url) def commit(self, application_url): """ Commit method If email changes, send confirmation mail to user If password changes, check passwords rules """ if not self.is_validated(self.fields): return # Test if email_to_confirm has changed if (self.target.email_to_confirm != self.email_to_confirm() and self.target.email != self.email_to_confirm()): # Change target email_to_confirm (need it to send mail) self.target.email_to_confirm = self.email_to_confirm() confirmation = self._create_email_confirmation(application_url) confirmation.send_email(self.mail_sender) self.email_to_confirm.info = _( 'A confirmation email has been sent.') # Test if password has changed if (len(self.password()) > 0 and not(self.old_password.error) and not(self.password_repeat.error)): user = security.get_user() user.data.change_password(self.password()) user.update_password(self.password()) self.password_repeat.info = _('The password has been changed') super(BasicUserForm, self).commit(self.fields) def set_picture(self, new_file): uid = self.target.username self.picture.error = None error = None # No value, exit if new_file == '': return None try: validator.validate_file( new_file, self.assets_manager.max_size, _(u'File must be less than %d KB')) except ValueError, e: error = e.message if imghdr.what(new_file.file) is None: error = _(u'Invalid image file') if error: self.picture.error = error return None # Remove old value if self.target.picture: self.assets_manager.delete(uid) # Save new value self.assets_manager.save(new_file.file.read(), file_id=uid, metadata={ 'filename': new_file.filename, 'content-type': new_file.type}, THUMB_SIZE=(100, 100)) self.picture(self.assets_manager.get_image_url(uid, size='thumb'))
def show_password_editor(self, user): self._show_modal(PasswordEditor(user, with_cancel=True), title=_('Please change your password'))
def render_boardweights_edit(self, h, comp, *args): """Render the weights configuration panel""" with h.div(class_='panel-section'): h << h.div(_(u'Weighting cards'), class_='panel-section-title') h << h.p(_(u'Activate cards weights')) with h.form: with h.div(class_='btn-group'): if self._changed(): h << h.script('reload_columns()') self._changed(False) h << h.a( _('Disabled'), class_='btn %s' % ('active btn-primary' if self.board.weighting_cards == WEIGHTING_OFF else ''), onclick= ("if (confirm(%(message)s)){%(action)s;}return false" % { 'action': h.a.action(self.deactivate_weighting).get('onclick'), 'message': ajax.py2js( _(u'All affected weights will be reseted. Are you sure?' )).decode('UTF-8') })) h << h.button( _('Free integer'), class_='btn %s' % ('active btn-primary' if self.board.weighting_cards == WEIGHTING_FREE else ''), onclick= ("if (confirm(%(message)s)){%(action)s;}return false" % { 'action': h.a.action(lambda: self.activate_weighting( WEIGHTING_FREE)).get('onclick'), 'message': ajax .py2js( _(u'All affected weights will be reseted. Are you sure?' )).decode('UTF-8') }), title=_('Card weights can be any integer')) h << h.button( _('Integer sequence'), class_='btn %s' % ('active btn-primary' if self.board.weighting_cards == WEIGHTING_LIST else ''), onclick= ("if (confirm(%(message)s)){%(action)s;}return false" % { 'action': h.a.action(lambda: self.activate_weighting( WEIGHTING_LIST)).get('onclick'), 'message': ajax .py2js( _(u'All affected weights will be reseted. Are you sure?' )).decode('UTF-8') }), title=_('Choosen within a sequence of integers')) if self.board.weighting_cards == WEIGHTING_LIST: h << h.p(_('Enter a sequence of integers')) h << self._weights_editor return h.root
def render_async(self, h, comp, *args): with h.div(class_='calendar-input'): input_id = h.generate_id('input') calendar_id = h.generate_id('calendar') if self.is_hidden: style = 'display: none;' else: style = 'display: block;' with h.div(class_='calendar', id_=calendar_id, style=style): with h.div(class_='calendar-header'): with h.a(title=_(u'Previous')).action(self.previous_month): h << h.i(class_='icon-arrow-left', title=_(u'Previous')) with h.span(class_='current'): with h.select(onchange=ajax.Update( action=self.change_month)): for n, month in i18n.get_month_names().iteritems(): month = month.capitalize() h << h.option(month, value=n).selected( self.current.month) h << u' ' with h.select(onchange=ajax.Update( action=self.change_year)): for year in xrange(self.current.year - YEARS_AROUND, self.current.year + YEARS_AROUND): h << h.option(year, value=year).selected( self.current.year) with h.a(title=_(u'Next')).action(self.next_month): h << h.i(class_='icon-arrow-right', title=_(u'Next')) with h.div(class_='calendar-content'): if isinstance(self.date, date): if self.current.year == self.date.year and self.current.month == self.date.month: active = self.date.day else: active = -1 else: active = -1 today = date.today() if today.month == self.current.month and today.year == self.current.year: today = today.day else: today = -1 with h.table: with h.thead: with h.tr: h << h.th(h.span(_('Wk'), title=_('Week number')), class_='week_number') days = [ day.capitalize() for day in i18n.get_day_names().itervalues() ] h << [h.th(h.span(d[:2], title=d)) for d in days] with h.tbody: for line in calendar.monthcalendar( self.current.year, self.current.month): with h.tr: week_number = date( self.current.year, self.current.month, max(1, line[0])).isocalendar()[1] h << h.td(week_number, class_='week_number') for day in line: if day == 0: h << h.td(class_='not-this-month') else: authorized = self.is_authorized_date( self.current.replace(day=day)) cls = [] if day == active: cls.append(u'active') if day == today: cls.append(u'today') if not authorized: cls.append(u'excluded') with h.td(class_=' '.join(cls)): if authorized: h << h.a(day).action( lambda day=day: self. choose_date(day, comp)) else: h << h.span(day) with h.div(class_='calendar-today'): h << h.a(h.i(class_='icon-calendar'), _(u"Today"), class_='today-link btn').action(self.set_today) if self.allow_none: h << h.a(h.i(class_='icon-remove'), _(u'None'), class_='erase btn').action( lambda: self.remove_date(comp)) h << h.script( "YAHOO.util.Event.onDOMReady(function() {" "var region = YAHOO.util.Dom.getRegion(%(input_id)s);" "YAHOO.util.Dom.setXY(%(calendar_id)s, [region.left, region.bottom + 3]);" "});" % { 'input_id': ajax.py2js(input_id), 'calendar_id': ajax.py2js(calendar_id) }) h << h.div(class_='clear') return h.root
def render_BoardLabels_menu(self, h, comp, *args): """Render the link leading to the label configuration""" h << h.a(_('Labels')).action(comp.answer) return h.root
def validate_non_empty_string(value, msg=_L("Required field")): """Check that the value is a non-empty string""" # strip whitespace characters return validator.StringValidator(value, strip=True).not_empty(_(msg)).to_string()
def render_boardweights_menu(self, h, comp, *args): """Render the link leading to the weights configuration""" h << h.a(_('Weights')).action(comp.answer) return h.root
def check_users_have_enough_points(self): emails = self.users_with_not_enough_points() if emails: msg = _(u'The following users do not have enough available points: %s') % ', '.join(emails) self.users_emails.error = msg