Sunday, July 8, 2018

How to implement detail layouts in OpenUI5

Yesterday Hamza and I also dived into the generation of XML for detail layouts (#2303). As Tonis pointed out earlier, the next challenge here is that Lino’s layout mechanism is per se not designed to be responsive.

For example TicketDetail is currently defined like this:

class TicketDetail(TicketDetail):
    main = "general more"

    general = dd.Panel("""
    general1:60 comments.CommentsByRFC:30
    """, label=_("General"))

    general1 = """
    summary id:6
    user end_user site ticket_type private:10
    workflow_buttons:30 priority:10 assigned_to planned_time

    bottom_box = """
    description:30 working.SessionsByTicket:20

    more = dd.Panel("""
    more1 DuplicatesByTicket:20
    upgrade_notes LinksByTicket uploads.UploadsByController
    """, label=_("More"))

    more1 = """
    created modified fixed_since
    state ref duplicate_of deadline

Which is rendered like this:


In OpenUI5 we have the concept of SimpleForm which is a Form control with FormContainers and FormElements, but the complexity in the API is removed:

  • A new Title or Toolbar starts a new group (FormContainer) in the form.
  • A new Label starts a new row (FormElement) in the form.
  • All other controls will be assigned to the row (FormElement) that started with the last label.
  • You can specify LayoutData to influence the layout for special cases in the Input/Display controls.

We played wiht some SimpleForm examples.

We will probably abandon the concept of detail layouts (or extend it) in order to use SimpleForm. Basically a detail form would be a <VBox> containing a <SimpleForm>. And the application developer must somehow specify resaonable “layout blocks”.

Now I am trying to find out how I would want to define a TicketDetail.

  • A detail layout is currently a series of nested panels, each panel being either vertical or horizontal. If the main panel is horizontal, the form is tabbed and every 2nd-level panel must have a label.
  • Lino could automatically decide that the content of a horizontal panel is optionally vertical when there is not enough space.
  • The general1 panel in our current TicketDetail is too large. Lino would have difficulties to render this into a reasonable layout on a mobile phone. We can fix this by saying that the application developer is responsible for not defining such panels that require more width than a mobile device can provide.


  • Issue a warning when the minimum width of a horizontal panel in a detail layout is bigger than a phone device can provide.
  • rename lino.utils.jsgen.Value.value_template to ext_value_template to express the fact that it is ExtJS-specific.
  • move jsgen to lino.modlib.extjs?
summary id

user end_user
site ticket_type
priority:10 assigned_to planned_time

created modified fixed_since
state ref duplicate_of deadline


Select at least a start period

When a user tried the AccountingReport, Lino raised a TypeError: bad argument type: __proxy__(u'Select at least a start period') instead of simply saying that message in the report’s body. This regression was introduced months ago when we switched to the lxml element trees. I now wrote a test case to reproduce this condition (in The General Ledger: moving money between accounts). While I was there I thought to also test what happens when the users specifies an invalid period range (end before start). Oops: instead of issuing an error message, Lino produced some report. That’s not fool-proof enough for an accounting application, so I changed it: Lino now has a new method check_params which you can implement either on an action or on an actor. Or you can use a ParameterPanel for your parameters and implement your own ParameterPanel.check_values method. Which is what we now do for AccountingPeriodRange.