payload-nested-docs-page-tree 1.1.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 +21 -0
- package/README.md +132 -0
- package/dist/components/PageTreeContext.d.ts +15 -0
- package/dist/components/PageTreeContext.js +26 -0
- package/dist/components/PageTreeContext.js.map +1 -0
- package/dist/components/PageTreeListView.client.d.ts +17 -0
- package/dist/components/PageTreeListView.client.js +960 -0
- package/dist/components/PageTreeListView.client.js.map +1 -0
- package/dist/components/PageTreeListView.module.css +358 -0
- package/dist/components/PageTreeListView.server.d.ts +3 -0
- package/dist/components/PageTreeListView.server.js +390 -0
- package/dist/components/PageTreeListView.server.js.map +1 -0
- package/dist/components/PageTreeTitleCell.d.ts +6 -0
- package/dist/components/PageTreeTitleCell.js +80 -0
- package/dist/components/PageTreeTitleCell.js.map +1 -0
- package/dist/endpoints/createMovePageEndpoint.d.ts +5 -0
- package/dist/endpoints/createMovePageEndpoint.js +265 -0
- package/dist/endpoints/createMovePageEndpoint.js.map +1 -0
- package/dist/exports/client.d.ts +1 -0
- package/dist/exports/client.js +3 -0
- package/dist/exports/client.js.map +1 -0
- package/dist/exports/rsc.d.ts +1 -0
- package/dist/exports/rsc.js +3 -0
- package/dist/exports/rsc.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +142 -0
- package/dist/index.js.map +1 -0
- package/dist/types.d.ts +35 -0
- package/dist/types.js +8 -0
- package/dist/types.js.map +1 -0
- package/dist/utilities/badgeConfig.d.ts +2 -0
- package/dist/utilities/badgeConfig.js +30 -0
- package/dist/utilities/badgeConfig.js.map +1 -0
- package/dist/utilities/dropTargets.d.ts +31 -0
- package/dist/utilities/dropTargets.js +73 -0
- package/dist/utilities/dropTargets.js.map +1 -0
- package/dist/utilities/moveValidation.d.ts +11 -0
- package/dist/utilities/moveValidation.js +44 -0
- package/dist/utilities/moveValidation.js.map +1 -0
- package/dist/utilities/pageTree.d.ts +37 -0
- package/dist/utilities/pageTree.js +300 -0
- package/dist/utilities/pageTree.js.map +1 -0
- package/dist/utilities/pageTreeCollision.d.ts +16 -0
- package/dist/utilities/pageTreeCollision.js +70 -0
- package/dist/utilities/pageTreeCollision.js.map +1 -0
- package/dist/utilities/pageTreeConfig.d.ts +3 -0
- package/dist/utilities/pageTreeConfig.js +21 -0
- package/dist/utilities/pageTreeConfig.js.map +1 -0
- package/dist/utilities/status.d.ts +17 -0
- package/dist/utilities/status.js +72 -0
- package/dist/utilities/status.js.map +1 -0
- package/package.json +115 -0
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
import { CANCEL_DRAG_MESSAGE } from '../utilities/moveValidation.js';
|
|
2
|
+
import { buildChildrenByParentID, collectDescendantIDs, getDocParentID, stringifyDocID } from '../utilities/pageTree.js';
|
|
3
|
+
function respond(status, body) {
|
|
4
|
+
return Response.json(body, {
|
|
5
|
+
status
|
|
6
|
+
});
|
|
7
|
+
}
|
|
8
|
+
function hasOwnProperty(value, key) {
|
|
9
|
+
return Object.prototype.hasOwnProperty.call(value, key);
|
|
10
|
+
}
|
|
11
|
+
function normalizeID(value) {
|
|
12
|
+
if (value === null || value === undefined || value === '') {
|
|
13
|
+
return null;
|
|
14
|
+
}
|
|
15
|
+
if (typeof value === 'number' || typeof value === 'string') {
|
|
16
|
+
return stringifyDocID(value);
|
|
17
|
+
}
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
function normalizeMoveDocumentBody(value) {
|
|
21
|
+
const incomingData = typeof value === 'string' ? (()=>{
|
|
22
|
+
try {
|
|
23
|
+
return JSON.parse(value);
|
|
24
|
+
} catch {
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
})() : value;
|
|
28
|
+
if (!incomingData || typeof incomingData !== 'object' || Array.isArray(incomingData)) {
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
if (!hasOwnProperty(incomingData, 'parentID')) {
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
const parentID = normalizeID(incomingData.parentID);
|
|
35
|
+
if (incomingData.parentID !== null && incomingData.parentID !== undefined && parentID === null) {
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
return {
|
|
39
|
+
parentID
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
async function readBodyFromRequest(req) {
|
|
43
|
+
const directBody = normalizeMoveDocumentBody(req.data);
|
|
44
|
+
if (directBody) {
|
|
45
|
+
return directBody;
|
|
46
|
+
}
|
|
47
|
+
if (typeof req.json === 'function') {
|
|
48
|
+
try {
|
|
49
|
+
const jsonBody = normalizeMoveDocumentBody(await req.json());
|
|
50
|
+
if (jsonBody) {
|
|
51
|
+
return jsonBody;
|
|
52
|
+
}
|
|
53
|
+
} catch {
|
|
54
|
+
// Fall through to the text-based fallback when the runtime does not hydrate req.data.
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
if (typeof req.text === 'function') {
|
|
58
|
+
try {
|
|
59
|
+
return normalizeMoveDocumentBody(await req.text());
|
|
60
|
+
} catch {
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
function getPayloadCollection({ collectionSlug, req }) {
|
|
67
|
+
return req.payload.collections[collectionSlug];
|
|
68
|
+
}
|
|
69
|
+
function usesNumericID({ collectionSlug, req }) {
|
|
70
|
+
const collection = getPayloadCollection({
|
|
71
|
+
collectionSlug,
|
|
72
|
+
req
|
|
73
|
+
});
|
|
74
|
+
if (!collection) {
|
|
75
|
+
return false;
|
|
76
|
+
}
|
|
77
|
+
const idType = collection.customIDType ?? req.payload.db.defaultIDType;
|
|
78
|
+
return idType === 'number';
|
|
79
|
+
}
|
|
80
|
+
function toCollectionID(args) {
|
|
81
|
+
const { collectionSlug, id, req } = args;
|
|
82
|
+
if (!usesNumericID({
|
|
83
|
+
collectionSlug,
|
|
84
|
+
req
|
|
85
|
+
})) {
|
|
86
|
+
return id;
|
|
87
|
+
}
|
|
88
|
+
return Number(id);
|
|
89
|
+
}
|
|
90
|
+
function getRequestedLocale(req) {
|
|
91
|
+
return req.locale && req.locale !== 'all' ? req.locale : undefined;
|
|
92
|
+
}
|
|
93
|
+
function collectionHasDrafts(args) {
|
|
94
|
+
return Boolean(getPayloadCollection(args)?.config?.versions?.drafts);
|
|
95
|
+
}
|
|
96
|
+
async function assertUpdateAccess(args) {
|
|
97
|
+
const { collectionSlug, movedID, nextParentID, parentFieldSlug, req } = args;
|
|
98
|
+
const collection = getPayloadCollection({
|
|
99
|
+
collectionSlug,
|
|
100
|
+
req
|
|
101
|
+
});
|
|
102
|
+
const updateAccess = collection?.config?.access?.update;
|
|
103
|
+
if (!updateAccess) {
|
|
104
|
+
return null;
|
|
105
|
+
}
|
|
106
|
+
const accessResult = await updateAccess({
|
|
107
|
+
data: {
|
|
108
|
+
[parentFieldSlug]: nextParentID
|
|
109
|
+
},
|
|
110
|
+
id: movedID,
|
|
111
|
+
req
|
|
112
|
+
});
|
|
113
|
+
if (accessResult === false) {
|
|
114
|
+
return respond(403, {
|
|
115
|
+
message: req.i18n.t('error:unauthorized')
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
if (accessResult && typeof accessResult === 'object') {
|
|
119
|
+
const matchingDocs = await req.payload.find({
|
|
120
|
+
collection: collectionSlug,
|
|
121
|
+
depth: 0,
|
|
122
|
+
draft: collectionHasDrafts({
|
|
123
|
+
collectionSlug,
|
|
124
|
+
req
|
|
125
|
+
}) ? true : undefined,
|
|
126
|
+
limit: 1,
|
|
127
|
+
locale: getRequestedLocale(req),
|
|
128
|
+
overrideAccess: true,
|
|
129
|
+
req,
|
|
130
|
+
where: {
|
|
131
|
+
and: [
|
|
132
|
+
{
|
|
133
|
+
id: {
|
|
134
|
+
equals: movedID
|
|
135
|
+
}
|
|
136
|
+
},
|
|
137
|
+
accessResult
|
|
138
|
+
]
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
if (matchingDocs.docs.length === 0) {
|
|
142
|
+
return respond(403, {
|
|
143
|
+
message: req.i18n.t('error:unauthorized')
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
return null;
|
|
148
|
+
}
|
|
149
|
+
export function createMovePageEndpoint(args) {
|
|
150
|
+
const { collectionSlug, parentFieldSlug } = args;
|
|
151
|
+
return {
|
|
152
|
+
handler: async (req)=>{
|
|
153
|
+
const movedIDFromRoute = normalizeID(req.routeParams?.id);
|
|
154
|
+
if (!movedIDFromRoute) {
|
|
155
|
+
return respond(400, {
|
|
156
|
+
message: 'Document ID was not specified.'
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
const body = await readBodyFromRequest(req);
|
|
160
|
+
if (!body) {
|
|
161
|
+
return respond(400, {
|
|
162
|
+
message: 'A valid parentID is required.'
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
const movedID = toCollectionID({
|
|
166
|
+
collectionSlug,
|
|
167
|
+
id: movedIDFromRoute,
|
|
168
|
+
req
|
|
169
|
+
});
|
|
170
|
+
const nextParentID = body.parentID === null ? null : toCollectionID({
|
|
171
|
+
collectionSlug,
|
|
172
|
+
id: body.parentID,
|
|
173
|
+
req
|
|
174
|
+
});
|
|
175
|
+
const accessError = await assertUpdateAccess({
|
|
176
|
+
collectionSlug,
|
|
177
|
+
movedID,
|
|
178
|
+
nextParentID,
|
|
179
|
+
parentFieldSlug,
|
|
180
|
+
req
|
|
181
|
+
});
|
|
182
|
+
if (accessError) {
|
|
183
|
+
return accessError;
|
|
184
|
+
}
|
|
185
|
+
const docsResult = await req.payload.find({
|
|
186
|
+
collection: collectionSlug,
|
|
187
|
+
depth: 0,
|
|
188
|
+
draft: collectionHasDrafts({
|
|
189
|
+
collectionSlug,
|
|
190
|
+
req
|
|
191
|
+
}) ? true : undefined,
|
|
192
|
+
fallbackLocale: false,
|
|
193
|
+
limit: 0,
|
|
194
|
+
locale: getRequestedLocale(req),
|
|
195
|
+
overrideAccess: true,
|
|
196
|
+
req
|
|
197
|
+
});
|
|
198
|
+
const docs = docsResult.docs;
|
|
199
|
+
const docsByID = new Map(docs.map((doc)=>[
|
|
200
|
+
stringifyDocID(doc.id),
|
|
201
|
+
doc
|
|
202
|
+
]));
|
|
203
|
+
const movedDoc = docsByID.get(movedIDFromRoute);
|
|
204
|
+
if (!movedDoc) {
|
|
205
|
+
return respond(404, {
|
|
206
|
+
message: 'Document not found.'
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
if (body.parentID !== null && !docsByID.has(body.parentID)) {
|
|
210
|
+
return respond(400, {
|
|
211
|
+
message: 'Parent document not found.'
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
const currentParentID = getDocParentID(movedDoc, parentFieldSlug);
|
|
215
|
+
if (currentParentID === body.parentID) {
|
|
216
|
+
return respond(400, {
|
|
217
|
+
message: 'Document already has that parent.'
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
if (body.parentID === movedIDFromRoute) {
|
|
221
|
+
return respond(400, {
|
|
222
|
+
message: CANCEL_DRAG_MESSAGE
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
const childrenByParentID = buildChildrenByParentID({
|
|
226
|
+
docs,
|
|
227
|
+
parentFieldSlug
|
|
228
|
+
});
|
|
229
|
+
const descendantIDs = collectDescendantIDs(movedIDFromRoute, childrenByParentID);
|
|
230
|
+
if (body.parentID !== null && descendantIDs.includes(body.parentID)) {
|
|
231
|
+
return respond(400, {
|
|
232
|
+
message: 'A document cannot be moved under one of its descendants.'
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
await req.payload.update({
|
|
236
|
+
collection: collectionSlug,
|
|
237
|
+
data: {
|
|
238
|
+
[parentFieldSlug]: body.parentID === null ? null : toCollectionID({
|
|
239
|
+
collectionSlug,
|
|
240
|
+
id: body.parentID,
|
|
241
|
+
req
|
|
242
|
+
})
|
|
243
|
+
},
|
|
244
|
+
depth: 0,
|
|
245
|
+
draft: collectionHasDrafts({
|
|
246
|
+
collectionSlug,
|
|
247
|
+
req
|
|
248
|
+
}) ? true : undefined,
|
|
249
|
+
id: movedID,
|
|
250
|
+
locale: getRequestedLocale(req),
|
|
251
|
+
overrideAccess: true,
|
|
252
|
+
req
|
|
253
|
+
});
|
|
254
|
+
return respond(200, {
|
|
255
|
+
movedID: movedIDFromRoute,
|
|
256
|
+
ok: true,
|
|
257
|
+
parentID: body.parentID
|
|
258
|
+
});
|
|
259
|
+
},
|
|
260
|
+
method: 'post',
|
|
261
|
+
path: '/:id/move'
|
|
262
|
+
};
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
//# sourceMappingURL=createMovePageEndpoint.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/endpoints/createMovePageEndpoint.ts"],"sourcesContent":["import type { Endpoint, PayloadRequest, Where } from 'payload'\r\n\r\nimport { CANCEL_DRAG_MESSAGE } from '../utilities/moveValidation.js'\r\nimport {\r\n buildChildrenByParentID,\r\n collectDescendantIDs,\r\n getDocParentID,\r\n stringifyDocID,\r\n} from '../utilities/pageTree.js'\r\nimport type { PageTreeSourceDoc } from '../types.js'\r\n\r\ntype MoveDocumentRequestBody = {\r\n parentID: null | string\r\n}\r\n\r\ntype PayloadCollectionLike = {\r\n config?: {\r\n access?: {\r\n update?: ((args: Record<string, unknown>) => Promise<Record<string, unknown> | boolean> | Record<string, unknown> | boolean) | undefined\r\n }\r\n versions?: {\r\n drafts?: unknown\r\n }\r\n }\r\n customIDType?: string\r\n}\r\n\r\nfunction respond(status: number, body: Record<string, unknown>) {\r\n return Response.json(body, { status })\r\n}\r\n\r\nfunction hasOwnProperty(value: object, key: PropertyKey): boolean {\r\n return Object.prototype.hasOwnProperty.call(value, key)\r\n}\r\n\r\nfunction normalizeID(value: unknown): null | string {\r\n if (value === null || value === undefined || value === '') {\r\n return null\r\n }\r\n\r\n if (typeof value === 'number' || typeof value === 'string') {\r\n return stringifyDocID(value)\r\n }\r\n\r\n return null\r\n}\r\n\r\nfunction normalizeMoveDocumentBody(value: unknown): MoveDocumentRequestBody | null {\r\n const incomingData =\r\n typeof value === 'string'\r\n ? (() => {\r\n try {\r\n return JSON.parse(value) as unknown\r\n } catch {\r\n return null\r\n }\r\n })()\r\n : value\r\n\r\n if (!incomingData || typeof incomingData !== 'object' || Array.isArray(incomingData)) {\r\n return null\r\n }\r\n\r\n if (!hasOwnProperty(incomingData, 'parentID')) {\r\n return null\r\n }\r\n\r\n const parentID = normalizeID((incomingData as { parentID?: unknown }).parentID)\r\n\r\n if (\r\n (incomingData as { parentID?: unknown }).parentID !== null &&\r\n (incomingData as { parentID?: unknown }).parentID !== undefined &&\r\n parentID === null\r\n ) {\r\n return null\r\n }\r\n\r\n return {\r\n parentID,\r\n }\r\n}\r\n\r\nasync function readBodyFromRequest(req: PayloadRequest): Promise<MoveDocumentRequestBody | null> {\r\n const directBody = normalizeMoveDocumentBody(req.data)\r\n\r\n if (directBody) {\r\n return directBody\r\n }\r\n\r\n if (typeof req.json === 'function') {\r\n try {\r\n const jsonBody = normalizeMoveDocumentBody(await req.json())\r\n\r\n if (jsonBody) {\r\n return jsonBody\r\n }\r\n } catch {\r\n // Fall through to the text-based fallback when the runtime does not hydrate req.data.\r\n }\r\n }\r\n\r\n if (typeof req.text === 'function') {\r\n try {\r\n return normalizeMoveDocumentBody(await req.text())\r\n } catch {\r\n return null\r\n }\r\n }\r\n\r\n return null\r\n}\r\n\r\nfunction getPayloadCollection({\r\n collectionSlug,\r\n req,\r\n}: {\r\n collectionSlug: string\r\n req: PayloadRequest\r\n}): PayloadCollectionLike | undefined {\r\n return (req.payload.collections as unknown as Record<string, PayloadCollectionLike | undefined>)[\r\n collectionSlug\r\n ]\r\n}\r\n\r\nfunction usesNumericID({\r\n collectionSlug,\r\n req,\r\n}: {\r\n collectionSlug: string\r\n req: PayloadRequest\r\n}): boolean {\r\n const collection = getPayloadCollection({ collectionSlug, req })\r\n\r\n if (!collection) {\r\n return false\r\n }\r\n\r\n const idType = collection.customIDType ?? req.payload.db.defaultIDType\r\n\r\n return idType === 'number'\r\n}\r\n\r\nfunction toCollectionID(args: {\r\n collectionSlug: string\r\n id: string\r\n req: PayloadRequest\r\n}): number | string {\r\n const { collectionSlug, id, req } = args\r\n\r\n if (!usesNumericID({ collectionSlug, req })) {\r\n return id\r\n }\r\n\r\n return Number(id)\r\n}\r\n\r\nfunction getRequestedLocale(req: PayloadRequest): string | undefined {\r\n return req.locale && req.locale !== 'all' ? req.locale : undefined\r\n}\r\n\r\nfunction collectionHasDrafts(args: {\r\n collectionSlug: string\r\n req: PayloadRequest\r\n}): boolean {\r\n return Boolean(getPayloadCollection(args)?.config?.versions?.drafts)\r\n}\r\n\r\nasync function assertUpdateAccess(args: {\r\n collectionSlug: string\r\n movedID: number | string\r\n nextParentID: null | number | string\r\n parentFieldSlug: string\r\n req: PayloadRequest\r\n}): Promise<Response | null> {\r\n const { collectionSlug, movedID, nextParentID, parentFieldSlug, req } = args\r\n const collection = getPayloadCollection({ collectionSlug, req })\r\n const updateAccess = collection?.config?.access?.update\r\n\r\n if (!updateAccess) {\r\n return null\r\n }\r\n\r\n const accessResult = await updateAccess({\r\n data: { [parentFieldSlug]: nextParentID } as never,\r\n id: movedID as never,\r\n req,\r\n })\r\n\r\n if (accessResult === false) {\r\n return respond(403, {\r\n message: req.i18n.t('error:unauthorized'),\r\n })\r\n }\r\n\r\n if (accessResult && typeof accessResult === 'object') {\r\n const matchingDocs = await req.payload.find({\r\n collection: collectionSlug as never,\r\n depth: 0,\r\n draft: collectionHasDrafts({ collectionSlug, req }) ? true : undefined,\r\n limit: 1,\r\n locale: getRequestedLocale(req) as never,\r\n overrideAccess: true,\r\n req,\r\n where: {\r\n and: [\r\n {\r\n id: {\r\n equals: movedID,\r\n },\r\n },\r\n accessResult as Where,\r\n ],\r\n },\r\n } as never)\r\n\r\n if (matchingDocs.docs.length === 0) {\r\n return respond(403, {\r\n message: req.i18n.t('error:unauthorized'),\r\n })\r\n }\r\n }\r\n\r\n return null\r\n}\r\n\r\nexport function createMovePageEndpoint(args: {\r\n collectionSlug: string\r\n parentFieldSlug: string\r\n}): Endpoint {\r\n const { collectionSlug, parentFieldSlug } = args\r\n\r\n return {\r\n handler: async (req) => {\r\n const movedIDFromRoute = normalizeID(req.routeParams?.id)\r\n\r\n if (!movedIDFromRoute) {\r\n return respond(400, {\r\n message: 'Document ID was not specified.',\r\n })\r\n }\r\n\r\n const body = await readBodyFromRequest(req)\r\n\r\n if (!body) {\r\n return respond(400, {\r\n message: 'A valid parentID is required.',\r\n })\r\n }\r\n\r\n const movedID = toCollectionID({\r\n collectionSlug,\r\n id: movedIDFromRoute,\r\n req,\r\n })\r\n const nextParentID =\r\n body.parentID === null\r\n ? null\r\n : toCollectionID({\r\n collectionSlug,\r\n id: body.parentID,\r\n req,\r\n })\r\n const accessError = await assertUpdateAccess({\r\n collectionSlug,\r\n movedID,\r\n nextParentID,\r\n parentFieldSlug,\r\n req,\r\n })\r\n\r\n if (accessError) {\r\n return accessError\r\n }\r\n\r\n const docsResult = await req.payload.find({\r\n collection: collectionSlug as never,\r\n depth: 0,\r\n draft: collectionHasDrafts({ collectionSlug, req }) ? true : undefined,\r\n fallbackLocale: false as never,\r\n limit: 0,\r\n locale: getRequestedLocale(req) as never,\r\n overrideAccess: true,\r\n req,\r\n } as never)\r\n const docs = docsResult.docs as unknown as PageTreeSourceDoc[]\r\n const docsByID = new Map(docs.map((doc) => [stringifyDocID(doc.id), doc]))\r\n const movedDoc = docsByID.get(movedIDFromRoute)\r\n\r\n if (!movedDoc) {\r\n return respond(404, {\r\n message: 'Document not found.',\r\n })\r\n }\r\n\r\n if (body.parentID !== null && !docsByID.has(body.parentID)) {\r\n return respond(400, {\r\n message: 'Parent document not found.',\r\n })\r\n }\r\n\r\n const currentParentID = getDocParentID(movedDoc, parentFieldSlug)\r\n\r\n if (currentParentID === body.parentID) {\r\n return respond(400, {\r\n message: 'Document already has that parent.',\r\n })\r\n }\r\n\r\n if (body.parentID === movedIDFromRoute) {\r\n return respond(400, {\r\n message: CANCEL_DRAG_MESSAGE,\r\n })\r\n }\r\n\r\n const childrenByParentID = buildChildrenByParentID({\r\n docs,\r\n parentFieldSlug,\r\n })\r\n const descendantIDs = collectDescendantIDs(movedIDFromRoute, childrenByParentID)\r\n\r\n if (body.parentID !== null && descendantIDs.includes(body.parentID)) {\r\n return respond(400, {\r\n message: 'A document cannot be moved under one of its descendants.',\r\n })\r\n }\r\n\r\n await req.payload.update({\r\n collection: collectionSlug as never,\r\n data: {\r\n [parentFieldSlug]:\r\n body.parentID === null\r\n ? null\r\n : toCollectionID({\r\n collectionSlug,\r\n id: body.parentID,\r\n req,\r\n }),\r\n } as never,\r\n depth: 0,\r\n draft: collectionHasDrafts({ collectionSlug, req }) ? true : undefined,\r\n id: movedID as never,\r\n locale: getRequestedLocale(req) as never,\r\n overrideAccess: true,\r\n req,\r\n } as never)\r\n\r\n return respond(200, {\r\n movedID: movedIDFromRoute,\r\n ok: true,\r\n parentID: body.parentID,\r\n })\r\n },\r\n method: 'post',\r\n path: '/:id/move',\r\n }\r\n}\r\n"],"names":["CANCEL_DRAG_MESSAGE","buildChildrenByParentID","collectDescendantIDs","getDocParentID","stringifyDocID","respond","status","body","Response","json","hasOwnProperty","value","key","Object","prototype","call","normalizeID","undefined","normalizeMoveDocumentBody","incomingData","JSON","parse","Array","isArray","parentID","readBodyFromRequest","req","directBody","data","jsonBody","text","getPayloadCollection","collectionSlug","payload","collections","usesNumericID","collection","idType","customIDType","db","defaultIDType","toCollectionID","args","id","Number","getRequestedLocale","locale","collectionHasDrafts","Boolean","config","versions","drafts","assertUpdateAccess","movedID","nextParentID","parentFieldSlug","updateAccess","access","update","accessResult","message","i18n","t","matchingDocs","find","depth","draft","limit","overrideAccess","where","and","equals","docs","length","createMovePageEndpoint","handler","movedIDFromRoute","routeParams","accessError","docsResult","fallbackLocale","docsByID","Map","map","doc","movedDoc","get","has","currentParentID","childrenByParentID","descendantIDs","includes","ok","method","path"],"mappings":"AAEA,SAASA,mBAAmB,QAAQ,iCAAgC;AACpE,SACEC,uBAAuB,EACvBC,oBAAoB,EACpBC,cAAc,EACdC,cAAc,QACT,2BAA0B;AAmBjC,SAASC,QAAQC,MAAc,EAAEC,IAA6B;IAC5D,OAAOC,SAASC,IAAI,CAACF,MAAM;QAAED;IAAO;AACtC;AAEA,SAASI,eAAeC,KAAa,EAAEC,GAAgB;IACrD,OAAOC,OAAOC,SAAS,CAACJ,cAAc,CAACK,IAAI,CAACJ,OAAOC;AACrD;AAEA,SAASI,YAAYL,KAAc;IACjC,IAAIA,UAAU,QAAQA,UAAUM,aAAaN,UAAU,IAAI;QACzD,OAAO;IACT;IAEA,IAAI,OAAOA,UAAU,YAAY,OAAOA,UAAU,UAAU;QAC1D,OAAOP,eAAeO;IACxB;IAEA,OAAO;AACT;AAEA,SAASO,0BAA0BP,KAAc;IAC/C,MAAMQ,eACJ,OAAOR,UAAU,WACb,AAAC,CAAA;QACC,IAAI;YACF,OAAOS,KAAKC,KAAK,CAACV;QACpB,EAAE,OAAM;YACN,OAAO;QACT;IACF,CAAA,MACAA;IAEN,IAAI,CAACQ,gBAAgB,OAAOA,iBAAiB,YAAYG,MAAMC,OAAO,CAACJ,eAAe;QACpF,OAAO;IACT;IAEA,IAAI,CAACT,eAAeS,cAAc,aAAa;QAC7C,OAAO;IACT;IAEA,MAAMK,WAAWR,YAAY,AAACG,aAAwCK,QAAQ;IAE9E,IACE,AAACL,aAAwCK,QAAQ,KAAK,QACtD,AAACL,aAAwCK,QAAQ,KAAKP,aACtDO,aAAa,MACb;QACA,OAAO;IACT;IAEA,OAAO;QACLA;IACF;AACF;AAEA,eAAeC,oBAAoBC,GAAmB;IACpD,MAAMC,aAAaT,0BAA0BQ,IAAIE,IAAI;IAErD,IAAID,YAAY;QACd,OAAOA;IACT;IAEA,IAAI,OAAOD,IAAIjB,IAAI,KAAK,YAAY;QAClC,IAAI;YACF,MAAMoB,WAAWX,0BAA0B,MAAMQ,IAAIjB,IAAI;YAEzD,IAAIoB,UAAU;gBACZ,OAAOA;YACT;QACF,EAAE,OAAM;QACN,sFAAsF;QACxF;IACF;IAEA,IAAI,OAAOH,IAAII,IAAI,KAAK,YAAY;QAClC,IAAI;YACF,OAAOZ,0BAA0B,MAAMQ,IAAII,IAAI;QACjD,EAAE,OAAM;YACN,OAAO;QACT;IACF;IAEA,OAAO;AACT;AAEA,SAASC,qBAAqB,EAC5BC,cAAc,EACdN,GAAG,EAIJ;IACC,OAAO,AAACA,IAAIO,OAAO,CAACC,WAAW,AAAiE,CAC9FF,eACD;AACH;AAEA,SAASG,cAAc,EACrBH,cAAc,EACdN,GAAG,EAIJ;IACC,MAAMU,aAAaL,qBAAqB;QAAEC;QAAgBN;IAAI;IAE9D,IAAI,CAACU,YAAY;QACf,OAAO;IACT;IAEA,MAAMC,SAASD,WAAWE,YAAY,IAAIZ,IAAIO,OAAO,CAACM,EAAE,CAACC,aAAa;IAEtE,OAAOH,WAAW;AACpB;AAEA,SAASI,eAAeC,IAIvB;IACC,MAAM,EAAEV,cAAc,EAAEW,EAAE,EAAEjB,GAAG,EAAE,GAAGgB;IAEpC,IAAI,CAACP,cAAc;QAAEH;QAAgBN;IAAI,IAAI;QAC3C,OAAOiB;IACT;IAEA,OAAOC,OAAOD;AAChB;AAEA,SAASE,mBAAmBnB,GAAmB;IAC7C,OAAOA,IAAIoB,MAAM,IAAIpB,IAAIoB,MAAM,KAAK,QAAQpB,IAAIoB,MAAM,GAAG7B;AAC3D;AAEA,SAAS8B,oBAAoBL,IAG5B;IACC,OAAOM,QAAQjB,qBAAqBW,OAAOO,QAAQC,UAAUC;AAC/D;AAEA,eAAeC,mBAAmBV,IAMjC;IACC,MAAM,EAAEV,cAAc,EAAEqB,OAAO,EAAEC,YAAY,EAAEC,eAAe,EAAE7B,GAAG,EAAE,GAAGgB;IACxE,MAAMN,aAAaL,qBAAqB;QAAEC;QAAgBN;IAAI;IAC9D,MAAM8B,eAAepB,YAAYa,QAAQQ,QAAQC;IAEjD,IAAI,CAACF,cAAc;QACjB,OAAO;IACT;IAEA,MAAMG,eAAe,MAAMH,aAAa;QACtC5B,MAAM;YAAE,CAAC2B,gBAAgB,EAAED;QAAa;QACxCX,IAAIU;QACJ3B;IACF;IAEA,IAAIiC,iBAAiB,OAAO;QAC1B,OAAOtD,QAAQ,KAAK;YAClBuD,SAASlC,IAAImC,IAAI,CAACC,CAAC,CAAC;QACtB;IACF;IAEA,IAAIH,gBAAgB,OAAOA,iBAAiB,UAAU;QACpD,MAAMI,eAAe,MAAMrC,IAAIO,OAAO,CAAC+B,IAAI,CAAC;YAC1C5B,YAAYJ;YACZiC,OAAO;YACPC,OAAOnB,oBAAoB;gBAAEf;gBAAgBN;YAAI,KAAK,OAAOT;YAC7DkD,OAAO;YACPrB,QAAQD,mBAAmBnB;YAC3B0C,gBAAgB;YAChB1C;YACA2C,OAAO;gBACLC,KAAK;oBACH;wBACE3B,IAAI;4BACF4B,QAAQlB;wBACV;oBACF;oBACAM;iBACD;YACH;QACF;QAEA,IAAII,aAAaS,IAAI,CAACC,MAAM,KAAK,GAAG;YAClC,OAAOpE,QAAQ,KAAK;gBAClBuD,SAASlC,IAAImC,IAAI,CAACC,CAAC,CAAC;YACtB;QACF;IACF;IAEA,OAAO;AACT;AAEA,OAAO,SAASY,uBAAuBhC,IAGtC;IACC,MAAM,EAAEV,cAAc,EAAEuB,eAAe,EAAE,GAAGb;IAE5C,OAAO;QACLiC,SAAS,OAAOjD;YACd,MAAMkD,mBAAmB5D,YAAYU,IAAImD,WAAW,EAAElC;YAEtD,IAAI,CAACiC,kBAAkB;gBACrB,OAAOvE,QAAQ,KAAK;oBAClBuD,SAAS;gBACX;YACF;YAEA,MAAMrD,OAAO,MAAMkB,oBAAoBC;YAEvC,IAAI,CAACnB,MAAM;gBACT,OAAOF,QAAQ,KAAK;oBAClBuD,SAAS;gBACX;YACF;YAEA,MAAMP,UAAUZ,eAAe;gBAC7BT;gBACAW,IAAIiC;gBACJlD;YACF;YACA,MAAM4B,eACJ/C,KAAKiB,QAAQ,KAAK,OACd,OACAiB,eAAe;gBACbT;gBACAW,IAAIpC,KAAKiB,QAAQ;gBACjBE;YACF;YACN,MAAMoD,cAAc,MAAM1B,mBAAmB;gBAC3CpB;gBACAqB;gBACAC;gBACAC;gBACA7B;YACF;YAEA,IAAIoD,aAAa;gBACf,OAAOA;YACT;YAEA,MAAMC,aAAa,MAAMrD,IAAIO,OAAO,CAAC+B,IAAI,CAAC;gBACxC5B,YAAYJ;gBACZiC,OAAO;gBACPC,OAAOnB,oBAAoB;oBAAEf;oBAAgBN;gBAAI,KAAK,OAAOT;gBAC7D+D,gBAAgB;gBAChBb,OAAO;gBACPrB,QAAQD,mBAAmBnB;gBAC3B0C,gBAAgB;gBAChB1C;YACF;YACA,MAAM8C,OAAOO,WAAWP,IAAI;YAC5B,MAAMS,WAAW,IAAIC,IAAIV,KAAKW,GAAG,CAAC,CAACC,MAAQ;oBAAChF,eAAegF,IAAIzC,EAAE;oBAAGyC;iBAAI;YACxE,MAAMC,WAAWJ,SAASK,GAAG,CAACV;YAE9B,IAAI,CAACS,UAAU;gBACb,OAAOhF,QAAQ,KAAK;oBAClBuD,SAAS;gBACX;YACF;YAEA,IAAIrD,KAAKiB,QAAQ,KAAK,QAAQ,CAACyD,SAASM,GAAG,CAAChF,KAAKiB,QAAQ,GAAG;gBAC1D,OAAOnB,QAAQ,KAAK;oBAClBuD,SAAS;gBACX;YACF;YAEA,MAAM4B,kBAAkBrF,eAAekF,UAAU9B;YAEjD,IAAIiC,oBAAoBjF,KAAKiB,QAAQ,EAAE;gBACrC,OAAOnB,QAAQ,KAAK;oBAClBuD,SAAS;gBACX;YACF;YAEA,IAAIrD,KAAKiB,QAAQ,KAAKoD,kBAAkB;gBACtC,OAAOvE,QAAQ,KAAK;oBAClBuD,SAAS5D;gBACX;YACF;YAEA,MAAMyF,qBAAqBxF,wBAAwB;gBACjDuE;gBACAjB;YACF;YACA,MAAMmC,gBAAgBxF,qBAAqB0E,kBAAkBa;YAE7D,IAAIlF,KAAKiB,QAAQ,KAAK,QAAQkE,cAAcC,QAAQ,CAACpF,KAAKiB,QAAQ,GAAG;gBACnE,OAAOnB,QAAQ,KAAK;oBAClBuD,SAAS;gBACX;YACF;YAEA,MAAMlC,IAAIO,OAAO,CAACyB,MAAM,CAAC;gBACvBtB,YAAYJ;gBACZJ,MAAM;oBACJ,CAAC2B,gBAAgB,EACfhD,KAAKiB,QAAQ,KAAK,OACd,OACAiB,eAAe;wBACbT;wBACAW,IAAIpC,KAAKiB,QAAQ;wBACjBE;oBACF;gBACR;gBACAuC,OAAO;gBACPC,OAAOnB,oBAAoB;oBAAEf;oBAAgBN;gBAAI,KAAK,OAAOT;gBAC7D0B,IAAIU;gBACJP,QAAQD,mBAAmBnB;gBAC3B0C,gBAAgB;gBAChB1C;YACF;YAEA,OAAOrB,QAAQ,KAAK;gBAClBgD,SAASuB;gBACTgB,IAAI;gBACJpE,UAAUjB,KAAKiB,QAAQ;YACzB;QACF;QACAqE,QAAQ;QACRC,MAAM;IACR;AACF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as PageTreeListViewClient } from '../components/PageTreeListView.client.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/exports/client.ts"],"sourcesContent":["export { default as PageTreeListViewClient } from '../components/PageTreeListView.client.js'\n"],"names":["default","PageTreeListViewClient"],"mappings":"AAAA,SAASA,WAAWC,sBAAsB,QAAQ,2CAA0C"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { NestedDocsPageTreeListView } from '../components/PageTreeListView.server.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/exports/rsc.ts"],"sourcesContent":["export { NestedDocsPageTreeListView } from '../components/PageTreeListView.server.js'\n"],"names":["NestedDocsPageTreeListView"],"mappings":"AAAA,SAASA,0BAA0B,QAAQ,2CAA0C"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { Config } from 'payload';
|
|
2
|
+
import type { NestedDocsPageTreePluginConfig } from './types.js';
|
|
3
|
+
export type { NestedDocsPageTreePluginBadgeConfig, NestedDocsPageTreePluginBadgeMap, NestedDocsPageTreePluginBadgeStatus, NestedDocsPageTreePluginConfig, } from './types.js';
|
|
4
|
+
export declare const nestedDocsPageTreePlugin: (pluginOptions: NestedDocsPageTreePluginConfig) => (config: Config) => Config;
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import { createMovePageEndpoint } from './endpoints/createMovePageEndpoint.js';
|
|
2
|
+
import { nestedDocsPageTreePluginCustomKey } from './types.js';
|
|
3
|
+
import { normalizeNestedDocsPageTreePluginBadgeConfig } from './utilities/badgeConfig.js';
|
|
4
|
+
const DEFAULT_BREADCRUMBS_FIELD_SLUG = 'breadcrumbs';
|
|
5
|
+
const DEFAULT_LIMIT = 100;
|
|
6
|
+
const DEFAULT_PARENT_FIELD_SLUG = 'parent';
|
|
7
|
+
const PAGE_TREE_LIST_VIEW_PATH = 'payload-nested-docs-page-tree/rsc#NestedDocsPageTreeListView';
|
|
8
|
+
function getTopLevelField(collection, fieldName) {
|
|
9
|
+
return collection.fields.find((field)=>'name' in field && field.name === fieldName);
|
|
10
|
+
}
|
|
11
|
+
function getCollectionEndpoints(collection) {
|
|
12
|
+
return Array.isArray(collection.endpoints) ? [
|
|
13
|
+
...collection.endpoints
|
|
14
|
+
] : [];
|
|
15
|
+
}
|
|
16
|
+
function patchBreadcrumbField(args) {
|
|
17
|
+
const { breadcrumbsFieldSlug, field, hideBreadcrumbs } = args;
|
|
18
|
+
if (!('name' in field) || field.name !== breadcrumbsFieldSlug) {
|
|
19
|
+
return field;
|
|
20
|
+
}
|
|
21
|
+
return {
|
|
22
|
+
...field,
|
|
23
|
+
admin: {
|
|
24
|
+
...field.admin ?? {},
|
|
25
|
+
hidden: hideBreadcrumbs
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
function validateTargetCollection(args) {
|
|
30
|
+
const { breadcrumbsFieldSlug, collection, parentFieldSlug } = args;
|
|
31
|
+
if (typeof collection.admin?.useAsTitle !== 'string' || collection.admin.useAsTitle.includes('.')) {
|
|
32
|
+
throw new Error(`payload-nested-docs-page-tree requires "${collection.slug}" to define a top-level admin.useAsTitle field.`);
|
|
33
|
+
}
|
|
34
|
+
if (!getTopLevelField(collection, collection.admin.useAsTitle)) {
|
|
35
|
+
throw new Error(`payload-nested-docs-page-tree could not find the useAsTitle field "${collection.admin.useAsTitle}" on "${collection.slug}".`);
|
|
36
|
+
}
|
|
37
|
+
if (!getTopLevelField(collection, parentFieldSlug)) {
|
|
38
|
+
throw new Error(`payload-nested-docs-page-tree requires "${collection.slug}" to already define the nested docs parent field "${parentFieldSlug}". Register @payloadcms/plugin-nested-docs before payload-nested-docs-page-tree.`);
|
|
39
|
+
}
|
|
40
|
+
if (!getTopLevelField(collection, breadcrumbsFieldSlug)) {
|
|
41
|
+
throw new Error(`payload-nested-docs-page-tree requires "${collection.slug}" to already define the nested docs breadcrumbs field "${breadcrumbsFieldSlug}". Register @payloadcms/plugin-nested-docs before payload-nested-docs-page-tree.`);
|
|
42
|
+
}
|
|
43
|
+
const existingListView = collection.admin?.components?.views?.list?.Component;
|
|
44
|
+
if (existingListView && existingListView !== PAGE_TREE_LIST_VIEW_PATH) {
|
|
45
|
+
throw new Error(`payload-nested-docs-page-tree cannot own the "${collection.slug}" list view because the collection already defines a custom admin.components.views.list.Component.`);
|
|
46
|
+
}
|
|
47
|
+
const existingMoveEndpoint = getCollectionEndpoints(collection).find((endpoint)=>endpoint.path === '/:id/move');
|
|
48
|
+
if (existingMoveEndpoint) {
|
|
49
|
+
throw new Error(`payload-nested-docs-page-tree cannot add the move endpoint to "${collection.slug}" because the collection already defines POST /:id/move.`);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
function buildCollectionCustom(args) {
|
|
53
|
+
const { badges, breadcrumbsFieldSlug, defaultLimit, hideBreadcrumbs, parentFieldSlug } = args;
|
|
54
|
+
return {
|
|
55
|
+
badges,
|
|
56
|
+
breadcrumbsFieldSlug,
|
|
57
|
+
defaultLimit,
|
|
58
|
+
hideBreadcrumbs,
|
|
59
|
+
parentFieldSlug
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
export const nestedDocsPageTreePlugin = (pluginOptions)=>(config)=>{
|
|
63
|
+
if (!pluginOptions.collections?.length) {
|
|
64
|
+
throw new Error('payload-nested-docs-page-tree requires at least one collection slug.');
|
|
65
|
+
}
|
|
66
|
+
if (pluginOptions.disabled) {
|
|
67
|
+
return config;
|
|
68
|
+
}
|
|
69
|
+
const breadcrumbsFieldSlug = pluginOptions.breadcrumbsFieldSlug ?? DEFAULT_BREADCRUMBS_FIELD_SLUG;
|
|
70
|
+
const defaultLimit = pluginOptions.defaultLimit ?? DEFAULT_LIMIT;
|
|
71
|
+
const hideBreadcrumbs = pluginOptions.hideBreadcrumbs ?? true;
|
|
72
|
+
const parentFieldSlug = pluginOptions.parentFieldSlug ?? DEFAULT_PARENT_FIELD_SLUG;
|
|
73
|
+
const badges = normalizeNestedDocsPageTreePluginBadgeConfig(pluginOptions.badges);
|
|
74
|
+
const targetedCollectionSlugs = new Set(pluginOptions.collections);
|
|
75
|
+
if (!config.collections?.length) {
|
|
76
|
+
throw new Error('payload-nested-docs-page-tree could not find any collections to patch.');
|
|
77
|
+
}
|
|
78
|
+
const foundCollectionSlugs = new Set();
|
|
79
|
+
const nextCollections = config.collections.map((collection)=>{
|
|
80
|
+
if (!targetedCollectionSlugs.has(collection.slug)) {
|
|
81
|
+
return collection;
|
|
82
|
+
}
|
|
83
|
+
foundCollectionSlugs.add(collection.slug);
|
|
84
|
+
validateTargetCollection({
|
|
85
|
+
breadcrumbsFieldSlug,
|
|
86
|
+
collection,
|
|
87
|
+
parentFieldSlug
|
|
88
|
+
});
|
|
89
|
+
return {
|
|
90
|
+
...collection,
|
|
91
|
+
admin: {
|
|
92
|
+
...collection.admin ?? {},
|
|
93
|
+
components: {
|
|
94
|
+
...collection.admin?.components ?? {},
|
|
95
|
+
views: {
|
|
96
|
+
...collection.admin?.components?.views ?? {},
|
|
97
|
+
list: {
|
|
98
|
+
...collection.admin?.components?.views?.list ?? {},
|
|
99
|
+
Component: PAGE_TREE_LIST_VIEW_PATH
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
},
|
|
103
|
+
pagination: {
|
|
104
|
+
...collection.admin?.pagination ?? {},
|
|
105
|
+
defaultLimit: collection.admin?.pagination?.defaultLimit === undefined ? defaultLimit : collection.admin.pagination.defaultLimit
|
|
106
|
+
}
|
|
107
|
+
},
|
|
108
|
+
custom: {
|
|
109
|
+
...collection.custom ?? {},
|
|
110
|
+
[nestedDocsPageTreePluginCustomKey]: buildCollectionCustom({
|
|
111
|
+
badges,
|
|
112
|
+
breadcrumbsFieldSlug,
|
|
113
|
+
defaultLimit,
|
|
114
|
+
hideBreadcrumbs,
|
|
115
|
+
parentFieldSlug
|
|
116
|
+
})
|
|
117
|
+
},
|
|
118
|
+
endpoints: [
|
|
119
|
+
...getCollectionEndpoints(collection),
|
|
120
|
+
createMovePageEndpoint({
|
|
121
|
+
collectionSlug: collection.slug,
|
|
122
|
+
parentFieldSlug
|
|
123
|
+
})
|
|
124
|
+
],
|
|
125
|
+
fields: collection.fields.map((field)=>patchBreadcrumbField({
|
|
126
|
+
breadcrumbsFieldSlug,
|
|
127
|
+
field,
|
|
128
|
+
hideBreadcrumbs
|
|
129
|
+
}))
|
|
130
|
+
};
|
|
131
|
+
});
|
|
132
|
+
const missingCollections = pluginOptions.collections.filter((collectionSlug)=>!foundCollectionSlugs.has(collectionSlug));
|
|
133
|
+
if (missingCollections.length > 0) {
|
|
134
|
+
throw new Error(`payload-nested-docs-page-tree could not find the following collections: ${missingCollections.join(', ')}`);
|
|
135
|
+
}
|
|
136
|
+
return {
|
|
137
|
+
...config,
|
|
138
|
+
collections: nextCollections
|
|
139
|
+
};
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import type { CollectionConfig, Config } from 'payload'\n\nimport { createMovePageEndpoint } from './endpoints/createMovePageEndpoint.js'\nimport type {\n NestedDocsPageTreePluginCollectionCustom,\n NestedDocsPageTreePluginConfig,\n} from './types.js'\nimport { nestedDocsPageTreePluginCustomKey } from './types.js'\nimport { normalizeNestedDocsPageTreePluginBadgeConfig } from './utilities/badgeConfig.js'\n\nconst DEFAULT_BREADCRUMBS_FIELD_SLUG = 'breadcrumbs'\nconst DEFAULT_LIMIT = 100\nconst DEFAULT_PARENT_FIELD_SLUG = 'parent'\nconst PAGE_TREE_LIST_VIEW_PATH =\n 'payload-nested-docs-page-tree/rsc#NestedDocsPageTreeListView'\ntype CollectionEndpoint = NonNullable<Exclude<CollectionConfig['endpoints'], false>>[number]\n\nfunction getTopLevelField(\n collection: Pick<CollectionConfig, 'fields'>,\n fieldName: string,\n) {\n return collection.fields.find((field) => 'name' in field && field.name === fieldName)\n}\n\nfunction getCollectionEndpoints(collection: CollectionConfig): CollectionEndpoint[] {\n return Array.isArray(collection.endpoints) ? [...collection.endpoints] : []\n}\n\nfunction patchBreadcrumbField<TField extends CollectionConfig['fields'][number]>(args: {\n breadcrumbsFieldSlug: string\n field: TField\n hideBreadcrumbs: boolean\n}): TField {\n const { breadcrumbsFieldSlug, field, hideBreadcrumbs } = args\n\n if (!('name' in field) || field.name !== breadcrumbsFieldSlug) {\n return field\n }\n\n return {\n ...field,\n admin: {\n ...(field.admin ?? {}),\n hidden: hideBreadcrumbs,\n },\n } as TField\n}\n\nfunction validateTargetCollection(args: {\n breadcrumbsFieldSlug: string\n collection: CollectionConfig\n parentFieldSlug: string\n}) {\n const { breadcrumbsFieldSlug, collection, parentFieldSlug } = args\n\n if (typeof collection.admin?.useAsTitle !== 'string' || collection.admin.useAsTitle.includes('.')) {\n throw new Error(\n `payload-nested-docs-page-tree requires \"${collection.slug}\" to define a top-level admin.useAsTitle field.`,\n )\n }\n\n if (!getTopLevelField(collection, collection.admin.useAsTitle)) {\n throw new Error(\n `payload-nested-docs-page-tree could not find the useAsTitle field \"${collection.admin.useAsTitle}\" on \"${collection.slug}\".`,\n )\n }\n\n if (!getTopLevelField(collection, parentFieldSlug)) {\n throw new Error(\n `payload-nested-docs-page-tree requires \"${collection.slug}\" to already define the nested docs parent field \"${parentFieldSlug}\". Register @payloadcms/plugin-nested-docs before payload-nested-docs-page-tree.`,\n )\n }\n\n if (!getTopLevelField(collection, breadcrumbsFieldSlug)) {\n throw new Error(\n `payload-nested-docs-page-tree requires \"${collection.slug}\" to already define the nested docs breadcrumbs field \"${breadcrumbsFieldSlug}\". Register @payloadcms/plugin-nested-docs before payload-nested-docs-page-tree.`,\n )\n }\n\n const existingListView = collection.admin?.components?.views?.list?.Component\n\n if (existingListView && existingListView !== PAGE_TREE_LIST_VIEW_PATH) {\n throw new Error(\n `payload-nested-docs-page-tree cannot own the \"${collection.slug}\" list view because the collection already defines a custom admin.components.views.list.Component.`,\n )\n }\n\n const existingMoveEndpoint = getCollectionEndpoints(collection).find(\n (endpoint) => endpoint.path === '/:id/move',\n )\n\n if (existingMoveEndpoint) {\n throw new Error(\n `payload-nested-docs-page-tree cannot add the move endpoint to \"${collection.slug}\" because the collection already defines POST /:id/move.`,\n )\n }\n}\n\nfunction buildCollectionCustom(args: {\n badges: NestedDocsPageTreePluginCollectionCustom['badges']\n breadcrumbsFieldSlug: string\n defaultLimit: number\n hideBreadcrumbs: boolean\n parentFieldSlug: string\n}): NestedDocsPageTreePluginCollectionCustom {\n const { badges, breadcrumbsFieldSlug, defaultLimit, hideBreadcrumbs, parentFieldSlug } = args\n\n return {\n badges,\n breadcrumbsFieldSlug,\n defaultLimit,\n hideBreadcrumbs,\n parentFieldSlug,\n }\n}\n\nexport type {\n NestedDocsPageTreePluginBadgeConfig,\n NestedDocsPageTreePluginBadgeMap,\n NestedDocsPageTreePluginBadgeStatus,\n NestedDocsPageTreePluginConfig,\n} from './types.js'\n\nexport const nestedDocsPageTreePlugin =\n (pluginOptions: NestedDocsPageTreePluginConfig) =>\n (config: Config): Config => {\n if (!pluginOptions.collections?.length) {\n throw new Error('payload-nested-docs-page-tree requires at least one collection slug.')\n }\n\n if (pluginOptions.disabled) {\n return config\n }\n\n const breadcrumbsFieldSlug =\n pluginOptions.breadcrumbsFieldSlug ?? DEFAULT_BREADCRUMBS_FIELD_SLUG\n const defaultLimit = pluginOptions.defaultLimit ?? DEFAULT_LIMIT\n const hideBreadcrumbs = pluginOptions.hideBreadcrumbs ?? true\n const parentFieldSlug = pluginOptions.parentFieldSlug ?? DEFAULT_PARENT_FIELD_SLUG\n const badges = normalizeNestedDocsPageTreePluginBadgeConfig(pluginOptions.badges)\n const targetedCollectionSlugs = new Set<string>(pluginOptions.collections)\n\n if (!config.collections?.length) {\n throw new Error('payload-nested-docs-page-tree could not find any collections to patch.')\n }\n\n const foundCollectionSlugs = new Set<string>()\n const nextCollections = config.collections.map((collection) => {\n if (!targetedCollectionSlugs.has(collection.slug)) {\n return collection\n }\n\n foundCollectionSlugs.add(collection.slug)\n validateTargetCollection({\n breadcrumbsFieldSlug,\n collection,\n parentFieldSlug,\n })\n\n return {\n ...collection,\n admin: {\n ...(collection.admin ?? {}),\n components: {\n ...(collection.admin?.components ?? {}),\n views: {\n ...(collection.admin?.components?.views ?? {}),\n list: {\n ...(collection.admin?.components?.views?.list ?? {}),\n Component: PAGE_TREE_LIST_VIEW_PATH,\n },\n },\n },\n pagination: {\n ...(collection.admin?.pagination ?? {}),\n defaultLimit:\n collection.admin?.pagination?.defaultLimit === undefined\n ? defaultLimit\n : collection.admin.pagination.defaultLimit,\n },\n },\n custom: {\n ...(collection.custom ?? {}),\n [nestedDocsPageTreePluginCustomKey]: buildCollectionCustom({\n badges,\n breadcrumbsFieldSlug,\n defaultLimit,\n hideBreadcrumbs,\n parentFieldSlug,\n }),\n },\n endpoints: [\n ...getCollectionEndpoints(collection),\n createMovePageEndpoint({\n collectionSlug: collection.slug,\n parentFieldSlug,\n }),\n ],\n fields: collection.fields.map((field) =>\n patchBreadcrumbField({\n breadcrumbsFieldSlug,\n field,\n hideBreadcrumbs,\n }),\n ),\n }\n })\n\n const missingCollections = pluginOptions.collections.filter(\n (collectionSlug) => !foundCollectionSlugs.has(collectionSlug),\n )\n\n if (missingCollections.length > 0) {\n throw new Error(\n `payload-nested-docs-page-tree could not find the following collections: ${missingCollections.join(', ')}`,\n )\n }\n\n return {\n ...config,\n collections: nextCollections as CollectionConfig[],\n }\n }\n"],"names":["createMovePageEndpoint","nestedDocsPageTreePluginCustomKey","normalizeNestedDocsPageTreePluginBadgeConfig","DEFAULT_BREADCRUMBS_FIELD_SLUG","DEFAULT_LIMIT","DEFAULT_PARENT_FIELD_SLUG","PAGE_TREE_LIST_VIEW_PATH","getTopLevelField","collection","fieldName","fields","find","field","name","getCollectionEndpoints","Array","isArray","endpoints","patchBreadcrumbField","args","breadcrumbsFieldSlug","hideBreadcrumbs","admin","hidden","validateTargetCollection","parentFieldSlug","useAsTitle","includes","Error","slug","existingListView","components","views","list","Component","existingMoveEndpoint","endpoint","path","buildCollectionCustom","badges","defaultLimit","nestedDocsPageTreePlugin","pluginOptions","config","collections","length","disabled","targetedCollectionSlugs","Set","foundCollectionSlugs","nextCollections","map","has","add","pagination","undefined","custom","collectionSlug","missingCollections","filter","join"],"mappings":"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"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { CollectionSlug } from 'payload';
|
|
2
|
+
export declare const nestedDocsPageTreePluginBadgeStatuses: readonly ["published", "changed", "draft"];
|
|
3
|
+
export type NestedDocsPageTreePluginBadgeStatus = (typeof nestedDocsPageTreePluginBadgeStatuses)[number];
|
|
4
|
+
export type NestedDocsPageTreePluginBadgeMap = Partial<Record<NestedDocsPageTreePluginBadgeStatus, string>>;
|
|
5
|
+
export type NestedDocsPageTreePluginBadgeConfig = {
|
|
6
|
+
colors?: NestedDocsPageTreePluginBadgeMap;
|
|
7
|
+
labels?: NestedDocsPageTreePluginBadgeMap;
|
|
8
|
+
};
|
|
9
|
+
export type NestedDocsPageTreePluginResolvedBadgeConfig = {
|
|
10
|
+
colors: NestedDocsPageTreePluginBadgeMap;
|
|
11
|
+
labels: NestedDocsPageTreePluginBadgeMap;
|
|
12
|
+
};
|
|
13
|
+
export type NestedDocsPageTreePluginConfig = {
|
|
14
|
+
badges?: NestedDocsPageTreePluginBadgeConfig;
|
|
15
|
+
breadcrumbsFieldSlug?: string;
|
|
16
|
+
collections: CollectionSlug[];
|
|
17
|
+
defaultLimit?: number;
|
|
18
|
+
disabled?: boolean;
|
|
19
|
+
hideBreadcrumbs?: boolean;
|
|
20
|
+
parentFieldSlug?: string;
|
|
21
|
+
};
|
|
22
|
+
export type NestedDocsPageTreePluginCollectionCustom = {
|
|
23
|
+
badges: NestedDocsPageTreePluginResolvedBadgeConfig;
|
|
24
|
+
breadcrumbsFieldSlug: string;
|
|
25
|
+
defaultLimit: number;
|
|
26
|
+
hideBreadcrumbs: boolean;
|
|
27
|
+
parentFieldSlug: string;
|
|
28
|
+
};
|
|
29
|
+
export type PageTreeSourceDoc = Record<string, unknown> & {
|
|
30
|
+
_displayStatus?: null | string;
|
|
31
|
+
_status?: null | string;
|
|
32
|
+
id?: number | string;
|
|
33
|
+
slug?: null | string;
|
|
34
|
+
};
|
|
35
|
+
export declare const nestedDocsPageTreePluginCustomKey = "nestedDocsPageTreePlugin";
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/types.ts"],"sourcesContent":["import type { CollectionSlug } from 'payload'\n\nexport const nestedDocsPageTreePluginBadgeStatuses = ['published', 'changed', 'draft'] as const\n\nexport type NestedDocsPageTreePluginBadgeStatus =\n (typeof nestedDocsPageTreePluginBadgeStatuses)[number]\n\nexport type NestedDocsPageTreePluginBadgeMap = Partial<\n Record<NestedDocsPageTreePluginBadgeStatus, string>\n>\n\nexport type NestedDocsPageTreePluginBadgeConfig = {\n colors?: NestedDocsPageTreePluginBadgeMap\n labels?: NestedDocsPageTreePluginBadgeMap\n}\n\nexport type NestedDocsPageTreePluginResolvedBadgeConfig = {\n colors: NestedDocsPageTreePluginBadgeMap\n labels: NestedDocsPageTreePluginBadgeMap\n}\n\nexport type NestedDocsPageTreePluginConfig = {\n badges?: NestedDocsPageTreePluginBadgeConfig\n breadcrumbsFieldSlug?: string\n collections: CollectionSlug[]\n defaultLimit?: number\n disabled?: boolean\r\n hideBreadcrumbs?: boolean\r\n parentFieldSlug?: string\n}\n\nexport type NestedDocsPageTreePluginCollectionCustom = {\n badges: NestedDocsPageTreePluginResolvedBadgeConfig\n breadcrumbsFieldSlug: string\n defaultLimit: number\n hideBreadcrumbs: boolean\n parentFieldSlug: string\r\n}\r\n\r\nexport type PageTreeSourceDoc = Record<string, unknown> & {\n _displayStatus?: null | string\n _status?: null | string\n id?: number | string\n slug?: null | string\n}\n\nexport const nestedDocsPageTreePluginCustomKey = 'nestedDocsPageTreePlugin'\n"],"names":["nestedDocsPageTreePluginBadgeStatuses","nestedDocsPageTreePluginCustomKey"],"mappings":"AAEA,OAAO,MAAMA,wCAAwC;IAAC;IAAa;IAAW;CAAQ,CAAS;AA4C/F,OAAO,MAAMC,oCAAoC,2BAA0B"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import type { NestedDocsPageTreePluginBadgeConfig, NestedDocsPageTreePluginResolvedBadgeConfig } from '../types.js';
|
|
2
|
+
export declare function normalizeNestedDocsPageTreePluginBadgeConfig(value: NestedDocsPageTreePluginBadgeConfig | unknown): NestedDocsPageTreePluginResolvedBadgeConfig;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { nestedDocsPageTreePluginBadgeStatuses } from '../types.js';
|
|
2
|
+
function normalizeBadgeMap(value) {
|
|
3
|
+
const normalized = {};
|
|
4
|
+
if (!value || typeof value !== 'object' || Array.isArray(value)) {
|
|
5
|
+
return normalized;
|
|
6
|
+
}
|
|
7
|
+
const badgeMap = value;
|
|
8
|
+
for (const status of nestedDocsPageTreePluginBadgeStatuses){
|
|
9
|
+
const statusValue = badgeMap[status];
|
|
10
|
+
if (typeof statusValue === 'string' && statusValue.trim().length > 0) {
|
|
11
|
+
normalized[status] = statusValue.trim();
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
return normalized;
|
|
15
|
+
}
|
|
16
|
+
export function normalizeNestedDocsPageTreePluginBadgeConfig(value) {
|
|
17
|
+
if (!value || typeof value !== 'object' || Array.isArray(value)) {
|
|
18
|
+
return {
|
|
19
|
+
colors: {},
|
|
20
|
+
labels: {}
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
const badgeConfig = value;
|
|
24
|
+
return {
|
|
25
|
+
colors: normalizeBadgeMap(badgeConfig.colors),
|
|
26
|
+
labels: normalizeBadgeMap(badgeConfig.labels)
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
//# sourceMappingURL=badgeConfig.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/utilities/badgeConfig.ts"],"sourcesContent":["import type {\n NestedDocsPageTreePluginBadgeConfig,\n NestedDocsPageTreePluginBadgeMap,\n NestedDocsPageTreePluginResolvedBadgeConfig,\n} from '../types.js'\nimport { nestedDocsPageTreePluginBadgeStatuses } from '../types.js'\n\nfunction normalizeBadgeMap(value: unknown): NestedDocsPageTreePluginBadgeMap {\n const normalized: NestedDocsPageTreePluginBadgeMap = {}\n\n if (!value || typeof value !== 'object' || Array.isArray(value)) {\n return normalized\n }\n\n const badgeMap = value as Record<string, unknown>\n\n for (const status of nestedDocsPageTreePluginBadgeStatuses) {\n const statusValue = badgeMap[status]\n\n if (typeof statusValue === 'string' && statusValue.trim().length > 0) {\n normalized[status] = statusValue.trim()\n }\n }\n\n return normalized\n}\n\nexport function normalizeNestedDocsPageTreePluginBadgeConfig(\n value: NestedDocsPageTreePluginBadgeConfig | unknown,\n): NestedDocsPageTreePluginResolvedBadgeConfig {\n if (!value || typeof value !== 'object' || Array.isArray(value)) {\n return {\n colors: {},\n labels: {},\n }\n }\n\n const badgeConfig = value as NestedDocsPageTreePluginBadgeConfig\n\n return {\n colors: normalizeBadgeMap(badgeConfig.colors),\n labels: normalizeBadgeMap(badgeConfig.labels),\n }\n}\n"],"names":["nestedDocsPageTreePluginBadgeStatuses","normalizeBadgeMap","value","normalized","Array","isArray","badgeMap","status","statusValue","trim","length","normalizeNestedDocsPageTreePluginBadgeConfig","colors","labels","badgeConfig"],"mappings":"AAKA,SAASA,qCAAqC,QAAQ,cAAa;AAEnE,SAASC,kBAAkBC,KAAc;IACvC,MAAMC,aAA+C,CAAC;IAEtD,IAAI,CAACD,SAAS,OAAOA,UAAU,YAAYE,MAAMC,OAAO,CAACH,QAAQ;QAC/D,OAAOC;IACT;IAEA,MAAMG,WAAWJ;IAEjB,KAAK,MAAMK,UAAUP,sCAAuC;QAC1D,MAAMQ,cAAcF,QAAQ,CAACC,OAAO;QAEpC,IAAI,OAAOC,gBAAgB,YAAYA,YAAYC,IAAI,GAAGC,MAAM,GAAG,GAAG;YACpEP,UAAU,CAACI,OAAO,GAAGC,YAAYC,IAAI;QACvC;IACF;IAEA,OAAON;AACT;AAEA,OAAO,SAASQ,6CACdT,KAAoD;IAEpD,IAAI,CAACA,SAAS,OAAOA,UAAU,YAAYE,MAAMC,OAAO,CAACH,QAAQ;QAC/D,OAAO;YACLU,QAAQ,CAAC;YACTC,QAAQ,CAAC;QACX;IACF;IAEA,MAAMC,cAAcZ;IAEpB,OAAO;QACLU,QAAQX,kBAAkBa,YAAYF,MAAM;QAC5CC,QAAQZ,kBAAkBa,YAAYD,MAAM;IAC9C;AACF"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { PageTreeDoc } from './pageTree.js';
|
|
2
|
+
export type PageTreeInsertDropTarget = {
|
|
3
|
+
depth: number;
|
|
4
|
+
dropID: string;
|
|
5
|
+
dropType: 'insert';
|
|
6
|
+
parentID: null | string;
|
|
7
|
+
referenceRowID: string;
|
|
8
|
+
};
|
|
9
|
+
export type PageTreeRowDropTarget = {
|
|
10
|
+
dropType: 'row';
|
|
11
|
+
insertAfterDropID: string;
|
|
12
|
+
insertBeforeDropID: string;
|
|
13
|
+
rowID: string;
|
|
14
|
+
};
|
|
15
|
+
export type PageTreeDropTarget = PageTreeInsertDropTarget | PageTreeRowDropTarget;
|
|
16
|
+
export type PageTreeOrderPlacement = {
|
|
17
|
+
nextSiblingID: null | string;
|
|
18
|
+
parentID: null | string;
|
|
19
|
+
previousSiblingID: null | string;
|
|
20
|
+
};
|
|
21
|
+
export declare function buildInsertDropTargets(docs: PageTreeDoc[]): PageTreeInsertDropTarget[];
|
|
22
|
+
export declare function getDropTargetParentDoc(args: {
|
|
23
|
+
docsByID: ReadonlyMap<string, PageTreeDoc>;
|
|
24
|
+
dropTarget: null | PageTreeDropTarget;
|
|
25
|
+
}): null | PageTreeDoc;
|
|
26
|
+
export declare function getOrderPlacementFromDropTarget(args: {
|
|
27
|
+
activeDoc: PageTreeDoc;
|
|
28
|
+
docs: PageTreeDoc[];
|
|
29
|
+
docsByID: ReadonlyMap<string, PageTreeDoc>;
|
|
30
|
+
dropTarget: null | PageTreeDropTarget;
|
|
31
|
+
}): null | PageTreeOrderPlacement;
|