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/"); + }); +});