Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@
<templates xml:space="preserve">

<t t-name="html_builder.BuilderButton">
<BuilderComponent dependencies="props.dependencies">
<BuilderComponent>
<button type="button" class="btn btn-primary"
t-att-data-action-id="this.props.action"
t-att-data-class-action="this.props.classAction"
t-att-data-style-action="this.props.styleAction"
t-att-data-action-id="this.props.action || this.env.weContext.action"
t-att-data-action-param="this.props.actionParam || this.env.weContext.actionParam"
t-att-data-action-value="this.props.actionValue"
t-att-data-class-action="this.props.classAction || this.env.weContext.classAction"
t-att-data-style-action="this.props.styleAction || this.env.weContext.styleAction"
t-att-data-style-action-value="this.props.styleActionValue"
t-att-data-attribute-action="this.props.attributeAction"
t-att-data-attribute-action="this.props.attributeAction || this.env.weContext.attributeAction"
t-att-data-attribute-action-value="this.props.attributeActionValue"
t-att-class="className"
t-att-title="props.title"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ export class BuilderButtonGroup extends Component {
static props = {
...basicContainerBuilderComponentProps,
id: { type: String, optional: true },
dependencies: { type: [String, Array], optional: true },
slots: { type: Object, optional: true },
};
static components = { BuilderComponent };
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<templates xml:space="preserve">

<t t-name="html_builder.BuilderButtonGroup">
<BuilderComponent dependencies="props.dependencies">
<BuilderComponent>
<div class="btn-group w-100" t-ref="root">
<t t-slot="default"/>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<templates xml:space="preserve">

<t t-name="html_builder.BuilderCheckbox">
<BuilderComponent dependencies="props.dependencies">
<BuilderComponent>
<div t-att-data-action-id="this.props.action">
<CheckBox className="getClassName()" onChange="onChange" value="state.isActive"/>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<templates xml:space="preserve">

<t t-name="html_builder.BuilderColorPicker">
<BuilderComponent dependencies="props.dependencies">
<BuilderComponent>
<div>
<ColorSelector
type="this.colorType"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,32 +1,15 @@
import { Component, onWillDestroy, xml } from "@odoo/owl";
import { useDependencies, useDomState } from "./utils";
import { useBus } from "@web/core/utils/hooks";
import { Component, xml } from "@odoo/owl";
import { useDomState } from "./utils";

export class BuilderComponent extends Component {
static template = xml`<t t-if="this.state.isVisible"><t t-slot="default"/></t>`;
static props = {
dependencies: { type: [String, { type: Array, element: String }], optional: true },
slots: { type: Object },
};

setup() {
const isDependenciesVisible = useDependencies(this.props.dependencies);
const isVisible = () =>
!!this.env.getEditingElement() && (!this.props.dependencies || isDependenciesVisible());
this.state = useDomState(() => ({
isVisible: isVisible(),
this.state = useDomState((editingElement) => ({
isVisible: !!editingElement,
}));
useBus(this.env.dependencyManager, "dependency-updated", () => {
this.state.isVisible = isVisible();
});
if (this.props.dependencies?.length) {
const listener = () => {
this.state.isVisible = isVisible();
};
this.env.dependencyManager.addEventListener("dependency-updated", listener);
onWillDestroy(() => {
this.env.dependencyManager.removeEventListener("dependency-updated", listener);
});
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { BuilderComponent } from "./builder_component";

export class BuilderContext extends Component {
static template = xml`
<BuilderComponent dependencies="props.dependencies">
<BuilderComponent>
<t t-slot="default"/>
</BuilderComponent>
`;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<templates xml:space="preserve">

<t t-name="html_builder.BuilderNumberInput">
<BuilderComponent dependencies="props.dependencies">
<BuilderComponent>
<div class="d-flex flex-row flex-nowrap align-items-center"
style="width: 60px"
t-att-data-action-id="props.action"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<templates xml:space="preserve">

<t t-name="html_builder.BuilderRange">
<BuilderComponent dependencies="props.dependencies">
<BuilderComponent>
<div class="d-flex flex-row flex-nowrap align-items-center" t-att-data-action-id="props.action" style="width: 60px">
<input
type="range"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ export class BuilderRow extends Component {
static props = {
...basicContainerBuilderComponentProps,
label: String,
dependencies: { type: [String, Array], optional: true },
tooltip: { type: String, optional: true },
slots: { type: Object, optional: true },
level: { type: Number, optional: true },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<templates xml:space="preserve">

<t t-name="html_builder.BuilderRow">
<BuilderComponent dependencies="props.dependencies">
<BuilderComponent>
<div class="d-flex p-1 px-2 hb-row" t-att-class="this.getLevelClass()" t-ref="root" t-att-data-label="props.label">
<div class="d-flex" style="flex-grow: 0.4; flex-basis: 0; min-width: 0;" t-att-data-tooltip="props.tooltip">
<span class="text-nowrap text-truncate" t-out="props.label"/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<templates xml:space="preserve">

<t t-name="html_builder.BuilderSelect">
<BuilderComponent dependencies="props.dependencies">
<BuilderComponent>
<!-- Render the SelectItem(s) into an invisible node to ensure the label of the
button is being set. -->
<div t-ref="root">
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Component, useRef } from "@odoo/owl";
import { Component, onMounted, useRef } from "@odoo/owl";
import { clickableBuilderComponentProps, useSelectableItemComponent } from "./utils";
import { BuilderComponent } from "./builder_component";

Expand All @@ -17,9 +17,19 @@ export class BuilderSelectItem extends Component {
throw new Error("BuilderSelectItem must be used inside a BuilderSelect component.");
}
const item = useRef("item");
let label = "";
const getLabel = () => {
// todo: it's not clear why the item.el?.innerHTML is not set at in
// some cases. We fallback on a previously set value to circumvent
// the problem, but it should be investigated.
label = item.el?.innerHTML || label || "";
return label;
};

onMounted(getLabel);

const { state, operation } = useSelectableItemComponent(this.props.id, {
getLabel: () => item.el?.innerHTML || "",
getLabel,
});
this.state = state;
this.onClick = () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,18 @@
<templates xml:space="preserve">

<t t-name="html_builder.BuilderSelectItem">
<BuilderComponent dependencies="props.dependencies">
<BuilderComponent>
<div
class="d-flex flex-column cursor-pointer"
t-att-class="{'active': this.state.isActive}"
t-att-data-action-id="props.action"
t-att-data-class-action="this.props.classAction"
t-att-data-attribute-action-id="props.attributeAction || this.env.weContext.attributeAction"
t-att-data-attribute-action-value-id="props.attributeActionValue"
t-att-data-action-id="this.props.action || this.env.weContext.action"
t-att-data-action-param="this.props.actionParam || this.env.weContext.actionParam"
t-att-data-action-value="this.props.actionValue"
t-att-data-class-action="this.props.classAction || this.env.weContext.classAction"
t-att-data-style-action="this.props.styleAction || this.env.weContext.styleAction"
t-att-data-style-action-value="this.props.styleActionValue"
t-att-data-attribute-action="this.props.attributeAction || this.env.weContext.attributeAction"
t-att-data-attribute-action-value="this.props.attributeActionValue"
t-att-title="props.title"
t-on-click="() => this.onClick()"
t-on-mouseenter="() => this.onMouseenter(props.id)"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<templates xml:space="preserve">

<t t-name="html_builder.BuilderTextInput">
<BuilderComponent dependencies="props.dependencies">
<BuilderComponent>
<div class="d-flex flex-row flex-nowrap align-items-center" t-att-data-action-id="props.action" style="width: 60px">
<input
type="text"
Expand Down
81 changes: 58 additions & 23 deletions addons/html_builder/static/src/builder_components/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,16 +47,7 @@ export function useBuilderComponent() {
newEnv.getEditingElement = () => editingElements[0];
}
const weContext = {};
const contextKeys = [
"preview",
"action",
"actionParam",
"classAction",
"attributeAction",
"dataAttributeAction",
"styleAction",
];
for (const key of contextKeys) {
for (const key of basicContainerBuilderComponentPropsNames) {
if (key in comp.props) {
weContext[key] = comp.props[key];
}
Expand Down Expand Up @@ -93,6 +84,43 @@ export function useDependencies(dependencies) {
return isDependenciesVisible;
}

export function useIsActiveItem() {
const env = useEnv();
const listenedKeys = new Set();

function isActive(itemId) {
const isActiveFn = env.dependencyManager.get(itemId)?.isActive;
if (!isActiveFn) {
return false;
}
return isActiveFn();
}

const getState = () => {
const newState = {};
for (const itemId of listenedKeys) {
newState[itemId] = isActive(itemId);
}
return newState;
};
const state = useDomState(getState);
const listener = () => {
const newState = getState();
Object.assign(state, newState);
};
env.dependencyManager.addEventListener("dependency-updated", listener);
onWillDestroy(() => {
env.dependencyManager.removeEventListener("dependency-updated", listener);
});
return function isActiveItem(itemId) {
listenedKeys.add(itemId);
if (state[itemId] === undefined) {
return isActive(itemId);
}
return state[itemId];
};
}

export function useSelectableComponent(id, { onItemChange } = {}) {
useBuilderComponent();
const selectableItems = [];
Expand Down Expand Up @@ -202,7 +230,9 @@ export function useClickableBuilderComponent() {
const { getAllActions, callOperation } = getAllActionsAndOperations(comp);
const getAction = comp.env.editor.shared.builderActions.getAction;
const applyOperation = comp.env.editor.shared.history.makePreviewableOperation(callApply);
const shouldToggle = !comp.env.actionBus;
const shouldToggle = !comp.env.selectableContext;
const inheritedActionIds =
comp.props.inheritedActions || comp.env.weContext.inheritedActions || [];
const hasPreview =
comp.props.preview === true ||
(comp.props.preview === undefined && comp.env.weContext.preview !== false);
Expand Down Expand Up @@ -254,8 +284,8 @@ export function useClickableBuilderComponent() {

function callApply(applySpecs) {
comp.env.selectableContext?.cleanSelectedItem(applySpecs);
const cleans = comp.props.inheritedActions
?.map((actionId) => comp.env.dependencyManager.get(actionId).cleanSelectedItem)
const cleans = inheritedActionIds
.map((actionId) => comp.env.dependencyManager.get(actionId).cleanSelectedItem)
.filter(Boolean);
for (const clean of new Set(cleans)) {
clean(applySpecs);
Expand Down Expand Up @@ -434,7 +464,7 @@ export function useVisibilityObserver(contentName, callback) {
export const basicContainerBuilderComponentProps = {
applyTo: { type: String, optional: true },
preview: { type: Boolean, optional: true },
dependencies: { type: [String, Array], optional: true },
inheritedActions: { type: Array, element: String, optional: true },
// preview: { type: Boolean, optional: true },
// reloadPage: { type: Boolean, optional: true },

Expand All @@ -447,6 +477,7 @@ export const basicContainerBuilderComponentProps = {
dataAttributeAction: { type: String, optional: true },
styleAction: { type: String, optional: true },
};
const basicContainerBuilderComponentPropsNames = Object.keys(basicContainerBuilderComponentProps);
const validateIsNull = { validate: (value) => value === null };
export const clickableBuilderComponentProps = {
...basicContainerBuilderComponentProps,
Expand All @@ -467,6 +498,9 @@ export const clickableBuilderComponentProps = {
};

export function getAllActionsAndOperations(comp) {
const inheritedActionIds =
comp.props.inheritedActions || comp.env.weContext.inheritedActions || [];

function getActionsSpecs(actions, userValueInput) {
const getAction = comp.env.editor.shared.builderActions.getAction;
const specs = [];
Expand Down Expand Up @@ -522,15 +556,16 @@ export function getAllActionsAndOperations(comp) {
if (actionId) {
actions.push({ actionId, actionParam, actionValue });
}
const inheritedActions = comp.props.inheritedActions
?.map(
(actionId) =>
comp.env.dependencyManager
// The dependency might not be loaded yet.
.get(actionId)
?.getActions?.() || []
)
.flat();
const inheritedActions =
inheritedActionIds
.map(
(actionId) =>
comp.env.dependencyManager
// The dependency might not be loaded yet.
.get(actionId)
?.getActions?.() || []
)
.flat() || [];
return actions.concat(inheritedActions || []);
}
function callOperation(fn, params = {}) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,11 @@ import { useService } from "@web/core/utils/hooks";
import { _t } from "@web/core/l10n/translation";
import { defaultBuilderComponents } from "../builder_components/default_builder_components";
import { globalBuilderOptions } from "../builder_components/global_builder_options";
import { useVisibilityObserver, useApplyVisibility } from "../builder_components/utils";
import {
useVisibilityObserver,
useApplyVisibility,
useIsActiveItem,
} from "../builder_components/utils";
import { DependencyManager } from "../plugins/dependency_manager";
import { getSnippetName } from "@html_builder/utils/utils";

Expand All @@ -27,6 +31,7 @@ export class OptionsContainer extends Component {
getEditingElements: () => [this.props.editingElement],
weContext: {},
});
this.isActiveItem = useIsActiveItem();
useVisibilityObserver("content", useApplyVisibility("root"));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
<BuilderSelectItem title.translate="Highlight Active" classAction="'s_accordion_highlight'">Highlight Active</BuilderSelectItem>
</BuilderSelect>
</BuilderRow>
<BuilderRow label.translate="Hide Borders" level="1" dependencies="'accordion_style_boxed_opt'">
<BuilderRow label.translate="Hide Borders" level="1" t-if="this.isActiveItem('accordion_style_boxed_opt')">
<BuilderCheckbox classAction="'accordion-flush'"/>
</BuilderRow>
<BuilderRow label.translate="Round Corners" level="1">
Expand Down
Loading