@configuratorware/configurator-admingui 1.36.2 → 1.37.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 (22) hide show
  1. package/Components/FormFragments/Text.js +2 -4
  2. package/Screens/ApiKeys/Containers/Edit.js +4 -2
  3. package/Screens/ApiKeys/Translations.js +6 -2
  4. package/Screens/Designer/SubScreens/DesignAreas/Components/MaskEditorField/MaskEditorCanvas.js +1 -1
  5. package/Screens/Designer/SubScreens/DesignAreas/Components/MaskEditorField/MaskEditorField.js +86 -11
  6. package/Screens/Designer/SubScreens/DesignAreas/Containers/Edit.js +36 -26
  7. package/Screens/Designer/SubScreens/DesignAreas/Containers/FormProductionMethods.js +6 -5
  8. package/Screens/Designer/SubScreens/DesignAreas/Translations.js +10 -4
  9. package/UIComponents/SelectField.js +1 -1
  10. package/Utils/Events/pointerEvent.js +6 -0
  11. package/package.json +2 -2
  12. package/src/Components/FormFragments/Text.js +0 -1
  13. package/src/Screens/ApiKeys/Containers/Edit.js +3 -1
  14. package/src/Screens/ApiKeys/Translations.js +4 -0
  15. package/src/Screens/Designer/SubScreens/DesignAreas/Components/MaskEditorField/MaskEditorCanvas.js +1 -1
  16. package/src/Screens/Designer/SubScreens/DesignAreas/Components/MaskEditorField/MaskEditorField.js +65 -9
  17. package/src/Screens/Designer/SubScreens/DesignAreas/Containers/Edit.js +28 -19
  18. package/src/Screens/Designer/SubScreens/DesignAreas/Containers/FormProductionMethods.js +29 -21
  19. package/src/Screens/Designer/SubScreens/DesignAreas/Translations.js +12 -2
  20. package/src/Screens/Designer/__tests__/__snapshots__/FormProductionMethods.test.js.snap +36 -39
  21. package/src/UIComponents/SelectField.js +3 -1
  22. package/src/Utils/Events/pointerEvent.js +5 -0
@@ -13,10 +13,8 @@ var _styles = _interopRequireDefault(require("./styles"));
13
13
 
14
14
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
15
15
 
16
- function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
17
-
18
16
  var text = function text(props) {
19
- return /*#__PURE__*/_react["default"].createElement(_TextField["default"], _defineProperty({
17
+ return /*#__PURE__*/_react["default"].createElement(_TextField["default"], {
20
18
  label: props.label,
21
19
  onChange: function onChange(evt) {
22
20
  props.onChange(props.name, evt.target.value === '' && props.emptyValue !== undefined ? props.emptyValue : evt.target.value);
@@ -32,7 +30,7 @@ var text = function text(props) {
32
30
  },
33
31
  inputProps: props.inputProps,
34
32
  rows: props.rows || 1
35
- }, "helperText", props.helperText));
33
+ });
36
34
  };
37
35
 
38
36
  text.defaultProps = {
@@ -112,11 +112,13 @@ var connectedTextField = (0, _connect["default"])(mapStateToProps, mapDispatchTo
112
112
  var formFields = [{
113
113
  name: 'email',
114
114
  label: 'E-mail',
115
- type: 'text'
115
+ type: 'text',
116
+ helperText: (0, _i18n.t)('apiKeys.mailHelperText')
116
117
  }, {
117
118
  name: 'username',
118
119
  label: 'User name',
119
- type: 'text'
120
+ type: 'text',
121
+ helperText: (0, _i18n.t)('apiKeys.userHelperText')
120
122
  }, {
121
123
  name: 'api_key',
122
124
  label: 'apikey',
@@ -10,7 +10,9 @@ require("../../App/i18n").use({
10
10
  apikey: 'API Key',
11
11
  'create new api key': 'neuen API key erstellen',
12
12
  apiKeys: {
13
- addButtonlabel: 'API Key hinzufügen'
13
+ addButtonlabel: 'API Key hinzufügen',
14
+ mailHelperText: 'Die E-Mail Adresse muss einzigartig und keinem bestehenden API Key oder adminarea Nutzer zugeordnet sein',
15
+ userHelperText: 'Der Nutzername muss einzigartig und keinem bestehenden Nutzer zugeordnet sein'
14
16
  }
15
17
  },
16
18
  en: {
@@ -18,7 +20,9 @@ require("../../App/i18n").use({
18
20
  apikey: 'API Key',
19
21
  'create new api key': 'create new api key',
20
22
  apiKeys: {
21
- addButtonlabel: 'Add API Key'
23
+ addButtonlabel: 'Add API Key',
24
+ mailHelperText: 'The e-mail address has to be unique and must not be used by an existing API key or adminarea user',
25
+ userHelperText: 'The username has to be unique and must not be used by an existing API key or adminarea user'
22
26
  }
23
27
  }
24
28
  }, true);
@@ -36,7 +36,7 @@ var calculateCanvasSize = function calculateCanvasSize(ratio
36
36
  /* width / height */
37
37
  ) {
38
38
  // experimental values for canvas margin (looks good with the dialog)
39
- var modalFitCorrectionY = 260;
39
+ var modalFitCorrectionY = 280;
40
40
  var modalFitCorrectionX = 144;
41
41
  var base = Math.min(window.innerWidth, window.innerHeight) - (window.innerWidth < window.innerHeight - modalFitCorrectionY ? modalFitCorrectionX : modalFitCorrectionY);
42
42
  var width = ratio < 1 ? base * ratio : base;
@@ -41,6 +41,8 @@ var _MaskEditorCanvas = require("./MaskEditorCanvas");
41
41
 
42
42
  var _maskTypes = require("../../Utils/maskTypes");
43
43
 
44
+ var _Typography = _interopRequireDefault(require("@material-ui/core/Typography/Typography"));
45
+
44
46
  var _excluded = ["onChange", "name"];
45
47
 
46
48
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
@@ -69,19 +71,45 @@ function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArra
69
71
 
70
72
  function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
71
73
 
72
- function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
73
-
74
- function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
75
-
76
74
  function _iterableToArrayLimit(arr, i) { var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"]; if (_i == null) return; var _arr = []; var _n = true; var _d = false; var _s, _e; try { for (_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }
77
75
 
78
76
  function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
79
77
 
78
+ function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e2) { throw _e2; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e3) { didErr = true; err = _e3; }, f: function f() { try { if (!normalCompletion && it["return"] != null) it["return"](); } finally { if (didErr) throw err; } } }; }
79
+
80
+ function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
81
+
82
+ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
83
+
80
84
  var maskTypeValues = Object.values(_maskTypes.maskTypes);
81
85
  var defaultValue = {
82
86
  maskType: (0, _first["default"])(maskTypeValues),
83
87
  maskData: {}
84
88
  };
89
+ var safeClipElements = ['ellipse', 'circle', 'rect', 'line', 'polygon', 'polyline', 'path'];
90
+
91
+ var getUnsafeElements = function getUnsafeElements(svgString) {
92
+ var matchedElements = svgString.matchAll(/<((?!svg)\w+)/g);
93
+ var unsafeElements = [];
94
+
95
+ var _iterator = _createForOfIteratorHelper(matchedElements),
96
+ _step;
97
+
98
+ try {
99
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
100
+ var match = _step.value;
101
+ var tagName = match[1];
102
+ !safeClipElements.includes(tagName) && !unsafeElements.includes(tagName) && unsafeElements.push(tagName);
103
+ }
104
+ } catch (err) {
105
+ _iterator.e(err);
106
+ } finally {
107
+ _iterator.f();
108
+ }
109
+
110
+ return unsafeElements;
111
+ };
112
+
85
113
  var UploadStatus = (0, _withStyles["default"])({
86
114
  uploadStatusContainer: {
87
115
  textAlign: 'right'
@@ -111,6 +139,16 @@ var styles = {
111
139
  }
112
140
  }
113
141
  };
142
+ var StyledDialog = (0, _withStyles["default"])({
143
+ dialogContentTextRoot: {
144
+ display: 'flex',
145
+ '& canvas': {
146
+ margin: 'auto',
147
+ maxHeight: '100%',
148
+ maxWidth: '100%'
149
+ }
150
+ }
151
+ })(_Dialog["default"]);
114
152
  var MaskEditorField = (0, _withStyles["default"])(styles)((0, _withFileUpload.withFileUpload)(function (_ref2) {
115
153
  var value = _ref2.value,
116
154
  _ref2$ratio = _ref2.ratio,
@@ -142,11 +180,21 @@ var MaskEditorField = (0, _withStyles["default"])(styles)((0, _withFileUpload.wi
142
180
  freeFormFile = _useState6[0],
143
181
  setFreeFormFile = _useState6[1];
144
182
 
145
- var _useState7 = (0, _react.useState)(false),
183
+ var _useState7 = (0, _react.useState)((initialValue === null || initialValue === void 0 ? void 0 : initialValue.maskDataUrl) || false),
146
184
  _useState8 = _slicedToArray(_useState7, 2),
147
185
  dataUrl = _useState8[0],
148
186
  setDataUrl = _useState8[1];
149
187
 
188
+ var _useState9 = (0, _react.useState)(false),
189
+ _useState10 = _slicedToArray(_useState9, 2),
190
+ embeddedImageError = _useState10[0],
191
+ setEmbeddedImageError = _useState10[1];
192
+
193
+ var _useState11 = (0, _react.useState)([]),
194
+ _useState12 = _slicedToArray(_useState11, 2),
195
+ unsafeElements = _useState12[0],
196
+ setUnsafeElements = _useState12[1];
197
+
150
198
  var maskType = currentValue.maskType,
151
199
  maskData = currentValue.maskData;
152
200
 
@@ -161,17 +209,33 @@ var MaskEditorField = (0, _withStyles["default"])(styles)((0, _withFileUpload.wi
161
209
  maskType: maskType,
162
210
  maskData: {}
163
211
  }));
212
+ resetState();
213
+ };
214
+
215
+ var resetState = function resetState() {
164
216
  setFreeFormFile(false);
165
- setDataUrl(false);
217
+ setDataUrl((initialValue === null || initialValue === void 0 ? void 0 : initialValue.maskDataUrl) || false);
218
+ setEmbeddedImageError(false);
166
219
  };
167
220
 
168
221
  var getFileDataUrl = function getFileDataUrl(file) {
222
+ setEmbeddedImageError(false);
223
+
169
224
  if (!file) {
170
225
  return;
171
226
  }
172
227
 
173
228
  var reader = new FileReader();
174
229
  reader.addEventListener('load', function () {
230
+ var svgString = atob(reader.result.replace(/data:image\/svg\+xml;base64,/, ''));
231
+ var embeddedImageIndex = svgString.search('<image');
232
+
233
+ if (embeddedImageIndex !== -1) {
234
+ setEmbeddedImageError(true);
235
+ return;
236
+ }
237
+
238
+ setUnsafeElements(getUnsafeElements(svgString));
175
239
  setDataUrl(reader.result);
176
240
  setFreeFormFile(file);
177
241
  clearMaskData();
@@ -179,6 +243,9 @@ var MaskEditorField = (0, _withStyles["default"])(styles)((0, _withFileUpload.wi
179
243
  reader.readAsDataURL(file);
180
244
  };
181
245
 
246
+ (0, _react.useEffect)(function () {
247
+ (initialValue === null || initialValue === void 0 ? void 0 : initialValue.maskDataUrl) && setDataUrl(initialValue.maskDataUrl);
248
+ }, [initialValue]);
182
249
  (0, _react.useEffect)(function () {
183
250
  // update the current value explicitly with the value prop (eg. the changes has been saved)
184
251
  if ((0, _size["default"])(value) > 0) {
@@ -188,8 +255,7 @@ var MaskEditorField = (0, _withStyles["default"])(styles)((0, _withFileUpload.wi
188
255
  (0, _react.useEffect)(function () {
189
256
  // reset internal state when showing the dialog
190
257
  if (showDialog) {
191
- setDataUrl(false);
192
- setFreeFormFile(false);
258
+ resetState();
193
259
 
194
260
  if ((0, _size["default"])(value) > 0) {
195
261
  setCurrentValue(initialValue);
@@ -204,9 +270,9 @@ var MaskEditorField = (0, _withStyles["default"])(styles)((0, _withFileUpload.wi
204
270
  return function (maskType) {
205
271
  var _maskTypes$none$maskT;
206
272
 
207
- return showDialog && (_maskTypes$none$maskT = {}, _defineProperty(_maskTypes$none$maskT, _maskTypes.maskTypes.none, false), _defineProperty(_maskTypes$none$maskT, _maskTypes.maskTypes.circle, _circle["default"]), _defineProperty(_maskTypes$none$maskT, _maskTypes.maskTypes.freeForm, initialValue.maskDataUrl || dataUrl || "".concat(freeFormUrl, "?v=").concat(Math.random())), _maskTypes$none$maskT)[maskType];
273
+ return showDialog && (_maskTypes$none$maskT = {}, _defineProperty(_maskTypes$none$maskT, _maskTypes.maskTypes.none, false), _defineProperty(_maskTypes$none$maskT, _maskTypes.maskTypes.circle, _circle["default"]), _defineProperty(_maskTypes$none$maskT, _maskTypes.maskTypes.freeForm, dataUrl || "".concat(freeFormUrl, "?v=").concat(Math.random())), _maskTypes$none$maskT)[maskType];
208
274
  };
209
- }, [freeFormUrl, dataUrl, showDialog, initialValue]);
275
+ }, [freeFormUrl, dataUrl, showDialog]);
210
276
  var getMaskDataRef = (0, _react.useRef)(function () {});
211
277
 
212
278
  var onOkClick = /*#__PURE__*/function () {
@@ -269,7 +335,7 @@ var MaskEditorField = (0, _withStyles["default"])(styles)((0, _withFileUpload.wi
269
335
  color: "primary"
270
336
  }),
271
337
  label: (0, _i18n.t)('maskEditor.checkboxLabel')
272
- })), /*#__PURE__*/_react["default"].createElement(_Dialog["default"], {
338
+ })), /*#__PURE__*/_react["default"].createElement(StyledDialog, {
273
339
  title: /*#__PURE__*/_react["default"].createElement(_react["default"].Fragment, null, /*#__PURE__*/_react["default"].createElement("div", {
274
340
  className: classes.inlineFormWrapper
275
341
  }, (0, _i18n.T)('mask editor'), /*#__PURE__*/_react["default"].createElement(_SelectField["default"], {
@@ -291,6 +357,15 @@ var MaskEditorField = (0, _withStyles["default"])(styles)((0, _withFileUpload.wi
291
357
  onChange: getFileDataUrl,
292
358
  src: getMaskSrc(maskType),
293
359
  fileName: freeFormFile ? freeFormFile.name : freeFormUrl.replace(/.*\/([^/]+)$/, '$1')
360
+ })), embeddedImageError && /*#__PURE__*/_react["default"].createElement(_Typography["default"], {
361
+ variant: "body1",
362
+ color: "error"
363
+ }, (0, _i18n.t)('maskEditor.embeddedImageError')), unsafeElements.length > 0 && /*#__PURE__*/_react["default"].createElement(_Typography["default"], {
364
+ variant: "body1",
365
+ color: "error"
366
+ }, (0, _i18n.T)('maskEditor.unsafeElementsError', {
367
+ unsafeElements: unsafeElements.join(', '),
368
+ safeClipElements: safeClipElements.join(', ')
294
369
  }))),
295
370
  open: showDialog,
296
371
  maxWidth: 'xl',
@@ -33,6 +33,8 @@ var _FormArray = _interopRequireDefault(require("../Components/FormArray"));
33
33
 
34
34
  var _i18n = require("../../../../../App/i18n");
35
35
 
36
+ var _lodash = _interopRequireDefault(require("lodash"));
37
+
36
38
  function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
37
39
 
38
40
  function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { "default": obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj["default"] = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
@@ -45,39 +47,47 @@ function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o =
45
47
 
46
48
  function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
47
49
 
48
- var getVariantsDefaultColors = function getVariantsDefaultColors(productionMethod, extendedItem) {
49
- var variantsDefaultColors = [];
50
+ var getItemDefaultColors = function getItemDefaultColors(productionMethod, extendedItem) {
51
+ var itemDefaultColors = [];
50
52
  var defaultColors = productionMethod.defaultColors;
51
53
 
52
54
  if ((0, _isObject["default"])(defaultColors)) {
53
- var _iterator = _createForOfIteratorHelper(extendedItem.children),
54
- _step;
55
-
56
- try {
57
- for (_iterator.s(); !(_step = _iterator.n()).done;) {
58
- var child = _step.value;
59
- var defaultColor = {
60
- variantIdentifier: child.identifier,
61
- variantTitle: child.title,
62
- colorPaletteIdentifier: null,
63
- colorIdentifier: null
64
- };
65
-
66
- if (defaultColors[child.identifier]) {
67
- defaultColor.colorPaletteIdentifier = Object.keys(defaultColors[child.identifier])[0];
68
- defaultColor.colorIdentifier = defaultColors[child.identifier][defaultColor.colorPaletteIdentifier];
55
+ if (_lodash["default"].isArray(_lodash["default"].get(extendedItem, 'children')) && extendedItem.children.length > 0) {
56
+ var _iterator = _createForOfIteratorHelper(extendedItem.children),
57
+ _step;
58
+
59
+ try {
60
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
61
+ var child = _step.value;
62
+ itemDefaultColors.push(getDefaultColor(child, defaultColors));
69
63
  }
70
-
71
- variantsDefaultColors.push(defaultColor);
64
+ } catch (err) {
65
+ _iterator.e(err);
66
+ } finally {
67
+ _iterator.f();
72
68
  }
73
- } catch (err) {
74
- _iterator.e(err);
75
- } finally {
76
- _iterator.f();
69
+ } else {
70
+ itemDefaultColors.push(getDefaultColor(extendedItem, defaultColors));
77
71
  }
78
72
  }
79
73
 
80
- return variantsDefaultColors;
74
+ return itemDefaultColors;
75
+ };
76
+
77
+ var getDefaultColor = function getDefaultColor(item, defaultColors) {
78
+ var defaultColor = {
79
+ variantIdentifier: item.identifier,
80
+ variantTitle: item.title || item.translated_title,
81
+ colorPaletteIdentifier: null,
82
+ colorIdentifier: null
83
+ };
84
+
85
+ if (defaultColors[item.identifier]) {
86
+ defaultColor.colorPaletteIdentifier = Object.keys(defaultColors[item.identifier])[0];
87
+ defaultColor.colorIdentifier = defaultColors[item.identifier][defaultColor.colorPaletteIdentifier];
88
+ }
89
+
90
+ return defaultColor;
81
91
  };
82
92
 
83
93
  var ConnectedFormComponent = (0, _reactRedux.connect)(function (state, ownProps) {
@@ -99,7 +109,7 @@ var ConnectedFormComponent = (0, _reactRedux.connect)(function (state, ownProps)
99
109
  var availableColorPalettes = colorPalettes.filter(function (palette) {
100
110
  return availableColorPaletteIds.indexOf(palette.id) !== -1;
101
111
  });
102
- var variantsDefaultColors = getVariantsDefaultColors(ownProps.data, extendedItem);
112
+ var variantsDefaultColors = getItemDefaultColors(ownProps.data, extendedItem);
103
113
  var errorData = (0, _get["default"])(state, 'dataBySource.designarea.error.response.data.errors');
104
114
  var index = (0, _findIndex["default"])(ownDesignProductionMethods, {
105
115
  id: ownProps.data.id
@@ -122,7 +122,8 @@ var styles = function styles() {
122
122
  engravingBackgroundColor: {
123
123
  display: 'flex',
124
124
  alignItems: 'baseline',
125
- marginBottom: '1em'
125
+ marginBottom: '1em',
126
+ marginLeft: '1em'
126
127
  },
127
128
  inputAlign: {
128
129
  textAlign: 'center'
@@ -555,7 +556,7 @@ var FormProductionMethods = /*#__PURE__*/function (_React$Component) {
555
556
 
556
557
  var currentValues = _lodash["default"].get(productionMethod, 'additionalData.engravingBackgroundColors', []);
557
558
 
558
- var availableItemIdentifiers = _lodash["default"].isArray(_lodash["default"].get(extendedItem, 'children')) ? extendedItem.children.map(function (_ref3) {
559
+ var availableItemIdentifiers = _lodash["default"].isArray(_lodash["default"].get(extendedItem, 'children')) && extendedItem.children.length > 0 ? extendedItem.children.map(function (_ref3) {
559
560
  var identifier = _ref3.identifier;
560
561
  return identifier;
561
562
  }) : [extendedItem.identifier];
@@ -879,7 +880,7 @@ var FormProductionMethods = /*#__PURE__*/function (_React$Component) {
879
880
  })), /*#__PURE__*/_react["default"].createElement(_Grid["default"], {
880
881
  item: true,
881
882
  xs: 12
882
- }, isEngravingEffect(productionMethod) && engravingBackgroundColors.map(function (item) {
883
+ }, isEngravingEffect(productionMethod) && /*#__PURE__*/_react["default"].createElement(_react["default"].Fragment, null, /*#__PURE__*/_react["default"].createElement(_Typography["default"], null, (0, _i18n.t)('EngravingBackgroundColor')), engravingBackgroundColors.map(function (item) {
883
884
  return /*#__PURE__*/_react["default"].createElement("div", {
884
885
  key: item.itemIdentifier,
885
886
  className: classes.engravingBackgroundColor
@@ -890,13 +891,13 @@ var FormProductionMethods = /*#__PURE__*/function (_React$Component) {
890
891
  component: "legend"
891
892
  }, item.itemIdentifier, ":"), /*#__PURE__*/_react["default"].createElement(_TextField["default"], {
892
893
  key: item.itemIdentifier,
893
- placeholder: (0, _i18n.t)('EngravingBackgroundColor'),
894
+ placeholder: (0, _i18n.t)('EngravingBackgroundColorPlaceholder'),
894
895
  onChange: _this4.onChangeEngravingBackgroundColor(item),
895
896
  value: item.colorHex,
896
897
  style: styles.input,
897
898
  className: classes.inputAlign
898
899
  }));
899
- }))), /*#__PURE__*/_react["default"].createElement(_Grid["default"], {
900
+ })))), /*#__PURE__*/_react["default"].createElement(_Grid["default"], {
900
901
  item: true,
901
902
  xs: 12,
902
903
  className: classes.checkboxGrid
@@ -7,7 +7,8 @@ require("../../../../App/i18n").use({
7
7
  isDefault: 'default',
8
8
  allowBulkNames: 'Allow bulk names',
9
9
  varyingDefaultColors: 'Varying Default Color',
10
- EngravingBackgroundColor: 'Color value',
10
+ EngravingBackgroundColorPlaceholder: 'Color value',
11
+ EngravingBackgroundColor: 'Engraving color',
11
12
  errors: {
12
13
  noProdMethodLeft: 'No more production methods exist.'
13
14
  },
@@ -42,7 +43,9 @@ require("../../../../App/i18n").use({
42
43
  selectFile: 'Select SVG file',
43
44
  uploadAndSave: 'Upload and save',
44
45
  uploadFailed: 'Failed to upload the SVG',
45
- uploadInProgress: 'Upload in progress, please wait...'
46
+ uploadInProgress: 'Upload in progress, please wait...',
47
+ embeddedImageError: 'The provided file contains an embedded raster graphic. Please use plain / vector only svg files.',
48
+ unsafeElementsError: 'The provided file contains elements that are not safe to be used for clipping. Please consider using only the following safe elements: %{safeClipElements}'
46
49
  },
47
50
  validation: {
48
51
  designProductionMethod: {
@@ -73,7 +76,8 @@ require("../../../../App/i18n").use({
73
76
  isDefault: 'Standard',
74
77
  allowBulkNames: 'Einzelnamen erlauben',
75
78
  varyingDefaultColors: 'abweichende Standardfarbe',
76
- EngravingBackgroundColor: 'Farbwert',
79
+ EngravingBackgroundColorPlaceholder: 'Farbwert',
80
+ EngravingBackgroundColor: 'Gravurfarbe',
77
81
  errors: {
78
82
  noProdMethodLeft: 'Keine weiteren Produktionsverfahren vorhanden.'
79
83
  },
@@ -102,7 +106,9 @@ require("../../../../App/i18n").use({
102
106
  selectFile: 'SVG Datei auswählen',
103
107
  uploadAndSave: 'Hochladen und speichern',
104
108
  uploadFailed: 'Fehler beim Hochladen von SVG',
105
- uploadInProgress: 'Upload läuft, bitte warten...'
109
+ uploadInProgress: 'Upload läuft, bitte warten...',
110
+ embeddedImageError: 'Die gewählte Datei enthält eingebettete Pixelgrafiken und kann nicht verwendet werden. Bitte wähle eine Datei, die ausschließlich Vektordaten enthält.',
111
+ unsafeElementsError: 'Die verwendete Datei beinhaltet Elemente, die für das Beschneiden nicht verwendet werden können. Bitte verwenden Sie nur folgende Elemente: %{safeClipElements}'
106
112
  },
107
113
  validation: {
108
114
  designProductionMethod: {
@@ -113,7 +113,7 @@ var UISelectField = /*#__PURE__*/function (_React$Component) {
113
113
  }, placeholder && /*#__PURE__*/_react["default"].createElement(_MenuItem["default"], {
114
114
  value: placeholderValue,
115
115
  disabled: disablePlaceholder
116
- }, placeholder), children), /*#__PURE__*/_react["default"].createElement(_FormHelperText["default"], null, error));
116
+ }, placeholder), children), error && /*#__PURE__*/_react["default"].createElement(_FormHelperText["default"], null, error));
117
117
  }
118
118
  }]);
119
119
 
@@ -31,6 +31,12 @@ var getPointFromPointerEvent = function getPointFromPointerEvent(evt) {
31
31
  y -= top;
32
32
  }
33
33
 
34
+ if (relativeTo.width) {
35
+ var scaling = relativeTo.getBoundingClientRect().width / relativeTo.width;
36
+ x *= 1 / scaling;
37
+ y *= 1 / scaling;
38
+ }
39
+
34
40
  return {
35
41
  x: x,
36
42
  y: y
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@configuratorware/configurator-admingui",
3
- "version": "1.36.2",
3
+ "version": "1.37.1",
4
4
  "license": "UNLICENSED",
5
5
  "private": false,
6
6
  "dependencies": {
@@ -29,7 +29,7 @@
29
29
  "react-redux-i18n": "^1.9.3",
30
30
  "react-router": "^3.2.6",
31
31
  "react-sortable-hoc": "^1.11.0",
32
- "redhotmagma-visualization": "1.36.2",
32
+ "redhotmagma-visualization": "1.37.1",
33
33
  "redux": "^4.1.0",
34
34
  "redux-logger": "^3.0.6",
35
35
  "redux-persist": "^5.10.0",
@@ -25,7 +25,6 @@ const text = props => (
25
25
  }}
26
26
  inputProps={props.inputProps}
27
27
  rows={props.rows || 1}
28
- helperText={props.helperText}
29
28
  />
30
29
  );
31
30
 
@@ -2,7 +2,7 @@ import React, { useState } from 'react';
2
2
  import connect from 'react-redux/es/connect/connect';
3
3
  import { setFieldData, postData, refreshListAction, APIUSER_REDUCER_NAME } from '../Reducers/Actions';
4
4
  import { get } from 'lodash';
5
- import { T } from '../../../App/i18n';
5
+ import { T, t } from '../../../App/i18n';
6
6
  import generateConnectedEdit from '../../../Components/DefaultConnectedForm';
7
7
  import Text from '../../../Components/FormFragments/Text';
8
8
  import Button from '@material-ui/core/Button/Button';
@@ -41,11 +41,13 @@ const formFields = [
41
41
  name: 'email',
42
42
  label: 'E-mail',
43
43
  type: 'text',
44
+ helperText: t('apiKeys.mailHelperText')
44
45
  },
45
46
  {
46
47
  name: 'username',
47
48
  label: 'User name',
48
49
  type: 'text',
50
+ helperText: t('apiKeys.userHelperText')
49
51
  },
50
52
  {
51
53
  name: 'api_key',
@@ -10,6 +10,8 @@ require('../../App/i18n').use(
10
10
  'create new api key': 'neuen API key erstellen',
11
11
  apiKeys: {
12
12
  addButtonlabel: 'API Key hinzufügen',
13
+ mailHelperText: 'Die E-Mail Adresse muss einzigartig und keinem bestehenden API Key oder adminarea Nutzer zugeordnet sein',
14
+ userHelperText: 'Der Nutzername muss einzigartig und keinem bestehenden Nutzer zugeordnet sein',
13
15
  },
14
16
  },
15
17
  en: {
@@ -18,6 +20,8 @@ require('../../App/i18n').use(
18
20
  'create new api key': 'create new api key',
19
21
  apiKeys: {
20
22
  addButtonlabel: 'Add API Key',
23
+ mailHelperText: 'The e-mail address has to be unique and must not be used by an existing API key or adminarea user',
24
+ userHelperText: 'The username has to be unique and must not be used by an existing API key or adminarea user',
21
25
  },
22
26
  },
23
27
  },
@@ -17,7 +17,7 @@ const styles = {
17
17
 
18
18
  const calculateCanvasSize = (ratio /* width / height */) => {
19
19
  // experimental values for canvas margin (looks good with the dialog)
20
- const modalFitCorrectionY = 260;
20
+ const modalFitCorrectionY = 280;
21
21
  const modalFitCorrectionX = 144;
22
22
  const base =
23
23
  Math.min(window.innerWidth, window.innerHeight) -
@@ -16,6 +16,7 @@ import { withFileUpload } from './withFileUpload';
16
16
  import InlineFileInput from './InlineFileInput';
17
17
  import { MaskEditorCanvas } from './MaskEditorCanvas';
18
18
  import { maskTypes } from '../../Utils/maskTypes';
19
+ import Typography from '@material-ui/core/Typography/Typography';
19
20
 
20
21
  const maskTypeValues = Object.values(maskTypes);
21
22
 
@@ -24,6 +25,20 @@ const defaultValue = {
24
25
  maskData: {},
25
26
  };
26
27
 
28
+ const safeClipElements = ['ellipse', 'circle', 'rect', 'line', 'polygon', 'polyline', 'path'];
29
+
30
+ const getUnsafeElements = svgString => {
31
+ const matchedElements = svgString.matchAll(/<((?!svg)\w+)/g);
32
+ const unsafeElements = [];
33
+ for (const match of matchedElements) {
34
+ const tagName = match[1];
35
+ !safeClipElements.includes(tagName) &&
36
+ !unsafeElements.includes(tagName) &&
37
+ unsafeElements.push(tagName);
38
+ }
39
+ return unsafeElements;
40
+ };
41
+
27
42
  const UploadStatus = withStyles({
28
43
  uploadStatusContainer: {
29
44
  textAlign: 'right',
@@ -57,6 +72,17 @@ const styles = {
57
72
  },
58
73
  };
59
74
 
75
+ const StyledDialog = withStyles({
76
+ dialogContentTextRoot: {
77
+ display: 'flex',
78
+ '& canvas': {
79
+ margin: 'auto',
80
+ maxHeight: '100%',
81
+ maxWidth: '100%',
82
+ },
83
+ },
84
+ })(Dialog);
85
+
60
86
  export const MaskEditorField = withStyles(styles)(
61
87
  withFileUpload(
62
88
  ({
@@ -77,18 +103,26 @@ export const MaskEditorField = withStyles(styles)(
77
103
  const [showDialog, toggleDialog] = useState(false);
78
104
  const [currentValue, setCurrentValue] = useState(initialValue);
79
105
  const [freeFormFile, setFreeFormFile] = useState(false);
80
- const [dataUrl, setDataUrl] = useState(false);
106
+ const [dataUrl, setDataUrl] = useState(initialValue?.maskDataUrl || false);
107
+ const [embeddedImageError, setEmbeddedImageError] = useState(false);
108
+ const [unsafeElements, setUnsafeElements] = useState([]);
81
109
 
82
110
  const { maskType, maskData } = currentValue;
83
111
 
84
112
  const clearMaskData = () => setCurrentValue({ ...currentValue, maskData: {} });
85
113
  const setMaskType = maskType => {
86
114
  setCurrentValue({ ...currentValue, maskType, maskData: {} });
115
+ resetState();
116
+ };
117
+
118
+ const resetState = () => {
87
119
  setFreeFormFile(false);
88
- setDataUrl(false);
120
+ setDataUrl(initialValue?.maskDataUrl || false);
121
+ setEmbeddedImageError(false);
89
122
  };
90
123
 
91
124
  const getFileDataUrl = file => {
125
+ setEmbeddedImageError(false);
92
126
  if (!file) {
93
127
  return;
94
128
  }
@@ -96,6 +130,13 @@ export const MaskEditorField = withStyles(styles)(
96
130
  reader.addEventListener(
97
131
  'load',
98
132
  function() {
133
+ const svgString = atob(reader.result.replace(/data:image\/svg\+xml;base64,/, ''));
134
+ const embeddedImageIndex = svgString.search('<image');
135
+ if (embeddedImageIndex !== -1) {
136
+ setEmbeddedImageError(true);
137
+ return;
138
+ }
139
+ setUnsafeElements(getUnsafeElements(svgString));
99
140
  setDataUrl(reader.result);
100
141
  setFreeFormFile(file);
101
142
  clearMaskData();
@@ -105,6 +146,10 @@ export const MaskEditorField = withStyles(styles)(
105
146
  reader.readAsDataURL(file);
106
147
  };
107
148
 
149
+ useEffect(() => {
150
+ initialValue?.maskDataUrl && setDataUrl(initialValue.maskDataUrl);
151
+ }, [initialValue]);
152
+
108
153
  useEffect(() => {
109
154
  // update the current value explicitly with the value prop (eg. the changes has been saved)
110
155
  if (size(value) > 0) {
@@ -115,8 +160,7 @@ export const MaskEditorField = withStyles(styles)(
115
160
  useEffect(() => {
116
161
  // reset internal state when showing the dialog
117
162
  if (showDialog) {
118
- setDataUrl(false);
119
- setFreeFormFile(false);
163
+ resetState();
120
164
  if (size(value) > 0) {
121
165
  setCurrentValue(initialValue);
122
166
  }
@@ -134,10 +178,9 @@ export const MaskEditorField = withStyles(styles)(
134
178
  {
135
179
  [maskTypes.none]: false,
136
180
  [maskTypes.circle]: circleMask,
137
- [maskTypes.freeForm]:
138
- initialValue.maskDataUrl || dataUrl || `${freeFormUrl}?v=${Math.random()}`,
181
+ [maskTypes.freeForm]: dataUrl || `${freeFormUrl}?v=${Math.random()}`,
139
182
  }[maskType],
140
- [freeFormUrl, dataUrl, showDialog, initialValue]
183
+ [freeFormUrl, dataUrl, showDialog]
141
184
  );
142
185
 
143
186
  const getMaskDataRef = useRef(() => {});
@@ -180,7 +223,7 @@ export const MaskEditorField = withStyles(styles)(
180
223
  label={t('maskEditor.checkboxLabel')}
181
224
  />
182
225
  </Grid>
183
- <Dialog
226
+ <StyledDialog
184
227
  title={
185
228
  <React.Fragment>
186
229
  <div className={classes.inlineFormWrapper}>
@@ -213,6 +256,19 @@ export const MaskEditorField = withStyles(styles)(
213
256
  />
214
257
  )}
215
258
  </div>
259
+ {embeddedImageError && (
260
+ <Typography variant="body1" color="error">
261
+ {t('maskEditor.embeddedImageError')}
262
+ </Typography>
263
+ )}
264
+ {unsafeElements.length > 0 && (
265
+ <Typography variant="body1" color="error">
266
+ {T('maskEditor.unsafeElementsError', {
267
+ unsafeElements: unsafeElements.join(', '),
268
+ safeClipElements: safeClipElements.join(', '),
269
+ })}
270
+ </Typography>
271
+ )}
216
272
  </React.Fragment>
217
273
  }
218
274
  open={showDialog}
@@ -242,7 +298,7 @@ export const MaskEditorField = withStyles(styles)(
242
298
  />
243
299
 
244
300
  <UploadStatus uploadStatus={uploadStatus} />
245
- </Dialog>
301
+ </StyledDialog>
246
302
  </React.Fragment>
247
303
  );
248
304
  }
@@ -12,34 +12,43 @@ import FormProductionMethods from './FormProductionMethods';
12
12
  import { DesignAreaMaskEditorField } from './ConnectedMaskEditorField';
13
13
  import FormArray from '../Components/FormArray';
14
14
  import { t } from '../../../../../App/i18n';
15
+ import _ from 'lodash';
15
16
 
16
- const getVariantsDefaultColors = (productionMethod, extendedItem) => {
17
- const variantsDefaultColors = [];
17
+ const getItemDefaultColors = (productionMethod, extendedItem) => {
18
+ const itemDefaultColors = [];
18
19
 
19
20
  const { defaultColors } = productionMethod;
20
-
21
21
  if (isObject(defaultColors)) {
22
- for (const child of extendedItem.children) {
23
- const defaultColor = {
24
- variantIdentifier: child.identifier,
25
- variantTitle: child.title,
26
- colorPaletteIdentifier: null,
27
- colorIdentifier: null,
28
- };
29
-
30
- if (defaultColors[child.identifier]) {
31
- defaultColor.colorPaletteIdentifier = Object.keys(defaultColors[child.identifier])[0];
32
- defaultColor.colorIdentifier =
33
- defaultColors[child.identifier][defaultColor.colorPaletteIdentifier];
22
+ if (_.isArray(_.get(extendedItem, 'children')) && extendedItem.children.length > 0) {
23
+ for (const child of extendedItem.children) {
24
+ itemDefaultColors.push(getDefaultColor(child, defaultColors));
34
25
  }
35
-
36
- variantsDefaultColors.push(defaultColor);
26
+ }
27
+ else {
28
+ itemDefaultColors.push(getDefaultColor(extendedItem, defaultColors));
37
29
  }
38
30
  }
39
31
 
40
- return variantsDefaultColors;
32
+ return itemDefaultColors;
41
33
  };
42
34
 
35
+ const getDefaultColor = (item, defaultColors) => {
36
+ const defaultColor = {
37
+ variantIdentifier: item.identifier,
38
+ variantTitle: item.title || item.translated_title,
39
+ colorPaletteIdentifier: null,
40
+ colorIdentifier: null,
41
+ };
42
+
43
+ if (defaultColors[item.identifier]) {
44
+ defaultColor.colorPaletteIdentifier = Object.keys(defaultColors[item.identifier])[0];
45
+ defaultColor.colorIdentifier =
46
+ defaultColors[item.identifier][defaultColor.colorPaletteIdentifier];
47
+ }
48
+
49
+ return defaultColor;
50
+ }
51
+
43
52
  const ConnectedFormComponent = connect(
44
53
  (state, ownProps) => {
45
54
  const itemId = get(state, 'designAreasData.data.item.value.id');
@@ -61,7 +70,7 @@ const ConnectedFormComponent = connect(
61
70
  const availableColorPalettes = colorPalettes.filter(
62
71
  palette => availableColorPaletteIds.indexOf(palette.id) !== -1
63
72
  );
64
- const variantsDefaultColors = getVariantsDefaultColors(ownProps.data, extendedItem);
73
+ const variantsDefaultColors = getItemDefaultColors(ownProps.data, extendedItem);
65
74
 
66
75
  const errorData = get(state, 'dataBySource.designarea.error.response.data.errors');
67
76
  const index = findIndex(ownDesignProductionMethods, { id: ownProps.data.id });
@@ -40,6 +40,7 @@ const styles = () => ({
40
40
  display: 'flex',
41
41
  alignItems: 'baseline',
42
42
  marginBottom: '1em',
43
+ marginLeft: '1em',
43
44
  },
44
45
  inputAlign: {
45
46
  textAlign: 'center',
@@ -323,7 +324,7 @@ class FormProductionMethods extends React.Component {
323
324
  return [];
324
325
  }
325
326
  const currentValues = _.get(productionMethod, 'additionalData.engravingBackgroundColors', []);
326
- const availableItemIdentifiers = _.isArray(_.get(extendedItem, 'children'))
327
+ const availableItemIdentifiers = (_.isArray(_.get(extendedItem, 'children')) && extendedItem.children.length > 0)
327
328
  ? extendedItem.children.map(({ identifier }) => identifier)
328
329
  : [extendedItem.identifier];
329
330
  const result = [];
@@ -434,7 +435,6 @@ class FormProductionMethods extends React.Component {
434
435
  onColorPalettesDialogSelectClick = (value, colorIdentifier, colorPaletteIdentifier) => {
435
436
  const { openedVariantsDefaultColor } = this.state;
436
437
  const { data } = this.props;
437
-
438
438
  const newData = {
439
439
  ...data,
440
440
  defaultColors: {
@@ -744,25 +744,33 @@ class FormProductionMethods extends React.Component {
744
744
  ))}
745
745
  </UISelectField>
746
746
  <Grid item xs={12}>
747
- {isEngravingEffect(productionMethod) &&
748
- engravingBackgroundColors.map(item => (
749
- <div
750
- key={item.itemIdentifier}
751
- className={classes.engravingBackgroundColor}
752
- >
753
- <FormLabel classes={{ root: classes.InputLabel }} component="legend">
754
- {item.itemIdentifier}:
755
- </FormLabel>
756
- <TextField
757
- key={item.itemIdentifier}
758
- placeholder={t('EngravingBackgroundColor')}
759
- onChange={this.onChangeEngravingBackgroundColor(item)}
760
- value={item.colorHex}
761
- style={styles.input}
762
- className={classes.inputAlign}
763
- />
764
- </div>
765
- ))}
747
+ {isEngravingEffect(productionMethod) && (
748
+ <React.Fragment>
749
+ <Typography>
750
+ {t('EngravingBackgroundColor')}
751
+ </Typography>
752
+ {
753
+ engravingBackgroundColors.map(item => (
754
+ <div
755
+ key={item.itemIdentifier}
756
+ className={classes.engravingBackgroundColor}
757
+ >
758
+ <FormLabel classes={{ root: classes.InputLabel }} component="legend">
759
+ {item.itemIdentifier}:
760
+ </FormLabel>
761
+ <TextField
762
+ key={item.itemIdentifier}
763
+ placeholder={t('EngravingBackgroundColorPlaceholder')}
764
+ onChange={this.onChangeEngravingBackgroundColor(item)}
765
+ value={item.colorHex}
766
+ style={styles.input}
767
+ className={classes.inputAlign}
768
+ />
769
+ </div>
770
+ ))
771
+ }
772
+ </React.Fragment>
773
+ )}
766
774
  </Grid>
767
775
  </Grid>
768
776
  <Grid item xs={12} className={classes.checkboxGrid}>
@@ -6,7 +6,8 @@ require('../../../../App/i18n').use(
6
6
  isDefault: 'default',
7
7
  allowBulkNames: 'Allow bulk names',
8
8
  varyingDefaultColors: 'Varying Default Color',
9
- EngravingBackgroundColor: 'Color value',
9
+ EngravingBackgroundColorPlaceholder: 'Color value',
10
+ EngravingBackgroundColor: 'Engraving color',
10
11
  errors: {
11
12
  noProdMethodLeft: 'No more production methods exist.',
12
13
  },
@@ -43,6 +44,10 @@ require('../../../../App/i18n').use(
43
44
  uploadAndSave: 'Upload and save',
44
45
  uploadFailed: 'Failed to upload the SVG',
45
46
  uploadInProgress: 'Upload in progress, please wait...',
47
+ embeddedImageError:
48
+ 'The provided file contains an embedded raster graphic. Please use plain / vector only svg files.',
49
+ unsafeElementsError:
50
+ 'The provided file contains elements that are not safe to be used for clipping. Please consider using only the following safe elements: %{safeClipElements}',
46
51
  },
47
52
  validation: {
48
53
  designProductionMethod: {
@@ -75,7 +80,8 @@ require('../../../../App/i18n').use(
75
80
  isDefault: 'Standard',
76
81
  allowBulkNames: 'Einzelnamen erlauben',
77
82
  varyingDefaultColors: 'abweichende Standardfarbe',
78
- EngravingBackgroundColor: 'Farbwert',
83
+ EngravingBackgroundColorPlaceholder: 'Farbwert',
84
+ EngravingBackgroundColor: 'Gravurfarbe',
79
85
  errors: {
80
86
  noProdMethodLeft: 'Keine weiteren Produktionsverfahren vorhanden.',
81
87
  },
@@ -106,6 +112,10 @@ require('../../../../App/i18n').use(
106
112
  uploadAndSave: 'Hochladen und speichern',
107
113
  uploadFailed: 'Fehler beim Hochladen von SVG',
108
114
  uploadInProgress: 'Upload läuft, bitte warten...',
115
+ embeddedImageError:
116
+ 'Die gewählte Datei enthält eingebettete Pixelgrafiken und kann nicht verwendet werden. Bitte wähle eine Datei, die ausschließlich Vektordaten enthält.',
117
+ unsafeElementsError:
118
+ 'Die verwendete Datei beinhaltet Elemente, die für das Beschneiden nicht verwendet werden können. Bitte verwenden Sie nur folgende Elemente: %{safeClipElements}',
109
119
  },
110
120
  validation: {
111
121
  designProductionMethod: {
@@ -51,9 +51,6 @@ exports[`Unit- FormProductionMethods renders correctly 1`] = `
51
51
  </svg>
52
52
  </div>
53
53
  </div>
54
- <p
55
- class="MuiFormHelperText-root-197 MuiFormHelperText-filled-203"
56
- />
57
54
  </div>
58
55
  <div
59
56
  class="MuiGrid-item-44 MuiGrid-grid-xs-12-83"
@@ -63,13 +60,13 @@ exports[`Unit- FormProductionMethods renders correctly 1`] = `
63
60
  class="MuiGrid-item-44 MuiGrid-grid-xs-12-83 FormProductionMethods-checkboxGrid-1"
64
61
  >
65
62
  <label
66
- class="MuiFormControlLabel-root-205"
63
+ class="MuiFormControlLabel-root-197"
67
64
  >
68
65
  <span
69
- class="MuiButtonBase-root-227 MuiIconButton-root-221 MuiPrivateSwitchBase-root-217 MuiCheckbox-root-211 MuiCheckbox-colorPrimary-215"
66
+ class="MuiButtonBase-root-219 MuiIconButton-root-213 MuiPrivateSwitchBase-root-209 MuiCheckbox-root-203 MuiCheckbox-colorPrimary-207"
70
67
  >
71
68
  <span
72
- class="MuiIconButton-label-226"
69
+ class="MuiIconButton-label-218"
73
70
  >
74
71
  <svg
75
72
  aria-hidden="true"
@@ -83,7 +80,7 @@ exports[`Unit- FormProductionMethods renders correctly 1`] = `
83
80
  />
84
81
  </svg>
85
82
  <input
86
- class="MuiPrivateSwitchBase-input-220"
83
+ class="MuiPrivateSwitchBase-input-212"
87
84
  data-indeterminate="false"
88
85
  type="checkbox"
89
86
  value="varyingDimensions"
@@ -91,7 +88,7 @@ exports[`Unit- FormProductionMethods renders correctly 1`] = `
91
88
  </span>
92
89
  </span>
93
90
  <span
94
- class="MuiTypography-root-230 MuiTypography-body1-239 MuiFormControlLabel-label-210"
91
+ class="MuiTypography-root-222 MuiTypography-body1-231 MuiFormControlLabel-label-202"
95
92
  >
96
93
  varyingDimensions
97
94
  </span>
@@ -101,13 +98,13 @@ exports[`Unit- FormProductionMethods renders correctly 1`] = `
101
98
  class="MuiGrid-item-44 MuiGrid-grid-xs-12-83 FormProductionMethods-checkboxGrid-1"
102
99
  >
103
100
  <label
104
- class="MuiFormControlLabel-root-205"
101
+ class="MuiFormControlLabel-root-197"
105
102
  >
106
103
  <span
107
- class="MuiButtonBase-root-227 MuiIconButton-root-221 MuiPrivateSwitchBase-root-217 MuiCheckbox-root-211 MuiCheckbox-colorPrimary-215"
104
+ class="MuiButtonBase-root-219 MuiIconButton-root-213 MuiPrivateSwitchBase-root-209 MuiCheckbox-root-203 MuiCheckbox-colorPrimary-207"
108
105
  >
109
106
  <span
110
- class="MuiIconButton-label-226"
107
+ class="MuiIconButton-label-218"
111
108
  >
112
109
  <svg
113
110
  aria-hidden="true"
@@ -121,7 +118,7 @@ exports[`Unit- FormProductionMethods renders correctly 1`] = `
121
118
  />
122
119
  </svg>
123
120
  <input
124
- class="MuiPrivateSwitchBase-input-220"
121
+ class="MuiPrivateSwitchBase-input-212"
125
122
  data-indeterminate="false"
126
123
  type="checkbox"
127
124
  value="allowBulkNames"
@@ -129,7 +126,7 @@ exports[`Unit- FormProductionMethods renders correctly 1`] = `
129
126
  </span>
130
127
  </span>
131
128
  <span
132
- class="MuiTypography-root-230 MuiTypography-body1-239 MuiFormControlLabel-label-210"
129
+ class="MuiTypography-root-222 MuiTypography-body1-231 MuiFormControlLabel-label-202"
133
130
  >
134
131
  allowBulkNames
135
132
  </span>
@@ -139,13 +136,13 @@ exports[`Unit- FormProductionMethods renders correctly 1`] = `
139
136
  class="MuiGrid-item-44 MuiGrid-grid-xs-12-83 FormProductionMethods-checkboxGrid-1"
140
137
  >
141
138
  <label
142
- class="MuiFormControlLabel-root-205"
139
+ class="MuiFormControlLabel-root-197"
143
140
  >
144
141
  <span
145
- class="MuiButtonBase-root-227 MuiIconButton-root-221 MuiPrivateSwitchBase-root-217 MuiCheckbox-root-211 MuiCheckbox-colorPrimary-215"
142
+ class="MuiButtonBase-root-219 MuiIconButton-root-213 MuiPrivateSwitchBase-root-209 MuiCheckbox-root-203 MuiCheckbox-colorPrimary-207"
146
143
  >
147
144
  <span
148
- class="MuiIconButton-label-226"
145
+ class="MuiIconButton-label-218"
149
146
  >
150
147
  <svg
151
148
  aria-hidden="true"
@@ -159,7 +156,7 @@ exports[`Unit- FormProductionMethods renders correctly 1`] = `
159
156
  />
160
157
  </svg>
161
158
  <input
162
- class="MuiPrivateSwitchBase-input-220"
159
+ class="MuiPrivateSwitchBase-input-212"
163
160
  data-indeterminate="false"
164
161
  type="checkbox"
165
162
  value="isDefault"
@@ -167,7 +164,7 @@ exports[`Unit- FormProductionMethods renders correctly 1`] = `
167
164
  </span>
168
165
  </span>
169
166
  <span
170
- class="MuiTypography-root-230 MuiTypography-body1-239 MuiFormControlLabel-label-210"
167
+ class="MuiTypography-root-222 MuiTypography-body1-231 MuiFormControlLabel-label-202"
171
168
  >
172
169
  isDefault
173
170
  </span>
@@ -177,13 +174,13 @@ exports[`Unit- FormProductionMethods renders correctly 1`] = `
177
174
  class="MuiGrid-item-44 MuiGrid-grid-xs-12-83 FormProductionMethods-checkboxGrid-1"
178
175
  >
179
176
  <label
180
- class="MuiFormControlLabel-root-205"
177
+ class="MuiFormControlLabel-root-197"
181
178
  >
182
179
  <span
183
- class="MuiButtonBase-root-227 MuiIconButton-root-221 MuiPrivateSwitchBase-root-217 MuiCheckbox-root-211 MuiCheckbox-colorPrimary-215"
180
+ class="MuiButtonBase-root-219 MuiIconButton-root-213 MuiPrivateSwitchBase-root-209 MuiCheckbox-root-203 MuiCheckbox-colorPrimary-207"
184
181
  >
185
182
  <span
186
- class="MuiIconButton-label-226"
183
+ class="MuiIconButton-label-218"
187
184
  >
188
185
  <svg
189
186
  aria-hidden="true"
@@ -197,7 +194,7 @@ exports[`Unit- FormProductionMethods renders correctly 1`] = `
197
194
  />
198
195
  </svg>
199
196
  <input
200
- class="MuiPrivateSwitchBase-input-220"
197
+ class="MuiPrivateSwitchBase-input-212"
201
198
  data-indeterminate="false"
202
199
  type="checkbox"
203
200
  value="varyingDefaultColors"
@@ -205,7 +202,7 @@ exports[`Unit- FormProductionMethods renders correctly 1`] = `
205
202
  </span>
206
203
  </span>
207
204
  <span
208
- class="MuiTypography-root-230 MuiTypography-body1-239 MuiFormControlLabel-label-210"
205
+ class="MuiTypography-root-222 MuiTypography-body1-231 MuiFormControlLabel-label-202"
209
206
  >
210
207
  varyingDefaultColors
211
208
  </span>
@@ -215,13 +212,13 @@ exports[`Unit- FormProductionMethods renders correctly 1`] = `
215
212
  class="MuiGrid-item-44 MuiGrid-grid-xs-12-83 FormProductionMethods-checkboxGrid-1"
216
213
  >
217
214
  <label
218
- class="MuiFormControlLabel-root-205"
215
+ class="MuiFormControlLabel-root-197"
219
216
  >
220
217
  <span
221
- class="MuiButtonBase-root-227 MuiIconButton-root-221 MuiPrivateSwitchBase-root-217 MuiCheckbox-root-211 MuiCheckbox-colorPrimary-215"
218
+ class="MuiButtonBase-root-219 MuiIconButton-root-213 MuiPrivateSwitchBase-root-209 MuiCheckbox-root-203 MuiCheckbox-colorPrimary-207"
222
219
  >
223
220
  <span
224
- class="MuiIconButton-label-226"
221
+ class="MuiIconButton-label-218"
225
222
  >
226
223
  <svg
227
224
  aria-hidden="true"
@@ -235,7 +232,7 @@ exports[`Unit- FormProductionMethods renders correctly 1`] = `
235
232
  />
236
233
  </svg>
237
234
  <input
238
- class="MuiPrivateSwitchBase-input-220"
235
+ class="MuiPrivateSwitchBase-input-212"
239
236
  data-indeterminate="false"
240
237
  type="checkbox"
241
238
  value="designElementsLocked"
@@ -243,7 +240,7 @@ exports[`Unit- FormProductionMethods renders correctly 1`] = `
243
240
  </span>
244
241
  </span>
245
242
  <span
246
- class="MuiTypography-root-230 MuiTypography-body1-239 MuiFormControlLabel-label-210"
243
+ class="MuiTypography-root-222 MuiTypography-body1-231 MuiFormControlLabel-label-202"
247
244
  >
248
245
  designElementsLocked
249
246
  </span>
@@ -253,13 +250,13 @@ exports[`Unit- FormProductionMethods renders correctly 1`] = `
253
250
  class="MuiGrid-item-44 MuiGrid-grid-xs-12-83 FormProductionMethods-checkboxGrid-1"
254
251
  >
255
252
  <label
256
- class="MuiFormControlLabel-root-205"
253
+ class="MuiFormControlLabel-root-197"
257
254
  >
258
255
  <span
259
- class="MuiButtonBase-root-227 MuiIconButton-root-221 MuiPrivateSwitchBase-root-217 MuiCheckbox-root-211 MuiCheckbox-colorPrimary-215"
256
+ class="MuiButtonBase-root-219 MuiIconButton-root-213 MuiPrivateSwitchBase-root-209 MuiCheckbox-root-203 MuiCheckbox-colorPrimary-207"
260
257
  >
261
258
  <span
262
- class="MuiIconButton-label-226"
259
+ class="MuiIconButton-label-218"
263
260
  >
264
261
  <svg
265
262
  aria-hidden="true"
@@ -273,7 +270,7 @@ exports[`Unit- FormProductionMethods renders correctly 1`] = `
273
270
  />
274
271
  </svg>
275
272
  <input
276
- class="MuiPrivateSwitchBase-input-220"
273
+ class="MuiPrivateSwitchBase-input-212"
277
274
  data-indeterminate="false"
278
275
  type="checkbox"
279
276
  value="oneLineText"
@@ -281,7 +278,7 @@ exports[`Unit- FormProductionMethods renders correctly 1`] = `
281
278
  </span>
282
279
  </span>
283
280
  <span
284
- class="MuiTypography-root-230 MuiTypography-body1-239 MuiFormControlLabel-label-210"
281
+ class="MuiTypography-root-222 MuiTypography-body1-231 MuiFormControlLabel-label-202"
285
282
  >
286
283
  oneLineText
287
284
  </span>
@@ -294,7 +291,7 @@ exports[`Unit- FormProductionMethods renders correctly 1`] = `
294
291
  class="MuiFormControl-root-143"
295
292
  >
296
293
  <label
297
- class="MuiFormLabel-root-277 MuiInputLabel-root-266 MuiInputLabel-formControl-271 MuiInputLabel-animated-274"
294
+ class="MuiFormLabel-root-269 MuiInputLabel-root-258 MuiInputLabel-formControl-263 MuiInputLabel-animated-266"
298
295
  data-shrink="false"
299
296
  >
300
297
  minimumOrderAmount
@@ -318,7 +315,7 @@ exports[`Unit- FormProductionMethods renders correctly 1`] = `
318
315
  class="FormProductionMethods-inputWithLabel-14"
319
316
  >
320
317
  <legend
321
- class="MuiFormLabel-root-277"
318
+ class="MuiFormLabel-root-269"
322
319
  >
323
320
  maxTextElements
324
321
  </legend>
@@ -344,7 +341,7 @@ exports[`Unit- FormProductionMethods renders correctly 1`] = `
344
341
  class="FormProductionMethods-inputWithLabel-14"
345
342
  >
346
343
  <legend
347
- class="MuiFormLabel-root-277"
344
+ class="MuiFormLabel-root-269"
348
345
  >
349
346
  maxImageElements
350
347
  </legend>
@@ -370,7 +367,7 @@ exports[`Unit- FormProductionMethods renders correctly 1`] = `
370
367
  class="FormProductionMethods-inputWithLabel-14"
371
368
  >
372
369
  <legend
373
- class="MuiFormLabel-root-277"
370
+ class="MuiFormLabel-root-269"
374
371
  >
375
372
  maxTotalElements
376
373
  </legend>
@@ -404,14 +401,14 @@ exports[`Unit- FormProductionMethods renders correctly 1`] = `
404
401
  class="MuiGrid-item-44 MuiGrid-grid-xs-12-83"
405
402
  >
406
403
  <button
407
- class="MuiButtonBase-root-227 MuiIconButton-root-221"
404
+ class="MuiButtonBase-root-219 MuiIconButton-root-213"
408
405
  id="remove"
409
406
  label="Remove"
410
407
  tabindex="0"
411
408
  type="button"
412
409
  >
413
410
  <span
414
- class="MuiIconButton-label-226"
411
+ class="MuiIconButton-label-218"
415
412
  >
416
413
  <svg
417
414
  aria-hidden="true"
@@ -59,7 +59,9 @@ class UISelectField extends React.Component {
59
59
  )}
60
60
  {children}
61
61
  </Select>
62
- <FormHelperText>{error}</FormHelperText>
62
+ {error &&
63
+ <FormHelperText>{error}</FormHelperText>
64
+ }
63
65
  </FormControl>
64
66
  );
65
67
  }
@@ -18,6 +18,11 @@ export const getPointFromPointerEvent = (evt, relativeTo = false) => {
18
18
  x -= left;
19
19
  y -= top;
20
20
  }
21
+ if (relativeTo.width) {
22
+ const scaling = relativeTo.getBoundingClientRect().width / relativeTo.width;
23
+ x *= 1 / scaling;
24
+ y *= 1 / scaling;
25
+ }
21
26
  return { x, y };
22
27
  };
23
28