@shopgate/pwa-ui-shared 7.30.0-alpha.6 → 7.30.0-alpha.8
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 +59 -2
- package/ActionButton/style.js +22 -1
- package/AddToCartButton/index.js +184 -27
- package/AddToCartButton/mock.js +18 -4
- package/AddToCartButton/spec.js +51 -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 +300 -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 +41 -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/FavoritesButton/spec.js
CHANGED
|
@@ -1,6 +1,124 @@
|
|
|
1
|
-
import React from'react';
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Provider } from 'react-redux';
|
|
3
|
+
import configureStore from 'redux-mock-store';
|
|
4
|
+
import { mount } from 'enzyme';
|
|
5
|
+
import mockRenderOptions from '@shopgate/pwa-common/helpers/mocks/mockRenderOptions';
|
|
6
|
+
import appConfig from '@shopgate/pwa-common/helpers/config';
|
|
7
|
+
import FavoritesButton from "./index";
|
|
8
|
+
import { mockedStateEmpty, mockedStateOnList, mockedStateNotOnList } from "./mock";
|
|
9
|
+
const mockedStore = configureStore();
|
|
10
|
+
const dispatcher = jest.fn();
|
|
11
|
+
jest.mock('@shopgate/pwa-common/helpers/config');
|
|
12
|
+
jest.mock('@shopgate/pwa-common-commerce/favorites/selectors/index', () => ({
|
|
13
|
+
isFetching: () => false
|
|
14
|
+
}));
|
|
15
|
+
beforeEach(() => {
|
|
16
|
+
jest.resetModules();
|
|
17
|
+
});
|
|
18
|
+
describe('<FavoritesButton />', () => {
|
|
19
|
+
let component = null;
|
|
20
|
+
|
|
21
|
+
/**
|
|
2
22
|
* Creates component with provided store state.
|
|
3
23
|
* @param {Object} mockedState Mocked stage.
|
|
4
24
|
* @param {Object} props Additional props.
|
|
5
25
|
* @return {ReactWrapper}
|
|
6
|
-
*/
|
|
26
|
+
*/
|
|
27
|
+
const createComponent = (mockedState, props = {
|
|
28
|
+
active: false
|
|
29
|
+
}) => {
|
|
30
|
+
const store = mockedStore(mockedState);
|
|
31
|
+
store.dispatch = dispatcher;
|
|
32
|
+
return mount(/*#__PURE__*/React.createElement(Provider, {
|
|
33
|
+
store: store
|
|
34
|
+
}, /*#__PURE__*/React.createElement(FavoritesButton, props)), mockRenderOptions);
|
|
35
|
+
};
|
|
36
|
+
beforeEach(() => {
|
|
37
|
+
dispatcher.mockReset();
|
|
38
|
+
});
|
|
39
|
+
it('should only render when no favorites set', () => {
|
|
40
|
+
component = createComponent(mockedStateEmpty);
|
|
41
|
+
expect(component).toMatchSnapshot();
|
|
42
|
+
expect(component.find('Heart').exists()).toBe(false);
|
|
43
|
+
expect(component.find('HeartOutline').exists()).toBe(true);
|
|
44
|
+
component.find('button').simulate('click');
|
|
45
|
+
});
|
|
46
|
+
it('should render when favorites set', () => {
|
|
47
|
+
component = createComponent(mockedStateOnList, {
|
|
48
|
+
active: true
|
|
49
|
+
});
|
|
50
|
+
expect(component).toMatchSnapshot();
|
|
51
|
+
expect(component.find('Heart').exists()).toBe(true);
|
|
52
|
+
expect(component.find('HeartOutline').exists()).toBe(false);
|
|
53
|
+
});
|
|
54
|
+
it('should add to favorites on click', () => {
|
|
55
|
+
component = createComponent(mockedStateNotOnList, {
|
|
56
|
+
productId: '1',
|
|
57
|
+
active: false
|
|
58
|
+
});
|
|
59
|
+
expect(component.find('Heart').exists()).toBe(false);
|
|
60
|
+
expect(component.find('HeartOutline').exists()).toBe(true);
|
|
61
|
+
component.find('button').simulate('click');
|
|
62
|
+
component.update();
|
|
63
|
+
expect(dispatcher).toHaveBeenCalled();
|
|
64
|
+
});
|
|
65
|
+
it('should remove from favorites on click', done => {
|
|
66
|
+
component = createComponent(mockedStateOnList, {
|
|
67
|
+
productId: '1',
|
|
68
|
+
active: true
|
|
69
|
+
});
|
|
70
|
+
expect(component.find('Heart').exists()).toBe(true);
|
|
71
|
+
expect(component.find('HeartOutline').exists()).toBe(false);
|
|
72
|
+
component.find('button').simulate('click');
|
|
73
|
+
component.update();
|
|
74
|
+
setTimeout(() => {
|
|
75
|
+
expect(dispatcher).toHaveBeenCalled();
|
|
76
|
+
done();
|
|
77
|
+
}, 0);
|
|
78
|
+
});
|
|
79
|
+
it('should process ripple complete callback', () => {
|
|
80
|
+
const onRippleComplete = jest.fn();
|
|
81
|
+
component = createComponent(mockedStateOnList, {
|
|
82
|
+
productId: '1',
|
|
83
|
+
active: true,
|
|
84
|
+
onRippleComplete
|
|
85
|
+
});
|
|
86
|
+
component.find('Ripple').instance().props.onComplete();
|
|
87
|
+
component.update();
|
|
88
|
+
expect(onRippleComplete).toHaveBeenCalled();
|
|
89
|
+
});
|
|
90
|
+
it('should only react on first click', done => {
|
|
91
|
+
component = createComponent(mockedStateOnList, {
|
|
92
|
+
once: true,
|
|
93
|
+
productId: '1',
|
|
94
|
+
active: false
|
|
95
|
+
});
|
|
96
|
+
component.find('button').simulate('click');
|
|
97
|
+
component.update();
|
|
98
|
+
component.find('button').simulate('click');
|
|
99
|
+
component.update();
|
|
100
|
+
setTimeout(() => {
|
|
101
|
+
expect(dispatcher.mock.calls.length).toBe(1);
|
|
102
|
+
done();
|
|
103
|
+
}, 1);
|
|
104
|
+
});
|
|
105
|
+
it('should only react on both clicks', done => {
|
|
106
|
+
component = createComponent(mockedStateOnList, {
|
|
107
|
+
productId: '1',
|
|
108
|
+
active: false
|
|
109
|
+
});
|
|
110
|
+
component.find('button').simulate('click');
|
|
111
|
+
component.update();
|
|
112
|
+
component.find('button').simulate('click');
|
|
113
|
+
component.update();
|
|
114
|
+
setTimeout(() => {
|
|
115
|
+
expect(dispatcher.mock.calls.length).toBe(2);
|
|
116
|
+
done();
|
|
117
|
+
}, 1);
|
|
118
|
+
});
|
|
119
|
+
it('should render null when feature flag is off', () => {
|
|
120
|
+
jest.spyOn(appConfig, 'hasFavorites', 'get').mockReturnValue(false);
|
|
121
|
+
component = createComponent(mockedStateOnList);
|
|
122
|
+
expect(component.isEmptyRender()).toBe(true);
|
|
123
|
+
});
|
|
124
|
+
});
|
package/FavoritesButton/style.js
CHANGED
|
@@ -1 +1,26 @@
|
|
|
1
|
-
|
|
1
|
+
import { css } from 'glamor';
|
|
2
|
+
import { themeShadows, themeColors } from '@shopgate/pwa-common/helpers/config';
|
|
3
|
+
const buttonProto = {
|
|
4
|
+
display: 'block',
|
|
5
|
+
position: 'relative',
|
|
6
|
+
background: themeColors.light,
|
|
7
|
+
borderRadius: '50%',
|
|
8
|
+
padding: 0,
|
|
9
|
+
fontSize: 20,
|
|
10
|
+
lineHeight: 1,
|
|
11
|
+
color: `var(--color-secondary, ${themeColors.accent})`,
|
|
12
|
+
outline: 0
|
|
13
|
+
};
|
|
14
|
+
const buttonFlat = css(buttonProto).toString();
|
|
15
|
+
const button = css({
|
|
16
|
+
...buttonProto,
|
|
17
|
+
boxShadow: themeShadows.buttons.elevated
|
|
18
|
+
}).toString();
|
|
19
|
+
const ripple = css({
|
|
20
|
+
padding: 6
|
|
21
|
+
}).toString();
|
|
22
|
+
export default {
|
|
23
|
+
buttonFlat,
|
|
24
|
+
button,
|
|
25
|
+
ripple
|
|
26
|
+
};
|
|
@@ -1,10 +1,44 @@
|
|
|
1
|
-
|
|
1
|
+
import "core-js/modules/es.array.reduce.js";
|
|
2
|
+
import { logger } from '@shopgate/pwa-core/helpers';
|
|
3
|
+
import iso3166 from "../iso-3166-2";
|
|
4
|
+
|
|
5
|
+
/**
|
|
2
6
|
* Get country list for
|
|
3
7
|
* @param {Object} countryElement Configuration of which form fields to render
|
|
4
8
|
* @param {?Object} optional object to prepend optional choice
|
|
5
9
|
* @return {Object}
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
//
|
|
9
|
-
|
|
10
|
-
|
|
10
|
+
*/
|
|
11
|
+
export default (countryElement, optional = null) => {
|
|
12
|
+
// Check validity of the country element options list "countries"
|
|
13
|
+
if (countryElement.countries !== null && countryElement.countries !== undefined && !Array.isArray(countryElement.countries)) {
|
|
14
|
+
logger.error("Error: Invalid property type 'countries' in element " + `'${countryElement.id}'. Must be 'array', 'null' or 'undefined'`);
|
|
15
|
+
return {};
|
|
16
|
+
}
|
|
17
|
+
// Build country display list for the country element (whitelist)
|
|
18
|
+
// For 'null', 'undefined' and '[]' it shows all countries
|
|
19
|
+
let countryKeys;
|
|
20
|
+
if (countryElement.countries.length > 0) {
|
|
21
|
+
countryKeys = countryElement.countries;
|
|
22
|
+
} else {
|
|
23
|
+
countryKeys = Object.keys(iso3166);
|
|
24
|
+
}
|
|
25
|
+
const countryList = countryKeys.reduce((reducer, countryCode) => {
|
|
26
|
+
if (!iso3166[countryCode]) {
|
|
27
|
+
logger.error(`Error: unknown country code [${countryCode}]`);
|
|
28
|
+
return reducer;
|
|
29
|
+
}
|
|
30
|
+
return {
|
|
31
|
+
...reducer,
|
|
32
|
+
[countryCode]: iso3166[countryCode].name
|
|
33
|
+
};
|
|
34
|
+
}, {});
|
|
35
|
+
|
|
36
|
+
// Add a "no selection" element
|
|
37
|
+
if (countryElement.required) {
|
|
38
|
+
return countryList;
|
|
39
|
+
}
|
|
40
|
+
return {
|
|
41
|
+
...optional,
|
|
42
|
+
...countryList
|
|
43
|
+
};
|
|
44
|
+
};
|
|
@@ -1,10 +1,39 @@
|
|
|
1
|
-
|
|
1
|
+
import { ELEMENT_TYPE_CHECKBOX, ELEMENT_TYPE_SELECT } from "../elementTypes";
|
|
2
|
+
|
|
3
|
+
/**
|
|
2
4
|
* Prepare state of formData for form builder
|
|
3
5
|
* @param {Object} formElements form elements
|
|
4
6
|
* @param {Object} defaults form defaults
|
|
5
7
|
* @returns {Object}
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
*/
|
|
9
|
+
export default (formElements = [], defaults = {}) => {
|
|
10
|
+
const formDefaults = {};
|
|
11
|
+
|
|
12
|
+
// Take only those defaults from props, that are actually represented by an element
|
|
13
|
+
formElements.forEach(element => {
|
|
14
|
+
let defaultState = element.type === ELEMENT_TYPE_CHECKBOX ? false : '';
|
|
15
|
+
if (element.type === ELEMENT_TYPE_SELECT && !element.default) {
|
|
16
|
+
[defaultState] = Object.keys(element.options);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// Use default from element config as a base
|
|
20
|
+
if (element.default !== undefined && element.default !== null) {
|
|
21
|
+
defaultState = element.default;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// Take defaults from "customAttributes" property or from the higher level, based on element
|
|
25
|
+
if (element.custom && defaults.customAttributes !== undefined) {
|
|
26
|
+
if (defaults.customAttributes[element.id] !== undefined) {
|
|
27
|
+
defaultState = defaults.customAttributes[element.id];
|
|
28
|
+
}
|
|
29
|
+
} else if (!element.custom && defaults[element.id] !== undefined) {
|
|
30
|
+
defaultState = defaults[element.id];
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Save default into the form state and into defaults property if one was set
|
|
34
|
+
if (defaultState !== undefined) {
|
|
35
|
+
formDefaults[element.id] = defaultState;
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
return formDefaults;
|
|
39
|
+
};
|
|
@@ -1,4 +1,10 @@
|
|
|
1
|
-
|
|
1
|
+
import { logger } from '@shopgate/pwa-core/helpers';
|
|
2
|
+
import { ELEMENT_TYPE_COUNTRY, ELEMENT_TYPE_PROVINCE } from "../elementTypes";
|
|
3
|
+
|
|
4
|
+
/** Noop function */
|
|
5
|
+
const noop = () => {};
|
|
6
|
+
|
|
7
|
+
/**
|
|
2
8
|
* @typedef {Object} FormElement
|
|
3
9
|
* @property {string} id
|
|
4
10
|
* @property {boolean} custom
|
|
@@ -11,21 +17,73 @@ var _excluded=["custom"];function _objectWithoutProperties(source,excluded){if(s
|
|
|
11
17
|
* @property {boolean|null|undefined} required
|
|
12
18
|
* @property {boolean|null|undefined} visible
|
|
13
19
|
* @property {FormFieldAction[]|null|undefined} actions
|
|
14
|
-
*/
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
/**
|
|
15
23
|
* Takes a list of which elements to render based on the respective element type
|
|
16
24
|
*
|
|
17
25
|
* @param {Form} formConfig Configuration of which form fields to render
|
|
18
26
|
* @param {Function} elementChangeHandler change handler
|
|
19
27
|
* @return {FormElement[]}
|
|
20
|
-
*/
|
|
28
|
+
*/
|
|
29
|
+
export default (formConfig, elementChangeHandler = noop) => {
|
|
30
|
+
/**
|
|
21
31
|
* @type {FormElement[]}
|
|
22
|
-
*/
|
|
32
|
+
*/
|
|
33
|
+
const elementList = [];
|
|
34
|
+
let hasCountryElement = false;
|
|
35
|
+
let hasProvinceElement = false;
|
|
36
|
+
|
|
37
|
+
/**
|
|
23
38
|
* @param {string} id id
|
|
24
39
|
* @param {AnyFormField} field field
|
|
25
40
|
* @param {boolean} custom custom
|
|
26
|
-
*/
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
41
|
+
*/
|
|
42
|
+
const addFormElement = (id, field, custom = false) => {
|
|
43
|
+
// The "custom" field is just a placeholder for more fields
|
|
44
|
+
if (typeof field.type !== 'string') {
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Make sure country and province elements are only added once
|
|
49
|
+
if (field.type === ELEMENT_TYPE_COUNTRY) {
|
|
50
|
+
if (hasCountryElement) {
|
|
51
|
+
logger.error(`Error: Can not add multiple elements of type '${field.type}'`);
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
hasCountryElement = true;
|
|
55
|
+
}
|
|
56
|
+
if (field.type === ELEMENT_TYPE_PROVINCE) {
|
|
57
|
+
if (hasProvinceElement) {
|
|
58
|
+
logger.error(`Error: Can not add multiple elements of type '${field.type}'`);
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
hasProvinceElement = true;
|
|
62
|
+
}
|
|
63
|
+
elementList.push({
|
|
64
|
+
id,
|
|
65
|
+
...field,
|
|
66
|
+
custom,
|
|
67
|
+
handleChange: value => elementChangeHandler(id, value)
|
|
68
|
+
});
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
// Extract custom fields, do not mix with normal fields
|
|
72
|
+
const {
|
|
73
|
+
custom,
|
|
74
|
+
...restFields
|
|
75
|
+
} = formConfig.fields;
|
|
76
|
+
|
|
77
|
+
// Add all non-custom attributes and mark them as such
|
|
78
|
+
Object.keys(restFields).forEach(id => {
|
|
79
|
+
addFormElement(id, formConfig.fields[id]);
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
// Add custom fields to the element list
|
|
83
|
+
if (custom) {
|
|
84
|
+
Object.keys(custom).forEach(id => {
|
|
85
|
+
addFormElement(id, formConfig.fields.custom[id], true);
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
return elementList;
|
|
89
|
+
};
|
|
@@ -1,7 +1,24 @@
|
|
|
1
|
-
|
|
1
|
+
import iso3166 from "../iso-3166-2";
|
|
2
|
+
|
|
3
|
+
/**
|
|
2
4
|
* Returns a list of provinces based on the given country id
|
|
3
5
|
*
|
|
4
6
|
* @param {string} countryCode Country code of the country to fetch provinces from
|
|
5
7
|
* @param {?Object} optional object to prepend optional choice
|
|
6
8
|
* @return {Object}
|
|
7
|
-
*/
|
|
9
|
+
*/
|
|
10
|
+
export default (countryCode, optional = null) => {
|
|
11
|
+
if (!iso3166) {
|
|
12
|
+
return {};
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/** @property {iso3166} divisions */
|
|
16
|
+
const provinceList = iso3166[countryCode] ? iso3166[countryCode].divisions : {};
|
|
17
|
+
if (!optional) {
|
|
18
|
+
return provinceList;
|
|
19
|
+
}
|
|
20
|
+
return {
|
|
21
|
+
...optional,
|
|
22
|
+
...provinceList
|
|
23
|
+
};
|
|
24
|
+
};
|
|
@@ -1,5 +1,10 @@
|
|
|
1
|
-
|
|
1
|
+
import "core-js/modules/es.array.reduce.js";
|
|
2
|
+
/**
|
|
2
3
|
* Builds an Object, that contains all validation errors given as array of objects
|
|
3
4
|
* @param {{path: string, message: string}[]} validationErrors Associated object containing errors
|
|
4
5
|
* @return {Object}
|
|
5
|
-
*/
|
|
6
|
+
*/
|
|
7
|
+
export default validationErrors => validationErrors.reduce((result, validationError) => ({
|
|
8
|
+
...result,
|
|
9
|
+
[validationError.path]: validationError.message
|
|
10
|
+
}), {});
|
|
@@ -1,2 +1,22 @@
|
|
|
1
|
-
|
|
2
|
-
export
|
|
1
|
+
export const ACTION_TYPE_UPDATE_PROVINCE_ELEMENT = 'updateProvinceElement';
|
|
2
|
+
export const ACTION_TYPE_SET_VISIBILITY = 'setVisibility';
|
|
3
|
+
export const ACTION_TYPE_SET_VALUE = 'setValue';
|
|
4
|
+
export const ACTION_TYPE_TRANSFORM = 'transform';
|
|
5
|
+
export const ACTION_SET_VALUE_FIXED = 'fixed';
|
|
6
|
+
export const ACTION_SET_VALUE_COPY_FROM = 'copyFrom';
|
|
7
|
+
export const ACTION_SET_VALUE_LENGTH_OF = 'lengthOf';
|
|
8
|
+
export const ACTION_RULE_TYPE_NOT_IN = 'notIn';
|
|
9
|
+
export const ACTION_RULE_TYPE_ONE_OF = 'oneOf';
|
|
10
|
+
export const ACTION_RULE_TYPE_BOOLEAN = 'boolean';
|
|
11
|
+
export const ACTION_RULE_TYPE_REGEX = 'regex';
|
|
12
|
+
|
|
13
|
+
// Rule data is formatted as array
|
|
14
|
+
export const ACTION_RULE_DATA_TYPES = {
|
|
15
|
+
[ACTION_RULE_TYPE_NOT_IN]: 'array',
|
|
16
|
+
[ACTION_RULE_TYPE_ONE_OF]: 'array',
|
|
17
|
+
[ACTION_RULE_TYPE_BOOLEAN]: 'boolean',
|
|
18
|
+
[ACTION_RULE_TYPE_REGEX]: 'string'
|
|
19
|
+
};
|
|
20
|
+
export const ACTION_RULES_CONCAT_METHOD_ALL = 'all';
|
|
21
|
+
export const ACTION_RULES_CONCAT_METHOD_ANY = 'any';
|
|
22
|
+
export const ACTION_RULES_CONCAT_METHOD_NONE = 'none';
|