cortezaproject / corteza

Low-code platform
https://cortezaproject.org
Apache License 2.0
1.64k stars 374 forks source link

Support for multi-page views [PlanID:2023.3/49/1.6] #479

Closed darh closed 1 year ago

darh commented 2 years ago

About

Supporting multi-page views enables us to improve the UX of end-users interacting with our low-code applications. Multi page views enable us to define different dashboards for different user roles, wizard-like flows for creating complex modules such as a subscription plan.

The current generation of our webapp will provide a simpler solution where we will expand on the idea in future iterations.

How

Each page now defines a list of layouts where each layout may define an expression. The expression determines if the layout can be shown based on the current situation.

When visiting a page, the page render logic iterates the list and shows the first layout where the expression evaluates into true. If there are layouts with no expressions, prioritise those.

Each layout can define a set of actions it can perform; create, update, delete record & move to next layout & redirect to next page.

Move layout action

The move layout action would permit you to go to the next layout where a user can interact with different bits and pieces. The action should accept some layout identifier (ID, label, handle, ...) and move to it.

The exact details of how users would redirect to other layouts should be discussed.

Here, be careful, to properly handle state updates as the page should hold a single state for all of the layouts the user goes through.

When we would move to a layout that doesn't belong to this page, we should save the ongoing record (and potentially prompt a notification before doing so).

Other actions

The rest of the actions simply define what (combination of) button(s) we should show in the toolbar.

Concerns/considerations:

Expression

Expressions should work similarly to how we've solved it for conditional fields. Expressions can access the current record, authenticated user and it's roles, date & time.

Refs

Original spec draft: https://docs.google.com/document/d/135EvSkCeU1tiNHNnztLf8PWsjzCpFtBwwUNFIFsSjrU/edit

github-actions[bot] commented 1 year ago

Stale issue message

katrinDY commented 1 year ago

For today: Tomaž will finish most of what needs to be done. The CRUD parts will be finished

tjerman commented 1 year ago

CRUD stuff is sorted. We'll discuss buttons, expressions, and layout actions with @Fajfa tomorrow.

tjerman commented 1 year ago

To add from me:

tjerman commented 1 year ago

Debating how access control should be done...

My current thoughts are either:

Opt. 1

Opt. 2

Currently, I'm leaning more towards the second option but I'm contemplating if such granular RBAC is overkill for page layouts. A counterargument would be module fields which also have their own RBAC rules.

I'm considering the first option because page layouts are basically an extension to the page wrapper so it doesn't really make sense to have granular RBAC on layouts also.

tjerman commented 1 year ago

Picking the second option primarily for consistency (modules and module fields). For most cases, wildcard allows will do. Might re-think before the feature goes out.

petergrlica commented 1 year ago

Second option for me as well, 1st - consistency. 2nd - defining a primary layout can be done on admin level, secondary on a less-permissive level ie content editor. I have a feeling editors will need this feature, especially on bigger projects.

tjerman commented 1 year ago

At a later point (probably during test fest) I'll be adding some extra test cases

katrinDY commented 1 year ago

For today: write integration tests for CRUD operations

tjerman commented 1 year ago
katrinDY commented 1 year ago

For today: define specs for supporting page layout actions

tjerman commented 1 year ago

Page Layout Actions

Actions introduce a new flexible way of trivially defining custom user journeys such as multi-step onboarding for a subscription, invoice billing, and payment systems, ...

Currently, pages can have these actions (which also fall under the corresponding button):

With the introduction of page layouts, we need additional bits to navigate between different layouts. We can take this further and provide additional mechanisms to provide access to the interaction state for more flexibility such as storing intermediate variables (can remove some prompts and temporary hidden fields).

Proposed Actions

new

the layout acts like the old new button

edit

the layout acts like the old edit button

submit

the layout acts like the old submit button

delete

the layout acts like the old delete button

clone

the layout acts like the old clone button

back

the layout acts like the old back button

goto(ident)

The action navigates to the specified page layout. This action can be used to navigate between different layouts using identifiers.

Note the same could be done with eval but a convenience function could be nice.

gotoPage(ident)

the action navigates to the specified page (a redirect) This action can be used to navigate between different pages using their identifiers.

An example use-case would be where a user onboarding would span over multiple resources, such as subscriptions and payment methods. After completing one (on one page), we can automatically send them off to a different page where they'd complete a different bit of the story.

eval(expr1, expr2, ..., exprN)

The action runs the given expressions and keeps the results in the interaction session This action can be used to manipulate the interaction session to hold custom values, and define expressions based on arbitrary session values (such as counters).

An example use-case would be where we have 5 layouts representing 5 steps, each layout defines an expression of i++ and each layout shows only when the value on i is correct. Can be replaced with goto and good layout handles, but this could be a nice addition.

The expression should be evaluated on the backend endpoint.

The variable assignment could be done in a similar manner to how we do workflow expression steps (target, type, expr).

run(ident)

The action runs the defined automation. The used identifier would be the same as what the event bus sees.

Note this might require a bunch of work so we should probs omit it for V1.

FE Implementation

Actions

On the front end, this would be represented as a button. But, an additional improvement would be to bind multiple actions under the same button.

A solid example would be to define the following chain: evaluate some values, update the record, save the record, gotoPage. This would all be under the same button.

When a single button holds multiple actions, they are executed in the same order they appear in. How we handle errors is up for debate. My suggestion is to just kill it and show the error.

State management

When you navigate to a page, we initialize a new interaction session. This session holds a few pre-defined variables (we'll decide on what; probably viewport, user, roles, ...) as well as some space for arbitrary values.

The state should exist as long as the user is interacting with the current page, potentially surviving refresh.

When evaluating expressions, the session should be included as a variable.

Potentially, the session could interact with records and UI elements.

Structs for Reference

Button struct {
  ButtomID uint64
  Placement string
  Meta any
  Label string
  // ...

  Actions []Action
}

Action struct {
  Kind string
  Params any
}
tjerman commented 1 year ago

@Fajfa

tjerman commented 1 year ago

V1 middle grounds

  1. Under the expression and roles (on configure page layout) add a list of all existing buttons (create, edit, delete, ...) -- Each button can be enabled/disabled
  2. under that list, another list of custom buttons (currently only go to layout) where you can tell the placement, label, enabled/disabled

When rendering a layout (on a specific view) if the button can exist and is enabled, show it, else (if it either can't exist or is disabled), don't show it.

tjerman commented 1 year ago

Some clarifications:

tjerman commented 1 year ago

@tjerman

Fajfa commented 1 year ago

@Fajfa

tjerman commented 1 year ago
Bojan-Svirkov commented 1 year ago

Tested and confirming that this looks and works good. Moving the ticket to Done, we will add the CL later as a part of the mention docs ticket above.