From f1bce9dcade5d2efd44bd5992b9ca3371c254a15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A9ry=20Debongnie?= Date: Fri, 7 Feb 2025 09:12:05 +0100 Subject: [PATCH] add snippet_service --- addons/html_builder/static/src/builder.js | 59 +------------- addons/html_builder/static/src/builder.xml | 2 +- .../static/src/sidebar/block_tab.js | 31 +++---- .../static/src/sidebar/block_tab.xml | 14 ++-- .../add_snippet_dialog.js | 2 - .../add_snippet_dialog.scss | 0 .../add_snippet_dialog.xml | 0 .../input_confirmation_dialog.js | 0 .../input_confirmation_dialog.xml | 0 .../snippet_service.js} | 81 ++++++++++++++++++- .../{sidebar => snippets}/snippet_viewer.js | 3 +- .../{sidebar => snippets}/snippet_viewer.scss | 0 .../{sidebar => snippets}/snippet_viewer.xml | 0 .../static/tests/options/helpers.js | 2 +- 14 files changed, 98 insertions(+), 96 deletions(-) rename addons/html_builder/static/src/{sidebar => snippets}/add_snippet_dialog.js (96%) rename addons/html_builder/static/src/{sidebar => snippets}/add_snippet_dialog.scss (100%) rename addons/html_builder/static/src/{sidebar => snippets}/add_snippet_dialog.xml (100%) rename addons/html_builder/static/src/{sidebar => snippets}/input_confirmation_dialog.js (100%) rename addons/html_builder/static/src/{sidebar => snippets}/input_confirmation_dialog.xml (100%) rename addons/html_builder/static/src/{snippet_model.js => snippets/snippet_service.js} (81%) rename addons/html_builder/static/src/{sidebar => snippets}/snippet_viewer.js (96%) rename addons/html_builder/static/src/{sidebar => snippets}/snippet_viewer.scss (100%) rename addons/html_builder/static/src/{sidebar => snippets}/snippet_viewer.xml (100%) diff --git a/addons/html_builder/static/src/builder.js b/addons/html_builder/static/src/builder.js index 4c5d567334d3b..3153a5ba81a1a 100644 --- a/addons/html_builder/static/src/builder.js +++ b/addons/html_builder/static/src/builder.js @@ -11,7 +11,6 @@ import { useRef, useState, useSubEnv, - markup, } from "@odoo/owl"; import { ConfirmationDialog } from "@web/core/confirmation_dialog/confirmation_dialog"; import { useHotkey } from "@web/core/hotkeys/hotkey_hook"; @@ -19,9 +18,6 @@ import { _t } from "@web/core/l10n/translation"; import { registry } from "@web/core/registry"; import { useService } from "@web/core/utils/hooks"; import { addLoadingEffect as addButtonLoadingEffect } from "@web/core/utils/ui"; -import { RPCError } from "@web/core/network/rpc"; -import { escape } from "@web/core/utils/strings"; -import { user } from "@web/core/user"; import { useSetupAction } from "@web/search/action_hook"; import { AnchorPlugin } from "./core/plugins/anchor/anchor_plugin"; import { BuilderActionsPlugin } from "./core/plugins/builder_actions_plugin"; @@ -41,7 +37,6 @@ import { ReplacePlugin } from "./core/plugins/replace/replace_plugin"; import { SetupEditorPlugin } from "./core/plugins/setup_editor_plugin"; import { SnippetLifecyclePlugin } from "./core/plugins/snippet_lifecycle_plugin"; import { VisibilityPlugin } from "./core/plugins/visibility_plugin"; -import { SnippetModel } from "./snippet_model"; import { InvisibleElementsPanel } from "./sidebar/invisible_elements_panel"; import { BlockTab } from "./sidebar/block_tab"; import { CustomizeTab } from "./sidebar/customize_tab"; @@ -153,19 +148,7 @@ export class Builder extends Component { this.env.services ); - this.context = { - website_id: this.websiteService.currentWebsite.id, - lang: this.websiteService.currentWebsite.metadata.lang, - user_lang: user.context.lang, - }; - - this.snippetModel = useState( - new SnippetModel(this.env.services, { - snippetsName: this.props.snippetsName, - installSnippetModule: this.installSnippetModule.bind(this), - context: this.context, - }) - ); + this.snippetModel = useState(useService("html_builder.snippets")); onWillStart(async () => { await this.snippetModel.load(); @@ -343,46 +326,6 @@ export class Builder extends Component { ...this.editor.editable.querySelectorAll(this.getInvisibleSelector(isMobile)), ]; } - - installSnippetModule(snippet) { - // TODO: Should be the app name, not the snippet name ... Maybe both ? - const bodyText = _t("Do you want to install %s App?", snippet.title); - const linkText = _t("More info about this app."); - const linkUrl = - "/odoo/action-base.open_module_tree/" + encodeURIComponent(snippet.moduleId); - - this.dialog.add(ConfirmationDialog, { - title: _t("Install %s", snippet.title), - body: markup( - `${escape(bodyText)}\n${escape(linkText)}` - ), - confirm: async () => { - try { - await this.orm.call("ir.module.module", "button_immediate_install", [ - [Number(snippet.moduleId)], - ]); - // TODO Need to Reload webclient - // this._onSaveRequest({ - // data: { - // reloadWebClient: true, - // }, - // }); - } catch (e) { - if (e instanceof RPCError) { - const message = escape(_t("Could not install module %s", snippet.title)); - this.notification.add(message, { - type: "danger", - sticky: true, - }); - return; - } - throw e; - } - }, - confirmLabel: _t("Save and Install"), - cancel: () => {}, - }); - } } registry.category("lazy_components").add("website.Builder", Builder); diff --git a/addons/html_builder/static/src/builder.xml b/addons/html_builder/static/src/builder.xml index a5d6f51a66cbd..e77262052ca2d 100644 --- a/addons/html_builder/static/src/builder.xml +++ b/addons/html_builder/static/src/builder.xml @@ -27,7 +27,7 @@
- + diff --git a/addons/html_builder/static/src/sidebar/block_tab.js b/addons/html_builder/static/src/sidebar/block_tab.js index 2ee965d506230..b9051dd557209 100644 --- a/addons/html_builder/static/src/sidebar/block_tab.js +++ b/addons/html_builder/static/src/sidebar/block_tab.js @@ -1,7 +1,6 @@ -import { Component } from "@odoo/owl"; +import { Component, useState } from "@odoo/owl"; import { useDraggable } from "@web/core/utils/draggable"; import { useService } from "@web/core/utils/hooks"; -import { AddSnippetDialog } from "./add_snippet_dialog"; import { CustomInnerSnippet } from "./custom_inner_snippet"; // TODO move it in web (copy from web_studio) @@ -34,14 +33,12 @@ function copyElementOnDrag() { export class BlockTab extends Component { static template = "html_builder.BlockTab"; static components = { CustomInnerSnippet }; - static props = { - snippetModel: { type: Object }, - installSnippetModule: { type: Function }, - }; + static props = {}; setup() { this.dialog = useService("dialog"); this.orm = useService("orm"); + this.snippetModel = useState(useService("html_builder.snippets")); const copyOnDrag = copyElementOnDrag(); useDraggable({ @@ -55,7 +52,7 @@ export class BlockTab extends Component { onDragStart: ({ element }) => { copyOnDrag.insert(); const { category, id } = element.dataset; - const snippet = this.props.snippetModel.getSnippet(category, id); + const snippet = this.snippetModel.getSnippet(category, id); this.dropzonePlugin.displayDropZone(snippet); }, onDrag: ({ element }) => { @@ -65,7 +62,7 @@ export class BlockTab extends Component { const { x, y, height, width } = element.getClientRects()[0]; const position = { x, y, height, width }; const { category, id } = element.dataset; - const snippet = this.props.snippetModel.getSnippet(category, id); + const snippet = this.snippetModel.getSnippet(category, id); if (category === "snippet_groups") { this.openSnippetDialog(snippet, position); return; @@ -94,19 +91,11 @@ export class BlockTab extends Component { if (addElement.noDrop) { return; } - this.dialog.add( - AddSnippetDialog, - { - selectedSnippet: snippet, - snippetModel: this.props.snippetModel, - selectSnippet: (snippet) => { - addElement(snippet.content.cloneNode(true)); - }, - installModule: this.props.installSnippetModule, + this.snippetModel.select(snippet, { + onSelect: (snippet) => { + addElement(snippet.content.cloneNode(true)); }, - { - onClose: () => this.dropzonePlugin.clearDropZone(), - } - ); + onClose: () => this.dropzonePlugin.clearDropZone(), + }); } } diff --git a/addons/html_builder/static/src/sidebar/block_tab.xml b/addons/html_builder/static/src/sidebar/block_tab.xml index cffb510fbad75..551ab6ff89d8a 100644 --- a/addons/html_builder/static/src/sidebar/block_tab.xml +++ b/addons/html_builder/static/src/sidebar/block_tab.xml @@ -5,11 +5,11 @@
Categories
-
+
- +
@@ -17,21 +17,21 @@
- +
Custom Inner Content
- - + +
Inner Content
-
+
- +
diff --git a/addons/html_builder/static/src/sidebar/add_snippet_dialog.js b/addons/html_builder/static/src/snippets/add_snippet_dialog.js similarity index 96% rename from addons/html_builder/static/src/sidebar/add_snippet_dialog.js rename to addons/html_builder/static/src/snippets/add_snippet_dialog.js index 9334098d138ac..1976382d61068 100644 --- a/addons/html_builder/static/src/sidebar/add_snippet_dialog.js +++ b/addons/html_builder/static/src/snippets/add_snippet_dialog.js @@ -12,7 +12,6 @@ export class AddSnippetDialog extends Component { selectedSnippet: { type: Object }, selectSnippet: { type: Function }, snippetModel: { type: Object }, - installModule: { type: Function }, close: { type: Function }, }; @@ -31,7 +30,6 @@ export class AddSnippetDialog extends Component { this.props.close(); }, snippetModel: this.props.snippetModel, - installModule: this.props.installModule, }; let root; diff --git a/addons/html_builder/static/src/sidebar/add_snippet_dialog.scss b/addons/html_builder/static/src/snippets/add_snippet_dialog.scss similarity index 100% rename from addons/html_builder/static/src/sidebar/add_snippet_dialog.scss rename to addons/html_builder/static/src/snippets/add_snippet_dialog.scss diff --git a/addons/html_builder/static/src/sidebar/add_snippet_dialog.xml b/addons/html_builder/static/src/snippets/add_snippet_dialog.xml similarity index 100% rename from addons/html_builder/static/src/sidebar/add_snippet_dialog.xml rename to addons/html_builder/static/src/snippets/add_snippet_dialog.xml diff --git a/addons/html_builder/static/src/sidebar/input_confirmation_dialog.js b/addons/html_builder/static/src/snippets/input_confirmation_dialog.js similarity index 100% rename from addons/html_builder/static/src/sidebar/input_confirmation_dialog.js rename to addons/html_builder/static/src/snippets/input_confirmation_dialog.js diff --git a/addons/html_builder/static/src/sidebar/input_confirmation_dialog.xml b/addons/html_builder/static/src/snippets/input_confirmation_dialog.xml similarity index 100% rename from addons/html_builder/static/src/sidebar/input_confirmation_dialog.xml rename to addons/html_builder/static/src/snippets/input_confirmation_dialog.xml diff --git a/addons/html_builder/static/src/snippet_model.js b/addons/html_builder/static/src/snippets/snippet_service.js similarity index 81% rename from addons/html_builder/static/src/snippet_model.js rename to addons/html_builder/static/src/snippets/snippet_service.js index 1b9c1b801ad5b..2845c6a9760a9 100644 --- a/addons/html_builder/static/src/snippet_model.js +++ b/addons/html_builder/static/src/snippets/snippet_service.js @@ -3,16 +3,20 @@ import { _t } from "@web/core/l10n/translation"; import { uniqueId } from "@web/core/utils/functions"; import { Reactive } from "@web/core/utils/reactive"; import { escape } from "@web/core/utils/strings"; -import { AddSnippetDialog } from "@html_builder/sidebar/add_snippet_dialog"; +import { AddSnippetDialog } from "./add_snippet_dialog"; +import { registry } from "@web/core/registry"; +import { user } from "@web/core/user"; +import { markup } from "@odoo/owl"; +import { RPCError } from "@web/core/network/rpc"; export class SnippetModel extends Reactive { - constructor(services, { snippetsName, installSnippetModule, context }) { + constructor(services, { snippetsName, context }) { super(); this.orm = services.orm; this.dialog = services.dialog; + this.notification = services.notification; this.snippetsName = snippetsName; this.websiteService = services.website; - this.installSnippetModule = installSnippetModule; this.context = context; this.snippetsByCategory = { @@ -71,6 +75,58 @@ export class SnippetModel extends Reactive { return this.snippetsByCategory[category].filter((snippet) => snippet.id === id)[0]; } + installSnippetModule(snippet) { + // TODO: Should be the app name, not the snippet name ... Maybe both ? + const bodyText = _t("Do you want to install %s App?", snippet.title); + const linkText = _t("More info about this app."); + const linkUrl = + "/odoo/action-base.open_module_tree/" + encodeURIComponent(snippet.moduleId); + + this.dialog.add(ConfirmationDialog, { + title: _t("Install %s", snippet.title), + body: markup( + `${escape(bodyText)}\n${escape(linkText)}` + ), + confirm: async () => { + try { + await this.orm.call("ir.module.module", "button_immediate_install", [ + [Number(snippet.moduleId)], + ]); + // TODO Need to Reload webclient + // this._onSaveRequest({ + // data: { + // reloadWebClient: true, + // }, + // }); + } catch (e) { + if (e instanceof RPCError) { + const message = escape(_t("Could not install module %s", snippet.title)); + this.notification.add(message, { + type: "danger", + sticky: true, + }); + return; + } + throw e; + } + }, + confirmLabel: _t("Save and Install"), + cancel: () => {}, + }); + } + + select(snippet, { onSelect, onClose }) { + this.dialog.add( + AddSnippetDialog, + { + selectedSnippet: snippet, + snippetModel: this, + selectSnippet: onSelect, + }, + { onClose } + ); + } + async load() { const context = { ...this.context, rendering_bundle: true }; if (context.user_lang) { @@ -242,7 +298,6 @@ export class SnippetModel extends Reactive { newSnippet = selectedSnippet.content.cloneNode(true); snippetToReplace.replaceWith(newSnippet); }, - installModule: this.installSnippetModule, }, { onClose: () => resolve() } ); @@ -314,3 +369,21 @@ export class SnippetModel extends Reactive { }); } } + +registry.category("services").add("html_builder.snippets", { + dependencies: ["orm", "dialog", "website", "notification"], + + start(env, { orm, dialog, website, notification }) { + const services = { orm, dialog, website, notification }; + const context = { + website_id: website.currentWebsite?.id, + lang: website.currentWebsite?.metadata.lang, + user_lang: user.context.lang, + }; + + return new SnippetModel(services, { + snippetsName: "website.snippets", + context, + }); + }, +}); diff --git a/addons/html_builder/static/src/sidebar/snippet_viewer.js b/addons/html_builder/static/src/snippets/snippet_viewer.js similarity index 96% rename from addons/html_builder/static/src/sidebar/snippet_viewer.js rename to addons/html_builder/static/src/snippets/snippet_viewer.js index 4c6cfce85e0b8..dff36666b56ef 100644 --- a/addons/html_builder/static/src/sidebar/snippet_viewer.js +++ b/addons/html_builder/static/src/snippets/snippet_viewer.js @@ -9,7 +9,6 @@ export class SnippetViewer extends Component { state: { type: Object }, selectSnippet: { type: Function }, snippetModel: { type: Object }, - installModule: { type: Function }, }; setup() { @@ -50,7 +49,7 @@ export class SnippetViewer extends Component { onClick(snippet) { if (snippet.moduleId) { - this.props.installModule(snippet); + this.props.snippetModel.installModule(snippet); } else { this.props.selectSnippet(snippet); } diff --git a/addons/html_builder/static/src/sidebar/snippet_viewer.scss b/addons/html_builder/static/src/snippets/snippet_viewer.scss similarity index 100% rename from addons/html_builder/static/src/sidebar/snippet_viewer.scss rename to addons/html_builder/static/src/snippets/snippet_viewer.scss diff --git a/addons/html_builder/static/src/sidebar/snippet_viewer.xml b/addons/html_builder/static/src/snippets/snippet_viewer.xml similarity index 100% rename from addons/html_builder/static/src/sidebar/snippet_viewer.xml rename to addons/html_builder/static/src/snippets/snippet_viewer.xml diff --git a/addons/html_builder/static/tests/options/helpers.js b/addons/html_builder/static/tests/options/helpers.js index 72c4e122226dd..746159b7e270c 100644 --- a/addons/html_builder/static/tests/options/helpers.js +++ b/addons/html_builder/static/tests/options/helpers.js @@ -1,5 +1,5 @@ import { setupWebsiteBuilder } from "../helpers"; -import { SnippetModel } from "@html_builder/snippet_model"; +import { SnippetModel } from "@html_builder/snippets/snippet_service"; import { getMockEnv, makeMockEnv, mockService } from "@web/../tests/web_test_helpers"; export async function getStructureSnippet(snippetName) {