• on_user_change and after_ui_save are two solutions for the same problem. Can replace after_ui_save with on_user_change, but on_user_change should receive the complete ar, not only the web request.

–> Replaced on_user_change by new method lino.core.modeltools.Model.before_ui_save(). And we now call it from lino.ui.extjs3.ext_ui.ExtUI.form2obj_and_save() and no longer from lino.utils.dblogger (who is responsible just for logging: e.g. it is also used by watch_tim which cannot be considered as a user change).

  • Bugfix: Calling “Act as…” from the Calendar Panel doesn’t work.

Caused a “Uncaught TypeError: Object [object Object] has no method ‘set_base_param’” in JS console.

Calendar workflow

Event state “suggested” now means that your colleague has fixed a rendez-vous in your name with a client, the client is informed and you must confirm that the date/time suits you. If it doesn’t, you are responsible for contacting the client and finding a new date/time.

Writing end-user documentation

I started a user documentation page for the calendar module: /pcsw/calendrier. But this page obviously is another example of why you should not ask the developer of a framework to write end-user documentation for one of the applications developed using that framework.

I got stuck when I had the feeling that now I should add some screenshots, and I wanted them to be in French, of course. Instead of screenshots, Lino has now a series of subtle optimizations and bugfixes which are useful only in multilingual sites:

Automatic events and tasks are now generated in the user’s language. cal.PanelCalendars now returns calendar descriptions in the user’s language. Users now inherit the language of their partner (if they have one). The messages in linolib.js hadn’t been extracted during the last 5 months.

Or a funny little problems like with this excerpt from /lino/ui/extjs3/linolib.js:

config.bbar = config.bbar.concat([
  { text: '[$_("Help Text Editor")]',
    handler: Lino.help_text_editor,
    qtip: "$_('Edit help texts for fields on this model.')",
    scope: this}

(And the French for “Help Text Editor” is “Editeur textes d’aide”. Do you guess why there was a Javascript syntax error after translating?)

Another subtile bug was:

  • Event.summary_row generated the following link which was supposed to open the detail window on that event:

    javascript:Lino.cal.Events.detail_action.run({ "record_id": 238 })

    That worked for system admins, but normal users don’t have Lino.cal.Events (seeing all Events at once is reserved to managers).

Lino now links to the detail action of MyEvents. lino.modlib.cal.reminders() manually adds a _detail_action attribute to each instance which is detected by instance_handler. This solution is not beautiful, but works at least.

instance_handler now also tests whether the user has permission to execute that detail handler. For example the user names in jobs.UsersWithClients are no longer clickable for normal users because only system administrators may see the detail of other users.

And this one took me also quite some time:

  • Buttons “Save” and “Delete” are displayed in German also for French users.

It was simply due to the fact that lino.core.actions used ugettext and not ugettext_lazy as _:

# from django.utils.translation import ugettext as _
from django.utils.translation import ugettext_lazy as _

But the most difficult and not yet solved problem is: the Ext.ensible CalendarPanel translates “Calendar” to “Agenda” in French…