Skip to content

Commit 8ca8e1e

Browse files
authored
Merge pull request #104 from magento-trigger/MC-1263
MC-1263: Buttons of Image Content Block are not aligned correctly
2 parents 0954b2e + 4fba6d0 commit 8ca8e1e

File tree

10 files changed

+265
-1
lines changed

10 files changed

+265
-1
lines changed

app/code/Magento/PageBuilder/Test/Mftf/Section/PageBuilderColumnSection.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
<element name="columnResizeGridLine" type="block" selector=".resize-grid .grid-line:nth-child({{arg}})" parameterized="true"/>
2222
<element name="columnStyle" type="text" selector="(//div[contains(@class, 'pagebuilder-column-group')])[1]/descendant::div[contains(@class, 'pagebuilder-content-type') and contains(@class, 'pagebuilder-column')][{{arg1}}][contains(@style, '{{arg2}}')]" parameterized="true"/>
2323
<element name="columnChildrenStyle" type="text" selector="(//div[contains(@class, 'pagebuilder-column-group')])[{{arg1}}]/descendant::div[contains(@class, 'pagebuilder-content-type') and contains(@class, 'pagebuilder-column')][{{arg2}}]//div[contains(@class, 'element-children')][contains(@style, '{{arg3}}')]" parameterized="true"/>
24+
<element name="columnByIndexAndWidthClass" type="text" selector="(//div[contains(@class,'pagebuilder-content-type') and contains(@class,'pagebuilder-column')])[{{arg1}}][contains(@class,'column-width-{{arg2}}')]" parameterized="true"/>
2425
<element name="displayLabel" type="button" selector='(//div[contains(@class, "pagebuilder-content-type") and contains(@class, "pagebuilder-column")])[{{arg1}}]/descendant::div[contains(@class, "pagebuilder-display-label")][contains(text(), "{{arg2}}")]' parameterized="true"/>
2526
<element name="columnMoveByIndex" type="button" selector='(//div[contains(@class, "pagebuilder-content-type") and contains(@class, "pagebuilder-column")])[{{arg1}}]//div[contains(@class,"pagebuilder-options-visible")]/descendant::*[@class="move-column"]' parameterized="true"/>
2627
<element name="displayLabelGridSize" type="button" selector='(//div[contains(@class, "pagebuilder-column-group")])[{{arg1}}]//div[contains(@class, "pagebuilder-display-label")][1][contains(text(), "/{{arg2}}")]' parameterized="true"/>

app/code/Magento/PageBuilder/Test/Mftf/Test/AdminPageBuilderColumnResizingTest.xml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,18 @@
3737
<!-- Get 3/6 Column Width -->
3838
<comment userInput="Get 3/6 Column Width" stepKey="context1"/>
3939
<executeJS function="return document.querySelector('{{ColumnOnBackend.columnX('1')}}').clientWidth" stepKey="initalColumnWidth"/>
40+
<!-- Assert the initial width classes are correct -->
41+
<waitForElement selector="{{ColumnOnBackend.columnByIndexAndWidthClass('1','50')}}" stepKey="assertInitialWidthClass1"/>
42+
<waitForElement selector="{{ColumnOnBackend.columnByIndexAndWidthClass('2','50')}}" stepKey="assertInitialWidthClass2"/>
4043
<!-- Change Columns To 6:0 Ratio -->
4144
<comment userInput="Change Columns To 6:0 Ratio" stepKey="context2"/>
4245
<actionGroup ref="removeContentTypeFromStageByIndex" stepKey="removeSecondColumn">
4346
<argument name="contentType" value="PageBuilderColumnContentType"/>
4447
<argument name="contentTypeNumber" value="2"/>
4548
</actionGroup>
49+
<!-- Assert the width class changed to 100 correctly on the first column -->
50+
<waitForElement selector="{{ColumnOnBackend.columnByIndexAndWidthClass('1','100')}}" stepKey="assertWidthClass1"/>
51+
<!-- Add a new column -->
4652
<actionGroup ref="dragContentTypeToContainer" stepKey="dragIntoStage">
4753
<argument name="contentType" value="PageBuilderDividerContentType"/>
4854
<argument name="containerTargetType" value="PageBuilderColumnContentType"/>
@@ -116,6 +122,9 @@
116122
<!-- Change Columns To 5:1 Ratio -->
117123
<comment userInput="Change Columns To 5:1 Ratio" stepKey="context1"/>
118124
<dragAndDrop selector1="{{ColumnOnBackend.columnX('1')}} {{ColumnOnBackend.columnResizeHandle}}" selector2="{{ColumnOnBackend.columnResizeGridLine('10')}}" x="$guideWidth" stepKey="dragColumnOneToFive"/>
125+
<!-- Assert the width classes are correct after manual resize -->
126+
<waitForElement selector="{{ColumnOnBackend.columnByIndexAndWidthClass('1','90')}}" stepKey="assertWidthClass1"/>
127+
<waitForElement selector="{{ColumnOnBackend.columnByIndexAndWidthClass('2','20')}}" stepKey="assertWidthClass2"/>
119128
<actionGroup ref="dragContentTypeToContainer" stepKey="dragIntoStage1">
120129
<argument name="contentType" value="PageBuilderDividerContentType"/>
121130
<argument name="containerTargetType" value="PageBuilderColumnContentType"/>

app/code/Magento/PageBuilder/view/adminhtml/web/css/source/form/element/uploader/preview/_image.less

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,37 @@
6767
display: none;
6868
}
6969

70+
._compact-ui .file-uploader-area,
71+
._micro-ui .file-uploader-area {
72+
align-items: center;
73+
display: flex;
74+
flex-direction: column;
75+
position: relative;
76+
77+
> span {
78+
display: none;
79+
}
80+
.image-upload-instructions {
81+
margin-bottom: 5px;
82+
}
83+
.file-uploader-button {
84+
display: block;
85+
margin-left: 0;
86+
margin-right: 0;
87+
margin-top: 15px;
88+
max-width: 180px;
89+
width: 100%;
90+
}
91+
}
92+
._micro-ui .file-uploader-area {
93+
.file-uploader-button {
94+
padding: .6rem 0;
95+
}
96+
.image-upload-requirements {
97+
display: none;
98+
}
99+
}
100+
70101
.pagebuilder-image-uploader-container-dropzone-overlay {
71102
display: none;
72103
height: 100%;

app/code/Magento/PageBuilder/view/adminhtml/web/js/content-type/column/preview.js

Lines changed: 23 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

app/code/Magento/PageBuilder/view/adminhtml/web/js/form/element/image-uploader.js

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,22 +8,34 @@ define([
88
'underscore',
99
'uiRegistry',
1010
'Magento_Ui/js/form/element/image-uploader',
11+
'Magento_PageBuilder/js/resource/resize-observer/ResizeObserver.min',
1112
'Magento_PageBuilder/js/events',
1213
'mage/translate'
13-
], function ($, _, uiRegistry, Uploader, events, $t) {
14+
], function ($, _, uiRegistry, Uploader, ResizeObserver, events, $t) {
1415
'use strict';
1516

1617
var initializedOnce = false;
1718

1819
return Uploader.extend({
1920
defaults: {
21+
$uploadArea: null,
2022
isShowImageUploadInstructions: true,
2123
isShowImageUploadOptions: false,
2224
classes: {
2325
dragging: 'dragging',
2426
draggingInside: 'dragging-inside',
2527
draggingOutside: 'dragging-outside'
2628
},
29+
// listed in ascending order
30+
elementWidthModifierClasses: {
31+
'_micro-ui': {
32+
maxWidth: 130
33+
},
34+
'_compact-ui': {
35+
minWidth: 131,
36+
maxWidth: 440
37+
}
38+
},
2739
translations: {
2840
allowedFileTypes: $t('Allowed file types'),
2941
dragImageHere: $t('Drag image here'),
@@ -59,6 +71,15 @@ define([
5971
}
6072
},
6173

74+
/**
75+
* {@inheritDoc}
76+
*/
77+
initUploader: function (fileInput) {
78+
this._super(fileInput);
79+
this.$uploadArea = $(this.$fileInput).closest('.pagebuilder-image-empty-preview');
80+
new ResizeObserver(this.updateResponsiveClasses.bind(this)).observe(this.$uploadArea.get(0));
81+
},
82+
6283
/**
6384
* Remove draggable classes from dropzones
6485
* {@inheritDoc}
@@ -138,6 +159,42 @@ define([
138159
*/
139160
onAssignedFile: function (file) {
140161
this.value([file]);
162+
},
163+
164+
/**
165+
* Adds the appropriate ui state class to the upload control area based on the current rendered size
166+
*/
167+
updateResponsiveClasses: function () {
168+
var classesToAdd = [],
169+
classConfig,
170+
elementWidth = this.$uploadArea.width(),
171+
modifierClass;
172+
173+
if (!this.$uploadArea.is(':visible')) {
174+
return;
175+
}
176+
177+
this.$uploadArea.removeClass(Object.keys(this.elementWidthModifierClasses).join(' '));
178+
179+
for (modifierClass in this.elementWidthModifierClasses) {
180+
if (!this.elementWidthModifierClasses.hasOwnProperty(modifierClass)) {
181+
continue;
182+
}
183+
184+
classConfig = this.elementWidthModifierClasses[modifierClass];
185+
186+
if (classConfig.minWidth && classConfig.maxWidth &&
187+
(classConfig.minWidth <= elementWidth && elementWidth <= classConfig.maxWidth) ||
188+
classConfig.minWidth && !classConfig.maxWidth && classConfig.minWidth <= elementWidth ||
189+
classConfig.maxWidth && !classConfig.minWidth && elementWidth <= classConfig.maxWidth
190+
) {
191+
classesToAdd.push(modifierClass);
192+
}
193+
}
194+
195+
if (classesToAdd.length) {
196+
this.$uploadArea.addClass(classesToAdd.join(' '));
197+
}
141198
}
142199
});
143200
});

app/code/Magento/PageBuilder/view/adminhtml/web/ts/js/content-type/column/preview.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ export default class Preview extends PreviewCollection {
5252
super(parent, config, observableUpdater);
5353

5454
// Update the width label for the column
55+
this.parent.dataStore.subscribe(this.updateColumnWidthClass.bind(this), "width");
5556
this.parent.dataStore.subscribe(this.updateDisplayLabel.bind(this), "width");
5657
this.parent.parent.dataStore.subscribe(this.updateDisplayLabel.bind(this), "grid_size");
5758
}
@@ -84,6 +85,7 @@ export default class Preview extends PreviewCollection {
8485
*/
8586
public initColumn(element: Element) {
8687
this.element = $(element);
88+
this.updateColumnWidthClass();
8789
events.trigger("column:initializeAfter", {
8890
column: this.parent,
8991
element: $(element),
@@ -266,6 +268,26 @@ export default class Preview extends PreviewCollection {
266268
}
267269
}
268270

271+
/**
272+
* Syncs the column-width-* class on the children-wrapper with the current width to the nearest tenth rounded up
273+
*/
274+
public updateColumnWidthClass() {
275+
// Only update once instantiated
276+
if (!this.element) {
277+
return;
278+
}
279+
280+
const currentClass = this.element.attr("class").match(/(?:^|\s)(column-width-\d{1,3})(?:$|\s)/);
281+
282+
if (currentClass !== null) {
283+
this.element.removeClass(currentClass[1]);
284+
}
285+
286+
const roundedWidth = Math.ceil(parseFloat(this.parent.dataStore.get("width").toString()) / 10) * 10;
287+
288+
this.element.addClass("column-width-" + roundedWidth);
289+
}
290+
269291
/**
270292
* Update the style attribute mapper converts images to directives, override it to include the correct URL
271293
*
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
/**
2+
*
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
/* eslint-disable max-nested-callbacks */
8+
define([
9+
'Magento_PageBuilder/js/form/element/image-uploader',
10+
'jquery'
11+
], function (ImageUploader, $) {
12+
'use strict';
13+
14+
var uploader,
15+
modifierClassSet1 = {
16+
'foo': {
17+
minWidth: 1000
18+
},
19+
'bar': {
20+
minWidth: 3000
21+
},
22+
'baz': {
23+
minWidth: 100,
24+
maxWidth: 200
25+
},
26+
'bash': {
27+
maxWidth: 50
28+
}
29+
},
30+
scenarios = [
31+
{
32+
config: modifierClassSet1,
33+
elementWidth: 1000,
34+
expectedClasses: 'foo'
35+
},
36+
{
37+
config: modifierClassSet1,
38+
elementWidth: 1500,
39+
expectedClasses: 'foo'
40+
},
41+
{
42+
config: modifierClassSet1,
43+
elementWidth: 3100,
44+
expectedClasses: 'foo bar'
45+
},
46+
{
47+
config: modifierClassSet1,
48+
elementWidth: 100,
49+
expectedClasses: 'baz'
50+
},
51+
{
52+
config: modifierClassSet1,
53+
elementWidth: 200,
54+
expectedClasses: 'baz'
55+
},
56+
{
57+
config: modifierClassSet1,
58+
elementWidth: 10,
59+
expectedClasses: 'bash'
60+
},
61+
{
62+
config: modifierClassSet1,
63+
elementWidth: 50,
64+
expectedClasses: 'bash'
65+
}
66+
];
67+
68+
beforeEach(function () {
69+
/**
70+
* A stub constructor to bypass the original
71+
* @constructor
72+
*/
73+
var MockUploader = function () {};
74+
75+
MockUploader.prototype = Object.create(ImageUploader.prototype);
76+
MockUploader.prototype.constructor = MockUploader;
77+
uploader = new MockUploader();
78+
uploader.$uploadArea = $('<div/>');
79+
});
80+
81+
describe('Magento_PageBuilder/js/form/element/image-uploader', function () {
82+
describe('updateResponsiveClasses', function () {
83+
it('Should do nothing when element is not visible', function () {
84+
spyOn(uploader.$uploadArea, 'is').and.returnValue(false);
85+
spyOn(uploader.$uploadArea, 'removeClass');
86+
spyOn(uploader.$uploadArea, 'addClass');
87+
88+
uploader.updateResponsiveClasses();
89+
90+
// None of the algorithm should have been attempted
91+
expect(uploader.$uploadArea.addClass).not.toHaveBeenCalled();
92+
expect(uploader.$uploadArea.removeClass).not.toHaveBeenCalled();
93+
});
94+
it('Attempts to remove all defined modifier classes', function () {
95+
uploader.elementWidthModifierClasses = {
96+
'foo': {},
97+
'bar': {}
98+
};
99+
spyOn(uploader.$uploadArea, 'is').and.returnValue(true);
100+
spyOn(uploader.$uploadArea, 'removeClass');
101+
102+
uploader.updateResponsiveClasses();
103+
104+
expect(uploader.$uploadArea.removeClass).toHaveBeenCalledWith('foo bar');
105+
});
106+
107+
$.each(scenarios, function (i, scenario) {
108+
it('Should add modifier classes if configuration is met in scenario ' + i, function () {
109+
uploader.elementWidthModifierClasses = scenario.config;
110+
spyOn(uploader.$uploadArea, 'is').and.returnValue(true);
111+
spyOn(uploader.$uploadArea, 'width').and.returnValue(scenario.elementWidth);
112+
spyOn(uploader.$uploadArea, 'addClass');
113+
114+
uploader.updateResponsiveClasses();
115+
116+
expect(uploader.$uploadArea.addClass).toHaveBeenCalledWith(scenario.expectedClasses);
117+
});
118+
});
119+
});
120+
});
121+
});

0 commit comments

Comments
 (0)