def buttons2pager(buttons, title=None): items = [] if title: items.append(E.li(E.span(title))) for symbol, label, url in buttons: if url is None: items.append(E.li(E.span(symbol), class_="disabled")) else: items.append(E.li(E.a(symbol, href=url))) # Bootstrap version 2.x # return E.div(E.ul(*items), class_='pagination') return E.ul(*items, class_='pagination pagination-sm')
def welcome_html(self, ui=None): "See :meth:`ad.Site.welcome_html`." from django.utils.translation import ugettext as _ p = [] sep = '' if self.verbose_name: p.append(_("This is ")) if self.url: p.append( E.a(self.verbose_name, href=self.url, target='_blank')) else: p.append(E.b(self.verbose_name)) if self.version: p.append(' ') p.append(self.version) sep = _(' using ') for name, version, url in self.get_used_libs(html=E): p.append(sep) p.append(E.a(name, href=url, target='_blank')) p.append(' ') p.append(version) sep = ', ' return E.span(*p)
def you_are_busy_messages(ar): """Yield :message:`You are busy in XXX` messages for the welcome page.""" events = rt.modules.cal.Event.objects.filter( user=ar.get_user(), guest__state=GuestStates.busy).distinct() if events.count() > 0: chunks = [unicode(_("You are busy in "))] sep = None for evt in events: if sep: chunks.append(sep) ctx = dict(id=evt.id) if evt.event_type is None: ctx.update(label=unicode(evt)) else: ctx.update(label=evt.event_type.event_label) if evt.project is None: txt = _("{label} #{id}").format(**ctx) else: ctx.update(project=unicode(evt.project)) txt = _("{label} with {project}").format(**ctx) chunks.append(ar.obj2html(evt, txt)) chunks += [ ' (', ar.instance_action_button(evt.close_meeting), ')'] sep = ', ' chunks.append('. ') yield E.span(*chunks)
def workflow_buttons(obj, ar): #~ logger.info('20120930 workflow_buttons %r', obj) l = [] if ar is not None: actor = ar.actor state = actor.get_row_state(obj) if state is not None: #~ l.append(E.b(unicode(state),style="vertical-align:middle;")) l.append(E.b(unicode(state))) #~ l.append(u" » ") #~ l.append(u" \u25b8 ") #~ l.append(u" \u2192 ") #~ sep = u" \u25b8 " sep = u" \u2192 " else: # logger.info('20150602 no state for %s in %s (%s)', # obj, actor, actor.model) sep = '' for ba in actor.get_actions(): if ba.action.show_in_workflow: if actor.get_row_permission(obj, ar, state, ba): l.append(sep) l.append(ar.action_button(ba, obj)) sep = ' ' return E.span(*l)
def workflow_buttons(obj, ar): #~ logger.info('20120930 workflow_buttons %r', obj) l = [] if ar is not None: actor = ar.actor state = actor.get_row_state(obj) if state is not None: #~ l.append(E.b(unicode(state),style="vertical-align:middle;")) l.append(E.b(unicode(state))) #~ l.append(u" » ") #~ l.append(u" \u25b8 ") #~ l.append(u" \u2192 ") #~ sep = u" \u25b8 " sep = u" \u2192 " else: # logger.info('20150602 no state for %s in %s (%s)', # obj, actor, actor.model) sep = '' for ba in actor.get_actions(): if ba.action.show_in_workflow: if actor.get_row_permission(obj, ar, state, ba): l.append(sep) l.append(ar.action_button(ba, obj)) sep = ' ' return E.span(*l)
def workflow_buttons(obj, ar): #~ logger.info('20120930 workflow_buttons %r', obj) l = [] if ar is not None: actor = ar.actor state = actor.get_row_state(obj) sep = '' show = True # whether to show the state def show_state(): l.append(sep) #~ l.append(E.b(unicode(state),style="vertical-align:middle;")) # if state.button_text: # l.append(E.b(state.button_text)) # else: # l.append(E.b(str(state))) l.append(E.b(str(state))) #~ l.append(u" » ") #~ l.append(u" \u25b8 ") #~ l.append(u" \u2192 ") #~ sep = u" \u25b8 " for ba in actor.get_actions(): if ba.action.show_in_workflow: if actor.get_row_permission(obj, ar, state, ba): if show and isinstance(ba.action, ChangeStateAction): show_state() sep = u" \u2192 " show = False l.append(sep) l.append(ar.action_button(ba, obj)) sep = ' ' if state and show: show_state() return E.span(*l)
def welcome_html(self, ui=None): """ Return a HTML version of the "This is APPLICATION version VERSION using ..." text. to be displayed in the About dialog, in the plain html footer, and maybe at other places. """ from django.utils.translation import ugettext as _ p = [] sep = '' if self.verbose_name: p.append(_("This is ")) if self.url: p.append( E.a(self.verbose_name, href=self.url, target='_blank')) else: p.append(E.b(self.verbose_name)) if self.version: p.append(' ') p.append(self.version) sep = _(' using ') for name, version, url in self.get_used_libs(html=E): p.append(sep) p.append(E.a(name, href=url, target='_blank')) p.append(' ') p.append(version) sep = ', ' return E.span(*p)
def welcome_messages(ar): """Yield messages for the welcome page.""" Notification = rt.modules.notifier.Notification qs = Notification.objects.filter(user=ar.get_user(), seen__isnull=True) if qs.count() > 0: chunks = [str(_("You have %d unseen notifications: ")) % qs.count()] chunks += join_elems([ar.obj2html(obj, str(obj.owner)) for obj in qs]) yield E.span(*chunks)
def get_slave_summary(self, obj, ar): """Displays the uploads related to this controller as a list grouped by uploads type. Note that this also works on :class:`lino_welfare.modlib.uploads.models.UploadsByClient` and their subclasses for the different `_upload_area`. """ UploadType = rt.modules.uploads.UploadType # Upload = rt.modules.uploads.Upload elems = [] types = [] for ut in UploadType.objects.filter( upload_area=self._upload_area): sar = ar.spawn( self, master_instance=obj, known_values=dict(type_id=ut.id)) # logger.info("20140430 %s", sar.data_iterator.query) files = [] for m in sar: text = self.format_row_in_slave_summary(ar, m) if text is None: continue edit = ar.obj2html( m, text, # _("Edit"), # icon_name='application_form', title=_("Edit metadata of the uploaded file.")) if m.file.name: show = ar.renderer.href_button( settings.SITE.build_media_url(m.file.name), _(" [show]"), # fmt(m), target='_blank', icon_name='../xsite/link', # icon_name='page_go', # style="vertical-align:-30%;", title=_("Open the uploaded file in a new browser window")) # logger.info("20140430 %s", E.tostring(e)) files.append(E.span(edit, ' ', show)) else: files.append(edit) if ut.wanted and ( ut.max_number < 0 or len(files) < ut.max_number): files.append(sar.insert_button()) if len(files) > 0: e = E.p(unicode(ut), ': ', *join_elems(files, ', ')) types.append(e) # logger.info("20140430 %s", [E.tostring(e) for e in types]) if len(types) == 0: elems.append(E.ul(E.li(ar.no_data_text))) else: elems.append(E.ul(*[E.li(e) for e in types])) return E.div(*elems)
def question(self, obj, ar): if obj.question.number: txt = obj.question.NUMBERED_TITLE_FORMAT % (obj.question.number, obj.question.title) else: txt = obj.question.title attrs = dict(class_="htmlText") if obj.question.details: attrs.update(title=obj.question.details) if obj.question.is_heading: txt = E.b(txt, **attrs) return E.span(txt, **attrs)
def welcome_messages(ar): """Yield messages for the welcome page.""" Notification = rt.modules.notifier.Notification qs = Notification.objects.filter(user=ar.get_user(), seen__isnull=True) if qs.count() > 0: chunks = [ unicode(_("You have %d unseen notifications: ")) % qs.count() ] chunks += join_elems( [ar.obj2html(obj, unicode(obj.owner)) for obj in qs]) yield E.span(*chunks)
def info(self, row, ar): elems = [] if row.project: elems.append(ar.obj2html(row.project)) if row.partner: elems.append(ar.obj2html(row.partner)) # elems.append(row.partner.address) if row.bank_account: elems.append(ar.obj2html(row.bank_account)) if row.account: elems.append(ar.obj2html(row.account)) # return E.span(*join_elems(elems, ' / ')) return E.span(*join_elems(elems, E.br))
def question(self, obj, ar): if obj.question.number: txt = obj.question.NUMBERED_TITLE_FORMAT % (obj.question.number, obj.question.title) else: txt = obj.question.title attrs = dict(class_="htmlText") if obj.question.details: attrs.update(title=obj.question.details) if obj.question.is_heading: txt = E.b(txt, **attrs) return E.span(txt, **attrs)
def info(self, row, ar): elems = [] if row.project: elems.append(ar.obj2html(row.project)) if row.partner: elems.append(ar.obj2html(row.partner)) # elems.append(row.partner.address) if row.bank_account: elems.append(ar.obj2html(row.bank_account)) if row.account: elems.append(ar.obj2html(row.account)) # return E.span(*join_elems(elems, ' / ')) return E.span(*join_elems(elems, E.br))
def get_welcome_messages(cls,ar): guests = [] sar = ar.spawn(cls) for g in sar: guests.append(g) #~ print "20130909 MyBusyVisitors get_welcome_messages", guests if len(guests) > 0: #~ print 20130909, guests[0].get_default_table() chunks = [ unicode(_("You are busy with ")) ] def f(g): #~ return sar.obj2html(g,unicode(g.partner)) return sar.row_action_button(g,cls.detail_action,unicode(g.partner),icon_name=None) chunks += join_elems([f(g) for g in guests],sep=unicode(_(" and "))) chunks.append('.') yield E.span(*chunks)
def welcome_messages(ar): """Yield a message "Your stars are X, Y, ..." for the welcome page. This message mentions all starred objects of the requesting user and whose :attr:`nickname <Star.nickname>` is not empty. """ Star = rt.modules.stars.Star qs = Star.objects.filter(user=ar.get_user()).exclude(nickname='') if qs.count() > 0: chunks = [str(_("Your stars are "))] chunks += join_elems([ ar.obj2html(obj.owner, obj.nickname or str(obj.owner)) for obj in qs]) chunks.append('.') yield E.span(*chunks)
def welcome_messages(ar): """Yield a message "Your stars are X, Y, ..." for the welcome page. This message mentions all starred objects of the requesting user and whose :attr:`nickname <Star.nickname>` is not empty. """ Star = rt.modules.stars.Star qs = Star.objects.filter(user=ar.get_user()).exclude(nickname='') if qs.count() > 0: chunks = [unicode(_("Your stars are "))] chunks += join_elems([ ar.obj2html(obj.owner, obj.nickname or unicode(obj.owner)) for obj in qs ]) chunks.append('.') yield E.span(*chunks)
def answer_buttons(self, obj, ar): # assert isinstance(obj, Answer) cs = obj.question.get_choiceset() if cs is None: return '' elems = [] pv = dict(question=obj.question) # ia = obj.response.toggle_choice sar = obj.response.toggle_choice.request_from(ar) if False: # since 20170129 ba = Responses.actions.toggle_choice if ba is None: raise Exception("No toggle_choice on {0}?".format(ar.actor)) sar = ba.request_from(ar) # print("20150203 answer_buttons({0})".format(sar)) # if the response is registered, just display the choice, no # toggle buttons since answer cannot be toggled: # 20151211 sar.selected_rows = [obj.response] if not sar.get_permission(): return str(obj) AnswerChoice = rt.modules.polls.AnswerChoice for c in cs.choices.all(): pv.update(choice=c) text = str(c) qs = AnswerChoice.objects.filter(response=obj.response, **pv) if qs.count() == 1: text = [E.b('[', text, ']')] elif qs.count() == 0: pass else: raise Exception("Oops: %s returned %d rows." % (qs.query, qs.count())) sar.set_action_param_values(**pv) e = sar.ar2button(obj.response, text, style="text-decoration:none") elems.append(e) return E.span(*join_elems(elems), class_="htmlText")
def welcome_messages(ar): """Yield a message "Your favourites are X, Y, ..." for the welcome page. This message mentions all voted objects of the requesting user and whose :attr:`nickname <Vote.nickname>` is not empty. """ Vote = rt.models.votes.Vote qs = Vote.objects.filter(user=ar.get_user()).exclude(nickname='') qs = qs.order_by('priority') if qs.count() > 0: chunks = [six.text_type(_("Your favourite {0} are ").format( dd.plugins.votes.votable_model._meta.verbose_name_plural))] chunks += join_elems([ ar.obj2html(obj.votable, obj.nickname) for obj in qs]) chunks.append('.') yield E.span(*chunks)
def get_workflow_buttons(obj, ar): l = [] actor = ar.actor # print(20170102, actor) state = actor.get_row_state(obj) sep = '' show = True # whether to show the state # logger.info('20161219 workflow_buttons %r', state) def show_state(): l.append(sep) #~ l.append(E.b(unicode(state),style="vertical-align:middle;")) # if state.button_text: # l.append(E.b(state.button_text)) # else: # l.append(E.b(str(state))) l.append(E.b(str(state))) #~ l.append(u" » ") #~ l.append(u" \u25b8 ") #~ l.append(u" \u2192 ") #~ sep = u" \u25b8 " for ba in actor.get_actions(): assert ba.actor == actor # 20170102 if ba.action.show_in_workflow: # if actor.model.__name__ == 'Vote': # if ba.action.__class__.__name__ == 'MarkVoteAssigned': # print(20170115, actor, ar.get_user()) if actor.get_row_permission(obj, ar, state, ba): if show and isinstance(ba.action, ChangeStateAction): show_state() sep = u" \u2192 " show = False l.append(sep) l.append(ar.action_button(ba, obj)) sep = ' ' if state and show: show_state() return E.span(*l)
def get_slave_summary(self, obj, ar): if ar is None: return '' elems = [] # Active sessions: active_sessions = [] qs = rt.modules.clocking.Session.objects.filter(ticket=obj) tot = Duration() for ses in qs: d = ses.get_duration() if d is not None: tot += d if ses.end_time is None: txt = "{0} since {1}".format(ses.user, ses.start_time) lnk = ar.obj2html(ses, txt) sar = ses.end_session.request_from(ar) if sar.get_permission(): lnk = E.span(lnk, " ", sar.ar2button(ses)) active_sessions.append(lnk) # elems.append(E.p(_("Total {0} hours.").format(tot))) elems.append(E.p(_("Total %s hours.") % tot)) if len(active_sessions) > 0: elems.append(E.p( ensureUtf(_("Active sessions")), ": ", *join_elems(active_sessions, ', '))) # Button for starting a session from ticket sar = obj.start_session.request_from(ar) # if ar.renderer.is_interactive and sar.get_permission(): if sar.get_permission(): btn = sar.ar2button(obj) elems += [E.p(btn)] return E.div(*elems)
def answer_buttons(self, obj, ar): # assert isinstance(obj, Answer) cs = obj.question.get_choiceset() if cs is None: return "" elems = [] pv = dict(question=obj.question) ba = Responses.actions.toggle_choice if ba is None: raise Exception("No toggle_choice on {0}?".format(ar.actor)) sar = ba.request_from(ar) # print("20150203 answer_buttons({0})".format(sar)) # if the response is registered, just display the choice, no # toggle buttons since answer cannot be toggled: # 20151211 sar.selected_rows = [obj.response] if not sar.get_permission(): return str(obj) AnswerChoice = rt.modules.polls.AnswerChoice for c in cs.choices.all(): pv.update(choice=c) text = str(c) qs = AnswerChoice.objects.filter(response=obj.response, **pv) if qs.count() == 1: text = [E.b("[", text, "]")] elif qs.count() == 0: pass else: raise Exception("Oops: %s returned %d rows." % (qs.query, qs.count())) sar.set_action_param_values(**pv) e = sar.ar2button(obj.response, text, style="text-decoration:none") elems.append(e) return E.span(*join_elems(elems), class_="htmlText")
def get_data_rows(self, ar): """ """ data_rows = self.get_request_queryset(ar) today = ar.param_values.date or settings.SITE.today() period = (today, today) def UL(items): # ~ return E.ul(*[E.li(i) for i in items]) newitems = [] first = True for i in items: if first: first = False else: newitems.append(E.br()) newitems.append(i) return E.p(*newitems) for job in data_rows: showit = False working = [] qs = job.contract_set.order_by("applies_from") if ar.param_values.contract_type: qs = qs.filter(type=ar.param_values.contract_type) for ct in qs: if ct.applies_from: until = ct.date_ended or ct.applies_until if not until or (ct.applies_from <= today and until >= today): working.append(ct) if len(working) > 0: job._working = UL( [ E.span( # ~ ar.obj2html(ct.person,ct.person.last_name.upper()), ar.obj2html(ct.person), # pgettext("(place)", " at ") # + unicode(ct.company.name), " bis %s" % dd.fds(ct.applies_until), ) for ct in working ] ) showit = True else: job._working = "" candidates = [] qs = job.candidature_set.order_by("date_submitted").filter(state=CandidatureStates.active) qs = only_coached_on(qs, period, "person") for cand in qs: candidates.append(cand) if candidates: job._candidates = UL( [ # ~ ar.obj2html(i.person,i.person.last_name.upper()) ar.obj2html(i.person) for i in candidates ] ) showit = True else: job._candidates = "" probation = [] qs = job.candidature_set.order_by("date_submitted").filter(state=CandidatureStates.probation) qs = only_coached_on(qs, period, "person") for cand in qs: probation.append(cand) if probation: job._probation = UL( [ # ~ E.span(ar.obj2html(i.person,i.person.last_name.upper())) E.span(ar.obj2html(i.person)) for i in probation ] ) showit = True else: job._probation = "" if showit: yield job
def vouchers(self, row, ar): matches = [dm.match for dm in row._expected] return E.span(', '.join(matches))
def payments(self, row, ar): return E.span(*join_elems([ # E.p(...) until 20150128 ar.obj2html(i.voucher.get_mti_leaf()) for i in row.payments ]))
def actions(self, row, ar): # TODO return E.span("[Show debts] [Issue reminder]")
def mti_navigator(self, ar): buttons = self.get_mti_buttons(ar) return E.span(*buttons)
def get_slave_summary(self, obj, ar): """Displays the uploads related to this controller as a list grouped by uploads type. Note that this also works on :class:`lino_welfare.modlib.uploads.models.UploadsByClient` and their subclasses for the different `_upload_area`. """ UploadType = rt.modules.uploads.UploadType # Upload = rt.modules.uploads.Upload elems = [] types = [] perm = ar.get_user().profile.has_required_roles(self.required_roles) for ut in UploadType.objects.filter(upload_area=self._upload_area): sar = ar.spawn( self, master_instance=obj, known_values=dict(type_id=ut.id)) # logger.info("20140430 %s", sar.data_iterator.query) files = [] for m in sar: text = self.format_row_in_slave_summary(ar, m) if text is None: continue edit = ar.obj2html( m, text, # _("Edit"), # icon_name='application_form', title=_("Edit metadata of the uploaded file.")) if m.file.name: show = ar.renderer.href_button( settings.SITE.build_media_url(m.file.name), # u"\u21A7", # DOWNWARDS ARROW FROM BAR (↧) # u"\u21E8", u"\u21f2", # SOUTH EAST ARROW TO CORNER (⇲) style="text-decoration:none;", # _(" [show]"), # fmt(m), target='_blank', # icon_name=settings.SITE.build_static_url( # 'images/xsite/link'), # icon_name='page_go', # style="vertical-align:-30%;", title=_("Open the uploaded file in a new browser window")) # logger.info("20140430 %s", E.tostring(e)) files.append(E.span(edit, ' ', show)) else: files.append(edit) if perm and ut.wanted \ and (ut.max_number < 0 or len(files) < ut.max_number): btn = self.insert_action.request_from( sar, master_instance=obj, known_values=dict(type_id=ut.id)).ar2button() if btn is not None: files.append(btn) if len(files) > 0: e = E.p(str(ut), ': ', *join_elems(files, ', ')) types.append(e) # logger.info("20140430 %s", [E.tostring(e) for e in types]) if len(types) == 0: elems.append(E.ul(E.li(ar.no_data_text))) else: elems.append(E.ul(*[E.li(e) for e in types])) return E.div(*elems)
def mti_navigator(self, ar): buttons = self.get_mti_buttons(ar) return E.span(*buttons)
def get_slave_summary(self, obj, ar): """The :meth:`summary view <lino.core.actors.Actor.get_slave_summary>` for :class:`LinksByTicket`. """ # if obj.pk is None: # return '' # raise Exception("20150218") sar = self.request_from(ar, master_instance=obj) links = [] for lnk in sar: if lnk.parent is None or lnk.child is None: pass else: if lnk.child_id == obj.id: i = (lnk.type.as_child(), lnk.parent) else: i = (lnk.type.as_parent(), lnk.child) links.append(i) def by_age(a): return a[1].modified try: links.sort(key=by_age) # except AttributeError: except (AttributeError, ValueError): # AttributeError: 'str' object has no attribute 'as_date' # possible when empty birth_date # ValueError: day is out of range for month pass tbt = dict() # tickets by lnktype for lnktype, other in links: lst = tbt.setdefault(lnktype, []) txt = "#%d" % other.id lst.append(ar.obj2html(other, txt, title=other.summary)) items = [] for lnktype, lst in tbt.items(): items.append(E.li(unicode(lnktype), ": ", *join_elems(lst, ', '))) elems = [] if len(items) > 0: # elems += join_elems(items) # elems.append(l(*items)) elems.append(E.ul(*items)) # else: # elems.append(_("No dependencies.")) # Buttons for creating relationships: sar = obj.spawn_triggered.request_from(ar) if ar.renderer.is_interactive and sar.get_permission(): btn = sar.ar2button(obj) elems += [E.br(), btn] sar = self.insert_action.request_from(ar) if ar.renderer.is_interactive and sar.get_permission(): actions = [] for lt in LinkTypes.objects(): actions.append(E.br()) sar.known_values.update(type=lt, parent=obj) sar.known_values.pop('child', None) btn = sar.ar2button(None, lt.as_parent(), icon_name=None) if not lt.symmetric: # actions.append('/') sar.known_values.update(type=lt, child=obj) sar.known_values.pop('parent', None) btn2 = sar.ar2button(None, lt.as_child(), icon_name=None) # actions.append(btn) btn = E.span(btn, '/', btn2) actions.append(btn) # actions.append(' ') # actions = join_elems(actions, E.br) if len(actions) > 0: elems += [E.br(), _("Create dependency as ")] + actions return E.div(*elems)
def get_slave_summary(self, obj, ar): """Displays the uploads related to this controller as a list grouped by uploads type. Note that this also works on :class:`lino_welfare.modlib.uploads.models.UploadsByClient` and their subclasses for the different `_upload_area`. """ UploadType = rt.modules.uploads.UploadType # Upload = rt.modules.uploads.Upload elems = [] types = [] perm = ar.get_user().profile.has_required_roles(self.required_roles) for ut in UploadType.objects.filter(upload_area=self._upload_area): sar = ar.spawn(self, master_instance=obj, known_values=dict(type_id=ut.id)) # logger.info("20140430 %s", sar.data_iterator.query) files = [] for m in sar: text = self.format_row_in_slave_summary(ar, m) if text is None: continue edit = ar.obj2html( m, text, # _("Edit"), # icon_name='application_form', title=_("Edit metadata of the uploaded file.")) if m.file.name: show = ar.renderer.href_button( settings.SITE.build_media_url(m.file.name), # u"\u21A7", # DOWNWARDS ARROW FROM BAR (↧) # u"\u21E8", u"\u21f2", # SOUTH EAST ARROW TO CORNER (⇲) style="text-decoration:none;", # _(" [show]"), # fmt(m), target='_blank', # icon_name=settings.SITE.build_static_url( # 'images/xsite/link'), # icon_name='page_go', # style="vertical-align:-30%;", title=_( "Open the uploaded file in a new browser window")) # logger.info("20140430 %s", E.tostring(e)) files.append(E.span(edit, ' ', show)) else: files.append(edit) if perm and ut.wanted \ and (ut.max_number < 0 or len(files) < ut.max_number): btn = self.insert_action.request_from( sar, master_instance=obj, known_values=dict(type_id=ut.id)).ar2button() if btn is not None: files.append(btn) if len(files) > 0: e = E.p(unicode(ut), ': ', *join_elems(files, ', ')) types.append(e) # logger.info("20140430 %s", [E.tostring(e) for e in types]) if len(types) == 0: elems.append(E.ul(E.li(ar.no_data_text))) else: elems.append(E.ul(*[E.li(e) for e in types])) return E.div(*elems)
def payments(self, row, ar): return E.span(*join_elems([ # E.p(...) until 20150128 ar.obj2html(i.voucher.get_mti_leaf()) for i in row.payments]))