Skip to content

[IMP] Reorganize snippets in categories #4819

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 43 commits into
base: master-mysterious-egG-mail
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
8b91e9f
[IMP] html_builder, website: remove website dependency from snippet_s…
abd-msyukyu-odoo Jun 20, 2025
f3ec2b1
[REM] html_editor: remove dead code for toolbar
abd-msyukyu-odoo Jun 12, 2025
f89aadf
mass_mailing_builder
abd-msyukyu-odoo Mar 12, 2025
e41e419
WIP
abd-msyukyu-odoo Jun 19, 2025
42ba3c6
implement basic editor and complete iframe style
abd-msyukyu-odoo Jun 25, 2025
bf45502
implement readonly mode
abd-msyukyu-odoo Jun 26, 2025
747ed20
Fixes to HTML FIELD
abd-msyukyu-odoo Jun 26, 2025
d6d1902
[FIX] To remove when the Snippets have all a plugin.
thjo-odoo Jun 25, 2025
50ef5a4
[FIX] fixed the builder mounting
thjo-odoo Jun 25, 2025
0f1dd3c
[FIX] fixed templates so that they are droppable
thjo-odoo Jun 25, 2025
7887fa8
Add a progress bar
thjo-odoo Jun 27, 2025
eae7ca2
Working on snippet options/plugins (blockquote, ...)
thjo-odoo Jun 25, 2025
0e8447b
fixing after rebase
abd-msyukyu-odoo Jul 1, 2025
cdd99eb
WIP
abd-msyukyu-odoo Jul 1, 2025
35bface
better processing
abd-msyukyu-odoo Jul 1, 2025
4208370
fixes to send proper email
abd-msyukyu-odoo Jul 1, 2025
bfd739e
probably trash
abd-msyukyu-odoo Jul 1, 2025
5d6040a
wip
abd-msyukyu-odoo Jul 2, 2025
fac82ee
WIP style
abd-msyukyu-odoo Jul 2, 2025
3a9db93
DO NOT SQUASH: very specific fix for overlay_buttons_plugin move on s…
abd-msyukyu-odoo Jul 2, 2025
8769a01
fix favorite theme selection
abd-msyukyu-odoo Jul 3, 2025
1f7d0b9
make o_editable work + /field command + start fixing nbsp in templates
abd-msyukyu-odoo Jul 3, 2025
d85ef58
Add a progress bar
thjo-odoo Jun 27, 2025
83fda5a
WIP
thjo-odoo Jun 26, 2025
e9ff571
[MOV] html_builder: move BackgroundOption
thjo-odoo Jul 3, 2025
2235ee4
Masonry block options
thjo-odoo Jul 1, 2025
054c5e9
[FIX] Move utils to html_builder
thjo-odoo Jul 3, 2025
7b1f826
save_plugin
abd-msyukyu-odoo Jul 3, 2025
d8ac682
fix name
abd-msyukyu-odoo Jul 3, 2025
d9a8475
fix rounded corners
abd-msyukyu-odoo Jul 3, 2025
c1d9818
fix template xpath
abd-msyukyu-odoo Jul 3, 2025
7b752d9
use correct registry
abd-msyukyu-odoo Jul 3, 2025
63e7309
codeview implementation
abd-msyukyu-odoo Jul 3, 2025
37b7cbf
fix manifest warning
abd-msyukyu-odoo Jul 4, 2025
ec41e91
modify options mass_mailing_iframe
abd-msyukyu-odoo Jul 4, 2025
9683424
design tab
abd-msyukyu-odoo Jul 4, 2025
44373f2
[FIX] builder_overlay_patch sizingX exclude was incorrect
thjo-odoo Jul 3, 2025
4dabded
[FIX] Snippets options that were problematic
thjo-odoo Jul 3, 2025
09d6f4a
fix columns, border and alert options
thjo-odoo Jul 4, 2025
9237b7b
[FIX] closing iframe crash
thjo-odoo Jul 4, 2025
e852a65
[IMP] adjust z-index in modal
thjo-odoo Jul 4, 2025
483a097
[IMP] mobile works
thjo-odoo Jul 4, 2025
47ed5cb
[IMP] Reorganize snippets in categories
thjo-odoo Jul 7, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion addons/html_builder/static/src/bs/bs.buttons.scss
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
.o-website-builder_sidebar .btn {
.o-snippets-menu .btn {
--btn-font-weight: normal;
--btn-font-size: #{$o-we-font-size-sm};
--btn-box-shadow: 0 0;
Expand Down
38 changes: 30 additions & 8 deletions addons/html_builder/static/src/builder.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
onWillDestroy,
onWillStart,
onWillUpdateProps,
status,
useRef,
useState,
useSubEnv,
Expand All @@ -30,18 +31,22 @@ export class Builder extends Component {
static template = "html_builder.Builder";
static components = { BlockTab, CustomizeTab, InvisibleElementsPanel };
static props = {
closeEditor: { type: Function },
closeEditor: { type: Function, optional: true },
reloadEditor: { type: Function, optional: true },
onEditorLoad: { type: Function, optional: true },
installSnippetModule: { type: Function, optional: true },
snippetsName: { type: String },
snippetModel: { type: Object },
toggleMobile: { type: Function },
overlayRef: { type: Function },
iframeLoaded: { type: Object },
isMobile: { type: Boolean },
Plugins: { type: Array, optional: true },
config: { type: Object, optional: true },
getThemeTab: { type: Function, optional: true },
editableSelector: { type: String },
toggleFullscreen: { type: Function, optional: true },
toggleCodeView: { type: Function, optional: true },
getExternalScrollableAncestor: { type: Function, optional: true },
};
static defaultProps = {
onEditorLoad: () => {},
Expand All @@ -66,6 +71,7 @@ export class Builder extends Component {
this.dialog = useService("dialog");
this.ui = useService("ui");
this.notification = useService("notification");
this.snippetModel = useState(this.props.snippetModel);

const editorBus = new EventBus();

Expand All @@ -79,6 +85,9 @@ export class Builder extends Component {
if (!isPreviewing) {
this.state.canUndo = this.editor.shared.history.canUndo();
this.state.canRedo = this.editor.shared.history.canRedo();
if (this.props.config.onChange) {
this.props.config.onChange();
}
this.updateInvisibleEls();
editorBus.trigger("UPDATE_EDITING_ELEMENT");
editorBus.trigger("DOM_UPDATED");
Expand All @@ -91,10 +100,10 @@ export class Builder extends Component {
});
},
closeEditor: async () => {
await this.props.closeEditor();
await this.props.closeEditor?.();
},
installSnippetModule: async (snippet) =>
this.props.installSnippetModule(snippet, this.save.bind(this)),
this.props.installSnippetModule?.(snippet, this.save.bind(this)),
resources: {
trigger_dom_updated: () => {
editorBus.trigger("DOM_UPDATED");
Expand Down Expand Up @@ -128,6 +137,7 @@ export class Builder extends Component {
cleanForSaveHandlers,
wrapWithSaveSnippetHandlers
),
snippetModel: this.snippetModel,
getShared: () => this.editor.shared,
updateInvisibleElementsPanel: () => this.updateInvisibleEls(),
allowCustomStyle: true,
Expand All @@ -138,15 +148,18 @@ export class Builder extends Component {
);
this.props.onEditorLoad(this.editor);

this.snippetModel = useState(useService("html_builder.snippets"));

onWillStart(async () => {
await this.snippetModel.load();
// Ensure that the iframe is loaded and the editor is created before
// instantiating the sub components that potentially need the
// editor.
const iframeEl = await this.props.iframeLoaded;
this.editableEl = iframeEl.contentDocument.body.querySelector("#wrapwrap");
if (status(this) === "destroyed") {
return;
}
this.editableEl = iframeEl.contentDocument.body.querySelector(
this.props.editableSelector
);
setEditableWindow(iframeEl.contentWindow);
setEditableDocument(iframeEl.contentDocument);

Expand All @@ -172,7 +185,7 @@ export class Builder extends Component {
// });
onWillDestroy(() => {
this.editor.destroy();
this.editableEl.removeEventListener("dragstart", this.onDragStart);
this.editableEl?.removeEventListener("dragstart", this.onDragStart);
// actionService.setActionMode("current");
});

Expand Down Expand Up @@ -221,6 +234,9 @@ export class Builder extends Component {
}

async save() {
if (!this.props.closeEditor) {
return;
}
this.editor.shared.operation.next(this._save.bind(this), { withLoadingEffect: false });
}

Expand Down Expand Up @@ -266,13 +282,19 @@ export class Builder extends Component {
}

onBeforeUnload(event) {
if (!this.props.closeEditor) {
return;
}
if (!this.isSaving && this.state.canUndo) {
event.preventDefault();
event.returnValue = "Unsaved changes";
}
}

async onBeforeLeave() {
if (!this.props.closeEditor) {
return true;
}
if (this.state.canUndo && !this.editor.shared.savePlugin.isAlreadySaved()) {
let continueProcess = true;
await new Promise((resolve) => {
Expand Down
14 changes: 9 additions & 5 deletions addons/html_builder/static/src/builder.xml
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,13 @@
<button type="button" t-on-click="() => this.redo()" class="o-hb-btn btn fa fa-repeat" t-att-disabled="!state.canRedo"/>
</div>
<div class="d-flex gap-1">
<button t-on-click="onMobilePreviewClick" type="button" class="o-hb-btn btn d-flex align-items-center" t-att-class="{active: props.isMobile}" data-action="mobile" title="Mobile Preview" accesskey="v" style="--btn-font-size: 20px"><span class="fa fa-mobile" role="img"/></button>
<button type="button" t-on-click="discard" class="o-hb-btn btn" data-action="cancel" title="Tip: Esc to preview" accesskey="j">Discard</button>
<button type="button" t-on-click="save" class="o-hb-btn btn btn-success px-3" data-action="save" accesskey="s">Save</button>
<button t-on-click="onMobilePreviewClick" type="button" class="o-hb-btn btn d-flex align-items-center" t-att-class="{active: props.isMobile, disabled: props.isMobile}" data-action="mobile" title="Mobile Preview" accesskey="v" style="--btn-font-size: 20px"><span class="fa fa-mobile" role="img"/></button>
<button t-if="props.toggleCodeView" t-on-click="props.toggleCodeView"
class="o-hb-btn btn d-flex align-items-center" title="Code View" accesskey="c"><i class="fa fa-code"/></button>
<button t-if="props.toggleFullscreen" t-on-click="props.toggleFullscreen"
class="o-hb-btn btn d-flex align-items-center" title="Fullscreen" accesskey="f">FS</button>
<button t-if="props.closeEditor" type="button" t-on-click="discard" class="o-hb-btn btn" data-action="cancel" title="Tip: Esc to preview" accesskey="j">Discard</button>
<button t-if="props.closeEditor" type="button" t-on-click="save" class="o-hb-btn btn btn-success px-3" data-action="save" accesskey="s">Save</button>
</div>
</div>
<div class="o-snippets-tabs position-relative grid px-2 my-2" style="--columns: 3; --gap: 0.25rem">
Expand All @@ -29,12 +33,12 @@
<i class="oi oi-settings-adjust me-1" role="img"/>Edit
</button>
<button data-name="theme" data-hotkey="2" t-if="ThemeTab" class="o-hb-btn position-relative btn" t-att-class="{'active cursor-default': state.activeTab === 'theme'}" t-on-click="() => this.onTabClick('theme')" t-att-disabled="displayOnlyCustomizeTab">
<i class="fa fa-cog me-1" role="img"/>Theme
<i class="fa fa-cog me-1" role="img"/><t t-out="ThemeTab.displayName"/>
</button>
</div>
<div class="o-tab-content overflow-y-auto overflow-x-hidden flex-grow-1">
<t t-if="state.activeTab === 'blocks'">
<BlockTab />
<BlockTab snippetModel="snippetModel" getExternalScollableAncestor="props.getExternalScollableAncestor"/>
</t>
<t t-if="state.activeTab === 'customize'">
<t t-if="!!props.config.customizeTab" t-call="{{props.config.customizeTab}}"/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,4 @@ class BorderRadiusStylePlugin extends Plugin {
});
}
}
registry.category("website-plugins").add(BorderRadiusStylePlugin.id, BorderRadiusStylePlugin);
registry.category("builder-plugins").add(BorderRadiusStylePlugin.id, BorderRadiusStylePlugin);
Original file line number Diff line number Diff line change
Expand Up @@ -352,7 +352,7 @@ export class BuilderOptionsPlugin extends Plugin {
}

patchBuilderOptions({ target_name, target_element, method, value }) {
if (!target_name || !target_element || !method || !value) {
if (!target_name || !target_element || !method || (!value && method !== "remove")) {
throw new Error(
`Missing patch_builder_options required parameters: target_name, target_element, method, value`
);
Expand All @@ -367,6 +367,9 @@ export class BuilderOptionsPlugin extends Plugin {
case "replace":
builderOption[target_element] = value;
break;
case "remove":
delete builderOption[target_element];
break;
case "add":
if (!builderOption[target_element]) {
throw new Error(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ export class BuilderColorPicker extends Component {
getUsedCustomColors: { type: Function, optional: true },
selectedTab: { type: String, optional: true },
defaultColor: { type: String, optional: true },
colorPrefix: { type: String, optional: true },
};
static defaultProps = {
getUsedCustomColors: () => [],
Expand All @@ -133,7 +134,7 @@ export class BuilderColorPicker extends Component {
applyColorPreview: onPreview,
applyColorResetPreview: onPreviewRevert,
getUsedCustomColors: this.props.getUsedCustomColors,
colorPrefix: "color-prefix-",
colorPrefix: this.props.colorPrefix || "color-prefix-",
showRgbaField: true,
noTransparency: this.props.noTransparency,
enabledTabs: this.props.enabledTabs,
Expand Down
2 changes: 1 addition & 1 deletion addons/html_builder/static/src/core/color_style_plugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,4 @@ class ColorStylePlugin extends Plugin {
}
}

registry.category("website-plugins").add(ColorStylePlugin.id, ColorStylePlugin);
registry.category("builder-plugins").add(ColorStylePlugin.id, ColorStylePlugin);
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,4 @@ export class CustomizeTabPlugin extends Plugin {
}
}

registry.category("website-plugins").add(CustomizeTabPlugin.id, CustomizeTabPlugin);
registry.category("builder-plugins").add(CustomizeTabPlugin.id, CustomizeTabPlugin);
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export class DisableSnippetsPlugin extends Plugin {
};

setup() {
this.snippetModel = this.services["html_builder.snippets"];
this.snippetModel = this.config.snippetModel;
this._disableSnippets = this.disableUndroppableSnippets.bind(this);

// TODO only for website ?
Expand Down Expand Up @@ -65,6 +65,9 @@ export class DisableSnippetsPlugin extends Plugin {
}
};
const canDrop = (snippet) => {
if (!snippet) {
return false;
}
const snippetEl = snippet.content;
return !!dropAreasBySelector.find(
({ selector, exclude, dropAreaEls }) =>
Expand Down
4 changes: 3 additions & 1 deletion addons/html_builder/static/src/core/drag_and_drop_plugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,9 @@ export class DragAndDropPlugin extends Plugin {
this.document.defaultView !== window ? this.document.defaultView : false;

const scrollingElement = () =>
this.dependencies.dropzone.getDropRootElement() || getScrollingElement(this.document);
this.dependencies.dropzone.getDropRootElement() ||
this.config.getExternalScrollableAncestor?.() ||
getScrollingElement(this.document);

const dragAndDropOptions = {
ref: { el: element },
Expand Down
2 changes: 1 addition & 1 deletion addons/html_builder/static/src/core/drop_zone_plugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export class DropZonePlugin extends Plugin {
];

setup() {
this.snippetModel = this.services["html_builder.snippets"];
this.snippetModel = this.config.snippetModel;
this.dropzoneSelectors = this.getResource("dropzone_selector");
this.iframe = this.document.defaultView.frameElement;
}
Expand Down
5 changes: 4 additions & 1 deletion addons/html_builder/static/src/core/setup_editor_plugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export class SetupEditorPlugin extends Plugin {
resources = {
clean_for_save_handlers: this.cleanForSave.bind(this),
normalize_handlers: withSequence(0, this.setContenteditable.bind(this)),
o_editable_selectors: "[data-oe-model]",
};

setup() {
Expand All @@ -20,7 +21,9 @@ export class SetupEditorPlugin extends Plugin {
return;
}
// Add the `o_editable` class on the editable elements
let editableEls = this.getEditableElements("[data-oe-model]")
let editableEls = this.getEditableElements(
this.getResource("o_editable_selectors").join(", ")
)
.filter((el) => !el.matches("link, script"))
.filter((el) => !el.hasAttribute("data-oe-readonly"))
.filter(
Expand Down
4 changes: 2 additions & 2 deletions addons/html_builder/static/src/core/version_control_plugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export class VersionControlPlugin extends Plugin {
return this.accessPerOutdatedEl.get(el);
}
const snippetKey = el.dataset.snippet;
const snippet = this.services["html_builder.snippets"].getOriginalSnippet(snippetKey);
const snippet = this.config.snippetModel.getOriginalSnippet(snippetKey);
let isUpToDate = true;
if (snippet) {
const {
Expand All @@ -34,7 +34,7 @@ export class VersionControlPlugin extends Plugin {
}
replaceWithNewVersion(el) {
const snippetKey = el.dataset.snippet;
const snippet = this.services["html_builder.snippets"].getOriginalSnippet(snippetKey);
const snippet = this.config.snippetModel.getOriginalSnippet(snippetKey);
const cloneEl = snippet.content.cloneNode(true);
el.replaceWith(cloneEl);
this.dependencies["builderOptions"].updateContainers(cloneEl);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ class AlertOptionPlugin extends Plugin {
withSequence(before(WIDTH), {
template: "html_builder.AlertOption",
selector: ".s_alert",
name: "alertTypeOption",
}),
],
so_content_addition_selector: [".s_alert"],
Expand Down Expand Up @@ -48,4 +49,4 @@ export class AlertIconAction extends BuilderAction {
return iconEl.classList.contains(className);
}
}
registry.category("website-plugins").add(AlertOptionPlugin.id, AlertOptionPlugin);
registry.category("builder-plugins").add(AlertOptionPlugin.id, AlertOptionPlugin);
Original file line number Diff line number Diff line change
Expand Up @@ -220,5 +220,5 @@ export class DynamicColorAction extends BuilderAction {
}

registry
.category("website-plugins")
.category("builder-plugins")
.add(BackgroundImageOptionPlugin.id, BackgroundImageOptionPlugin);
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { ImageFilterOption } from "@html_builder/plugins/image/image_filter_opti
import { ImageFormatOption } from "@html_builder/plugins/image/image_format_option";

export class BackgroundOption extends BaseOptionComponent {
static template = "website.BackgroundOption";
static template = "html_builder.BackgroundOption";
static components = {
BackgroundImageOption,
BackgroundPositionOption,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<templates xml:space="preserve">

<t t-name="website.BackgroundOption">
<t t-name="html_builder.BackgroundOption">
<!-- BackgroundToggler -->
<BuilderRow label.translate="Background" t-if="props.withColors or props.withImages">
<!-- todo adapt when colorpicker is implemented: snippet_options_background_color_widget-->
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { applyFunDependOnSelectorAndExclude } from "@website/builder/plugins/utils";
import { applyFunDependOnSelectorAndExclude } from "@html_builder/plugins/utils";
import { Plugin } from "@html_editor/plugin";
import { registry } from "@web/core/registry";

Expand All @@ -22,4 +22,4 @@ class BackgroundOptionPlugin extends Plugin {
editingEl.classList.add("o_colored_level");
}
}
registry.category("website-plugins").add(BackgroundOptionPlugin.id, BackgroundOptionPlugin);
registry.category("builder-plugins").add(BackgroundOptionPlugin.id, BackgroundOptionPlugin);
Original file line number Diff line number Diff line change
Expand Up @@ -121,5 +121,5 @@ export class BackgroundPositionOverlayAction extends BuilderAction {
}

registry
.category("website-plugins")
.category("builder-plugins")
.add(BackgroundPositionOptionPlugin.id, BackgroundPositionOptionPlugin);
Original file line number Diff line number Diff line change
Expand Up @@ -458,5 +458,5 @@ class BackgroundShapeColorAction extends BaseAnimationAction {
}

registry
.category("website-plugins")
.category("builder-plugins")
.add(BackgroundShapeOptionPlugin.id, BackgroundShapeOptionPlugin);
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,4 @@ class BlockAlignmentOptionPlugin extends Plugin {
};
}

registry.category("website-plugins").add(BlockAlignmentOptionPlugin.id, BlockAlignmentOptionPlugin);
registry.category("builder-plugins").add(BlockAlignmentOptionPlugin.id, BlockAlignmentOptionPlugin);
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { BaseOptionComponent, useDomState } from "@html_builder/core/utils";
import { BaseOptionComponent, useDomState, useGetItemValue } from "@html_builder/core/utils";

export class BorderConfigurator extends BaseOptionComponent {
static template = "html_builder.BorderConfiguratorOption";
Expand All @@ -17,10 +17,16 @@ export class BorderConfigurator extends BaseOptionComponent {

setup() {
super.setup();
this.getItemValue = useGetItemValue();
this.state = useDomState((editingElement) => ({
hasBorder: this.hasBorder(editingElement),
}));
}

get showBorderRadiusOption() {
return this.props.withRoundCorner && this.state.hasBorder;
}

getStyleActionParam(param) {
return `border-${this.props.direction ? this.props.direction + "-" : ""}${param}`;
}
Expand Down
Loading