Skip to content

Commit b51a289

Browse files
committed
product image option plugin
1 parent 4183094 commit b51a289

File tree

6 files changed

+95
-43
lines changed

6 files changed

+95
-43
lines changed

addons/html_builder/static/src/plugins/image/replace_media_option.js

+18-17
Original file line numberDiff line numberDiff line change
@@ -12,33 +12,34 @@ export class ReplaceMediaOption extends BaseOptionComponent {
1212
}
1313
canSetLink(editingElement) {
1414
return (
15-
this.isImageSupportedForStyle(editingElement) &&
15+
isImageSupportedForStyle(editingElement) &&
1616
!searchSupportedParentLinkEl(editingElement).matches("a[data-oe-xpath]")
1717
);
1818
}
1919
hasHref(editingElement) {
2020
const parentEl = searchSupportedParentLinkEl(editingElement);
2121
return parentEl.tagName === "A" && parentEl.hasAttribute("href");
2222
}
23-
isImageSupportedForStyle(img) {
24-
if (!img.parentElement) {
25-
return false;
26-
}
23+
}
24+
25+
export function isImageSupportedForStyle(img) {
26+
if (!img.parentElement) {
27+
return false;
28+
}
2729

28-
// See also `[data-oe-type='image'] > img` added as data-exclude of some
29-
// snippet options.
30-
const isTFieldImg = "oeType" in img.parentElement.dataset;
30+
// See also `[data-oe-type='image'] > img` added as data-exclude of some
31+
// snippet options.
32+
const isTFieldImg = "oeType" in img.parentElement.dataset;
3133

32-
// Editable root elements are technically *potentially* supported here (if
33-
// the edited attributes are not computed inside the related view, they
34-
// could technically be saved... but as we cannot tell the computed ones
35-
// apart from the "static" ones, we choose to not support edition at all in
36-
// those "root" cases).
37-
// See also `[data-oe-xpath]` added as data-exclude of some snippet options.
38-
const isEditableRootElement = "oeXpath" in img.dataset;
34+
// Editable root elements are technically *potentially* supported here (if
35+
// the edited attributes are not computed inside the related view, they
36+
// could technically be saved... but as we cannot tell the computed ones
37+
// apart from the "static" ones, we choose to not support edition at all in
38+
// those "root" cases).
39+
// See also `[data-oe-xpath]` added as data-exclude of some snippet options.
40+
const isEditableRootElement = "oeXpath" in img.dataset;
3941

40-
return !isTFieldImg && !isEditableRootElement;
41-
}
42+
return !isTFieldImg && !isEditableRootElement;
4243
}
4344

4445
export function searchSupportedParentLinkEl(editingElement) {

addons/html_builder/static/src/plugins/image/replace_media_option.xml

+2-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@
66
<BuilderButton
77
action="'replaceMedia'"
88
title.translate="Replace image"
9-
className="'o_we_bg_success'"
9+
className="'flex-grow-1'"
10+
type="'success'"
1011
preview="false"
1112
label.translate="Replace" />
1213
<BuilderButton icon="'fa-link'"

addons/html_builder/static/src/website_builder/plugins/options/animate_option.js

+1-24
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { KeepLast } from "@web/core/utils/concurrency";
22
import { BaseOptionComponent, useDomState } from "@html_builder/core/utils";
3+
import { isImageSupportedForStyle } from "@html_builder/plugins/image/replace_media_option";
34

45
export class AnimateOption extends BaseOptionComponent {
56
static template = "html_builder.AnimateOption";
@@ -75,27 +76,3 @@ export class AnimateOption extends BaseOptionComponent {
7576
return hasDirection;
7677
}
7778
}
78-
79-
/**
80-
* @param {HTMLImageElement} img
81-
* @returns {Boolean}
82-
*/
83-
export function isImageSupportedForStyle(img) {
84-
if (!img.parentElement) {
85-
return false;
86-
}
87-
88-
// See also `[data-oe-type='image'] > img` added as data-exclude of some
89-
// snippet options.
90-
const isTFieldImg = "oeType" in img.parentElement.dataset;
91-
92-
// Editable root elements are technically *potentially* supported here (if
93-
// the edited attributes are not computed inside the related view, they
94-
// could technically be saved... but as we cannot tell the computed ones
95-
// apart from the "static" ones, we choose to not support edition at all in
96-
// those "root" cases).
97-
// See also `[data-oe-xpath]` added as data-exclude of some snippet options.
98-
const isEditableRootElement = "oeXpath" in img.dataset;
99-
100-
return !isTFieldImg && !isEditableRootElement;
101-
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<templates xml:space="preserve">
3+
4+
5+
<t t-inherit="html_builder.ReplaceMediaOption" t-inherit-mode="extension">
6+
<xpath expr="//BuilderRow[BuilderButton[@action=&quot;'replaceMedia'&quot;]]" position="after">
7+
<BuilderRow label.translate="Re-order">
8+
<BuilderButtonGroup preview="false" action="'setPosition'">
9+
<BuilderButton icon="'fa-angle-double-left'" title.translate="Move to first" actionValue="'first'"/>
10+
<BuilderButton icon="'fa-angle-left'" title.translate="Move to previous" actionValue="'left'"/>
11+
<BuilderButton icon="'fa-angle-right'" title.translate="Move to next" actionValue="'right'"/>
12+
<BuilderButton icon="'fa-angle-double-right'" title.translate="Move to last" actionValue="'last'"/>
13+
</BuilderButtonGroup>
14+
</BuilderRow>
15+
</xpath>
16+
17+
<xpath expr="//BuilderRow[BuilderButton[@action=&quot;'replaceMedia'&quot;]]" position="inside">
18+
<BuilderButton
19+
action="'removeMedia'"
20+
preview="false"
21+
type="'danger'"
22+
className="'flex-grow-1'"
23+
label.translate="Remove" />
24+
</xpath>
25+
</t>
26+
27+
</templates>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import { Plugin } from "@html_editor/plugin";
2+
import { rpc } from "@web/core/network/rpc";
3+
import { registry } from "@web/core/registry";
4+
5+
export class ProductImageOptionPlugin extends Plugin {
6+
static id = "ProductImageOption";
7+
resources = {
8+
builder_options: {
9+
editableOnly: false,
10+
},
11+
builder_actions: {
12+
/*
13+
* Change sequence of product page images
14+
*/
15+
setPosition: {
16+
reload: {},
17+
apply: async ({ editingElement: el, value }) => {
18+
const params = {
19+
image_res_model: el.parentElement.dataset.oeModel,
20+
image_res_id: el.parentElement.dataset.oeId,
21+
move: value,
22+
};
23+
24+
await rpc("/shop/product/resequence-image", params);
25+
},
26+
},
27+
/*
28+
* Removes the image in the back-end
29+
*/
30+
removeMedia: {
31+
reload: {},
32+
apply: async ({ editingElement: el }) => {
33+
if (el.parentElement.dataset.oeModel === "product.image") {
34+
// Unlink the "product.image" record as it is not the main product image.
35+
await this.services.orm.unlink("product.image", [
36+
parseInt(el.parentElement.dataset.oeId),
37+
]);
38+
}
39+
el.remove();
40+
},
41+
},
42+
},
43+
};
44+
}
45+
46+
registry.category("website-plugins").add(ProductImageOptionPlugin.id, ProductImageOptionPlugin);

addons/website/static/tests/tours/media_dialog.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ registerWebsitePreviewTour("website_media_dialog_image_shape", {
156156
},
157157
{
158158
content: "Open MediaDialog from an image",
159-
trigger: ".o_we_bg_success[data-action-id='replaceMedia']",
159+
trigger: ".btn-success[data-action-id='replaceMedia']",
160160
run: "click",
161161
},
162162
{

0 commit comments

Comments
 (0)