Skip to content
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

wip #4196

Open
wants to merge 86 commits into
base: master-mysterious-egg
Choose a base branch
from
Open

wip #4196

Changes from 1 commit
Commits
Show all changes
86 commits
Select commit Hold shift + click to select a range
133dbc9
[ADD] create mysterious_egg module
fdardenne Oct 9, 2024
7d0a9b0
shape[1].imgSize
Goaman Feb 19, 2025
8eac4ca
combine background shape and image shape selector
Goaman Feb 25, 2025
2df0238
consistency naming
Goaman Feb 25, 2025
e75d0d6
params for shorthand actions
bso-odoo Feb 19, 2025
cfe4e01
REF Layout option first part
FrancoisGe Feb 24, 2025
5558de6
set shape colors
Goaman Feb 26, 2025
ea4171a
FIX nb columns switch mobile
FrancoisGe Feb 26, 2025
aceddfc
shape transform + small refactor shape api
Goaman Feb 27, 2025
8b85760
Trigger onChange with arrows + update multi value
robinlej Feb 26, 2025
d07c799
remove useless addStep
FrancoisGe Feb 27, 2025
ad3ed57
Fix blocks tab and snippets style and xml template + add tooltips
sobo-odoo Feb 24, 2025
d2fe1b2
add button options without the custom options
Jinjiu96 Feb 21, 2025
db355eb
small fix to pass the target position to drag&drop
Jinjiu96 Feb 26, 2025
1cd5ebe
Chart BackgroundOption
robinlej Feb 26, 2025
c21ee9e
Add default BuilderInput styles
robinlej Feb 26, 2025
b030fdc
ChartOption & ChartOptionPlugin
robinlej Feb 26, 2025
5f75262
Restart chart interaction on input (previewing history step)
robinlej Feb 26, 2025
a8405eb
getUsedCustomColors in BuilderColorPicker
robinlej Feb 26, 2025
34df8bd
ChartOption tests
robinlej Feb 27, 2025
0d07c80
shape animation speed
Goaman Feb 27, 2025
f0a44ad
[REF] html_builder: AddElementOption, SpacingOption
sebgeelen Feb 27, 2025
61990a5
fix ColorPicker
robinlej Feb 28, 2025
c27c584
lint
agau-odoo Feb 28, 2025
10875d7
move unit and saveUnit to BuilderNumberInput
agau-odoo Feb 28, 2025
17a6371
code cleanup
agau-odoo Feb 28, 2025
7d90a19
fix datetime picker test indeterminism
agau-odoo Feb 28, 2025
f914f34
dynamic svg option + withGradient in color picker
bso-odoo Jan 31, 2025
799966d
add grid image option
Jinjiu96 Feb 27, 2025
374303a
Restore container selection when undo/redo
fdardenne Feb 26, 2025
04446d1
Fallback container to parent if target disappear
fdardenne Feb 26, 2025
56dcce0
ImageGallery restore the container selection
fdardenne Feb 26, 2025
feb7bb1
Fix BorderConfigurator
robinlej Mar 4, 2025
2b638cc
Fix BuilderNumberInput with trailing space
robinlej Mar 4, 2025
fc39e1d
Sanitize BuilderNumberInput on input/change
robinlej Mar 4, 2025
bcfebe7
Fix BuilderSelect: revert previews on cancel + better UI
robinlej Feb 28, 2025
b3755bb
fix BuilderColorPicker custom colors + chart option
robinlej Mar 5, 2025
bf47c8c
Card image options
cammarosano Feb 26, 2025
a6e6d0b
Implement nomode in image_gallery option
fdardenne Mar 5, 2025
13698f9
Fix customStyleActions apply params order
robinlej Mar 5, 2025
5018a87
Allow multiple values in BuilderNumberInput only if composable
robinlej Mar 5, 2025
7141520
Group BuilderNumberInput tests
robinlej Mar 5, 2025
23bed64
move to /layout_option
FrancoisGe Feb 28, 2025
d42294a
fix rebase
ged-odoo Mar 6, 2025
004490c
add only grid/column
FrancoisGe Mar 5, 2025
87604ac
REF API builder_style_actions
FrancoisGe Mar 5, 2025
f5d16d9
small imp
FrancoisGe Mar 5, 2025
cb05a41
Add min & max props on BuilderNumberInput
robinlej Mar 5, 2025
eb7f939
oops
robinlej Mar 5, 2025
5a9c91f
VerticalJustifyOption
blse-odoo Mar 5, 2025
8dadcbf
fix target of ContentWidthOption (aka ContainerWidth)
blse-odoo Mar 5, 2025
979109d
shadow option: fix svgs buttons
fdardenne Mar 6, 2025
ad5b88e
image_gallery_option: add spacing between images
fdardenne Mar 6, 2025
867fc05
builder_range: Fix style
fdardenne Mar 6, 2025
d170ee5
remove
FrancoisGe Mar 5, 2025
cac11b3
add BuilderUrlPicker
agau-odoo Feb 24, 2025
947ffa1
fix isActive in ButtonGroups
FrancoisGe Mar 6, 2025
51854b7
[FIX] Firefox dirty mutations with ZWS
robinlej Mar 6, 2025
f81c815
fix rebase
ged-odoo Mar 6, 2025
694a961
add gallery element option
Jinjiu96 Feb 27, 2025
1ece0ff
fix import
FrancoisGe Mar 7, 2025
7accd4f
Better accessibility on blocks tab
robinlej Feb 28, 2025
82697c9
Fix multi-word buttons
robinlej Feb 28, 2025
88c14f9
Open options on snippet drop
robinlej Mar 6, 2025
0a7be37
theme options
bso-odoo Mar 4, 2025
9236e22
Snippet add dialog tests: make it green
fdardenne Mar 7, 2025
5324e40
Poc Custom mutation
FrancoisGe Mar 6, 2025
4e2e347
Add comment
loco-odoo Mar 6, 2025
046b78b
[FIX] delete background image
loco-odoo Feb 28, 2025
2511d18
Starts interaction at action preview and at normalize
loco-odoo Mar 10, 2025
8a42639
update of apply to mechanism
loco-odoo Mar 10, 2025
e6e7345
add gallery_img option into imageGalleryOption and after remove handler
Jinjiu96 Mar 7, 2025
2fb9bb7
Load inside_builder_style bundle in edit mode only
robinlej Mar 11, 2025
1dcf53d
Merge pull request #4180 from odoo-dev/master-mysterious-egg-role-3
fdardenne Mar 11, 2025
96ae65b
fix selector from CardImageOptions + rename CardOptionPlugin to CardW…
blse-odoo Mar 11, 2025
830d306
Merge pull request #4181 from odoo-dev/master-mysterious-egg-2-blse
fdardenne Mar 11, 2025
b0460ec
Map Option
AlessandroLupo Mar 11, 2025
53469b4
builder font family picker
bso-odoo Mar 6, 2025
0a15648
mini fix to handle width style properties
ged-odoo Mar 11, 2025
d61c407
TopMenuVisibility and TopMenuColor and HideFooter
duau-odoo Mar 6, 2025
3178473
moved website_page_config to website_builder
duau-odoo Mar 13, 2025
d2e31a9
Get the right selector siblings/children
sobo-odoo Mar 7, 2025
70c3ce0
Disable undroppable snippets
sobo-odoo Mar 13, 2025
647da49
Filter the options target properly + add `noCheck` (=> `editableOnly`)
sobo-odoo Mar 10, 2025
ae62461
Check the elements before adding the overlay options on them
sobo-odoo Mar 10, 2025
a369da9
wip
ged-odoo Mar 12, 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
10 changes: 5 additions & 5 deletions addons/html_builder/static/src/builder.js
Original file line number Diff line number Diff line change
@@ -68,17 +68,17 @@ export class Builder extends Component {
{
Plugins,
onChange: ({ isPreviewing }) => {
this.state.canUndo = this.editor.shared.history.canUndo();
this.state.canRedo = this.editor.shared.history.canRedo();
if (!isPreviewing) {
this.state.canUndo = this.editor.shared.history.canUndo();
this.state.canRedo = this.editor.shared.history.canRedo();
this.updateInvisibleEls();
editorBus.trigger("UPDATE_EDITING_ELEMENT");
editorBus.trigger("DOM_UPDATED");
}
editorBus.trigger("UPDATE_EDITING_ELEMENT");
editorBus.trigger("DOM_UPDATED", { isPreviewing });
},
resources: {
on_mobile_preview_clicked: () => {
editorBus.trigger("DOM_UPDATED", { isPreviewing: false });
editorBus.trigger("DOM_UPDATED");
},
change_current_options_containers_listeners: (currentOptionsContainers) => {
this.state.currentOptionsContainers = currentOptionsContainers;
7 changes: 1 addition & 6 deletions addons/html_builder/static/src/core/building_blocks/utils.js
Original file line number Diff line number Diff line change
@@ -192,12 +192,7 @@ export function useSelectableComponent(id, { onItemChange } = {}) {
}

onMounted(refreshCurrentItem);
useBus(env.editorBus, "DOM_UPDATED", (ev) => {
if (ev.detail.isPreviewing) {
return;
}
refreshCurrentItem();
});
useBus(env.editorBus, "DOM_UPDATED", refreshCurrentItem);
function cleanSelectedItem(...args) {
if (currentSelectedItem) {
currentSelectedItem.clean(...args);
Original file line number Diff line number Diff line change
@@ -134,11 +134,11 @@ export class DropZonePlugin extends Plugin {
}
const dropZone = position
? closest(touching(this.dropZoneElements, position), position) ||
closest(this.dropZoneElements, position)
closest(this.dropZoneElements, position)
: closest(this.dropZoneElements, {
x: window.innerWidth / 2,
y: window.innerHeight / 2,
});
x: window.innerWidth / 2,
y: window.innerHeight / 2,
});
if (!dropZone) {
this.clearDropZone();
return;
@@ -160,7 +160,6 @@ export class DropZonePlugin extends Plugin {
this.dispatchTo("on_add_element_handlers", { elementToAdd: elementToAdd });
scrollToWindow(elementToAdd, { behavior: "smooth", offset: 50 });
this.dependencies.history.addStep();
this.dispatchTo("update_interactions", elementToAdd);
};
}
}
Original file line number Diff line number Diff line change
@@ -50,7 +50,6 @@ export class ReplacePlugin extends Plugin {
this.dependencies.history.addStep();
this.dependencies["builder-options"].updateContainers(newSnippet);
// TODO post snippet drop (onBuild,...)
this.dispatchTo("update_interactions", newSnippet);
}
}
}
Original file line number Diff line number Diff line change
@@ -5,8 +5,7 @@ export class EditInteractionPlugin extends Plugin {
static id = "edit_interaction";

resources = {
update_interactions: this.startInteractions.bind(this),
on_remove_handlers: this.stopInteractions.bind(this),
normalize_handlers: this.startInteractions.bind(this),
};

setup() {
@@ -22,8 +21,6 @@ export class EditInteractionPlugin extends Plugin {

updateEditInteraction({ detail: { websiteEditService } }) {
this.websiteEditService = websiteEditService;
const targetEl = this.document.querySelector("#wrapwrap");
this.startInteractions(targetEl);
}

startInteractions(element) {
@@ -32,13 +29,6 @@ export class EditInteractionPlugin extends Plugin {
}
this.websiteEditService.update(element, true);
}

stopInteractions(element) {
if (!this.websiteEditService) {
throw new Error("website edit service not loaded");
}
this.websiteEditService.stop(element);
}
}

registry.category("website-plugins").add(EditInteractionPlugin.id, EditInteractionPlugin);
Original file line number Diff line number Diff line change
@@ -64,10 +64,6 @@ export class WebsiteBuilder extends Component {
this.setIframeLoaded();
this.addSystrayItems();
onWillDestroy(() => {
window.parent.document.removeEventListener(
"website_edit_loaded",
this.updateEditInteraction
);
this.websiteService.useMysterious = false;
registry.category("systray").remove("website.WebsiteSystrayItem");
});
Original file line number Diff line number Diff line change
@@ -152,12 +152,12 @@ test("clean another action", async () => {
await click("[data-class-action='my-custom-class1']");
expect(":iframe .test-options-target").toHaveAttribute(
"class",
"test-options-target my-custom-class1 o-paragraph"
"test-options-target o-paragraph my-custom-class1"
);
await click("[data-class-action='my-custom-class2']");
expect(":iframe .test-options-target").toHaveAttribute(
"class",
"test-options-target my-custom-class2 o-paragraph"
"test-options-target o-paragraph my-custom-class2"
);
});
test("clean should provide the next action value", async () => {
@@ -294,8 +294,8 @@ test("apply classAction on multi elements", async () => {
await contains("[data-class-action='my-custom-class']").click();
expect(editableContent).toHaveInnerHTML(`
<div class="test-options-target">
<div class="target-apply my-custom-class o-paragraph">a</div>
<div class="target-apply my-custom-class o-paragraph">b</div>
<div class="target-apply o-paragraph my-custom-class">a</div>
<div class="target-apply o-paragraph my-custom-class">b</div>
</div>`);
});
test("hide/display base on applyTo", async () => {
Original file line number Diff line number Diff line change
@@ -53,7 +53,7 @@ test("hide/display base on applyTo", async () => {

await contains("[data-class-action='my-custom-class']").click();
expect(editableContent).toHaveInnerHTML(
`<div class="parent-target"><div class="child-target b my-custom-class o-paragraph">b</div></div>`
`<div class="parent-target"><div class="child-target b o-paragraph my-custom-class">b</div></div>`
);
expect("[data-class-action='my-custom-class']").toHaveClass("active");
expect(".options-container .o-checkbox").toHaveCount(1);
Original file line number Diff line number Diff line change
@@ -59,7 +59,7 @@ test("hide/display base on applyTo", async () => {

await contains("[data-class-action='my-custom-class']").click();
expect(editableContent).toHaveInnerHTML(
`<div class="parent-target"><div class="child-target b my-custom-class o-paragraph">b</div></div>`
`<div class="parent-target"><div class="child-target b o-paragraph my-custom-class">b</div></div>`
);
expect("[data-class-action='my-custom-class']").toHaveClass("active");
expect(".options-container .o_we_color_preview").toHaveCount(1);
Original file line number Diff line number Diff line change
@@ -61,7 +61,7 @@ test("hide/display base on applyTo", async () => {

await contains("[data-class-action='my-custom-class']").click();
expect(editableContent).toHaveInnerHTML(
`<div class="parent-target"><div class="child-target my-custom-class o-paragraph">b</div></div>`
`<div class="parent-target"><div class="child-target o-paragraph my-custom-class">b</div></div>`
);
expect("[data-class-action='my-custom-class']").toHaveClass("active");
expect("[data-action-id='customAction']").toHaveCount(1);
Original file line number Diff line number Diff line change
@@ -122,7 +122,7 @@ test("hide/display BuilderSelect based on applyTo", async () => {

await contains("[data-class-action='my-custom-class']").click();
expect(editableContent).toHaveInnerHTML(
`<div class="parent-target"><div class="child-target b my-custom-class o-paragraph">b</div></div>`
`<div class="parent-target"><div class="child-target b o-paragraph my-custom-class">b</div></div>`
);
expect("[data-class-action='my-custom-class']").toHaveClass("active");
expect(".options-container button.dropdown-toggle").toHaveCount(1);
@@ -159,7 +159,7 @@ test("hide/display BuilderSelectItem base on applyTo", async () => {

await contains("[data-class-action='my-custom-class']").click();
expect(editableContent).toHaveInnerHTML(
`<div class="parent-target"><div class="child-target my-custom-class o-paragraph">b</div></div>`
`<div class="parent-target"><div class="child-target o-paragraph my-custom-class">b</div></div>`
);
expect("[data-class-action='my-custom-class']").toHaveClass("active");
await contains(".options-container button.dropdown-toggle").click();
Original file line number Diff line number Diff line change
@@ -38,7 +38,7 @@ test("hide/display base on applyTo", async () => {

await contains("[data-class-action='my-custom-class']").click();
expect(editableContent).toHaveInnerHTML(
`<div class="parent-target"><div class="child-target my-custom-class o-paragraph">b</div></div>`
`<div class="parent-target"><div class="child-target o-paragraph my-custom-class">b</div></div>`
);
expect("[data-class-action='my-custom-class']").toHaveClass("active");
expect("[data-action-id='customAction']").toHaveCount(1);
86 changes: 26 additions & 60 deletions addons/html_builder/static/tests/edit_interaction.test.js
Original file line number Diff line number Diff line change
@@ -2,35 +2,19 @@ import { expect, test } from "@odoo/hoot";
import { contains, patchWithCleanup } from "@web/../tests/web_test_helpers";
import { EditInteractionPlugin } from "@html_builder/website_builder/plugins/edit_interaction_plugin";
import {
addActionOption,
addOption,
confirmAddSnippet,
defineWebsiteModels,
openBuilderSidebar,
setupWebsiteBuilder,
setupWebsiteBuilderWithSnippet,
} from "./website_helpers";
import { animationFrame, click, waitFor } from "@odoo/hoot-dom";
import { click, waitFor } from "@odoo/hoot-dom";
import { xml } from "@odoo/owl";

defineWebsiteModels();

test("interactions are started when starting editing", async () => {
await setupWebsiteBuilder("", { openEditor: false });
let websiteEditService;
patchWithCleanup(EditInteractionPlugin.prototype, {
setup() {
super.setup();
this.websiteEditService.update = () => expect.step("update");
websiteEditService = this.websiteEditService;
},
});
await openBuilderSidebar();
window.parent.document.dispatchEvent(
new CustomEvent("transfer_website_edit_service", {
detail: { websiteEditService },
})
);
expect.verifySteps(["update"]);
});

test("dropping a new snippet starts its interaction", async () => {
await setupWebsiteBuilder("", { openEditor: false });
patchWithCleanup(EditInteractionPlugin.prototype, {
@@ -41,8 +25,7 @@ test("dropping a new snippet starts its interaction", async () => {
});
await openBuilderSidebar();
await waitFor(".o-website-builder_sidebar.o_builder_sidebar_open");
expect.verifySteps([]);

expect.verifySteps(["update"]);
await contains(
`.o-snippets-menu #snippet_groups .o_snippet[data-snippet-group='text'] .o_snippet_thumbnail_area`
).click();
@@ -60,54 +43,37 @@ test("replacing a snippet starts the interaction of the new snippet", async () =
});
await openBuilderSidebar();
await waitFor(":iframe [data-snippet='s_text_block']");
expect.verifySteps([]);
expect.verifySteps(["update"]);
await click(`:iframe [data-snippet="s_text_block"]`);
await contains(".btn.o_snippet_replace").click();
await confirmAddSnippet("s_title");
expect.verifySteps(["update"]);
});

test("removing a snippet stops its interaction", async () => {
await setupWebsiteBuilderWithSnippet("s_title", { openEditor: false });
patchWithCleanup(EditInteractionPlugin.prototype, {
setup() {
super.setup();
this.websiteEditService.stop = () => expect.step("stop");
test("ensure order of operations when hovering an option", async () => {
addActionOption({
customAction: {
load: async () => {
expect.step("load");
},
apply: ({ editingElement }) => {
editingElement.classList.add("new_class");
expect.step("apply");
},
},
});
await openBuilderSidebar();
await waitFor(":iframe [data-snippet='s_title']");
expect.verifySteps([]);
await click(`:iframe [data-snippet="s_title"]`);
await contains(".btn.oe_snippet_remove").click();
await animationFrame();
expect.verifySteps(["stop"]);
});

test("throw if edit interactions are started but website_edit service hasn't started", async () => {
await setupWebsiteBuilder("", { openEditor: false });
let plugin;
patchWithCleanup(EditInteractionPlugin.prototype, {
setup() {
super.setup();
this.websiteEditService = undefined;
plugin = this;
},
addOption({
selector: ".test-options-target",
template: xml`<BuilderButton action="'customAction'"/>`,
});
await openBuilderSidebar();
expect(() => plugin.startInteractions()).toThrow("website edit service not loaded");
});

test("throw if edit interactions are stopped but website_edit service hasn't started", async () => {
await setupWebsiteBuilder("", { openEditor: false });
let plugin;
patchWithCleanup(EditInteractionPlugin.prototype, {
setup() {
super.setup();
this.websiteEditService = undefined;
plugin = this;
startInteractions() {
expect.step("startInteractions");
},
});
await openBuilderSidebar();
expect(() => plugin.stopInteractions()).toThrow("website edit service not loaded");
await setupWebsiteBuilder(`<div class="test-options-target">b</div>`);
expect.verifySteps(["startInteractions"]);
await contains(":iframe .test-options-target").click();
await contains("[data-action-id='customAction']").hover();
expect.verifySteps(["load", "apply", "startInteractions"]);
});
10 changes: 5 additions & 5 deletions addons/html_builder/static/tests/options/shadow_option.test.js
Original file line number Diff line number Diff line change
@@ -27,23 +27,23 @@ test("edit box-shadow with ShadowOption", async () => {
]);
expect(queryAllValues('[data-action-id="setShadow"] input')).toEqual(["0", "8", "16", "0"]);
expect(":iframe .test-options-target").toHaveOuterHTML(
'<div class="test-options-target shadow o-paragraph" style="box-shadow: rgba(0, 0, 0, 0.15) 0px 8px 16px 0px !important;">b</div>'
'<div class="test-options-target o-paragraph shadow" style="box-shadow: rgba(0, 0, 0, 0.15) 0px 8px 16px 0px !important;">b</div>'
);

await contains('[data-action-param="offsetX"] input').fill(10);
await contains('[data-action-param="offsetY"] input').fill(2, { clean: true });
expect(":iframe .test-options-target").toHaveOuterHTML(
'<div class="test-options-target shadow o-paragraph" style="box-shadow: rgba(0, 0, 0, 0.15) 10px 82px 16px 0px !important;">b</div>'
'<div class="test-options-target o-paragraph shadow" style="box-shadow: rgba(0, 0, 0, 0.15) 10px 82px 16px 0px !important;">b</div>'
);

await contains('[data-action-param="blur"] input').fill(3);
expect(":iframe .test-options-target").toHaveOuterHTML(
'<div class="test-options-target shadow o-paragraph" style="box-shadow: rgba(0, 0, 0, 0.15) 10px 82px 163px 0px !important;">b</div>'
'<div class="test-options-target o-paragraph shadow" style="box-shadow: rgba(0, 0, 0, 0.15) 10px 82px 163px 0px !important;">b</div>'
);

await contains('[data-action-param="spread"] input').fill(4);
expect(":iframe .test-options-target").toHaveOuterHTML(
'<div class="test-options-target shadow o-paragraph" style="box-shadow: rgba(0, 0, 0, 0.15) 10px 82px 163px 4px !important;">b</div>'
'<div class="test-options-target o-paragraph shadow" style="box-shadow: rgba(0, 0, 0, 0.15) 10px 82px 163px 4px !important;">b</div>'
);

await contains('.options-container button[title="Inset"]').click();
@@ -56,7 +56,7 @@ test("edit box-shadow with ShadowOption", async () => {
]);
expect(queryAllValues('[data-action-id="setShadow"] input')).toEqual(["10", "82", "163", "4"]);
expect(":iframe .test-options-target").toHaveOuterHTML(
'<div class="test-options-target shadow o-paragraph" style="box-shadow: rgba(0, 0, 0, 0.15) 10px 82px 163px 4px inset !important;">b</div>'
'<div class="test-options-target o-paragraph shadow" style="box-shadow: rgba(0, 0, 0, 0.15) 10px 82px 163px 4px inset !important;">b</div>'
);

await contains(".options-container button:contains(None)").click();
42 changes: 42 additions & 0 deletions addons/html_builder/static/tests/preview_mode.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { Plugin } from "@html_editor/plugin";
import { after, expect, test } from "@odoo/hoot";
import { xml } from "@odoo/owl";
import { contains } from "@web/../tests/web_test_helpers";
import { registry } from "@web/core/registry";
import { uniqueId } from "@web/core/utils/functions";
import { addOption, defineWebsiteModels, setupWebsiteBuilder } from "./website_helpers";

defineWebsiteModels();

test("do not update builder if in preview mode", async () => {
const pluginId = uniqueId("test-action-plugin");
class P extends Plugin {
static id = pluginId;
static dependencies = ["history"];
resources = {
builder_actions: {
customAction: {
apply: ({ editingElement }) => {
editingElement.classList.add("applied");
this.dependencies.history.addStep();
},
isApplied: ({ editingElement }) => editingElement.classList.contains("applied"),
},
},
};
}
registry.category("website-plugins").add(pluginId, P);
after(() => {
registry.category("website-plugins").remove(P);
});
addOption({
selector: ".test-options-target",
template: xml`<BuilderButton id="'id1'" action="'customAction'">b1</BuilderButton>
<BuilderButton classAction="'b2_class'" t-if="this.isActiveItem('id1')">b2</BuilderButton>`,
});
await setupWebsiteBuilder(`<div class="test-options-target">b</div>`);
await contains(":iframe .test-options-target").click();
await contains("[data-action-id='customAction']").hover();
expect("[data-class-action='b2_class']").not.toBeVisible();
expect(".o-snippets-top-actions .fa-undo").not.toBeEnabled();
});
8 changes: 6 additions & 2 deletions addons/html_editor/static/src/core/history_plugin.js
Original file line number Diff line number Diff line change
@@ -591,7 +591,6 @@ export class HistoryPlugin extends Plugin {
if (stepState) {
this.stepsStates.set(currentStep.id, stepState);
}

this.handleObserverRecords();
const currentMutationsCount = currentStep.mutations.length;
if (currentMutationsCount === 0) {
@@ -983,6 +982,7 @@ export class HistoryPlugin extends Plugin {
let applied = false;
// TODO ABD TODO @phoenix: selection may become obsolete, it should evolve with mutations.
const selectionToRestore = this.dependencies.selection.preserveSelection();
const extraToRestore = {...this.currentStep.extra};
return () => {
if (applied) {
return;
@@ -996,6 +996,7 @@ export class HistoryPlugin extends Plugin {
this.handleObserverRecords();
// TODO ABD TODO @phoenix: evaluate if the selection is not restorable at the desired position
selectionToRestore.restore();
this.currentStep.extra = extraToRestore;
this.dispatchTo("restore_savepoint_handlers");
};
}
@@ -1012,7 +1013,10 @@ export class HistoryPlugin extends Plugin {
revertOperation();
revertOperation = this.makeSavePoint();
this.isPreviewing = true;
return operation(...args);
operation(...args);
// The operation should be similar than in the 'commit'
// (normalize etc...) hence the 'addStep'.
this.addStep();
},
commit: (...args) => {
revertOperation();
16 changes: 13 additions & 3 deletions addons/html_editor/static/tests/history.test.js
Original file line number Diff line number Diff line change
@@ -434,18 +434,24 @@ describe("makePreviewableOperation", () => {
newElem.setAttribute("id", elemId);
div.appendChild(newElem);
});
const numberOfSteps = history.steps.length;
let numberOfSteps = history.steps.length;
const numberOfCurrentMutations = history.currentStep.mutations.length;
previewableAddParagraph.preview("first");
// step added by the preview
numberOfSteps += 1;
await animationFrame();
expect(history.steps.length).toBe(numberOfSteps);
expect("#first").toHaveCount(1);
previewableAddParagraph.preview("second");
// step added by the revert of the first preview and the second preview
numberOfSteps += 2;
await animationFrame();
expect(history.steps.length).toBe(numberOfSteps);
expect("#first").toHaveCount(0);
expect("#second").toHaveCount(1);
previewableAddParagraph.revert();
// step added by the revert
numberOfSteps += 1;
await animationFrame();
expect("#first").toHaveCount(0);
expect("#second").toHaveCount(0);
@@ -463,16 +469,20 @@ describe("makePreviewableOperation", () => {
newElem.setAttribute("id", elemId);
div.appendChild(newElem);
});
const numberOfSteps = history.steps.length;
let numberOfSteps = history.steps.length;
previewableAddParagraph.preview("first");
// step added by the preview
numberOfSteps += 1;
await animationFrame();
expect(history.steps.length).toBe(numberOfSteps);
expect("#first").toHaveCount(1);
previewableAddParagraph.commit("second");
// step added by the revert due to the commit and the commit in itself
numberOfSteps += 2;
await animationFrame();
expect("#first").toHaveCount(0);
expect("#second").toHaveCount(1);
expect(history.steps.length).toBe(numberOfSteps + 1);
expect(history.steps.length).toBe(numberOfSteps);
});
});