@configuratorware/configurator-frontendgui 1.40.6 → 1.41.1

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.
Files changed (29) hide show
  1. package/App/Modules/Designer/Containers/ImageEditDialog.js +28 -10
  2. package/App/Reducers/DesignArea/Selectors.js +44 -11
  3. package/App/Reducers/DesignData/Modifiers.js +3 -1
  4. package/App/Reducers/ImageGallery/Actions.js +25 -18
  5. package/App/Reducers/ImageGallery/Reducer.js +5 -0
  6. package/App/Reducers/ImageGallery/Selectors.js +1 -1
  7. package/App/Screens/DesignerProductPreview/DesignerProductPreviewManager.js +10 -9
  8. package/App/Services/DesignDataService.js +494 -435
  9. package/App/Shared/Components/AmountPrice/index.js +175 -46
  10. package/App/Shared/Components/ConfigurationOverview/index.js +114 -0
  11. package/App/Shared/Containers/AmountPrice/index.js +2 -1
  12. package/App/configuration.js +1 -1
  13. package/package.json +4 -4
  14. package/public/translations/de_DE.json +1 -0
  15. package/src/App/Modules/Designer/Containers/ImageEditDialog.js +33 -6
  16. package/src/App/Reducers/DesignArea/Selectors.js +39 -9
  17. package/src/App/Reducers/DesignArea/__tests__/Selectors.test.js +19 -0
  18. package/src/App/Reducers/DesignData/Modifiers.js +3 -0
  19. package/src/App/Reducers/ImageGallery/Actions.js +20 -5
  20. package/src/App/Reducers/ImageGallery/Reducer.js +5 -0
  21. package/src/App/Reducers/ImageGallery/Selectors.js +4 -3
  22. package/src/App/Reducers/ImageGallery/__tests__/Actions.test.js +81 -7
  23. package/src/App/Screens/DesignerProductPreview/DesignerProductPreviewManager.js +4 -1
  24. package/src/App/Services/DesignDataService.js +56 -16
  25. package/src/App/Shared/Components/AmountPrice/__snapshots__/index.test.jsx.snap +133 -8
  26. package/src/App/Shared/Components/AmountPrice/index.js +109 -3
  27. package/src/App/Shared/Components/ConfigurationOverview/index.js +58 -0
  28. package/src/App/Shared/Containers/AmountPrice/index.js +2 -0
  29. package/src/App/configuration.js +1 -1
@@ -11,6 +11,31 @@ exports[`renders a boxed component with the boxed prop 1`] = `
11
11
  <div
12
12
  class="MuiCardContent-root AmountPrice-AmountPriceContent-6 AmountPrice-cardContentWrapper-5"
13
13
  >
14
+ <div
15
+ class="MuiGrid-root MuiGrid-container"
16
+ >
17
+ <div
18
+ class="MuiGrid-root AmountPrice-summary-17 MuiGrid-item MuiGrid-grid-xs-12 MuiGrid-grid-sm-12 MuiGrid-grid-md-12 MuiGrid-grid-lg-12"
19
+ >
20
+ <span
21
+ aria-hidden="true"
22
+ class="material-icons MuiIcon-root"
23
+ >
24
+ list_alt
25
+ </span>
26
+ <button
27
+ class="MuiButtonBase-root MuiButton-root MuiButton-text AmountPrice-configurationButton-16 MuiButton-textSizeSmall MuiButton-sizeSmall"
28
+ tabindex="0"
29
+ type="button"
30
+ >
31
+ <span
32
+ class="MuiButton-label"
33
+ >
34
+ amountPrice.configurationOverview
35
+ </span>
36
+ </button>
37
+ </div>
38
+ </div>
14
39
  <div
15
40
  class="MuiGrid-root MuiGrid-container"
16
41
  >
@@ -63,12 +88,12 @@ exports[`renders a boxed component with the boxed prop 1`] = `
63
88
  class="MuiGrid-root MuiGrid-item MuiGrid-grid-xs-12"
64
89
  >
65
90
  <button
66
- class="MuiButtonBase-root MuiButton-root MainButton-root-17 AmountPrice-mainButton-10 MuiButton-contained custom-css-cta-button MuiButton-fullWidth"
91
+ class="MuiButtonBase-root MuiButton-root MainButton-root-19 AmountPrice-mainButton-10 MuiButton-contained custom-css-cta-button MuiButton-fullWidth"
67
92
  tabindex="0"
68
93
  type="button"
69
94
  >
70
95
  <span
71
- class="MuiButton-label MainButton-label-18 AmountPrice-mainButtonLabel-11"
96
+ class="MuiButton-label MainButton-label-20 AmountPrice-mainButtonLabel-11"
72
97
  >
73
98
  amountPrice.intoCart
74
99
  </span>
@@ -92,6 +117,31 @@ exports[`renders correctly 1`] = `
92
117
  <div
93
118
  class="MuiCardContent-root AmountPrice-AmountPriceContent-6 AmountPrice-cardContentWrapper-5"
94
119
  >
120
+ <div
121
+ class="MuiGrid-root MuiGrid-container"
122
+ >
123
+ <div
124
+ class="MuiGrid-root AmountPrice-summary-17 MuiGrid-item MuiGrid-grid-xs-12 MuiGrid-grid-sm-12 MuiGrid-grid-md-12 MuiGrid-grid-lg-12"
125
+ >
126
+ <span
127
+ aria-hidden="true"
128
+ class="material-icons MuiIcon-root"
129
+ >
130
+ list_alt
131
+ </span>
132
+ <button
133
+ class="MuiButtonBase-root MuiButton-root MuiButton-text AmountPrice-configurationButton-16 MuiButton-textSizeSmall MuiButton-sizeSmall"
134
+ tabindex="0"
135
+ type="button"
136
+ >
137
+ <span
138
+ class="MuiButton-label"
139
+ >
140
+ amountPrice.configurationOverview
141
+ </span>
142
+ </button>
143
+ </div>
144
+ </div>
95
145
  <div
96
146
  class="MuiGrid-root MuiGrid-container"
97
147
  >
@@ -144,12 +194,12 @@ exports[`renders correctly 1`] = `
144
194
  class="MuiGrid-root MuiGrid-item MuiGrid-grid-xs-12"
145
195
  >
146
196
  <button
147
- class="MuiButtonBase-root MuiButton-root MainButton-root-17 AmountPrice-mainButton-10 MuiButton-contained custom-css-cta-button MuiButton-fullWidth"
197
+ class="MuiButtonBase-root MuiButton-root MainButton-root-19 AmountPrice-mainButton-10 MuiButton-contained custom-css-cta-button MuiButton-fullWidth"
148
198
  tabindex="0"
149
199
  type="button"
150
200
  >
151
201
  <span
152
- class="MuiButton-label MainButton-label-18 AmountPrice-mainButtonLabel-11"
202
+ class="MuiButton-label MainButton-label-20 AmountPrice-mainButtonLabel-11"
153
203
  >
154
204
  amountPrice.intoCart
155
205
  </span>
@@ -173,6 +223,31 @@ exports[`renders receiveOfferForm 1`] = `
173
223
  <div
174
224
  class="MuiCardContent-root AmountPrice-AmountPriceContent-6 AmountPrice-cardContentWrapper-5"
175
225
  >
226
+ <div
227
+ class="MuiGrid-root MuiGrid-container"
228
+ >
229
+ <div
230
+ class="MuiGrid-root AmountPrice-summary-17 MuiGrid-item MuiGrid-grid-xs-12 MuiGrid-grid-sm-12 MuiGrid-grid-md-12 MuiGrid-grid-lg-12"
231
+ >
232
+ <span
233
+ aria-hidden="true"
234
+ class="material-icons MuiIcon-root"
235
+ >
236
+ list_alt
237
+ </span>
238
+ <button
239
+ class="MuiButtonBase-root MuiButton-root MuiButton-text AmountPrice-configurationButton-16 MuiButton-textSizeSmall MuiButton-sizeSmall"
240
+ tabindex="0"
241
+ type="button"
242
+ >
243
+ <span
244
+ class="MuiButton-label"
245
+ >
246
+ amountPrice.configurationOverview
247
+ </span>
248
+ </button>
249
+ </div>
250
+ </div>
176
251
  <div
177
252
  class="MuiGrid-root MuiGrid-container"
178
253
  >
@@ -232,12 +307,12 @@ exports[`renders receiveOfferForm 1`] = `
232
307
  class="MuiGrid-root MuiGrid-item MuiGrid-grid-xs-6"
233
308
  >
234
309
  <button
235
- class="MuiButtonBase-root MuiButton-root MainButton-root-17 AmountPrice-mainButton-10 MuiButton-contained custom-css-cta-button MuiButton-fullWidth"
310
+ class="MuiButtonBase-root MuiButton-root MainButton-root-19 AmountPrice-mainButton-10 MuiButton-contained custom-css-cta-button MuiButton-fullWidth"
236
311
  tabindex="0"
237
312
  type="button"
238
313
  >
239
314
  <span
240
- class="MuiButton-label MainButton-label-18 AmountPrice-mainButtonLabel-11"
315
+ class="MuiButton-label MainButton-label-20 AmountPrice-mainButtonLabel-11"
241
316
  >
242
317
  receiveOfferForm.sendButton
243
318
  </span>
@@ -261,6 +336,31 @@ exports[`renders the ConfigurationModeSwitchComponent (if it is provided) 1`] =
261
336
  <div
262
337
  class="MuiCardContent-root AmountPrice-AmountPriceContent-6 AmountPrice-cardContentWrapper-5"
263
338
  >
339
+ <div
340
+ class="MuiGrid-root MuiGrid-container"
341
+ >
342
+ <div
343
+ class="MuiGrid-root AmountPrice-summary-17 MuiGrid-item MuiGrid-grid-xs-12 MuiGrid-grid-sm-12 MuiGrid-grid-md-12 MuiGrid-grid-lg-12"
344
+ >
345
+ <span
346
+ aria-hidden="true"
347
+ class="material-icons MuiIcon-root"
348
+ >
349
+ list_alt
350
+ </span>
351
+ <button
352
+ class="MuiButtonBase-root MuiButton-root MuiButton-text AmountPrice-configurationButton-16 MuiButton-textSizeSmall MuiButton-sizeSmall"
353
+ tabindex="0"
354
+ type="button"
355
+ >
356
+ <span
357
+ class="MuiButton-label"
358
+ >
359
+ amountPrice.configurationOverview
360
+ </span>
361
+ </button>
362
+ </div>
363
+ </div>
264
364
  <div
265
365
  class="MuiGrid-root MuiGrid-container"
266
366
  >
@@ -320,12 +420,12 @@ exports[`renders the ConfigurationModeSwitchComponent (if it is provided) 1`] =
320
420
  class="MuiGrid-root MuiGrid-item MuiGrid-grid-xs-6"
321
421
  >
322
422
  <button
323
- class="MuiButtonBase-root MuiButton-root MainButton-root-17 AmountPrice-mainButton-10 MuiButton-contained custom-css-cta-button MuiButton-fullWidth"
423
+ class="MuiButtonBase-root MuiButton-root MainButton-root-19 AmountPrice-mainButton-10 MuiButton-contained custom-css-cta-button MuiButton-fullWidth"
324
424
  tabindex="0"
325
425
  type="button"
326
426
  >
327
427
  <span
328
- class="MuiButton-label MainButton-label-18 AmountPrice-mainButtonLabel-11"
428
+ class="MuiButton-label MainButton-label-20 AmountPrice-mainButtonLabel-11"
329
429
  >
330
430
  amountPrice.intoCart
331
431
  </span>
@@ -349,6 +449,31 @@ exports[`renders without callToAction 1`] = `
349
449
  <div
350
450
  class="MuiCardContent-root AmountPrice-AmountPriceContent-6 AmountPrice-cardContentWrapper-5"
351
451
  >
452
+ <div
453
+ class="MuiGrid-root MuiGrid-container"
454
+ >
455
+ <div
456
+ class="MuiGrid-root AmountPrice-summary-17 MuiGrid-item MuiGrid-grid-xs-12 MuiGrid-grid-sm-12 MuiGrid-grid-md-12 MuiGrid-grid-lg-12"
457
+ >
458
+ <span
459
+ aria-hidden="true"
460
+ class="material-icons MuiIcon-root"
461
+ >
462
+ list_alt
463
+ </span>
464
+ <button
465
+ class="MuiButtonBase-root MuiButton-root MuiButton-text AmountPrice-configurationButton-16 MuiButton-textSizeSmall MuiButton-sizeSmall"
466
+ tabindex="0"
467
+ type="button"
468
+ >
469
+ <span
470
+ class="MuiButton-label"
471
+ >
472
+ amountPrice.configurationOverview
473
+ </span>
474
+ </button>
475
+ </div>
476
+ </div>
352
477
  <div
353
478
  class="MuiGrid-root MuiGrid-container"
354
479
  >
@@ -31,6 +31,8 @@ import AcceptDesign from '../AcceptDesign';
31
31
  import LoadingOverlay from '../../../../Framework/Components/LoadingOverlay';
32
32
  import { debounce } from '@material-ui/core';
33
33
  import AcceptPrivacy from '../AcceptPrivacy';
34
+ import ConfigurationOverview from '../ConfigurationOverview';
35
+ import { isMobileDevice } from 'Framework/Helpers/isMobileDevice';
34
36
  const styles = theme => ({
35
37
  contentPositioning: {
36
38
  paddingLeft: 32,
@@ -209,6 +211,22 @@ const styles = theme => ({
209
211
  cursor: 'pointer',
210
212
  },
211
213
  },
214
+ configurationButton: {
215
+ '&:hover': {
216
+ cursor: 'pointer',
217
+ },
218
+ fontWeight: 'bold',
219
+ textTransform: 'none',
220
+ padding: '6px 15px',
221
+ marginRight: '5px',
222
+ },
223
+ summary: {
224
+ display: 'flex',
225
+ alignItems: 'center',
226
+ '& svg': {
227
+ marginRight: 5,
228
+ },
229
+ },
212
230
  dialogTitleRoot: {
213
231
  padding: '20px 0',
214
232
  },
@@ -277,12 +295,14 @@ class AmountPrice extends React.Component {
277
295
  ReceiveOfferFormComponent: PropTypes.elementType,
278
296
  AcceptDesignComponent: PropTypes.elementType,
279
297
  PriceOverviewComponent: PropTypes.elementType,
298
+ ConfigurationOverviewComponent: PropTypes.elementType,
280
299
  NotificationComponent: PropTypes.elementType,
281
300
  PriceListComponent: PropTypes.elementType,
282
301
  AddToCartComponent: PropTypes.elementType,
283
302
  renderPriceBox: PropTypes.func,
284
303
  userComment: PropTypes.string,
285
304
  AcceptPrivacyComponent: PropTypes.elementType,
305
+ userConfiguration: PropTypes.object,
286
306
  };
287
307
 
288
308
  static defaultProps = {
@@ -296,6 +316,7 @@ class AmountPrice extends React.Component {
296
316
  ReceiveOfferFormComponent: ReceiveOfferForm,
297
317
  AcceptDesignComponent: AcceptDesign,
298
318
  PriceOverviewComponent: PriceOverview,
319
+ ConfigurationOverviewComponent: ConfigurationOverview,
299
320
  NotificationComponent: Notification,
300
321
  PriceListComponent: PriceList,
301
322
  AddToCartComponent: AddToCart,
@@ -304,6 +325,7 @@ class AmountPrice extends React.Component {
304
325
 
305
326
  state = {
306
327
  showPriceOverview: false,
328
+ showConfigurationOverview: false,
307
329
  notice: '',
308
330
  hasErrorReceiveOfferForm: false,
309
331
  bulkNameErrors: [],
@@ -332,6 +354,13 @@ class AmountPrice extends React.Component {
332
354
  const { onShowChange } = this.props;
333
355
  onShowChange && onShowChange(showPriceOverview);
334
356
  }
357
+
358
+ const { showConfigurationOverview } = this.state;
359
+ if (showConfigurationOverview !== prevState.showConfigurationOverview) {
360
+ const { onShowChange } = this.props;
361
+ onShowChange && onShowChange(showConfigurationOverview);
362
+ }
363
+
335
364
  if (this.state.notice === prevState.notice && this.props.userComment !== this.state.notice) {
336
365
  this.setState({ notice: this.props.userComment });
337
366
  }
@@ -432,8 +461,22 @@ class AmountPrice extends React.Component {
432
461
  }
433
462
  };
434
463
 
464
+ openConfigurationOverview = async () => {
465
+ try {
466
+ await this.props.validateConfiguration();
467
+ this.setState({
468
+ showConfigurationOverview: true,
469
+ hasErrorReceiveOfferForm: false,
470
+ });
471
+ } catch (e) {
472
+ // eslint-disable-next-line no-console
473
+ console.warn(`Error while validating configuration: ${e}`);
474
+ }
475
+ };
476
+
435
477
  handleClose = () => {
436
478
  this.setState({
479
+ showConfigurationOverview: false,
437
480
  showPriceOverview: false,
438
481
  bulkNameErrors: [],
439
482
  approval: {
@@ -490,6 +533,47 @@ class AmountPrice extends React.Component {
490
533
  this.setState({ inView: inView });
491
534
  };
492
535
 
536
+ renderConfigurationOverview() {
537
+ const { showConfigurationOverview } = this.state;
538
+
539
+ const { ConfigurationOverviewComponent, userConfiguration, width, classes } = this.props;
540
+
541
+ return (
542
+ <Dialog
543
+ aria-labelledby="alert-dialog-title"
544
+ aria-describedby="alert-dialog-description"
545
+ classes={{
546
+ paper: classes.dialogWrapper,
547
+ container: width === 'md' || width === 'xs' ? classes.dialogPositioning : '',
548
+ root: classes.dialogPositioning,
549
+ }}
550
+ BackdropProps={{ className: classes.dialogPositioning }}
551
+ onClose={this.handleClose.bind(this)}
552
+ open={showConfigurationOverview}
553
+ fullWidth
554
+ fullScreen={width === 'sm' || width === 'xs'}
555
+ scroll="paper"
556
+ >
557
+ <LoadingOverlay show={this.props.addToCartPopUpLoader} />
558
+ <DialogTitle classes={{ root: classes.dialogTitleRoot }}>
559
+ <Typography variant="body1">
560
+ <b>{t('amountPrice.configurationOverview')}</b>
561
+ </Typography>
562
+ <Icon className={classes.closeIcon} onClick={this.handleClose.bind(this)}>
563
+ close
564
+ </Icon>
565
+ </DialogTitle>
566
+ <RootRef rootRef={this.dialogContentRef}>
567
+ <DialogContent classes={{ root: classes.contentPositioning }}>
568
+ <ConfigurationOverviewComponent
569
+ optionclassifications={userConfiguration.optionclassifications}
570
+ />
571
+ </DialogContent>
572
+ </RootRef>
573
+ </Dialog>
574
+ );
575
+ }
576
+
493
577
  renderPriceOverview() {
494
578
  const {
495
579
  notice,
@@ -684,6 +768,7 @@ class AmountPrice extends React.Component {
684
768
  ConfigurationModeSwitchComponent,
685
769
  } = this.props;
686
770
 
771
+ const isMobile = isMobileDevice();
687
772
  const boxStyle = boxed ? classes.card : classes.cardUnboxed;
688
773
  return (
689
774
  <Card className={clsx(boxStyle, customClassName('cta-box'))}>
@@ -692,6 +777,21 @@ class AmountPrice extends React.Component {
692
777
  className={classes.cardContentWrapper}
693
778
  classes={{ root: classes.AmountPriceContent }}
694
779
  >
780
+ {!isMobile && (
781
+ <Grid container>
782
+ <Grid item xs={12} sm={12} md={12} lg={12} className={classes.summary}>
783
+ <Icon>list_alt</Icon>
784
+ <Button
785
+ className={classes.configurationButton}
786
+ variant="text"
787
+ size="small"
788
+ onClick={this.openConfigurationOverview}
789
+ >
790
+ {t('amountPrice.configurationOverview')}
791
+ </Button>
792
+ </Grid>
793
+ </Grid>
794
+ )}
695
795
  <Grid container>
696
796
  {!hidePieces && (
697
797
  <Grid item xs={12} sm={6} md={5} lg={5}>
@@ -781,15 +881,21 @@ class AmountPrice extends React.Component {
781
881
  render() {
782
882
  const { wrapperClass, renderPriceBox, ...props } = this.props;
783
883
 
784
- const { showPriceOverview } = this.state;
785
- const { openPriceOverview, renderDefaultPriceBox } = this;
884
+ const { showPriceOverview, showConfigurationOverview } = this.state;
885
+ const { openPriceOverview, openConfigurationOverview, renderDefaultPriceBox } = this;
786
886
 
787
887
  return (
788
888
  <div className={wrapperClass}>
789
889
  {renderPriceBox
790
- ? renderPriceBox({ ...props, openPriceOverview, renderDefaultPriceBox })
890
+ ? renderPriceBox({
891
+ ...props,
892
+ openPriceOverview,
893
+ openConfigurationOverview,
894
+ renderDefaultPriceBox,
895
+ })
791
896
  : this.renderDefaultPriceBox()}
792
897
  {showPriceOverview && this.renderPriceOverview()}
898
+ {showConfigurationOverview && this.renderConfigurationOverview()}
793
899
  </div>
794
900
  );
795
901
  }
@@ -0,0 +1,58 @@
1
+ import React from 'react';
2
+ import { withStyles } from '@material-ui/core/styles';
3
+ import Grid from '@material-ui/core/Grid/Grid';
4
+ import Typography from '@material-ui/core/Typography';
5
+ import PropTypes from 'prop-types';
6
+
7
+ const styles = () => ({
8
+ li: {
9
+ listStyle: 'none',
10
+ },
11
+ gridWrapper: {
12
+ padding: '10px 0 25px 0',
13
+ },
14
+ title: {
15
+ fontWeight: 'bold',
16
+ },
17
+ });
18
+
19
+ class ConfigurationOverview extends React.Component {
20
+ static propTypes = {
21
+ optionclassifications: PropTypes.array,
22
+ classes: PropTypes.object,
23
+ };
24
+ render() {
25
+ const { optionclassifications, classes } = this.props;
26
+
27
+ return (
28
+ <div className={classes.gridWrapper}>
29
+ <Grid container spacing={2}>
30
+ {optionclassifications?.map(optionclassification => (
31
+ <>
32
+ <Grid item xs={6} key={optionclassification.identifier}>
33
+ <Typography className={classes.title}>
34
+ {optionclassification.title}
35
+ </Typography>
36
+ </Grid>
37
+ <Grid item xs={6}>
38
+ {optionclassification.selectedoptions?.map(option => (
39
+ <li key={option.identifier} className={classes.li}>
40
+ {option.amount !== 1 ? (
41
+ <Typography>
42
+ {option.amount} x {option.title}
43
+ </Typography>
44
+ ) : (
45
+ <Typography>{option.title}</Typography>
46
+ )}
47
+ </li>
48
+ ))}
49
+ </Grid>
50
+ </>
51
+ ))}
52
+ </Grid>
53
+ </div>
54
+ );
55
+ }
56
+ }
57
+
58
+ export default withStyles(styles, { name: 'ConfigurationOverview' })(ConfigurationOverview);
@@ -18,6 +18,7 @@ import {
18
18
  getClientTexts,
19
19
  showCallToAction,
20
20
  showReceiveOfferForm,
21
+ getConfiguration,
21
22
  } from '../../../Reducers/Configurator/Selectors';
22
23
  import { getVisibilityMapProperty } from '../../../Reducers/UI/Selectors';
23
24
  import { getConf } from '../../../configuration';
@@ -196,6 +197,7 @@ const mapStateToProps = ({ configurator, configurationMode, ui }) => {
196
197
  clientTexts: getClientTexts(configurator),
197
198
  addToCartPopUpLoader: getVisibilityMapProperty(ui, 'addToCartPopUpLoader'),
198
199
  userComment: get(configurator, 'configuration.customdata.comment', ''),
200
+ userConfiguration: getConfiguration(configurator),
199
201
  };
200
202
  };
201
203
 
@@ -13,7 +13,7 @@ const DEVELOPMENT_HOST_LOCAL = 'http://localhost:10030';
13
13
 
14
14
  const hostsByNodeEnv = {
15
15
  production: '',
16
- development: DEVELOPMENT_HOST_INT,
16
+ development: DEVELOPMENT_HOST_LOCAL,
17
17
  test: '',
18
18
  };
19
19