def colored_calendar_fmt(self, pv): ele = E.span(self.calendar_fmt(pv)) data_color = self.get_diplay_color() if data_color: dot = E.span(u"\u00A0", CLASS="dot") # ele.attrib['style'] = "color: white;background-color: {};".format(data_color) dot.attrib['style'] = "background-color: {};".format(data_color) return E.div(*[dot, ele]) else: return E.div(*[ele])
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 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 calendar_fmt(self, pv): # if pv.user: # if pv.assigned_to: # if settings.SITE.project_model is not None and pv.project: # if pv.event_type: t = [] if self.start_time: t.append(str(self.start_time)[:5]) # elif not pv.start_date: # t.append(str(self.start_date)) if not pv.user and self.user: t.append(str(self.user)) if self.summary: t.append(self.summary) if not pv.event_type and self.event_type: t.append(str(self.event_type)) if not pv.room and self.room: t.append(str(self.room)) if settings.SITE.project_model is not None and not pv.project and self.project: t.append(str(self.project)) # if u is None: # return "{} {}".format(t, self.room) if self.room else t # u = u.initials or u.username or str(u) return E.span(" ".join(t))
def gen_insert_button(actor, header_items, Event, ar, target_day): """Hackish solution to not having to recreate a new sub request when generating lots of insert buttons. Stores values in the actor as a cache, and uses id(ar) to check if it's a new request and needs updating. Works by replacing known unique value with the correct known value for the insert window.""" if ar.get_user().authenticated: if (getattr(actor, "insert_button", None) is not None and actor.insert_button_ar_id == id(ar)): insert_button = actor.insert_button.__copy__() else: # print("Making button") sar = Event.get_default_table().insert_action.request_from(ar) # print(20170217, sar) sar.known_values = dict(start_date="PLACEHOLDER") actor.insert_button = sar.ar2button(None, # _(" Reply "), icon_name=None ) actor.insert_button_ar_id = id(ar) insert_button = actor.insert_button.__copy__() insert_button.set( "href", insert_button.get("href").replace("PLACEHOLDER", str(target_day))) insert_button = E.span(insert_button, style="float: right;") header_items.append(insert_button) # btn.set("style", "padding-left:10px") return header_items
def get_calview_div(cls, obj, ar): """Return a <div> for this calendar entry in the view given by ar. """ time_text = "" if obj.start_time: time_text = "{} ".format(obj.start_time)[:5] # text = E.span(*cls.get_calview_chunks(obj, ar)) text = E.span(time_text, " ", *obj.get_event_summary(ar)) color = obj.get_diplay_color() if color: dot = E.span("\u00A0", CLASS="dot", style="background-color: {};".format(color)) # ele.attrib['style'] = "color: white;background-color: {};".format(data_color) # dot.attrib['style'] = "background-color: {};".format(data_color) return E.div(dot, text) else: return E.div(text)
def get_question_html(obj, ar): if obj.question.number: txt = obj.question.NUMBERED_TITLE_FORMAT % (obj.question.number, obj.question.title) else: txt = obj.question.title attrs = {} 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 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 = {} if obj.question.details: attrs.update(title=obj.question.details) if obj.question.is_heading: txt = E.b(txt, **attrs) return ar.html_text(E.span(txt, **attrs))
def get_table_summary(self, obj, ar): """Customized :meth:`summary view <lino.core.actors.Actor.get_table_summary>` for this table. """ sar = self.request_from(ar, master_instance=obj) html = [] states = {} for s, d in VoteStates.choices: states[s] = [] u = ar.get_user() for o in sar: states[o.state].append( ar.obj2html(o, o.user.initials or str(o.user), title=o.state)) if u == o.user: html.insert( 0, E.span( E.b(str(o.state)), u" \u2192 ", *join_elems([ sar.action_button(ba, o) for ba in sar.actor.get_actions() if ba.action.show_in_workflow and sar.actor.get_row_permission(o, sar, o.state, ba) and isinstance(ba.action, dd.ChangeStateAction) ], " "))) html.append( E.ul(*[ E.li(*([str(s.text), ": "] + join_elems(states[s], sep=", "))) for s, c in VoteStates.choices if states[s] ])) # print(tostring(html)) # items = [ # ar.obj2html(o, o.user.username or str(o.user)) # for o in rt.models.votes.Vote.objects.filter( # votable=obj).order_by('-id')] # sar.get_user() == v.user sar = self.insert_action.request_from(sar) if sar.get_permission(): # btn = sar.ar2button(None, _("Add voter"), icon_name=None) btn = sar.ar2button() # btn = sar.ar2button(None, u"⏍", icon_name=None) # 23CD SQUARE FOOT # btn = sar.ar2button(None, u"⊞", icon_name=None) # 229e SQUARED PLUS html.append(E.div(btn)) return ar.html_text(E.div(*html))
def description(self, obj, ar): # pv = dict(start_date=obj.day, end_date=obj.day) # pv.update(observed_event=dd.PeriodEvents.active) # pv.update(user=ar.param_values.user) # sar = ar.spawn(MySessionsByDate, param_values=pv) elems = [obj.sar.ar2button(label=six.text_type(obj))] tickets = [ ar.obj2html(t, "#{0}".format(t.id), title=t.summary) for t in obj._tickets] if len(tickets) > 0: elems.append(" (") elems += join_elems(tickets, ', ') elems.append(")") return E.span(*elems)
def get_html_chunks(self, level=1): h = headertag(level) if self.title: yield h(self.title) level += 1 h = headertag(level) #~ for v in Verse.objects.filter(section=self).order_by('seqno'): for v in VerseText.objects.filter(section=self): yield E.span(v.text) for s in Section.objects.filter(parent=self).order_by('seqno'): for chunk in s.get_html_chunks(level): yield chunk
def get_table_summary(self, obj, ar): if ar is None: return '' elems = [] # 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)] # Active sessions: active_sessions = [] session_summaries = E.ul() qs = rt.models.working.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) if ses.summary: session_summaries.insert(0, E.li( "%s %s: %s"%(ses.user, naturaltime(datetime.combine( ses.start_date, ses.start_time)) ,ses.summary) ) ) # 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, ', '))) if len(session_summaries) > 0: elems.append(session_summaries) return ar.html_text(E.div(*elems))
def get_table_summary(self, obj, ar): """Customized :meth:`summary view <lino.core.actors.Actor.get_table_summary>` for this table. """ sar = self.request_from(ar, master_instance=obj) html = [] states = {} for s, d in VoteStates.choices: states[s] = [] u = ar.get_user() for o in sar: states[o.state].append(ar.obj2html(o, o.user.initials or str(o.user), title=o.state)) if u == o.user: html.insert(0, E.span( E.b(str(o.state)), u" \u2192 ", *join_elems([sar.action_button(ba, o) for ba in sar.actor.get_actions() if ba.action.show_in_workflow and sar.actor.get_row_permission(o, sar, o.state, ba) and isinstance(ba.action, dd.ChangeStateAction)], " ") )) html.append(E.ul( *[E.li(*([str(s.text), ": "] + join_elems(states[s], sep=", "))) for s, c in VoteStates.choices if states[s] ] )) # print(tostring(html)) # items = [ # ar.obj2html(o, o.user.username or str(o.user)) # for o in rt.models.votes.Vote.objects.filter( # votable=obj).order_by('-id')] # sar.get_user() == v.user sar = self.insert_action.request_from(sar) if sar.get_permission(): # btn = sar.ar2button(None, _("Add voter"), icon_name=None) btn = sar.ar2button() # btn = sar.ar2button(None, u"⏍", icon_name=None) # 23CD SQUARE FOOT # btn = sar.ar2button(None, u"⊞", icon_name=None) # 229e SQUARED PLUS html.append(E.div(btn)) return ar.html_text(E.div(*html))
def welcome_messages(ar): """Yield messages for the welcome page.""" #todo show all users active sessions Session = rt.models.working.Session # Ticket = rt.models.tickets.Ticket # TicketStates = rt.models.tickets.TicketStates me = ar.get_user() # your open sessions (i.e. those you are busy with) qs = Session.objects.filter(end_time__isnull=True) working = {me: [E.b(str(_("You are busy with ")))]} if qs.count() == 0: return for ses in qs: if ses.user not in working: working[ses.user] = [ ar.obj2html(ses.user), gettext(" is working on: ") ] txt = str(ses.ticket) working[ses.user].append( ar.obj2html(ses.ticket, txt, title=getattr(ses.ticket, 'summary', "") or getattr(ses.ticket, 'name', ""))) if ses.user == me: working[ses.user] += [ ' (', ar.instance_action_button(ses.end_session, EndTicketSession.label), ')' ] working[ses.user].append(', ') if len(working[me]) > 1: working[me][-1] = working[me][-1].replace(", ", ".") result = E.p(*working.pop(me)) else: result = E.p() working.pop(me) for u, s in working.items(): if len(result): result.append(E.br()) s[-1] = s[-1].replace(", ", ".") result.append(E.span(*s)) yield result
def get_table_summary(self, obj, ar): if ar is None: return '' elems = [] # 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)] # Active sessions: active_sessions = [] session_summaries = E.ul() qs = rt.models.working.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) if ses.summary: session_summaries.insert( 0, E.li("%s %s: %s" % (ses.user, naturaltime( datetime.combine(ses.start_date, ses.start_time)), ses.summary))) # 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, ', '))) if len(session_summaries) > 0: elems.append(session_summaries) return ar.html_text(E.div(*elems))
def worked_tickets(self, obj, ar): # pv = dict(start_date=obj.day, end_date=obj.day) # pv.update(observed_event=dd.PeriodEvents.active) # pv.update(user=ar.param_values.user) # sar = ar.spawn(MySessionsByDate, param_values=pv) # elems = [obj.sar.ar2button(label=six.text_type(obj))] elems = [] tickets = [ ar.obj2html(t, "#{0}".format(t.id), title=t.summary) for t in obj._tickets ] if len(tickets) > 0: # elems.append(" (") elems += join_elems(tickets, ', ') # elems.append(")") return E.span(*elems)
def needed_skills(self, ar): """Displays a list of needed skills. This means: all skill demands for this object. """ if ar is None: return '' if not isinstance(self, dd.plugins.skills.demander_model): return '' Demand = rt.models.skills.Demand elems = [] for dem in Demand.objects.filter(demander=self): elems.append(dem.skill.obj2href(ar)) elems = join_elems(elems, ', ') return E.span(*elems)
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.models.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 welcome_messages(ar): def fmt(model, pk): try: obj = model.objects.get(pk=pk) except model.DoesNotExist: return "{}{}".format(model.__name__, pk) return ar.obj2html(obj) up = ar.get_user().get_preferences() if len(up.locked_rows): chunks = [ ugettext("You have a dangling edit lock on"), " "] chunks += join_elems( [fmt(m, pk) for m, pk in up.locked_rows], ", ") 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.models.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 unicode(obj.owner)) for obj in qs]) chunks.append('.') yield E.span(*chunks)
def welcome_messages(ar): def fmt(model, pk): try: obj = model.objects.get(pk=pk) except model.DoesNotExist: return "{}{}".format(model.__name__, pk) return ar.obj2html(obj) up = ar.get_user().get_preferences() if len(up.locked_rows): chunks = [ ugettext("You have a dangling edit lock on"), " " ] chunks += join_elems( [fmt(m, pk) for m, pk in up.locked_rows], ", ") 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, is_on_main_actor=False) # print(20170731, sar.is_on_main_actor) 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.models.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 ar.html_text(E.span(*join_elems(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) # ia = obj.response.toggle_choice sar = obj.response.toggle_choice.request_from(ar, is_on_main_actor=False) # print(20170731, sar.is_on_main_actor) 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.models.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 ar.html_text(E.span(*join_elems(elems)))
def welcome_messages(ar): """Yield messages for the welcome page.""" #todo show all users active sessions Session = rt.models.working.Session # Ticket = rt.models.tickets.Ticket # TicketStates = rt.models.tickets.TicketStates me = ar.get_user() # your open sessions (i.e. those you are busy with) qs = Session.objects.filter(end_time__isnull=True) working = {me:[E.b(six.text_type(_("You are busy with ")))]} if qs.count() == 0: return for ses in qs: if ses.user not in working: working[ses.user] = [ar.obj2html(ses.user), gettext(" is working on: ")] txt = six.text_type(ses.ticket) working[ses.user].append( ar.obj2html(ses.ticket, txt, title=getattr(ses.ticket,'summary',"") or getattr(ses.ticket,'name',""))) if ses.user == me: working[ses.user] += [ ' (', ar.instance_action_button( ses.end_session, EndTicketSession.label), ')'] working[ses.user].append(', ') if len(working[me]) > 1: working[me][-1] = working[me][-1].replace(", ", ".") result = E.p(*working.pop(me)) else: result = E.p() working.pop(me) for u, s in working.items(): if len(result): result.append(E.br()) s[-1] = s[-1].replace(", ", ".") result.append(E.span(*s)) yield result
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 " df = actor.get_disabled_fields(obj, ar) # print(20170909, df) 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 ba.action.action_name not in df: 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_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( config.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(u"{} {}".format(state.button_text, state))) 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 " df = actor.get_disabled_fields(obj, ar) # print(20170909, df) 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 ba.action.action_name not in df: 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_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( config.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 workflow_buttons(self, ar, **kwargs): if ar is None: return '' l = super(Deployment, self).get_workflow_buttons(ar) sar = rt.models.comments.CommentsByRFC.insert_action.request_from(ar) owner = ContentType.objects.get(app_label='tickets', model="ticket") # sar.bound_action.icon_name = None # sar.bound_action.label = _(" New Comment") sar.known_values.update( owner_id=self.ticket.id, owner_type=owner, # owner=self.ticket, user=ar.get_user()) if sar.get_permission(): l.append(E.span(u", ")) l.append(sar.ar2button(icon_name=None, label=_("New Comment"))) # print self.E.tostring(l) return l
def workflow_buttons(self, ar, **kwargs): if ar is None: return '' l = super(Deployment, self).get_workflow_buttons(ar) sar = rt.models.comments.CommentsByRFC.insert_action.request_from(ar) owner = ContentType.objects.get(app_label='tickets', model="ticket") # sar.bound_action.icon_name = None # sar.bound_action.label = _(" New Comment") sar.known_values.update( owner_id=self.ticket.id, owner_type=owner, # owner=self.ticket, user=ar.get_user() ) if sar.get_permission(): l.append(E.span(u", ")) l.append(sar.ar2button(icon_name=None, label=_("New Comment"))) # print self.E.tostring(l) return l
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 navigation_panel(cls, obj, ar): day_view = bool(cls.navigation_mode == 'day') weekly_view = bool(cls.navigation_mode == 'week') month_view = bool(cls.navigation_mode == 'month') # todo ensure that the end of the month is always in the view. today = obj.date daily, weekly, monthly = make_link_funcs(ar) long_unit = DurationUnits.years if month_view else DurationUnits.months prev_month = Day(date2pk(long_unit.add_duration(today, -1))) next_month = Day(date2pk(long_unit.add_duration(today, 1))) next_unit = DurationUnits.weeks if weekly_view else DurationUnits.days if day_view else DurationUnits.months prev_view = Day(date2pk(next_unit.add_duration(today, -1))) next_view = Day(date2pk(next_unit.add_duration(today, 1))) # current_view = weekly if weekly_view else daily current_view = daily if not day_view: current_view = monthly if month_view else weekly elems = [] #cls.calender_header(ar) # Month div rows, cells = [], [] for i, month in enumerate(YearMonths.get_list_items()): # each week is a list of seven datetime.date objects. pk = date2pk( DurationUnits.months.add_duration( today, int(month.value) - today.month)) if today.month == int(month.value): if not month_view: cells.append(E.td(E.b(monthly(Day(pk), str(month))))) else: cells.append(E.td(E.b(str(month)))) else: cells.append(E.td(monthly(Day(pk), str(month)))) if (i + 1) % 3 == 0: rows.append(E.tr(*cells, align="center")) cells = [] monthly_div = E.div(E.table(*rows, align="center"), CLASS="cal-month-table") header = [ current_view(prev_month, "<<"), " ", current_view(prev_view, "<"), E.span( E.span("{} {}".format(monthname(today.month), today.year), E.br(), monthly_div)), current_view(next_view, ">"), " ", current_view(next_month, ">>") ] elems.append(E.h2(*header, align="center")) weekdaysFirstLetter = " " + "".join( [gettext(week.text)[0] for week in Weekdays.objects()]) rows = [ E.tr(*[ E.td(E.b(day_of_week)) for day_of_week in weekdaysFirstLetter ], align='center') ] for week in CALENDAR.monthdatescalendar(today.year, today.month): # each week is a list of seven datetime.date objects. cells = [] current_week = week[0].isocalendar()[1] this_week = False for day in week: pk = date2pk(day) link = daily(Day(pk), str(day.day)) if day == dd.today(): link = E.b(link, CLASS="cal-nav-today") if day == today and day_view: cells.append(E.td(E.b(str(day.day)))) else: cells.append(E.td(link)) if day.isocalendar()[1] == today.isocalendar()[1]: this_week = True else: cells = [ E.td(E.b(str(current_week)) if this_week and weekly_view else weekly(Day(pk), str(current_week)), CLASS="cal-week") ] + cells rows.append(E.tr(*cells, align="center")) elems.append(E.table(*rows, align="center")) elems.append(E.p(daily(Day(), gettext("Today")), align="center")) elems.append(E.p(weekly(Day(), gettext("This week")), align="center")) elems.append(E.p(monthly(Day(), gettext("This month")), align="center")) # for o in range(-10, 10): # elems.append(ar.goto_pk(o, str(o))) # elems.append(" ") return E.div(*elems, CLASS="lino-nav-cal")
def table2html(ar, as_main=True): """Represent the given table request as an HTML table. `ar` is the request to be rendered, an instance of :class:`lino.core.tablerequest.TableRequest`. The returned HTML enclosed in a ``<div>`` tag and generated using :mod:`etgen.html`. If `as_main` is True, include additional elements such as a paging toolbar. (This argument is currently being ignored.) """ # as_main = True t = xghtml.Table() t.attrib.update(**{'class':"table table-striped table-hover"}) if ar.limit is None: ar.limit = PLAIN_PAGE_LENGTH pglen = ar.limit if ar.offset is None: page = 1 else: """ (assuming pglen is 5) offset page 0 1 5 2 """ page = int(old_div(ar.offset, pglen)) + 1 ar.dump2html(t, ar.sliced_data_iterator, header_links=as_main) if not as_main: url = ar.get_request_url() # open in own window return E.div( E.div( E.div( E.a( E.span(**{'class':"glyphicon glyphicon-folder-open"}), href=url, style="margin-left: 4px;", **{'class':"btn btn-default pull-right"}), E.h5(ar.get_title(), style="display: inline-block;"), **{'class': "panel-title"}), **{'class':"panel-heading"}), t.as_element(), style="display: inline-block;", **{'class':"panel panel-default"}) buttons = [] kw = dict() kw = {} if pglen != PLAIN_PAGE_LENGTH: kw[constants.URL_PARAM_LIMIT] = pglen if page > 1: kw[constants.URL_PARAM_START] = pglen * (page - 2) prev_url = ar.get_request_url(**kw) kw[constants.URL_PARAM_START] = 0 first_url = ar.get_request_url(**kw) else: prev_url = None first_url = None buttons.append(('<<', _("First page"), first_url)) buttons.append(('<', _("Previous page"), prev_url)) next_start = pglen * page if next_start < ar.get_total_count(): kw[constants.URL_PARAM_START] = next_start next_url = ar.get_request_url(**kw) last_page = int(old_div((ar.get_total_count() - 1), pglen)) kw[constants.URL_PARAM_START] = pglen * last_page last_url = ar.get_request_url(**kw) else: next_url = None last_url = None buttons.append(('>', _("Next page"), next_url)) buttons.append(('>>', _("Last page"), last_url)) return E.div(buttons2pager(buttons), t.as_element())
def get_table_summary(self, obj, ar): if obj is None: return UploadType = rt.models.uploads.UploadType # Upload = rt.models.uploads.Upload elems = [] types = [] perm = ar.get_user().user_type.has_required_roles(self.required_roles) qs = UploadType.objects.all() if isinstance(obj, UploadController): area = obj.get_upload_area() if area is not None: qs = qs.filter(upload_area=area) else: return E.div("{} is not an UploadController!".format( model_class_path(obj.__class__))) volume = obj.get_uploads_volume() # print(20190208, volume) for ut in qs: 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: url = settings.SITE.build_media_url(m.file.name) elif m.volume_id and m.volume.base_url and m.library_file: url = m.volume.base_url + m.library_file else: url = None if url: show = ar.renderer.href_button( url, # 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 file in a new browser window")) # title=_("Open the uploaded file in a new browser window")) # logger.info("20140430 %s", 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, volume=volume)).ar2button() if btn is not None: files.append(btn) if len(files) > 0: chunks = (str(ut), ': ') + tuple(join_elems(files, ', ')) types.append(chunks) # logger.info("20140430 %s", [tostring(e) for e in types]) # elems += [str(ar.bound_action.action.__class__), " "] if ar.bound_action.action.window_type == "d": if len(types) == 0: elems.append(E.ul(E.li(str(ar.no_data_text)))) else: elems.append(E.ul(*[E.li(*chunks) for chunks in types])) else: if len(types) == 0: elems.append(str(ar.no_data_text)) elems.append(" / ") else: for chunks in types: elems.extend(chunks) elems.append(" / ") elems.append(obj.show_uploads.as_button_elem(ar)) # ba = self.find_action_by_name("show_uploads") return E.div(*elems)
def table2html(ar, as_main=True): """Represent the given table request as an HTML table. `ar` is the request to be rendered, an instance of :class:`lino.core.tablerequest.TableRequest`. The returned HTML enclosed in a ``<div>`` tag and generated using :mod:`etgen.html`. If `as_main` is True, include additional elements such as a paging toolbar. (This argument is currently being ignored.) """ # as_main = True t = xghtml.Table() t.attrib.update(**{'class': "table table-striped table-hover"}) if ar.limit is None: ar.limit = PLAIN_PAGE_LENGTH pglen = ar.limit if ar.offset is None: page = 1 else: """ (assuming pglen is 5) offset page 0 1 5 2 """ page = int(old_div(ar.offset, pglen)) + 1 ar.dump2html(t, ar.sliced_data_iterator, header_links=as_main) if not as_main: url = ar.get_request_url() # open in own window return E.div(E.div( E.div( E.a(E.span(**{'class': "glyphicon glyphicon-folder-open"}), href=url, style="margin-left: 4px;", **{'class': "btn btn-default pull-right"}), E.h5(ar.get_title(), style="display: inline-block;"), **{'class': "panel-title"}), **{'class': "panel-heading"}), t.as_element(), style="display: inline-block;", **{'class': "panel panel-default"}) buttons = [] kw = dict() kw = {} if pglen != PLAIN_PAGE_LENGTH: kw[constants.URL_PARAM_LIMIT] = pglen if page > 1: kw[constants.URL_PARAM_START] = pglen * (page - 2) prev_url = ar.get_request_url(**kw) kw[constants.URL_PARAM_START] = 0 first_url = ar.get_request_url(**kw) else: prev_url = None first_url = None buttons.append(('<<', _("First page"), first_url)) buttons.append(('<', _("Previous page"), prev_url)) next_start = pglen * page if next_start < ar.get_total_count(): kw[constants.URL_PARAM_START] = next_start next_url = ar.get_request_url(**kw) last_page = int(old_div((ar.get_total_count() - 1), pglen)) kw[constants.URL_PARAM_START] = pglen * last_page last_url = ar.get_request_url(**kw) else: next_url = None last_url = None buttons.append(('>', _("Next page"), next_url)) buttons.append(('>>', _("Last page"), last_url)) return E.div(buttons2pager(buttons), t.as_element())
def get_table_summary(self, obj, ar): """The :meth:`summary view <lino.core.actors.Actor.get_table_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(other.obj2href(ar)) items = [] for lnktype, lst in tbt.items(): items.append(E.li(str(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] if self.insert_action is not None and ar.renderer.is_interactive: sar = self.insert_action.request_from(ar) if 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_table_summary(self, obj, ar): """The :meth:`summary view <lino.core.actors.Actor.get_table_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(other.obj2href(ar)) 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] if self.insert_action is not None and ar.renderer.is_interactive: sar = self.insert_action.request_from(ar) if 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 navigation_panel(cls, obj, ar): if ar is None: return None # if ar.actor.navigator is None: # # raise Exception("Oops, {} has no navigator".format(cls)) # print("Oops, {} has no navigator".format(cls)) # return None today = obj.date # daily, weekly, monthly = obj.cal_view.navigator.make_link_funcs(ar) daily = obj.planner.daily_button_func(ar) weekly = obj.planner.weekly_button_func(ar) monthly = obj.planner.monthly_button_func(ar) if obj.navigation_mode == 'day': long_unit = DurationUnits.months short_unit = DurationUnits.days current_view = daily elif obj.navigation_mode == 'week': long_unit = DurationUnits.months short_unit = DurationUnits.weeks current_view = weekly elif obj.navigation_mode == 'month': long_unit = DurationUnits.years short_unit = DurationUnits.months current_view = monthly else: raise Exception("20200224") daily_mode = bool(obj.navigation_mode == 'day') weekly_mode = bool(obj.navigation_mode == 'week') month_mode = bool(obj.navigation_mode == 'month') # todo ensure that the end of the month is always in the view. # long_unit = DurationUnits.years if month_mode else DurationUnits.months long_prev = cls.get_row_by_pk( ar, date2pk(long_unit.add_duration(today, -1))) long_next = cls.get_row_by_pk( ar, date2pk(long_unit.add_duration(today, 1))) # next_unit = DurationUnits.weeks if weekly_mode else DurationUnits.days if day_view else DurationUnits.months short_prev = cls.get_row_by_pk( ar, date2pk(short_unit.add_duration(today, -1))) short_next = cls.get_row_by_pk( ar, date2pk(short_unit.add_duration(today, 1))) # current_view = weekly if weekly_mode else daily # current_view = daily # if not day_view: # current_view = monthly if month_mode else weekly elems = [] #cls.calender_header(ar) # Month div rows, cells = [], [] for i, month in enumerate(YearMonths.get_list_items()): pk = date2pk( DurationUnits.months.add_duration(today, i + 1 - today.month)) if today.month == i + 1: if not month_mode: cells.append( E.td( E.b(monthly(cls.get_row_by_pk(ar, pk), str(month))))) else: cells.append(E.td(E.b(str(month)))) else: cells.append( E.td(monthly(cls.get_row_by_pk(ar, pk), str(month)))) if (i + 1) % 3 == 0: rows.append(E.tr(*cells, align="center")) cells = [] monthly_div = E.div(E.table(*rows, align="center"), CLASS="cal-month-table") header = [ current_view(long_prev, "<<"), " ", current_view(short_prev, "<"), E.span( E.span("{} {}".format(monthname(today.month), today.year), E.br(), monthly_div)), current_view(short_next, ">"), " ", current_view(long_next, ">>") ] elems.append(E.h2(*header, align="center")) weekdaysFirstLetter = " " + "".join( [gettext(week.text)[0] for week in Weekdays.objects()]) rows = [ E.tr(*[ E.td(E.b(day_of_week)) for day_of_week in weekdaysFirstLetter ], align='center') ] for week in CALENDAR.monthdatescalendar(today.year, today.month): # each week is a list of seven datetime.date objects. cells = [] current_week = week[0].isocalendar()[1] this_week = False for day in week: pk = date2pk(day) link = daily(cls.get_row_by_pk(ar, pk), str(day.day)) if day == dd.today(): link = E.b(link, CLASS="cal-nav-today") if day == today and daily_mode: cells.append(E.td(E.b(str(day.day)))) else: cells.append(E.td(link)) if day.isocalendar()[1] == today.isocalendar()[1]: this_week = True else: if this_week and weekly_mode: txt = E.b(str(current_week)) else: pk = date2pk(week[0]) txt = weekly(cls.get_row_by_pk(ar, pk), str(current_week)) cells = [E.td(txt, CLASS="cal-week")] + cells rows.append(E.tr(*cells, align="center")) today = cls.get_row_by_pk(ar, 0) elems.append(E.table(*rows, align="center")) elems.append(E.p(daily(today, gettext("Today")), align="center")) elems.append(E.p(weekly(today, gettext("This week")), align="center")) elems.append(E.p(monthly(today, gettext("This month")), align="center")) # for o in range(-10, 10): # elems.append(ar.goto_pk(o, str(o))) # elems.append(" ") return E.div(*elems, CLASS="lino-nav-cal")
def mti_navigator(self, ar): buttons = self.get_mti_buttons(ar) return E.span(*buttons)
def get_table_summary(self, obj, ar): if obj is None: return UploadType = rt.models.uploads.UploadType # Upload = rt.models.uploads.Upload elems = [] types = [] perm = ar.get_user().user_type.has_required_roles(self.required_roles) qs = UploadType.objects.all() if isinstance(obj, UploadController): area = obj.get_upload_area() if area is not None: qs = qs.filter(upload_area=area) else: return E.div("{} is not an UploadController!".format( model_class_path(obj.__class__))) volume = obj.get_uploads_volume() # print(20190208, volume) for ut in qs: 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: url = settings.SITE.build_media_url(m.file.name) elif m.volume_id and m.volume.base_url and m.library_file: url = m.volume.base_url + m.library_file else: url = None if url: show = ar.renderer.href_button( url, # 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 file in a new browser window")) # title=_("Open the uploaded file in a new browser window")) # logger.info("20140430 %s", 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, volume=volume)).ar2button() if btn is not None: files.append(btn) if len(files) > 0: chunks = (str(ut), ': ') + tuple(join_elems(files, ', ')) types.append(chunks) # logger.info("20140430 %s", [tostring(e) for e in types]) # elems += [str(ar.bound_action.action.__class__), " "] if ar.bound_action.action.window_type == "d": if len(types) == 0: elems.append(E.ul(E.li(str(ar.no_data_text)))) else: elems.append(E.ul(*[E.li(*chunks) for chunks in types])) else: if len(types) == 0: elems.append(str(ar.no_data_text)) elems.append(" / ") else: for chunks in types: elems.extend(chunks) elems.append(" / ") elems.append(obj.show_uploads.as_button_elem(ar)) # ba = self.find_action_by_name("show_uploads") return E.div(*elems)
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 get_table_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`. """ if obj is None: return UploadType = rt.models.uploads.UploadType # Upload = rt.models.uploads.Upload elems = [] types = [] perm = ar.get_user().user_type.has_required_roles(self.required_roles) qs = UploadType.objects.all() if isinstance(obj, UploadController): area = obj.get_upload_area() if area is not None: qs = qs.filter(upload_area=area) else: raise Exception("A {} is not an UploadController!".format( obj.__class__)) for ut in qs: 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", 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", [tostring(e) for e in types]) if len(types) == 0: elems.append(E.ul(E.li(str(ar.no_data_text)))) else: elems.append(E.ul(*[E.li(e) for e in types])) return E.div(*elems)