class Messages(dd.Table): model = 'notify.Message' column_names = "created subject user seen sent *" # cell_edit = False card_layout = """ user seen subject workflow_buttons """ # detail_layout = dd.DetailLayout(""" # created user seen sent owner # overview # """, window_size=(50, 15)) parameters = ObservedDateRange( # user=dd.ForeignKey( # settings.SITE.user_model, # blank=True, null=True), show_seen=dd.YesNo.field(_("Seen"), blank=True), ) params_layout = "user show_seen start_date end_date" # @classmethod # def get_simple_parameters(cls): # for p in super(Messages, cls).get_simple_parameters(): # yield p # yield 'user' @classmethod def get_request_queryset(self, ar, **filter): qs = super(Messages, self).get_request_queryset(ar, **filter) pv = ar.param_values if pv.show_seen == dd.YesNo.yes: qs = qs.filter(seen__isnull=False) elif pv.show_seen == dd.YesNo.no: qs = qs.filter(seen__isnull=True) return qs @classmethod def get_title_tags(self, ar): for t in super(Messages, self).get_title_tags(ar): yield t pv = ar.param_values if pv.show_seen: yield str(pv.show_seen) @classmethod def unused_get_detail_title(self, ar, obj): """This was used to set `seen` automatically when a detail was shown. """ if obj.seen is None and obj.user == ar.get_user(): obj.seen = timezone.now() obj.save() # dd.logger.info("20151115 Marked %s as seen", obj) return super(Messages, self).get_detail_title(ar, obj)
class DayNavigator(DaysTable): """ Base class for the three calendar views, but also used for independent tables like working.WorkedHours. A virtual table whose rows are calview.Day instances. Subclasses must set navigation_mode. """ # every row is a Day instance. Note that Day can be overridden. abstract = True editable = False # required_roles = dd.login_required((OfficeUser, OfficeOperator)) required_roles = dd.login_required(OfficeUser) parameters = ObservedDateRange( user=dd.ForeignKey('users.User', null=True, blank=True)) column_names = "detail_link *" params_panel_hidden = False display_mode = "html" # hide_top_toolbar = True planner = None # must be set for concrete subclasses @classmethod def get_navinfo(cls, ar, day): assert isinstance(day, Day) day.navigation_mode = cls.navigation_mode # so that str() gives the right format ni = dict(recno=day.pk, message=str(day)) if cls.navigation_mode == "month": ni.update(next=date2pk(day.skipmonth(1))) ni.update(prev=date2pk(day.skipmonth(-1))) ni.update(first=day.pk - 365) ni.update(last=day.pk + 365) elif cls.navigation_mode == "week": ni.update(next=day.pk + 7) ni.update(prev=day.pk - 7) ni.update(first=date2pk(day.skipmonth(-1))) ni.update(last=date2pk(day.skipmonth(1))) elif cls.navigation_mode == "day": ni.update(next=day.pk + 1) ni.update(prev=day.pk - 1) ni.update(first=date2pk(day.skipmonth(-1))) ni.update(last=date2pk(day.skipmonth(1))) else: raise Exception("Invalid navigation_mode {}".format( cls.navigation_mode)) return ni @dd.virtualfield(models.IntegerField(_("Day number"))) def day_number(cls, obj, ar): return obj.pk @classmethod def get_pk_field(cls): # return pk_field # return PK_FIELD # return cls.get_data_elem('day_number') return cls.day_number.return_type
class Guests(dd.Table): model = 'cal.Guest' # required_roles = dd.login_required((OfficeUser, OfficeOperator)) required_roles = dd.login_required(GuestOperator) column_names = 'partner role workflow_buttons remark event *' order_by = ['-event__start_date', '-event__start_time'] stay_in_grid = True detail_layout = "cal.GuestDetail" insert_layout = dd.InsertLayout(""" event partner role """, window_size=(60, 'auto')) parameters = ObservedDateRange( user=dd.ForeignKey(settings.SITE.user_model, verbose_name=_("Responsible user"), blank=True, null=True, help_text=_("Only rows managed by this user.")), project=dd.ForeignKey(settings.SITE.project_model, blank=True, null=True), partner=dd.ForeignKey(dd.plugins.cal.partner_model, blank=True, null=True), event_state=EntryStates.field( blank=True, verbose_name=_("Event state"), help_text=_("Only rows on calendar entries having this state.")), guest_state=GuestStates.field( blank=True, verbose_name=_("Guest state"), help_text=_("Only rows having this guest state.")), ) params_layout = """start_date end_date user event_state guest_state project partner""" @classmethod def get_table_summary(cls, obj, ar): return get_calendar_summary(cls, obj, ar) @classmethod def get_request_queryset(self, ar, **kwargs): qs = super(Guests, self).get_request_queryset(ar, **kwargs) if isinstance(qs, list): return qs pv = ar.param_values if pv.user: qs = qs.filter(event__user=pv.user) if settings.SITE.project_model is not None and pv.project: qs = qs.filter(event__project=pv.project) if pv.event_state: qs = qs.filter(event__state=pv.event_state) if pv.guest_state: qs = qs.filter(state=pv.guest_state) if pv.partner: qs = qs.filter(partner=pv.partner) # we test whether the *start_date* of event is within the # given range. Filtering guests by the end_date of their event # is currently not supported. if pv.start_date: qs = qs.filter(event__start_date__gte=pv.start_date) if pv.end_date: qs = qs.filter(event__start_date__lte=pv.end_date) return qs @classmethod def get_title_tags(self, ar): for t in super(Guests, self).get_title_tags(ar): yield t pv = ar.param_values if pv.start_date or pv.end_date: yield str( _("Dates %(min)s to %(max)s") % dict(min=pv.start_date or '...', max=pv.end_date or '...')) if pv.event_state: yield str(pv.event_state) if pv.partner: yield str(pv.partner) if pv.guest_state: yield str(pv.guest_state) # if pv.user: # yield str(pv.user) if settings.SITE.project_model is not None and pv.project: yield str(pv.project)
class Tasks(dd.Table): model = 'cal.Task' required_roles = dd.login_required(OfficeStaff) stay_in_grid = True column_names = 'priority start_date summary workflow_buttons *' order_by = ["priority", "-start_date", "-start_time"] detail_layout = """ start_date priority due_date id workflow_buttons summary user project #event_type owner created:20 modified:20 description #notes.NotesByTask """ insert_layout = dd.InsertLayout(""" summary user project """, window_size=(50, 'auto')) params_panel_hidden = True parameters = ObservedDateRange( user=dd.ForeignKey(settings.SITE.user_model, verbose_name=_("Managed by"), blank=True, null=True, help_text=_("Only rows managed by this user.")), project=dd.ForeignKey(settings.SITE.project_model, blank=True, null=True), state=TaskStates.field(blank=True, help_text=_("Only rows having this state.")), ) params_layout = """ start_date end_date user state project """ @classmethod def get_request_queryset(self, ar, **kwargs): # logger.info("20121010 Clients.get_request_queryset %s",ar.param_values) qs = super(Tasks, self).get_request_queryset(ar, **kwargs) if ar.param_values.user: qs = qs.filter(user=ar.param_values.user) if settings.SITE.project_model is not None and ar.param_values.project: qs = qs.filter(project=ar.param_values.project) if ar.param_values.state: qs = qs.filter(state=ar.param_values.state) if ar.param_values.start_date: qs = qs.filter(start_date__gte=ar.param_values.start_date) if ar.param_values.end_date: qs = qs.filter(start_date__lte=ar.param_values.end_date) return qs @classmethod def get_title_tags(self, ar): for t in super(Tasks, self).get_title_tags(ar): yield t if ar.param_values.start_date or ar.param_values.end_date: yield str( _("Dates %(min)s to %(max)s") % dict(min=ar.param_values.start_date or '...', max=ar.param_values.end_date or '...')) if ar.param_values.state: yield str(ar.param_values.state) # if ar.param_values.user: # yield str(ar.param_values.user) if settings.SITE.project_model is not None and ar.param_values.project: yield str(ar.param_values.project) @classmethod def apply_cell_format(self, ar, row, col, recno, td): """ Enhance today by making background color a bit darker. """ if row.start_date == settings.SITE.today(): td.set('bgcolor', "gold")
class Clients(contacts.Persons): model = 'avanti.Client' params_panel_hidden = True required_roles = dd.login_required(ClientsUser) column_names = "name_column:20 client_state national_id:10 \ gsm:10 address_column age:10 email phone:10 id ref:8 #language:10 *" detail_layout = 'avanti.ClientDetail' parameters = ObservedDateRange( nationality=dd.ForeignKey('countries.Country', blank=True, null=True, verbose_name=_("Nationality"))) # observed_event=ClientEvents.field(blank=True) params_layout = """ aged_from aged_to gender nationality client_state user start_date end_date #observed_event course enrolment_state client_contact_type client_contact_company """ @classmethod def get_request_queryset(self, ar): """This converts the values of the different parameter panel fields to the query filter. """ qs = super(Clients, self).get_request_queryset(ar) pv = ar.param_values # period = [pv.start_date, pv.end_date] # if period[0] is None: # period[0] = period[1] or dd.today() # if period[1] is None: # period[1] = period[0] ce = pv.observed_event if ce: qs = ce.add_filter(qs, pv) # if ce is None: # pass # elif ce == ClientEvents.active: # pass # elif ce == ClientEvents.isip: # flt = has_contracts_filter('isip_contract_set_by_client', period) # qs = qs.filter(flt).distinct() # elif ce == ClientEvents.jobs: # flt = has_contracts_filter('jobs_contract_set_by_client', period) # qs = qs.filter(flt).distinct() # elif dd.is_installed('immersion') and ce == ClientEvents.immersion: # flt = has_contracts_filter( # 'immersion_contract_set_by_client', period) # qs = qs.filter(flt).distinct() # elif ce == ClientEvents.available: # # Build a condition "has some ISIP or some jobs.Contract # # or some immersion.Contract" and then `exclude` it. # flt = has_contracts_filter('isip_contract_set_by_client', period) # flt |= has_contracts_filter('jobs_contract_set_by_client', period) # if dd.is_installed('immersion'): # flt |= has_contracts_filter( # 'immersion_contract_set_by_client', period) # qs = qs.exclude(flt).distinct() if pv.nationality: qs = qs.filter( models.Q(nationality=pv.nationality) | models.Q(nationality2=pv.nationality)) # print(20150305, qs.query) return qs @classmethod def get_title_tags(self, ar): for t in super(Clients, self).get_title_tags(ar): yield t pv = ar.param_values # if pv.observed_event: # yield str(pv.observed_event) if pv.start_date or pv.end_date: yield daterange_text(pv.start_date, pv.end_date) # @classmethod # def apply_cell_format(self, ar, row, col, recno, td): # if row.client_state == ClientStates.newcomer: # td.attrib.update(bgcolor="green") @classmethod def get_row_classes(cls, obj, ar): # if obj.client_state == ClientStates.newcomer: # yield 'green' if obj.client_state in (ClientStates.refused, ClientStates.former): yield 'yellow'
class Votes(dd.Table): """Table parameters: .. attribute:: observed_event There are two class attributes for defining a filter conditions which canot be removed by the user: .. attribute:: filter_vote_states A set of vote states to require (i.e. to filter upon). This must resolve using :meth:`resolve_states <lino.core.model.Model.resolve_states>`. .. attribute:: exclude_vote_states A set of vote states to exclude. This must resolve using :meth:`resolve_states <lino.core.model.Model.resolve_states>`. .. attribute:: filter_ticket_states A set of ticket states to require (i.e. to filter upon). This must resolve using :meth:`resolve_states <lino.core.model.Model.resolve_states>`. """ model = 'votes.Vote' order_by = ['-id'] # stay_in_grid = True required_roles = dd.login_required(VotesUser) parameters = ObservedDateRange(observed_event=VoteEvents.field(blank=True)) params_layout = """ user mail_mode state votable_state ticket_user start_date end_date observed_event exclude_ticket_user""" params_panel_hidden = True # show_detail_navigator = False # hide_top_toolbar = True detail_layout = dd.DetailLayout(""" user votable #project mail_mode priority nickname state rating """, window_size=(40, 'auto')) filter_vote_states = None exclude_vote_states = None filter_ticket_states = None # @classmethod # def on_analyze(self, site): # super(Votes, self).on_analyze(site) @classmethod def do_setup(self): # print("Votes.to_setup") self.filter_vote_states = self.model.resolve_states( self.filter_vote_states) self.exclude_vote_states = self.model.resolve_states( self.exclude_vote_states) self.filter_ticket_states = config.votable_model.resolve_states( self.filter_ticket_states) super(Votes, self).do_setup() self.detail_action.action.hide_top_toolbar = True @classmethod def get_detail_title(self, ar, obj): """Overrides the default beaviour """ me = ar.get_user() pk = obj.votable.pk if me == obj.user: return _("My vote about #{}").format(pk) else: return _("{}'s vote about #{}").format(obj.user, pk) @classmethod def get_simple_parameters(cls): s = list(super(Votes, cls).get_simple_parameters()) s.append('state') s.append('mail_mode') return s @classmethod def get_request_queryset(self, ar, **kwargs): qs = super(Votes, self).get_request_queryset(ar, **kwargs) pv = ar.param_values if self.filter_vote_states is not None: qs = qs.filter(state__in=self.filter_vote_states) if self.exclude_vote_states is not None: qs = qs.exclude(state__in=self.exclude_vote_states) if self.filter_ticket_states is not None: qs = qs.filter(votable__state__in=self.filter_ticket_states) if pv.ticket_user: qs = qs.filter(votable__user=pv.ticket_user) if pv.exclude_ticket_user: qs = qs.exclude(votable__user=pv.exclude_ticket_user) # if pv.show_todo == dd.YesNo.no: # qs = qs.exclude(state__in=VoteStates.todo_states) # elif pv.show_todo == dd.YesNo.yes: # qs = qs.filter(state__in=VoteStates.todo_states) if pv.observed_event: qs = pv.observed_event.add_filter(qs, pv) return qs @classmethod def get_title_tags(self, ar): pv = ar.param_values # if pv.vote_view: # pv.vote_view.text for t in super(Votes, self).get_title_tags(ar): yield t if pv.start_date or pv.end_date: yield daterange_text(pv.start_date, pv.end_date)
class Days(dd.VirtualTable): # every row is a Day instance. Note that Day can be overridden. # required_roles = dd.login_required((OfficeUser, OfficeOperator)) required_roles = dd.login_required(OfficeUser) column_names = "detail_link *" parameters = ObservedDateRange( user=dd.ForeignKey('users.User', null=True, blank=True)) model = 'calview.Day' editable = False navigation_mode = "day" # or "week" or "month" abstract = True @classmethod def get_navinfo(cls, ar, day): assert isinstance(day, Day) day.navigation_mode = ar.actor.navigation_mode # so that str() gives the right formar ni = dict(recno=day.pk, message=str(day)) if cls.navigation_mode == "month": ni.update(next=date2pk(day.skipmonth(1))) ni.update(prev=date2pk(day.skipmonth(-1))) ni.update(first=day.pk - 365) ni.update(last=day.pk + 365) elif cls.navigation_mode == "week": ni.update(next=day.pk + 7) ni.update(prev=day.pk - 7) ni.update(first=date2pk(day.skipmonth(-1))) ni.update(last=date2pk(day.skipmonth(1))) elif cls.navigation_mode == "day": ni.update(next=day.pk + 1) ni.update(prev=day.pk - 1) ni.update(first=date2pk(day.skipmonth(-1))) ni.update(last=date2pk(day.skipmonth(1))) else: raise Exception("Invalid navigation_mode {}".format( cls.navigation_mode)) return ni @dd.virtualfield(models.IntegerField(_("Day number"))) def day_number(cls, obj, ar): return obj.pk @classmethod def get_pk_field(cls): # return pk_field # return PK_FIELD # return cls.get_data_elem('day_number') return cls.day_number.return_type @classmethod def get_row_by_pk(cls, ar, pk): """ pk is the offset from beginning_of_time """ #if pk is None: # pk = "0" # return dd.today(int(pk)) # if ar is None: # return cls.model(int(pk)) # return cls.model(int(pk), ar.actor.navigation_mode) return cls.model(int(pk), ar, cls.navigation_mode) @classmethod def get_request_queryset(cls, ar, **filter): home = cls.get_row_by_pk(ar, 0) ni = cls.get_navinfo(ar, home) pv = ar.param_values date = pv.start_date or dd.today(ni['first']) last = pv.end_date or dd.today(ni['last']) if cls.navigation_mode == "day": step = lambda x: x + timedelta(days=1) elif cls.navigation_mode == "week": step = lambda x: x + timedelta(days=7) else: step = lambda x: DurationUnits.months.add_duration(x, 1) while date <= last: yield cls.get_row_by_pk(ar, date2pk(date)) date = step(date)