Saturday, March 7, 2020

Customized calendar views

Uff! Seems that I can finally publish my work for #3502 (Customized calendar views). More than 30 hours of work, distributed over one month. The lino_presto.lib.contacts plugin is our first usage example. It introduces a second “planner” which, unlike the default planner shows the workers instead of the time slots as the rows of the weekly and daily views. The new workers planner has no monthly view because that wouldn’t make sense.

Here is a summary of my manual test suite:

  • team : check whether WorkedHours is being displayed in the dashboard and contains data. robin didn’t work, so he has no hours, but the table is there because it is not empty. robin acting as jean would have some hours

  • lydia : a standard calendar view with events.

  • noereth : here we have two “calendar view” entries in the Calendar menu.

  • mathieu : is the daily planner in the dashboard?

For each calendar view : check whether insert buttons are at the right place and open a correct insert dialog. Check whether clicking on an event opens that event. Check whether navigation works in general.

TODO:

  • rename DailyPlannerRow model to TimeSlot?

  • write documentation

  • Workers calendar in presto has no monthly view, so the month header should not have a popup div for selecting another month

  • customize the title tags of individual calendar entries

  • customize the text to show per event

  • switch between the two planners (e.g. from the general weekly view in a given week to the workers view in that same week)

New features in the framework:

New method lino.core.tablerequest.TableRequest.gen_insert_button() is a generalized and no longer hackerish implementation of the hackerish solution used in the monthly view until now.

When the label of a table is None, the ExtJS front-end now suppresses the header of the grid panel (including the “open in own window” button). This is used by the slave tables in the detail layouts of the calendar views. But note that you cannot simply set label = None on the actor because that default value is overridden by the model’s verbose_name_plural. So to get an actor without label you be more explicit and say:

@classmethod
def get_actor_label(cls):
    return None