Skip to content

Commit 0565709

Browse files
committed
[WIP] disable legacy options and keep editors in DOM
Prior to this, when dropping a snippets, its editors would be started but not added to the DOM, which means that when clicking on it, there would be a significant delay before options would be accessible. Note that this delay is present when clicking on a Snippet that is not dropped for the first time. The reason for this delay is because even thought the widgets where not in the DOM, they were still stored somewhere inside the started editor, reducing the need for renders when clicking on a snippet that was previously enabled. This commit tries to mimic the old behaviour by keeping every element in the DOM and mounted, just hidden with a d-none when the editor is not currently enabled. This could have some side effects, like in tours where a SnippetEditor selected is not the one currently visible. For this reason, this commit is kept separate for now.
1 parent 67342bd commit 0565709

File tree

2 files changed

+102
-75
lines changed

2 files changed

+102
-75
lines changed

addons/web_editor/static/src/js/editor/snippets.editor.js

Lines changed: 70 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -622,7 +622,7 @@ var SnippetEditor = Widget.extend({
622622
if (editorUIsToUpdate.length > 0 && !optionsSectionVisible) {
623623
return null;
624624
}
625-
return this._customize$Elements;
625+
return this.getOptions();
626626
},
627627
/**
628628
* Returns the OWL Options templates to mount their widgets.
@@ -860,6 +860,7 @@ var SnippetEditor = Widget.extend({
860860
option.isTopOption = true;
861861
}
862862
} else {
863+
return;
863864
option = new (options.registry[optionName] || options.Class)(
864865
this,
865866
val.$el.children(),
@@ -1892,6 +1893,59 @@ var SnippetEditor = Widget.extend({
18921893
},
18931894
});
18941895

1896+
class SnippetOptionsManager extends Component {
1897+
static props = {
1898+
editors: { type: Object },
1899+
enabledEditors: { type: Array },
1900+
onOptionMounted: { type: Function },
1901+
activateTab: { type: Function },
1902+
execWithLoadingEffect: { type: Function },
1903+
};
1904+
static template = "web_editor.SnippetOptionsManager";
1905+
1906+
setup() {
1907+
useEffect(
1908+
() => {
1909+
this.props.execWithLoadingEffect(async () => {
1910+
const editorToEnable = this.props.enabledEditors[0];
1911+
let enabledOptions;
1912+
if (editorToEnable) {
1913+
enabledOptions = await editorToEnable.toggleOptions(true);
1914+
if (!enabledOptions) {
1915+
// As some options can only be generated using JavaScript
1916+
// (e.g. 'SwitchableViews'), it may happen at this point
1917+
// that the overlay is activated even though there are no
1918+
// options. That's why we disable the overlay if there are
1919+
// no options to enable.
1920+
editorToEnable.toggleOverlay(false);
1921+
}
1922+
}
1923+
if (enabledOptions) {
1924+
this.props.activateTab(SnippetsMenu.tabs.OPTIONS);
1925+
}
1926+
});
1927+
},
1928+
() => {
1929+
// The compute dependencies can never return an empty array or
1930+
// the effect will not be reapplied, and therefore the tab will
1931+
// not change to blocks.
1932+
if (this.props.enabledEditors.length) {
1933+
return this.props.enabledEditors;
1934+
} else {
1935+
return [false];
1936+
}
1937+
}
1938+
);
1939+
}
1940+
1941+
getEditors() {
1942+
return [...this.props.editors].sort((e1, e2) => {
1943+
return this.props.enabledEditors.indexOf(e1) < this.props.enabledEditors.indexOf(e2);
1944+
});
1945+
}
1946+
}
1947+
1948+
18951949
/**
18961950
* Management of drag&drop menu and snippet related behaviors in the page.
18971951
*/
@@ -1958,7 +2012,7 @@ class SnippetsMenu extends Component {
19582012

19592013
static template = "web_editor.SnippetsMenu";
19602014

1961-
static components = { Toolbar, LinkTools };
2015+
static components = { Toolbar, LinkTools, SnippetOptionsManager };
19622016

19632017
setup() {
19642018
super.setup(...arguments);
@@ -3013,17 +3067,11 @@ class SnippetsMenu extends Component {
30133067
|| ifInactiveOptions && this.state.enabledEditorHierarchy.includes(editorToEnable)) {
30143068
return editorToEnable;
30153069
}
3016-
// TODO: @owl-options remove when legacy is completely converted.
3017-
let hasOwlOptions = false;
30183070

30193071
if (!previewMode) {
30203072
this.state.enabledEditorHierarchy = [];
30213073
let current = editorToEnable;
30223074
while (current && current.$target) {
3023-
// TODO: @owl-options remove when legacy is completely converted.
3024-
hasOwlOptions = current._hasOwlOptions;
3025-
// TODO: @owl-options, make sure changes to instances
3026-
// of SnippetEditor should not trigger re-renders.
30273075
this.state.enabledEditorHierarchy.push(markRaw(current));
30283076
current = current.getParent();
30293077
}
@@ -3054,33 +3102,21 @@ class SnippetsMenu extends Component {
30543102
parentEditor.toggleOverlay(true, previewMode);
30553103
}
30563104
}
3057-
customize$Elements = await editorToEnable.toggleOptions(true);
3058-
this.state.options = editorToEnable.getOptions();
3105+
// TODO: this code is handled by SnippetOptionsManager now
3106+
// customize$Elements = await editorToEnable.toggleOptions(true);
30593107
} else {
30603108
for (const editor of this.snippetEditors) {
30613109
if (editor.isSticky()) {
30623110
editor.toggleOverlay(true, false);
3063-
customize$Elements = await editor.toggleOptions(true);
3111+
// customize$Elements = await editor.toggleOptions(true);
3112+
this.state.enabledEditorHierarchy.push(editor);
30643113
}
30653114
}
30663115
}
3067-
3068-
if (!previewMode) {
3069-
// As some options can only be generated using JavaScript
3070-
// (e.g. 'SwitchableViews'), it may happen at this point
3071-
// that the overlay is activated even though there are no
3072-
// options. That's why we disable the overlay if there are
3073-
// no options to enable.
3074-
if (editorToEnable && !customize$Elements) {
3075-
editorToEnable.toggleOverlay(false);
3076-
}
3116+
if (!editorToEnable || this.state.enabledEditorHierarchy.lenght === 0) {
30773117
this._updateRightPanelContent({
3078-
content: customize$Elements || [],
3079-
// TODO: @owl-options, disable the change of tab,
3080-
// here, instead let the onOptionMounted do it. To review
3081-
// tab: customize$Elements ? this.tabs.OPTIONS : this.tabs.BLOCKS,
3082-
tab: !hasOwlOptions && customize$Elements ? this.tabs.OPTIONS : this.tabs.BLOCKS,
3083-
});
3118+
tab: this.tabs.BLOCKS
3119+
})
30843120
}
30853121

30863122
return editorToEnable;
@@ -4027,7 +4063,7 @@ class SnippetsMenu extends Component {
40274063
* the new content of the customizePanel
40284064
* @param {this.tabs.VALUE} [tab='blocks'] - the tab to select
40294065
*/
4030-
_updateRightPanelContent({content, tab, ...options}) {
4066+
_updateRightPanelContent({tab, ...options}) {
40314067
this._hideTooltips();
40324068
this._closeWidgets();
40334069

@@ -4036,30 +4072,15 @@ class SnippetsMenu extends Component {
40364072
tab = SnippetsMenu.tabs.OPTIONS;
40374073
}
40384074

4039-
this.state.currentTab = tab || SnippetsMenu.tabs.BLOCKS;
4040-
4041-
if (this._$toolbarContainer) {
4042-
this._$toolbarContainer[0].remove();
4043-
}
40444075
this.state.showToolbar = false;
40454076
this._$toolbarContainer = null;
4046-
if (content) {
4047-
// The toolbar component will be hidden or shown by state.showToolbar
4048-
// as it is an OWL Component, OWL is in charge of the HTML for that
4049-
// component. So we do not want to remove it.
4050-
// TODO: This should be improved when SnippetEditor / SnippetOptions
4051-
// are converted to OWL.
4052-
while (this.customizePanel.firstChild?.id !== "legacyOptionsLimiter") {
4053-
this.customizePanel.removeChild(this.customizePanel.firstChild);
4054-
}
4055-
$(this.customizePanel).prepend(content);
4056-
if (this.state.currentTab === this.tabs.OPTIONS && !options.forceEmptyTab) {
4057-
this._addToolbar();
4058-
}
4077+
if (this.state.currentTab === this.tabs.OPTIONS && !options.forceEmptyTab) {
4078+
this._addToolbar();
40594079
}
40604080
if (options.forceEmptyTab) {
40614081
this.state.showToolbar = false;
40624082
}
4083+
this.state.currentTab = tab;
40634084
}
40644085
/**
40654086
* Scrolls to given snippet.
@@ -5157,7 +5178,6 @@ class SnippetsMenu extends Component {
51575178
this.execWithLoadingEffect(async () => {
51585179
await Promise.all(this.state.enabledEditorHierarchy.map(editor => editor.updateOptionsUI()));
51595180
await Promise.all(this.state.enabledEditorHierarchy.map(editor => editor.updateOptionsUIVisibility()));
5160-
this.state.currentTab = this.tabs.OPTIONS;
51615181
});
51625182
}
51635183

@@ -5427,6 +5447,9 @@ class SnippetsMenu extends Component {
54275447
}
54285448
snippet.renaming = false;
54295449
}
5450+
activateTab(tab) {
5451+
this._updateRightPanelContent({tab});
5452+
}
54305453
}
54315454

54325455
export default {

addons/web_editor/static/src/xml/snippets.xml

Lines changed: 32 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -217,34 +217,7 @@
217217
</t>
218218
</div>
219219
<div class="o_we_customize_panel" t-ref="customize-panel" t-att-class="{ 'd-none': state.currentTab === constructor.tabs.BLOCKS }">
220-
<div class="d-none" id="legacyOptionsLimiter"/>
221-
<t t-foreach="[...state.enabledEditorHierarchy].reverse()" t-as="editor" t-key="editor.key">
222-
<t t-set="snippetOptions" t-value="editor.getOptions()"/>
223-
<we-customizeblock-options t-if="snippetOptions.length > 0">
224-
<we-title>
225-
<span>
226-
[OWL] <t t-out="editor.name"/>
227-
<t t-out="editor.extraTitle"/>
228-
</span>
229-
<we-top-button-group>
230-
<t t-foreach="snippetOptions" t-as="option" t-key="option_index">
231-
<t t-if="option.isTopOption" t-component="option.renderingComponent"
232-
snippetOption="option"
233-
onOptionMounted.bind="onOptionMounted"/>
234-
</t>
235-
</we-top-button-group>
236-
</we-title>
237-
<t t-foreach="snippetOptions" t-as="option" t-key="option_index">
238-
<!-- todo: @owl-options this div encapsulation is
239-
there so solve a weird crash -->
240-
<div t-if="!option.isTopOption">
241-
<t t-component="option.renderingComponent"
242-
snippetOption="option"
243-
onOptionMounted.bind="onOptionMounted"/>
244-
</div>
245-
</t>
246-
</we-customizeblock-options>
247-
</t>
220+
<SnippetOptionsManager editors="snippetEditors" enabledEditors="state.enabledEditorHierarchy" onOptionMounted="onOptionMounted" activateTab.bind="activateTab" execWithLoadingEffect.bind="this.execWithLoadingEffect"/>
248221
<we-customizeblock-options id="o_we_editor_toolbar_container" t-att-class="{ 'd-none': !state.showToolbar }">
249222
<we-title>
250223
<span t-out="state.toolbarTitle"/>
@@ -287,4 +260,35 @@
287260
</ul>
288261
</t>
289262

263+
<t t-name="web_editor.SnippetOptionsManager">
264+
<t t-foreach="getEditors()" t-as="editor" t-key="editor.key">
265+
<t t-set="snippetOptions" t-value="editor.getOptions()"/>
266+
<we-customizeblock-options t-if="snippetOptions.length > 0" t-att-class="{'d-none': props.enabledEditors.indexOf(editor) lt 0 }">
267+
<we-title>
268+
<span>
269+
<t t-out="editor.name"/>
270+
<t t-out="editor.extraTitle"/>
271+
</span>
272+
<we-top-button-group>
273+
<t t-foreach="snippetOptions" t-as="option" t-key="option_index">
274+
<t t-if="option.isTopOption" t-component="option.renderingComponent"
275+
snippetOption="option"
276+
onOptionMounted="props.onOptionMounted"/>
277+
</t>
278+
<we-button class="fa fa-fw fa-clone oe_snippet_clone o_we_link o_we_hover_success" data-title="Duplicate Container" aria-label="Duplicate Container" t-on-click="(ev) => editor._onCloneClick(ev)"/>
279+
<we-button class="fa fa-fw fa-trash oe_snippet_remove o_we_link o_we_hover_danger" data-title="Remove Block" aria-label="Remove Block" t-on-click="(ev) => editor._onRemoveClick(ev)"/>
280+
</we-top-button-group>
281+
</we-title>
282+
<t t-foreach="snippetOptions" t-as="option" t-key="option_index">
283+
<!-- todo: @owl-options this div encapsulation is
284+
there so solve a weird crash -->
285+
<div t-if="!option.isTopOption">
286+
<t t-component="option.renderingComponent"
287+
snippetOption="option"
288+
onOptionMounted="props.onOptionMounted"/>
289+
</div>
290+
</t>
291+
</we-customizeblock-options>
292+
</t>
293+
</t>
290294
</templates>

0 commit comments

Comments
 (0)