sanity-plugin-media 4.1.1 → 4.2.0

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 (59) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +56 -4
  3. package/dist/index.d.mts +131 -57
  4. package/dist/index.d.ts +131 -57
  5. package/dist/index.js +259 -98
  6. package/dist/index.js.map +1 -1
  7. package/dist/index.mjs +259 -98
  8. package/dist/index.mjs.map +1 -1
  9. package/package.json +9 -2
  10. package/src/__tests__/fixtures/createEpicTestStore.ts +27 -0
  11. package/src/__tests__/fixtures/listenMock.ts +9 -0
  12. package/src/__tests__/fixtures/mockSanityClient.ts +84 -0
  13. package/src/__tests__/fixtures/renderWithProviders.tsx +54 -0
  14. package/src/__tests__/fixtures/rootState.ts +27 -0
  15. package/src/__tests__/fixtures/withinDialog.ts +28 -0
  16. package/src/components/Browser/Browser.test.tsx +44 -0
  17. package/src/components/CardAsset/CardAsset.test.tsx +322 -0
  18. package/src/components/DialogAssetEdit/Details.tsx +123 -44
  19. package/src/components/DialogAssetEdit/DialogAssetEdit.test.tsx +215 -0
  20. package/src/components/DialogAssetEdit/index.tsx +138 -30
  21. package/src/components/DialogTagCreate/DialogTagCreate.test.tsx +120 -0
  22. package/src/components/DialogTagEdit/DialogTagEdit.test.tsx +164 -0
  23. package/src/components/FormBuilderTool/FormBuilderTool.test.tsx +62 -0
  24. package/src/components/UploadDropzone/UploadDropzone.test.tsx +39 -0
  25. package/src/contexts/ToolOptionsContext.tsx +6 -3
  26. package/src/formSchema/index.test.ts +55 -0
  27. package/src/formSchema/index.ts +28 -12
  28. package/src/hooks/useVersionedClient.ts +1 -1
  29. package/src/modules/assets/deleteAndUpdateEpics.test.ts +86 -0
  30. package/src/modules/assets/fetchEpic.test.ts +72 -0
  31. package/src/modules/assets/reducer.test.ts +90 -0
  32. package/src/modules/assets/tagsAndListenerEpics.test.ts +205 -0
  33. package/src/modules/dialog/epics.test.ts +167 -0
  34. package/src/modules/dialog/reducer.test.ts +184 -0
  35. package/src/modules/notifications/epics.test.ts +373 -0
  36. package/src/modules/notifications/index.ts +24 -4
  37. package/src/modules/notifications/reducer.test.ts +53 -0
  38. package/src/modules/search/index.test.ts +35 -0
  39. package/src/modules/selectors.test.ts +20 -0
  40. package/src/modules/tags/epics.test.ts +95 -0
  41. package/src/modules/tags/index.test.ts +41 -0
  42. package/src/modules/uploads/epics.test.ts +108 -0
  43. package/src/modules/uploads/index.test.ts +58 -0
  44. package/src/operators/checkTagName.test.ts +28 -0
  45. package/src/types/index.ts +20 -7
  46. package/src/utils/blocksToText.test.ts +42 -0
  47. package/src/utils/constructFilter.test.ts +119 -0
  48. package/src/utils/generatePreviewBlobUrl.test.ts +69 -0
  49. package/src/utils/getAssetResolution.test.ts +12 -0
  50. package/src/utils/getDocumentAssetIds.test.ts +49 -0
  51. package/src/utils/getSchemeColor.test.ts +11 -0
  52. package/src/utils/getTagSelectOptions.test.ts +43 -0
  53. package/src/utils/getUniqueDocuments.test.ts +25 -0
  54. package/src/utils/imageDprUrl.test.ts +45 -0
  55. package/src/utils/isSupportedAssetType.test.ts +15 -0
  56. package/src/utils/sanitizeFormData.test.ts +58 -0
  57. package/src/utils/typeGuards.test.ts +17 -0
  58. package/src/utils/uploadSanityAsset.test.ts +28 -0
  59. package/src/utils/withMaxConcurrency.test.ts +42 -0
package/dist/index.mjs CHANGED
@@ -549,7 +549,7 @@ const useKeyPress = (hotkey, onPress) => {
549
549
  if (context === void 0)
550
550
  throw new Error("useAssetSourceActions must be used within an AssetSourceDispatchProvider");
551
551
  return context;
552
- }, useVersionedClient = () => useClient({ apiVersion: "2022-10-01" }), ORDER_DICTIONARY = {
552
+ }, useVersionedClient = () => useClient({ apiVersion: "2025-10-02" }), ORDER_DICTIONARY = {
553
553
  _createdAt: {
554
554
  asc: "Last created: Oldest first",
555
555
  desc: "Last created: Newest first"
@@ -2372,14 +2372,16 @@ const Container$1 = styled(Box)(({ $scheme, theme }) => css`
2372
2372
  enabled: options?.creditLine?.enabled || !1,
2373
2373
  excludeSources: creditLineExcludeSources
2374
2374
  },
2375
- directUploads: options?.directUploads ?? !0
2375
+ directUploads: options?.directUploads ?? !0,
2376
+ locales: options?.locales
2376
2377
  };
2377
2378
  }, [
2378
2379
  options?.creditLine?.enabled,
2379
2380
  options?.components,
2380
2381
  options?.creditLine?.excludeSources,
2381
2382
  options?.maximumUploadSize,
2382
- options?.directUploads
2383
+ options?.directUploads,
2384
+ options?.locales
2383
2385
  ]);
2384
2386
  return /* @__PURE__ */ jsx(ToolOptionsContext.Provider, { value, children });
2385
2387
  }, useToolOptions = () => {
@@ -2658,21 +2660,35 @@ const DebugControls = () => {
2658
2660
  ] })
2659
2661
  }
2660
2662
  ) : null;
2661
- }, tagOptionSchema = z.object({
2663
+ };
2664
+ function localizedStringSchema(locales) {
2665
+ if (!locales || locales.length === 0)
2666
+ return z.string().trim().optional();
2667
+ const shape = {};
2668
+ for (const locale of locales)
2669
+ shape[locale.id] = z.string().trim().optional();
2670
+ return z.object(shape).passthrough();
2671
+ }
2672
+ const tagOptionSchema = z.object({
2662
2673
  label: z.string().trim().min(1, { message: "Label cannot be empty" }),
2663
2674
  value: z.string().trim().min(1, { message: "Value cannot be empty" })
2664
- }), assetFormSchema = z.object({
2665
- altText: z.string().trim().optional(),
2666
- creditLine: z.string().trim().optional(),
2667
- description: z.string().trim().optional(),
2668
- opt: z.object({
2669
- media: z.object({
2670
- tags: z.array(tagOptionSchema).nullable()
2671
- })
2672
- }),
2673
- originalFilename: z.string().trim().min(1, { message: "Filename cannot be empty" }),
2674
- title: z.string().trim().optional()
2675
- }), tagFormSchema = z.object({
2675
+ });
2676
+ function getAssetFormSchema(locales) {
2677
+ return z.object({
2678
+ altText: localizedStringSchema(locales),
2679
+ creditLine: localizedStringSchema(locales),
2680
+ description: localizedStringSchema(locales),
2681
+ opt: z.object({
2682
+ media: z.object({
2683
+ tags: z.array(tagOptionSchema).nullable()
2684
+ })
2685
+ }),
2686
+ originalFilename: z.string().trim().min(1, { message: "Filename cannot be empty" }),
2687
+ title: localizedStringSchema(locales)
2688
+ });
2689
+ }
2690
+ getAssetFormSchema();
2691
+ const tagFormSchema = z.object({
2676
2692
  name: z.string().min(1, { message: "Name cannot be empty" })
2677
2693
  });
2678
2694
  function getUniqueDocuments(documents) {
@@ -3107,6 +3123,11 @@ const imageDprUrl = (asset, options) => {
3107
3123
  )
3108
3124
  ] });
3109
3125
  });
3126
+ function toStringField(value) {
3127
+ if (typeof value == "string") return value;
3128
+ if (typeof value == "object" && value !== null)
3129
+ return Object.values(value).find((v) => v) || void 0;
3130
+ }
3110
3131
  function Details({
3111
3132
  formUpdating,
3112
3133
  handleCreateTag,
@@ -3116,8 +3137,10 @@ function Details({
3116
3137
  allTagOptions,
3117
3138
  assetTagOptions,
3118
3139
  currentAsset,
3119
- creditLine
3140
+ creditLine,
3141
+ locales
3120
3142
  }) {
3143
+ const hasLocales = locales && locales.length > 0, [activeLocaleTab, setActiveLocaleTab] = useState(0);
3121
3144
  return /* @__PURE__ */ jsxs(Stack, { space: 3, children: [
3122
3145
  /* @__PURE__ */ jsx(
3123
3146
  FormFieldInputTags,
@@ -3144,51 +3167,117 @@ function Details({
3144
3167
  value: currentAsset?.originalFilename
3145
3168
  }
3146
3169
  ),
3147
- /* @__PURE__ */ jsx(
3148
- FormFieldInputText,
3149
- {
3150
- ...register("title"),
3151
- disabled: formUpdating,
3152
- error: errors?.title?.message,
3153
- label: "Title",
3154
- name: "title",
3155
- value: currentAsset?.title
3156
- }
3157
- ),
3158
- /* @__PURE__ */ jsx(
3159
- FormFieldInputText,
3160
- {
3161
- ...register("altText"),
3162
- disabled: formUpdating,
3163
- error: errors?.altText?.message,
3164
- label: "Alt Text",
3165
- name: "altText",
3166
- value: currentAsset?.altText
3167
- }
3168
- ),
3169
- /* @__PURE__ */ jsx(
3170
- FormFieldInputTextarea,
3171
- {
3172
- ...register("description"),
3173
- disabled: formUpdating,
3174
- error: errors?.description?.message,
3175
- label: "Description",
3176
- name: "description",
3177
- rows: 5,
3178
- value: currentAsset?.description
3179
- }
3180
- ),
3181
- creditLine?.enabled && /* @__PURE__ */ jsx(
3182
- FormFieldInputText,
3183
- {
3184
- ...register("creditLine"),
3185
- error: errors?.creditLine?.message,
3186
- label: "Credit",
3187
- name: "creditLine",
3188
- value: currentAsset?.creditLine,
3189
- disabled: formUpdating || creditLine?.excludeSources?.includes(currentAsset?.source?.name)
3190
- }
3191
- )
3170
+ hasLocales ? /* @__PURE__ */ jsx(Card, { marginTop: 2, shadow: 1, padding: 3, radius: 1, children: /* @__PURE__ */ jsxs(Stack, { space: 2, children: [
3171
+ /* @__PURE__ */ jsx(TabList, { space: 2, children: locales.map((locale, idx) => /* @__PURE__ */ jsx(
3172
+ Tab,
3173
+ {
3174
+ id: `locale-tab-${locale.id}`,
3175
+ "aria-controls": `locale-panel-${locale.id}`,
3176
+ selected: activeLocaleTab === idx,
3177
+ onClick: () => setActiveLocaleTab(idx),
3178
+ label: locale.title
3179
+ },
3180
+ locale.id
3181
+ )) }),
3182
+ locales.map((locale, idx) => /* @__PURE__ */ jsx(
3183
+ TabPanel,
3184
+ {
3185
+ id: `locale-panel-${locale.id}`,
3186
+ "aria-labelledby": `locale-tab-${locale.id}`,
3187
+ hidden: activeLocaleTab !== idx,
3188
+ children: /* @__PURE__ */ jsxs(Stack, { space: 3, children: [
3189
+ /* @__PURE__ */ jsx(
3190
+ FormFieldInputText,
3191
+ {
3192
+ ...register(`title.${locale.id}`),
3193
+ disabled: formUpdating,
3194
+ error: errors?.title?.[locale.id]?.message,
3195
+ label: "Title",
3196
+ name: `title.${locale.id}`
3197
+ }
3198
+ ),
3199
+ /* @__PURE__ */ jsx(
3200
+ FormFieldInputText,
3201
+ {
3202
+ ...register(`altText.${locale.id}`),
3203
+ disabled: formUpdating,
3204
+ error: errors?.altText?.[locale.id]?.message,
3205
+ label: "Alt Text",
3206
+ name: `altText.${locale.id}`
3207
+ }
3208
+ ),
3209
+ /* @__PURE__ */ jsx(
3210
+ FormFieldInputTextarea,
3211
+ {
3212
+ ...register(`description.${locale.id}`),
3213
+ disabled: formUpdating,
3214
+ error: errors?.description?.[locale.id]?.message,
3215
+ label: "Description",
3216
+ name: `description.${locale.id}`,
3217
+ rows: 5
3218
+ }
3219
+ ),
3220
+ creditLine?.enabled && /* @__PURE__ */ jsx(
3221
+ FormFieldInputText,
3222
+ {
3223
+ ...register(`creditLine.${locale.id}`),
3224
+ error: errors?.creditLine?.[locale.id]?.message,
3225
+ label: "Credit",
3226
+ name: `creditLine.${locale.id}`,
3227
+ disabled: formUpdating || creditLine?.excludeSources?.includes(currentAsset?.source?.name)
3228
+ }
3229
+ )
3230
+ ] })
3231
+ },
3232
+ locale.id
3233
+ ))
3234
+ ] }) }) : /* @__PURE__ */ jsxs(Fragment, { children: [
3235
+ /* @__PURE__ */ jsx(
3236
+ FormFieldInputText,
3237
+ {
3238
+ ...register("title"),
3239
+ disabled: formUpdating,
3240
+ error: errors?.title?.message,
3241
+ label: "Title",
3242
+ name: "title",
3243
+ value: toStringField(currentAsset?.title)
3244
+ }
3245
+ ),
3246
+ /* @__PURE__ */ jsx(
3247
+ FormFieldInputText,
3248
+ {
3249
+ ...register("altText"),
3250
+ disabled: formUpdating,
3251
+ error: errors?.altText?.message,
3252
+ label: "Alt Text",
3253
+ name: "altText",
3254
+ value: toStringField(currentAsset?.altText)
3255
+ }
3256
+ ),
3257
+ /* @__PURE__ */ jsx(
3258
+ FormFieldInputTextarea,
3259
+ {
3260
+ ...register("description"),
3261
+ disabled: formUpdating,
3262
+ error: errors?.description?.message,
3263
+ label: "Description",
3264
+ name: "description",
3265
+ rows: 5,
3266
+ value: toStringField(currentAsset?.description)
3267
+ }
3268
+ ),
3269
+ creditLine?.enabled && /* @__PURE__ */ jsx(
3270
+ FormFieldInputText,
3271
+ {
3272
+ ...register("creditLine"),
3273
+ error: errors?.creditLine?.message,
3274
+ label: "Credit",
3275
+ name: "creditLine",
3276
+ value: toStringField(currentAsset?.creditLine),
3277
+ disabled: formUpdating || creditLine?.excludeSources?.includes(currentAsset?.source?.name)
3278
+ }
3279
+ )
3280
+ ] })
3192
3281
  ] });
3193
3282
  }
3194
3283
  function renderDefaultDetails(props) {
@@ -3198,16 +3287,37 @@ const DialogAssetEdit = (props) => {
3198
3287
  const {
3199
3288
  children,
3200
3289
  dialog: { assetId, id, lastCreatedTag, lastRemovedTagIds }
3201
- } = props, client = useVersionedClient(), scheme = useColorSchemeValue(), documentStore = useDocumentStore(), dispatch = useDispatch(), assetItem = useTypedSelector((state) => selectAssetById(state, String(assetId))), tags = useTypedSelector(selectTags), assetUpdatedPrev = useRef(void 0), [assetSnapshot, setAssetSnapshot] = useState(assetItem?.asset), [tabSection, setTabSection] = useState("details"), currentAsset = assetItem ? assetItem?.asset : assetSnapshot, allTagOptions = getTagSelectOptions(tags), assetTagOptions = useTypedSelector(selectTagSelectOptions(currentAsset)), { creditLine, components: { details: CustomDetails } = {} } = useToolOptions(), generateDefaultValues = useCallback(
3202
- (asset) => ({
3203
- altText: asset?.altText || "",
3204
- creditLine: asset?.creditLine || "",
3205
- description: asset?.description || "",
3206
- originalFilename: asset?.originalFilename || "",
3207
- opt: { media: { tags: assetTagOptions } },
3208
- title: asset?.title || ""
3209
- }),
3210
- [assetTagOptions]
3290
+ } = props, client = useVersionedClient(), scheme = useColorSchemeValue(), documentStore = useDocumentStore(), dispatch = useDispatch(), assetItem = useTypedSelector((state) => selectAssetById(state, String(assetId))), tags = useTypedSelector(selectTags), assetUpdatedPrev = useRef(void 0), [assetSnapshot, setAssetSnapshot] = useState(assetItem?.asset), [tabSection, setTabSection] = useState("details"), currentAsset = assetItem ? assetItem?.asset : assetSnapshot, allTagOptions = getTagSelectOptions(tags), assetTagOptions = useTypedSelector(selectTagSelectOptions(currentAsset)), { creditLine, components: { details: CustomDetails } = {}, locales } = useToolOptions(), generateDefaultValues = useCallback(
3291
+ (asset) => {
3292
+ if (locales && locales.length > 0) {
3293
+ const makeLocaleObj = (field) => {
3294
+ const obj = {};
3295
+ for (let i = 0; i < locales.length; i++) {
3296
+ const locale = locales[i];
3297
+ typeof field == "object" && field && field[locale.id] ? obj[locale.id] = field[locale.id] : typeof field == "string" ? obj[locale.id] = i === 0 ? field : "" : obj[locale.id] = "";
3298
+ }
3299
+ return obj;
3300
+ };
3301
+ return {
3302
+ altText: makeLocaleObj(asset?.altText),
3303
+ creditLine: makeLocaleObj(asset?.creditLine),
3304
+ description: makeLocaleObj(asset?.description),
3305
+ originalFilename: asset?.originalFilename || "",
3306
+ opt: { media: { tags: assetTagOptions } },
3307
+ title: makeLocaleObj(asset?.title)
3308
+ };
3309
+ }
3310
+ const flattenField = (field) => typeof field == "string" ? field : typeof field == "object" && field !== null && Object.values(field).find((v) => v) || "";
3311
+ return {
3312
+ altText: flattenField(asset?.altText),
3313
+ creditLine: flattenField(asset?.creditLine),
3314
+ description: flattenField(asset?.description),
3315
+ originalFilename: asset?.originalFilename || "",
3316
+ opt: { media: { tags: assetTagOptions } },
3317
+ title: flattenField(asset?.title)
3318
+ };
3319
+ },
3320
+ [assetTagOptions, locales]
3211
3321
  ), {
3212
3322
  control,
3213
3323
  // Read the formState before render to subscribe the form state through Proxy
@@ -3220,7 +3330,7 @@ const DialogAssetEdit = (props) => {
3220
3330
  } = useForm({
3221
3331
  defaultValues: generateDefaultValues(assetItem?.asset),
3222
3332
  mode: "onChange",
3223
- resolver: zodResolver(assetFormSchema)
3333
+ resolver: zodResolver(getAssetFormSchema(locales))
3224
3334
  }), formUpdating = !assetItem || assetItem?.updating, handleClose = useCallback(() => {
3225
3335
  dispatch(dialogActions.remove({ id }));
3226
3336
  }, [dispatch, id]), handleDelete = useCallback(() => {
@@ -3243,7 +3353,39 @@ const DialogAssetEdit = (props) => {
3243
3353
  );
3244
3354
  },
3245
3355
  [currentAsset?._id, dispatch]
3246
- ), onSubmit = useCallback(
3356
+ ), hasOrphanedLocales = useMemo(() => {
3357
+ if (!currentAsset) return !1;
3358
+ const isLocaleObj = (v) => typeof v == "object" && v !== null && !Array.isArray(v), fields = [
3359
+ currentAsset.title,
3360
+ currentAsset.altText,
3361
+ currentAsset.description,
3362
+ ...currentAsset._type === "sanity.imageAsset" ? [currentAsset.creditLine] : []
3363
+ ];
3364
+ if (!fields.some((f) => isLocaleObj(f))) return !1;
3365
+ if (!locales || locales.length === 0) return !0;
3366
+ const configuredIds = new Set(locales.map((l) => l.id));
3367
+ return fields.some((f) => isLocaleObj(f) ? Object.keys(f).some((k) => !configuredIds.has(k)) : !1);
3368
+ }, [currentAsset, locales]), handleCleanupLocales = useCallback(async () => {
3369
+ if (!currentAsset) return;
3370
+ const cleanField = (field) => {
3371
+ if (typeof field != "object" || field === null || Array.isArray(field)) return field;
3372
+ const obj = field;
3373
+ if (!locales || locales.length === 0)
3374
+ return Object.keys(obj).sort().map((k) => obj[k]).find((v) => v) || "";
3375
+ const configuredIds = new Set(locales.map((l) => l.id)), cleaned = {};
3376
+ for (const [key, val] of Object.entries(obj))
3377
+ configuredIds.has(key) && (cleaned[key] = val);
3378
+ return cleaned;
3379
+ };
3380
+ await client.patch(currentAsset._id).set({
3381
+ title: cleanField(currentAsset.title),
3382
+ altText: cleanField(currentAsset.altText),
3383
+ description: cleanField(currentAsset.description),
3384
+ ...currentAsset._type === "sanity.imageAsset" && {
3385
+ creditLine: cleanField(currentAsset.creditLine)
3386
+ }
3387
+ }).commit();
3388
+ }, [client, currentAsset, locales]), onSubmit = useCallback(
3247
3389
  (formData) => {
3248
3390
  if (!assetItem?.asset)
3249
3391
  return;
@@ -3291,27 +3433,42 @@ const DialogAssetEdit = (props) => {
3291
3433
  }, [getValues, lastRemovedTagIds, setValue]), useEffect(() => {
3292
3434
  assetUpdatedPrev.current !== assetItem?.asset._updatedAt && reset(generateDefaultValues(assetItem?.asset)), assetUpdatedPrev.current = assetItem?.asset._updatedAt;
3293
3435
  }, [assetItem?.asset, generateDefaultValues, reset]);
3294
- const Footer = () => /* @__PURE__ */ jsx(Box, { padding: 3, children: /* @__PURE__ */ jsxs(Flex, { justify: "space-between", children: [
3295
- /* @__PURE__ */ jsx(
3296
- Button,
3297
- {
3298
- disabled: formUpdating,
3299
- fontSize: 1,
3300
- mode: "bleed",
3301
- onClick: handleDelete,
3302
- text: "Delete",
3303
- tone: "critical"
3304
- }
3305
- ),
3306
- /* @__PURE__ */ jsx(
3307
- FormSubmitButton,
3308
- {
3309
- disabled: formUpdating || !isDirty || !isValid,
3310
- isValid,
3311
- lastUpdated: currentAsset?._updatedAt,
3312
- onClick: handleSubmit(onSubmit)
3313
- }
3314
- )
3436
+ const Footer = () => /* @__PURE__ */ jsx(Box, { padding: 3, children: /* @__PURE__ */ jsxs(Stack, { space: 3, children: [
3437
+ hasOrphanedLocales && /* @__PURE__ */ jsx(Card, { padding: 3, radius: 2, shadow: 1, tone: "caution", children: /* @__PURE__ */ jsxs(Flex, { align: "center", justify: "space-between", gap: 3, children: [
3438
+ /* @__PURE__ */ jsx(Text, { size: 1, children: "This asset has localized fields that are no longer configured. Clean them up to avoid validation errors." }),
3439
+ /* @__PURE__ */ jsx(
3440
+ Button,
3441
+ {
3442
+ fontSize: 1,
3443
+ mode: "ghost",
3444
+ onClick: handleCleanupLocales,
3445
+ text: "Cleanup localized fields",
3446
+ tone: "caution"
3447
+ }
3448
+ )
3449
+ ] }) }),
3450
+ /* @__PURE__ */ jsxs(Flex, { justify: "space-between", children: [
3451
+ /* @__PURE__ */ jsx(
3452
+ Button,
3453
+ {
3454
+ disabled: formUpdating,
3455
+ fontSize: 1,
3456
+ mode: "bleed",
3457
+ onClick: handleDelete,
3458
+ text: "Delete",
3459
+ tone: "critical"
3460
+ }
3461
+ ),
3462
+ /* @__PURE__ */ jsx(
3463
+ FormSubmitButton,
3464
+ {
3465
+ disabled: formUpdating || !isDirty || !isValid || hasOrphanedLocales,
3466
+ isValid,
3467
+ lastUpdated: currentAsset?._updatedAt,
3468
+ onClick: handleSubmit(onSubmit)
3469
+ }
3470
+ )
3471
+ ] })
3315
3472
  ] }) });
3316
3473
  if (!currentAsset)
3317
3474
  return null;
@@ -3325,7 +3482,8 @@ const DialogAssetEdit = (props) => {
3325
3482
  allTagOptions,
3326
3483
  handleCreateTag,
3327
3484
  currentAsset,
3328
- creditLine
3485
+ creditLine,
3486
+ locales
3329
3487
  };
3330
3488
  return /* @__PURE__ */ jsxs(
3331
3489
  Dialog,
@@ -5109,6 +5267,9 @@ const TableRowUpload = (props) => {
5109
5267
  reducers: {}
5110
5268
  });
5111
5269
  var selectedReducer = selectedSlice.reducer;
5270
+ function messageFromGenericErrorPayload(payload) {
5271
+ return !payload || typeof payload != "object" ? "Unknown error" : "error" in payload && payload.error && typeof payload.error == "object" && payload.error !== null && "message" in payload.error ? String(payload.error.message) : "message" in payload && typeof payload.message == "string" ? String(payload.message) : "Unknown error";
5272
+ }
5112
5273
  const initialState = {
5113
5274
  items: []
5114
5275
  }, notificationsSlice = createSlice({
@@ -5195,11 +5356,11 @@ const initialState = {
5195
5356
  uploadsActions.uploadError.type
5196
5357
  ),
5197
5358
  mergeMap((action) => {
5198
- const error = action.payload?.error;
5359
+ const title = `An error occurred: ${messageFromGenericErrorPayload(action.payload)}`;
5199
5360
  return of(
5200
5361
  notificationsSlice.actions.add({
5201
5362
  status: "error",
5202
- title: `An error occured: ${error.message}`
5363
+ title
5203
5364
  })
5204
5365
  );
5205
5366
  })