@crystaldesign/diva-backoffice 26.7.0-rc.2 → 26.7.0-rc.20

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 (20) hide show
  1. package/build/esm/index.js +389 -168
  2. package/build/types/backoffice/src/ui/Form/useFormData.d.ts.map +1 -1
  3. package/build/types/backoffice/src/ui/Table/BaseTable/cellRenderer/MediaViewerCell/index.d.ts.map +1 -1
  4. package/build/types/backoffice/src/ui/TableRenderJobs/components/RenderApprove/components/AIImageSelector/components/SortableImageRow/index.d.ts.map +1 -1
  5. package/build/types/backoffice/src/ui/TableRenderJobs/components/RenderApprove/components/AIImageSelector/index.d.ts +3 -3
  6. package/build/types/backoffice/src/ui/TableRenderJobs/components/RenderApprove/components/AIImageSelector/index.d.ts.map +1 -1
  7. package/build/types/backoffice/src/ui/TableRenderJobs/components/RenderApprove/components/ImageSelectionWorkspace/index.d.ts +4 -3
  8. package/build/types/backoffice/src/ui/TableRenderJobs/components/RenderApprove/components/ImageSelectionWorkspace/index.d.ts.map +1 -1
  9. package/build/types/backoffice/src/ui/TableRenderJobs/components/RenderApprove/components/MetadataPanel/index.d.ts +3 -1
  10. package/build/types/backoffice/src/ui/TableRenderJobs/components/RenderApprove/components/MetadataPanel/index.d.ts.map +1 -1
  11. package/build/types/backoffice/src/ui/TableRenderJobs/components/RenderApprove/hooks/useRenderJobData.d.ts +3 -1
  12. package/build/types/backoffice/src/ui/TableRenderJobs/components/RenderApprove/hooks/useRenderJobData.d.ts.map +1 -1
  13. package/build/types/backoffice/src/ui/TableRenderJobs/components/RenderApprove/index.d.ts.map +1 -1
  14. package/build/types/backoffice/src/ui/TableRenderJobs/components/UploadImageModal/index.d.ts +11 -1
  15. package/build/types/backoffice/src/ui/TableRenderJobs/components/UploadImageModal/index.d.ts.map +1 -1
  16. package/build/types/backoffice/src/ui/TableRenderJobs/hooks/useUploadRenderImage.d.ts +14 -0
  17. package/build/types/backoffice/src/ui/TableRenderJobs/hooks/useUploadRenderImage.d.ts.map +1 -0
  18. package/build/types/backoffice/src/ui/TableRenderJobs/types.d.ts +10 -3
  19. package/build/types/backoffice/src/ui/TableRenderJobs/types.d.ts.map +1 -1
  20. package/package.json +9 -9
@@ -18640,7 +18640,10 @@ function useFormData (_ref) {
18640
18640
  });
18641
18641
  }
18642
18642
  changedFields.current.forEach(function (changedField) {
18643
- orig[changedField.name[0]] = newData[changedField.name[0]];
18643
+ // Apply only the changed leaf path (e.g. ['predictedStorage', 'metadata', 'storageSpaceId'])
18644
+ // instead of the whole top-level key, so per-row sibling fields (e.g. predictedStorage.resolvedAt)
18645
+ // are preserved and not overwritten with the reference row's value during mass editing.
18646
+ setFieldInObject(changedField.name, orig, getData(changedField.name, newData));
18644
18647
  });
18645
18648
  return orig;
18646
18649
  };
@@ -28551,9 +28554,11 @@ function MediaViewerCell (_ref) {
28551
28554
  actions.loadModelViewer();
28552
28555
  }, []);
28553
28556
 
28554
- // The field value may be a plain url or an array of urls (e.g. renderImages);
28555
- // in the array case the first entry is shown.
28556
- var rawValue = Array.isArray(children === null || children === void 0 ? void 0 : children[1]) ? children[1][0] : children === null || children === void 0 ? void 0 : children[1];
28557
+ // The field value may be a plain url or an array (e.g. renderImages); in the
28558
+ // array case the first entry is shown. Entries may be plain urls or objects
28559
+ // carrying a `url` (e.g. renderImages: { mediaItemRefId?, url }).
28560
+ var firstEntry = Array.isArray(children === null || children === void 0 ? void 0 : children[1]) ? children[1][0] : children === null || children === void 0 ? void 0 : children[1];
28561
+ var rawValue = firstEntry && _typeof(firstEntry) === 'object' ? firstEntry.url : firstEntry;
28557
28562
  if (!rawValue) {
28558
28563
  return /*#__PURE__*/jsx(Fragment, {});
28559
28564
  }
@@ -53665,7 +53670,6 @@ var thumbPlaceholder = "thumbPlaceholder-zX1-S";
53665
53670
  var info = "info-8ZlUD";
53666
53671
  var label = "label-y-wTq";
53667
53672
  var meta = "meta-Ihuqr";
53668
- var referenceTag = "referenceTag-gyKQR";
53669
53673
  var css_248z$g = ".root-7OUrP {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 10px 12px;\n border: 1px solid #d9d9d9;\n border: 1px solid var(--ant-color-border, #d9d9d9);\n border-radius: 8px;\n background: #fff;\n background: var(--ant-color-bg-container, #fff);\n cursor: pointer;\n -webkit-user-select: none;\n -moz-user-select: none;\n user-select: none;\n}\n\n.root-7OUrP:active {\n cursor: grabbing;\n}\n\n.rootSelected-Z8LGb {\n border-color: #1677ff;\n border-color: var(--ant-color-primary, #1677ff);\n background: #e6f4ff;\n background: var(--ant-color-primary-bg, #e6f4ff);\n}\n\n.dragHandle-xo0vD {\n display: inline-flex;\n align-items: center;\n cursor: grab;\n color: #999;\n color: var(--ant-color-text-tertiary, #999);\n touch-action: none;\n}\n\n.dragHandle-xo0vD:active {\n cursor: grabbing;\n}\n\n.badge-7hZ6T {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 20px;\n height: 20px;\n padding: 0 6px;\n border-radius: 10px;\n font-size: 12px;\n font-weight: 600;\n color: #fff;\n background: #1677ff;\n background: var(--ant-color-primary, #1677ff);\n}\n\n.thumb-ePFWB {\n width: 88px;\n height: 88px;\n -o-object-fit: cover;\n object-fit: cover;\n border-radius: 6px;\n flex: 0 0 auto;\n background: #f0f0f0;\n background: var(--ant-color-fill-secondary, #f0f0f0);\n cursor: pointer;\n}\n\n.thumbPlaceholder-zX1-S {\n width: 88px;\n height: 88px;\n border-radius: 6px;\n background: #f0f0f0;\n background: var(--ant-color-fill-secondary, #f0f0f0);\n flex: 0 0 auto;\n}\n\n.info-8ZlUD {\n display: flex;\n flex-direction: column;\n min-width: 0;\n flex: 1 1 auto;\n}\n\n.label-y-wTq {\n font-size: 14px;\n font-weight: 500;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.meta-Ihuqr {\n font-size: 12px;\n color: #888;\n color: var(--ant-color-text-secondary, #888);\n overflow: hidden;\n text-overflow: ellipsis;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n}\n\n.referenceTag-gyKQR {\n align-self: flex-start;\n margin-top: 4px;\n padding: 1px 8px;\n border-radius: 4px;\n font-size: 11px;\n font-weight: 500;\n color: #1677ff;\n color: var(--ant-color-primary, #1677ff);\n background: #e6f4ff;\n background: var(--ant-color-primary-bg, #e6f4ff);\n border: 1px solid #91caff;\n border: 1px solid var(--ant-color-primary-border, #91caff);\n white-space: nowrap;\n}\n";
53670
53674
  styleInject(css_248z$g);
53671
53675
 
@@ -53766,12 +53770,6 @@ function SortableImageRow(_ref) {
53766
53770
  className: meta,
53767
53771
  title: metaText,
53768
53772
  children: ["(", metaText, ")"]
53769
- }) : null, selected && typeof orderNumber === 'number' ? /*#__PURE__*/jsx("span", {
53770
- className: referenceTag,
53771
- children: t('backoffice.renderapprove.aiImageSelector.referenceTag', {
53772
- defaultValue: 'used as AI reference ({{order}})',
53773
- order: orderNumber
53774
- })
53775
53773
  }) : null]
53776
53774
  })]
53777
53775
  }))
@@ -53847,11 +53845,14 @@ function buildItems(slides, selectedUrls) {
53847
53845
  });
53848
53846
  });
53849
53847
  }
53850
- function orderedSelectedUrls(items) {
53848
+ function orderedSelectedImages(items) {
53851
53849
  return items.filter(function (it) {
53852
53850
  return it.selected && it.media.url != null;
53853
53851
  }).map(function (it) {
53854
- return it.media.url;
53852
+ return {
53853
+ mediaItemRefId: it.media.mediaItemRefId,
53854
+ url: it.media.url
53855
+ };
53855
53856
  });
53856
53857
  }
53857
53858
 
@@ -53894,7 +53895,7 @@ function AIImageSelector(_ref2) {
53894
53895
  }));
53895
53896
  var commit = function commit(next) {
53896
53897
  setItems(next);
53897
- onChange === null || onChange === void 0 || onChange(orderedSelectedUrls(next));
53898
+ onChange === null || onChange === void 0 || onChange(orderedSelectedImages(next));
53898
53899
  };
53899
53900
  var toggle = function toggle(key) {
53900
53901
  commit(items.map(function (it) {
@@ -53991,25 +53992,40 @@ function AIImageSelector(_ref2) {
53991
53992
  * approve / reject / upload, since there is nothing to decide yet.
53992
53993
  */
53993
53994
  function ImageSelectionWorkspace(_ref) {
53995
+ var _job$renderImages;
53994
53996
  var job = _ref.job,
53995
53997
  slides = _ref.slides,
53996
53998
  selectionDisabled = _ref.selectionDisabled,
53997
53999
  onSelectionChange = _ref.onSelectionChange,
53998
54000
  onOpenFullscreen = _ref.onOpenFullscreen,
54001
+ onUpload = _ref.onUpload,
53999
54002
  actionDisabled = _ref.actionDisabled,
54000
54003
  busy = _ref.busy,
54001
54004
  isFirst = _ref.isFirst,
54002
54005
  shortcutItems = _ref.shortcutItems,
54003
54006
  onPrev = _ref.onPrev,
54004
54007
  onNext = _ref.onNext;
54008
+ var _useTranslation = useTranslation(),
54009
+ t = _useTranslation.t;
54005
54010
  return /*#__PURE__*/jsxs(Fragment, {
54006
54011
  children: [/*#__PURE__*/jsx(AIImageSelector, {
54007
54012
  slides: slides,
54008
- selectedUrls: job.renderImages,
54013
+ selectedUrls: (_job$renderImages = job.renderImages) === null || _job$renderImages === void 0 ? void 0 : _job$renderImages.map(function (image) {
54014
+ return image.url;
54015
+ }),
54009
54016
  disabled: selectionDisabled,
54010
54017
  onChange: onSelectionChange,
54011
54018
  onOpenFullscreen: onOpenFullscreen
54012
- }, job._id), /*#__PURE__*/jsx(ActionBar, {
54019
+ }, job._id), onUpload && /*#__PURE__*/jsx(Button, {
54020
+ icon: /*#__PURE__*/jsx(UploadOutlined, {}),
54021
+ onClick: onUpload,
54022
+ disabled: selectionDisabled,
54023
+ style: {
54024
+ marginTop: 12
54025
+ },
54026
+ block: true,
54027
+ children: t('backoffice.renderapprove.aiImageSelector.uploadImage')
54028
+ }), /*#__PURE__*/jsx(ActionBar, {
54013
54029
  disabled: actionDisabled,
54014
54030
  busy: busy,
54015
54031
  isFirst: isFirst,
@@ -54410,6 +54426,7 @@ function MetadataPanel(_ref) {
54410
54426
  promptActionBusy = _ref.promptActionBusy,
54411
54427
  onPromptRestart = _ref.onPromptRestart,
54412
54428
  promptWarningMessage = _ref.promptWarningMessage,
54429
+ hidePrompt = _ref.hidePrompt,
54413
54430
  children = _ref.children;
54414
54431
  var _useTranslation = useTranslation(),
54415
54432
  t = _useTranslation.t;
@@ -54446,7 +54463,7 @@ function MetadataPanel(_ref) {
54446
54463
  var promptValue = optimisticPrompt !== null && optimisticPrompt !== void 0 ? optimisticPrompt : jobPromptValue;
54447
54464
  var promptSourceValue = promptValue !== null && promptValue !== void 0 ? promptValue : '';
54448
54465
  var hasPromptSource = promptSourceValue.trim().length > 0;
54449
- var showPromptPanel = isAiEngine(job === null || job === void 0 ? void 0 : job.engine);
54466
+ var showPromptPanel = isAiEngine(job === null || job === void 0 ? void 0 : job.engine) && !hidePrompt;
54450
54467
  var isDetailsControlled = typeof detailsOpen === 'boolean';
54451
54468
  var isPromptControlled = typeof promptOpen === 'boolean';
54452
54469
  var isDetailsOpen = isDetailsControlled ? detailsOpen : internalSidebarOpen;
@@ -55347,12 +55364,14 @@ function UploadImageModal(_ref) {
55347
55364
  var open = _ref.open,
55348
55365
  renderJob = _ref.renderJob,
55349
55366
  onClose = _ref.onClose,
55350
- onSuccess = _ref.onSuccess;
55367
+ onSuccess = _ref.onSuccess,
55368
+ uploadOverride = _ref.uploadOverride,
55369
+ skipValidation = _ref.skipValidation,
55370
+ allowedExtensions = _ref.allowedExtensions;
55351
55371
  var _useTranslation = useTranslation(),
55352
55372
  t = _useTranslation.t;
55353
55373
  var _useUploadRenderJobIm = useUploadRenderJobImage(),
55354
- upload = _useUploadRenderJobIm.upload,
55355
- uploading = _useUploadRenderJobIm.uploading;
55374
+ upload = _useUploadRenderJobIm.upload;
55356
55375
  var _useState = useState(null),
55357
55376
  _useState2 = _slicedToArray(_useState, 2),
55358
55377
  selectedFile = _useState2[0],
@@ -55365,10 +55384,14 @@ function UploadImageModal(_ref) {
55365
55384
  _useState6 = _slicedToArray(_useState5, 2),
55366
55385
  validating = _useState6[0],
55367
55386
  setValidating = _useState6[1];
55368
- var _useState7 = useState(null),
55387
+ var _useState7 = useState(false),
55369
55388
  _useState8 = _slicedToArray(_useState7, 2),
55370
- uploadError = _useState8[0],
55371
- setUploadError = _useState8[1];
55389
+ uploading = _useState8[0],
55390
+ setUploading = _useState8[1];
55391
+ var _useState9 = useState(null),
55392
+ _useState10 = _slicedToArray(_useState9, 2),
55393
+ uploadError = _useState10[0],
55394
+ setUploadError = _useState10[1];
55372
55395
  var reset = function reset() {
55373
55396
  setSelectedFile(null);
55374
55397
  setWarnings([]);
@@ -55381,35 +55404,51 @@ function UploadImageModal(_ref) {
55381
55404
  };
55382
55405
  var handleFileSelect = /*#__PURE__*/function () {
55383
55406
  var _ref2 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee(file) {
55384
- var w;
55407
+ var _file$name$split$pop$, _file$name$split$pop, ext, w;
55385
55408
  return _regeneratorRuntime.wrap(function _callee$(_context) {
55386
55409
  while (1) switch (_context.prev = _context.next) {
55387
55410
  case 0:
55388
- setSelectedFile(file);
55389
55411
  setUploadError(null);
55390
55412
  setWarnings([]);
55391
- if (!renderJob) {
55392
- _context.next = 13;
55413
+ if (!(allowedExtensions && allowedExtensions.length > 0)) {
55414
+ _context.next = 8;
55415
+ break;
55416
+ }
55417
+ ext = (_file$name$split$pop$ = (_file$name$split$pop = file.name.split('.').pop()) === null || _file$name$split$pop === void 0 ? void 0 : _file$name$split$pop.toLowerCase()) !== null && _file$name$split$pop$ !== void 0 ? _file$name$split$pop$ : '';
55418
+ if (allowedExtensions.includes(ext)) {
55419
+ _context.next = 8;
55420
+ break;
55421
+ }
55422
+ setSelectedFile(null);
55423
+ setUploadError(t('backoffice.renderapprove.uploadModal.invalidImageType', {
55424
+ defaultValue: 'Nur folgende Bildformate sind erlaubt: {{formats}}',
55425
+ formats: allowedExtensions.join(', ')
55426
+ }));
55427
+ return _context.abrupt("return", false);
55428
+ case 8:
55429
+ setSelectedFile(file);
55430
+ if (!(!skipValidation && renderJob)) {
55431
+ _context.next = 19;
55393
55432
  break;
55394
55433
  }
55395
55434
  setValidating(true);
55396
- _context.prev = 5;
55397
- _context.next = 8;
55435
+ _context.prev = 11;
55436
+ _context.next = 14;
55398
55437
  return validateImageFile(file, renderJob, t);
55399
- case 8:
55438
+ case 14:
55400
55439
  w = _context.sent;
55401
55440
  setWarnings(w);
55402
- case 10:
55403
- _context.prev = 10;
55441
+ case 16:
55442
+ _context.prev = 16;
55404
55443
  setValidating(false);
55405
- return _context.finish(10);
55406
- case 13:
55444
+ return _context.finish(16);
55445
+ case 19:
55407
55446
  return _context.abrupt("return", false);
55408
- case 14:
55447
+ case 20:
55409
55448
  case "end":
55410
55449
  return _context.stop();
55411
55450
  }
55412
- }, _callee, null, [[5,, 10, 13]]);
55451
+ }, _callee, null, [[11,, 16, 19]]);
55413
55452
  }));
55414
55453
  return function handleFileSelect(_x) {
55415
55454
  return _ref2.apply(this, arguments);
@@ -55428,25 +55467,30 @@ function UploadImageModal(_ref) {
55428
55467
  return _context2.abrupt("return");
55429
55468
  case 2:
55430
55469
  setUploadError(null);
55431
- _context2.prev = 3;
55432
- _context2.next = 6;
55433
- return upload(selectedFile, renderJob);
55434
- case 6:
55470
+ setUploading(true);
55471
+ _context2.prev = 4;
55472
+ _context2.next = 7;
55473
+ return (uploadOverride !== null && uploadOverride !== void 0 ? uploadOverride : upload)(selectedFile, renderJob);
55474
+ case 7:
55435
55475
  reset();
55436
55476
  onSuccess === null || onSuccess === void 0 || onSuccess();
55437
- _context2.next = 13;
55477
+ _context2.next = 14;
55438
55478
  break;
55439
- case 10:
55440
- _context2.prev = 10;
55441
- _context2.t0 = _context2["catch"](3);
55479
+ case 11:
55480
+ _context2.prev = 11;
55481
+ _context2.t0 = _context2["catch"](4);
55442
55482
  setUploadError((_message = _context2.t0 === null || _context2.t0 === void 0 ? void 0 : _context2.t0.message) !== null && _message !== void 0 ? _message : t('backoffice.renderapprove.uploadModal.uploadFailed', {
55443
55483
  defaultValue: 'Upload fehlgeschlagen'
55444
55484
  }));
55445
- case 13:
55485
+ case 14:
55486
+ _context2.prev = 14;
55487
+ setUploading(false);
55488
+ return _context2.finish(14);
55489
+ case 17:
55446
55490
  case "end":
55447
55491
  return _context2.stop();
55448
55492
  }
55449
- }, _callee2, null, [[3, 10]]);
55493
+ }, _callee2, null, [[4, 11, 14, 17]]);
55450
55494
  }));
55451
55495
  return function handleUpload() {
55452
55496
  return _ref3.apply(this, arguments);
@@ -55474,7 +55518,9 @@ function UploadImageModal(_ref) {
55474
55518
  children: /*#__PURE__*/jsxs(Spin, {
55475
55519
  spinning: validating || uploading,
55476
55520
  children: [/*#__PURE__*/jsxs(Upload$2.Dragger, {
55477
- accept: "image/*",
55521
+ accept: allowedExtensions && allowedExtensions.length > 0 ? allowedExtensions.map(function (e) {
55522
+ return ".".concat(e);
55523
+ }).join(',') : 'image/*',
55478
55524
  beforeUpload: handleFileSelect,
55479
55525
  maxCount: 1,
55480
55526
  showUploadList: !!selectedFile,
@@ -56165,12 +56211,12 @@ function fetchJson(_x, _x2) {
56165
56211
  return _fetchJson.apply(this, arguments);
56166
56212
  }
56167
56213
  function _fetchJson() {
56168
- _fetchJson = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee2(url, jwt) {
56214
+ _fetchJson = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee3(url, jwt) {
56169
56215
  var response;
56170
- return _regeneratorRuntime.wrap(function _callee2$(_context2) {
56171
- while (1) switch (_context2.prev = _context2.next) {
56216
+ return _regeneratorRuntime.wrap(function _callee3$(_context3) {
56217
+ while (1) switch (_context3.prev = _context3.next) {
56172
56218
  case 0:
56173
- _context2.next = 2;
56219
+ _context3.next = 2;
56174
56220
  return fetch(url, {
56175
56221
  headers: _objectSpread$g({
56176
56222
  'Content-Type': 'application/json'
@@ -56179,24 +56225,24 @@ function _fetchJson() {
56179
56225
  } : {})
56180
56226
  });
56181
56227
  case 2:
56182
- response = _context2.sent;
56228
+ response = _context3.sent;
56183
56229
  if (response.ok) {
56184
- _context2.next = 5;
56230
+ _context3.next = 5;
56185
56231
  break;
56186
56232
  }
56187
56233
  throw new DivaError("Request failed: ".concat(response.status, " ").concat(response.statusText), {
56188
56234
  code: 'RENDERAPPROVE_FETCH_FAILED'
56189
56235
  });
56190
56236
  case 5:
56191
- _context2.next = 7;
56237
+ _context3.next = 7;
56192
56238
  return response.json();
56193
56239
  case 7:
56194
- return _context2.abrupt("return", _context2.sent);
56240
+ return _context3.abrupt("return", _context3.sent);
56195
56241
  case 8:
56196
56242
  case "end":
56197
- return _context2.stop();
56243
+ return _context3.stop();
56198
56244
  }
56199
- }, _callee2);
56245
+ }, _callee3);
56200
56246
  }));
56201
56247
  return _fetchJson.apply(this, arguments);
56202
56248
  }
@@ -56233,22 +56279,22 @@ function fetchProductMedia(_x3, _x4, _x5, _x6, _x7) {
56233
56279
  return _fetchProductMedia.apply(this, arguments);
56234
56280
  }
56235
56281
  function _fetchProductMedia() {
56236
- _fetchProductMedia = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee4(catalogService, baseUrl, jwt, productId, excludeUrl) {
56282
+ _fetchProductMedia = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee5(catalogService, baseUrl, jwt, productId, excludeUrl) {
56237
56283
  var data, product, media, sorted, seen, result, _iterator2, _step2, _mapped$metadata, item, mapped, ref;
56238
- return _regeneratorRuntime.wrap(function _callee4$(_context4) {
56239
- while (1) switch (_context4.prev = _context4.next) {
56284
+ return _regeneratorRuntime.wrap(function _callee5$(_context5) {
56285
+ while (1) switch (_context5.prev = _context5.next) {
56240
56286
  case 0:
56241
- _context4.next = 2;
56287
+ _context5.next = 2;
56242
56288
  return fetchJson("".concat(catalogService, "/v1/products/").concat(encodeURIComponent(productId), "/list"), jwt);
56243
56289
  case 2:
56244
- data = _context4.sent;
56290
+ data = _context5.sent;
56245
56291
  product = Array.isArray(data) ? data[0] : undefined;
56246
56292
  media = product === null || product === void 0 ? void 0 : product.media;
56247
56293
  if (!(!Array.isArray(media) || media.length === 0)) {
56248
- _context4.next = 7;
56294
+ _context5.next = 7;
56249
56295
  break;
56250
56296
  }
56251
- return _context4.abrupt("return", []);
56297
+ return _context5.abrupt("return", []);
56252
56298
  case 7:
56253
56299
  sorted = _toConsumableArray(media).sort(function (a, b) {
56254
56300
  var pa = typeof (a === null || a === void 0 ? void 0 : a.position) === 'number' ? a.position : Number.MAX_SAFE_INTEGER;
@@ -56259,42 +56305,45 @@ function _fetchProductMedia() {
56259
56305
  if (excludeUrl) seen.add(excludeUrl);
56260
56306
  result = [];
56261
56307
  _iterator2 = _createForOfIteratorHelper$9(sorted);
56262
- _context4.prev = 12;
56308
+ _context5.prev = 12;
56263
56309
  _iterator2.s();
56264
56310
  case 14:
56265
56311
  if ((_step2 = _iterator2.n()).done) {
56266
- _context4.next = 32;
56312
+ _context5.next = 32;
56267
56313
  break;
56268
56314
  }
56269
56315
  item = _step2.value;
56270
56316
  if (!(item !== null && item !== void 0 && item.functionType && EXCLUDED_FUNCTION_TYPES.has(item.functionType))) {
56271
- _context4.next = 18;
56317
+ _context5.next = 18;
56272
56318
  break;
56273
56319
  }
56274
- return _context4.abrupt("continue", 30);
56320
+ return _context5.abrupt("continue", 30);
56275
56321
  case 18:
56276
56322
  if (!(item !== null && item !== void 0 && item.mediaType && !ALLOWED_MEDIA_TYPES.has(item.mediaType))) {
56277
- _context4.next = 20;
56323
+ _context5.next = 20;
56278
56324
  break;
56279
56325
  }
56280
- return _context4.abrupt("continue", 30);
56326
+ return _context5.abrupt("continue", 30);
56281
56327
  case 20:
56282
56328
  mapped = toMedia(item);
56283
56329
  if (!(!mapped || !mapped.url)) {
56284
- _context4.next = 23;
56330
+ _context5.next = 23;
56285
56331
  break;
56286
56332
  }
56287
- return _context4.abrupt("continue", 30);
56333
+ return _context5.abrupt("continue", 30);
56288
56334
  case 23:
56289
56335
  if (!seen.has(mapped.url)) {
56290
- _context4.next = 25;
56336
+ _context5.next = 25;
56291
56337
  break;
56292
56338
  }
56293
- return _context4.abrupt("continue", 30);
56339
+ return _context5.abrupt("continue", 30);
56294
56340
  case 25:
56295
56341
  seen.add(mapped.url);
56296
56342
  ref = typeof (item === null || item === void 0 ? void 0 : item.ref) === 'string' ? item.ref : undefined;
56297
- if (ref) mapped.id = ref;
56343
+ if (ref) {
56344
+ mapped.id = ref;
56345
+ mapped.mediaItemRefId = ref;
56346
+ }
56298
56347
  // Base metadata already available from the product list.
56299
56348
  mapped.metadata = _objectSpread$g(_objectSpread$g({}, item !== null && item !== void 0 && item.functionType ? {
56300
56349
  functionType: item.functionType
@@ -56304,38 +56353,38 @@ function _fetchProductMedia() {
56304
56353
  ref: ref
56305
56354
  });
56306
56355
  case 30:
56307
- _context4.next = 14;
56356
+ _context5.next = 14;
56308
56357
  break;
56309
56358
  case 32:
56310
- _context4.next = 37;
56359
+ _context5.next = 37;
56311
56360
  break;
56312
56361
  case 34:
56313
- _context4.prev = 34;
56314
- _context4.t0 = _context4["catch"](12);
56315
- _iterator2.e(_context4.t0);
56362
+ _context5.prev = 34;
56363
+ _context5.t0 = _context5["catch"](12);
56364
+ _iterator2.e(_context5.t0);
56316
56365
  case 37:
56317
- _context4.prev = 37;
56366
+ _context5.prev = 37;
56318
56367
  _iterator2.f();
56319
- return _context4.finish(37);
56368
+ return _context5.finish(37);
56320
56369
  case 40:
56321
- _context4.next = 42;
56370
+ _context5.next = 42;
56322
56371
  return Promise.all(result.map(/*#__PURE__*/function () {
56323
- var _ref7 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee3(_ref6) {
56372
+ var _ref9 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee4(_ref8) {
56324
56373
  var media, ref, _yield$Promise$allSet3, _yield$Promise$allSet4, mediaItemRes, refRes, item, _media$metadata, payload, refDoc, _media$metadata2;
56325
- return _regeneratorRuntime.wrap(function _callee3$(_context3) {
56326
- while (1) switch (_context3.prev = _context3.next) {
56374
+ return _regeneratorRuntime.wrap(function _callee4$(_context4) {
56375
+ while (1) switch (_context4.prev = _context4.next) {
56327
56376
  case 0:
56328
- media = _ref6.media, ref = _ref6.ref;
56377
+ media = _ref8.media, ref = _ref8.ref;
56329
56378
  if (ref) {
56330
- _context3.next = 3;
56379
+ _context4.next = 3;
56331
56380
  break;
56332
56381
  }
56333
- return _context3.abrupt("return");
56382
+ return _context4.abrupt("return");
56334
56383
  case 3:
56335
- _context3.next = 5;
56384
+ _context4.next = 5;
56336
56385
  return Promise.allSettled([fetchJson("".concat(baseUrl, "/v1/mediaitemref/").concat(encodeURIComponent(ref), "/mediaitem"), jwt), fetchJson("".concat(baseUrl, "/v1/mediaitems/refs?filter=").concat(encodeURIComponent("{_id,eq,'".concat(ref, "'}"))), jwt)]);
56337
56386
  case 5:
56338
- _yield$Promise$allSet3 = _context3.sent;
56387
+ _yield$Promise$allSet3 = _context4.sent;
56339
56388
  _yield$Promise$allSet4 = _slicedToArray(_yield$Promise$allSet3, 2);
56340
56389
  mediaItemRes = _yield$Promise$allSet4[0];
56341
56390
  refRes = _yield$Promise$allSet4[1];
@@ -56355,23 +56404,23 @@ function _fetchProductMedia() {
56355
56404
  }
56356
56405
  case 11:
56357
56406
  case "end":
56358
- return _context3.stop();
56407
+ return _context4.stop();
56359
56408
  }
56360
- }, _callee3);
56409
+ }, _callee4);
56361
56410
  }));
56362
- return function (_x12) {
56363
- return _ref7.apply(this, arguments);
56411
+ return function (_x13) {
56412
+ return _ref9.apply(this, arguments);
56364
56413
  };
56365
56414
  }()));
56366
56415
  case 42:
56367
- return _context4.abrupt("return", result.map(function (r) {
56416
+ return _context5.abrupt("return", result.map(function (r) {
56368
56417
  return r.media;
56369
56418
  }));
56370
56419
  case 43:
56371
56420
  case "end":
56372
- return _context4.stop();
56421
+ return _context5.stop();
56373
56422
  }
56374
- }, _callee4, null, [[12, 34, 37, 40]]);
56423
+ }, _callee5, null, [[12, 34, 37, 40]]);
56375
56424
  }));
56376
56425
  return _fetchProductMedia.apply(this, arguments);
56377
56426
  }
@@ -56387,47 +56436,47 @@ function resolveMediaItem(_x8, _x9, _x10, _x11) {
56387
56436
  * session hook can call them without depending on the currently-loaded job.
56388
56437
  */
56389
56438
  function _resolveMediaItem() {
56390
- _resolveMediaItem = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee5(baseUrl, jwt, mediaItemId, mediaItemRef) {
56439
+ _resolveMediaItem = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee6(baseUrl, jwt, mediaItemId, mediaItemRef) {
56391
56440
  var item, media, _item, _media;
56392
- return _regeneratorRuntime.wrap(function _callee5$(_context5) {
56393
- while (1) switch (_context5.prev = _context5.next) {
56441
+ return _regeneratorRuntime.wrap(function _callee6$(_context6) {
56442
+ while (1) switch (_context6.prev = _context6.next) {
56394
56443
  case 0:
56395
56444
  if (!mediaItemRef) {
56396
- _context5.next = 7;
56445
+ _context6.next = 7;
56397
56446
  break;
56398
56447
  }
56399
- _context5.next = 3;
56448
+ _context6.next = 3;
56400
56449
  return fetchJson("".concat(baseUrl, "/v1/mediaitemref/").concat(encodeURIComponent(mediaItemRef), "/mediaitem"), jwt);
56401
56450
  case 3:
56402
- item = _context5.sent;
56451
+ item = _context6.sent;
56403
56452
  media = toMedia(item);
56404
56453
  if (!media) {
56405
- _context5.next = 7;
56454
+ _context6.next = 7;
56406
56455
  break;
56407
56456
  }
56408
- return _context5.abrupt("return", media);
56457
+ return _context6.abrupt("return", media);
56409
56458
  case 7:
56410
56459
  if (!mediaItemId) {
56411
- _context5.next = 14;
56460
+ _context6.next = 14;
56412
56461
  break;
56413
56462
  }
56414
- _context5.next = 10;
56463
+ _context6.next = 10;
56415
56464
  return fetchJson("".concat(baseUrl, "/v1/mediaitems/").concat(encodeURIComponent(mediaItemId)), jwt);
56416
56465
  case 10:
56417
- _item = _context5.sent;
56466
+ _item = _context6.sent;
56418
56467
  _media = toMedia(_item);
56419
56468
  if (!_media) {
56420
- _context5.next = 14;
56469
+ _context6.next = 14;
56421
56470
  break;
56422
56471
  }
56423
- return _context5.abrupt("return", _media);
56472
+ return _context6.abrupt("return", _media);
56424
56473
  case 14:
56425
- return _context5.abrupt("return", null);
56474
+ return _context6.abrupt("return", null);
56426
56475
  case 15:
56427
56476
  case "end":
56428
- return _context5.stop();
56477
+ return _context6.stop();
56429
56478
  }
56430
- }, _callee5);
56479
+ }, _callee6);
56431
56480
  }));
56432
56481
  return _resolveMediaItem.apply(this, arguments);
56433
56482
  }
@@ -56472,21 +56521,21 @@ function useRenderJobData(id, refreshKey) {
56472
56521
  setError(undefined);
56473
56522
  setJob(undefined);
56474
56523
  setImages({});
56475
- _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee() {
56476
- var _fetchedJob$realTimeR, fetchedJob, left, initialSlides, mediaItemId, mediaItemRef, productId, rightPromise, productPromise, _yield$Promise$allSet, _yield$Promise$allSet2, rightResult, productResult, right, _rightResult$value, _rightResult$reason, productMedia, _productResult$reason, renderImageUrls, productByUrl, _iterator, _step, m, renderImageSet, remainingProduct, leftSlides, renderImageSlides, previewAfter, _message, message;
56477
- return _regeneratorRuntime.wrap(function _callee$(_context) {
56478
- while (1) switch (_context.prev = _context.next) {
56524
+ _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee2() {
56525
+ var _fetchedJob$realTimeR, fetchedJob, left, initialSlides, mediaItemId, mediaItemRef, productId, rightPromise, productPromise, _yield$Promise$allSet, _yield$Promise$allSet2, rightResult, productResult, right, _rightResult$value, _rightResult$reason, productMedia, _productResult$reason, renderImages, productByUrl, _iterator, _step, m, renderImageSet, remainingProduct, leftSlides, renderImageSlides, previewAfter, _message, message;
56526
+ return _regeneratorRuntime.wrap(function _callee2$(_context2) {
56527
+ while (1) switch (_context2.prev = _context2.next) {
56479
56528
  case 0:
56480
- _context.prev = 0;
56481
- _context.next = 3;
56529
+ _context2.prev = 0;
56530
+ _context2.next = 3;
56482
56531
  return fetchJson("".concat(baseUrl, "/renderjobs/").concat(encodeURIComponent(id)), jwt);
56483
56532
  case 3:
56484
- fetchedJob = _context.sent;
56533
+ fetchedJob = _context2.sent;
56485
56534
  if (!cancelled) {
56486
- _context.next = 6;
56535
+ _context2.next = 6;
56487
56536
  break;
56488
56537
  }
56489
- return _context.abrupt("return");
56538
+ return _context2.abrupt("return");
56490
56539
  case 6:
56491
56540
  setJob(fetchedJob);
56492
56541
 
@@ -56508,18 +56557,18 @@ function useRenderJobData(id, refreshKey) {
56508
56557
  // failure cannot block the right panel and vice versa.
56509
56558
  rightPromise = mediaItemId || mediaItemRef ? resolveMediaItem(baseUrl, jwt, mediaItemId, mediaItemRef) : Promise.resolve(null);
56510
56559
  productPromise = catalogService && typeof productId === 'string' && productId.length > 0 ? fetchProductMedia(catalogService, baseUrl, jwt, productId, left.url) : Promise.resolve([]);
56511
- _context.next = 17;
56560
+ _context2.next = 17;
56512
56561
  return Promise.allSettled([rightPromise, productPromise]);
56513
56562
  case 17:
56514
- _yield$Promise$allSet = _context.sent;
56563
+ _yield$Promise$allSet = _context2.sent;
56515
56564
  _yield$Promise$allSet2 = _slicedToArray(_yield$Promise$allSet, 2);
56516
56565
  rightResult = _yield$Promise$allSet2[0];
56517
56566
  productResult = _yield$Promise$allSet2[1];
56518
56567
  if (!cancelled) {
56519
- _context.next = 23;
56568
+ _context2.next = 23;
56520
56569
  break;
56521
56570
  }
56522
- return _context.abrupt("return");
56571
+ return _context2.abrupt("return");
56523
56572
  case 23:
56524
56573
  if (rightResult.status === 'fulfilled') {
56525
56574
  right = (_rightResult$value = rightResult.value) !== null && _rightResult$value !== void 0 ? _rightResult$value : {
@@ -56545,8 +56594,8 @@ function useRenderJobData(id, refreshKey) {
56545
56594
  // The realtime preview is shown first only when there are no renderImages;
56546
56595
  // once renderImages exist it comes right after them, and only if it is
56547
56596
  // not already one of them.
56548
- renderImageUrls = Array.isArray(fetchedJob === null || fetchedJob === void 0 ? void 0 : fetchedJob.renderImages) ? fetchedJob.renderImages.filter(function (u) {
56549
- return typeof u === 'string' && u.length > 0;
56597
+ renderImages = Array.isArray(fetchedJob === null || fetchedJob === void 0 ? void 0 : fetchedJob.renderImages) ? fetchedJob.renderImages.filter(function (image) {
56598
+ return typeof (image === null || image === void 0 ? void 0 : image.url) === 'string' && image.url.length > 0;
56550
56599
  }) : [];
56551
56600
  productByUrl = new Map();
56552
56601
  _iterator = _createForOfIteratorHelper$9(productMedia);
@@ -56560,16 +56609,24 @@ function useRenderJobData(id, refreshKey) {
56560
56609
  } finally {
56561
56610
  _iterator.f();
56562
56611
  }
56563
- renderImageSet = new Set(renderImageUrls);
56612
+ renderImageSet = new Set(renderImages.map(function (image) {
56613
+ return image.url;
56614
+ }));
56564
56615
  remainingProduct = productMedia.filter(function (m) {
56565
56616
  return !(m.url && renderImageSet.has(m.url));
56566
56617
  });
56567
- if (renderImageUrls.length > 0) {
56568
- renderImageSlides = renderImageUrls.map(function (url) {
56618
+ if (renderImages.length > 0) {
56619
+ // Product media (rich metadata) wins on url match; otherwise build a
56620
+ // minimal slide that carries the stored MediaItemRef id so uploaded
56621
+ // images keep their ref when re-selected.
56622
+ renderImageSlides = renderImages.map(function (_ref6) {
56569
56623
  var _productByUrl$get;
56624
+ var url = _ref6.url,
56625
+ mediaItemRefId = _ref6.mediaItemRefId;
56570
56626
  return url === left.url ? left : (_productByUrl$get = productByUrl.get(url)) !== null && _productByUrl$get !== void 0 ? _productByUrl$get : {
56571
56627
  url: url,
56572
- mediaType: 'PCT'
56628
+ mediaType: 'PCT',
56629
+ mediaItemRefId: mediaItemRefId
56573
56630
  };
56574
56631
  });
56575
56632
  previewAfter = left.url != null && !renderImageSet.has(left.url) ? [left] : [];
@@ -56577,49 +56634,183 @@ function useRenderJobData(id, refreshKey) {
56577
56634
  } else {
56578
56635
  leftSlides = [left].concat(_toConsumableArray(remainingProduct));
56579
56636
  }
56637
+
56638
+ // Uploaded AI input images are not part of the product media, so their
56639
+ // display name (filename) is resolved from the MediaItemRef (best-effort).
56640
+ _context2.next = 35;
56641
+ return Promise.all(leftSlides.map(/*#__PURE__*/function () {
56642
+ var _ref7 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee(slide) {
56643
+ var item;
56644
+ return _regeneratorRuntime.wrap(function _callee$(_context) {
56645
+ while (1) switch (_context.prev = _context.next) {
56646
+ case 0:
56647
+ if (!(slide.name || !slide.mediaItemRefId)) {
56648
+ _context.next = 2;
56649
+ break;
56650
+ }
56651
+ return _context.abrupt("return");
56652
+ case 2:
56653
+ _context.prev = 2;
56654
+ _context.next = 5;
56655
+ return fetchJson("".concat(baseUrl, "/v1/mediaitemref/").concat(encodeURIComponent(slide.mediaItemRefId), "/mediaitem"), jwt);
56656
+ case 5:
56657
+ item = _context.sent;
56658
+ if (typeof (item === null || item === void 0 ? void 0 : item.name) === 'string' && item.name.length > 0) slide.name = item.name;
56659
+ _context.next = 11;
56660
+ break;
56661
+ case 9:
56662
+ _context.prev = 9;
56663
+ _context.t0 = _context["catch"](2);
56664
+ case 11:
56665
+ case "end":
56666
+ return _context.stop();
56667
+ }
56668
+ }, _callee, null, [[2, 9]]);
56669
+ }));
56670
+ return function (_x12) {
56671
+ return _ref7.apply(this, arguments);
56672
+ };
56673
+ }()));
56674
+ case 35:
56675
+ if (!cancelled) {
56676
+ _context2.next = 37;
56677
+ break;
56678
+ }
56679
+ return _context2.abrupt("return");
56680
+ case 37:
56580
56681
  setImages({
56581
56682
  left: left,
56582
56683
  leftSlides: leftSlides,
56583
56684
  right: right
56584
56685
  });
56585
- _context.next = 43;
56686
+ _context2.next = 47;
56586
56687
  break;
56587
- case 36:
56588
- _context.prev = 36;
56589
- _context.t0 = _context["catch"](0);
56688
+ case 40:
56689
+ _context2.prev = 40;
56690
+ _context2.t0 = _context2["catch"](0);
56590
56691
  if (!cancelled) {
56591
- _context.next = 40;
56692
+ _context2.next = 44;
56592
56693
  break;
56593
56694
  }
56594
- return _context.abrupt("return");
56595
- case 40:
56596
- message = (_message = _context.t0 === null || _context.t0 === void 0 ? void 0 : _context.t0.message) !== null && _message !== void 0 ? _message : 'Unknown error';
56695
+ return _context2.abrupt("return");
56696
+ case 44:
56697
+ message = (_message = _context2.t0 === null || _context2.t0 === void 0 ? void 0 : _context2.t0.message) !== null && _message !== void 0 ? _message : 'Unknown error';
56597
56698
  LOG$4.error(new DivaError("Failed to load render job ".concat(id, ": ").concat(message), {
56598
56699
  code: 'RENDERAPPROVE_LOAD_JOB'
56599
56700
  }));
56600
56701
  setError(message);
56601
- case 43:
56602
- _context.prev = 43;
56702
+ case 47:
56703
+ _context2.prev = 47;
56603
56704
  if (!cancelled) setLoading(false);
56604
- return _context.finish(43);
56605
- case 46:
56705
+ return _context2.finish(47);
56706
+ case 50:
56606
56707
  case "end":
56607
- return _context.stop();
56708
+ return _context2.stop();
56608
56709
  }
56609
- }, _callee, null, [[0, 36, 43, 46]]);
56710
+ }, _callee2, null, [[0, 40, 47, 50]]);
56610
56711
  }))();
56611
56712
  return function () {
56612
56713
  cancelled = true;
56613
56714
  };
56614
56715
  }, [id, baseUrl, catalogService, jwt, t, refreshKey]);
56716
+ var applyRenderImages = useCallback(function (renderImages) {
56717
+ setJob(function (prev) {
56718
+ return prev ? _objectSpread$g(_objectSpread$g({}, prev), {}, {
56719
+ renderImages: renderImages
56720
+ }) : prev;
56721
+ });
56722
+ }, []);
56615
56723
  return useMemo(function () {
56616
56724
  return {
56617
56725
  job: job,
56618
56726
  images: images,
56619
56727
  loading: loading,
56620
- error: error
56728
+ error: error,
56729
+ applyRenderImages: applyRenderImages
56621
56730
  };
56622
- }, [job, images, loading, error]);
56731
+ }, [job, images, loading, error, applyRenderImages]);
56732
+ }
56733
+
56734
+ /**
56735
+ * Uploads an image as a MediaItem/MediaItemRef (same asset pipeline as the
56736
+ * regular RenderApprove upload) and appends it to the render job's
56737
+ * `renderImages` so it becomes one of the AI input images. Unlike
56738
+ * `useUploadRenderJobImage` it does not touch `mediaItemRef`/`fileUrl` or change
56739
+ * the render job state - the job stays in the image-selection phase.
56740
+ */
56741
+ function useUploadRenderImage() {
56742
+ var _root$configurationSt, _root$configurationSt2, _root$dataStore$jwt;
56743
+ var root = useStore();
56744
+ var baseUrl = (_root$configurationSt = (_root$configurationSt2 = root.configurationStore.apiConfig) === null || _root$configurationSt2 === void 0 ? void 0 : _root$configurationSt2.mediaService) !== null && _root$configurationSt !== void 0 ? _root$configurationSt : '';
56745
+ var jwt = (_root$dataStore$jwt = root.dataStore.jwt) !== null && _root$dataStore$jwt !== void 0 ? _root$dataStore$jwt : '';
56746
+ var patchJob = useUpdateRenderJobPatch();
56747
+ var _useState = useState(false),
56748
+ _useState2 = _slicedToArray(_useState, 2),
56749
+ uploading = _useState2[0],
56750
+ setUploading = _useState2[1];
56751
+ var _useState3 = useState(null),
56752
+ _useState4 = _slicedToArray(_useState3, 2),
56753
+ error = _useState4[0],
56754
+ setError = _useState4[1];
56755
+ var upload = useCallback(/*#__PURE__*/function () {
56756
+ var _ref = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee(file, job) {
56757
+ var _job$organization, _job$renderImages, result, newImage, renderImages, op, err;
56758
+ return _regeneratorRuntime.wrap(function _callee$(_context) {
56759
+ while (1) switch (_context.prev = _context.next) {
56760
+ case 0:
56761
+ setUploading(true);
56762
+ setError(null);
56763
+ _context.prev = 2;
56764
+ _context.next = 5;
56765
+ return uploadMediaItem(baseUrl, jwt, {
56766
+ organizationId: (_job$organization = job.organization) !== null && _job$organization !== void 0 ? _job$organization : '',
56767
+ file: file,
56768
+ mediaType: 'PCT',
56769
+ functionType: 'SHO'
56770
+ });
56771
+ case 5:
56772
+ result = _context.sent;
56773
+ newImage = {
56774
+ mediaItemRefId: result.ref._id,
56775
+ url: result.ref.url
56776
+ };
56777
+ renderImages = [].concat(_toConsumableArray((_job$renderImages = job.renderImages) !== null && _job$renderImages !== void 0 ? _job$renderImages : []), [newImage]); // RFC 6902: `add` is rejected when the path already exists, so replace
56778
+ // when the job already carries a renderImages list.
56779
+ op = job.renderImages === undefined ? 'add' : 'replace';
56780
+ _context.next = 11;
56781
+ return patchJob(job._id, [{
56782
+ op: op,
56783
+ path: '/renderImages',
56784
+ value: renderImages
56785
+ }], true);
56786
+ case 11:
56787
+ _context.next = 18;
56788
+ break;
56789
+ case 13:
56790
+ _context.prev = 13;
56791
+ _context.t0 = _context["catch"](2);
56792
+ err = _context.t0;
56793
+ setError(err);
56794
+ throw err;
56795
+ case 18:
56796
+ _context.prev = 18;
56797
+ setUploading(false);
56798
+ return _context.finish(18);
56799
+ case 21:
56800
+ case "end":
56801
+ return _context.stop();
56802
+ }
56803
+ }, _callee, null, [[2, 13, 18, 21]]);
56804
+ }));
56805
+ return function (_x, _x2) {
56806
+ return _ref.apply(this, arguments);
56807
+ };
56808
+ }(), [baseUrl, jwt, patchJob]);
56809
+ return {
56810
+ upload: upload,
56811
+ uploading: uploading,
56812
+ error: error
56813
+ };
56623
56814
  }
56624
56815
 
56625
56816
  /** Return `false` when the shortcut should not run (e.g. modal open) so default browser behavior is preserved. */
@@ -56746,7 +56937,7 @@ function focusBackConfirmButton(button) {
56746
56937
  ok === null || ok === void 0 || ok.focus();
56747
56938
  }
56748
56939
  function RenderApprove() {
56749
- var _data$job, _data$job2, _data$images$right2, _data$images$right3, _data$images$leftSlid, _data$job3, _data$job4, _imageFullscreen$name;
56940
+ var _data$job, _data$job2, _data$images$right2, _data$images$right3, _data$images$leftSlid, _data$job3, _data$job4, _data$job5, _imageFullscreen$name;
56750
56941
  var store = useStore();
56751
56942
  var navigate = useNavigate();
56752
56943
  var _useTranslation = useTranslation(),
@@ -56788,10 +56979,16 @@ function RenderApprove() {
56788
56979
  _useState16 = _slicedToArray(_useState15, 2),
56789
56980
  uploadOpen = _useState16[0],
56790
56981
  setUploadOpen = _useState16[1];
56791
- var _useState17 = useState(0),
56982
+ var _useState17 = useState(false),
56792
56983
  _useState18 = _slicedToArray(_useState17, 2),
56793
- dataRefreshKey = _useState18[0],
56794
- setDataRefreshKey = _useState18[1];
56984
+ selectionUploadOpen = _useState18[0],
56985
+ setSelectionUploadOpen = _useState18[1];
56986
+ var _useUploadRenderImage = useUploadRenderImage(),
56987
+ uploadRenderImage = _useUploadRenderImage.upload;
56988
+ var _useState19 = useState(0),
56989
+ _useState20 = _slicedToArray(_useState19, 2),
56990
+ dataRefreshKey = _useState20[0],
56991
+ setDataRefreshKey = _useState20[1];
56795
56992
  var data = useRenderJobData(session.currentId, dataRefreshKey);
56796
56993
  var leftSwiperRef = useRef(null);
56797
56994
  var isAiJob = typeof ((_data$job = data.job) === null || _data$job === void 0 ? void 0 : _data$job.engine) === 'string' && data.job.engine.trim().toLowerCase() === 'ai';
@@ -56800,7 +56997,7 @@ function RenderApprove() {
56800
56997
  // side-by-side comparison view is shown as before.
56801
56998
  var showImageSelector = isAiJob && typeof ((_data$job2 = data.job) === null || _data$job2 === void 0 ? void 0 : _data$job2.state) === 'number' && data.job.state < RENDER_JOB_STATE.inChecking;
56802
56999
  var mode = showImageSelector ? 'select' : 'approve';
56803
- var shortcutItems = buildShortcutItems(mode, isAiJob);
57000
+ var shortcutItems = buildShortcutItems(mode, isAiJob && !showImageSelector);
56804
57001
  // On the finish screen `data.job` is gone, so `showImageSelector` flips to
56805
57002
  // false. Latch whether this session ran in image-selector mode (sessions are
56806
57003
  // homogeneous) so header/finish-screen stay consistent across that screen.
@@ -57121,10 +57318,10 @@ function RenderApprove() {
57121
57318
  };
57122
57319
 
57123
57320
  // Persists the ordered selection of input images on the render job. The
57124
- // `renderImages` array (CDN urls, in order) is the source of truth the AI
57125
- // generation consumes.
57321
+ // `renderImages` array (CDN url + MediaItemRef id, in order) is the source of
57322
+ // truth the AI generation consumes.
57126
57323
  var persistImageSelection = /*#__PURE__*/function () {
57127
- var _ref3 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee4(orderedUrls) {
57324
+ var _ref3 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee4(renderImages) {
57128
57325
  var op;
57129
57326
  return _regeneratorRuntime.wrap(function _callee4$(_context4) {
57130
57327
  while (1) switch (_context4.prev = _context4.next) {
@@ -57135,30 +57332,33 @@ function RenderApprove() {
57135
57332
  }
57136
57333
  return _context4.abrupt("return");
57137
57334
  case 2:
57335
+ // Optimistically update the in-memory job so re-renders (and a subsequent
57336
+ // upload) use this order instead of snapping back to the last fetched one.
57337
+ data.applyRenderImages(renderImages);
57138
57338
  // RFC 6902: `add` is rejected when the path already exists (AI jobs often
57139
57339
  // ship with a default renderImages list), so replace when it's present.
57140
57340
  op = data.job.renderImages === undefined ? 'add' : 'replace';
57141
- _context4.prev = 3;
57142
- _context4.next = 6;
57341
+ _context4.prev = 4;
57342
+ _context4.next = 7;
57143
57343
  return updateRenderJobPatch(data.job._id, [{
57144
57344
  op: op,
57145
57345
  path: '/renderImages',
57146
- value: orderedUrls
57346
+ value: renderImages
57147
57347
  }]);
57148
- case 6:
57149
- _context4.next = 11;
57348
+ case 7:
57349
+ _context4.next = 12;
57150
57350
  break;
57151
- case 8:
57152
- _context4.prev = 8;
57153
- _context4.t0 = _context4["catch"](3);
57351
+ case 9:
57352
+ _context4.prev = 9;
57353
+ _context4.t0 = _context4["catch"](4);
57154
57354
  message.error(t('backoffice.renderapprove.aiImageSelector.saveFailed', {
57155
57355
  defaultValue: 'Bildauswahl konnte nicht gespeichert werden.'
57156
57356
  }));
57157
- case 11:
57357
+ case 12:
57158
57358
  case "end":
57159
57359
  return _context4.stop();
57160
57360
  }
57161
- }, _callee4, null, [[3, 8]]);
57361
+ }, _callee4, null, [[4, 9]]);
57162
57362
  }));
57163
57363
  return function persistImageSelection(_x2) {
57164
57364
  return _ref3.apply(this, arguments);
@@ -57295,12 +57495,18 @@ function RenderApprove() {
57295
57495
  promptActionBusy: promptRestarting,
57296
57496
  onPromptRestart: onPromptRestart,
57297
57497
  promptWarningMessage: !showImageSelector ? t('backoffice.renderapprove.prompt.warningMessage') : undefined,
57498
+ hidePrompt: showImageSelector,
57298
57499
  children: showImageSelector && data.job ? /*#__PURE__*/jsx(ImageSelectionWorkspace, {
57299
57500
  job: data.job,
57300
- slides: (_data$images$leftSlid = data.images.leftSlides) !== null && _data$images$leftSlid !== void 0 ? _data$images$leftSlid : [],
57501
+ slides: ((_data$images$leftSlid = data.images.leftSlides) !== null && _data$images$leftSlid !== void 0 ? _data$images$leftSlid : []).filter(function (slide) {
57502
+ return slide.mediaType !== 'AR';
57503
+ }),
57301
57504
  selectionDisabled: session.isCurrentReadOnly || session.isUpdating,
57302
57505
  onSelectionChange: persistImageSelection,
57303
57506
  onOpenFullscreen: setImageFullscreen,
57507
+ onUpload: function onUpload() {
57508
+ return setSelectionUploadOpen(true);
57509
+ },
57304
57510
  actionDisabled: data.loading || !data.job,
57305
57511
  busy: session.isUpdating || promptRestarting,
57306
57512
  isFirst: session.isFirst,
@@ -57353,6 +57559,21 @@ function RenderApprove() {
57353
57559
  return k + 1;
57354
57560
  });
57355
57561
  }
57562
+ }), /*#__PURE__*/jsx(UploadImageModal, {
57563
+ open: selectionUploadOpen,
57564
+ renderJob: (_data$job5 = data.job) !== null && _data$job5 !== void 0 ? _data$job5 : null,
57565
+ uploadOverride: uploadRenderImage,
57566
+ skipValidation: true,
57567
+ allowedExtensions: ['webp', 'png', 'jpg', 'jpeg'],
57568
+ onClose: function onClose() {
57569
+ return setSelectionUploadOpen(false);
57570
+ },
57571
+ onSuccess: function onSuccess() {
57572
+ setSelectionUploadOpen(false);
57573
+ setDataRefreshKey(function (k) {
57574
+ return k + 1;
57575
+ });
57576
+ }
57356
57577
  }), /*#__PURE__*/jsx(FullscreenViewer, {
57357
57578
  open: fullscreenSide !== null,
57358
57579
  media: fullscreenMedia,