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
    """

    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:

../../_images/0708a.png

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.

Ideas:

  • 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
private:10
workflow_buttons:30
priority:10 assigned_to planned_time

description:30
working.SessionsByTicket:20
created modified fixed_since
state ref duplicate_of deadline
DuplicatesByTicket:20
upgrade_notes
LinksByTicket
uploads.UploadsByController

comments.CommentsByRFC:30

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 (Thursday, March 8, 2018) when we switched to the lxml element trees. I now wrote a test case to reproduce this condition (in accounting: General accounting). 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.