From 80e1c0062ecb31e6ece540b63fa974f933d1e657 Mon Sep 17 00:00:00 2001 From: Jorge Pinna Puissant Date: Mon, 23 Jan 2023 14:51:34 +0000 Subject: [PATCH] [IMP] web: documentation link widget This commit introduces the documentation link widget, the aim is to standardize the help documentation links that can be found in the views. This widget will add an icon (o_doc_link), this icon is a link to the documentation. Note that you can use relative or absolute path. The relative path is relative to `https://www.odoo.com/documentation/server_version`, so it's not necessary to hard-code the server version on the arch any more. ```xml ``` Task-id: 2980478 Part-of: odoo/odoo#110432 --- .../documentation_link/documentation_link.js | 36 ++++++++++ .../documentation_link/documentation_link.xml | 6 ++ addons/web/static/src/views/widgets/widget.js | 8 ++- .../settings_form_view/settings/setting.js | 14 +--- .../settings_form_view/settings/setting.xml | 2 +- .../views/widgets/document_link_tests.js | 72 +++++++++++++++++++ 6 files changed, 124 insertions(+), 14 deletions(-) create mode 100644 addons/web/static/src/views/widgets/documentation_link/documentation_link.js create mode 100644 addons/web/static/src/views/widgets/documentation_link/documentation_link.xml create mode 100644 addons/web/static/tests/views/widgets/document_link_tests.js diff --git a/addons/web/static/src/views/widgets/documentation_link/documentation_link.js b/addons/web/static/src/views/widgets/documentation_link/documentation_link.js new file mode 100644 index 00000000000..199bbaea720 --- /dev/null +++ b/addons/web/static/src/views/widgets/documentation_link/documentation_link.js @@ -0,0 +1,36 @@ +/** @odoo-module **/ + +import { session } from "@web/session"; +import { standardWidgetProps } from "@web/views/widgets/standard_widget_props"; +import { Component } from "@odoo/owl"; +import { registry } from "@web/core/registry"; + +const LINK_REGEX = new RegExp("^https?://"); + +export class DocumentationLink extends Component { + get url() { + if (LINK_REGEX.test(this.props.path)) { + return this.props.path; + } else { + const serverVersion = session.server_version.includes("alpha") + ? "master" + : session.server_version; + return "https://www.odoo.com/documentation/" + serverVersion + this.props.path; + } + } +} +DocumentationLink.template = "web.DocumentationLink"; +DocumentationLink.props = { + ...standardWidgetProps, + record: { type: Object, optional: 1 }, // The record is not needed in this widget + path: { type: String }, +}; +DocumentationLink.extractProps = ({ attrs }) => { + const { path } = attrs; + return { + path, + }; +}; +DocumentationLink.additionalClasses = ["d-inline"]; + +registry.category("view_widgets").add("documentation_link", DocumentationLink); diff --git a/addons/web/static/src/views/widgets/documentation_link/documentation_link.xml b/addons/web/static/src/views/widgets/documentation_link/documentation_link.xml new file mode 100644 index 00000000000..b9a1754d3f9 --- /dev/null +++ b/addons/web/static/src/views/widgets/documentation_link/documentation_link.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/addons/web/static/src/views/widgets/widget.js b/addons/web/static/src/views/widgets/widget.js index a422ba6e32a..e2b62db5e06 100644 --- a/addons/web/static/src/views/widgets/widget.js +++ b/addons/web/static/src/views/widgets/widget.js @@ -25,11 +25,17 @@ export class Widget extends Component { } get classNames() { - return { + const classNames = { o_widget: true, [`o_widget_${this.props.name}`]: true, [this.props.className]: Boolean(this.props.className), }; + if (this.Widget.additionalClasses) { + for (const cls of this.Widget.additionalClasses) { + classNames[cls] = true; + } + } + return classNames; } get widgetProps() { const { node: rawNode } = this.props; diff --git a/addons/web/static/src/webclient/settings_form_view/settings/setting.js b/addons/web/static/src/webclient/settings_form_view/settings/setting.js index 719443aabb6..19af10ba606 100644 --- a/addons/web/static/src/webclient/settings_form_view/settings/setting.js +++ b/addons/web/static/src/webclient/settings_form_view/settings/setting.js @@ -5,9 +5,8 @@ import { HighlightText } from "../highlight_text/highlight_text"; import { session } from "@web/session"; import { FormLabelHighlightText } from "../highlight_text/form_label_highlight_text"; import { Component, useState } from "@odoo/owl"; +import { DocumentationLink } from "@web/views/widgets/documentation_link/documentation_link"; - -const LINK_REGEX = new RegExp("^https?://"); export class Setting extends Component { setup() { this.state = useState({ @@ -57,16 +56,6 @@ export class Setting extends Component { return label || ""; } - get url() { - if (LINK_REGEX.test(this.props.documentation)) { - return this.props.documentation; - } else { - const serverVersion = session.server_version.includes("alpha") - ? "master" - : session.server_version; - return "https://www.odoo.com/documentation/" + serverVersion + this.props.documentation; - } - } visible() { if (!this.state.search.value) { return true; @@ -84,6 +73,7 @@ export class Setting extends Component { Setting.components = { FormLabelHighlightText, HighlightText, + DocumentationLink, }; Setting.template = "web.Setting"; Setting.props = { diff --git a/addons/web/static/src/webclient/settings_form_view/settings/setting.xml b/addons/web/static/src/webclient/settings_form_view/settings/setting.xml index 4c8ff64b877..224811cca22 100644 --- a/addons/web/static/src/webclient/settings_form_view/settings/setting.xml +++ b/addons/web/static/src/webclient/settings_form_view/settings/setting.xml @@ -13,7 +13,7 @@ - + diff --git a/addons/web/static/tests/views/widgets/document_link_tests.js b/addons/web/static/tests/views/widgets/document_link_tests.js new file mode 100644 index 00000000000..c50ebcdb45f --- /dev/null +++ b/addons/web/static/tests/views/widgets/document_link_tests.js @@ -0,0 +1,72 @@ +/** @odoo-module **/ +import { getFixture } from "@web/../tests/helpers/utils"; +import { makeView, setupViewRegistries } from "@web/../tests/views/helpers"; + +let target; +let serverData; + +QUnit.module("Widgets", (hooks) => { + hooks.beforeEach(() => { + target = getFixture(); + serverData = { + models: { + partner: { + fields: { + bar: { string: "Bar", type: "boolean" }, + }, + }, + }, + }; + + setupViewRegistries(); + }); + + QUnit.module("DocumentationLink"); + + QUnit.test("documentation_link: relative path", async function (assert) { + await makeView({ + type: "form", + resModel: "partner", + serverData, + arch: ` +
+ + + `, + }); + + assert.hasAttrValue( + target.querySelector(".o_doc_link"), + "href", + "https://www.odoo.com/documentation/1.0/applications/technical/web/settings/this_is_a_test.html" + ); + }); + QUnit.test("documentation_link: absoluth path (http)", async function (assert) { + await makeView({ + type: "form", + resModel: "partner", + serverData, + arch: ` +
+ + + `, + }); + + assert.hasAttrValue(target.querySelector(".o_doc_link"), "href", "http://www.odoo.com/"); + }); + QUnit.test("documentation_link: absoluth path (https)", async function (assert) { + await makeView({ + type: "form", + resModel: "partner", + serverData, + arch: ` +
+ + + `, + }); + + assert.hasAttrValue(target.querySelector(".o_doc_link"), "href", "https://www.odoo.com/"); + }); +});