@shopgate/pwa-ui-shared 7.30.0-alpha.7 → 7.30.0-alpha.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AccordionContainer/index.js +39 -5
- package/AccordionContainer/spec.js +25 -2
- package/ActionButton/index.js +63 -7
- package/ActionButton/spec.js +63 -2
- package/ActionButton/style.js +22 -1
- package/AddToCartButton/index.js +184 -27
- package/AddToCartButton/mock.js +18 -4
- package/AddToCartButton/spec.js +65 -2
- package/AddToCartButton/style.js +127 -11
- package/Availability/index.js +34 -2
- package/Availability/spec.js +41 -1
- package/Availability/style.js +19 -1
- package/Button/index.js +76 -5
- package/Button/spec.js +33 -1
- package/Button/style.js +130 -21
- package/ButtonLink/connector.js +11 -2
- package/ButtonLink/index.js +44 -6
- package/ButtonLink/spec.js +23 -1
- package/Card/index.js +19 -2
- package/Card/style.js +11 -1
- package/CardList/components/Item/index.js +26 -2
- package/CardList/components/Item/style.js +7 -1
- package/CardList/index.js +34 -3
- package/CartTotalLine/components/Amount/index.js +28 -2
- package/CartTotalLine/components/Amount/style.js +8 -1
- package/CartTotalLine/components/Hint/index.js +23 -2
- package/CartTotalLine/components/Hint/style.js +12 -1
- package/CartTotalLine/components/Label/index.js +36 -2
- package/CartTotalLine/components/Label/style.js +17 -1
- package/CartTotalLine/components/Spacer/index.js +16 -2
- package/CartTotalLine/index.js +39 -2
- package/CartTotalLine/style.js +31 -1
- package/Checkbox/index.js +31 -2
- package/Checkbox/style.js +18 -1
- package/Chip/index.js +61 -2
- package/Chip/spec.js +24 -1
- package/Chip/style.js +71 -3
- package/ContextMenu/ContextMenu.hooks.js +6 -2
- package/ContextMenu/ContextMenuProvider.context.js +9 -3
- package/ContextMenu/ContextMenuProvider.js +21 -2
- package/ContextMenu/components/Item/index.js +67 -5
- package/ContextMenu/components/Item/style.js +32 -3
- package/ContextMenu/components/Position/index.js +61 -10
- package/ContextMenu/components/Position/style.js +11 -1
- package/ContextMenu/index.js +124 -3
- package/ContextMenu/spec.js +101 -2
- package/ContextMenu/style.js +45 -1
- package/Dialog/components/BasicDialog/index.js +5 -1
- package/Dialog/components/HtmlContentDialog/index.js +22 -2
- package/Dialog/components/HtmlContentDialog/spec.js +59 -1
- package/Dialog/components/PipelineErrorDialog/index.js +114 -25
- package/Dialog/components/PipelineErrorDialog/spec.js +92 -12
- package/Dialog/components/TextMessageDialog/index.js +28 -2
- package/Dialog/components/TextMessageDialog/spec.js +59 -1
- package/Dialog/components/VariantSelectModal/connector.js +11 -2
- package/Dialog/components/VariantSelectModal/index.js +65 -6
- package/Dialog/components/VariantSelectModal/spec.js +51 -2
- package/Dialog/constants.js +6 -1
- package/Dialog/index.js +114 -7
- package/Dialog/spec.js +81 -3
- package/DiscountBadge/index.js +30 -2
- package/DiscountBadge/spec.js +19 -1
- package/DiscountBadge/style.js +34 -2
- package/FavoritesButton/connector.js +18 -3
- package/FavoritesButton/index.js +118 -15
- package/FavoritesButton/mock.js +50 -4
- package/FavoritesButton/spec.js +120 -2
- package/FavoritesButton/style.js +26 -1
- package/Form/Builder/builders/buildCountryList.js +40 -6
- package/Form/Builder/builders/buildFormDefaults.js +35 -6
- package/Form/Builder/builders/buildFormElements.js +68 -10
- package/Form/Builder/builders/buildProvinceList.js +19 -2
- package/Form/Builder/builders/buildValidationErrorList.js +7 -2
- package/Form/Builder/classes/ActionListener/constants.js +22 -2
- package/Form/Builder/classes/ActionListener/index.js +441 -93
- package/Form/Builder/classes/ActionListener/spec.js +321 -19
- package/Form/Builder/components/CheckboxElement.js +35 -3
- package/Form/Builder/components/CountryElement.js +40 -3
- package/Form/Builder/components/ProvinceElement.js +40 -3
- package/Form/Builder/components/RadioElement.js +41 -3
- package/Form/Builder/components/SelectElement.js +39 -3
- package/Form/Builder/components/TextElement.js +49 -4
- package/Form/Builder/elementTypes.js +11 -1
- package/Form/Builder/index.js +298 -52
- package/Form/Builder/iso-3166-2.js +4943 -1
- package/Form/Builder/spec.js +308 -16
- package/Form/Checkbox/index.js +66 -4
- package/Form/Checkbox/style.js +25 -2
- package/Form/InfoField/index.js +50 -2
- package/Form/InfoField/spec.js +9 -1
- package/Form/InfoField/style.js +11 -1
- package/Form/Password/index.js +51 -6
- package/Form/Password/spec.js +34 -1
- package/Form/Password/style.js +11 -1
- package/Form/RadioGroup/components/Item/index.js +59 -3
- package/Form/RadioGroup/components/Item/style.js +32 -2
- package/Form/RadioGroup/index.js +101 -9
- package/Form/RadioGroup/spec.js +83 -3
- package/Form/RadioGroup/style.js +18 -2
- package/Form/Select/index.js +158 -10
- package/Form/Select/spec.js +36 -5
- package/Form/Select/style.js +27 -1
- package/Form/SelectContextChoices/index.js +77 -3
- package/Form/SelectContextChoices/spec.js +33 -4
- package/Form/SelectContextChoices/style.js +23 -1
- package/Form/TextField/index.js +92 -8
- package/Form/TextField/spec.js +110 -1
- package/Form/TextField/style.js +66 -8
- package/Form/index.js +54 -13
- package/FormElement/components/ErrorText/index.js +31 -2
- package/FormElement/components/ErrorText/style.js +13 -1
- package/FormElement/components/Label/index.js +35 -2
- package/FormElement/components/Label/style.js +76 -8
- package/FormElement/components/Placeholder/index.js +26 -2
- package/FormElement/components/Placeholder/style.js +48 -6
- package/FormElement/components/Underline/index.js +18 -2
- package/FormElement/components/Underline/style.js +51 -4
- package/FormElement/index.js +91 -6
- package/FormElement/spec.js +67 -2
- package/FormElement/style.js +13 -2
- package/Glow/index.js +90 -7
- package/Glow/spec.js +9 -1
- package/Glow/style.js +18 -1
- package/IndicatorCircle/index.js +33 -3
- package/IndicatorCircle/spec.js +28 -1
- package/IndicatorCircle/style.js +57 -3
- package/LoadingIndicator/index.js +29 -2
- package/LoadingIndicator/style.js +20 -1
- package/Manufacturer/index.js +20 -2
- package/Manufacturer/style.js +5 -1
- package/MessageBar/index.js +36 -2
- package/MessageBar/spec.js +79 -1
- package/MessageBar/style.js +38 -1
- package/NoResults/components/Icon/index.js +130 -2
- package/NoResults/components/Icon/style.js +17 -1
- package/NoResults/index.js +46 -2
- package/NoResults/style.js +31 -1
- package/Placeholder/index.js +25 -3
- package/Placeholder/style.js +11 -1
- package/PlaceholderLabel/index.js +27 -2
- package/PlaceholderLabel/spec.js +19 -1
- package/PlaceholderLabel/style.js +12 -1
- package/PlaceholderParagraph/index.js +36 -2
- package/PlaceholderParagraph/spec.js +19 -1
- package/Price/index.js +88 -7
- package/Price/style.js +22 -1
- package/PriceInfo/index.js +20 -2
- package/PriceInfo/style.js +5 -1
- package/PriceStriked/index.js +83 -12
- package/PriceStriked/style.js +33 -3
- package/ProductProperties/index.js +32 -2
- package/ProgressBar/index.js +101 -13
- package/ProgressBar/spec.js +13 -1
- package/ProgressBar/style.js +83 -2
- package/RadioButton/index.js +18 -2
- package/RadioButton/spec.js +21 -1
- package/RadioButton/style.js +21 -1
- package/RatingNumber/index.js +29 -2
- package/RatingStars/constants.js +2 -1
- package/RatingStars/index.js +130 -12
- package/RatingStars/spec.js +90 -3
- package/RatingStars/style.js +51 -2
- package/Ripple/components/RippleAnimation/index.js +88 -6
- package/Ripple/index.js +218 -40
- package/Ripple/style.js +18 -1
- package/RippleButton/index.js +52 -5
- package/RippleButton/spec.js +45 -1
- package/ScannerOverlay/components/CameraOverlay/index.js +13 -2
- package/ScannerOverlay/components/CameraOverlay/style.js +40 -1
- package/ScannerOverlay/components/ScannerBar/components/FlashlightButton/index.js +34 -2
- package/ScannerOverlay/components/ScannerBar/components/FlashlightButton/style.js +28 -1
- package/ScannerOverlay/components/ScannerBar/components/ScannerInstructions/index.js +11 -2
- package/ScannerOverlay/components/ScannerBar/index.js +31 -2
- package/ScannerOverlay/components/ScannerBar/style.js +20 -1
- package/ScannerOverlay/index.js +47 -7
- package/Sheet/components/Header/components/SearchBar/index.js +46 -2
- package/Sheet/components/Header/components/SearchBar/spec.js +21 -3
- package/Sheet/components/Header/components/SearchBar/style.js +47 -1
- package/Sheet/components/Header/index.js +75 -7
- package/Sheet/components/Header/spec.js +14 -1
- package/Sheet/components/Header/style.js +50 -1
- package/Sheet/index.js +170 -17
- package/Sheet/spec.js +85 -5
- package/Sheet/style.js +143 -2
- package/TaxDisclaimer/index.js +34 -4
- package/TaxDisclaimer/spec.js +31 -3
- package/TaxDisclaimer/style.js +9 -1
- package/TextField/components/ErrorText/index.js +33 -2
- package/TextField/components/ErrorText/style.js +25 -3
- package/TextField/components/FormElement/index.js +19 -2
- package/TextField/components/FormElement/style.js +32 -4
- package/TextField/components/Hint/index.js +21 -2
- package/TextField/components/Hint/style.js +40 -5
- package/TextField/components/Label/index.js +32 -3
- package/TextField/components/Label/style.js +68 -8
- package/TextField/components/Underline/index.js +19 -2
- package/TextField/components/Underline/style.js +51 -4
- package/TextField/index.js +189 -27
- package/TextField/spec.js +128 -3
- package/TextField/style.js +34 -4
- package/ToggleIcon/index.js +58 -8
- package/ToggleIcon/spec.js +35 -1
- package/icons/AccountBoxIcon.js +11 -2
- package/icons/AddMoreIcon.js +11 -2
- package/icons/ArrowDropIcon.js +11 -2
- package/icons/ArrowIcon.js +21 -2
- package/icons/BarcodeScannerIcon.js +11 -2
- package/icons/BoxIcon.js +11 -2
- package/icons/BrowseIcon.js +11 -2
- package/icons/BurgerIcon.js +11 -2
- package/icons/CalendarIcon.js +15 -3
- package/icons/CartCouponIcon.js +72 -2
- package/icons/CartIcon.js +11 -2
- package/icons/CartPlusIcon.js +11 -2
- package/icons/CheckIcon.js +11 -2
- package/icons/CheckedIcon.js +11 -2
- package/icons/ChevronIcon.js +11 -2
- package/icons/CreditCardIcon.js +11 -2
- package/icons/CrossIcon.js +11 -2
- package/icons/DescriptionIcon.js +11 -2
- package/icons/FilterIcon.js +11 -2
- package/icons/FlashDisabledIcon.js +11 -2
- package/icons/FlashEnabledIcon.js +11 -2
- package/icons/GridIcon.js +11 -2
- package/icons/HeartIcon.js +11 -2
- package/icons/HeartOutlineIcon.js +11 -2
- package/icons/HeartPlusIcon.js +12 -2
- package/icons/HeartPlusOutlineIcon.js +12 -2
- package/icons/HomeIcon.js +11 -2
- package/icons/InfoIcon.js +11 -2
- package/icons/InfoOutlineIcon.js +11 -2
- package/icons/ListIcon.js +11 -2
- package/icons/LocalShippingIcon.js +11 -2
- package/icons/LocationIcon.js +13 -3
- package/icons/LocatorIcon.js +11 -2
- package/icons/LockIcon.js +11 -2
- package/icons/LogoutIcon.js +11 -2
- package/icons/MagnifierIcon.js +11 -2
- package/icons/MapMarkerIcon.js +24 -3
- package/icons/MoreIcon.js +11 -2
- package/icons/MoreVertIcon.js +11 -2
- package/icons/NotificationIcon.js +14 -3
- package/icons/PersonIcon.js +12 -2
- package/icons/PhoneIcon.js +13 -3
- package/icons/PlaceholderIcon.js +11 -2
- package/icons/RadioCheckedIcon.js +11 -2
- package/icons/RadioUncheckedIcon.js +11 -2
- package/icons/SecurityIcon.js +11 -2
- package/icons/ShippingMethodIcon.js +18 -3
- package/icons/ShoppingCartIcon.js +11 -2
- package/icons/SortIcon.js +11 -2
- package/icons/StarHalfIcon.js +18 -2
- package/icons/StarIcon.js +18 -2
- package/icons/StarOutlineIcon.js +11 -2
- package/icons/StopIcon.js +11 -2
- package/icons/TickIcon.js +11 -2
- package/icons/TimeIcon.js +14 -3
- package/icons/TrashIcon.js +11 -2
- package/icons/TrashOutlineIcon.js +12 -2
- package/icons/UncheckedIcon.js +11 -2
- package/icons/ViewListIcon.js +11 -2
- package/icons/VisibilityIcon.js +11 -2
- package/icons/VisibilityOffIcon.js +11 -2
- package/icons/WarningIcon.js +11 -2
- package/index.js +13 -1
- package/package.json +5 -5
package/ContextMenu/style.js
CHANGED
|
@@ -1 +1,45 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { css } from 'glamor';
|
|
2
|
+
import { themeConfig } from '@shopgate/pwa-common/helpers/config';
|
|
3
|
+
const container = css({
|
|
4
|
+
position: 'relative'
|
|
5
|
+
}).toString();
|
|
6
|
+
const button = css({
|
|
7
|
+
display: 'block',
|
|
8
|
+
fontSize: '1.5rem',
|
|
9
|
+
outline: 0,
|
|
10
|
+
padding: 0,
|
|
11
|
+
color: 'inherit'
|
|
12
|
+
}).toString();
|
|
13
|
+
const disabled = css({
|
|
14
|
+
cursor: 'not-allowed'
|
|
15
|
+
}).toString();
|
|
16
|
+
const overlay = css({
|
|
17
|
+
position: 'fixed',
|
|
18
|
+
top: 0,
|
|
19
|
+
right: 0,
|
|
20
|
+
bottom: 0,
|
|
21
|
+
left: 0,
|
|
22
|
+
zIndex: 10
|
|
23
|
+
}).toString();
|
|
24
|
+
const menu = css({
|
|
25
|
+
position: 'absolute',
|
|
26
|
+
top: 0,
|
|
27
|
+
left: 0,
|
|
28
|
+
padding: `${themeConfig.variables.gap.small}px 0`,
|
|
29
|
+
minWidth: 130,
|
|
30
|
+
background: themeConfig.colors.light,
|
|
31
|
+
borderRadius: 2,
|
|
32
|
+
boxShadow: themeConfig.shadows.contextMenu
|
|
33
|
+
}).toString();
|
|
34
|
+
const scrollable = css({
|
|
35
|
+
maxHeight: '30vh',
|
|
36
|
+
overflowY: 'auto'
|
|
37
|
+
}).toString();
|
|
38
|
+
export default {
|
|
39
|
+
container,
|
|
40
|
+
button,
|
|
41
|
+
menu,
|
|
42
|
+
overlay,
|
|
43
|
+
disabled,
|
|
44
|
+
scrollable
|
|
45
|
+
};
|
|
@@ -1,2 +1,6 @@
|
|
|
1
1
|
// TODO: Move to ThemeContext
|
|
2
|
-
import BaseDialogGMD from'@shopgate/pwa-ui-material/BaseDialog';
|
|
2
|
+
import BaseDialogGMD from '@shopgate/pwa-ui-material/BaseDialog';
|
|
3
|
+
import BaseDialogIOS from '@shopgate/pwa-ui-ios/BaseDialog';
|
|
4
|
+
import { themeName } from '@shopgate/pwa-common/helpers/config';
|
|
5
|
+
const isIos = themeName.includes('ios');
|
|
6
|
+
export default isIos ? BaseDialogIOS : BaseDialogGMD;
|
|
@@ -1,6 +1,26 @@
|
|
|
1
|
-
import React from'react';
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import PropTypes from 'prop-types';
|
|
3
|
+
import BasicDialog from "../BasicDialog";
|
|
4
|
+
|
|
5
|
+
/**
|
|
2
6
|
* Renders a simple dialog with a title and html content as a message.
|
|
3
7
|
* This is the default dialog if no type has been specified.
|
|
4
8
|
* @param {Object} props The component properties.
|
|
5
9
|
* @returns {JSX.Element} The rendered component.
|
|
6
|
-
*/
|
|
10
|
+
*/
|
|
11
|
+
const HtmlContentDialog = ({
|
|
12
|
+
actions,
|
|
13
|
+
message,
|
|
14
|
+
title
|
|
15
|
+
}) => /*#__PURE__*/React.createElement(BasicDialog, {
|
|
16
|
+
title: title,
|
|
17
|
+
actions: actions
|
|
18
|
+
}, /*#__PURE__*/React.createElement("div", {
|
|
19
|
+
dangerouslySetInnerHTML: {
|
|
20
|
+
__html: message
|
|
21
|
+
}
|
|
22
|
+
}));
|
|
23
|
+
HtmlContentDialog.defaultProps = {
|
|
24
|
+
title: BasicDialog.defaultProps.title
|
|
25
|
+
};
|
|
26
|
+
export default HtmlContentDialog;
|
|
@@ -1 +1,59 @@
|
|
|
1
|
-
import React from'react';
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { shallow } from 'enzyme';
|
|
3
|
+
import HtmlContentDialog from "./index";
|
|
4
|
+
const message = '<p><i>This is a html message.</i></p>';
|
|
5
|
+
const title = 'This is the title.';
|
|
6
|
+
jest.mock('@shopgate/engage/a11y/components');
|
|
7
|
+
describe('<HtmlContentDialog />', () => {
|
|
8
|
+
it('should render with minimal props', () => {
|
|
9
|
+
const wrapper = shallow(/*#__PURE__*/React.createElement(HtmlContentDialog, {
|
|
10
|
+
message: message,
|
|
11
|
+
actions: []
|
|
12
|
+
}));
|
|
13
|
+
expect(wrapper).toMatchSnapshot();
|
|
14
|
+
expect(wrapper.html()).toMatch(message);
|
|
15
|
+
});
|
|
16
|
+
it('should render with title and html message', () => {
|
|
17
|
+
const wrapper = shallow(/*#__PURE__*/React.createElement(HtmlContentDialog, {
|
|
18
|
+
title: title,
|
|
19
|
+
message: message,
|
|
20
|
+
actions: []
|
|
21
|
+
}));
|
|
22
|
+
expect(wrapper).toMatchSnapshot();
|
|
23
|
+
expect(wrapper.html()).toMatch(title);
|
|
24
|
+
});
|
|
25
|
+
it('should render with title, html message and messageParams', () => {
|
|
26
|
+
const wrapper = shallow(/*#__PURE__*/React.createElement(HtmlContentDialog, {
|
|
27
|
+
title: title,
|
|
28
|
+
message: "Message with {name}",
|
|
29
|
+
params: {
|
|
30
|
+
name: 'Placeholder'
|
|
31
|
+
},
|
|
32
|
+
actions: []
|
|
33
|
+
}));
|
|
34
|
+
expect(wrapper).toMatchSnapshot();
|
|
35
|
+
});
|
|
36
|
+
it('should render the actions', () => {
|
|
37
|
+
const actions = [{
|
|
38
|
+
label: 'fooAction',
|
|
39
|
+
action: () => {}
|
|
40
|
+
}];
|
|
41
|
+
const wrapper = shallow(/*#__PURE__*/React.createElement(HtmlContentDialog, {
|
|
42
|
+
title: title,
|
|
43
|
+
message: message,
|
|
44
|
+
actions: actions
|
|
45
|
+
}));
|
|
46
|
+
expect(wrapper).toMatchSnapshot();
|
|
47
|
+
expect(wrapper.html()).toMatch(actions[0].label);
|
|
48
|
+
});
|
|
49
|
+
it('should pass title through', () => {
|
|
50
|
+
const customTitle = /*#__PURE__*/React.createElement("div", null, "Title");
|
|
51
|
+
const wrapper = shallow(/*#__PURE__*/React.createElement(HtmlContentDialog, {
|
|
52
|
+
title: customTitle,
|
|
53
|
+
message: message,
|
|
54
|
+
params: {},
|
|
55
|
+
actions: []
|
|
56
|
+
}));
|
|
57
|
+
expect(wrapper.find('BasicDialog').prop('title')).toEqual(customTitle);
|
|
58
|
+
});
|
|
59
|
+
});
|
|
@@ -1,36 +1,125 @@
|
|
|
1
|
-
|
|
1
|
+
import React, { Component } from 'react';
|
|
2
|
+
import PropTypes from 'prop-types';
|
|
3
|
+
import I18n from '@shopgate/pwa-common/components/I18n';
|
|
4
|
+
import BasicDialog from "../BasicDialog";
|
|
5
|
+
|
|
6
|
+
/**
|
|
2
7
|
* The number of taps required until the dialog switches to/from developer mode.
|
|
3
|
-
*/
|
|
8
|
+
*/
|
|
9
|
+
const requiredTapsToSwitchModes = 10;
|
|
10
|
+
|
|
11
|
+
/**
|
|
4
12
|
* The timeout between repeated tapping on the message (in ms).
|
|
5
|
-
*/
|
|
13
|
+
*/
|
|
14
|
+
const switchModeTapTimeout = 4000 / requiredTapsToSwitchModes;
|
|
15
|
+
|
|
16
|
+
/**
|
|
6
17
|
* This component displays a pipeline error dialog.
|
|
7
18
|
* The special behaviour of this message is that the user may tap the message body
|
|
8
19
|
* ten times until it reveals additional information about the error that occurred.
|
|
9
|
-
*/
|
|
20
|
+
*/
|
|
21
|
+
class PipelineErrorDialog extends Component {
|
|
22
|
+
/**
|
|
10
23
|
* Creates the component.
|
|
11
24
|
* @param {Object} props The component props.
|
|
12
|
-
*/
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
*
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
}
|
|
25
|
+
*/
|
|
26
|
+
constructor(props) {
|
|
27
|
+
super(props);
|
|
28
|
+
/**
|
|
29
|
+
* Clears the tap counter once the
|
|
30
|
+
*/
|
|
31
|
+
this.handleTapTimeout = () => {
|
|
32
|
+
this.tapCounter = 0;
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* User tapped the message, increase the tap counter and switch view modes if required.
|
|
36
|
+
*/
|
|
37
|
+
this.handleClick = () => {
|
|
38
|
+
this.tapCounter += 1;
|
|
39
|
+
if (this.tapTimeout) {
|
|
40
|
+
// Clear the timeout.
|
|
41
|
+
clearTimeout(this.tapTimeout);
|
|
42
|
+
}
|
|
43
|
+
if (this.tapCounter >= requiredTapsToSwitchModes) {
|
|
44
|
+
// Switch modes and reset the tap counter.
|
|
45
|
+
this.tapCounter = 0;
|
|
46
|
+
this.setState(({
|
|
47
|
+
devMode
|
|
48
|
+
}) => ({
|
|
49
|
+
devMode: !devMode
|
|
50
|
+
}));
|
|
51
|
+
} else {
|
|
52
|
+
this.tapTimeout = setTimeout(this.handleTapTimeout, switchModeTapTimeout);
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
/**
|
|
56
|
+
* Renders the error message in developer mode.
|
|
57
|
+
* @returns {JSX}
|
|
58
|
+
*/
|
|
59
|
+
this.renderDevErrorMessage = () => {
|
|
60
|
+
/**
|
|
61
|
+
* Checks the input to be truthy, "0" or "false" and enables it to be rendered then.
|
|
62
|
+
* @param {Object|string|number|boolean} value The value to be checked if it should be rendered.
|
|
63
|
+
* @returns {boolean}
|
|
64
|
+
*/
|
|
65
|
+
const checkValue = value => !!value || value === 0 || value === false;
|
|
66
|
+
const {
|
|
67
|
+
params
|
|
68
|
+
} = this.props;
|
|
69
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
70
|
+
"aria-hidden": true
|
|
71
|
+
}, /*#__PURE__*/React.createElement("span", null, /*#__PURE__*/React.createElement("strong", null, "Pipeline:"), /*#__PURE__*/React.createElement("span", null, ` ${params.pipeline}`), /*#__PURE__*/React.createElement("br", null)), checkValue(params.entityId) && /*#__PURE__*/React.createElement("span", null, /*#__PURE__*/React.createElement("strong", null, "Entity id:"), /*#__PURE__*/React.createElement("span", null, ` ${params.entityId}`), /*#__PURE__*/React.createElement("br", null)), checkValue(params.code) && /*#__PURE__*/React.createElement("span", null, /*#__PURE__*/React.createElement("strong", null, "Code:"), /*#__PURE__*/React.createElement("span", null, ` ${params.code}`), /*#__PURE__*/React.createElement("br", null)), /*#__PURE__*/React.createElement("span", null, /*#__PURE__*/React.createElement("strong", null, "Message:"), /*#__PURE__*/React.createElement("span", null, ` ${params.message}`), /*#__PURE__*/React.createElement("br", null)), checkValue(params.translated) && /*#__PURE__*/React.createElement("span", null, /*#__PURE__*/React.createElement("strong", null, "Message Translated:"), /*#__PURE__*/React.createElement("span", null, ` ${params.translated.toString()}`), /*#__PURE__*/React.createElement("br", null)), checkValue(params.messageParams) && /*#__PURE__*/React.createElement("p", null, /*#__PURE__*/React.createElement("strong", null, "Message Params:"), /*#__PURE__*/React.createElement("br", null), /*#__PURE__*/React.createElement("span", null, JSON.stringify(params.messageParams, null, ' ')), /*#__PURE__*/React.createElement("br", null)), checkValue(params.request) && /*#__PURE__*/React.createElement("p", null, /*#__PURE__*/React.createElement("strong", null, "Request Params:"), /*#__PURE__*/React.createElement("br", null), /*#__PURE__*/React.createElement("span", null, JSON.stringify(params.request, null, ' ')), /*#__PURE__*/React.createElement("br", null)));
|
|
72
|
+
};
|
|
73
|
+
/**
|
|
74
|
+
* Renders the regular error message in user mode.
|
|
75
|
+
* @returns {JSX}
|
|
76
|
+
*/
|
|
77
|
+
this.renderUserErrorMessage = () => {
|
|
78
|
+
const {
|
|
79
|
+
message = '',
|
|
80
|
+
params = {}
|
|
81
|
+
} = this.props;
|
|
82
|
+
return /*#__PURE__*/React.createElement(React.Fragment, null, !!params.translated && (message || params.message || /*#__PURE__*/React.createElement(I18n.Text, {
|
|
83
|
+
string: "modal.body_error"
|
|
84
|
+
})), !params.translated && /*#__PURE__*/React.createElement(I18n.Text, {
|
|
85
|
+
string: message || params.message || 'modal.body_error',
|
|
86
|
+
params: params.messageParams || {}
|
|
87
|
+
}));
|
|
88
|
+
};
|
|
89
|
+
this.tapTimeout = null;
|
|
90
|
+
this.tapCounter = 0;
|
|
91
|
+
this.state = {
|
|
92
|
+
devMode: false // Indicating whether we are in dev mode.
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
30
97
|
* @return {string} The title based on the current state of the dialog.
|
|
31
|
-
*/
|
|
98
|
+
*/
|
|
99
|
+
get title() {
|
|
100
|
+
return this.state.devMode ? 'Pipeline Error' : 'modal.title_error';
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
32
104
|
* @return {JSX} The content component based on the the current state of the dialog.
|
|
33
|
-
*/
|
|
105
|
+
*/
|
|
106
|
+
get content() {
|
|
107
|
+
return this.state.devMode ? this.renderDevErrorMessage() : this.renderUserErrorMessage();
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
34
110
|
* Renders the error message depending on the current mode.
|
|
35
111
|
* @return {JSX}
|
|
36
|
-
*/
|
|
112
|
+
*/
|
|
113
|
+
render() {
|
|
114
|
+
return /*#__PURE__*/React.createElement(BasicDialog, {
|
|
115
|
+
title: this.title,
|
|
116
|
+
actions: this.props.actions
|
|
117
|
+
}, /*#__PURE__*/React.createElement("div", {
|
|
118
|
+
onClick: this.handleClick
|
|
119
|
+
}, this.content));
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
PipelineErrorDialog.defaultProps = {
|
|
123
|
+
message: ''
|
|
124
|
+
};
|
|
125
|
+
export default PipelineErrorDialog;
|
|
@@ -1,14 +1,94 @@
|
|
|
1
|
-
import React from'react';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { mount } from 'enzyme';
|
|
3
|
+
import PipelineErrorDialog from "./index";
|
|
4
|
+
jest.mock('@shopgate/engage/a11y/components');
|
|
5
|
+
describe('<PipelineErrorDialog />', () => {
|
|
6
|
+
const defaultParams = {
|
|
7
|
+
code: '123',
|
|
8
|
+
message: 'Error message',
|
|
9
|
+
pipeline: 'fakePipeline',
|
|
10
|
+
request: {}
|
|
11
|
+
};
|
|
12
|
+
it('should render with minimal props', () => {
|
|
13
|
+
const wrapper = mount(/*#__PURE__*/React.createElement(PipelineErrorDialog, {
|
|
14
|
+
actions: [],
|
|
15
|
+
params: defaultParams
|
|
16
|
+
}));
|
|
17
|
+
expect(wrapper).toMatchSnapshot();
|
|
18
|
+
});
|
|
19
|
+
it('should show a custom message if a message is is provided', () => {
|
|
20
|
+
const message = 'Custom message';
|
|
21
|
+
const wrapper = mount(/*#__PURE__*/React.createElement(PipelineErrorDialog, {
|
|
22
|
+
actions: [],
|
|
23
|
+
message: message,
|
|
24
|
+
params: defaultParams
|
|
25
|
+
}));
|
|
26
|
+
expect(wrapper).toMatchSnapshot();
|
|
27
|
+
expect(wrapper.html()).toMatch(message);
|
|
28
|
+
});
|
|
29
|
+
it('should switch modes on tap', () => {
|
|
30
|
+
const wrapper = mount(/*#__PURE__*/React.createElement(PipelineErrorDialog, {
|
|
31
|
+
actions: [],
|
|
32
|
+
params: defaultParams
|
|
33
|
+
}));
|
|
34
|
+
const numTaps = 10;
|
|
35
|
+
const clickElement = wrapper.find('div[onClick]');
|
|
36
|
+
|
|
37
|
+
// Dev mode should be disabled.
|
|
38
|
+
for (let i = 0; i < numTaps; i += 1) {
|
|
39
|
+
expect(wrapper.state().devMode).toBe(false);
|
|
40
|
+
clickElement.simulate('click');
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Dev mode should be enabled.
|
|
44
|
+
for (let i = 0; i < numTaps; i += 1) {
|
|
45
|
+
expect(wrapper.state().devMode).toBe(true);
|
|
46
|
+
clickElement.simulate('click');
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Dev mode should be disabled again.
|
|
50
|
+
expect(wrapper.state().devMode).toBe(false);
|
|
51
|
+
});
|
|
52
|
+
it('should not switch modes if tapped too slow', () => {
|
|
53
|
+
jest.useFakeTimers();
|
|
54
|
+
const wrapper = mount(/*#__PURE__*/React.createElement(PipelineErrorDialog, {
|
|
55
|
+
actions: [],
|
|
56
|
+
params: defaultParams
|
|
57
|
+
}));
|
|
58
|
+
const numTaps = 10;
|
|
59
|
+
const numTapsUntilTimeout = Math.round(numTaps / 2);
|
|
60
|
+
const clickElement = wrapper.find('div[onClick]');
|
|
61
|
+
|
|
62
|
+
// Dev mode should be disabled.
|
|
63
|
+
expect(wrapper.state().devMode).toBe(false);
|
|
64
|
+
|
|
65
|
+
/**
|
|
6
66
|
* Simulates multiple tap events.
|
|
7
67
|
* @param {number} amount The number of tap events to simulate in a row.
|
|
8
|
-
*/
|
|
9
|
-
tapOnElement
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
68
|
+
*/
|
|
69
|
+
const tapOnElement = amount => {
|
|
70
|
+
if (amount > 0) {
|
|
71
|
+
clickElement.simulate('click');
|
|
72
|
+
tapOnElement(amount - 1);
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
// Tap a few times.
|
|
77
|
+
tapOnElement(numTapsUntilTimeout);
|
|
78
|
+
|
|
79
|
+
// Trigger a timeout (user was too slow).
|
|
80
|
+
jest.runAllTimers();
|
|
81
|
+
|
|
82
|
+
// Tap the remaining times.
|
|
83
|
+
tapOnElement(numTaps - numTapsUntilTimeout);
|
|
84
|
+
|
|
85
|
+
// We timed out and should not be in dev mode by now.
|
|
86
|
+
expect(wrapper.state().devMode).toBe(false);
|
|
87
|
+
|
|
88
|
+
// Add the remaining amount of taps to enter dev mode.
|
|
89
|
+
tapOnElement(numTapsUntilTimeout);
|
|
90
|
+
|
|
91
|
+
// This time dev mode should be enabled.
|
|
92
|
+
expect(wrapper.state().devMode).toBe(true);
|
|
93
|
+
});
|
|
94
|
+
});
|
|
@@ -1,6 +1,32 @@
|
|
|
1
|
-
import React from'react';
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import PropTypes from 'prop-types';
|
|
3
|
+
import I18n from '@shopgate/pwa-common/components/I18n';
|
|
4
|
+
import { i18n, nl2br } from '@shopgate/engage/core';
|
|
5
|
+
import BasicDialog from "../BasicDialog";
|
|
6
|
+
|
|
7
|
+
/**
|
|
2
8
|
* Renders a simple dialog with a title and a text message.
|
|
3
9
|
* This is the default dialog if no type has been specified.
|
|
4
10
|
* @param {Object} props The component properties.
|
|
5
11
|
* @returns {JSX} The rendered component.
|
|
6
|
-
*/
|
|
12
|
+
*/
|
|
13
|
+
const TextMessageDialog = ({
|
|
14
|
+
actions,
|
|
15
|
+
message,
|
|
16
|
+
title,
|
|
17
|
+
params,
|
|
18
|
+
children
|
|
19
|
+
}) => /*#__PURE__*/React.createElement(BasicDialog, {
|
|
20
|
+
title: title,
|
|
21
|
+
actions: actions
|
|
22
|
+
}, /*#__PURE__*/React.createElement("span", {
|
|
23
|
+
dangerouslySetInnerHTML: {
|
|
24
|
+
__html: nl2br(i18n.text(message, params))
|
|
25
|
+
}
|
|
26
|
+
}), children);
|
|
27
|
+
TextMessageDialog.defaultProps = {
|
|
28
|
+
title: BasicDialog.defaultProps.title,
|
|
29
|
+
params: I18n.Text.defaultProps.params,
|
|
30
|
+
children: null
|
|
31
|
+
};
|
|
32
|
+
export default TextMessageDialog;
|
|
@@ -1 +1,59 @@
|
|
|
1
|
-
import React from'react';
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { shallow } from 'enzyme';
|
|
3
|
+
import TextMessageDialog from "./index";
|
|
4
|
+
const message = 'This is the message.';
|
|
5
|
+
const title = 'This is the title.';
|
|
6
|
+
jest.mock('@shopgate/engage/a11y/components');
|
|
7
|
+
describe('<TextMessageDialog />', () => {
|
|
8
|
+
it('should render with minimal props', () => {
|
|
9
|
+
const wrapper = shallow(/*#__PURE__*/React.createElement(TextMessageDialog, {
|
|
10
|
+
message: message,
|
|
11
|
+
actions: []
|
|
12
|
+
}));
|
|
13
|
+
expect(wrapper).toMatchSnapshot();
|
|
14
|
+
expect(wrapper.html()).toMatch(message);
|
|
15
|
+
});
|
|
16
|
+
it('should render with title and message', () => {
|
|
17
|
+
const wrapper = shallow(/*#__PURE__*/React.createElement(TextMessageDialog, {
|
|
18
|
+
title: title,
|
|
19
|
+
message: message,
|
|
20
|
+
actions: []
|
|
21
|
+
}));
|
|
22
|
+
expect(wrapper).toMatchSnapshot();
|
|
23
|
+
expect(wrapper.html()).toMatch(title);
|
|
24
|
+
});
|
|
25
|
+
it('should render with title, message and messageParams', () => {
|
|
26
|
+
const wrapper = shallow(/*#__PURE__*/React.createElement(TextMessageDialog, {
|
|
27
|
+
title: title,
|
|
28
|
+
message: "Message with {name}",
|
|
29
|
+
params: {
|
|
30
|
+
name: 'Placeholder'
|
|
31
|
+
},
|
|
32
|
+
actions: []
|
|
33
|
+
}));
|
|
34
|
+
expect(wrapper).toMatchSnapshot();
|
|
35
|
+
});
|
|
36
|
+
it('should render the actions', () => {
|
|
37
|
+
const actions = [{
|
|
38
|
+
label: 'fooAction',
|
|
39
|
+
action: () => {}
|
|
40
|
+
}];
|
|
41
|
+
const wrapper = shallow(/*#__PURE__*/React.createElement(TextMessageDialog, {
|
|
42
|
+
title: title,
|
|
43
|
+
message: message,
|
|
44
|
+
actions: actions
|
|
45
|
+
}));
|
|
46
|
+
expect(wrapper).toMatchSnapshot();
|
|
47
|
+
expect(wrapper.html()).toMatch(actions[0].label);
|
|
48
|
+
});
|
|
49
|
+
it('should pass title through', () => {
|
|
50
|
+
const customTitle = /*#__PURE__*/React.createElement("div", null, "Title");
|
|
51
|
+
const wrapper = shallow(/*#__PURE__*/React.createElement(TextMessageDialog, {
|
|
52
|
+
title: customTitle,
|
|
53
|
+
message: message,
|
|
54
|
+
params: {},
|
|
55
|
+
actions: []
|
|
56
|
+
}));
|
|
57
|
+
expect(wrapper.find('BasicDialog').prop('title')).toEqual(customTitle);
|
|
58
|
+
});
|
|
59
|
+
});
|
|
@@ -1,5 +1,14 @@
|
|
|
1
|
-
import{connect}from'react-redux';
|
|
1
|
+
import { connect } from 'react-redux';
|
|
2
|
+
import { historyPush } from '@shopgate/pwa-common/actions/router';
|
|
3
|
+
|
|
4
|
+
/**
|
|
2
5
|
* Connects the dispatch function to a callable function in the props.
|
|
3
6
|
* @param {Function} dispatch The redux dispatch function.
|
|
4
7
|
* @return {Object} The extended component props.
|
|
5
|
-
*/
|
|
8
|
+
*/
|
|
9
|
+
const mapDispatchToProps = dispatch => ({
|
|
10
|
+
navigate: pathname => dispatch(historyPush({
|
|
11
|
+
pathname
|
|
12
|
+
}))
|
|
13
|
+
});
|
|
14
|
+
export default connect(null, mapDispatchToProps);
|
|
@@ -1,14 +1,50 @@
|
|
|
1
|
-
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import PropTypes from 'prop-types';
|
|
3
|
+
import I18n from '@shopgate/pwa-common/components/I18n';
|
|
4
|
+
import { ITEM_PATH } from '@shopgate/pwa-common-commerce/product/constants';
|
|
5
|
+
import { bin2hex } from '@shopgate/pwa-common/helpers/data';
|
|
6
|
+
import BasicDialog from "../BasicDialog";
|
|
7
|
+
import connect from "./connector";
|
|
8
|
+
|
|
9
|
+
/**
|
|
2
10
|
* Reorders the actions for the modal so that the confirmation button will be rendered last.
|
|
3
11
|
* Also attaches a navigation action to the confirmation action.
|
|
4
12
|
* @param {Array} actions The confirm and dismiss actions.
|
|
5
13
|
* @param {string} productId The product id passed through params.
|
|
6
14
|
* @param {string} navigate The navigate action.
|
|
7
15
|
* @return {Array} Reordered and extended actions.
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
16
|
+
*/
|
|
17
|
+
const reorderActions = (actions, {
|
|
18
|
+
productId
|
|
19
|
+
}, navigate) => {
|
|
20
|
+
let confirmAction;
|
|
21
|
+
const orderedActions = actions;
|
|
22
|
+
orderedActions.forEach((act, index) => {
|
|
23
|
+
if (act.action.name !== 'onConfirm') {
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
confirmAction = {
|
|
27
|
+
...act,
|
|
28
|
+
action: () => {
|
|
29
|
+
// Execute default action
|
|
30
|
+
act.action();
|
|
31
|
+
// Navigate to product details page
|
|
32
|
+
if (productId) {
|
|
33
|
+
navigate(`${ITEM_PATH}/${bin2hex(productId)}`);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
orderedActions.splice(index, 1);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
// Push the confirm action last so that we have the button rendered at the bottom right of modal.
|
|
41
|
+
if (confirmAction) {
|
|
42
|
+
orderedActions.push(confirmAction);
|
|
43
|
+
}
|
|
44
|
+
return orderedActions;
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
/**
|
|
12
48
|
* Renders a simple dialog with a title and a text message.
|
|
13
49
|
* @param {Array} actions The modal button actions.
|
|
14
50
|
* @param {string} message The modal message.
|
|
@@ -16,4 +52,27 @@ if(confirmAction){orderedActions.push(confirmAction);}return orderedActions;};/*
|
|
|
16
52
|
* @param {Object} params The modal params.
|
|
17
53
|
* @return {JSX} The rendered component.
|
|
18
54
|
* @constructor
|
|
19
|
-
*/
|
|
55
|
+
*/
|
|
56
|
+
const VariantSelectModal = ({
|
|
57
|
+
actions,
|
|
58
|
+
message,
|
|
59
|
+
navigate,
|
|
60
|
+
title,
|
|
61
|
+
params
|
|
62
|
+
}) => {
|
|
63
|
+
const parsedActions = reorderActions(actions, params, navigate);
|
|
64
|
+
return /*#__PURE__*/React.createElement(BasicDialog, {
|
|
65
|
+
title: title,
|
|
66
|
+
actions: parsedActions
|
|
67
|
+
}, /*#__PURE__*/React.createElement(I18n.Text, {
|
|
68
|
+
string: message
|
|
69
|
+
}));
|
|
70
|
+
};
|
|
71
|
+
VariantSelectModal.defaultProps = {
|
|
72
|
+
params: {
|
|
73
|
+
productId: null
|
|
74
|
+
},
|
|
75
|
+
title: BasicDialog.defaultProps.title
|
|
76
|
+
};
|
|
77
|
+
export default connect(VariantSelectModal);
|
|
78
|
+
export { VariantSelectModal as UnwrappedVariantSelectModal };
|