Skip to content

Commit 1f10d38

Browse files
committed
Merge remote-tracking branch 'origin/2.3-develop' into MC-20419
2 parents e79776b + 7324325 commit 1f10d38

File tree

343 files changed

+15958
-1994
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

343 files changed

+15958
-1994
lines changed

app/code/Magento/AdminAnalytics/view/adminhtml/ui_component/admin_usage_notification.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@
8585
<item name="text" xsi:type="string" translate="true"><![CDATA[
8686
<p>Help us improve Magento Admin by allowing us to collect usage data.</p>
8787
<p>All usage data that we collect for this purpose cannot be used to individually identify you and is used only to improve the Magento Admin and related products and services.</p>
88-
<p>You can learn more and opt out at any time by following the instructions in <a href="https://docs.magento.com/m2/ce/user_guide/stores/admin.html" target="_blank">merchant documentation</a>.</p>
88+
<p>You can learn more and opt out at any time by following the instructions in <a href="https://docs.magento.com/m2/ce/user_guide/stores/admin.html" target="_blank" tabindex="0">merchant documentation</a>.</p>
8989
]]></item>
9090
</item>
9191
</argument>

app/code/Magento/AdminAnalytics/view/adminhtml/web/js/modal/component.js

Lines changed: 84 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -20,16 +20,7 @@ define([
2020
enableLogAction: '${ $.provider }:data.enableLogAction',
2121
disableLogAction: '${ $.provider }:data.disableLogAction'
2222
},
23-
options: {
24-
keyEventHandlers: {
25-
/**
26-
* Prevents escape key from exiting out of modal
27-
*/
28-
escapeKey: function () {
29-
return;
30-
}
31-
}
32-
},
23+
options: {},
3324
notificationWindow: null
3425
},
3526

@@ -41,11 +32,32 @@ define([
4132
this._super();
4233
},
4334

35+
/**
36+
* Configure ESC and TAB so user can't leave modal
37+
* without selecting an option
38+
*
39+
* @returns {Object} Chainable.
40+
*/
41+
initModalEvents: function () {
42+
this._super();
43+
//Don't allow ESC key to close modal
44+
this.options.keyEventHandlers.escapeKey = this.handleEscKey.bind(this);
45+
//Restrict tab action to the modal
46+
this.options.keyEventHandlers.tabKey = this.handleTabKey.bind(this);
47+
48+
return this;
49+
},
50+
4451
/**
4552
* Once the modal is opened it hides the X
4653
*/
4754
onOpened: function () {
48-
$('.modal-header button.action-close').hide();
55+
$('.modal-header button.action-close').attr('disabled', true).hide();
56+
57+
this.focusableElements = $(this.rootSelector).find('a[href], button:enabled');
58+
this.firstFocusableElement = this.focusableElements[0];
59+
this.lastFocusableElement = this.focusableElements[this.focusableElements.length - 1];
60+
this.firstFocusableElement.focus();
4961
},
5062

5163
/**
@@ -104,11 +116,70 @@ define([
104116
* Allows admin usage popup to be shown first and then new release notification
105117
*/
106118
openReleasePopup: function () {
107-
var notifiModal = registry.get('release_notification.release_notification.notification_modal_1');
119+
var notificationModalSelector = 'release_notification.release_notification.notification_modal_1';
108120

109121
if (analyticsPopupConfig.releaseVisible) {
110-
notifiModal.initializeContentAfterAnalytics();
122+
registry.get(notificationModalSelector).initializeContentAfterAnalytics();
111123
}
124+
},
125+
126+
/**
127+
* Handle Tab and Shift+Tab key event
128+
*
129+
* Keep the tab actions restricted to the popup modal
130+
* so the user must select an option to dismiss the modal
131+
*/
132+
handleTabKey: function (event) {
133+
var modal = this,
134+
KEY_TAB = 9;
135+
136+
/**
137+
* Handle Shift+Tab to tab backwards
138+
*/
139+
function handleBackwardTab() {
140+
if (document.activeElement === modal.firstFocusableElement ||
141+
document.activeElement === $(modal.rootSelector)[0]
142+
) {
143+
event.preventDefault();
144+
modal.lastFocusableElement.focus();
145+
}
146+
}
147+
148+
/**
149+
* Handle Tab forward
150+
*/
151+
function handleForwardTab() {
152+
if (document.activeElement === modal.lastFocusableElement) {
153+
event.preventDefault();
154+
modal.firstFocusableElement.focus();
155+
}
156+
}
157+
158+
switch (event.keyCode) {
159+
case KEY_TAB:
160+
if (modal.focusableElements.length === 1) {
161+
event.preventDefault();
162+
break;
163+
}
164+
165+
if (event.shiftKey) {
166+
handleBackwardTab();
167+
break;
168+
}
169+
handleForwardTab();
170+
break;
171+
default:
172+
break;
173+
}
174+
},
175+
176+
/**
177+
* Handle Esc key
178+
*
179+
* Esc key should not close modal
180+
*/
181+
handleEscKey: function (event) {
182+
event.preventDefault();
112183
}
113184
}
114185
);

app/code/Magento/Bundle/Test/Mftf/ActionGroup/CreateBundleProductActionGroup.xml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,4 +146,17 @@
146146
<fillField selector="{{AdminProductFormBundleSection.bundleOptionXProductYQuantity(x, '4')}}" userInput="2" stepKey="fillQuantity5" after="fillQuantity4"/>
147147
<fillField selector="{{AdminProductFormBundleSection.bundleOptionXProductYQuantity(x, '5')}}" userInput="2" stepKey="fillQuantity6" after="fillQuantity5"/>
148148
</actionGroup>
149+
150+
<actionGroup name="deleteBundleOptionByIndex">
151+
<annotations>
152+
<description>Requires Navigation to Product Creation page. Removes any Bundle Option by index specified in arguments. 'deleteIndex' refers to Bundle option number.</description>
153+
</annotations>
154+
<arguments>
155+
<argument name="deleteIndex" type="string"/>
156+
</arguments>
157+
158+
<conditionalClick selector="{{AdminProductFormBundleSection.bundleItemsToggle}}" dependentSelector="{{AdminProductFormBundleSection.bundleItemsToggle}}" visible="false" stepKey="conditionallyOpenSectionBundleItems"/>
159+
<scrollTo selector="{{AdminProductFormBundleSection.bundleItemsToggle}}" stepKey="scrollUpABit"/>
160+
<click selector="{{AdminProductFormBundleSection.deleteOption(deleteIndex)}}" stepKey="clickDeleteOption"/>
161+
</actionGroup>
149162
</actionGroups>

app/code/Magento/Bundle/Test/Mftf/Section/AdminProductFormBundleSection.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,10 @@
4646
<element name="currentBundleOption" type="text" selector="//div[@data-index='bundle-items']//div[contains(@class, 'admin__collapsible-title')]/span"/>
4747
<!--AddingAnOption-->
4848
<element name="addOptions" type="button" selector="//tr[@data-repeat-index='0']//td[4]" timeout="30"/>
49+
<!--DragAnOption -->
50+
<element name="dragOption" type="block" selector="//tr[{{dragIndex}}]//div[contains(@class, 'draggable-handle')]" timeout="30" parameterized="true"/>
51+
<!--DeleteAnOption -->
52+
<element name="deleteOption" type="button" selector="//tr[{{deleteIndex}}]//button[@data-index='delete_button']" timeout="30" parameterized="true"/>
4953
<!--SEODropdownTab-->
5054
<element name="seoDropdown" type="button" selector="//div[@data-index='search-engine-optimization']"/>
5155
<element name="seoDependent" type="button" selector="//div[@data-index='search-engine-optimization']//div[contains(@class, '_show')]"/>

app/code/Magento/Bundle/Test/Mftf/Test/AdminCreateAndEditBundleProductSettingsTest.xml

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,5 +141,116 @@
141141
<argument name="websiteName" value="$createWebsite.website[name]$"/>
142142
</actionGroup>
143143
</test>
144+
<test name="AdminCreateAndEditBundleProductOptionsNegativeTest">
145+
<annotations>
146+
<features value="Bundle"/>
147+
<stories value="Modify bundle product in Admin"/>
148+
<title value="Admin should be able to remove any bundle option a bundle product"/>
149+
<description value="Admin should be able to set/edit other product information when creating/editing a bundle product"/>
150+
<severity value="MAJOR"/>
151+
<testCaseId value="MC-224"/>
152+
<skip>
153+
<issueId value="https://github.com/magento/magento2/issues/25468"/>
154+
</skip>
155+
<group value="Catalog"/>
156+
</annotations>
157+
<before>
158+
<!-- Create a Website -->
159+
<createData entity="customWebsite" stepKey="createWebsite"/>
160+
161+
<!-- Create first simple product for a bundle option -->
162+
<createData entity="SimpleProduct2" stepKey="createFirstSimpleProduct"/>
163+
164+
<!-- Create second simple product for a bundle option -->
165+
<createData entity="SimpleProduct2" stepKey="createSecondSimpleProduct"/>
166+
167+
<!-- Login as admin -->
168+
<actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/>
169+
</before>
170+
<after>
171+
<!-- Delete the simple product -->
172+
<deleteData createDataKey="createFirstSimpleProduct" stepKey="deleteFirstSimpleProduct"/>
173+
174+
<!-- Delete the simple product -->
175+
<deleteData createDataKey="createSecondSimpleProduct" stepKey="deleteSecondSimpleProduct"/>
176+
177+
<!-- Delete a Website -->
178+
<actionGroup ref="AdminDeleteWebsiteActionGroup" stepKey="deleteWebsite">
179+
<argument name="websiteName" value="Second Website"/>
180+
</actionGroup>
181+
182+
<!-- Log out -->
183+
<actionGroup ref="logout" stepKey="logout"/>
184+
</after>
185+
186+
<!-- Create new bundle product -->
187+
<actionGroup ref="GoToSpecifiedCreateProductPage" stepKey="createBundleProduct">
188+
<argument name="productType" value="bundle"/>
189+
</actionGroup>
190+
191+
<!-- Fill all main fields -->
192+
<actionGroup ref="fillMainBundleProductForm" stepKey="fillMainProductFields"/>
193+
194+
<!-- Add first bundle option to the product -->
195+
<actionGroup ref="addBundleOptionWithTwoProducts" stepKey="addFirstBundleOption">
196+
<argument name="x" value="0"/>
197+
<argument name="n" value="1"/>
198+
<argument name="prodOneSku" value="$$createFirstSimpleProduct.sku$$"/>
199+
<argument name="prodTwoSku" value="$$createSecondSimpleProduct.sku$$"/>
200+
<argument name="optionTitle" value="{{RadioButtonsOption.title}}"/>
201+
<argument name="inputType" value="{{RadioButtonsOption.type}}"/>
202+
</actionGroup>
203+
204+
<!-- Add second bundle option to the product -->
205+
<actionGroup ref="addBundleOptionWithTwoProducts" stepKey="addSecondBundleOption">
206+
<argument name="x" value="1"/>
207+
<argument name="n" value="2"/>
208+
<argument name="prodOneSku" value="$$createFirstSimpleProduct.sku$$"/>
209+
<argument name="prodTwoSku" value="$$createSecondSimpleProduct.sku$$"/>
210+
<argument name="optionTitle" value="{{CheckboxOption.title}}"/>
211+
<argument name="inputType" value="{{CheckboxOption.type}}"/>
212+
</actionGroup>
213+
214+
<!-- Add third bundle option to the product -->
215+
<actionGroup ref="addBundleOptionWithTwoProducts" stepKey="addThirdBundleOption">
216+
<argument name="x" value="2"/>
217+
<argument name="n" value="3"/>
218+
<argument name="prodOneSku" value="$$createFirstSimpleProduct.sku$$"/>
219+
<argument name="prodTwoSku" value="$$createSecondSimpleProduct.sku$$"/>
220+
<argument name="optionTitle" value="{{RadioButtonsOption.title}}"/>
221+
<argument name="inputType" value="{{RadioButtonsOption.type}}"/>
222+
</actionGroup>
223+
224+
<!-- Set product in created Website -->
225+
<actionGroup ref="AdminAssignProductInWebsiteActionGroup" stepKey="selectProductInWebsites">
226+
<argument name="website" value="$createWebsite.website[name]$"/>
227+
</actionGroup>
228+
229+
<!-- Save product form -->
230+
<actionGroup ref="saveProductForm" stepKey="saveWithThreeOptions"/>
231+
232+
<!-- Open created product -->
233+
<actionGroup ref="SearchForProductOnBackendActionGroup" stepKey="searchForSimpleProduct">
234+
<argument name="product" value="BundleProduct"/>
235+
</actionGroup>
236+
<actionGroup ref="OpenEditProductOnBackendActionGroup" stepKey="openEditProduct">
237+
<argument name="product" value="BundleProduct"/>
238+
</actionGroup>
239+
240+
<!-- Remove second option -->
241+
<actionGroup ref="deleteBundleOptionByIndex" stepKey="deleteSecondOption">
242+
<argument name="deleteIndex" value="1"/>
243+
</actionGroup>
244+
245+
<!-- Save product form -->
246+
<actionGroup ref="saveProductForm" stepKey="clickSaveProduct"/>
247+
<click selector="{{AdminProductFormActionSection.saveButton}}" stepKey="saveWithTwoOptions"/>
248+
<seeElement selector="{{AdminCategoryMessagesSection.SuccessMessage}}" stepKey="messageYouSavedTheProductIsShown"/>
249+
250+
<!-- Delete created bundle product -->
251+
<actionGroup ref="deleteProductUsingProductGrid" stepKey="deleteProduct">
252+
<argument name="product" value="BundleProduct"/>
253+
</actionGroup>
254+
</test>
144255
</tests>
145256

app/code/Magento/Bundle/etc/di.xml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,4 +221,17 @@
221221
</argument>
222222
</arguments>
223223
</type>
224+
<type name="Magento\Eav\Model\Config">
225+
<arguments>
226+
<argument name="attributesForPreload" xsi:type="array">
227+
<item name="catalog_product" xsi:type="array">
228+
<item name="price_type" xsi:type="string">catalog_product</item>
229+
<item name="price_view" xsi:type="string">catalog_product</item>
230+
<item name="shipment_type" xsi:type="string">catalog_product</item>
231+
<item name="sku_type" xsi:type="string">catalog_product</item>
232+
<item name="weight_type" xsi:type="string">catalog_product</item>
233+
</item>
234+
</argument>
235+
</arguments>
236+
</type>
224237
</config>

app/code/Magento/Catalog/Controller/Adminhtml/Category.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ public function __construct(
8282
}
8383

8484
/**
85-
* Initialize requested category and put it into registry
85+
* Initialize requested category and put it into registry.
8686
*
8787
* Root category can be returned, if inappropriate store/category is specified
8888
*
@@ -111,6 +111,8 @@ protected function _initCategory($getRootInstead = false)
111111
}
112112
}
113113

114+
$this->registry->unregister('category');
115+
$this->registry->unregister('current_category');
114116
$this->registry->register('category', $category);
115117
$this->registry->register('current_category', $category);
116118
$this->wysiwigConfig->setStoreId($storeId);

app/code/Magento/Catalog/Controller/Adminhtml/Category/Save.php

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -183,29 +183,29 @@ public function execute()
183183
$products = json_decode($categoryPostData['category_products'], true);
184184
$category->setPostedProducts($products);
185185
}
186-
$this->_eventManager->dispatch(
187-
'catalog_category_prepare_save',
188-
['category' => $category, 'request' => $this->getRequest()]
189-
);
190186

191-
/**
192-
* Check "Use Default Value" checkboxes values
193-
*/
194-
if (isset($categoryPostData['use_default']) && !empty($categoryPostData['use_default'])) {
195-
foreach ($categoryPostData['use_default'] as $attributeCode => $attributeValue) {
196-
if ($attributeValue) {
197-
$category->setData($attributeCode, null);
187+
try {
188+
$this->_eventManager->dispatch(
189+
'catalog_category_prepare_save',
190+
['category' => $category, 'request' => $this->getRequest()]
191+
);
192+
/**
193+
* Check "Use Default Value" checkboxes values
194+
*/
195+
if (isset($categoryPostData['use_default']) && !empty($categoryPostData['use_default'])) {
196+
foreach ($categoryPostData['use_default'] as $attributeCode => $attributeValue) {
197+
if ($attributeValue) {
198+
$category->setData($attributeCode, null);
199+
}
198200
}
199201
}
200-
}
201202

202-
/**
203-
* Proceed with $_POST['use_config']
204-
* set into category model for processing through validation
205-
*/
206-
$category->setData('use_post_data_config', $useConfig);
203+
/**
204+
* Proceed with $_POST['use_config']
205+
* set into category model for processing through validation
206+
*/
207+
$category->setData('use_post_data_config', $useConfig);
207208

208-
try {
209209
$categoryResource = $category->getResource();
210210
if ($category->hasCustomDesignTo()) {
211211
$categoryResource->getAttribute('custom_design_from')->setMaxValue($category->getCustomDesignTo());
@@ -231,10 +231,16 @@ public function execute()
231231

232232
$category->save();
233233
$this->messageManager->addSuccessMessage(__('You saved the category.'));
234+
// phpcs:disable Magento2.Exceptions.ThrowCatch
234235
} catch (\Magento\Framework\Exception\LocalizedException $e) {
235236
$this->messageManager->addExceptionMessage($e);
236237
$this->logger->critical($e);
237238
$this->_getSession()->setCategoryData($categoryPostData);
239+
// phpcs:disable Magento2.Exceptions.ThrowCatch
240+
} catch (\Throwable $e) {
241+
$this->messageManager->addErrorMessage(__('Something went wrong while saving the category.'));
242+
$this->logger->critical($e);
243+
$this->_getSession()->setCategoryData($categoryPostData);
238244
}
239245
}
240246

app/code/Magento/Catalog/Controller/Adminhtml/Product/Builder.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,9 @@ public function build(RequestInterface $request): ProductInterface
115115
$store = $this->storeFactory->create();
116116
$store->load($storeId);
117117

118+
$this->registry->unregister('product');
119+
$this->registry->unregister('current_product');
120+
$this->registry->unregister('current_store');
118121
$this->registry->register('product', $product);
119122
$this->registry->register('current_product', $product);
120123
$this->registry->register('current_store', $store);

0 commit comments

Comments
 (0)