@configuratorware/configurator-frontendgui 1.55.4 → 1.55.5

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.
@@ -114,12 +114,17 @@ var styles = function styles(theme) {
114
114
  margin: theme.smallScreen.padding
115
115
  }),
116
116
  imageTabOptions: {
117
+ backgroundColor: '#E8E8EA',
118
+ borderRadius: '5px',
117
119
  '& button': {
118
- minWidth: '33%',
120
+ minWidth: '33.33%',
119
121
  minHeight: 64,
120
122
  textTransform: 'none',
121
123
  fontSize: 15,
122
- color: '#757575'
124
+ color: theme.palette.primary.darkText
125
+ },
126
+ '& .MuiTabs-indicator': {
127
+ display: 'none'
123
128
  }
124
129
  },
125
130
  colorizeCaption: {
@@ -270,7 +275,12 @@ var styles = function styles(theme) {
270
275
  display: 'flex',
271
276
  justifyContent: 'space-between'
272
277
  }),
273
- imageTab: _defineProperty({}, theme.breakpoints.down('xs'), {
278
+ imageTab: _defineProperty({
279
+ '&.Mui-selected': {
280
+ backgroundColor: theme.palette.primary.main,
281
+ color: '#FFFFFF'
282
+ }
283
+ }, theme.breakpoints.down('xs'), {
274
284
  fontWeight: 'bold',
275
285
  fontSize: '13px !important'
276
286
  }),
@@ -3,7 +3,7 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.preparePrintDesignData = exports.prepareDesignDataSnapshots = exports.getMatchAt = exports.embeddedSvgImageToInlineSvgContent = exports.alterObjectValues = exports.alterArrayValues = void 0;
6
+ exports.preparePrintDesignData = exports.prepareDesignDataSnapshots = exports.getMissingViewBox = exports.getMatchAt = exports.embeddedSvgImageToInlineSvgContent = exports.alterObjectValues = exports.alterArrayValues = void 0;
7
7
  var getMatchAt = exports.getMatchAt = function getMatchAt(str, regexp) {
8
8
  var idx = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 1;
9
9
  var defaultValue = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : '';
@@ -38,4 +38,62 @@ var prepareDesignDataSnapshots = exports.prepareDesignDataSnapshots = function p
38
38
  };
39
39
  var preparePrintDesignData = exports.preparePrintDesignData = function preparePrintDesignData(svgMap) {
40
40
  return alterObjectValues(svgMap, embeddedSvgImageToInlineSvgContent);
41
+ };
42
+
43
+ /**
44
+ * Calculates the bounding viewBox for an SVG string.
45
+ * @param {string} svgString - The raw SVG string from the API.
46
+ * @returns {string} The calculated viewBox (e.g., "0 0 100 100").
47
+ */
48
+ var getMissingViewBox = exports.getMissingViewBox = function getMissingViewBox(svgString, fallbackSize) {
49
+ var padding = 2;
50
+
51
+ // 1. Parse the SVG string into a DOM element
52
+ var parser = new DOMParser();
53
+ var doc = parser.parseFromString(svgString, 'image/svg+xml');
54
+ var svgElement = doc.querySelector('svg');
55
+ if (!svgElement) {
56
+ throw new Error('Invalid SVG string provided.');
57
+ }
58
+
59
+ // 2. Prepare the SVG to be rendered invisibly
60
+ if (svgElement.style) {
61
+ svgElement.style.position = 'absolute';
62
+ svgElement.style.visibility = 'hidden';
63
+ svgElement.style.width = 'auto';
64
+ svgElement.style.height = 'auto';
65
+ } else {
66
+ svgElement.setAttribute('style', 'position: absolute; visibility: hidden; width: auto; height: auto;');
67
+ }
68
+
69
+ // 3. Wrap all children in a <g> tag.
70
+ // Calling getBBox() directly on the <svg> root can be unreliable across
71
+ // different browsers. A wrapper group guarantees we measure the actual content.
72
+ var wrapperGroup = document.createElementNS('http://www.w3.org/2000/svg', 'g');
73
+ while (svgElement.firstChild) {
74
+ wrapperGroup.appendChild(svgElement.firstChild);
75
+ }
76
+ svgElement.appendChild(wrapperGroup);
77
+
78
+ // 4. Attach to the DOM so the browser can calculate layout dimensions
79
+ document.body.appendChild(svgElement);
80
+
81
+ // 5. Calculate the bounding box
82
+ var viewBox = "0 0 ".concat(fallbackSize.width, " ").concat(fallbackSize.height);
83
+ if (!wrapperGroup.getBBox) {
84
+ return viewBox;
85
+ }
86
+ try {
87
+ var bbox = wrapperGroup.getBBox();
88
+ var x = bbox.x - padding;
89
+ var y = bbox.y - padding;
90
+ var width = bbox.width + padding * 2;
91
+ var height = bbox.height + padding * 2;
92
+ // Construct the viewBox string: min-x, min-y, width, height
93
+ viewBox = "".concat(x, " ").concat(y, " ").concat(width, " ").concat(height);
94
+ } finally {
95
+ // 6. Clean up by removing the hidden SVG from the DOM
96
+ document.body.removeChild(svgElement);
97
+ }
98
+ return viewBox;
41
99
  };
@@ -83,7 +83,7 @@ var prepareImageObjectData = exports.prepareImageObjectData = function prepareIm
83
83
  return (0, _DesignDataService.getSvgContent)(url, true);
84
84
  case 3:
85
85
  svgContent = _context.v;
86
- return _context.a(2, (0, _DesignDataService.applySvgContentOperations)(image.original, image.preview, displayColorPreview || gallery ? operations ? operations : image.operations : null, svgContent));
86
+ return _context.a(2, (0, _DesignDataService.applySvgContentOperations)(image.original, image.preview, displayColorPreview || gallery || originalVector ? operations ? operations : image.operations : null, svgContent));
87
87
  }
88
88
  }, _callee);
89
89
  }));
@@ -3,7 +3,7 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.setColorOnOperations = exports.replaceColorOnOperations = exports.removeVectorizeFromOperations = exports.reduceNumberOfDistinctColorsBy = exports.isOneColorAboveThreshold = exports.getEditDataFromOperations = exports.createVectorizeColorsMap = exports.compareOperations = exports.applyProductionMethodChangeToCanvasObjects = void 0;
6
+ exports.setColorOnOperations = exports.replaceColorOnOperations = exports.removeVectorizeFromOperations = exports.reduceNumberOfDistinctColorsBy = exports.isOneColorAboveThreshold = exports.getEditDataFromOperations = exports.extendCanvasDataWithMetricContentSize = exports.createVectorizeColorsMap = exports.compareOperations = exports.applyProductionMethodChangeToCanvasObjects = void 0;
7
7
  var _cloneDeep = _interopRequireDefault(require("lodash/cloneDeep"));
8
8
  var _isEqual = _interopRequireDefault(require("lodash/isEqual"));
9
9
  var _omit = _interopRequireDefault(require("lodash/omit"));
@@ -247,4 +247,66 @@ var updateLockState = function updateLockState(newProductionMethod, oldProductio
247
247
  });
248
248
  }
249
249
  return objects;
250
+ };
251
+ var extendCanvasDataWithMetricContentSize = exports.extendCanvasDataWithMetricContentSize = function extendCanvasDataWithMetricContentSize(canvasData) {
252
+ var b = {
253
+ minX: Infinity,
254
+ maxX: -Infinity,
255
+ minY: Infinity,
256
+ maxY: -Infinity
257
+ };
258
+ var mergeRotated = function mergeRotated(cx, cy, hw, hh, deg) {
259
+ var rad = deg * Math.PI / 180;
260
+ var c = Math.cos(rad);
261
+ var s = Math.sin(rad);
262
+ for (var _i = 0, _arr = [[-hw, -hh], [hw, -hh], [hw, hh], [-hw, hh]]; _i < _arr.length; _i++) {
263
+ var _arr$_i = _slicedToArray(_arr[_i], 2),
264
+ dx = _arr$_i[0],
265
+ dy = _arr$_i[1];
266
+ var x = cx + dx * c - dy * s;
267
+ var y = cy + dx * s + dy * c;
268
+ b.minX = Math.min(b.minX, x);
269
+ b.maxX = Math.max(b.maxX, x);
270
+ b.minY = Math.min(b.minY, y);
271
+ b.maxY = Math.max(b.maxY, y);
272
+ }
273
+ };
274
+ var mergeAxisAligned = function mergeAxisAligned(cx, cy, hw, hh) {
275
+ b.minX = Math.min(b.minX, cx - hw);
276
+ b.maxX = Math.max(b.maxX, cx + hw);
277
+ b.minY = Math.min(b.minY, cy - hh);
278
+ b.maxY = Math.max(b.maxY, cy + hh);
279
+ };
280
+ var _iterator2 = _createForOfIteratorHelper(canvasData.objects),
281
+ _step2;
282
+ try {
283
+ for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
284
+ var object = _step2.value;
285
+ if (!object.metric) continue;
286
+ var w = object.metric.width || 0;
287
+ var h = object.metric.height || 0;
288
+ var hw = w / 2;
289
+ var hh = h / 2;
290
+ var cx = object.metric.x || 0;
291
+ var cy = object.metric.y || 0;
292
+ if (typeof object.rotation === 'number' && object.rotation !== 0 && w && h) {
293
+ mergeRotated(cx, cy, hw, hh, object.rotation);
294
+ } else {
295
+ mergeAxisAligned(cx, cy, hw, hh);
296
+ }
297
+ }
298
+ } catch (err) {
299
+ _iterator2.e(err);
300
+ } finally {
301
+ _iterator2.f();
302
+ }
303
+ if (!Number.isFinite(b.minX)) {
304
+ return canvasData;
305
+ }
306
+ return _objectSpread(_objectSpread({}, canvasData), {}, {
307
+ metricContentSize: {
308
+ width: Math.abs(b.maxX - b.minX),
309
+ height: Math.abs(b.maxY - b.minY)
310
+ }
311
+ });
250
312
  };
@@ -355,11 +355,29 @@ var ConfiguratorService = exports["default"] = /*#__PURE__*/function (_AbstractC
355
355
  roughDesignData[designAreaIdentifier] = {
356
356
  objectCount: (0, _get["default"])(canvasData, 'objects.length'),
357
357
  designProductionMethodIdentifier: designProductionMethodIdentifier,
358
- colorAmount: colorAmount
358
+ colorAmount: colorAmount,
359
+ objects: this.getRoughDesignDataObjectDetails(designAreaData)
359
360
  };
360
361
  }
361
362
  return roughDesignData;
362
363
  }
364
+ }, {
365
+ key: "getRoughDesignDataObjectDetails",
366
+ value: function getRoughDesignDataObjectDetails(designData) {
367
+ var includeMetricData = (0, _configuration2.getConf)('designer.includeMetricContentSize', false);
368
+ return (0, _get["default"])(designData, 'canvasData.objects', []).map(function (object) {
369
+ var _object$metric, _object$metric2, _object$metric3, _object$metric4;
370
+ return _objectSpread({
371
+ uuid: object.uuid
372
+ }, includeMetricData ? {
373
+ x: ((_object$metric = object.metric) === null || _object$metric === void 0 ? void 0 : _object$metric.x) || 0,
374
+ y: ((_object$metric2 = object.metric) === null || _object$metric2 === void 0 ? void 0 : _object$metric2.y) || 0,
375
+ width: ((_object$metric3 = object.metric) === null || _object$metric3 === void 0 ? void 0 : _object$metric3.width) || 0,
376
+ height: ((_object$metric4 = object.metric) === null || _object$metric4 === void 0 ? void 0 : _object$metric4.height) || 0,
377
+ rotation: object.rotation || 0
378
+ } : {});
379
+ });
380
+ }
363
381
 
364
382
  //// <-- ACTIONS -->
365
383
  }, {
@@ -36,6 +36,7 @@ var _FontFaceRepository = require("../Modules/Designer/Utils/FontFaceRepository"
36
36
  var _Selectors5 = require("../Reducers/DesignData/Selectors");
37
37
  var _ImageEditUtils = require("../Modules/Designer/Utils/ImageEditUtils");
38
38
  var _DesignElementSelectors = require("../Reducers/DesignArea/DesignElementSelectors");
39
+ var _SvgFixers = require("../Modules/Designer/Utils/SvgFixers");
39
40
  var _designer_placeholder_logo = _interopRequireDefault(require("../../Resources/Images/designer_placeholder_logo.svg"));
40
41
  var _this = void 0;
41
42
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { "default": e }; }
@@ -344,11 +345,15 @@ var applySvgContentOperations = exports.applySvgContentOperations = function app
344
345
  var pixelHeight = Math.round(preview.height * scaleFactor);
345
346
  var isSvgUpload = _Selectors2.vectorFormats.indexOf(original.format.toLowerCase()) !== -1;
346
347
  if (svgTag.indexOf('viewBox=') === -1) {
347
- if (isSvgUpload) {
348
- svgContent = svgContent.replace('<svg', "<svg viewBox=\"0 0 ".concat(pixelWidth, " ").concat(pixelHeight, "\""));
349
- } else {
350
- svgContent = svgContent.replace('<svg', "<svg viewBox=\"0 0 ".concat(preview.width, " ").concat(preview.height, "\""));
351
- }
348
+ var fallbackSize = isSvgUpload ? {
349
+ width: pixelWidth,
350
+ height: pixelHeight
351
+ } : {
352
+ width: preview.width,
353
+ height: preview.height
354
+ };
355
+ var viewBox = (0, _SvgFixers.getMissingViewBox)(svgContent, fallbackSize);
356
+ svgContent = svgContent.replace('<svg', "<svg viewBox=\"".concat(viewBox, "\""));
352
357
  }
353
358
  if (svgTag.indexOf('height=') === -1) {
354
359
  if (isSvgUpload) {
@@ -1727,7 +1732,17 @@ var DesignDataService = exports["default"] = /*#__PURE__*/function () {
1727
1732
  }, {
1728
1733
  key: "setCanvasData",
1729
1734
  value: function setCanvasData(canvasData, targetDesignAreaIdentifier) {
1730
- _ServiceLocator.Services.store.dispatch((0, _Actions.setCanvasData)(canvasData, targetDesignAreaIdentifier));
1735
+ var extendedCanvasData = this.getExtendedCanvasData(canvasData);
1736
+ _ServiceLocator.Services.store.dispatch((0, _Actions.setCanvasData)(extendedCanvasData, targetDesignAreaIdentifier));
1737
+ }
1738
+ }, {
1739
+ key: "getExtendedCanvasData",
1740
+ value: function getExtendedCanvasData(canvasData) {
1741
+ var _canvasData$objects;
1742
+ if (!(0, _configuration.getConf)('designer.includeMetricContentSize', false) || !(canvasData !== null && canvasData !== void 0 && (_canvasData$objects = canvasData.objects) !== null && _canvasData$objects !== void 0 && _canvasData$objects.length)) {
1743
+ return canvasData;
1744
+ }
1745
+ return (0, _Modifiers.extendCanvasDataWithMetricContentSize)(canvasData);
1731
1746
  }
1732
1747
  }, {
1733
1748
  key: "setColorAmount",
@@ -203,7 +203,9 @@ var applicationConfiguration = {
203
203
  // the default canvas dpi as project specific option
204
204
  maxColorAmount: 10,
205
205
  // the default max number of colors in the colorizing feature
206
- allowedImageUploadFormats: 'jpg,jpeg,svg,png,pdf,bmp,tif,tiff,eps,ai,gif' // the image formats users can upload to designareas / designer items
206
+ allowedImageUploadFormats: 'jpg,jpeg,svg,png,pdf,bmp,tif,tiff,eps,ai,gif',
207
+ // the image formats users can upload to designareas / designer items
208
+ includeMetricContentSize: false // set true to include the metric content size in the design data
207
209
  },
208
210
  vectorizeImageQuality: 45000,
209
211
  renderPreviewImagesForCheckout: true,
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@configuratorware/configurator-frontendgui",
3
- "version": "1.55.4",
3
+ "version": "1.55.5",
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.55.4",
9
+ "@configuratorware/scripts": "1.55.5",
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.55.4",
40
- "redhotmagma-visualization": "1.55.4",
39
+ "redhotmagma-graphics-editor": "1.55.5",
40
+ "redhotmagma-visualization": "1.55.5",
41
41
  "redux": "^4.1.0",
42
42
  "redux-logger": "^3.0.6",
43
43
  "redux-persist": "^5.10.0",
@@ -103,12 +103,17 @@ const styles = theme => ({
103
103
  },
104
104
  },
105
105
  imageTabOptions: {
106
+ backgroundColor: '#E8E8EA',
107
+ borderRadius: '5px',
106
108
  '& button': {
107
- minWidth: '33%',
109
+ minWidth: '33.33%',
108
110
  minHeight: 64,
109
111
  textTransform: 'none',
110
112
  fontSize: 15,
111
- color: '#757575',
113
+ color: theme.palette.primary.darkText,
114
+ },
115
+ '& .MuiTabs-indicator': {
116
+ display: 'none',
112
117
  },
113
118
  },
114
119
  colorizeCaption: {
@@ -283,6 +288,10 @@ const styles = theme => ({
283
288
  },
284
289
  },
285
290
  imageTab: {
291
+ '&.Mui-selected': {
292
+ backgroundColor: theme.palette.primary.main,
293
+ color: '#FFFFFF',
294
+ },
286
295
  [theme.breakpoints.down('xs')]: {
287
296
  fontWeight: 'bold',
288
297
  fontSize: '13px !important',
@@ -34,3 +34,69 @@ export const prepareDesignDataSnapshots = svgArrMap =>
34
34
  alterObjectValues(svgArrMap, arr => alterArrayValues(arr, embeddedSvgImageToInlineSvgContent));
35
35
 
36
36
  export const preparePrintDesignData = svgMap => alterObjectValues(svgMap, embeddedSvgImageToInlineSvgContent);
37
+
38
+ /**
39
+ * Calculates the bounding viewBox for an SVG string.
40
+ * @param {string} svgString - The raw SVG string from the API.
41
+ * @returns {string} The calculated viewBox (e.g., "0 0 100 100").
42
+ */
43
+ export const getMissingViewBox = (svgString, fallbackSize) => {
44
+ const padding = 2;
45
+
46
+ // 1. Parse the SVG string into a DOM element
47
+ const parser = new DOMParser();
48
+ const doc = parser.parseFromString(svgString, 'image/svg+xml');
49
+ const svgElement = doc.querySelector('svg');
50
+
51
+ if (!svgElement) {
52
+ throw new Error('Invalid SVG string provided.');
53
+ }
54
+
55
+ // 2. Prepare the SVG to be rendered invisibly
56
+ if (svgElement.style) {
57
+ svgElement.style.position = 'absolute';
58
+ svgElement.style.visibility = 'hidden';
59
+ svgElement.style.width = 'auto';
60
+ svgElement.style.height = 'auto';
61
+ } else {
62
+ svgElement.setAttribute(
63
+ 'style',
64
+ 'position: absolute; visibility: hidden; width: auto; height: auto;'
65
+ );
66
+ }
67
+
68
+ // 3. Wrap all children in a <g> tag.
69
+ // Calling getBBox() directly on the <svg> root can be unreliable across
70
+ // different browsers. A wrapper group guarantees we measure the actual content.
71
+ const wrapperGroup = document.createElementNS('http://www.w3.org/2000/svg', 'g');
72
+ while (svgElement.firstChild) {
73
+ wrapperGroup.appendChild(svgElement.firstChild);
74
+ }
75
+ svgElement.appendChild(wrapperGroup);
76
+
77
+ // 4. Attach to the DOM so the browser can calculate layout dimensions
78
+ document.body.appendChild(svgElement);
79
+
80
+ // 5. Calculate the bounding box
81
+ let viewBox = `0 0 ${fallbackSize.width} ${fallbackSize.height}`;
82
+
83
+ if (!wrapperGroup.getBBox) {
84
+ return viewBox;
85
+ }
86
+
87
+ try {
88
+ const bbox = wrapperGroup.getBBox();
89
+
90
+ const x = bbox.x - padding;
91
+ const y = bbox.y - padding;
92
+ const width = bbox.width + padding * 2;
93
+ const height = bbox.height + padding * 2;
94
+ // Construct the viewBox string: min-x, min-y, width, height
95
+ viewBox = `${x} ${y} ${width} ${height}`;
96
+ } finally {
97
+ // 6. Clean up by removing the hidden SVG from the DOM
98
+ document.body.removeChild(svgElement);
99
+ }
100
+
101
+ return viewBox;
102
+ };
@@ -47,7 +47,11 @@ export const prepareImageObjectData = rawObject => {
47
47
  return applySvgContentOperations(
48
48
  image.original,
49
49
  image.preview,
50
- displayColorPreview || gallery ? (operations ? operations : image.operations) : null,
50
+ displayColorPreview || gallery || originalVector
51
+ ? operations
52
+ ? operations
53
+ : image.operations
54
+ : null,
51
55
  svgContent
52
56
  );
53
57
  };
@@ -254,3 +254,61 @@ const updateLockState = (newProductionMethod, oldProductionMethod, objects) => {
254
254
  }
255
255
  return objects;
256
256
  };
257
+
258
+ export const extendCanvasDataWithMetricContentSize = canvasData => {
259
+ const b = { minX: Infinity, maxX: -Infinity, minY: Infinity, maxY: -Infinity };
260
+
261
+ const mergeRotated = (cx, cy, hw, hh, deg) => {
262
+ const rad = (deg * Math.PI) / 180;
263
+ const c = Math.cos(rad);
264
+ const s = Math.sin(rad);
265
+ for (const [dx, dy] of [
266
+ [-hw, -hh],
267
+ [hw, -hh],
268
+ [hw, hh],
269
+ [-hw, hh],
270
+ ]) {
271
+ const x = cx + dx * c - dy * s;
272
+ const y = cy + dx * s + dy * c;
273
+ b.minX = Math.min(b.minX, x);
274
+ b.maxX = Math.max(b.maxX, x);
275
+ b.minY = Math.min(b.minY, y);
276
+ b.maxY = Math.max(b.maxY, y);
277
+ }
278
+ };
279
+
280
+ const mergeAxisAligned = (cx, cy, hw, hh) => {
281
+ b.minX = Math.min(b.minX, cx - hw);
282
+ b.maxX = Math.max(b.maxX, cx + hw);
283
+ b.minY = Math.min(b.minY, cy - hh);
284
+ b.maxY = Math.max(b.maxY, cy + hh);
285
+ };
286
+
287
+ for (const object of canvasData.objects) {
288
+ if (!object.metric) continue;
289
+ const w = object.metric.width || 0;
290
+ const h = object.metric.height || 0;
291
+ const hw = w / 2;
292
+ const hh = h / 2;
293
+ const cx = object.metric.x || 0;
294
+ const cy = object.metric.y || 0;
295
+
296
+ if (typeof object.rotation === 'number' && object.rotation !== 0 && w && h) {
297
+ mergeRotated(cx, cy, hw, hh, object.rotation);
298
+ } else {
299
+ mergeAxisAligned(cx, cy, hw, hh);
300
+ }
301
+ }
302
+
303
+ if (!Number.isFinite(b.minX)) {
304
+ return canvasData;
305
+ }
306
+
307
+ return {
308
+ ...canvasData,
309
+ metricContentSize: {
310
+ width: Math.abs(b.maxX - b.minX),
311
+ height: Math.abs(b.maxY - b.minY),
312
+ },
313
+ };
314
+ };
@@ -254,11 +254,28 @@ export default class ConfiguratorService extends AbstractConfiguratorService {
254
254
  objectCount: get(canvasData, 'objects.length'),
255
255
  designProductionMethodIdentifier,
256
256
  colorAmount,
257
+ objects: this.getRoughDesignDataObjectDetails(designAreaData),
257
258
  };
258
259
  }
259
260
  return roughDesignData;
260
261
  }
261
262
 
263
+ getRoughDesignDataObjectDetails(designData) {
264
+ const includeMetricData = getConf('designer.includeMetricContentSize', false);
265
+ return get(designData, 'canvasData.objects', []).map(object => ({
266
+ uuid: object.uuid,
267
+ ...(includeMetricData
268
+ ? {
269
+ x: object.metric?.x || 0,
270
+ y: object.metric?.y || 0,
271
+ width: object.metric?.width || 0,
272
+ height: object.metric?.height || 0,
273
+ rotation: object.rotation || 0,
274
+ }
275
+ : {}),
276
+ }));
277
+ }
278
+
262
279
  //// <-- ACTIONS -->
263
280
 
264
281
  async saveConfiguration(configuration, configurationtype) {
@@ -40,7 +40,9 @@ import {
40
40
  removeVectorizeFromOperations,
41
41
  reduceNumberOfDistinctColorsBy,
42
42
  applyProductionMethodChangeToCanvasObjects,
43
+ extendCanvasDataWithMetricContentSize,
43
44
  } from '../Reducers/DesignData/Modifiers';
45
+
44
46
  import {
45
47
  clearDesignAreaSelection,
46
48
  selectDesignArea,
@@ -116,6 +118,7 @@ import { FontFaceRepository } from '../Modules/Designer/Utils/FontFaceRepository
116
118
  import { getAggregatedColorCount, isPlaceholderObject } from '../Reducers/DesignData/Selectors';
117
119
  import { expandVectorizeColorsMap } from '../Modules/Designer/Utils/ImageEditUtils';
118
120
  import { checkDesignElementRestrictionsWithRemovalCount } from '../Reducers/DesignArea/DesignElementSelectors';
121
+ import { getMissingViewBox } from '../Modules/Designer/Utils/SvgFixers';
119
122
 
120
123
  import placeholderLogo from '../../Resources/Images/designer_placeholder_logo.svg';
121
124
 
@@ -418,14 +421,17 @@ export const applySvgContentOperations = (original, preview, operations, svgCont
418
421
  const pixelHeight = Math.round(preview.height * scaleFactor);
419
422
  const isSvgUpload = vectorFormats.indexOf(original.format.toLowerCase()) !== -1;
420
423
  if (svgTag.indexOf('viewBox=') === -1) {
421
- if (isSvgUpload) {
422
- svgContent = svgContent.replace('<svg', `<svg viewBox="0 0 ${pixelWidth} ${pixelHeight}"`);
423
- } else {
424
- svgContent = svgContent.replace(
425
- '<svg',
426
- `<svg viewBox="0 0 ${preview.width} ${preview.height}"`
427
- );
428
- }
424
+ const fallbackSize = isSvgUpload
425
+ ? {
426
+ width: pixelWidth,
427
+ height: pixelHeight,
428
+ }
429
+ : {
430
+ width: preview.width,
431
+ height: preview.height,
432
+ };
433
+ const viewBox = getMissingViewBox(svgContent, fallbackSize);
434
+ svgContent = svgContent.replace('<svg', `<svg viewBox="${viewBox}"`);
429
435
  }
430
436
 
431
437
  if (svgTag.indexOf('height=') === -1) {
@@ -1494,7 +1500,16 @@ export default class DesignDataService {
1494
1500
  }
1495
1501
 
1496
1502
  setCanvasData(canvasData, targetDesignAreaIdentifier) {
1497
- Services.store.dispatch(setCanvasData(canvasData, targetDesignAreaIdentifier));
1503
+ const extendedCanvasData = this.getExtendedCanvasData(canvasData);
1504
+ Services.store.dispatch(setCanvasData(extendedCanvasData, targetDesignAreaIdentifier));
1505
+ }
1506
+
1507
+ getExtendedCanvasData(canvasData) {
1508
+ if (!getConf('designer.includeMetricContentSize', false) || !canvasData?.objects?.length) {
1509
+ return canvasData;
1510
+ }
1511
+
1512
+ return extendCanvasDataWithMetricContentSize(canvasData);
1498
1513
  }
1499
1514
 
1500
1515
  async setColorAmount(maxColorCount) {
@@ -98,7 +98,10 @@ describe('Services/ConfiguratorService', () => {
98
98
  designdata: {
99
99
  test_canvas: {
100
100
  canvasData: {
101
- objects: [{ type: 'Image' }, { type: 'Text' }],
101
+ objects: [
102
+ { type: 'Image', uuid: 'image_1' },
103
+ { type: 'Text', uuid: 'text_1' },
104
+ ],
102
105
  },
103
106
  colorAmount: 1,
104
107
  designProductionMethodIdentifier: 'print',
@@ -135,6 +138,7 @@ describe('Services/ConfiguratorService', () => {
135
138
  objectCount: 2,
136
139
  colorAmount: 1,
137
140
  designProductionMethodIdentifier: 'print',
141
+ objects: [{ uuid: 'image_1' }, { uuid: 'text_1' }],
138
142
  },
139
143
  },
140
144
  customdata: {
@@ -214,6 +214,7 @@ let applicationConfiguration = {
214
214
  dpi: 300, // the default canvas dpi as project specific option
215
215
  maxColorAmount: 10, // the default max number of colors in the colorizing feature
216
216
  allowedImageUploadFormats: 'jpg,jpeg,svg,png,pdf,bmp,tif,tiff,eps,ai,gif', // the image formats users can upload to designareas / designer items
217
+ includeMetricContentSize: false, // set true to include the metric content size in the design data
217
218
  },
218
219
 
219
220
  vectorizeImageQuality: 45000,