@sanity/cross-dataset-duplicator 1.4.1 → 1.5.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/README.md +5 -1
- package/dist/index.d.mts +81 -0
- package/dist/index.d.ts +3 -4
- package/dist/index.js +413 -885
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +654 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +26 -31
- package/src/components/CrossDatasetDuplicator.tsx +1 -1
- package/src/components/Duplicator.tsx +3 -5
- package/src/components/DuplicatorQuery.tsx +3 -10
- package/src/components/DuplicatorWrapper.tsx +2 -3
- package/src/components/ResetSecret.tsx +6 -3
- package/src/context/ConfigProvider.tsx +1 -1
- package/src/helpers/constants.ts +2 -1
- package/src/plugin.tsx +1 -1
- package/src/types/index.ts +1 -0
- package/dist/index.cjs.mjs +0 -7
- package/dist/index.esm.js +0 -1104
- package/dist/index.esm.js.map +0 -1
- package/src/helpers/clientConfig.ts +0 -1
package/dist/index.js
CHANGED
|
@@ -1,69 +1,40 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
var sanity = require('sanity');
|
|
7
|
-
var jsxRuntime = require('react/jsx-runtime');
|
|
8
|
-
var React = require('react');
|
|
9
|
-
var icons = require('@sanity/icons');
|
|
10
|
-
var studioSecrets = require('@sanity/studio-secrets');
|
|
11
|
-
var ui = require('@sanity/ui');
|
|
12
|
-
var mapLimit = require('async/mapLimit');
|
|
13
|
-
var asyncify = require('async/asyncify');
|
|
14
|
-
var mutator = require('@sanity/mutator');
|
|
15
|
-
var dset = require('dset');
|
|
16
|
-
var assetUtils = require('@sanity/asset-utils');
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: !0 });
|
|
3
|
+
var sanity = require("sanity"), jsxRuntime = require("react/jsx-runtime"), React = require("react"), icons = require("@sanity/icons"), studioSecrets = require("@sanity/studio-secrets"), ui = require("@sanity/ui"), mapLimit = require("async/mapLimit"), asyncify = require("async/asyncify"), mutator = require("@sanity/mutator"), dset = require("dset"), assetUtils = require("@sanity/asset-utils");
|
|
17
4
|
function _interopDefaultCompat(e) {
|
|
18
|
-
return e && typeof e
|
|
19
|
-
default: e
|
|
20
|
-
};
|
|
5
|
+
return e && typeof e == "object" && "default" in e ? e : { default: e };
|
|
21
6
|
}
|
|
22
|
-
var React__default =
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
7
|
+
var React__default = /* @__PURE__ */ _interopDefaultCompat(React), mapLimit__default = /* @__PURE__ */ _interopDefaultCompat(mapLimit), asyncify__default = /* @__PURE__ */ _interopDefaultCompat(asyncify);
|
|
8
|
+
function createInitialMessage(docCount = 0, refsCount = 0) {
|
|
9
|
+
return [
|
|
10
|
+
docCount === 1 ? "This Document contains" : `These ${docCount} Documents contain`,
|
|
11
|
+
refsCount === 1 ? "1 Reference." : `${refsCount} References.`,
|
|
12
|
+
refsCount === 1 ? "That Document" : "Those Documents",
|
|
13
|
+
"may have References too. If referenced Documents do not exist at the target Destination, this transaction will fail."
|
|
14
|
+
].join(" ");
|
|
30
15
|
}
|
|
31
|
-
const stickyStyles =
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
backgroundColor: isDarkMode ? "rgba(10,10,10,0.95)" : "rgba(255,255,255,0.95)"
|
|
38
|
-
};
|
|
39
|
-
};
|
|
16
|
+
const stickyStyles = (isDarkMode = !0) => ({
|
|
17
|
+
position: "sticky",
|
|
18
|
+
top: 0,
|
|
19
|
+
zIndex: 100,
|
|
20
|
+
backgroundColor: isDarkMode ? "rgba(10,10,10,0.95)" : "rgba(255,255,255,0.95)"
|
|
21
|
+
});
|
|
40
22
|
async function getDocumentsInArray(options) {
|
|
41
|
-
const {
|
|
42
|
-
fetchIds
|
|
43
|
-
client,
|
|
44
|
-
pluginConfig,
|
|
45
|
-
currentIds,
|
|
46
|
-
projection
|
|
47
|
-
} = options;
|
|
48
|
-
const collection = [];
|
|
49
|
-
const filter = ["_id in $fetchIds", pluginConfig.filter].filter(Boolean).join(" && ");
|
|
50
|
-
const query = "*[".concat(filter, "]").concat(projection != null ? projection : "");
|
|
51
|
-
const data = await client.fetch(query, {
|
|
52
|
-
fetchIds: fetchIds != null ? fetchIds : []
|
|
23
|
+
const { fetchIds, client, pluginConfig, currentIds, projection } = options, collection = [], query = `*[${["_id in $fetchIds", pluginConfig.filter].filter(Boolean).join(" && ")}]${projection ?? ""}`, data = await client.fetch(query, {
|
|
24
|
+
fetchIds: fetchIds ?? []
|
|
53
25
|
});
|
|
54
|
-
if (!
|
|
26
|
+
if (!data?.length)
|
|
55
27
|
return [];
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
await Promise.all(data.map(async doc => {
|
|
63
|
-
const expr = ".._ref";
|
|
64
|
-
const references = mutator.extractWithPath(expr, doc).map(ref => ref.value);
|
|
28
|
+
const localCurrentIds = currentIds ?? /* @__PURE__ */ new Set(), newDataIds = new Set(
|
|
29
|
+
data.map((dataDoc) => dataDoc._id).filter((id) => currentIds?.size ? !localCurrentIds.has(id) : !!id)
|
|
30
|
+
);
|
|
31
|
+
return newDataIds.size && (collection.push(...data), localCurrentIds.add(...newDataIds), await Promise.all(
|
|
32
|
+
data.map(async (doc) => {
|
|
33
|
+
const references = mutator.extractWithPath(".._ref", doc).map((ref) => ref.value);
|
|
65
34
|
if (references.length) {
|
|
66
|
-
const newReferenceIds = new Set(
|
|
35
|
+
const newReferenceIds = new Set(
|
|
36
|
+
references.filter((ref) => !localCurrentIds.has(ref))
|
|
37
|
+
);
|
|
67
38
|
if (newReferenceIds.size) {
|
|
68
39
|
const referenceDocs = await getDocumentsInArray({
|
|
69
40
|
fetchIds: Array.from(newReferenceIds),
|
|
@@ -71,84 +42,63 @@ async function getDocumentsInArray(options) {
|
|
|
71
42
|
client,
|
|
72
43
|
pluginConfig
|
|
73
44
|
});
|
|
74
|
-
|
|
75
|
-
collection.push(...referenceDocs);
|
|
76
|
-
}
|
|
45
|
+
referenceDocs?.length && collection.push(...referenceDocs);
|
|
77
46
|
}
|
|
78
47
|
}
|
|
79
|
-
})
|
|
80
|
-
|
|
81
|
-
const uniqueCollection = collection.filter(Boolean).reduce((acc, cur) => {
|
|
82
|
-
if (acc.some(doc => doc._id === cur._id)) {
|
|
83
|
-
return acc;
|
|
84
|
-
}
|
|
85
|
-
return [...acc, cur];
|
|
86
|
-
}, []);
|
|
87
|
-
return uniqueCollection;
|
|
48
|
+
})
|
|
49
|
+
)), collection.filter(Boolean).reduce((acc, cur) => acc.some((doc) => doc._id === cur._id) ? acc : [...acc, cur], []);
|
|
88
50
|
}
|
|
89
51
|
const buttons = ["All", "None", null, "New", "Existing", "Older", null, "Documents", "Assets"];
|
|
90
52
|
function SelectButtons(props) {
|
|
91
|
-
const {
|
|
92
|
-
payload,
|
|
93
|
-
setPayload
|
|
94
|
-
} = props;
|
|
95
|
-
const [disabledActions, setDisabledActions] = React.useState([]);
|
|
53
|
+
const { payload, setPayload } = props, [disabledActions, setDisabledActions] = React.useState([]);
|
|
96
54
|
React.useEffect(() => {
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
}
|
|
100
|
-
}, [disabledActions == null ? void 0 : disabledActions.length, payload]);
|
|
55
|
+
!disabledActions?.length && payload.every((item) => item.include) && setDisabledActions(["ALL"]);
|
|
56
|
+
}, [disabledActions?.length, payload]);
|
|
101
57
|
function handleSelectButton(action) {
|
|
102
58
|
if (!action || !payload.length) return;
|
|
103
59
|
const newPayload = [...payload];
|
|
104
60
|
switch (action) {
|
|
105
61
|
case "ALL":
|
|
106
|
-
newPayload.map(item => item.include =
|
|
62
|
+
newPayload.map((item) => item.include = !0);
|
|
107
63
|
break;
|
|
108
64
|
case "NONE":
|
|
109
|
-
newPayload.map(item => item.include =
|
|
65
|
+
newPayload.map((item) => item.include = !1);
|
|
110
66
|
break;
|
|
111
67
|
case "NEW":
|
|
112
|
-
newPayload.map(item => item.include =
|
|
68
|
+
newPayload.map((item) => item.include = item.status === "CREATE");
|
|
113
69
|
break;
|
|
114
70
|
case "EXISTING":
|
|
115
|
-
newPayload.map(item => item.include =
|
|
71
|
+
newPayload.map((item) => item.include = item.status === "EXISTS");
|
|
116
72
|
break;
|
|
117
73
|
case "OLDER":
|
|
118
|
-
newPayload.map(item => item.include =
|
|
74
|
+
newPayload.map((item) => item.include = item.status === "OVERWRITE");
|
|
119
75
|
break;
|
|
120
76
|
case "ASSETS":
|
|
121
|
-
newPayload.map(item => item.include = assetUtils.isAssetId(item.doc._id));
|
|
77
|
+
newPayload.map((item) => item.include = assetUtils.isAssetId(item.doc._id));
|
|
122
78
|
break;
|
|
123
79
|
case "DOCUMENTS":
|
|
124
|
-
newPayload.map(item => item.include = !assetUtils.isAssetId(item.doc._id));
|
|
80
|
+
newPayload.map((item) => item.include = !assetUtils.isAssetId(item.doc._id));
|
|
125
81
|
break;
|
|
126
82
|
}
|
|
127
|
-
setDisabledActions([action]);
|
|
128
|
-
setPayload(newPayload);
|
|
83
|
+
setDisabledActions([action]), setPayload(newPayload);
|
|
129
84
|
}
|
|
130
|
-
return /* @__PURE__ */jsxRuntime.jsx(ui.Card, {
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
children: /* @__PURE__ */jsxRuntime.jsx(ui.Flex, {
|
|
135
|
-
gap: 2,
|
|
136
|
-
wrap: "wrap",
|
|
137
|
-
children: buttons.map((action, actionIndex) => action ? /* @__PURE__ */jsxRuntime.jsx(ui.Button, {
|
|
85
|
+
return /* @__PURE__ */ jsxRuntime.jsx(ui.Card, { padding: 1, radius: 3, shadow: 1, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Flex, { gap: 2, wrap: "wrap", children: buttons.map(
|
|
86
|
+
(action, actionIndex) => action ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
87
|
+
ui.Button,
|
|
88
|
+
{
|
|
138
89
|
fontSize: 1,
|
|
139
90
|
mode: "bleed",
|
|
140
91
|
padding: 2,
|
|
141
92
|
text: action,
|
|
142
93
|
disabled: disabledActions.includes(action.toUpperCase()),
|
|
143
94
|
onClick: () => handleSelectButton(action.toUpperCase())
|
|
144
|
-
},
|
|
95
|
+
},
|
|
96
|
+
action
|
|
97
|
+
) : (
|
|
145
98
|
// eslint-disable-next-line react/no-array-index-key
|
|
146
|
-
/* @__PURE__ */
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
}, "divider-".concat(actionIndex)))
|
|
150
|
-
})
|
|
151
|
-
});
|
|
99
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Card, { borderLeft: !0 }, `divider-${actionIndex}`)
|
|
100
|
+
)
|
|
101
|
+
) }) });
|
|
152
102
|
}
|
|
153
103
|
const documentTones = {
|
|
154
104
|
EXISTS: "primary",
|
|
@@ -156,15 +106,13 @@ const documentTones = {
|
|
|
156
106
|
UPDATE: "caution",
|
|
157
107
|
CREATE: "positive",
|
|
158
108
|
UNPUBLISHED: "caution"
|
|
159
|
-
}
|
|
160
|
-
const assetTones = {
|
|
109
|
+
}, assetTones = {
|
|
161
110
|
EXISTS: "critical",
|
|
162
111
|
OVERWRITE: "critical",
|
|
163
112
|
UPDATE: "critical",
|
|
164
113
|
CREATE: "positive",
|
|
165
114
|
UNPUBLISHED: "default"
|
|
166
|
-
}
|
|
167
|
-
const documentMessages = {
|
|
115
|
+
}, documentMessages = {
|
|
168
116
|
// Only happens once document is copied the first time, and _updatedAt is the same
|
|
169
117
|
EXISTS: "This document already exists at the Destination with the same ID with the same Updated time.",
|
|
170
118
|
// Is true immediately after transaction as _updatedAt is updated by API after mutation
|
|
@@ -176,15 +124,13 @@ const documentMessages = {
|
|
|
176
124
|
// Document at destination doesn't exist
|
|
177
125
|
CREATE: "This document will be created at the destination.",
|
|
178
126
|
UNPUBLISHED: "A Draft version of this Document exists in this Dataset, but only the Published version will be duplicated to the destination."
|
|
179
|
-
}
|
|
180
|
-
const assetMessages = {
|
|
127
|
+
}, assetMessages = {
|
|
181
128
|
EXISTS: "This Asset already exists at the Destination",
|
|
182
129
|
OVERWRITE: "This Asset already exists at the Destination",
|
|
183
130
|
UPDATE: "This Asset already exists at the Destination",
|
|
184
131
|
CREATE: "This Asset does not yet exist at the Destination",
|
|
185
132
|
UNPUBLISHED: ""
|
|
186
|
-
}
|
|
187
|
-
const assetStatus = {
|
|
133
|
+
}, assetStatus = {
|
|
188
134
|
EXISTS: "RE-UPLOAD",
|
|
189
135
|
OVERWRITE: "RE-UPLOAD",
|
|
190
136
|
UPDATE: "RE-UPLOAD",
|
|
@@ -192,858 +138,465 @@ const assetStatus = {
|
|
|
192
138
|
UNPUBLISHED: ""
|
|
193
139
|
};
|
|
194
140
|
function StatusBadge(props) {
|
|
195
|
-
const {
|
|
196
|
-
|
|
197
|
-
isAsset
|
|
198
|
-
} = props;
|
|
199
|
-
if (!status) {
|
|
141
|
+
const { status, isAsset } = props;
|
|
142
|
+
if (!status)
|
|
200
143
|
return null;
|
|
201
|
-
}
|
|
202
144
|
const badgeTone = isAsset ? assetTones[status] : documentTones[status];
|
|
203
|
-
if (!badgeTone)
|
|
204
|
-
return /* @__PURE__ */jsxRuntime.jsx(ui.Badge, {
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
children:
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
},
|
|
220
|
-
children: /* @__PURE__ */jsxRuntime.jsx(ui.Text, {
|
|
221
|
-
size: 1,
|
|
222
|
-
children: badgeText
|
|
223
|
-
})
|
|
224
|
-
}),
|
|
225
|
-
fallbackPlacements: ["right", "left"],
|
|
226
|
-
placement: "top",
|
|
227
|
-
portal: true,
|
|
228
|
-
children: /* @__PURE__ */jsxRuntime.jsxs(ui.Badge, {
|
|
229
|
-
muted: true,
|
|
230
|
-
padding: 3,
|
|
231
|
-
fontSize: 1,
|
|
232
|
-
tone: badgeTone,
|
|
233
|
-
mode: "outline",
|
|
234
|
-
children: [badgeStatus, /* @__PURE__ */jsxRuntime.jsx(ui.Box, {
|
|
235
|
-
marginLeft: 2,
|
|
236
|
-
display: "inline-block",
|
|
237
|
-
as: "span",
|
|
238
|
-
children: /* @__PURE__ */jsxRuntime.jsx(icons.InfoOutlineIcon, {})
|
|
239
|
-
})]
|
|
240
|
-
})
|
|
241
|
-
});
|
|
145
|
+
if (!badgeTone)
|
|
146
|
+
return /* @__PURE__ */ jsxRuntime.jsx(ui.Badge, { muted: !0, padding: 2, fontSize: 1, mode: "outline", children: "Checking..." });
|
|
147
|
+
const badgeText = isAsset ? assetMessages[status] : documentMessages[status], badgeStatus = isAsset ? assetStatus[status] : status;
|
|
148
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
149
|
+
ui.Tooltip,
|
|
150
|
+
{
|
|
151
|
+
content: /* @__PURE__ */ jsxRuntime.jsx(ui.Box, { padding: 3, style: { maxWidth: 200 }, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: 1, children: badgeText }) }),
|
|
152
|
+
fallbackPlacements: ["right", "left"],
|
|
153
|
+
placement: "top",
|
|
154
|
+
portal: !0,
|
|
155
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Badge, { muted: !0, padding: 3, fontSize: 1, tone: badgeTone, mode: "outline", children: [
|
|
156
|
+
badgeStatus,
|
|
157
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Box, { marginLeft: 2, display: "inline-block", as: "span", children: /* @__PURE__ */ jsxRuntime.jsx(icons.InfoOutlineIcon, {}) })
|
|
158
|
+
] })
|
|
159
|
+
}
|
|
160
|
+
);
|
|
242
161
|
}
|
|
243
162
|
function Feedback(props) {
|
|
244
|
-
const {
|
|
245
|
-
|
|
246
|
-
tone = "caution"
|
|
247
|
-
} = props;
|
|
248
|
-
return /* @__PURE__ */jsxRuntime.jsx(ui.Card, {
|
|
249
|
-
padding: 3,
|
|
250
|
-
radius: 2,
|
|
251
|
-
shadow: 1,
|
|
252
|
-
tone,
|
|
253
|
-
children: /* @__PURE__ */jsxRuntime.jsx(ui.Text, {
|
|
254
|
-
size: 1,
|
|
255
|
-
children
|
|
256
|
-
})
|
|
257
|
-
});
|
|
163
|
+
const { children, tone = "caution" } = props;
|
|
164
|
+
return /* @__PURE__ */ jsxRuntime.jsx(ui.Card, { padding: 3, radius: 2, shadow: 1, tone, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: 1, children }) });
|
|
258
165
|
}
|
|
259
|
-
const clientConfig = {
|
|
260
|
-
apiVersion: "2021-05-19"
|
|
261
|
-
};
|
|
262
166
|
function Duplicator(props) {
|
|
263
|
-
|
|
264
|
-
const {
|
|
265
|
-
docs,
|
|
266
|
-
token,
|
|
267
|
-
pluginConfig,
|
|
268
|
-
onDuplicated
|
|
269
|
-
} = props;
|
|
270
|
-
const isDarkMode = ui.useTheme().sanity.color.dark;
|
|
271
|
-
const originClient = sanity.useClient(clientConfig);
|
|
272
|
-
const schema = sanity.useSchema();
|
|
273
|
-
const workspaces = sanity.useWorkspaces();
|
|
274
|
-
const workspacesOptions = workspaces.map(workspace => ({
|
|
167
|
+
const { docs, token, pluginConfig, onDuplicated } = props, isDarkMode = ui.useTheme().sanity.color.dark, originClient = sanity.useClient({ apiVersion: pluginConfig.apiVersion }), schema = sanity.useSchema(), workspaces = sanity.useWorkspaces(), workspacesOptions = workspaces.map((workspace) => ({
|
|
275
168
|
...workspace,
|
|
276
169
|
disabled: workspace.dataset === originClient.config().dataset && workspace.projectId === originClient.config().projectId
|
|
277
|
-
}))
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
const [payload, setPayload] = React.useState([]);
|
|
281
|
-
const [hasReferences, setHasReferences] = React.useState(false);
|
|
282
|
-
const [isDuplicating, setIsDuplicating] = React.useState(false);
|
|
283
|
-
const [isGathering, setIsGathering] = React.useState(false);
|
|
284
|
-
const [progress, setProgress] = React.useState([0, 0]);
|
|
285
|
-
React.useEffect(() => {
|
|
286
|
-
const expr = ".._ref";
|
|
287
|
-
const initialRefs = [];
|
|
288
|
-
const initialPayload = [];
|
|
289
|
-
docs.forEach(doc => {
|
|
290
|
-
const refs = mutator.extractWithPath(expr, doc).map(ref => ref.value);
|
|
291
|
-
initialRefs.push(...refs);
|
|
292
|
-
initialPayload.push({
|
|
293
|
-
include: true,
|
|
294
|
-
doc
|
|
295
|
-
});
|
|
296
|
-
});
|
|
297
|
-
updatePayloadStatuses(initialPayload);
|
|
298
|
-
const docCount = docs.length;
|
|
299
|
-
const refsCount = initialRefs.length;
|
|
300
|
-
if (initialRefs.length) {
|
|
301
|
-
setHasReferences(true);
|
|
302
|
-
setMessage({
|
|
303
|
-
tone: "caution",
|
|
304
|
-
text: createInitialMessage(docCount, refsCount)
|
|
305
|
-
});
|
|
306
|
-
}
|
|
307
|
-
}, [docs]);
|
|
170
|
+
})), [destination, setDestination] = React.useState(
|
|
171
|
+
workspaces.length ? workspacesOptions.find((space) => !space.disabled) ?? null : null
|
|
172
|
+
), [message, setMessage] = React.useState(null), [payload, setPayload] = React.useState([]), [hasReferences, setHasReferences] = React.useState(!1), [isDuplicating, setIsDuplicating] = React.useState(!1), [isGathering, setIsGathering] = React.useState(!1), [progress, setProgress] = React.useState([0, 0]);
|
|
308
173
|
React.useEffect(() => {
|
|
174
|
+
const expr = ".._ref", initialRefs = [], initialPayload = [];
|
|
175
|
+
docs.forEach((doc) => {
|
|
176
|
+
const refs = mutator.extractWithPath(expr, doc).map((ref) => ref.value);
|
|
177
|
+
initialRefs.push(...refs), initialPayload.push({ include: !0, doc });
|
|
178
|
+
}), updatePayloadStatuses(initialPayload);
|
|
179
|
+
const docCount = docs.length, refsCount = initialRefs.length;
|
|
180
|
+
initialRefs.length && (setHasReferences(!0), setMessage({
|
|
181
|
+
tone: "caution",
|
|
182
|
+
text: createInitialMessage(docCount, refsCount)
|
|
183
|
+
}));
|
|
184
|
+
}, [docs]), React.useEffect(() => {
|
|
309
185
|
updatePayloadStatuses();
|
|
310
186
|
}, [destination]);
|
|
311
|
-
async function updatePayloadStatuses() {
|
|
312
|
-
let newPayload = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
|
|
187
|
+
async function updatePayloadStatuses(newPayload = []) {
|
|
313
188
|
const payloadActual = newPayload.length ? newPayload : payload;
|
|
314
|
-
if (!payloadActual.length || !
|
|
189
|
+
if (!payloadActual.length || !destination?.name)
|
|
315
190
|
return;
|
|
316
|
-
}
|
|
317
|
-
const payloadIds = payloadActual.map(_ref => {
|
|
318
|
-
let {
|
|
319
|
-
doc
|
|
320
|
-
} = _ref;
|
|
321
|
-
return doc._id;
|
|
322
|
-
});
|
|
323
|
-
const destinationClient = originClient.withConfig({
|
|
324
|
-
...clientConfig,
|
|
191
|
+
const payloadIds = payloadActual.map(({ doc }) => doc._id), destinationData = await originClient.withConfig({
|
|
325
192
|
dataset: destination.dataset,
|
|
326
193
|
projectId: destination.projectId
|
|
327
|
-
})
|
|
328
|
-
|
|
329
|
-
payloadIds
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
"OVERWRITE" : // Document at destination is older
|
|
340
|
-
"UPDATE";
|
|
341
|
-
}
|
|
342
|
-
} else {
|
|
343
|
-
item.status = "CREATE";
|
|
344
|
-
}
|
|
345
|
-
return item;
|
|
194
|
+
}).fetch(
|
|
195
|
+
"*[_id in $payloadIds]{ _id, _updatedAt }",
|
|
196
|
+
{ payloadIds }
|
|
197
|
+
), updatedPayload = payloadActual.map((item) => {
|
|
198
|
+
const existingDoc = destinationData.find((doc) => doc._id === item.doc._id);
|
|
199
|
+
return existingDoc?._updatedAt && item?.doc?._updatedAt ? existingDoc._updatedAt === item.doc._updatedAt ? item.status = "EXISTS" : existingDoc._updatedAt && item.doc._updatedAt && (item.status = new Date(existingDoc._updatedAt) > new Date(item.doc._updatedAt) ? (
|
|
200
|
+
// Document at destination is newer
|
|
201
|
+
"OVERWRITE"
|
|
202
|
+
) : (
|
|
203
|
+
// Document at destination is older
|
|
204
|
+
"UPDATE"
|
|
205
|
+
)) : item.status = "CREATE", item;
|
|
346
206
|
});
|
|
347
207
|
setPayload(updatedPayload);
|
|
348
208
|
}
|
|
349
209
|
function handleCheckbox(_id) {
|
|
350
|
-
const updatedPayload = payload.map(item =>
|
|
351
|
-
if (item.doc._id === _id) {
|
|
352
|
-
item.include = !item.include;
|
|
353
|
-
}
|
|
354
|
-
return item;
|
|
355
|
-
});
|
|
210
|
+
const updatedPayload = payload.map((item) => (item.doc._id === _id && (item.include = !item.include), item));
|
|
356
211
|
setPayload(updatedPayload);
|
|
357
212
|
}
|
|
358
213
|
async function handleReferences() {
|
|
359
|
-
setIsGathering(
|
|
360
|
-
const docIds = docs.map(doc => doc._id)
|
|
361
|
-
const payloadDocs = await getDocumentsInArray({
|
|
214
|
+
setIsGathering(!0);
|
|
215
|
+
const docIds = docs.map((doc) => doc._id), payloadDocs = await getDocumentsInArray({
|
|
362
216
|
fetchIds: docIds,
|
|
363
217
|
client: originClient,
|
|
364
218
|
pluginConfig
|
|
365
|
-
})
|
|
366
|
-
|
|
367
|
-
fetchIds: docIds.map(id => "drafts.".concat(id)),
|
|
219
|
+
}), draftDocs = await getDocumentsInArray({
|
|
220
|
+
fetchIds: docIds.map((id) => `drafts.${id}`),
|
|
368
221
|
client: originClient,
|
|
369
222
|
projection: "{_id}",
|
|
370
223
|
pluginConfig
|
|
371
|
-
})
|
|
372
|
-
const draftDocsIds = new Set(draftDocs.map(_ref2 => {
|
|
373
|
-
let {
|
|
374
|
-
_id
|
|
375
|
-
} = _ref2;
|
|
376
|
-
return _id;
|
|
377
|
-
}));
|
|
378
|
-
const payloadShaped = payloadDocs.map(doc => ({
|
|
224
|
+
}), draftDocsIds = new Set(draftDocs.map(({ _id }) => _id)), payloadShaped = payloadDocs.map((doc) => ({
|
|
379
225
|
doc,
|
|
380
226
|
// Include this in the transaction?
|
|
381
|
-
include:
|
|
227
|
+
include: !0,
|
|
382
228
|
// Does it exist at the destination?
|
|
383
229
|
status: void 0,
|
|
384
230
|
// Does it have any drafts?
|
|
385
|
-
hasDraft: draftDocsIds.has(
|
|
231
|
+
hasDraft: draftDocsIds.has(`drafts.${doc._id}`)
|
|
386
232
|
}));
|
|
387
|
-
setPayload(payloadShaped);
|
|
388
|
-
updatePayloadStatuses(payloadShaped);
|
|
389
|
-
setIsGathering(false);
|
|
233
|
+
setPayload(payloadShaped), updatePayloadStatuses(payloadShaped), setIsGathering(!1);
|
|
390
234
|
}
|
|
391
235
|
async function handleDuplicate() {
|
|
392
|
-
if (!destination)
|
|
236
|
+
if (!destination)
|
|
393
237
|
return;
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
const assetsCount = payload.filter(_ref3 => {
|
|
397
|
-
let {
|
|
398
|
-
doc,
|
|
399
|
-
include
|
|
400
|
-
} = _ref3;
|
|
401
|
-
return include && assetUtils.isAssetId(doc._id);
|
|
402
|
-
}).length;
|
|
238
|
+
setIsDuplicating(!0);
|
|
239
|
+
const assetsCount = payload.filter(({ doc, include }) => include && assetUtils.isAssetId(doc._id)).length;
|
|
403
240
|
let currentProgress = 0;
|
|
404
|
-
setProgress([currentProgress, assetsCount]);
|
|
405
|
-
setMessage({
|
|
406
|
-
text: "Duplicating...",
|
|
407
|
-
tone: "transparent"
|
|
408
|
-
});
|
|
241
|
+
setProgress([currentProgress, assetsCount]), setMessage({ text: "Duplicating...", tone: "transparent" });
|
|
409
242
|
const destinationClient = originClient.withConfig({
|
|
410
|
-
|
|
243
|
+
apiVersion: pluginConfig.apiVersion,
|
|
411
244
|
dataset: destination.dataset,
|
|
412
245
|
projectId: destination.projectId
|
|
413
|
-
});
|
|
414
|
-
const transactionDocs = [];
|
|
415
|
-
const svgMaps = [];
|
|
246
|
+
}), transactionDocs = [], svgMaps = [];
|
|
416
247
|
async function fetchDoc(doc) {
|
|
417
248
|
if (assetUtils.isAssetId(doc._id)) {
|
|
418
|
-
const typeIsFile = assetUtils.isSanityFileAsset(doc);
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
filename: doc.originalFilename
|
|
429
|
-
};
|
|
430
|
-
const assetDoc = await destinationClient.assets.upload(typeIsFile ? "file" : "image", assetData, options);
|
|
431
|
-
if ((doc == null ? void 0 : doc.extension) === "svg") {
|
|
432
|
-
svgMaps.push({
|
|
433
|
-
old: doc._id,
|
|
434
|
-
new: assetDoc._id
|
|
435
|
-
});
|
|
436
|
-
}
|
|
437
|
-
transactionDocs.push(assetDoc);
|
|
438
|
-
doc.url = assetDoc.url;
|
|
439
|
-
doc.path = assetDoc.path;
|
|
440
|
-
});
|
|
441
|
-
currentProgress += 1;
|
|
442
|
-
setMessage({
|
|
443
|
-
text: "Duplicating ".concat(currentProgress, "/").concat(assetsCount, " ").concat(assetsCount === 1 ? "Assets" : "Assets"),
|
|
249
|
+
const typeIsFile = assetUtils.isSanityFileAsset(doc), downloadUrl = typeIsFile ? doc.url : `${doc.url}?dlRaw=true`, downloadConfig = typeIsFile ? {} : { headers: { Authorization: `Bearer ${token}` } };
|
|
250
|
+
await fetch(downloadUrl, downloadConfig).then(async (res) => {
|
|
251
|
+
const assetData = await res.blob(), options = { filename: doc.originalFilename }, assetDoc = await destinationClient.assets.upload(
|
|
252
|
+
typeIsFile ? "file" : "image",
|
|
253
|
+
assetData,
|
|
254
|
+
options
|
|
255
|
+
);
|
|
256
|
+
doc?.extension === "svg" && svgMaps.push({ old: doc._id, new: assetDoc._id }), transactionDocs.push(assetDoc), doc.url = assetDoc.url, doc.path = assetDoc.path;
|
|
257
|
+
}), currentProgress += 1, setMessage({
|
|
258
|
+
text: `Duplicating ${currentProgress}/${assetsCount} Assets`,
|
|
444
259
|
tone: "default"
|
|
445
|
-
});
|
|
446
|
-
setProgress([currentProgress, assetsCount]);
|
|
260
|
+
}), setProgress([currentProgress, assetsCount]);
|
|
447
261
|
}
|
|
448
262
|
return transactionDocs.push(doc);
|
|
449
263
|
}
|
|
450
|
-
|
|
451
|
-
const payloadIncludedDocs = payload.filter(item => item.include).map(item => item.doc);
|
|
452
|
-
mapLimit__default.default(payloadIncludedDocs, 3, asyncify__default.default(fetchDoc), err => {
|
|
453
|
-
|
|
454
|
-
setIsDuplicating(false);
|
|
455
|
-
setMessage({
|
|
456
|
-
tone: "critical",
|
|
457
|
-
text: "Duplication Failed"
|
|
458
|
-
});
|
|
459
|
-
console.error(err);
|
|
460
|
-
reject(new Error("Duplication Failed"));
|
|
461
|
-
}
|
|
462
|
-
resolve();
|
|
264
|
+
await new Promise((resolve, reject) => {
|
|
265
|
+
const payloadIncludedDocs = payload.filter((item) => item.include).map((item) => item.doc);
|
|
266
|
+
mapLimit__default.default(payloadIncludedDocs, 3, asyncify__default.default(fetchDoc), (err) => {
|
|
267
|
+
err && (setIsDuplicating(!1), setMessage({ tone: "critical", text: "Duplication Failed" }), console.error(err), reject(new Error("Duplication Failed"))), resolve();
|
|
463
268
|
});
|
|
464
269
|
});
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
if (!references.length) {
|
|
470
|
-
return doc;
|
|
471
|
-
}
|
|
472
|
-
references.forEach(ref => {
|
|
473
|
-
var _a2;
|
|
474
|
-
const newRefValue = (_a2 = svgMaps.find(asset => asset.old === ref.value)) == null ? void 0 : _a2.new;
|
|
270
|
+
const transactionDocsMapped = transactionDocs.map((doc) => {
|
|
271
|
+
const references = mutator.extractWithPath(".._ref", doc);
|
|
272
|
+
return references.length && references.forEach((ref) => {
|
|
273
|
+
const newRefValue = svgMaps.find((asset) => asset.old === ref.value)?.new;
|
|
475
274
|
if (newRefValue) {
|
|
476
275
|
const refPath = ref.path.join(".");
|
|
477
276
|
dset.dset(doc, refPath, newRefValue);
|
|
478
277
|
}
|
|
479
|
-
});
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
const transaction = destinationClient.transaction();
|
|
483
|
-
transactionDocsMapped.forEach(doc => {
|
|
278
|
+
}), doc;
|
|
279
|
+
}), transaction = destinationClient.transaction();
|
|
280
|
+
if (transactionDocsMapped.forEach((doc) => {
|
|
484
281
|
transaction.createOrReplace(doc);
|
|
485
|
-
})
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
});
|
|
491
|
-
updatePayloadStatuses();
|
|
492
|
-
}).catch(err => {
|
|
493
|
-
setMessage({
|
|
494
|
-
tone: "critical",
|
|
495
|
-
text: err.details.description
|
|
496
|
-
});
|
|
497
|
-
});
|
|
498
|
-
setIsDuplicating(false);
|
|
499
|
-
setProgress([0, 0]);
|
|
500
|
-
if (onDuplicated) {
|
|
282
|
+
}), await transaction.commit().then((res) => {
|
|
283
|
+
setMessage({ tone: "positive", text: "Duplication complete!" }), updatePayloadStatuses();
|
|
284
|
+
}).catch((err) => {
|
|
285
|
+
setMessage({ tone: "critical", text: err.details.description });
|
|
286
|
+
}), setIsDuplicating(!1), setProgress([0, 0]), onDuplicated)
|
|
501
287
|
try {
|
|
502
288
|
await onDuplicated();
|
|
503
289
|
} catch (error) {
|
|
504
|
-
setMessage({
|
|
505
|
-
tone: "critical",
|
|
506
|
-
text: "Error in onDuplicated hook: ".concat(error)
|
|
507
|
-
});
|
|
290
|
+
setMessage({ tone: "critical", text: `Error in onDuplicated hook: ${error}` });
|
|
508
291
|
}
|
|
509
|
-
}
|
|
510
292
|
}
|
|
511
293
|
function handleChange(e) {
|
|
512
|
-
if (!workspacesOptions.length)
|
|
294
|
+
if (!workspacesOptions.length)
|
|
513
295
|
return;
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
if (targeted) {
|
|
517
|
-
setDestination(targeted);
|
|
518
|
-
}
|
|
296
|
+
const targeted = workspacesOptions.find((space) => space.name === e.currentTarget.value);
|
|
297
|
+
targeted && setDestination(targeted);
|
|
519
298
|
}
|
|
520
|
-
const payloadCount = payload.length
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
return doc.extension === "svg";
|
|
526
|
-
});
|
|
527
|
-
const selectedDocumentsCount = payload.filter(item => item.include && !assetUtils.isAssetId(item.doc._id)).length;
|
|
528
|
-
const selectedAssetsCount = payload.filter(item => item.include && assetUtils.isAssetId(item.doc._id)).length;
|
|
529
|
-
const selectedTotal = selectedDocumentsCount + selectedAssetsCount;
|
|
530
|
-
const destinationTitle = (_b = destination == null ? void 0 : destination.title) != null ? _b : destination == null ? void 0 : destination.name;
|
|
531
|
-
const hasMultipleProjectIds = new Set(workspacesOptions.map(space => space == null ? void 0 : space.projectId).filter(Boolean)).size > 1;
|
|
532
|
-
const headingText = [selectedTotal, "/", payloadCount, "Documents and Assets selected"].join(" ");
|
|
533
|
-
const buttonText = React__default.default.useMemo(() => {
|
|
299
|
+
const payloadCount = payload.length, firstSvgIndex = payload.findIndex(({ doc }) => doc.extension === "svg"), selectedDocumentsCount = payload.filter(
|
|
300
|
+
(item) => item.include && !assetUtils.isAssetId(item.doc._id)
|
|
301
|
+
).length, selectedAssetsCount = payload.filter(
|
|
302
|
+
(item) => item.include && assetUtils.isAssetId(item.doc._id)
|
|
303
|
+
).length, selectedTotal = selectedDocumentsCount + selectedAssetsCount, destinationTitle = destination?.title ?? destination?.name, hasMultipleProjectIds = new Set(workspacesOptions.map((space) => space?.projectId).filter(Boolean)).size > 1, headingText = [selectedTotal, "/", payloadCount, "Documents and Assets selected"].join(" "), buttonText = React__default.default.useMemo(() => {
|
|
534
304
|
const text = ["Duplicate"];
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
space:
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
radius: 2,
|
|
644
|
-
shadow: 1,
|
|
645
|
-
tone: message.tone,
|
|
646
|
-
children: /* @__PURE__ */jsxRuntime.jsx(ui.Text, {
|
|
647
|
-
size: 1,
|
|
648
|
-
children: message.text
|
|
649
|
-
})
|
|
650
|
-
}), payload.length > 0 ? /* @__PURE__ */jsxRuntime.jsx(ui.Stack, {
|
|
651
|
-
children: payload.map((_ref5, index) => {
|
|
652
|
-
let {
|
|
653
|
-
doc,
|
|
654
|
-
include,
|
|
655
|
-
status,
|
|
656
|
-
hasDraft
|
|
657
|
-
} = _ref5;
|
|
658
|
-
const schemaType = schema.get(doc._type);
|
|
659
|
-
return /* @__PURE__ */jsxRuntime.jsxs(React__default.default.Fragment, {
|
|
660
|
-
children: [/* @__PURE__ */jsxRuntime.jsxs(ui.Flex, {
|
|
661
|
-
align: "center",
|
|
662
|
-
children: [/* @__PURE__ */jsxRuntime.jsx(ui.Checkbox, {
|
|
663
|
-
checked: include,
|
|
664
|
-
onChange: () => handleCheckbox(doc._id)
|
|
665
|
-
}), /* @__PURE__ */jsxRuntime.jsx(ui.Box, {
|
|
666
|
-
flex: 1,
|
|
667
|
-
paddingX: 3,
|
|
668
|
-
children: schemaType ? /* @__PURE__ */jsxRuntime.jsx(sanity.Preview, {
|
|
669
|
-
value: doc,
|
|
670
|
-
schemaType
|
|
671
|
-
}) : /* @__PURE__ */jsxRuntime.jsx(ui.Card, {
|
|
672
|
-
tone: "caution",
|
|
673
|
-
children: "Invalid schema type"
|
|
674
|
-
})
|
|
675
|
-
}), /* @__PURE__ */jsxRuntime.jsxs(ui.Flex, {
|
|
676
|
-
align: "center",
|
|
677
|
-
gap: 2,
|
|
678
|
-
children: [hasDraft ? /* @__PURE__ */jsxRuntime.jsx(StatusBadge, {
|
|
679
|
-
status: "UNPUBLISHED",
|
|
680
|
-
isAsset: false
|
|
681
|
-
}) : null, /* @__PURE__ */jsxRuntime.jsx(StatusBadge, {
|
|
682
|
-
status,
|
|
683
|
-
isAsset: assetUtils.isAssetId(doc._id)
|
|
684
|
-
})]
|
|
685
|
-
})]
|
|
686
|
-
}), (doc == null ? void 0 : doc.extension) === "svg" && index === firstSvgIndex && /* @__PURE__ */jsxRuntime.jsx(ui.Card, {
|
|
687
|
-
padding: 3,
|
|
688
|
-
radius: 2,
|
|
689
|
-
shadow: 1,
|
|
690
|
-
tone: "caution",
|
|
691
|
-
children: /* @__PURE__ */jsxRuntime.jsxs(ui.Text, {
|
|
692
|
-
size: 1,
|
|
693
|
-
children: ["Due to how SVGs are sanitized after first uploaded, duplicated SVG assets may have new ", /* @__PURE__ */jsxRuntime.jsx("code", {
|
|
694
|
-
children: "_id"
|
|
695
|
-
}), "'s at the destination. The newly generated ", /* @__PURE__ */jsxRuntime.jsx("code", {
|
|
696
|
-
children: "_id"
|
|
697
|
-
}), " will be the same in each duplication, but it will never be the same ", /* @__PURE__ */jsxRuntime.jsx("code", {
|
|
698
|
-
children: "_id"
|
|
699
|
-
}), " as the first time this Asset was uploaded. References to the asset will be updated to use the new ", /* @__PURE__ */jsxRuntime.jsx("code", {
|
|
700
|
-
children: "_id"
|
|
701
|
-
}), "."]
|
|
702
|
-
})
|
|
703
|
-
})]
|
|
704
|
-
}, doc._id);
|
|
705
|
-
})
|
|
706
|
-
}) : /* @__PURE__ */jsxRuntime.jsx(ui.Flex, {
|
|
707
|
-
padding: 4,
|
|
708
|
-
align: "center",
|
|
709
|
-
justify: "center",
|
|
710
|
-
children: /* @__PURE__ */jsxRuntime.jsx(ui.Spinner, {})
|
|
711
|
-
}), /* @__PURE__ */jsxRuntime.jsxs(ui.Stack, {
|
|
712
|
-
space: 2,
|
|
713
|
-
children: [hasReferences && /* @__PURE__ */jsxRuntime.jsx(ui.Button, {
|
|
714
|
-
fontSize: 2,
|
|
715
|
-
padding: 4,
|
|
716
|
-
tone: "positive",
|
|
717
|
-
mode: "ghost",
|
|
718
|
-
icon: icons.SearchIcon,
|
|
719
|
-
onClick: handleReferences,
|
|
720
|
-
text: "Gather References",
|
|
721
|
-
disabled: isDuplicating || !selectedTotal || isGathering
|
|
722
|
-
}), /* @__PURE__ */jsxRuntime.jsx(ui.Button, {
|
|
723
|
-
fontSize: 2,
|
|
724
|
-
padding: 4,
|
|
725
|
-
tone: "positive",
|
|
726
|
-
icon: icons.LaunchIcon,
|
|
727
|
-
onClick: handleDuplicate,
|
|
728
|
-
text: buttonText,
|
|
729
|
-
disabled: isDuplicating || !selectedTotal || isGathering
|
|
730
|
-
})]
|
|
731
|
-
})]
|
|
732
|
-
})
|
|
733
|
-
})]
|
|
734
|
-
})
|
|
735
|
-
})
|
|
736
|
-
});
|
|
305
|
+
return selectedDocumentsCount > 1 && text.push(
|
|
306
|
+
String(selectedDocumentsCount),
|
|
307
|
+
selectedDocumentsCount === 1 ? "Document" : "Documents"
|
|
308
|
+
), selectedAssetsCount > 1 && text.push("and", String(selectedAssetsCount), selectedAssetsCount === 1 ? "Asset" : "Assets"), originClient.config().projectId !== destination?.projectId && text.push("between Projects"), text.push("to", String(destinationTitle)), text.join(" ");
|
|
309
|
+
}, [
|
|
310
|
+
selectedDocumentsCount,
|
|
311
|
+
selectedAssetsCount,
|
|
312
|
+
originClient,
|
|
313
|
+
destination?.projectId,
|
|
314
|
+
destinationTitle
|
|
315
|
+
]);
|
|
316
|
+
return workspacesOptions.length < 2 ? /* @__PURE__ */ jsxRuntime.jsxs(Feedback, { tone: "critical", children: [
|
|
317
|
+
/* @__PURE__ */ jsxRuntime.jsx("code", { children: "sanity.config.ts" }),
|
|
318
|
+
" must contain at least two Workspaces to use this plugin."
|
|
319
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsx(ui.Container, { width: 1, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Card, { border: !0, children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Stack, { children: [
|
|
320
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Card, { padding: 4, style: stickyStyles(isDarkMode), children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Stack, { space: 4, children: [
|
|
321
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Flex, { gap: 3, children: [
|
|
322
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Stack, { style: { flex: 1 }, space: 3, children: [
|
|
323
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Label, { children: "Duplicate from" }),
|
|
324
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Select, { readOnly: !0, value: workspacesOptions.find((space) => space.disabled)?.name, children: workspacesOptions.filter((space) => space.disabled).map((space) => /* @__PURE__ */ jsxRuntime.jsxs("option", { value: space.name, disabled: space.disabled, children: [
|
|
325
|
+
space.title ?? space.name,
|
|
326
|
+
hasMultipleProjectIds ? ` (${space.projectId})` : ""
|
|
327
|
+
] }, space.name)) })
|
|
328
|
+
] }),
|
|
329
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Box, { padding: 4, paddingTop: 5, paddingBottom: 0, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: 3, children: /* @__PURE__ */ jsxRuntime.jsx(icons.ArrowRightIcon, {}) }) }),
|
|
330
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Stack, { style: { flex: 1 }, space: 3, children: [
|
|
331
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Label, { children: "To Destination" }),
|
|
332
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Select, { onChange: handleChange, children: workspacesOptions.map((space) => /* @__PURE__ */ jsxRuntime.jsxs("option", { value: space.name, disabled: space.disabled, children: [
|
|
333
|
+
space.title ?? space.name,
|
|
334
|
+
hasMultipleProjectIds ? ` (${space.projectId})` : "",
|
|
335
|
+
space.disabled ? " (Current)" : ""
|
|
336
|
+
] }, space.name)) })
|
|
337
|
+
] })
|
|
338
|
+
] }),
|
|
339
|
+
isDuplicating && /* @__PURE__ */ jsxRuntime.jsx(ui.Card, { border: !0, radius: 2, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
340
|
+
ui.Card,
|
|
341
|
+
{
|
|
342
|
+
style: {
|
|
343
|
+
width: "100%",
|
|
344
|
+
transform: `scaleX(${progress[0] / progress[1]})`,
|
|
345
|
+
transformOrigin: "left",
|
|
346
|
+
transition: "transform .2s ease",
|
|
347
|
+
boxSizing: "border-box"
|
|
348
|
+
},
|
|
349
|
+
padding: 1,
|
|
350
|
+
tone: "positive"
|
|
351
|
+
}
|
|
352
|
+
) }),
|
|
353
|
+
payload.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
354
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Label, { children: headingText }),
|
|
355
|
+
/* @__PURE__ */ jsxRuntime.jsx(SelectButtons, { payload, setPayload })
|
|
356
|
+
] })
|
|
357
|
+
] }) }),
|
|
358
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Card, { borderTop: !0, padding: 4, children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Stack, { space: 3, children: [
|
|
359
|
+
message && /* @__PURE__ */ jsxRuntime.jsx(ui.Card, { padding: 3, radius: 2, shadow: 1, tone: message.tone, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: 1, children: message.text }) }),
|
|
360
|
+
payload.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(ui.Stack, { children: payload.map(({ doc, include, status, hasDraft }, index) => {
|
|
361
|
+
const schemaType = schema.get(doc._type);
|
|
362
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(React__default.default.Fragment, { children: [
|
|
363
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Flex, { align: "center", children: [
|
|
364
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Checkbox, { checked: include, onChange: () => handleCheckbox(doc._id) }),
|
|
365
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Box, { flex: 1, paddingX: 3, children: schemaType ? /* @__PURE__ */ jsxRuntime.jsx(sanity.Preview, { value: doc, schemaType }) : /* @__PURE__ */ jsxRuntime.jsx(ui.Card, { tone: "caution", children: "Invalid schema type" }) }),
|
|
366
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Flex, { align: "center", gap: 2, children: [
|
|
367
|
+
hasDraft ? /* @__PURE__ */ jsxRuntime.jsx(StatusBadge, { status: "UNPUBLISHED", isAsset: !1 }) : null,
|
|
368
|
+
/* @__PURE__ */ jsxRuntime.jsx(StatusBadge, { status, isAsset: assetUtils.isAssetId(doc._id) })
|
|
369
|
+
] })
|
|
370
|
+
] }),
|
|
371
|
+
doc?.extension === "svg" && index === firstSvgIndex && /* @__PURE__ */ jsxRuntime.jsx(ui.Card, { padding: 3, radius: 2, shadow: 1, tone: "caution", children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { size: 1, children: [
|
|
372
|
+
"Due to how SVGs are sanitized after first uploaded, duplicated SVG assets may have new ",
|
|
373
|
+
/* @__PURE__ */ jsxRuntime.jsx("code", { children: "_id" }),
|
|
374
|
+
"'s at the destination. The newly generated ",
|
|
375
|
+
/* @__PURE__ */ jsxRuntime.jsx("code", { children: "_id" }),
|
|
376
|
+
" will be the same in each duplication, but it will never be the same ",
|
|
377
|
+
/* @__PURE__ */ jsxRuntime.jsx("code", { children: "_id" }),
|
|
378
|
+
" as the first time this Asset was uploaded. References to the asset will be updated to use the new ",
|
|
379
|
+
/* @__PURE__ */ jsxRuntime.jsx("code", { children: "_id" }),
|
|
380
|
+
"."
|
|
381
|
+
] }) })
|
|
382
|
+
] }, doc._id);
|
|
383
|
+
}) }) : /* @__PURE__ */ jsxRuntime.jsx(ui.Flex, { padding: 4, align: "center", justify: "center", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Spinner, {}) }),
|
|
384
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Stack, { space: 2, children: [
|
|
385
|
+
hasReferences && /* @__PURE__ */ jsxRuntime.jsx(
|
|
386
|
+
ui.Button,
|
|
387
|
+
{
|
|
388
|
+
fontSize: 2,
|
|
389
|
+
padding: 4,
|
|
390
|
+
tone: "positive",
|
|
391
|
+
mode: "ghost",
|
|
392
|
+
icon: icons.SearchIcon,
|
|
393
|
+
onClick: handleReferences,
|
|
394
|
+
text: "Gather References",
|
|
395
|
+
disabled: isDuplicating || !selectedTotal || isGathering
|
|
396
|
+
}
|
|
397
|
+
),
|
|
398
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
399
|
+
ui.Button,
|
|
400
|
+
{
|
|
401
|
+
fontSize: 2,
|
|
402
|
+
padding: 4,
|
|
403
|
+
tone: "positive",
|
|
404
|
+
icon: icons.LaunchIcon,
|
|
405
|
+
onClick: handleDuplicate,
|
|
406
|
+
text: buttonText,
|
|
407
|
+
disabled: isDuplicating || !selectedTotal || isGathering
|
|
408
|
+
}
|
|
409
|
+
)
|
|
410
|
+
] })
|
|
411
|
+
] }) })
|
|
412
|
+
] }) }) });
|
|
737
413
|
}
|
|
738
414
|
function DuplicatorQuery(props) {
|
|
739
|
-
|
|
740
|
-
const {
|
|
741
|
-
token,
|
|
742
|
-
pluginConfig
|
|
743
|
-
} = props;
|
|
744
|
-
const {
|
|
745
|
-
queries: preDefinedQueries
|
|
746
|
-
} = pluginConfig;
|
|
747
|
-
const originClient = sanity.useClient(clientConfig);
|
|
748
|
-
const schema = sanity.useSchema();
|
|
749
|
-
const schemaTypes = schema.getTypeNames();
|
|
750
|
-
const [value, setValue] = React.useState("");
|
|
751
|
-
const [fetched, setFetched] = React.useState(false);
|
|
752
|
-
const [initialData, setInitialData] = React.useState({
|
|
415
|
+
const { token, pluginConfig } = props, { queries: preDefinedQueries, apiVersion } = pluginConfig, originClient = sanity.useClient({ apiVersion }), schemaTypes = sanity.useSchema().getTypeNames(), [value, setValue] = React.useState(""), [fetched, setFetched] = React.useState(!1), [initialData, setInitialData] = React.useState({
|
|
753
416
|
docs: []
|
|
754
|
-
// draftIds: []
|
|
755
417
|
});
|
|
756
|
-
|
|
757
418
|
function handleSubmit(e) {
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
const registeredAndPublishedDocs = res.length ? res.filter(doc => schemaTypes.includes(doc._type)).filter(doc => !doc._id.startsWith("drafts.")) : [];
|
|
419
|
+
e && e.preventDefault(), originClient.fetch(value).then((res) => {
|
|
420
|
+
const registeredAndPublishedDocs = res.length ? res.filter((doc) => schemaTypes.includes(doc._type)).filter((doc) => !doc._id.startsWith("drafts.")) : [];
|
|
761
421
|
setInitialData({
|
|
762
422
|
docs: registeredAndPublishedDocs
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
setFetched(true);
|
|
767
|
-
}).catch(err => console.error(err));
|
|
423
|
+
}), setFetched(!0);
|
|
424
|
+
}).catch((err) => console.error(err));
|
|
768
425
|
}
|
|
769
|
-
React.useEffect(() => {
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
padding: 4,
|
|
827
|
-
radius: 3,
|
|
828
|
-
border: true,
|
|
829
|
-
children: /* @__PURE__ */jsxRuntime.jsx(ui.Box, {
|
|
830
|
-
children: /* @__PURE__ */jsxRuntime.jsxs(ui.Stack, {
|
|
831
|
-
space: 4,
|
|
832
|
-
children: [/* @__PURE__ */jsxRuntime.jsx(ui.Box, {
|
|
833
|
-
children: /* @__PURE__ */jsxRuntime.jsx(ui.Label, {
|
|
834
|
-
children: "Predefined Queries"
|
|
835
|
-
})
|
|
836
|
-
}), /* @__PURE__ */jsxRuntime.jsx(ui.Stack, {
|
|
837
|
-
space: 2,
|
|
838
|
-
children: preDefinedQueries.map(query => /* @__PURE__ */jsxRuntime.jsx(ui.Button, {
|
|
839
|
-
padding: 2,
|
|
840
|
-
paddingX: 4,
|
|
841
|
-
tone: "primary",
|
|
842
|
-
onClick: () => setValue("*[".concat(query.query, "]")),
|
|
843
|
-
text: query.label
|
|
844
|
-
}, query.label.replace(/\s+/g, "-")))
|
|
845
|
-
})]
|
|
846
|
-
})
|
|
847
|
-
})
|
|
848
|
-
})]
|
|
849
|
-
}), fetched && initialData.docs.length < 1 && /* @__PURE__ */jsxRuntime.jsx(ui.Container, {
|
|
850
|
-
width: 1,
|
|
851
|
-
children: /* @__PURE__ */jsxRuntime.jsx(ui.Card, {
|
|
852
|
-
padding: 5,
|
|
853
|
-
children: value ? "No documents match this query" : "Start with a valid GROQ query"
|
|
854
|
-
})
|
|
855
|
-
}), ((_a = initialData.docs) == null ? void 0 : _a.length) > 0 && /* @__PURE__ */jsxRuntime.jsx(Duplicator, {
|
|
856
|
-
docs: initialData.docs,
|
|
857
|
-
token,
|
|
858
|
-
pluginConfig
|
|
859
|
-
})]
|
|
860
|
-
})
|
|
861
|
-
})
|
|
862
|
-
});
|
|
426
|
+
return React.useEffect(() => {
|
|
427
|
+
!initialData.docs?.length && value && handleSubmit();
|
|
428
|
+
}, []), /* @__PURE__ */ jsxRuntime.jsx(ui.Card, { padding: [0, 0, 0, 5], children: /* @__PURE__ */ jsxRuntime.jsx(ui.Container, { children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Grid, { columns: [1, 1, 1, 2], gap: [1, 1, 1, 4], children: [
|
|
429
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Box, { padding: [2, 2, 2, 0], children: [
|
|
430
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Card, { padding: 4, radius: 3, border: !0, children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Stack, { space: 4, children: [
|
|
431
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Box, { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Label, { children: "Initial Documents Query" }) }),
|
|
432
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Box, { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { children: "Start with a valid GROQ query to load initial documents. The query will need to return an Array of Objects. Drafts will be removed from the results." }) }),
|
|
433
|
+
/* @__PURE__ */ jsxRuntime.jsx("form", { onSubmit: handleSubmit, children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Flex, { children: [
|
|
434
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Box, { flex: 1, paddingRight: 2, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
435
|
+
ui.TextInput,
|
|
436
|
+
{
|
|
437
|
+
style: { fontFamily: "monospace" },
|
|
438
|
+
fontSize: 2,
|
|
439
|
+
onChange: (event) => setValue(event.currentTarget.value),
|
|
440
|
+
padding: 4,
|
|
441
|
+
placeholder: '*[_type == "article"]',
|
|
442
|
+
value: value ?? ""
|
|
443
|
+
}
|
|
444
|
+
) }),
|
|
445
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
446
|
+
ui.Button,
|
|
447
|
+
{
|
|
448
|
+
padding: 2,
|
|
449
|
+
paddingX: 4,
|
|
450
|
+
tone: "primary",
|
|
451
|
+
onClick: handleSubmit,
|
|
452
|
+
text: "Query",
|
|
453
|
+
disabled: !value
|
|
454
|
+
}
|
|
455
|
+
)
|
|
456
|
+
] }) })
|
|
457
|
+
] }) }),
|
|
458
|
+
preDefinedQueries && preDefinedQueries?.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(ui.Card, { marginTop: 2, padding: 4, radius: 3, border: !0, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Box, { children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Stack, { space: 4, children: [
|
|
459
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Box, { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Label, { children: "Predefined Queries" }) }),
|
|
460
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Stack, { space: 2, children: preDefinedQueries.map((query) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
461
|
+
ui.Button,
|
|
462
|
+
{
|
|
463
|
+
padding: 2,
|
|
464
|
+
paddingX: 4,
|
|
465
|
+
tone: "primary",
|
|
466
|
+
onClick: () => setValue(`*[${query.query}]`),
|
|
467
|
+
text: query.label
|
|
468
|
+
},
|
|
469
|
+
query.label.replace(/\s+/g, "-")
|
|
470
|
+
)) })
|
|
471
|
+
] }) }) })
|
|
472
|
+
] }),
|
|
473
|
+
fetched && initialData.docs.length < 1 && /* @__PURE__ */ jsxRuntime.jsx(ui.Container, { width: 1, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Card, { padding: 5, children: value ? "No documents match this query" : "Start with a valid GROQ query" }) }),
|
|
474
|
+
initialData.docs?.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(
|
|
475
|
+
Duplicator,
|
|
476
|
+
{
|
|
477
|
+
docs: initialData.docs,
|
|
478
|
+
token,
|
|
479
|
+
pluginConfig
|
|
480
|
+
}
|
|
481
|
+
)
|
|
482
|
+
] }) }) });
|
|
863
483
|
}
|
|
864
484
|
function DuplicatorWrapper(props) {
|
|
865
|
-
const {
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
onDuplicated
|
|
870
|
-
} = props;
|
|
871
|
-
const [inbound, setInbound] = React.useState([]);
|
|
872
|
-
const {
|
|
873
|
-
follow = []
|
|
874
|
-
} = pluginConfig;
|
|
875
|
-
const [mode, setMode] = React.useState(follow.length === 1 ? follow[0] : "outbound");
|
|
876
|
-
const client = sanity.useClient(clientConfig);
|
|
877
|
-
React.useEffect(() => {
|
|
485
|
+
const { docs, token, pluginConfig, onDuplicated } = props, [inbound, setInbound] = React.useState([]), { follow = [], apiVersion } = pluginConfig, [mode, setMode] = React.useState(
|
|
486
|
+
follow.length === 1 ? follow[0] : "outbound"
|
|
487
|
+
), client = sanity.useClient({ apiVersion });
|
|
488
|
+
return React.useEffect(() => {
|
|
878
489
|
(async () => {
|
|
879
490
|
if (follow.includes("inbound")) {
|
|
880
|
-
const inboundReferences = await client.fetch("*[references($id)]", {
|
|
881
|
-
id: docs[0]._id
|
|
882
|
-
});
|
|
491
|
+
const inboundReferences = await client.fetch("*[references($id)]", { id: docs[0]._id });
|
|
883
492
|
setInbound([...props.docs, ...inboundReferences]);
|
|
884
493
|
}
|
|
885
494
|
})();
|
|
886
|
-
}, [])
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
marginBottom: 4,
|
|
892
|
-
borderBottom: true,
|
|
893
|
-
children: /* @__PURE__ */jsxRuntime.jsxs(ui.Grid, {
|
|
894
|
-
columns: 2,
|
|
895
|
-
gap: 4,
|
|
896
|
-
children: [follow.includes("outbound") ? /* @__PURE__ */jsxRuntime.jsx(ui.Button, {
|
|
495
|
+
}, []), /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { children: [
|
|
496
|
+
follow.length > 1 && (follow.includes("inbound") || follow.includes("outbound")) ? /* @__PURE__ */ jsxRuntime.jsx(ui.Card, { paddingX: 4, paddingBottom: 4, marginBottom: 4, borderBottom: !0, children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Grid, { columns: 2, gap: 4, children: [
|
|
497
|
+
follow.includes("outbound") ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
498
|
+
ui.Button,
|
|
499
|
+
{
|
|
897
500
|
mode: "ghost",
|
|
898
501
|
tone: "primary",
|
|
899
502
|
selected: mode === "outbound",
|
|
900
503
|
onClick: () => setMode("outbound"),
|
|
901
504
|
text: "Outbound"
|
|
902
|
-
}
|
|
505
|
+
}
|
|
506
|
+
) : null,
|
|
507
|
+
follow.includes("inbound") ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
508
|
+
ui.Button,
|
|
509
|
+
{
|
|
903
510
|
mode: "ghost",
|
|
904
511
|
tone: "primary",
|
|
905
512
|
selected: mode === "inbound",
|
|
906
513
|
onClick: () => setMode("inbound"),
|
|
907
514
|
disabled: inbound.length === 0,
|
|
908
|
-
text: inbound.length > 0 ?
|
|
909
|
-
}
|
|
910
|
-
|
|
911
|
-
}) : null,
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
515
|
+
text: inbound.length > 0 ? `Inbound (${inbound.length})` : "No inbound references"
|
|
516
|
+
}
|
|
517
|
+
) : null
|
|
518
|
+
] }) }) : null,
|
|
519
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
520
|
+
Duplicator,
|
|
521
|
+
{
|
|
522
|
+
docs: mode === "outbound" ? docs : inbound,
|
|
523
|
+
token,
|
|
524
|
+
pluginConfig,
|
|
525
|
+
onDuplicated
|
|
526
|
+
}
|
|
527
|
+
)
|
|
528
|
+
] });
|
|
918
529
|
}
|
|
919
|
-
const SECRET_NAMESPACE = "CrossDatasetDuplicator"
|
|
920
|
-
|
|
921
|
-
tool:
|
|
530
|
+
const SECRET_NAMESPACE = "CrossDatasetDuplicator", DEFAULT_CONFIG = {
|
|
531
|
+
apiVersion: "2025-02-19",
|
|
532
|
+
tool: !0,
|
|
922
533
|
types: [],
|
|
923
534
|
filter: "",
|
|
924
535
|
follow: ["outbound"],
|
|
925
536
|
queries: []
|
|
926
537
|
};
|
|
927
|
-
function ResetSecret() {
|
|
928
|
-
const client = sanity.useClient(
|
|
929
|
-
|
|
930
|
-
client.delete({
|
|
931
|
-
query: "*[_id == \"secrets.".concat(SECRET_NAMESPACE, "\"]")
|
|
932
|
-
});
|
|
538
|
+
function ResetSecret({ apiVersion }) {
|
|
539
|
+
const client = sanity.useClient({ apiVersion }), handleClick = React.useCallback(() => {
|
|
540
|
+
client.delete({ query: `*[_id == "secrets.${SECRET_NAMESPACE}"]` });
|
|
933
541
|
}, [client]);
|
|
934
|
-
return /* @__PURE__ */jsxRuntime.jsx(ui.Flex, {
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
paddingX: [2, 2, 2, 5],
|
|
938
|
-
paddingY: 5,
|
|
939
|
-
children: /* @__PURE__ */jsxRuntime.jsx(ui.Button, {
|
|
542
|
+
return /* @__PURE__ */ jsxRuntime.jsx(ui.Flex, { align: "center", justify: "flex-end", paddingX: [2, 2, 2, 5], paddingY: 5, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
543
|
+
ui.Button,
|
|
544
|
+
{
|
|
940
545
|
text: "Reset Secret",
|
|
941
546
|
onClick: handleClick,
|
|
942
547
|
mode: "ghost",
|
|
943
548
|
tone: "critical",
|
|
944
549
|
fontSize: 1,
|
|
945
550
|
padding: 2
|
|
946
|
-
}
|
|
947
|
-
});
|
|
551
|
+
}
|
|
552
|
+
) });
|
|
948
553
|
}
|
|
949
554
|
const CrossDatasetDuplicatorContext = React.createContext(DEFAULT_CONFIG);
|
|
950
555
|
function useCrossDatasetDuplicatorConfig() {
|
|
951
|
-
|
|
952
|
-
return pluginConfig;
|
|
556
|
+
return React.useContext(CrossDatasetDuplicatorContext);
|
|
953
557
|
}
|
|
954
558
|
function ConfigProvider(props) {
|
|
955
|
-
const {
|
|
956
|
-
|
|
957
|
-
...rest
|
|
958
|
-
} = props;
|
|
959
|
-
return /* @__PURE__ */jsxRuntime.jsx(CrossDatasetDuplicatorContext.Provider, {
|
|
960
|
-
value: pluginConfig,
|
|
961
|
-
children: props.renderDefault(rest)
|
|
962
|
-
});
|
|
559
|
+
const { pluginConfig, ...rest } = props;
|
|
560
|
+
return /* @__PURE__ */ jsxRuntime.jsx(CrossDatasetDuplicatorContext.Provider, { value: pluginConfig, children: props.renderDefault(rest) });
|
|
963
561
|
}
|
|
964
|
-
const secretConfigKeys = [
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
function CrossDatasetDuplicator(props) {
|
|
970
|
-
const {
|
|
971
|
-
mode = "tool",
|
|
972
|
-
docs = [],
|
|
973
|
-
onDuplicated
|
|
974
|
-
} = props != null ? props : {};
|
|
975
|
-
const pluginConfig = useCrossDatasetDuplicatorConfig();
|
|
976
|
-
const {
|
|
977
|
-
loading,
|
|
978
|
-
secrets
|
|
979
|
-
} = studioSecrets.useSecrets(SECRET_NAMESPACE);
|
|
980
|
-
const [showSecretsPrompt, setShowSecretsPrompt] = React.useState(false);
|
|
981
|
-
React.useEffect(() => {
|
|
982
|
-
if (secrets) {
|
|
983
|
-
setShowSecretsPrompt(!(secrets == null ? void 0 : secrets.bearerToken));
|
|
984
|
-
}
|
|
985
|
-
}, [secrets]);
|
|
986
|
-
if (loading) {
|
|
987
|
-
return /* @__PURE__ */jsxRuntime.jsx(ui.Flex, {
|
|
988
|
-
justify: "center",
|
|
989
|
-
align: "center",
|
|
990
|
-
children: /* @__PURE__ */jsxRuntime.jsx(ui.Box, {
|
|
991
|
-
padding: 5,
|
|
992
|
-
children: /* @__PURE__ */jsxRuntime.jsx(ui.Spinner, {})
|
|
993
|
-
})
|
|
994
|
-
});
|
|
562
|
+
const secretConfigKeys = [
|
|
563
|
+
{
|
|
564
|
+
key: "bearerToken",
|
|
565
|
+
title: "An API token with Viewer permissions is required to duplicate the original files of assets, and will be used for all Duplications. Create one at sanity.io/manage",
|
|
566
|
+
description: ""
|
|
995
567
|
}
|
|
996
|
-
|
|
997
|
-
|
|
568
|
+
];
|
|
569
|
+
function CrossDatasetDuplicator(props) {
|
|
570
|
+
const { mode = "tool", docs = [], onDuplicated } = props ?? {}, pluginConfig = useCrossDatasetDuplicatorConfig(), { loading, secrets } = studioSecrets.useSecrets(SECRET_NAMESPACE), [showSecretsPrompt, setShowSecretsPrompt] = React.useState(!1);
|
|
571
|
+
return React.useEffect(() => {
|
|
572
|
+
secrets && setShowSecretsPrompt(!secrets?.bearerToken);
|
|
573
|
+
}, [secrets]), loading ? /* @__PURE__ */ jsxRuntime.jsx(ui.Flex, { justify: "center", align: "center", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Box, { padding: 5, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Spinner, {}) }) }) : !loading && showSecretsPrompt || !secrets?.bearerToken ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
574
|
+
studioSecrets.SettingsView,
|
|
575
|
+
{
|
|
998
576
|
title: "Token Required",
|
|
999
577
|
namespace: SECRET_NAMESPACE,
|
|
1000
578
|
keys: secretConfigKeys,
|
|
1001
|
-
onClose: () => setShowSecretsPrompt(
|
|
1002
|
-
}
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
});
|
|
1016
|
-
}
|
|
1017
|
-
if (!pluginConfig) {
|
|
1018
|
-
return /* @__PURE__ */jsxRuntime.jsx(Feedback, {
|
|
1019
|
-
children: "No plugin config"
|
|
1020
|
-
});
|
|
1021
|
-
}
|
|
1022
|
-
return /* @__PURE__ */jsxRuntime.jsx(DuplicatorWrapper, {
|
|
1023
|
-
docs,
|
|
1024
|
-
token: secrets == null ? void 0 : secrets.bearerToken,
|
|
1025
|
-
pluginConfig,
|
|
1026
|
-
onDuplicated
|
|
1027
|
-
});
|
|
579
|
+
onClose: () => setShowSecretsPrompt(!1)
|
|
580
|
+
}
|
|
581
|
+
) : mode === "tool" && pluginConfig ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
582
|
+
/* @__PURE__ */ jsxRuntime.jsx(DuplicatorQuery, { token: secrets?.bearerToken, pluginConfig }),
|
|
583
|
+
/* @__PURE__ */ jsxRuntime.jsx(ResetSecret, { apiVersion: pluginConfig.apiVersion })
|
|
584
|
+
] }) : docs?.length ? pluginConfig ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
585
|
+
DuplicatorWrapper,
|
|
586
|
+
{
|
|
587
|
+
docs,
|
|
588
|
+
token: secrets?.bearerToken,
|
|
589
|
+
pluginConfig,
|
|
590
|
+
onDuplicated
|
|
591
|
+
}
|
|
592
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(Feedback, { children: "No plugin config" }) : /* @__PURE__ */ jsxRuntime.jsx(Feedback, { children: "No docs passed into Duplicator Tool" });
|
|
1028
593
|
}
|
|
1029
594
|
function CrossDatasetDuplicatorAction(props) {
|
|
1030
|
-
const {
|
|
1031
|
-
|
|
1032
|
-
onDuplicated
|
|
1033
|
-
} = props;
|
|
1034
|
-
return /* @__PURE__ */jsxRuntime.jsx(CrossDatasetDuplicator, {
|
|
1035
|
-
mode: "action",
|
|
1036
|
-
docs,
|
|
1037
|
-
onDuplicated
|
|
1038
|
-
});
|
|
595
|
+
const { docs = [], onDuplicated } = props;
|
|
596
|
+
return /* @__PURE__ */ jsxRuntime.jsx(CrossDatasetDuplicator, { mode: "action", docs, onDuplicated });
|
|
1039
597
|
}
|
|
1040
|
-
const DuplicateToAction = props => {
|
|
1041
|
-
const {
|
|
1042
|
-
draft,
|
|
1043
|
-
published,
|
|
1044
|
-
onComplete
|
|
1045
|
-
} = props;
|
|
1046
|
-
const [dialogOpen, setDialogOpen] = React.useState(false);
|
|
598
|
+
const DuplicateToAction = (props) => {
|
|
599
|
+
const { draft, published, onComplete } = props, [dialogOpen, setDialogOpen] = React.useState(!1);
|
|
1047
600
|
return {
|
|
1048
601
|
disabled: draft,
|
|
1049
602
|
title: draft ? "Document must be Published to begin" : null,
|
|
@@ -1051,28 +604,19 @@ const DuplicateToAction = props => {
|
|
|
1051
604
|
dialog: dialogOpen && published && {
|
|
1052
605
|
type: "modal",
|
|
1053
606
|
title: "Cross Dataset Duplicator",
|
|
1054
|
-
content: /* @__PURE__ */jsxRuntime.jsx(CrossDatasetDuplicatorAction, {
|
|
1055
|
-
docs: [published]
|
|
1056
|
-
}),
|
|
607
|
+
content: /* @__PURE__ */ jsxRuntime.jsx(CrossDatasetDuplicatorAction, { docs: [published] }),
|
|
1057
608
|
onClose: () => {
|
|
1058
|
-
onComplete();
|
|
1059
|
-
setDialogOpen(false);
|
|
609
|
+
onComplete(), setDialogOpen(!1);
|
|
1060
610
|
}
|
|
1061
611
|
},
|
|
1062
|
-
onHandle: () => setDialogOpen(
|
|
612
|
+
onHandle: () => setDialogOpen(!0),
|
|
1063
613
|
icon: icons.LaunchIcon
|
|
1064
614
|
};
|
|
1065
615
|
};
|
|
1066
616
|
DuplicateToAction.action = "duplicateTo";
|
|
1067
617
|
function CrossDatasetDuplicatorTool(props) {
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
docs = []
|
|
1071
|
-
} = (_a = props.tool.options) != null ? _a : {};
|
|
1072
|
-
return /* @__PURE__ */jsxRuntime.jsx(CrossDatasetDuplicator, {
|
|
1073
|
-
mode: "tool",
|
|
1074
|
-
docs
|
|
1075
|
-
});
|
|
618
|
+
const { docs = [] } = props.tool.options ?? {};
|
|
619
|
+
return /* @__PURE__ */ jsxRuntime.jsx(CrossDatasetDuplicator, { mode: "tool", docs });
|
|
1076
620
|
}
|
|
1077
621
|
const crossDatasetDuplicatorTool = () => ({
|
|
1078
622
|
title: "Duplicator",
|
|
@@ -1082,34 +626,18 @@ const crossDatasetDuplicatorTool = () => ({
|
|
|
1082
626
|
options: {
|
|
1083
627
|
docs: []
|
|
1084
628
|
}
|
|
1085
|
-
})
|
|
1086
|
-
const
|
|
1087
|
-
let config = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
1088
|
-
const pluginConfig = {
|
|
1089
|
-
...DEFAULT_CONFIG,
|
|
1090
|
-
...config
|
|
1091
|
-
};
|
|
1092
|
-
const {
|
|
1093
|
-
types
|
|
1094
|
-
} = pluginConfig;
|
|
629
|
+
}), crossDatasetDuplicator = sanity.definePlugin((config = {}) => {
|
|
630
|
+
const pluginConfig = { ...DEFAULT_CONFIG, ...config }, { types } = pluginConfig;
|
|
1095
631
|
return {
|
|
1096
632
|
name: "@sanity/cross-dataset-duplicator",
|
|
1097
|
-
tools: prev => pluginConfig.tool ? [...prev, crossDatasetDuplicatorTool()] : prev,
|
|
633
|
+
tools: (prev) => pluginConfig.tool ? [...prev, crossDatasetDuplicatorTool()] : prev,
|
|
1098
634
|
studio: {
|
|
1099
635
|
components: {
|
|
1100
|
-
layout: props => ConfigProvider({
|
|
1101
|
-
...props,
|
|
1102
|
-
pluginConfig
|
|
1103
|
-
})
|
|
636
|
+
layout: (props) => ConfigProvider({ ...props, pluginConfig })
|
|
1104
637
|
}
|
|
1105
638
|
},
|
|
1106
639
|
document: {
|
|
1107
|
-
actions: (prev,
|
|
1108
|
-
let {
|
|
1109
|
-
schemaType
|
|
1110
|
-
} = _ref6;
|
|
1111
|
-
return types && types.includes(schemaType) ? [...prev, DuplicateToAction] : prev;
|
|
1112
|
-
}
|
|
640
|
+
actions: (prev, { schemaType }) => types && types.includes(schemaType) ? [...prev, DuplicateToAction] : prev
|
|
1113
641
|
}
|
|
1114
642
|
};
|
|
1115
643
|
});
|