[IMP] account: new ActionableErrors widget for warnings display

The new widget is meant to be a warnings header for wizards and forms,
where flows like EDI can list a series of errors and actions for
the users to fix the roadblocks.

The HTML result is an `<ul>` list with a point for each warning
and a link to a given action. Clicking the link will fire the execution
of a Python method on the backend, also passing back to it a series of
parameters the component has stored on setup time.

During setup, ActionableErrors accepts this structure as incoming data:
{
    'error_key' : {
         'message': _("Description of the warning"),
         'action_text': _("Text of the link"),
         'action_model': 'model.on.which.the.method.is.called',
         'action_name': 'action_python_method_name',
         'action_params': [...],'
    },
    ...
}

A map is used instead of an array, so that the Owl framework
could be more precise in rendering changes in future development.
(i.e. remove a warning after clicking the action link
without re-rendering the whole widget)

This Widget will be used both for `l10n_it_edi` and `account_intrastat`
and can be embedded in many other occasions.

Part-of: odoo/odoo#142596
This commit is contained in:
Paolo Gatti (pgi)
2024-02-03 19:38:00 +00:00
parent a317f78068
commit f50fdc9d61
2 changed files with 50 additions and 0 deletions
@@ -0,0 +1,27 @@
/** @odoo-module **/
import { registry } from "@web/core/registry";
import { Component } from "@odoo/owl";
import { standardFieldProps } from "@web/views/fields/standard_field_props";
import { useRecordObserver } from "@web/model/relational_model/utils";
export class ActionableErrors extends Component {
static props = { ...standardFieldProps };
static template = "account.ActionableErrors";
setup() {
useRecordObserver(this.formatData.bind(this));
}
formatData(record) {
const errorsField = record.data[this.props.name];
this.errorsData = JSON.parse(JSON.stringify(errorsField));
}
async handleOnClick(errorData){
this.env.model.action.doAction(errorData.action);
}
}
export const actionableErrors = {component: ActionableErrors};
registry.category("fields").add("actionable_errors", actionableErrors);
@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<templates>
<t t-name="account.ActionableErrors">
<t t-if="errorsData">
<div class="alert alert-warning mb-2 px-3 py-2" role="alert">
<t t-foreach="errorsData" t-as="error" t-key="error">
<div t-att-name="error">
<t t-out="error_value.message"/>
<a class="fw-bold"
t-if="error_value.action"
href="#"
t-on-click.prevent="() => this.handleOnClick(error_value)"
>
<i class="oi oi-arrow-right ms-1"/>
<span class="ms-1" t-out="error_value.action_text"/>
<i t-if="error_value.critical" class="fa fa-warning ms-1"/>
</a>
</div>
</t>
</div>
</t>
</t>
</templates>