Monday, October 8, 2018¶
Row-level edit locking¶
Wow, Lino has a cool ned feature: row-level locking. This is to fix a
problem they encountered in Lino Avanti: user 1 opens the detail of
a client and starts editing the field translator_notes
. While she is still
writing, user 2 opens the same client, changes some other field
(e.g. professional_state
) and submits. One
minute later user 1 submits her translator notes. And poof, the
professional state is back to its old value.
To fix this problem, we decided that Lino should show all clients read-only by default. IOW all form fields are disabled. If somebody wants to modify something, they must first “lock” the record with a click, which enables the form fields. As soon as they hit Save the lock is released. The locking does not need to persist after a server restart (we are not launching a spaceship here).
The coding itself took only 1,5 hours. Plus two hours of meditation and surf.
New attribute lino.core.userprefs.UserPrefs.locked_rows
: a
set with a tuple (model, pk) for each row locked by this user.
A model mixin lino.modlib.system.mixins.Lockable
which adds
the two actions and the displayfield, and which extends the
after_ui_save
method to
automatically unlock the row after save. And the
disabled_fields
method
to return all fields unless the row is locked. Also the userprefs
registry is now thread-safe (it’s possible that this fixes a rather
unexplored problem that the dashboard didn’t always refresh).
Of course it’s not perfect. More ideas to improve it:
welcome message if locked_rows is not empty
currently it’s a displayfield showing either the “Lock” or the “Unlock” action. Disadvantage is that the field is only in one tab. So a toggle button in the toolbar would probably be better. But Lino doesn’t yet have support for toggle toolbar buttons.
Optimizations in UserRoles table¶
I worked a bit on lino.modlib.users.UserRoles
: added
docstrings for the roles, and a more subtle change: it makes no sense
to show UserRole
subclasses which have been defined in within
the user_types_module
itself since these are not useful for understanding which permissions
are given to which user type.