Intent Based Navigation

Version Date Notes By
0.1 2018-10-23 Initial pre release ROB

This system is not yet finished -> "Early Access!"

The intent based navigation system allows a frontend programer to set up a series of navigation event expectations that override the regular navigation flow of pages to fulfill the navigation intent.

For example, most create forms on submit return to their respective lists but you may wish to navigate from a form to a second form, submit that second form and return the id to the first form (bypassing the "return to list" behavior of the second form).

To do this, there is a globally available system, accessible through the appContainer in most viewModels.

The first step in our example above would be to use that global system to setup the intent like so:

this.appContainer.intentResolver.navigateToRouteWithIntent(
    // route name to navigate to
    'plans.plans.create',

    // route params (if any, null if no params)
    null,

    // intent object (may become builder like in the future)
    {
        // setup the "intention" to return to this route (once submited)
        return_to_route: 'processes.processes.indicators-maps.edit',

        // parameters to feed to route above, if any
        return_to_params: { id: this.indicator_map_id },

        // once routed to what was setup above, execute this function
        return_execute_function: {
            // function to execute
            function: 'associateNewlyCreatedPlanWithGoal',

            // params of function above
            params: [{
                goal: { id: this.goal.id }, indicator_map_id:
                      this.indicator_map_id
            }, IndicatorMapGoalPlans]
        },

        // once routed to what was setup above ("intention"), open this tab
        return_active_tab: 'tab3'
    }
);

In the intent object above the condition that triggers the return_to_route parameter above is hardcoded to be the submit event, this is very likely to change in the future.

The second step in the example, the second form, must have the following code placed inside the submit function, when the response to that submit returns successfully:

if (this.appContainer.intentResolver.hasIntentsToResolve()) {
    // resolve intent
    this.appContainer.intentResolver.resolveLatestIntent({
        /* 
        parameters to return to where the intent was created at 
        (example, the id of the newly created artifact)
        */
    });
} else {
    /* resolve original route */
}

Intents are added to the intent stack at the first stage and get removed (FIFO) from the stack as they are resolved via the resolveLatestIntent function.

This should be placed inside the base-form-view-model.js for maximum intent coverage (once this system has been reviewed in core meeting, in the year 2158).

The third step (once the intent has navigated back to the original form) is to retrive the disposition of the intent chain (basically, the information that was passed back via intent disposition, plus all the forms visited in the process).

For now, this is a manual process, but with more development this could be reduced / eliminated. In the activate function (or function called by activate function) place this code:

// Example of intent disposition resolution
if (this.appContainer.intentResolver.hasDispositionsToResolve('processes.processes.indicators-maps.edit')) {

    // get disposition information
    let disposition = this.appContainer.intentResolver.resolveDisposition('processes.processes.indicators-maps.edit');

    // Resolve the tab to open
    if (disposition.source_intent.return_active_tab) {
        for (let a in this.fancy_tab_controller) {
            this.fancy_tab_controller[a] = null;
        }
        this.fancy_tab_controller[disposition.source_intent.return_active_tab] = 'active';
    }

    // resolve function to call
    if (disposition.source_intent.return_execute_function) {
        // more complexity still for this intent system (viewModels composed into viewModels)
        this[disposition.source_intent.return_execute_function.function](disposition, ...disposition.source_intent.return_execute_function.params);
    }
}

Notes

This intent navigation system is very basic and incomplete, there are a lot of cases it needs to cover, both in terms of navigation (goto route and open modal, open modal inside modal, and other cases), in terms of aditional functionality (encode the intent in the url?) and in terms of ways to use (on submit, on viewModel function call?).

This is very much a first aproach and is subject to heavy change.