@configuratorware/configurator-frontendgui 1.50.4 → 1.51.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 (27) hide show
  1. package/App/Modules/Creator/Components/Option/index.js +3 -0
  2. package/App/Modules/Creator/Components/Optiondetail/index.js +6 -2
  3. package/App/Modules/Creator/Components/ProductPart/index.js +5 -1
  4. package/App/Modules/Designer/Components/ImageEditDialog/index.js +1 -2
  5. package/App/Modules/Designer/Containers/AddGalleryImage.js +1 -1
  6. package/App/Modules/Designer/Containers/ImageEditDialog.js +21 -26
  7. package/App/Reducers/ImageGallery/Selectors.js +1 -1
  8. package/App/Screens/DesignerProductPreview/DesignerProductPreviewManager.js +1 -1
  9. package/App/Services/DesignDataService.js +8 -4
  10. package/App/Services/DesignerService.js +3 -2
  11. package/App/Shared/Components/ConfigurationOverview/index.js +9 -4
  12. package/package.json +4 -4
  13. package/public/translations/de_DE.json +6 -0
  14. package/public/translations/en_GB.json +6 -0
  15. package/src/App/Modules/Creator/Components/Option/__snapshots__/index.test.js.snap +2 -0
  16. package/src/App/Modules/Creator/Components/Option/index.js +9 -1
  17. package/src/App/Modules/Creator/Components/Optiondetail/index.js +14 -2
  18. package/src/App/Modules/Creator/Components/ProductPart/__snapshots__/index.test.js.snap +8 -0
  19. package/src/App/Modules/Creator/Components/ProductPart/index.js +3 -0
  20. package/src/App/Modules/Designer/Components/ImageEditDialog/index.js +10 -14
  21. package/src/App/Modules/Designer/Containers/AddGalleryImage.js +1 -1
  22. package/src/App/Modules/Designer/Containers/ImageEditDialog.js +11 -9
  23. package/src/App/Reducers/ImageGallery/Selectors.js +1 -1
  24. package/src/App/Screens/DesignerProductPreview/DesignerProductPreviewManager.js +5 -1
  25. package/src/App/Services/DesignDataService.js +12 -6
  26. package/src/App/Services/DesignerService.js +4 -2
  27. package/src/App/Shared/Components/ConfigurationOverview/index.js +23 -4
@@ -288,6 +288,9 @@ var Option = function Option(_ref) {
288
288
  var src = (0, _getImageUrl["default"])(thumbnail);
289
289
  return src && /*#__PURE__*/_react["default"].createElement("img", {
290
290
  src: src,
291
+ alt: (0, _i18n.t)('ariaLabels.optionImage', {
292
+ title: option.title
293
+ }),
291
294
  onError: setImageAvailability
292
295
  });
293
296
  };
@@ -305,7 +305,8 @@ var Optiondetail = /*#__PURE__*/function (_React$Component) {
305
305
  onClose = _this$props5.onClose,
306
306
  details = _this$props5.details,
307
307
  classes = _this$props5.classes,
308
- width = _this$props5.width;
308
+ width = _this$props5.width,
309
+ optionclassification = _this$props5.optionclassification;
309
310
  var _this$state = this.state,
310
311
  loading = _this$state.loading,
311
312
  loadingContainerHeight = _this$state.loadingContainerHeight;
@@ -386,7 +387,10 @@ var Optiondetail = /*#__PURE__*/function (_React$Component) {
386
387
  onLoad: this.handleImageLoaded,
387
388
  className: this.state.zoomImage && ['xs', 'sm'].includes(width) ? classes.imageHidden : classes.image,
388
389
  src: (0, _getImageUrl["default"])(detailImage),
389
- alt: details.title
390
+ alt: (0, _i18n.T)('ariaLabels.optionDetailsImage', {
391
+ componentTitle: optionclassification.title,
392
+ optionTitle: details.title
393
+ })
390
394
  })), detailsContent) : detailsContent, showNav && /*#__PURE__*/_react["default"].createElement("div", {
391
395
  className: (0, _clsx2["default"])(classes.detailNav, 'next'),
392
396
  onClick: this.next
@@ -45,7 +45,11 @@ var ProductPart = function ProductPart(_ref) {
45
45
  className: "".concat(classes.icon, " ").concat(direction),
46
46
  style: imageUrl ? {
47
47
  backgroundImage: 'url(' + imageUrl + ')'
48
- } : {}
48
+ } : {},
49
+ "aria-label": (0, _i18n.t)('ariaLabels.component', {
50
+ title: optionclassification.title
51
+ }),
52
+ role: "img"
49
53
  });
50
54
  };
51
55
  var displayText = function displayText() {
@@ -400,7 +400,6 @@ var ImageEditDialog = /*#__PURE__*/function (_React$Component) {
400
400
  closePreviewDialog = _this$props2.closePreviewDialog,
401
401
  continueClick = _this$props2.continueClick,
402
402
  loaderComponent = _this$props2.loaderComponent,
403
- colorPickerEnabled = _this$props2.colorPickerEnabled,
404
403
  imageColorizeElement = _this$props2.imageColorizeElement,
405
404
  activeTabIndex = _this$props2.activeTabIndex,
406
405
  width = _this$props2.width,
@@ -611,7 +610,7 @@ var ImageEditDialog = /*#__PURE__*/function (_React$Component) {
611
610
  }),
612
611
  label: (0, _i18n.t)('fileUpload.removeBackgroundEverywhere'),
613
612
  disabled: backgroundSelected === null
614
- })))), colorPickerEnabled && /*#__PURE__*/_react["default"].createElement(_Typography["default"], {
613
+ })))), /*#__PURE__*/_react["default"].createElement(_Typography["default"], {
615
614
  variant: "caption",
616
615
  className: classes.colorizeCaption
617
616
  }, colorizeIcon !== null && colorizeIcon !== void 0 ? colorizeIcon : /*#__PURE__*/_react["default"].createElement(_Icon["default"], null, "colorize"), /*#__PURE__*/_react["default"].createElement("i", null, (0, _i18n.t)((0, _withWidth.isWidthDown)('xs', width) ? 'fileUpload.tabColorForRemove' : 'fileUpload.chooseColorForRemove')))), activeTabIndex === 2 && /*#__PURE__*/_react["default"].createElement("div", {
@@ -44,7 +44,7 @@ var getGalleryImages = (0, _createSelector["default"])(function (imageGallerySta
44
44
  var host = (0, _configuration.getConf)('network.host');
45
45
  return images.map(function (image) {
46
46
  return _objectSpread(_objectSpread({}, image), {}, {
47
- url: "".concat(host).concat(image.thumbUrl)
47
+ url: image.thumbUrl.startsWith('http') ? image.thumbUrl : "".concat(host).concat(image.thumbUrl)
48
48
  });
49
49
  });
50
50
  });
@@ -121,32 +121,33 @@ var ImageEditDialogContainer = exports.ImageEditDialogContainer = /*#__PURE__*/f
121
121
  });
122
122
  _defineProperty(_assertThisInitialized(_this), "lastImageUpdateData", null);
123
123
  _defineProperty(_assertThisInitialized(_this), "updateOriginalPreview", /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee() {
124
- var image, previewUrl, isSvg, svgContent, preview;
124
+ var image, url, previewUrl, isSvg, svgContent, preview;
125
125
  return _regeneratorRuntime().wrap(function _callee$(_context) {
126
126
  while (1) switch (_context.prev = _context.next) {
127
127
  case 0:
128
128
  image = _this.props.image;
129
- previewUrl = "".concat((0, _configuration.getConf)('network.host')).concat(image.preview.url);
129
+ url = (0, _get["default"])(image, 'preview.url', '');
130
+ previewUrl = url.startsWith('http') ? url : "".concat((0, _configuration.getConf)('network.host')).concat(url);
130
131
  isSvg = previewUrl && /\.svg$/.test(previewUrl);
131
132
  if (!isSvg) {
132
- _context.next = 11;
133
+ _context.next = 12;
133
134
  break;
134
135
  }
135
- _context.next = 6;
136
+ _context.next = 7;
136
137
  return (0, _DesignDataService.getSvgContent)(previewUrl, true);
137
- case 6:
138
+ case 7:
138
139
  svgContent = _context.sent;
139
140
  preview = (0, _DesignDataService.applySvgContentOperations)(image.preview, null, svgContent);
140
141
  _this.setState({
141
142
  originalImagePreview: preview
142
143
  });
143
- _context.next = 12;
144
+ _context.next = 13;
144
145
  break;
145
- case 11:
146
+ case 12:
146
147
  _this.setState({
147
148
  originalImagePreview: previewUrl
148
149
  });
149
- case 12:
150
+ case 13:
150
151
  case "end":
151
152
  return _context.stop();
152
153
  }
@@ -394,7 +395,6 @@ var ImageEditDialogContainer = exports.ImageEditDialogContainer = /*#__PURE__*/f
394
395
  _options$forceFetch,
395
396
  forceFetch,
396
397
  image,
397
- activeTabIndex,
398
398
  preview,
399
399
  originalImagePreview,
400
400
  previewUrl,
@@ -408,36 +408,32 @@ var ImageEditDialogContainer = exports.ImageEditDialogContainer = /*#__PURE__*/f
408
408
  options = _args6.length > 1 && _args6[1] !== undefined ? _args6[1] : {};
409
409
  _options$forceFetch = options.forceFetch, forceFetch = _options$forceFetch === void 0 ? false : _options$forceFetch;
410
410
  image = _this.props.image;
411
- activeTabIndex = _this.state.activeTabIndex;
412
411
  preview = null;
413
412
  originalImagePreview = null;
414
413
  previewUrl = image === null || image === void 0 || (_image$preview = image.preview) === null || _image$preview === void 0 ? void 0 : _image$preview.url;
415
- if (previewUrl && activeTabIndex === 1) {
416
- previewUrl = (0, _Transformers.getRasterURL)(previewUrl);
417
- }
418
414
  isSvg = previewUrl && /\.svg$/.test(previewUrl);
419
415
  if (!image) {
420
- _context6.next = 22;
416
+ _context6.next = 20;
421
417
  break;
422
418
  }
423
419
  updateSVG = isSvg;
424
420
  if (!updateSVG) {
425
- _context6.next = 19;
421
+ _context6.next = 17;
426
422
  break;
427
423
  }
428
424
  if (svgContent) {
429
- _context6.next = 16;
425
+ _context6.next = 14;
430
426
  break;
431
427
  }
432
- _context6.next = 15;
433
- return (0, _DesignDataService.getSvgContent)(image.preview.url, false, forceFetch);
434
- case 15:
428
+ _context6.next = 13;
429
+ return (0, _DesignDataService.getSvgContent)(image.preview.url, image.preview.url.startsWith('http'), forceFetch);
430
+ case 13:
435
431
  svgContent = _context6.sent;
436
- case 16:
432
+ case 14:
437
433
  preview = (0, _DesignDataService.applySvgContentOperations)(image.preview, image.displayColorPreview ? image.operations : null, svgContent);
438
- _context6.next = 22;
434
+ _context6.next = 20;
439
435
  break;
440
- case 19:
436
+ case 17:
441
437
  forceUpdate = isImageInvalidatedByChange(_this.lastImageUpdateData, image);
442
438
  if (forceUpdate) {
443
439
  _this.previewVersion = Math.random();
@@ -446,13 +442,13 @@ var ImageEditDialogContainer = exports.ImageEditDialogContainer = /*#__PURE__*/f
446
442
  preview = (0, _Selectors3.getPreviewUrlFromImageData)(previewUrl) + (_this.previewVersion ? "?".concat(_this.previewVersion) : '');
447
443
  originalImagePreview = preview;
448
444
  }
449
- case 22:
445
+ case 20:
450
446
  _this.lastImageUpdateData = image;
451
447
  _this.setState({
452
448
  preview: preview,
453
449
  originalImagePreview: originalImagePreview
454
450
  });
455
- case 24:
451
+ case 22:
456
452
  case "end":
457
453
  return _context6.stop();
458
454
  }
@@ -793,7 +789,6 @@ var ImageEditDialogContainer = exports.ImageEditDialogContainer = /*#__PURE__*/f
793
789
  closePreviewDialog: this.closePreviewDialog,
794
790
  backgroundSelected: clipping,
795
791
  preview: preview,
796
- colorPickerEnabled: !!clipping,
797
792
  uploadDelayed: uploadDelayed,
798
793
  continueButtonDisabled: continueButtonDisabled,
799
794
  continueClick: this.continueClick,
@@ -882,7 +877,7 @@ var getUserImages = (0, _createSelector["default"])(function (imageGalleryState)
882
877
  });
883
878
  return userImages.map(function (image) {
884
879
  return _objectSpread(_objectSpread({}, image), {}, {
885
- url: "".concat(host).concat(image.thumbnail.url)
880
+ url: image.thumbnail.url.startsWith('http') ? image.thumbnail.url : "".concat(host).concat(image.thumbnail.url)
886
881
  });
887
882
  });
888
883
  });
@@ -23,7 +23,7 @@ var getPreviewUrlFromImageData = exports.getPreviewUrlFromImageData = function g
23
23
  }
24
24
  var _options$host = options.host,
25
25
  host = _options$host === void 0 ? (0, _configuration.getConf)('network.host', '') : _options$host;
26
- return "".concat(host).concat(previewUrl);
26
+ return previewUrl.startsWith('http') ? previewUrl : "".concat(host).concat(previewUrl);
27
27
  };
28
28
  var isEditableVectorImage = exports.isEditableVectorImage = function isEditableVectorImage(preview) {
29
29
  return preview && preview.url && (/.svg$/.test(preview.url) || /^data:image\/svg\+xml/.test(preview.url));
@@ -70,7 +70,7 @@ var prepareImageData = function createImageDataPreProcessor() {
70
70
  break;
71
71
  }
72
72
  _context.next = 11;
73
- return (0, _DesignDataService.getSvgContent)(imageData.preview.url, false, true);
73
+ return (0, _DesignDataService.getSvgContent)(imageData.preview.url, imageData.preview.url.startsWith('http'), true);
74
74
  case 11:
75
75
  svgContent = _context.sent;
76
76
  svgColors = (0, _DesignDataService.getSvgColors)(svgContent, designProductionMethod);
@@ -153,7 +153,11 @@ var calculateImageBrightness = exports.calculateImageBrightness = function calcu
153
153
  if (!image) {
154
154
  return;
155
155
  }
156
- var imageUrl = image.data && image.data.thumbnail ? "".concat((0, _configuration.getConf)('network.host')).concat(image.data.thumbnail.url) : null;
156
+ var thumbnail = (0, _get2["default"])(image, 'data.thumbnail.url', null);
157
+ var imageUrl = null;
158
+ if (thumbnail) {
159
+ imageUrl = thumbnail.startsWith('http') ? thumbnail : "".concat((0, _configuration.getConf)('network.host')).concat(thumbnail);
160
+ }
157
161
  var fuzzy = 0.1;
158
162
  return new Promise(function (resolve, reject) {
159
163
  var downloadedImg = new Image(200, 200);
@@ -2457,7 +2461,7 @@ var DesignDataService = exports["default"] = /*#__PURE__*/function () {
2457
2461
  while (1) switch (_context33.prev = _context33.next) {
2458
2462
  case 0:
2459
2463
  _context33.next = 2;
2460
- return getSvgContent(url);
2464
+ return getSvgContent(url, url.startsWith('http'));
2461
2465
  case 2:
2462
2466
  svgContent = _context33.sent;
2463
2467
  designProductionMethod = (0, _Selectors.getSelectedDesignProductionMethod)(_ServiceLocator.Services.store.state);
@@ -2483,7 +2487,7 @@ var DesignDataService = exports["default"] = /*#__PURE__*/function () {
2483
2487
  while (1) switch (_context34.prev = _context34.next) {
2484
2488
  case 0:
2485
2489
  _context34.next = 2;
2486
- return getSvgContent(url);
2490
+ return getSvgContent(url, url.startsWith('http'));
2487
2491
  case 2:
2488
2492
  svgContent = _context34.sent;
2489
2493
  svgTag = (_svgContent$match = svgContent.match(/<svg[^>]+>/)) === null || _svgContent$match === void 0 ? void 0 : _svgContent$match[0];
@@ -2688,7 +2692,7 @@ var DesignDataService = exports["default"] = /*#__PURE__*/function () {
2688
2692
  }
2689
2693
  _designProductionMethod = (0, _Selectors.getSelectedDesignProductionMethod)(_ServiceLocator.Services.store.state);
2690
2694
  _context36.next = 35;
2691
- return getSvgContent(preview.url, false, !operationsMatching);
2695
+ return getSvgContent(preview.url, preview.url.startsWith('http'), !operationsMatching);
2692
2696
  case 35:
2693
2697
  svgContent = _context36.sent;
2694
2698
  svgColors = getSvgColors(svgContent, _designProductionMethod);
@@ -40,9 +40,10 @@ function getCanvasImageScalingWithImageData(canvasImage, imageData) {
40
40
  return canvasImage.scaling * (currentPreview.width / nextPreview.width);
41
41
  }
42
42
  function updateCanvasImageWithImageData(canvasImage, imageData) {
43
+ var _imageData$preview$ur;
43
44
  return canvasImage.updateOptions((0, _Transformers.prepareImageObjectData)({
44
45
  imageData: imageData,
45
- src: "".concat((0, _configuration.getConf)('network.host')).concat(imageData.preview.url),
46
+ src: (_imageData$preview$ur = imageData.preview.url) !== null && _imageData$preview$ur !== void 0 && _imageData$preview$ur.startsWith('http') ? imageData.preview.url : "".concat((0, _configuration.getConf)('network.host')).concat(imageData.preview.url),
46
47
  scaling: getCanvasImageScalingWithImageData(canvasImage, imageData)
47
48
  }));
48
49
  }
@@ -259,7 +260,7 @@ var DesignerService = exports["default"] = /*#__PURE__*/function () {
259
260
  throw new Error('Preview image url is not specified!');
260
261
  case 10:
261
262
  _ServiceLocator.Services.store.dispatch((0, _Actions.updateUploadDelayed)(false));
262
- return _context5.abrupt("return", "".concat((0, _configuration.getConf)('network.host')).concat(url));
263
+ return _context5.abrupt("return", url.startsWith('http') ? url : "".concat((0, _configuration.getConf)('network.host')).concat(url));
263
264
  case 12:
264
265
  case "end":
265
266
  return _context5.stop();
@@ -11,6 +11,7 @@ var _Typography = _interopRequireDefault(require("@material-ui/core/Typography")
11
11
  var _propTypes = _interopRequireDefault(require("prop-types"));
12
12
  var _get = _interopRequireDefault(require("lodash/get"));
13
13
  var _getImageUrl = _interopRequireDefault(require("../../../Utils/getImageUrl"));
14
+ var _i18n = require("../../../../Framework/i18n");
14
15
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
15
16
  function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
16
17
  function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor); } }
@@ -88,10 +89,14 @@ var ConfigurationOverview = /*#__PURE__*/function (_React$Component) {
88
89
  var _this$props = this.props,
89
90
  optionclassifications = _this$props.optionclassifications,
90
91
  classes = _this$props.classes;
91
- var renderImage = function renderImage(thumbnail) {
92
+ var renderImage = function renderImage(thumbnail, componentTitle, optionTitle) {
92
93
  var src = (0, _getImageUrl["default"])(thumbnail);
93
94
  return src && /*#__PURE__*/_react["default"].createElement("img", {
94
- src: src
95
+ src: src,
96
+ alt: (0, _i18n.t)('ariaLabels.overViewSelectedOptionImage', {
97
+ componentTitle: componentTitle,
98
+ optionTitle: optionTitle
99
+ })
95
100
  });
96
101
  };
97
102
  return /*#__PURE__*/_react["default"].createElement("div", {
@@ -114,11 +119,11 @@ var ConfigurationOverview = /*#__PURE__*/function (_React$Component) {
114
119
  className: classes.options
115
120
  }, option.amount !== 1 ? /*#__PURE__*/_react["default"].createElement("div", {
116
121
  className: classes.image
117
- }, renderImage((0, _get["default"])(option, 'thumbnail', '')), /*#__PURE__*/_react["default"].createElement(_Typography["default"], {
122
+ }, renderImage((0, _get["default"])(option, 'thumbnail', ''), optionclassification.title, option.title), /*#__PURE__*/_react["default"].createElement(_Typography["default"], {
118
123
  className: classes.option
119
124
  }, option.amount, " x ", option.title)) : /*#__PURE__*/_react["default"].createElement("div", {
120
125
  className: classes.image
121
- }, renderImage((0, _get["default"])(option, 'thumbnail', '')), /*#__PURE__*/_react["default"].createElement(_Typography["default"], {
126
+ }, renderImage((0, _get["default"])(option, 'thumbnail', ''), optionclassification.title, option.title), /*#__PURE__*/_react["default"].createElement(_Typography["default"], {
122
127
  className: classes.option
123
128
  }, option.title)));
124
129
  }))));
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@configuratorware/configurator-frontendgui",
3
- "version": "1.50.4",
3
+ "version": "1.51.1",
4
4
  "license": "UNLICENSED",
5
5
  "private": false,
6
6
  "main": "./index.js",
7
7
  "dependencies": {
8
8
  "@babel/polyfill": "^7.12.1",
9
- "@configuratorware/scripts": "1.50.4",
9
+ "@configuratorware/scripts": "1.51.1",
10
10
  "@material-ui/core": "^4.12.4",
11
11
  "@material-ui/icons": "^4.11.3",
12
12
  "@material-ui/lab": "^4.0.0-alpha.61",
@@ -36,8 +36,8 @@
36
36
  "react-router-dom": "^5.3.4",
37
37
  "react-swipeable": "^5.5.1",
38
38
  "react-zoom-pan-pinch": "^2.1.3",
39
- "redhotmagma-graphics-editor": "1.50.4",
40
- "redhotmagma-visualization": "1.50.4",
39
+ "redhotmagma-graphics-editor": "1.51.1",
40
+ "redhotmagma-visualization": "1.51.1",
41
41
  "redux": "^4.1.0",
42
42
  "redux-logger": "^3.0.6",
43
43
  "redux-persist": "^5.10.0",
@@ -474,5 +474,11 @@
474
474
  "title": "Produktübersicht",
475
475
  "customize": "Konfigurieren",
476
476
  "noItems": "Keine verfügbaren Produkte"
477
+ },
478
+ "ariaLabels": {
479
+ "component": "Komponente: %{title}",
480
+ "optionImage": "Option: %{title}",
481
+ "optionDetailsImage": "Detailansicht: %{componentTitle} %{optionTitle}",
482
+ "overViewSelectedOptionImage": "Meine Konfiguration: %{componentTitle} %{optionTitle}"
477
483
  }
478
484
  }
@@ -474,5 +474,11 @@
474
474
  "title": "Item Overview",
475
475
  "customize": "Customize",
476
476
  "noItems": "No available items"
477
+ },
478
+ "ariaLabels": {
479
+ "component": "Component: %{title}",
480
+ "optionImage": "Option: %{title}",
481
+ "optionDetailsImage": "Detailed view: %{componentTitle} %{optionTitle}",
482
+ "overViewSelectedOptionImage": "My configuration: %{componentTitle} %{optionTitle}"
477
483
  }
478
484
  }
@@ -323,6 +323,7 @@ exports[`Option renders with TextInput 1`] = `
323
323
  class="Option-image-154"
324
324
  >
325
325
  <img
326
+ alt="ariaLabels.optionImage"
326
327
  src="/images/options/010002011000.png"
327
328
  />
328
329
  </div>
@@ -386,6 +387,7 @@ exports[`Option renders with an available image 1`] = `
386
387
  class="Option-image-8"
387
388
  >
388
389
  <img
390
+ alt="ariaLabels.optionImage"
389
391
  src="/images/options/010002011000.png"
390
392
  />
391
393
  </div>
@@ -295,7 +295,15 @@ const Option = ({ children, render, ...props }) => {
295
295
 
296
296
  const renderImage = () => {
297
297
  const src = getImageUrl(thumbnail);
298
- return src && <img src={src} onError={setImageAvailability} />;
298
+ return (
299
+ src && (
300
+ <img
301
+ src={src}
302
+ alt={t('ariaLabels.optionImage', { title: option.title })}
303
+ onError={setImageAvailability}
304
+ />
305
+ )
306
+ );
299
307
  };
300
308
 
301
309
  const renderNotAvailableImage = () => {
@@ -265,7 +265,16 @@ class Optiondetail extends React.Component {
265
265
  };
266
266
 
267
267
  render() {
268
- const { LoadingComponent, options, show, onClose, details, classes, width } = this.props;
268
+ const {
269
+ LoadingComponent,
270
+ options,
271
+ show,
272
+ onClose,
273
+ details,
274
+ classes,
275
+ width,
276
+ optionclassification,
277
+ } = this.props;
269
278
  const { loading, loadingContainerHeight } = this.state;
270
279
  const showNav = isArray(options) && options.length > 1;
271
280
  const detailImage = details.detailImage;
@@ -389,7 +398,10 @@ class Optiondetail extends React.Component {
389
398
  : classes.image
390
399
  }
391
400
  src={getImageUrl(detailImage)}
392
- alt={details.title}
401
+ alt={T('ariaLabels.optionDetailsImage', {
402
+ componentTitle: optionclassification.title,
403
+ optionTitle: details.title,
404
+ })}
393
405
  />
394
406
  </div>
395
407
  {detailsContent}
@@ -13,7 +13,9 @@ exports[`ProductPart renders with horizontal marker 1`] = `
13
13
  type="button"
14
14
  >
15
15
  <i
16
+ aria-label="ariaLabels.component"
16
17
  class="ProductPart-icon-21 horizontal"
18
+ role="img"
17
19
  style="background-image:url(/images/components/seat.png)"
18
20
  />
19
21
  <span
@@ -38,7 +40,9 @@ exports[`ProductPart renders with vertical marker 1`] = `
38
40
  type="button"
39
41
  >
40
42
  <i
43
+ aria-label="ariaLabels.component"
41
44
  class="ProductPart-icon-15 vertical"
45
+ role="img"
42
46
  style="background-image:url(/images/components/seat.png)"
43
47
  />
44
48
  <span
@@ -63,7 +67,9 @@ exports[`ProductPart renders without marker 1`] = `
63
67
  type="button"
64
68
  >
65
69
  <i
70
+ aria-label="ariaLabels.component"
66
71
  class="ProductPart-icon-3 vertical"
72
+ role="img"
67
73
  style="background-image:url(/images/components/seat.png)"
68
74
  />
69
75
  <span
@@ -88,7 +94,9 @@ exports[`ProductPart renders without marker when menu is closed 1`] = `
88
94
  type="button"
89
95
  >
90
96
  <i
97
+ aria-label="ariaLabels.component"
91
98
  class="ProductPart-icon-9 vertical"
99
+ role="img"
92
100
  style="background-image:url(/images/components/seat.png)"
93
101
  />
94
102
  <span
@@ -7,6 +7,7 @@ import getImageUrl from 'App/Utils/getImageUrl';
7
7
  import customClassName from 'App/Utils/customClassName';
8
8
  import { Hyphenated } from 'Framework/i18n';
9
9
  import { withStyles } from '@material-ui/core/styles';
10
+ import { t } from 'Framework/i18n';
10
11
  import AccessibleButton from '../../../../Shared/Components/AccessibleButton/AccessibleButton';
11
12
 
12
13
  const ProductPart = ({
@@ -41,6 +42,8 @@ const ProductPart = ({
41
42
  <i
42
43
  className={`${classes.icon} ${direction}`}
43
44
  style={imageUrl ? { backgroundImage: 'url(' + imageUrl + ')' } : {}}
45
+ aria-label={t('ariaLabels.component', { title: optionclassification.title })}
46
+ role="img"
44
47
  />
45
48
  );
46
49
  };
@@ -352,7 +352,6 @@ class ImageEditDialog extends React.Component {
352
352
  closePreviewDialog: PropTypes.func,
353
353
  continueClick: PropTypes.func,
354
354
  onChangeColor: PropTypes.func,
355
- colorPickerEnabled: PropTypes.bool,
356
355
  imageColorizeElement: PropTypes.element,
357
356
  activeTabIndex: PropTypes.number,
358
357
  onActiveTabChange: PropTypes.func,
@@ -464,7 +463,6 @@ class ImageEditDialog extends React.Component {
464
463
  closePreviewDialog,
465
464
  continueClick,
466
465
  loaderComponent,
467
- colorPickerEnabled,
468
466
  imageColorizeElement,
469
467
  activeTabIndex,
470
468
  width,
@@ -785,18 +783,16 @@ class ImageEditDialog extends React.Component {
785
783
  </RadioGroup>
786
784
  </AnalyticsWrapper>
787
785
  </FormControl>
788
- {colorPickerEnabled && (
789
- <Typography variant="caption" className={classes.colorizeCaption}>
790
- {colorizeIcon ?? <Icon>colorize</Icon>}
791
- <i>
792
- {t(
793
- isWidthDown('xs', width)
794
- ? 'fileUpload.tabColorForRemove'
795
- : 'fileUpload.chooseColorForRemove'
796
- )}
797
- </i>
798
- </Typography>
799
- )}
786
+ <Typography variant="caption" className={classes.colorizeCaption}>
787
+ {colorizeIcon ?? <Icon>colorize</Icon>}
788
+ <i>
789
+ {t(
790
+ isWidthDown('xs', width)
791
+ ? 'fileUpload.tabColorForRemove'
792
+ : 'fileUpload.chooseColorForRemove'
793
+ )}
794
+ </i>
795
+ </Typography>
800
796
  </div>
801
797
  )}
802
798
  {activeTabIndex === 2 && (
@@ -37,7 +37,7 @@ const getGalleryImages = createSelector(
37
37
  const host = getConf('network.host');
38
38
  return images.map(image => ({
39
39
  ...image,
40
- url: `${host}${image.thumbUrl}`,
40
+ url: image.thumbUrl.startsWith('http') ? image.thumbUrl : `${host}${image.thumbUrl}`,
41
41
  }));
42
42
  }
43
43
  );
@@ -51,7 +51,7 @@ import createSelector from 'Utils/Function/createSelector';
51
51
  import { getConf } from 'App/configuration';
52
52
  import { EventTypes } from 'App/Constant';
53
53
  import { expandVectorizeColorsMap, getClosestColorFromMap } from '../Utils/ImageEditUtils';
54
- import { getRasterURL, isOriginalVector } from '../Utils/Transformers';
54
+ import { isOriginalVector } from '../Utils/Transformers';
55
55
  import { getClient, getConfigurator } from '../../../Reducers/Configurator/Selectors';
56
56
 
57
57
  const getOperationsFromState = state => {
@@ -318,7 +318,8 @@ export class ImageEditDialogContainer extends React.Component {
318
318
 
319
319
  updateOriginalPreview = async () => {
320
320
  const { image } = this.props;
321
- const previewUrl = `${getConf('network.host')}${image.preview.url}`;
321
+ const url = get(image, 'preview.url', '');
322
+ const previewUrl = url.startsWith('http') ? url : `${getConf('network.host')}${url}`;
322
323
  const isSvg = previewUrl && /\.svg$/.test(previewUrl);
323
324
  if (isSvg) {
324
325
  const svgContent = await getSvgContent(previewUrl, true);
@@ -515,15 +516,11 @@ export class ImageEditDialogContainer extends React.Component {
515
516
  updatePreview = async (svgContent, options = {}) => {
516
517
  const { forceFetch = false } = options;
517
518
  const { image } = this.props;
518
- const { activeTabIndex } = this.state;
519
519
 
520
520
  let preview = null;
521
521
  let originalImagePreview = null;
522
522
 
523
523
  let previewUrl = image?.preview?.url;
524
- if (previewUrl && activeTabIndex === 1) {
525
- previewUrl = getRasterURL(previewUrl);
526
- }
527
524
 
528
525
  const isSvg = previewUrl && /\.svg$/.test(previewUrl);
529
526
 
@@ -532,7 +529,11 @@ export class ImageEditDialogContainer extends React.Component {
532
529
 
533
530
  if (updateSVG) {
534
531
  if (!svgContent) {
535
- svgContent = await getSvgContent(image.preview.url, false, forceFetch);
532
+ svgContent = await getSvgContent(
533
+ image.preview.url,
534
+ image.preview.url.startsWith('http'),
535
+ forceFetch
536
+ );
536
537
  }
537
538
 
538
539
  preview = applySvgContentOperations(
@@ -741,7 +742,6 @@ export class ImageEditDialogContainer extends React.Component {
741
742
  closePreviewDialog={this.closePreviewDialog}
742
743
  backgroundSelected={clipping}
743
744
  preview={preview}
744
- colorPickerEnabled={!!clipping}
745
745
  uploadDelayed={uploadDelayed}
746
746
  continueButtonDisabled={continueButtonDisabled}
747
747
  continueClick={this.continueClick}
@@ -825,7 +825,9 @@ const getUserImages = createSelector(
825
825
  return userImages.map(image => {
826
826
  return {
827
827
  ...image,
828
- url: `${host}${image.thumbnail.url}`,
828
+ url: image.thumbnail.url.startsWith('http')
829
+ ? image.thumbnail.url
830
+ : `${host}${image.thumbnail.url}`,
829
831
  };
830
832
  });
831
833
  }
@@ -22,7 +22,7 @@ export const getPreviewUrlFromImageData = (preview, options = {}) => {
22
22
  return previewUrl;
23
23
  }
24
24
  const { host = getConf('network.host', '') } = options;
25
- return `${host}${previewUrl}`;
25
+ return previewUrl.startsWith('http') ? previewUrl : `${host}${previewUrl}`;
26
26
  };
27
27
 
28
28
  export const isEditableVectorImage = preview => {
@@ -55,7 +55,11 @@ const prepareImageData = (function createImageDataPreProcessor() {
55
55
 
56
56
  if (colorPreviewRequired) {
57
57
  // creating the color map, as it was added from the image edit dialog
58
- const svgContent = await getSvgContent(imageData.preview.url, false, true);
58
+ const svgContent = await getSvgContent(
59
+ imageData.preview.url,
60
+ imageData.preview.url.startsWith('http'),
61
+ true
62
+ );
59
63
  const svgColors = getSvgColors(svgContent, designProductionMethod);
60
64
  const vectorizeColorsMap = createVectorizeColorsMap({}, svgColors);
61
65
  patchedImageData = {
@@ -228,9 +228,11 @@ export const calculateImageBrightness = image => {
228
228
  if (!image) {
229
229
  return;
230
230
  }
231
-
232
- const imageUrl =
233
- image.data && image.data.thumbnail ? `${getConf('network.host')}${image.data.thumbnail.url}` : null;
231
+ const thumbnail = get(image, 'data.thumbnail.url', null);
232
+ let imageUrl = null;
233
+ if (thumbnail) {
234
+ imageUrl = thumbnail.startsWith('http') ? thumbnail : `${getConf('network.host')}${thumbnail}`;
235
+ }
234
236
  const fuzzy = 0.1;
235
237
 
236
238
  return new Promise((resolve, reject) => {
@@ -1888,7 +1890,7 @@ export default class DesignDataService {
1888
1890
  }
1889
1891
 
1890
1892
  async getGalleryImageColors(url) {
1891
- const svgContent = await getSvgContent(url);
1893
+ const svgContent = await getSvgContent(url, url.startsWith('http'));
1892
1894
 
1893
1895
  const designProductionMethod = getSelectedDesignProductionMethod(Services.store.state);
1894
1896
 
@@ -1896,7 +1898,7 @@ export default class DesignDataService {
1896
1898
  }
1897
1899
 
1898
1900
  async getSVGImageSize(url) {
1899
- const svgContent = await getSvgContent(url);
1901
+ const svgContent = await getSvgContent(url, url.startsWith('http'));
1900
1902
  const svgTag = svgContent.match(/<svg[^>]+>/)?.[0];
1901
1903
  const width = svgContent.match(/width="([^"]+)"/)?.[1];
1902
1904
  const height = svgContent.match(/height="([^"]+)"/)?.[1];
@@ -2043,7 +2045,11 @@ export default class DesignDataService {
2043
2045
 
2044
2046
  if (isEditableVectorImage(preview)) {
2045
2047
  const designProductionMethod = getSelectedDesignProductionMethod(Services.store.state);
2046
- const svgContent = await getSvgContent(preview.url, false, !operationsMatching);
2048
+ const svgContent = await getSvgContent(
2049
+ preview.url,
2050
+ preview.url.startsWith('http'),
2051
+ !operationsMatching
2052
+ );
2047
2053
  const svgColors = getSvgColors(svgContent, designProductionMethod);
2048
2054
 
2049
2055
  const vectorizeColorsMap = createVectorizeColorsMap(operations.vectorizeColorsMap, svgColors);
@@ -48,7 +48,9 @@ function updateCanvasImageWithImageData(canvasImage, imageData) {
48
48
  return canvasImage.updateOptions(
49
49
  prepareImageObjectData({
50
50
  imageData,
51
- src: `${getConf('network.host')}${imageData.preview.url}`,
51
+ src: imageData.preview.url?.startsWith('http')
52
+ ? imageData.preview.url
53
+ : `${getConf('network.host')}${imageData.preview.url}`,
52
54
  scaling: getCanvasImageScalingWithImageData(canvasImage, imageData),
53
55
  })
54
56
  );
@@ -184,7 +186,7 @@ export default class DesignerService {
184
186
  throw new Error('Preview image url is not specified!');
185
187
  }
186
188
  Services.store.dispatch(updateUploadDelayed(false));
187
- return `${getConf('network.host')}${url}`;
189
+ return url.startsWith('http') ? url : `${getConf('network.host')}${url}`;
188
190
  }
189
191
 
190
192
  async addImageFromUrl(canvas, url, imageData, options = {}) {
@@ -4,6 +4,7 @@ import Typography from '@material-ui/core/Typography';
4
4
  import PropTypes from 'prop-types';
5
5
  import get from 'lodash/get';
6
6
  import getImageUrl from '../../../Utils/getImageUrl';
7
+ import { t } from 'Framework/i18n';
7
8
 
8
9
  const styles = () => ({
9
10
  tableWrapper: {
@@ -65,9 +66,19 @@ class ConfigurationOverview extends React.Component {
65
66
  render() {
66
67
  const { optionclassifications, classes } = this.props;
67
68
 
68
- const renderImage = thumbnail => {
69
+ const renderImage = (thumbnail, componentTitle, optionTitle) => {
69
70
  const src = getImageUrl(thumbnail);
70
- return src && <img src={src} />;
71
+ return (
72
+ src && (
73
+ <img
74
+ src={src}
75
+ alt={t('ariaLabels.overViewSelectedOptionImage', {
76
+ componentTitle: componentTitle,
77
+ optionTitle: optionTitle,
78
+ })}
79
+ />
80
+ )
81
+ );
71
82
  };
72
83
 
73
84
  return (
@@ -88,14 +99,22 @@ class ConfigurationOverview extends React.Component {
88
99
  <li className={classes.options}>
89
100
  {option.amount !== 1 ? (
90
101
  <div className={classes.image}>
91
- {renderImage(get(option, 'thumbnail', ''))}
102
+ {renderImage(
103
+ get(option, 'thumbnail', ''),
104
+ optionclassification.title,
105
+ option.title
106
+ )}
92
107
  <Typography className={classes.option}>
93
108
  {option.amount} x {option.title}
94
109
  </Typography>
95
110
  </div>
96
111
  ) : (
97
112
  <div className={classes.image}>
98
- {renderImage(get(option, 'thumbnail', ''))}
113
+ {renderImage(
114
+ get(option, 'thumbnail', ''),
115
+ optionclassification.title,
116
+ option.title
117
+ )}
99
118
  <Typography className={classes.option}>
100
119
  {option.title}
101
120
  </Typography>