sanity-plugin-media 4.1.0 → 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.
- package/LICENSE +1 -1
- package/README.md +56 -4
- package/dist/index.d.mts +131 -57
- package/dist/index.d.ts +131 -57
- package/dist/index.js +273 -106
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +273 -106
- package/dist/index.mjs.map +1 -1
- package/package.json +11 -4
- package/src/__tests__/fixtures/createEpicTestStore.ts +27 -0
- package/src/__tests__/fixtures/listenMock.ts +9 -0
- package/src/__tests__/fixtures/mockSanityClient.ts +84 -0
- package/src/__tests__/fixtures/renderWithProviders.tsx +54 -0
- package/src/__tests__/fixtures/rootState.ts +27 -0
- package/src/__tests__/fixtures/withinDialog.ts +28 -0
- package/src/components/Browser/Browser.test.tsx +44 -0
- package/src/components/CardAsset/CardAsset.test.tsx +322 -0
- package/src/components/DialogAssetEdit/Details.tsx +123 -44
- package/src/components/DialogAssetEdit/DialogAssetEdit.test.tsx +215 -0
- package/src/components/DialogAssetEdit/index.tsx +138 -30
- package/src/components/DialogTagCreate/DialogTagCreate.test.tsx +120 -0
- package/src/components/DialogTagEdit/DialogTagEdit.test.tsx +164 -0
- package/src/components/FormBuilderTool/FormBuilderTool.test.tsx +62 -0
- package/src/components/ReduxProvider/index.tsx +2 -1
- package/src/components/UploadDropzone/UploadDropzone.test.tsx +39 -0
- package/src/constants.ts +6 -0
- package/src/contexts/ToolOptionsContext.tsx +6 -3
- package/src/formSchema/index.test.ts +55 -0
- package/src/formSchema/index.ts +28 -12
- package/src/hooks/useVersionedClient.ts +1 -1
- package/src/modules/assets/deleteAndUpdateEpics.test.ts +86 -0
- package/src/modules/assets/fetchEpic.test.ts +72 -0
- package/src/modules/assets/reducer.test.ts +90 -0
- package/src/modules/assets/tagsAndListenerEpics.test.ts +205 -0
- package/src/modules/dialog/epics.test.ts +167 -0
- package/src/modules/dialog/reducer.test.ts +184 -0
- package/src/modules/notifications/epics.test.ts +373 -0
- package/src/modules/notifications/index.ts +24 -4
- package/src/modules/notifications/reducer.test.ts +53 -0
- package/src/modules/search/index.test.ts +35 -0
- package/src/modules/selectors.test.ts +20 -0
- package/src/modules/tags/epics.test.ts +95 -0
- package/src/modules/tags/index.test.ts +41 -0
- package/src/modules/uploads/epics.test.ts +108 -0
- package/src/modules/uploads/index.test.ts +58 -0
- package/src/operators/checkTagName.test.ts +28 -0
- package/src/types/index.ts +23 -7
- package/src/utils/blocksToText.test.ts +42 -0
- package/src/utils/constructFilter.test.ts +119 -0
- package/src/utils/generatePreviewBlobUrl.test.ts +69 -0
- package/src/utils/getAssetResolution.test.ts +12 -0
- package/src/utils/getDocumentAssetIds.test.ts +49 -0
- package/src/utils/getSchemeColor.test.ts +11 -0
- package/src/utils/getTagSelectOptions.test.ts +43 -0
- package/src/utils/getUniqueDocuments.test.ts +25 -0
- package/src/utils/imageDprUrl.test.ts +45 -0
- package/src/utils/isSupportedAssetType.test.ts +15 -0
- package/src/utils/isSupportedAssetType.ts +15 -0
- package/src/utils/sanitizeFormData.test.ts +58 -0
- package/src/utils/typeGuards.test.ts +17 -0
- package/src/utils/uploadSanityAsset.test.ts +28 -0
- package/src/utils/withMaxConcurrency.test.ts +42 -0
package/dist/index.js
CHANGED
|
@@ -467,7 +467,10 @@ const useKeyPress = (hotkey, onPress) => {
|
|
|
467
467
|
fn: (value, _field) => value ? `references('${value}')` : void 0,
|
|
468
468
|
label: "includes"
|
|
469
469
|
}
|
|
470
|
-
},
|
|
470
|
+
}, SUPPORTED_ASSET_TYPES = [
|
|
471
|
+
"file",
|
|
472
|
+
"image"
|
|
473
|
+
], ORDER_OPTIONS = [
|
|
471
474
|
{
|
|
472
475
|
direction: "desc",
|
|
473
476
|
field: "_createdAt"
|
|
@@ -539,7 +542,7 @@ const useKeyPress = (hotkey, onPress) => {
|
|
|
539
542
|
if (context === void 0)
|
|
540
543
|
throw new Error("useAssetSourceActions must be used within an AssetSourceDispatchProvider");
|
|
541
544
|
return context;
|
|
542
|
-
}, useVersionedClient = () => sanity.useClient({ apiVersion: "
|
|
545
|
+
}, useVersionedClient = () => sanity.useClient({ apiVersion: "2025-10-02" }), ORDER_DICTIONARY = {
|
|
543
546
|
_createdAt: {
|
|
544
547
|
asc: "Last created: Oldest first",
|
|
545
548
|
desc: "Last created: Newest first"
|
|
@@ -2362,14 +2365,16 @@ const Container$1 = styledComponents.styled(ui.Box)(({ $scheme, theme }) => styl
|
|
|
2362
2365
|
enabled: options?.creditLine?.enabled || !1,
|
|
2363
2366
|
excludeSources: creditLineExcludeSources
|
|
2364
2367
|
},
|
|
2365
|
-
directUploads: options?.directUploads ?? !0
|
|
2368
|
+
directUploads: options?.directUploads ?? !0,
|
|
2369
|
+
locales: options?.locales
|
|
2366
2370
|
};
|
|
2367
2371
|
}, [
|
|
2368
2372
|
options?.creditLine?.enabled,
|
|
2369
2373
|
options?.components,
|
|
2370
2374
|
options?.creditLine?.excludeSources,
|
|
2371
2375
|
options?.maximumUploadSize,
|
|
2372
|
-
options?.directUploads
|
|
2376
|
+
options?.directUploads,
|
|
2377
|
+
options?.locales
|
|
2373
2378
|
]);
|
|
2374
2379
|
return /* @__PURE__ */ jsxRuntime.jsx(ToolOptionsContext.Provider, { value, children });
|
|
2375
2380
|
}, useToolOptions = () => {
|
|
@@ -2648,21 +2653,35 @@ const DebugControls = () => {
|
|
|
2648
2653
|
] })
|
|
2649
2654
|
}
|
|
2650
2655
|
) : null;
|
|
2651
|
-
}
|
|
2656
|
+
};
|
|
2657
|
+
function localizedStringSchema(locales) {
|
|
2658
|
+
if (!locales || locales.length === 0)
|
|
2659
|
+
return z__namespace.string().trim().optional();
|
|
2660
|
+
const shape = {};
|
|
2661
|
+
for (const locale of locales)
|
|
2662
|
+
shape[locale.id] = z__namespace.string().trim().optional();
|
|
2663
|
+
return z__namespace.object(shape).passthrough();
|
|
2664
|
+
}
|
|
2665
|
+
const tagOptionSchema = z__namespace.object({
|
|
2652
2666
|
label: z__namespace.string().trim().min(1, { message: "Label cannot be empty" }),
|
|
2653
2667
|
value: z__namespace.string().trim().min(1, { message: "Value cannot be empty" })
|
|
2654
|
-
})
|
|
2655
|
-
|
|
2656
|
-
|
|
2657
|
-
|
|
2658
|
-
|
|
2659
|
-
|
|
2660
|
-
|
|
2661
|
-
|
|
2662
|
-
|
|
2663
|
-
|
|
2664
|
-
|
|
2665
|
-
|
|
2668
|
+
});
|
|
2669
|
+
function getAssetFormSchema(locales) {
|
|
2670
|
+
return z__namespace.object({
|
|
2671
|
+
altText: localizedStringSchema(locales),
|
|
2672
|
+
creditLine: localizedStringSchema(locales),
|
|
2673
|
+
description: localizedStringSchema(locales),
|
|
2674
|
+
opt: z__namespace.object({
|
|
2675
|
+
media: z__namespace.object({
|
|
2676
|
+
tags: z__namespace.array(tagOptionSchema).nullable()
|
|
2677
|
+
})
|
|
2678
|
+
}),
|
|
2679
|
+
originalFilename: z__namespace.string().trim().min(1, { message: "Filename cannot be empty" }),
|
|
2680
|
+
title: localizedStringSchema(locales)
|
|
2681
|
+
});
|
|
2682
|
+
}
|
|
2683
|
+
getAssetFormSchema();
|
|
2684
|
+
const tagFormSchema = z__namespace.object({
|
|
2666
2685
|
name: z__namespace.string().min(1, { message: "Name cannot be empty" })
|
|
2667
2686
|
});
|
|
2668
2687
|
function getUniqueDocuments(documents) {
|
|
@@ -3097,6 +3116,11 @@ const imageDprUrl = (asset, options) => {
|
|
|
3097
3116
|
)
|
|
3098
3117
|
] });
|
|
3099
3118
|
});
|
|
3119
|
+
function toStringField(value) {
|
|
3120
|
+
if (typeof value == "string") return value;
|
|
3121
|
+
if (typeof value == "object" && value !== null)
|
|
3122
|
+
return Object.values(value).find((v) => v) || void 0;
|
|
3123
|
+
}
|
|
3100
3124
|
function Details({
|
|
3101
3125
|
formUpdating,
|
|
3102
3126
|
handleCreateTag,
|
|
@@ -3106,8 +3130,10 @@ function Details({
|
|
|
3106
3130
|
allTagOptions,
|
|
3107
3131
|
assetTagOptions,
|
|
3108
3132
|
currentAsset,
|
|
3109
|
-
creditLine
|
|
3133
|
+
creditLine,
|
|
3134
|
+
locales
|
|
3110
3135
|
}) {
|
|
3136
|
+
const hasLocales = locales && locales.length > 0, [activeLocaleTab, setActiveLocaleTab] = react.useState(0);
|
|
3111
3137
|
return /* @__PURE__ */ jsxRuntime.jsxs(ui.Stack, { space: 3, children: [
|
|
3112
3138
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3113
3139
|
FormFieldInputTags,
|
|
@@ -3134,51 +3160,117 @@ function Details({
|
|
|
3134
3160
|
value: currentAsset?.originalFilename
|
|
3135
3161
|
}
|
|
3136
3162
|
),
|
|
3137
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3138
|
-
|
|
3139
|
-
|
|
3140
|
-
|
|
3141
|
-
|
|
3142
|
-
|
|
3143
|
-
|
|
3144
|
-
|
|
3145
|
-
|
|
3146
|
-
|
|
3147
|
-
|
|
3148
|
-
|
|
3149
|
-
|
|
3150
|
-
|
|
3151
|
-
|
|
3152
|
-
|
|
3153
|
-
|
|
3154
|
-
|
|
3155
|
-
|
|
3156
|
-
|
|
3157
|
-
|
|
3158
|
-
|
|
3159
|
-
|
|
3160
|
-
|
|
3161
|
-
|
|
3162
|
-
|
|
3163
|
-
|
|
3164
|
-
|
|
3165
|
-
|
|
3166
|
-
|
|
3167
|
-
|
|
3168
|
-
|
|
3169
|
-
|
|
3170
|
-
|
|
3171
|
-
|
|
3172
|
-
|
|
3173
|
-
|
|
3174
|
-
|
|
3175
|
-
|
|
3176
|
-
|
|
3177
|
-
|
|
3178
|
-
|
|
3179
|
-
|
|
3180
|
-
|
|
3181
|
-
|
|
3163
|
+
hasLocales ? /* @__PURE__ */ jsxRuntime.jsx(ui.Card, { marginTop: 2, shadow: 1, padding: 3, radius: 1, children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Stack, { space: 2, children: [
|
|
3164
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.TabList, { space: 2, children: locales.map((locale, idx) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
3165
|
+
ui.Tab,
|
|
3166
|
+
{
|
|
3167
|
+
id: `locale-tab-${locale.id}`,
|
|
3168
|
+
"aria-controls": `locale-panel-${locale.id}`,
|
|
3169
|
+
selected: activeLocaleTab === idx,
|
|
3170
|
+
onClick: () => setActiveLocaleTab(idx),
|
|
3171
|
+
label: locale.title
|
|
3172
|
+
},
|
|
3173
|
+
locale.id
|
|
3174
|
+
)) }),
|
|
3175
|
+
locales.map((locale, idx) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
3176
|
+
ui.TabPanel,
|
|
3177
|
+
{
|
|
3178
|
+
id: `locale-panel-${locale.id}`,
|
|
3179
|
+
"aria-labelledby": `locale-tab-${locale.id}`,
|
|
3180
|
+
hidden: activeLocaleTab !== idx,
|
|
3181
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Stack, { space: 3, children: [
|
|
3182
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3183
|
+
FormFieldInputText,
|
|
3184
|
+
{
|
|
3185
|
+
...register(`title.${locale.id}`),
|
|
3186
|
+
disabled: formUpdating,
|
|
3187
|
+
error: errors?.title?.[locale.id]?.message,
|
|
3188
|
+
label: "Title",
|
|
3189
|
+
name: `title.${locale.id}`
|
|
3190
|
+
}
|
|
3191
|
+
),
|
|
3192
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3193
|
+
FormFieldInputText,
|
|
3194
|
+
{
|
|
3195
|
+
...register(`altText.${locale.id}`),
|
|
3196
|
+
disabled: formUpdating,
|
|
3197
|
+
error: errors?.altText?.[locale.id]?.message,
|
|
3198
|
+
label: "Alt Text",
|
|
3199
|
+
name: `altText.${locale.id}`
|
|
3200
|
+
}
|
|
3201
|
+
),
|
|
3202
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3203
|
+
FormFieldInputTextarea,
|
|
3204
|
+
{
|
|
3205
|
+
...register(`description.${locale.id}`),
|
|
3206
|
+
disabled: formUpdating,
|
|
3207
|
+
error: errors?.description?.[locale.id]?.message,
|
|
3208
|
+
label: "Description",
|
|
3209
|
+
name: `description.${locale.id}`,
|
|
3210
|
+
rows: 5
|
|
3211
|
+
}
|
|
3212
|
+
),
|
|
3213
|
+
creditLine?.enabled && /* @__PURE__ */ jsxRuntime.jsx(
|
|
3214
|
+
FormFieldInputText,
|
|
3215
|
+
{
|
|
3216
|
+
...register(`creditLine.${locale.id}`),
|
|
3217
|
+
error: errors?.creditLine?.[locale.id]?.message,
|
|
3218
|
+
label: "Credit",
|
|
3219
|
+
name: `creditLine.${locale.id}`,
|
|
3220
|
+
disabled: formUpdating || creditLine?.excludeSources?.includes(currentAsset?.source?.name)
|
|
3221
|
+
}
|
|
3222
|
+
)
|
|
3223
|
+
] })
|
|
3224
|
+
},
|
|
3225
|
+
locale.id
|
|
3226
|
+
))
|
|
3227
|
+
] }) }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
3228
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3229
|
+
FormFieldInputText,
|
|
3230
|
+
{
|
|
3231
|
+
...register("title"),
|
|
3232
|
+
disabled: formUpdating,
|
|
3233
|
+
error: errors?.title?.message,
|
|
3234
|
+
label: "Title",
|
|
3235
|
+
name: "title",
|
|
3236
|
+
value: toStringField(currentAsset?.title)
|
|
3237
|
+
}
|
|
3238
|
+
),
|
|
3239
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3240
|
+
FormFieldInputText,
|
|
3241
|
+
{
|
|
3242
|
+
...register("altText"),
|
|
3243
|
+
disabled: formUpdating,
|
|
3244
|
+
error: errors?.altText?.message,
|
|
3245
|
+
label: "Alt Text",
|
|
3246
|
+
name: "altText",
|
|
3247
|
+
value: toStringField(currentAsset?.altText)
|
|
3248
|
+
}
|
|
3249
|
+
),
|
|
3250
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3251
|
+
FormFieldInputTextarea,
|
|
3252
|
+
{
|
|
3253
|
+
...register("description"),
|
|
3254
|
+
disabled: formUpdating,
|
|
3255
|
+
error: errors?.description?.message,
|
|
3256
|
+
label: "Description",
|
|
3257
|
+
name: "description",
|
|
3258
|
+
rows: 5,
|
|
3259
|
+
value: toStringField(currentAsset?.description)
|
|
3260
|
+
}
|
|
3261
|
+
),
|
|
3262
|
+
creditLine?.enabled && /* @__PURE__ */ jsxRuntime.jsx(
|
|
3263
|
+
FormFieldInputText,
|
|
3264
|
+
{
|
|
3265
|
+
...register("creditLine"),
|
|
3266
|
+
error: errors?.creditLine?.message,
|
|
3267
|
+
label: "Credit",
|
|
3268
|
+
name: "creditLine",
|
|
3269
|
+
value: toStringField(currentAsset?.creditLine),
|
|
3270
|
+
disabled: formUpdating || creditLine?.excludeSources?.includes(currentAsset?.source?.name)
|
|
3271
|
+
}
|
|
3272
|
+
)
|
|
3273
|
+
] })
|
|
3182
3274
|
] });
|
|
3183
3275
|
}
|
|
3184
3276
|
function renderDefaultDetails(props) {
|
|
@@ -3188,16 +3280,37 @@ const DialogAssetEdit = (props) => {
|
|
|
3188
3280
|
const {
|
|
3189
3281
|
children,
|
|
3190
3282
|
dialog: { assetId, id, lastCreatedTag, lastRemovedTagIds }
|
|
3191
|
-
} = props, client = useVersionedClient(), scheme = sanity.useColorSchemeValue(), documentStore = sanity.useDocumentStore(), dispatch = reactRedux.useDispatch(), assetItem = useTypedSelector((state) => selectAssetById(state, String(assetId))), tags = useTypedSelector(selectTags), assetUpdatedPrev = react.useRef(void 0), [assetSnapshot, setAssetSnapshot] = react.useState(assetItem?.asset), [tabSection, setTabSection] = react.useState("details"), currentAsset = assetItem ? assetItem?.asset : assetSnapshot, allTagOptions = getTagSelectOptions(tags), assetTagOptions = useTypedSelector(selectTagSelectOptions(currentAsset)), { creditLine, components: { details: CustomDetails } = {} } = useToolOptions(), generateDefaultValues = react.useCallback(
|
|
3192
|
-
(asset) =>
|
|
3193
|
-
|
|
3194
|
-
|
|
3195
|
-
|
|
3196
|
-
|
|
3197
|
-
|
|
3198
|
-
|
|
3199
|
-
|
|
3200
|
-
|
|
3283
|
+
} = props, client = useVersionedClient(), scheme = sanity.useColorSchemeValue(), documentStore = sanity.useDocumentStore(), dispatch = reactRedux.useDispatch(), assetItem = useTypedSelector((state) => selectAssetById(state, String(assetId))), tags = useTypedSelector(selectTags), assetUpdatedPrev = react.useRef(void 0), [assetSnapshot, setAssetSnapshot] = react.useState(assetItem?.asset), [tabSection, setTabSection] = react.useState("details"), currentAsset = assetItem ? assetItem?.asset : assetSnapshot, allTagOptions = getTagSelectOptions(tags), assetTagOptions = useTypedSelector(selectTagSelectOptions(currentAsset)), { creditLine, components: { details: CustomDetails } = {}, locales } = useToolOptions(), generateDefaultValues = react.useCallback(
|
|
3284
|
+
(asset) => {
|
|
3285
|
+
if (locales && locales.length > 0) {
|
|
3286
|
+
const makeLocaleObj = (field) => {
|
|
3287
|
+
const obj = {};
|
|
3288
|
+
for (let i = 0; i < locales.length; i++) {
|
|
3289
|
+
const locale = locales[i];
|
|
3290
|
+
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] = "";
|
|
3291
|
+
}
|
|
3292
|
+
return obj;
|
|
3293
|
+
};
|
|
3294
|
+
return {
|
|
3295
|
+
altText: makeLocaleObj(asset?.altText),
|
|
3296
|
+
creditLine: makeLocaleObj(asset?.creditLine),
|
|
3297
|
+
description: makeLocaleObj(asset?.description),
|
|
3298
|
+
originalFilename: asset?.originalFilename || "",
|
|
3299
|
+
opt: { media: { tags: assetTagOptions } },
|
|
3300
|
+
title: makeLocaleObj(asset?.title)
|
|
3301
|
+
};
|
|
3302
|
+
}
|
|
3303
|
+
const flattenField = (field) => typeof field == "string" ? field : typeof field == "object" && field !== null && Object.values(field).find((v) => v) || "";
|
|
3304
|
+
return {
|
|
3305
|
+
altText: flattenField(asset?.altText),
|
|
3306
|
+
creditLine: flattenField(asset?.creditLine),
|
|
3307
|
+
description: flattenField(asset?.description),
|
|
3308
|
+
originalFilename: asset?.originalFilename || "",
|
|
3309
|
+
opt: { media: { tags: assetTagOptions } },
|
|
3310
|
+
title: flattenField(asset?.title)
|
|
3311
|
+
};
|
|
3312
|
+
},
|
|
3313
|
+
[assetTagOptions, locales]
|
|
3201
3314
|
), {
|
|
3202
3315
|
control,
|
|
3203
3316
|
// Read the formState before render to subscribe the form state through Proxy
|
|
@@ -3210,7 +3323,7 @@ const DialogAssetEdit = (props) => {
|
|
|
3210
3323
|
} = reactHookForm.useForm({
|
|
3211
3324
|
defaultValues: generateDefaultValues(assetItem?.asset),
|
|
3212
3325
|
mode: "onChange",
|
|
3213
|
-
resolver: zod.zodResolver(
|
|
3326
|
+
resolver: zod.zodResolver(getAssetFormSchema(locales))
|
|
3214
3327
|
}), formUpdating = !assetItem || assetItem?.updating, handleClose = react.useCallback(() => {
|
|
3215
3328
|
dispatch(dialogActions.remove({ id }));
|
|
3216
3329
|
}, [dispatch, id]), handleDelete = react.useCallback(() => {
|
|
@@ -3233,7 +3346,39 @@ const DialogAssetEdit = (props) => {
|
|
|
3233
3346
|
);
|
|
3234
3347
|
},
|
|
3235
3348
|
[currentAsset?._id, dispatch]
|
|
3236
|
-
),
|
|
3349
|
+
), hasOrphanedLocales = react.useMemo(() => {
|
|
3350
|
+
if (!currentAsset) return !1;
|
|
3351
|
+
const isLocaleObj = (v) => typeof v == "object" && v !== null && !Array.isArray(v), fields = [
|
|
3352
|
+
currentAsset.title,
|
|
3353
|
+
currentAsset.altText,
|
|
3354
|
+
currentAsset.description,
|
|
3355
|
+
...currentAsset._type === "sanity.imageAsset" ? [currentAsset.creditLine] : []
|
|
3356
|
+
];
|
|
3357
|
+
if (!fields.some((f) => isLocaleObj(f))) return !1;
|
|
3358
|
+
if (!locales || locales.length === 0) return !0;
|
|
3359
|
+
const configuredIds = new Set(locales.map((l) => l.id));
|
|
3360
|
+
return fields.some((f) => isLocaleObj(f) ? Object.keys(f).some((k) => !configuredIds.has(k)) : !1);
|
|
3361
|
+
}, [currentAsset, locales]), handleCleanupLocales = react.useCallback(async () => {
|
|
3362
|
+
if (!currentAsset) return;
|
|
3363
|
+
const cleanField = (field) => {
|
|
3364
|
+
if (typeof field != "object" || field === null || Array.isArray(field)) return field;
|
|
3365
|
+
const obj = field;
|
|
3366
|
+
if (!locales || locales.length === 0)
|
|
3367
|
+
return Object.keys(obj).sort().map((k) => obj[k]).find((v) => v) || "";
|
|
3368
|
+
const configuredIds = new Set(locales.map((l) => l.id)), cleaned = {};
|
|
3369
|
+
for (const [key, val] of Object.entries(obj))
|
|
3370
|
+
configuredIds.has(key) && (cleaned[key] = val);
|
|
3371
|
+
return cleaned;
|
|
3372
|
+
};
|
|
3373
|
+
await client.patch(currentAsset._id).set({
|
|
3374
|
+
title: cleanField(currentAsset.title),
|
|
3375
|
+
altText: cleanField(currentAsset.altText),
|
|
3376
|
+
description: cleanField(currentAsset.description),
|
|
3377
|
+
...currentAsset._type === "sanity.imageAsset" && {
|
|
3378
|
+
creditLine: cleanField(currentAsset.creditLine)
|
|
3379
|
+
}
|
|
3380
|
+
}).commit();
|
|
3381
|
+
}, [client, currentAsset, locales]), onSubmit = react.useCallback(
|
|
3237
3382
|
(formData) => {
|
|
3238
3383
|
if (!assetItem?.asset)
|
|
3239
3384
|
return;
|
|
@@ -3281,27 +3426,42 @@ const DialogAssetEdit = (props) => {
|
|
|
3281
3426
|
}, [getValues, lastRemovedTagIds, setValue]), react.useEffect(() => {
|
|
3282
3427
|
assetUpdatedPrev.current !== assetItem?.asset._updatedAt && reset(generateDefaultValues(assetItem?.asset)), assetUpdatedPrev.current = assetItem?.asset._updatedAt;
|
|
3283
3428
|
}, [assetItem?.asset, generateDefaultValues, reset]);
|
|
3284
|
-
const Footer = () => /* @__PURE__ */ jsxRuntime.jsx(ui.Box, { padding: 3, children: /* @__PURE__ */ jsxRuntime.jsxs(ui.
|
|
3285
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3286
|
-
ui.
|
|
3287
|
-
|
|
3288
|
-
|
|
3289
|
-
|
|
3290
|
-
|
|
3291
|
-
|
|
3292
|
-
|
|
3293
|
-
|
|
3294
|
-
|
|
3295
|
-
|
|
3296
|
-
|
|
3297
|
-
|
|
3298
|
-
|
|
3299
|
-
|
|
3300
|
-
|
|
3301
|
-
|
|
3302
|
-
|
|
3303
|
-
|
|
3304
|
-
|
|
3429
|
+
const Footer = () => /* @__PURE__ */ jsxRuntime.jsx(ui.Box, { padding: 3, children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Stack, { space: 3, children: [
|
|
3430
|
+
hasOrphanedLocales && /* @__PURE__ */ jsxRuntime.jsx(ui.Card, { padding: 3, radius: 2, shadow: 1, tone: "caution", children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Flex, { align: "center", justify: "space-between", gap: 3, children: [
|
|
3431
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: 1, children: "This asset has localized fields that are no longer configured. Clean them up to avoid validation errors." }),
|
|
3432
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3433
|
+
ui.Button,
|
|
3434
|
+
{
|
|
3435
|
+
fontSize: 1,
|
|
3436
|
+
mode: "ghost",
|
|
3437
|
+
onClick: handleCleanupLocales,
|
|
3438
|
+
text: "Cleanup localized fields",
|
|
3439
|
+
tone: "caution"
|
|
3440
|
+
}
|
|
3441
|
+
)
|
|
3442
|
+
] }) }),
|
|
3443
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Flex, { justify: "space-between", children: [
|
|
3444
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3445
|
+
ui.Button,
|
|
3446
|
+
{
|
|
3447
|
+
disabled: formUpdating,
|
|
3448
|
+
fontSize: 1,
|
|
3449
|
+
mode: "bleed",
|
|
3450
|
+
onClick: handleDelete,
|
|
3451
|
+
text: "Delete",
|
|
3452
|
+
tone: "critical"
|
|
3453
|
+
}
|
|
3454
|
+
),
|
|
3455
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3456
|
+
FormSubmitButton,
|
|
3457
|
+
{
|
|
3458
|
+
disabled: formUpdating || !isDirty || !isValid || hasOrphanedLocales,
|
|
3459
|
+
isValid,
|
|
3460
|
+
lastUpdated: currentAsset?._updatedAt,
|
|
3461
|
+
onClick: handleSubmit(onSubmit)
|
|
3462
|
+
}
|
|
3463
|
+
)
|
|
3464
|
+
] })
|
|
3305
3465
|
] }) });
|
|
3306
3466
|
if (!currentAsset)
|
|
3307
3467
|
return null;
|
|
@@ -3315,7 +3475,8 @@ const DialogAssetEdit = (props) => {
|
|
|
3315
3475
|
allTagOptions,
|
|
3316
3476
|
handleCreateTag,
|
|
3317
3477
|
currentAsset,
|
|
3318
|
-
creditLine
|
|
3478
|
+
creditLine,
|
|
3479
|
+
locales
|
|
3319
3480
|
};
|
|
3320
3481
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3321
3482
|
Dialog,
|
|
@@ -4009,7 +4170,7 @@ const DialogAssetEdit = (props) => {
|
|
|
4009
4170
|
`
|
|
4010
4171
|
), StyledWarningOutlineIcon = styledComponents.styled(icons.WarningFilledIcon)(({ theme }) => ({
|
|
4011
4172
|
color: theme.sanity.color.spot.red
|
|
4012
|
-
})), CardAsset = (props) => {
|
|
4173
|
+
})), CardAsset$1 = (props) => {
|
|
4013
4174
|
const { id, selected } = props, scheme = sanity.useColorSchemeValue(), shiftPressed = useKeyPress("shift"), dispatch = reactRedux.useDispatch(), lastPicked = useTypedSelector((state) => state.assets.lastPicked), item = useTypedSelector((state) => selectAssetById(state, id)), asset = item?.asset, error = item?.error, isOpaque = item?.asset?.metadata?.isOpaque, picked = item?.picked, updating = item?.updating, { onSelect } = useAssetSourceActions();
|
|
4014
4175
|
if (!asset)
|
|
4015
4176
|
return null;
|
|
@@ -4139,7 +4300,7 @@ const DialogAssetEdit = (props) => {
|
|
|
4139
4300
|
)
|
|
4140
4301
|
] }) });
|
|
4141
4302
|
};
|
|
4142
|
-
var CardAsset
|
|
4303
|
+
var CardAsset = react.memo(CardAsset$1);
|
|
4143
4304
|
const PREVIEW_WIDTH = 180, createBlob = (img) => new Promise((resolve) => {
|
|
4144
4305
|
const imageAspect = img.width / img.height, canvas = document.createElement("canvas");
|
|
4145
4306
|
canvas.width = PREVIEW_WIDTH, canvas.height = Math.max(PREVIEW_WIDTH / imageAspect, 1);
|
|
@@ -4496,7 +4657,7 @@ const CardWrapper = styledComponents.styled(ui.Flex)`
|
|
|
4496
4657
|
}
|
|
4497
4658
|
) });
|
|
4498
4659
|
}, CARD_HEIGHT = 220, CARD_WIDTH = 240, VirtualCell = react.memo(
|
|
4499
|
-
({ item, selected }) => item?.type === "asset" ? /* @__PURE__ */ jsxRuntime.jsx(CardAsset
|
|
4660
|
+
({ item, selected }) => item?.type === "asset" ? /* @__PURE__ */ jsxRuntime.jsx(CardAsset, { id: item.id, selected }) : item?.type === "upload" ? /* @__PURE__ */ jsxRuntime.jsx(CardUpload, { id: item.id }) : null
|
|
4500
4661
|
), StyledItemContainer = styledComponents.styled.div`
|
|
4501
4662
|
height: ${CARD_HEIGHT}px;
|
|
4502
4663
|
width: ${CARD_WIDTH}px;
|
|
@@ -4661,7 +4822,7 @@ const CardWrapper = styledComponents.styled(ui.Flex)`
|
|
|
4661
4822
|
`
|
|
4662
4823
|
), StyledWarningIcon = styledComponents.styled(icons.WarningFilledIcon)(({ theme }) => ({
|
|
4663
4824
|
color: theme.sanity.color.spot.red
|
|
4664
|
-
})), TableRowAsset = (props) => {
|
|
4825
|
+
})), TableRowAsset$1 = (props) => {
|
|
4665
4826
|
const { id, selected } = props, scheme = sanity.useColorSchemeValue(), shiftPressed = useKeyPress("shift"), [referenceCountVisible, setReferenceCountVisible] = react.useState(!1), refCountVisibleTimeout = react.useRef(null), dispatch = reactRedux.useDispatch(), lastPicked = useTypedSelector((state) => state.assets.lastPicked), item = useTypedSelector((state) => selectAssetById(state, id)), mediaIndex = ui.useMediaIndex(), asset = item?.asset, error = item?.error, isOpaque = item?.asset?.metadata?.isOpaque, picked = item?.picked, updating = item?.updating, { onSelect } = useAssetSourceActions(), handleContextActionClick = react.useCallback(
|
|
4666
4827
|
(e) => {
|
|
4667
4828
|
e.stopPropagation(), asset && (onSelect ? dispatch(dialogActions.showAssetEdit({ assetId: asset._id })) : shiftPressed.current && !picked ? dispatch(assetsActions.pickRange({ startId: lastPicked || asset._id, endId: asset._id })) : dispatch(assetsActions.pick({ assetId: asset._id, picked: !picked })));
|
|
@@ -4887,7 +5048,7 @@ const CardWrapper = styledComponents.styled(ui.Flex)`
|
|
|
4887
5048
|
}
|
|
4888
5049
|
) : null;
|
|
4889
5050
|
};
|
|
4890
|
-
var TableRowAsset
|
|
5051
|
+
var TableRowAsset = react.memo(TableRowAsset$1);
|
|
4891
5052
|
const TableRowUpload = (props) => {
|
|
4892
5053
|
const { id } = props, scheme = sanity.useColorSchemeValue(), dispatch = reactRedux.useDispatch(), item = useTypedSelector((state) => selectUploadById(state, id)), mediaIndex = ui.useMediaIndex();
|
|
4893
5054
|
if (!item)
|
|
@@ -5001,7 +5162,7 @@ const TableRowUpload = (props) => {
|
|
|
5001
5162
|
}
|
|
5002
5163
|
);
|
|
5003
5164
|
}, VirtualRow = react.memo(
|
|
5004
|
-
({ item, selected }) => item?.type === "asset" ? /* @__PURE__ */ jsxRuntime.jsx(ui.Box, { style: { height: "100px" }, children: /* @__PURE__ */ jsxRuntime.jsx(TableRowAsset
|
|
5165
|
+
({ item, selected }) => item?.type === "asset" ? /* @__PURE__ */ jsxRuntime.jsx(ui.Box, { style: { height: "100px" }, children: /* @__PURE__ */ jsxRuntime.jsx(TableRowAsset, { id: item.id, selected }) }) : item?.type === "upload" ? /* @__PURE__ */ jsxRuntime.jsx(ui.Box, { style: { height: "100px" }, children: /* @__PURE__ */ jsxRuntime.jsx(TableRowUpload, { id: item.id }) }) : null
|
|
5005
5166
|
), AssetTableVirtualized = (props) => {
|
|
5006
5167
|
const { items, onLoadMore } = props, selectedAssets = useTypedSelector((state) => state.selected.assets), selectedIds = selectedAssets && selectedAssets.map((asset) => asset._id) || [], totalCount = items?.length;
|
|
5007
5168
|
return totalCount === 0 ? null : /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -5101,6 +5262,9 @@ const TableRowUpload = (props) => {
|
|
|
5101
5262
|
reducers: {}
|
|
5102
5263
|
});
|
|
5103
5264
|
var selectedReducer = selectedSlice.reducer;
|
|
5265
|
+
function messageFromGenericErrorPayload(payload) {
|
|
5266
|
+
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";
|
|
5267
|
+
}
|
|
5104
5268
|
const initialState = {
|
|
5105
5269
|
items: []
|
|
5106
5270
|
}, notificationsSlice = toolkit.createSlice({
|
|
@@ -5187,11 +5351,11 @@ const initialState = {
|
|
|
5187
5351
|
uploadsActions.uploadError.type
|
|
5188
5352
|
),
|
|
5189
5353
|
operators$1.mergeMap((action) => {
|
|
5190
|
-
const
|
|
5354
|
+
const title = `An error occurred: ${messageFromGenericErrorPayload(action.payload)}`;
|
|
5191
5355
|
return rxjs.of(
|
|
5192
5356
|
notificationsSlice.actions.add({
|
|
5193
5357
|
status: "error",
|
|
5194
|
-
title
|
|
5358
|
+
title
|
|
5195
5359
|
})
|
|
5196
5360
|
);
|
|
5197
5361
|
})
|
|
@@ -5264,6 +5428,9 @@ const rootEpic = reduxObservable.combineEpics(
|
|
|
5264
5428
|
const assetIds = getAssetIds(document2);
|
|
5265
5429
|
return [...new Set(assetIds.sort())];
|
|
5266
5430
|
};
|
|
5431
|
+
function isSupportedAssetType(assetType) {
|
|
5432
|
+
return assetType ? SUPPORTED_ASSET_TYPES.includes(assetType) : !1;
|
|
5433
|
+
}
|
|
5267
5434
|
class ReduxProvider extends react.Component {
|
|
5268
5435
|
store;
|
|
5269
5436
|
constructor(props) {
|
|
@@ -5294,7 +5461,7 @@ class ReduxProvider extends react.Component {
|
|
|
5294
5461
|
preloadedState: {
|
|
5295
5462
|
assets: {
|
|
5296
5463
|
...initialState$5,
|
|
5297
|
-
assetTypes: props?.assetType ? [props.assetType] : ["file", "image"]
|
|
5464
|
+
assetTypes: isSupportedAssetType(props?.assetType) ? [props.assetType] : ["file", "image"]
|
|
5298
5465
|
},
|
|
5299
5466
|
debug: {
|
|
5300
5467
|
badConnection: !1,
|