Skip to content

Commit 0cabe13

Browse files
committed
AC-8379 related conflicts resolved
2 parents 5e08fc3 + 2d14130 commit 0cabe13

File tree

11 files changed

+157
-199
lines changed

11 files changed

+157
-199
lines changed

app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminCreateCatalogProductWidgetActionGroup.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@
2020
<click selector="{{AdminNewWidgetSection.selectCategory}}" stepKey="clickOnSelectCategory"/>
2121
<waitForPageLoad stepKey="waitForCategoryTreeLoaded"/>
2222
<click selector="{{AdminCategorySidebarTreeSection.expandRootCategoryByName(DefaultCategory.name)}}" stepKey="clickToExpandDefaultCategory"/>
23-
<waitForElementVisible selector="{{AdminCategorySidebarTreeSection.categoryInTree(categoryName)}}" stepKey="waitForCategoryVisible"/>
24-
<click selector="{{AdminCategorySidebarTreeSection.categoryInTree(categoryName)}}" stepKey="selectCategory"/>
23+
<waitForElementVisible selector="{{WidgetSection.CreateCategory(categoryName)}}" stepKey="waitForCategoryVisible"/>
24+
<click selector="{{WidgetSection.CreateCategory(categoryName)}}" stepKey="selectCategory"/>
2525
<waitForPageLoad stepKey="waitForWidgetPageLoaded"/>
2626
<click selector="{{AdminMainActionsSection.save}}" stepKey="clickSaveButton"/>
2727
<waitForElementVisible selector="{{AdminMessagesSection.success}}" stepKey="waitForSuccessMessage"/>

app/code/Magento/Catalog/Test/Mftf/Section/AdminCategorySidebarTreeSection.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,9 @@
2020
<element name="lastCreatedCategory" type="block" selector=".x-tree-root-ct li li:last-child" />
2121
<element name="treeContainer" type="block" selector=".tree-holder" />
2222
<element name="expandRootCategory" type="text" selector="img.x-tree-elbow-end-plus"/>
23-
<element name="expandRootCategoryByName" type="button" selector="//div[@class='x-tree-root-node']/li/div/a/span[contains(., '{{categoryName}}')]/../../img[contains(@class, 'x-tree-elbow-end-plus')]" parameterized="true" timeout="30"/>
23+
<element name="expandRootCategoryByName" type="button" selector="//a[contains(text(),'{{categoryName}}')]/ancestor::li[contains(@class,'jstree-node')]//i[contains(@class,'jstree-ocl')]" parameterized="true" timeout="30"/>
2424
<element name="categoryByName" type="text" selector="//div[contains(@class, 'categories-side-col')]//a/span[contains(text(), '{{categoryName}}')]" parameterized="true" timeout="30"/>
25-
<element name="expandCategoryByName" type="text" selector="//span[contains(text(),'{{categoryName}}')]/ancestor::div[contains(@class,'x-tree-node-el')]//img[contains(@class,'x-tree-elbow-end-plus') or contains(@class,'x-tree-elbow-plus')]" parameterized="true" timeout="30"/>
25+
<element name="expandCategoryByName" type="text" selector="//a[contains(text(),'{{categoryName}}')]/ancestor::li[contains(@class,'jstree-node')]//i[contains(@class,'jstree-ocl')]" parameterized="true" timeout="30"/>
2626
<element name="subCategoryProductCount" type="text" selector="//div[@class='tree-holder']//span[contains(text(),'SubCat') and contains(text(),'({{productCount}})')]" parameterized="true"/>
2727
<element name="defaultCategoryProductCount" type="text" selector="//div[@class='tree-holder']//span[contains(text(),'Default Category') and contains(text(),'({{productCount}})')]" parameterized="true"/>
2828
</section>

app/code/Magento/Catalog/view/adminhtml/templates/catalog/category/widget/tree.phtml

Lines changed: 133 additions & 161 deletions
Original file line numberDiff line numberDiff line change
@@ -10,204 +10,176 @@
1010
<?php $_divId = 'tree' . $block->getId() ?>
1111
<div id="<?= $block->escapeHtmlAttr($_divId) ?>" class="tree"></div>
1212
<?php
13-
$isUseMassaction = $block->getUseMassaction() ? 1 : 0;
13+
$isUseMassAction = $block->getUseMassaction() ? 1 : 0;
1414
$isAnchorOnly = $block->getIsAnchorOnly() ? 1 : 0;
15-
$intCategoryId = (int)$block->getCategoryId();
16-
$intRootId = (int) $block->getRoot()->getId();
1715
$scriptString = <<<script
1816
19-
require(['jquery', 'prototype', 'extjs/ext-tree-checkbox'], function(jQuery){
17+
require(['jquery', 'jquery/jstree/jquery.jstree'], function($) {
2018
21-
var tree{$block->escapeJs($block->getId())};
19+
let tree = $('#tree{$block->escapeJs($block->getId())}');
20+
let useMassAction = {$isUseMassAction};
21+
let isAnchorOnly = {$isAnchorOnly};
22+
let checkedNodes = [];
2223
23-
var useMassaction = {$isUseMassaction};
24-
25-
var isAnchorOnly = {$isAnchorOnly};
26-
27-
Ext.tree.TreePanel.Enhanced = function(el, config)
28-
{
29-
Ext.tree.TreePanel.Enhanced.superclass.constructor.call(this, el, config);
30-
};
31-
32-
Ext.extend(Ext.tree.TreePanel.Enhanced, Ext.tree.TreePanel, {
33-
34-
loadTree : function(config, firstLoad)
35-
{
36-
var parameters = config['parameters'];
37-
var data = config['data'];
24+
function addLastNodeProperty(nodes) {
25+
return nodes.map(node => {
26+
return node.children
27+
? { ...node, children: addLastNodeProperty(node.children) }
28+
: { ...node, lastNode: true };
29+
});
30+
}
3831
39-
if ((typeof parameters['root_visible']) != 'undefined') {
40-
this.rootVisible = parameters['root_visible']*1;
41-
}
32+
function actionBasedOnIsAnchorOnly() {
33+
tree.jstree().get_json('#', { flat: true }).each((node, value) => {
34+
const attrId = node.a_attr.id;
35+
const rootNode = tree.jstree().get_node("#");
36+
const rootId = rootNode.children[0];
4237
43-
var root = new Ext.tree.TreeNode(parameters);
38+
if (isAnchorOnly === 1 && node.id === rootId) {
39+
tree.jstree(true).disable_node(node);
40+
} else if (isAnchorOnly === 0 && node.id !== rootId) {
41+
tree.jstree(true).disable_node(node);
42+
}
43+
});
44+
}
4445
45-
this.nodeHash = {};
46-
this.setRootNode(root);
46+
function handleLoadedTree(e, data) {
47+
const container = $(e.target).closest('div.chooser_container');
48+
checkedNodes = container.find('input[type="text"].entities').val().split(',').map(item => item.trim());
4749
48-
if (firstLoad) {
50+
data.instance.get_json('#', { flat: true }).forEach(nodeId => {
51+
const node = data.instance.get_node(nodeId);
4952
50-
script;
51-
if ($block->getNodeClickListener()):
52-
$scriptString .= 'this.addListener(\'click\', ' . /* @noEscape */ $block->getNodeClickListener() .
53-
'.createDelegate(this));' . PHP_EOL;
54-
endif;
55-
$scriptString .= <<<script
56-
}
53+
if (checkedNodes.includes(node.id)) {
54+
tree.jstree(true).select_node(node.id);
55+
}
5756
58-
this.loader.buildCategoryTree(root, data);
59-
this.el.dom.innerHTML = '';
60-
// render the tree
61-
this.render();
57+
actionBasedOnIsAnchorOnly();
58+
});
6259
}
63-
});
64-
65-
jQuery(function()
66-
{
67-
68-
script;
69-
$scriptString .= 'var emptyNodeAdded = ' . ($block->getWithEmptyNode() ? 'false' : 'true') . ';' . PHP_EOL;
7060
71-
$scriptString .= <<<script
61+
function handleChange(e, data) {
62+
if (data.action === 'ready') {
63+
return;
64+
}
7265
73-
var categoryLoader = new Ext.tree.TreeLoader({
74-
dataUrl: '{$block->escapeJs($block->escapeUrl($block->getLoadTreeUrl()))}'
75-
});
66+
if (useMassAction) {
67+
const clickedNodeID = data.node.id;
68+
const currentCheckedNodes = data.instance.get_checked();
7669
77-
categoryLoader.processResponse = function (response, parent, callback) {
78-
var config = JSON.parse(response.responseText);
70+
if (data.action === 'select_node' && !checkedNodes.includes(clickedNodeID)) {
71+
checkedNodes = currentCheckedNodes;
72+
} else if (data.action === 'deselect_node') {
73+
checkedNodes = currentCheckedNodes.filter(nodeID => nodeID !== clickedNodeID);
74+
}
7975
80-
this.buildCategoryTree(parent, config);
76+
checkedNodes.sort((a, b) => a - b);
8177
82-
if (typeof callback == "function") {
83-
callback(this, parent);
78+
const container = $(e.target).closest('div.chooser_container');
79+
container.find('input[type="text"].entities').val(checkedNodes.join(', '));
80+
} else {
81+
node = data.node;
82+
node.attributes = node.original;
83+
const nodeClickListener = {$block->getNodeClickListener()};
84+
nodeClickListener(node);
8485
}
85-
};
86+
}
8687
87-
categoryLoader.buildCategoryTree = function(parent, config)
88-
{
89-
if (!config) return null;
90-
91-
92-
if (parent && config && config.length){
93-
for (var i = 0; i < config.length; i++) {
94-
var node;
95-
if (useMassaction && config[i].is_anchor == isAnchorOnly) {
96-
config[i].uiProvider = Ext.tree.CheckboxNodeUI;
97-
}
98-
var _node = Object.clone(config[i]);
99-
100-
// Add empty node to reset category filter
101-
if(!emptyNodeAdded) {
102-
var empty = Object.clone(_node);
103-
empty.text = '{$block->escapeJs(__('None'))}';
104-
empty.children = [];
105-
empty.id = 'none';
106-
empty.path = '1/none';
107-
empty.cls = 'leaf';
108-
parent.appendChild(new Ext.tree.TreeNode(empty));
109-
emptyNodeAdded = true;
110-
}
111-
112-
if (_node.children && !_node.children.length) {
113-
delete(_node.children);
114-
node = new Ext.tree.AsyncTreeNode(_node);
115-
} else {
116-
node = new Ext.tree.TreeNode(config[i]);
117-
}
118-
parent.appendChild(node);
119-
node.loader = node.getOwnerTree().loader;
120-
node.loader = node.getOwnerTree().loader;
121-
if (_node.children) {
122-
this.buildCategoryTree(node, _node.children);
123-
}
88+
function getCheckedNodeIds(tree, node) {
89+
if (node.children_d && node.children_d.length > 0) {
90+
const selectChildrenNodes = node.children_d.filter(item => checkedNodes.includes(item));
91+
92+
if (selectChildrenNodes.length > 0) {
93+
tree.jstree(true).select_node(selectChildrenNodes);
12494
}
12595
}
126-
};
96+
}
12797
128-
categoryLoader.createNode = function(config) {
129-
var node;
130-
if (useMassaction && config.is_anchor == isAnchorOnly) {
131-
config.uiProvider = Ext.tree.CheckboxNodeUI;
132-
}
133-
var _node = Object.clone(config);
134-
if (config.children && !config.children.length) {
135-
delete(config.children);
136-
node = new Ext.tree.AsyncTreeNode(config);
98+
function addLastNodeFlag(treeData) {
99+
if (treeData.children) {
100+
treeData.children.forEach(child => addLastNodeFlag(child));
137101
} else {
138-
node = new Ext.tree.TreeNode(config);
102+
treeData.lastNode = true;
139103
}
140-
return node;
141-
};
142-
143-
categoryLoader.buildHash = function(node)
144-
{
145-
var hash = {};
146-
147-
hash = this.toArray(node.attributes);
148-
149-
if (node.childNodes.length>0 || (node.loaded==false && node.loading==false)) {
150-
hash['children'] = new Array;
104+
}
151105
152-
for (var i = 0, len = node.childNodes.length; i < len; i++) {
153-
if (!hash['children']) {
154-
hash['children'] = new Array;
155-
}
156-
hash['children'].push(this.buildHash(node.childNodes[i]));
157-
}
106+
function handleSuccessResponse(response, childNode, data) {
107+
if (response.length > 0) {
108+
response.forEach(newNode => {
109+
addLastNodeFlag(newNode);
110+
111+
// Create the new node and execute node callback
112+
data.instance.create_node(childNode, newNode, 'last', node => {
113+
if (useMassAction) {
114+
if (checkedNodes.includes(node.id)) {
115+
tree.jstree(true).select_node(node.id);
116+
}
117+
getCheckedNodeIds(tree, node);
118+
actionBasedOnIsAnchorOnly();
119+
}
120+
});
121+
});
158122
}
123+
}
159124
160-
return hash;
161-
};
162-
163-
categoryLoader.toArray = function(attributes) {
164-
var data = {};
165-
for (var key in attributes) {
166-
var value = attributes[key];
167-
data[key] = value;
125+
function handleOpenNode(e, data) {
126+
let parentNode = data.node;
127+
128+
if (parentNode.children.length > 0) {
129+
let childNode = data.instance.get_node(parentNode.children, false);
130+
131+
// Check if the child node has no children (is not yet loaded)
132+
if (childNode.children && childNode.children.length === 0
133+
&& childNode.original && !childNode.original.lastNode) {
134+
$.ajax({
135+
url: '{$block->escapeJs($block->escapeUrl($block->getLoadTreeUrl()))}',
136+
data: {
137+
id: childNode.original.id,
138+
store: childNode.original.store,
139+
form_key: FORM_KEY
140+
},
141+
dataType: 'json',
142+
success: function (response) {
143+
handleSuccessResponse(response, childNode, data);
144+
},
145+
error: function (jqXHR, status, error) {
146+
console.log(status + ': ' + error + 'Response text:' + jqXHR.responseText);
147+
}
148+
});
149+
}
168150
}
151+
}
169152
170-
return data;
153+
var jstreeConfig = {
154+
core: {
155+
data: addLastNodeProperty({$block->getTreeJson()}),
156+
check_callback: true
157+
},
158+
plugins: []
171159
};
172160
173-
categoryLoader.on("beforeload", function(treeLoader, node) {
174-
treeLoader.baseParams.id = node.attributes.id;
175-
treeLoader.baseParams.store = node.attributes.store;
176-
treeLoader.baseParams.form_key = FORM_KEY;
177-
$('{$block->escapeJs($_divId)}').fire('category:beforeLoad', {treeLoader:treeLoader});
178-
});
179-
180-
tree{$block->escapeJs($block->getId())} = new Ext.tree.TreePanel.Enhanced('{$block->escapeJs($_divId)}', {
181-
animate: false,
182-
loader: categoryLoader,
183-
enableDD: false,
184-
containerScroll: true,
185-
rootVisible: false,
186-
useAjax: true,
187-
currentNodeId: {$intCategoryId},
188-
addNodeTo: false
189-
});
190-
191-
if (useMassaction) {
192-
tree{$block->escapeJs($block->getId())}.on('check', function(node) {
193-
$('{$block->escapeJs($_divId)}').fire('node:changed', {node:node});
194-
}, tree{$block->escapeJs($block->getId())});
161+
if (useMassAction) {
162+
jstreeConfig.plugins.push('checkbox');
163+
jstreeConfig.checkbox = {
164+
three_state: false
165+
};
195166
}
196167
197-
// set the root node
198-
var parameters = {
199-
text: 'Psw',
200-
draggable: false,
201-
id: {$intRootId},
202-
expanded: true,
203-
category_id: {$intCategoryId}
204-
};
168+
tree.jstree(jstreeConfig);
205169
206-
tree{$block->escapeJs($block->getId())}.loadTree({parameters:parameters, data:{$block->getTreeJson()}},true);
170+
if (useMassAction) {
171+
tree.on('loaded.jstree', (e, data) => handleLoadedTree(e, data));
172+
}
207173
174+
tree.on('changed.jstree', (e, data) => handleChange(e, data));
175+
tree.on('open_node.jstree', (e, data) => handleOpenNode(e, data));
208176
});
209177
210-
});
211178
script;
212179
?>
180+
<?= /* @noEscape */ $secureRenderer->renderStyleAsTag(
181+
'overflow-x: auto;',
182+
'#tree' . $block->escapeJs($block->getId())
183+
);
184+
?>
213185
<?= /* @noEscape */ $secureRenderer->renderTag('script', [], $scriptString, false); ?>

app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminUpdateWidgetsOfCatalogCategoryLinkActionGroup.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
<click selector="{{CmsNewWidgetOptionsSection.SelectCategory}}" stepKey="clickSelectCategoryButton1"/>
2323
<waitForPageLoad stepKey="waitToLoadRootCategory"/>
2424
<click selector="{{CmsNewWidgetOptionsSection.ExpandRootCategory}}" stepKey="clickToExpandRootCat"/>
25+
<waitForPageLoad stepKey="waitToExpandRootCategory"/>
2526
<click selector="{{CmsNewWidgetOptionsSection.SecondCategory}}" stepKey="clickSecondCategoryToSelect"/>
2627
<waitForPageLoad stepKey="waitToSelectSecondCategory"/>
2728
<click selector="{{CmsNewWidgetOptionsSection.SaveWidget}}" stepKey="clickSaveWidgetButton"/>

app/code/Magento/Cms/Test/Mftf/Section/TinyMCESection/CmsNewWidgetOptionsSection.xml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,9 @@
1616
<element name="SecondProduct" type="text" selector="//div[@class='admin__data-grid-wrap admin__data-grid-wrap-static']//tbody/tr[2]"/>
1717
<element name="SaveWidget" type="button" selector="//button[@id='save']"/>
1818
<element name="FirstWidget" type="text" selector="//tbody/tr[1]/td[3]"/>
19-
<element name="ExpandRootCategory" type="button" selector="//img[@class='x-tree-ec-icon x-tree-elbow-end-plus']"/>
20-
<element name="FirstCategory" type="text" selector="//Span[contains(text(),'simpleCategory')]"/>
21-
<element name="SecondCategory" type="text" selector="//Span[contains(text(),'CategoryB')]"/>
19+
<element name="ExpandRootCategory" type="button" selector="//li[contains(@class,'jstree-node jstree-closed')]//i[contains(@class,'jstree-icon jstree-ocl')]"/>
20+
<element name="FirstCategory" type="text" selector="//a[contains(text(),'simpleCategory')]/../..//a"/>
21+
<element name="SecondCategory" type="text" selector="//a[contains(text(),'CategoryB')]"/>
2222
</section>
2323
</sections>
2424

app/code/Magento/Cms/Test/Mftf/Section/TinyMCESection/CmsNewWidgetUpdateLayoutSection.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
<element name="Template" type="button" selector="#all_pages_0 > table > tbody > tr > td:nth-child(2) > div > div > select"/>
1515
<element name="SpecificCategories" type="button" selector="//input[@id='specific_anchor_categories_0']"/>
1616
<element name="CategoryChooserButton" type="button" selector="//*[@id='anchor_categories_ids_0']/p/a[1]/img"/>
17-
<element name="BranchCat" type="button" selector="//a/span[contains(text(),'{{var}}')]/../..//img[@class='x-tree-ec-icon x-tree-elbow-end-plus']" parameterized="true"/>
18-
<element name="CountAllNestedCat" type="button" selector="//*[@class='x-tree-ec-icon x-tree-elbow-end-minus' or @class='x-tree-ec-icon x-tree-elbow-end']"/>
17+
<element name="BranchCat" type="button" selector="//a[contains(text(),'{{var}}')]/..//i[contains(@class,'jstree-ocl')]" parameterized="true"/>
18+
<element name="CountAllNestedCat" type="button" selector="//*[@class='jstree-node jstree-last jstree-open' or @class='jstree-node jstree-leaf jstree-last']//*[@class='jstree-icon jstree-ocl']"/>
1919
</section>
2020
</sections>

0 commit comments

Comments
 (0)