payload-nested-docs-page-tree 1.2.1 → 1.2.3
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 +104 -46
- package/dist/components/PageTreeListView.client.d.ts +1 -1
- package/dist/components/PageTreeListView.client.js +5 -2
- package/dist/components/PageTreeListView.client.js.map +1 -1
- package/dist/endpoints/createMovePageEndpoint.js +4 -0
- package/dist/endpoints/createMovePageEndpoint.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +29 -2
- package/dist/index.js.map +1 -1
- package/dist/types.d.ts +6 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -1
- package/dist/utilities/pageTree.js +12 -4
- package/dist/utilities/pageTree.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -49,47 +49,47 @@ If needed, refresh the admin import map:
|
|
|
49
49
|
payload generate:importmap
|
|
50
50
|
```
|
|
51
51
|
|
|
52
|
-
## What It Adds
|
|
53
|
-
|
|
54
|
-
- replaces the collection list view with a nested tree table
|
|
55
|
-
- preserves sorting, filters, pagination, bulk selection, and row actions
|
|
56
|
-
- adds `POST /:id/move` for drag-and-drop parent changes
|
|
57
|
-
- marks the root page with slug `home` using a home icon on the title link
|
|
58
|
-
- hides the read-only breadcrumbs field by default
|
|
59
|
-
|
|
60
|
-
## Home Indicator
|
|
61
|
-
|
|
62
|
-
By default, the home icon is enabled only for the `pages` collection.
|
|
63
|
-
|
|
64
|
-
```ts
|
|
65
|
-
nestedDocsPageTreePlugin({
|
|
66
|
-
collections: ['pages'],
|
|
67
|
-
})
|
|
68
|
-
```
|
|
69
|
-
|
|
70
|
-
For custom page collection slugs, pass an exact allow-list:
|
|
71
|
-
|
|
72
|
-
```ts
|
|
73
|
-
nestedDocsPageTreePlugin({
|
|
74
|
-
collections: ['page-tree', 'categories'],
|
|
75
|
-
homeIndicator: {
|
|
76
|
-
collections: ['page-tree'],
|
|
77
|
-
},
|
|
78
|
-
})
|
|
79
|
-
```
|
|
80
|
-
|
|
81
|
-
To disable the home icon everywhere:
|
|
82
|
-
|
|
83
|
-
```ts
|
|
84
|
-
nestedDocsPageTreePlugin({
|
|
85
|
-
collections: ['pages'],
|
|
86
|
-
homeIndicator: false,
|
|
87
|
-
})
|
|
88
|
-
```
|
|
89
|
-
|
|
90
|
-
## Status Badges
|
|
91
|
-
|
|
92
|
-
The tree view supports three document states:
|
|
52
|
+
## What It Adds
|
|
53
|
+
|
|
54
|
+
- replaces the collection list view with a nested tree table
|
|
55
|
+
- preserves sorting, filters, pagination, bulk selection, and row actions
|
|
56
|
+
- adds `POST /:id/move` for drag-and-drop parent changes
|
|
57
|
+
- marks the root page with slug `home` using a home icon on the title link
|
|
58
|
+
- hides the read-only breadcrumbs field by default
|
|
59
|
+
|
|
60
|
+
## Home Indicator
|
|
61
|
+
|
|
62
|
+
By default, the home icon is enabled only for the `pages` collection.
|
|
63
|
+
|
|
64
|
+
```ts
|
|
65
|
+
nestedDocsPageTreePlugin({
|
|
66
|
+
collections: ['pages'],
|
|
67
|
+
})
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
For custom page collection slugs, pass an exact allow-list:
|
|
71
|
+
|
|
72
|
+
```ts
|
|
73
|
+
nestedDocsPageTreePlugin({
|
|
74
|
+
collections: ['page-tree', 'categories'],
|
|
75
|
+
homeIndicator: {
|
|
76
|
+
collections: ['page-tree'],
|
|
77
|
+
},
|
|
78
|
+
})
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
To disable the home icon everywhere:
|
|
82
|
+
|
|
83
|
+
```ts
|
|
84
|
+
nestedDocsPageTreePlugin({
|
|
85
|
+
collections: ['pages'],
|
|
86
|
+
homeIndicator: false,
|
|
87
|
+
})
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## Status Badges
|
|
91
|
+
|
|
92
|
+
The tree view supports three document states:
|
|
93
93
|
|
|
94
94
|
- `published`: live and up to date
|
|
95
95
|
- `changed`: live, but has unpublished changes
|
|
@@ -117,16 +117,74 @@ nestedDocsPageTreePlugin({
|
|
|
117
117
|
|
|
118
118
|
`labels` and `colors` are optional partial overrides. Missing entries fall back to the built-in defaults.
|
|
119
119
|
|
|
120
|
+
## Drag-And-Drop Is Triggering A Deploy?
|
|
121
|
+
|
|
122
|
+
A drag-and-drop move calls `payload.update()` on the draft only. The published version of the live site is never touched. So in most setups, dragging a page does not trigger any rebuild and you can skip this section.
|
|
123
|
+
|
|
124
|
+
### When you can skip this section
|
|
125
|
+
|
|
126
|
+
- The default Payload website template on Vercel (or any host using Next.js ISR), with drafts and autosave on. The template's `afterChange` hook only calls `revalidatePath` and `revalidateTag` from `next/cache`. Those just clear the edge cache. They do not trigger a Vercel build, do not consume build minutes, and do not change what visitors see when the published HTML hasn't changed.
|
|
127
|
+
- Any setup where your `afterChange` hooks only do in-process cache work (`revalidatePath`, `revalidateTag`, in-memory caches, etc.).
|
|
128
|
+
|
|
129
|
+
### When you need the one-line fix
|
|
130
|
+
|
|
131
|
+
You need the fix if **you** wrote an `afterChange` hook that calls something external or expensive on every save. Common cases:
|
|
132
|
+
|
|
133
|
+
- **Cloudflare Pages / Netlify / Vercel Deploy Hooks** (`fetch(DEPLOY_HOOK_URL)`) - these trigger full rebuilds and burn build minutes.
|
|
134
|
+
- **GitHub Actions** `repository_dispatch` triggers.
|
|
135
|
+
- **Manually-invoked SSG rebuilds**.
|
|
136
|
+
- **Publish notifications** (email, Slack) on status transitions.
|
|
137
|
+
- **Heavy search reindex jobs** (Algolia, Meilisearch full-document push).
|
|
138
|
+
|
|
139
|
+
Why a tree move trips these: a typical deploy hook fires when `previousDoc?._status === 'published'` so that it catches unpublish events too. A tree move on a published doc matches that condition (the previous draft state was published) - but the live site hasn't actually changed. Without the fix, every drag fires your deploy.
|
|
140
|
+
|
|
141
|
+
### The fix
|
|
142
|
+
|
|
143
|
+
Add one line at the top of your hook. The plugin sets a flag on Payload's [hook context](https://payloadcms.com/docs/hooks/context) for every move, and your hook reads it to bail out early:
|
|
144
|
+
|
|
145
|
+
```ts
|
|
146
|
+
import { pageTreeMoveContextKey } from 'payload-nested-docs-page-tree'
|
|
147
|
+
|
|
148
|
+
// at the top of your afterChange hook:
|
|
149
|
+
if (req.context?.[pageTreeMoveContextKey]) return
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
This goes in **your** hook - the one that calls the deploy webhook. Not in any of the template's stock files.
|
|
153
|
+
|
|
154
|
+
Full example:
|
|
155
|
+
|
|
156
|
+
```ts
|
|
157
|
+
import type { CollectionAfterChangeHook } from 'payload'
|
|
158
|
+
import { pageTreeMoveContextKey } from 'payload-nested-docs-page-tree'
|
|
159
|
+
|
|
160
|
+
export const triggerDeployOnPublishedChange: CollectionAfterChangeHook = async ({
|
|
161
|
+
doc,
|
|
162
|
+
previousDoc,
|
|
163
|
+
req,
|
|
164
|
+
}) => {
|
|
165
|
+
// -- plugin opt-out --
|
|
166
|
+
if (req.context?.[pageTreeMoveContextKey]) return
|
|
167
|
+
|
|
168
|
+
// -- your deploy logic (example) --
|
|
169
|
+
// Fire on publish, republish, or unpublish - every transition the live site cares about.
|
|
170
|
+
if (doc._status === 'published' || previousDoc?._status === 'published') {
|
|
171
|
+
// POST to your Cloudflare / Netlify / Vercel deploy hook here
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
See `dev/lib/rebuild.ts` for the full reference example.
|
|
177
|
+
|
|
120
178
|
## Configuration
|
|
121
179
|
|
|
122
180
|
- `collections`: target collection slugs
|
|
123
181
|
- `parentFieldSlug`: defaults to `'parent'`
|
|
124
182
|
- `breadcrumbsFieldSlug`: defaults to `'breadcrumbs'`
|
|
125
|
-
- `defaultLimit`: defaults to `100`
|
|
126
|
-
- `hideBreadcrumbs`: defaults to `true`
|
|
127
|
-
- `homeIndicator`: defaults to `{ collections: ['pages'] }`; set to `false` to disable
|
|
128
|
-
- `disabled`: defaults to `false`
|
|
129
|
-
- `badges`: optional label and color overrides for `published`, `changed`, and `draft`
|
|
183
|
+
- `defaultLimit`: defaults to `100`
|
|
184
|
+
- `hideBreadcrumbs`: defaults to `true`
|
|
185
|
+
- `homeIndicator`: defaults to `{ collections: ['pages'] }`; set to `false` to disable
|
|
186
|
+
- `disabled`: defaults to `false`
|
|
187
|
+
- `badges`: optional label and color overrides for `published`, `changed`, and `draft`
|
|
130
188
|
|
|
131
189
|
## Development
|
|
132
190
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Column, ListQuery, ListViewClientProps } from 'payload';
|
|
2
|
-
import type
|
|
2
|
+
import { type NestedDocsPageTreePluginResolvedBadgeConfig, type PageTreeSourceDoc } from '../types.js';
|
|
3
3
|
import { type PageTreeDoc } from '../utilities/pageTree.js';
|
|
4
4
|
type PageTreeListViewClientOwnProps = {
|
|
5
5
|
allDocs: PageTreeDoc[];
|
|
@@ -4,6 +4,7 @@ import { DndContext, DragOverlay, PointerSensor, useDroppable, useSensor, useSen
|
|
|
4
4
|
import { DefaultListView, ListQueryProvider, SelectAll, SelectRow, SortHeader, toast, useConfig, useLocale, useTranslation } from '@payloadcms/ui';
|
|
5
5
|
import { useRouter, useSearchParams } from 'next/navigation';
|
|
6
6
|
import React from 'react';
|
|
7
|
+
import { pageTreeMoveRequestHeader, pageTreeMoveRequestHeaderValue } from '../types.js';
|
|
7
8
|
import { buildInsertDropTargets, getDropTargetParentDoc, getOrderPlacementFromDropTarget } from '../utilities/dropTargets.js';
|
|
8
9
|
import { CANCEL_DRAG_MESSAGE, getDropValidation } from '../utilities/moveValidation.js';
|
|
9
10
|
import { buildDocSlugPath, buildPageTreeDocs, buildProspectiveDocSlugPath, getDocDisplayLabel, getVisibleTreeDocs } from '../utilities/pageTree.js';
|
|
@@ -627,7 +628,8 @@ export default function PageTreeListViewClient({ allDocs, badgeConfig, canMoveDo
|
|
|
627
628
|
credentials: 'include',
|
|
628
629
|
headers: {
|
|
629
630
|
'Accept-Language': i18n.language,
|
|
630
|
-
'Content-Type': 'application/json'
|
|
631
|
+
'Content-Type': 'application/json',
|
|
632
|
+
[pageTreeMoveRequestHeader]: pageTreeMoveRequestHeaderValue
|
|
631
633
|
},
|
|
632
634
|
method: 'POST'
|
|
633
635
|
});
|
|
@@ -668,7 +670,8 @@ export default function PageTreeListViewClient({ allDocs, badgeConfig, canMoveDo
|
|
|
668
670
|
credentials: 'include',
|
|
669
671
|
headers: {
|
|
670
672
|
'Accept-Language': i18n.language,
|
|
671
|
-
'Content-Type': 'application/json'
|
|
673
|
+
'Content-Type': 'application/json',
|
|
674
|
+
[pageTreeMoveRequestHeader]: pageTreeMoveRequestHeaderValue
|
|
672
675
|
},
|
|
673
676
|
method: 'POST'
|
|
674
677
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/components/PageTreeListView.client.tsx"],"sourcesContent":["'use client'\r\n\r\nimport type { Column, ListQuery, ListViewClientProps, PaginatedDocs } from 'payload'\r\n\r\nimport {\r\n DndContext,\r\n type DragEndEvent,\r\n type DragOverEvent,\r\n DragOverlay,\r\n type DragStartEvent,\r\n PointerSensor,\r\n useDroppable,\r\n useSensor,\r\n useSensors,\r\n} from '@dnd-kit/core'\r\nimport {\r\n DefaultListView,\r\n ListQueryProvider,\r\n SelectAll,\r\n SelectRow,\r\n SortHeader,\r\n toast,\r\n useConfig,\r\n useLocale,\r\n useTranslation,\r\n} from '@payloadcms/ui'\r\nimport { useRouter, useSearchParams } from 'next/navigation'\r\nimport React from 'react'\r\n\r\nimport type {\r\n NestedDocsPageTreePluginResolvedBadgeConfig,\r\n PageTreeSourceDoc,\r\n} from '../types.js'\r\n\r\nimport {\r\n buildInsertDropTargets,\r\n getDropTargetParentDoc,\r\n getOrderPlacementFromDropTarget,\r\n type PageTreeDropTarget,\r\n type PageTreeOrderPlacement,\r\n} from '../utilities/dropTargets.js'\r\nimport {\r\n CANCEL_DRAG_MESSAGE,\r\n getDropValidation,\r\n type PageTreeDropValidation,\r\n} from '../utilities/moveValidation.js'\r\nimport {\r\n buildDocSlugPath,\r\n buildPageTreeDocs,\r\n buildProspectiveDocSlugPath,\r\n getDocDisplayLabel,\r\n getVisibleTreeDocs,\r\n type PageTreeDoc,\r\n} from '../utilities/pageTree.js'\r\nimport { pageTreeCollisionDetectionStrategy } from '../utilities/pageTreeCollision.js'\r\nimport {\r\n getPageTreeBadgeColor,\r\n getPageTreeBadgeLabel,\r\n getPageTreeDisplayStatus,\r\n type PageTreeDisplayStatus,\r\n} from '../utilities/status.js'\r\nimport { PageTreeProvider } from './PageTreeContext.js'\r\nimport styles from './PageTreeListView.module.css'\r\nimport { PageTreeTitleCell } from './PageTreeTitleCell.js'\r\n\r\ntype PageTreeListViewClientOwnProps = {\r\n allDocs: PageTreeDoc[]\r\n badgeConfig: NestedDocsPageTreePluginResolvedBadgeConfig\r\n canMoveDocs: boolean\r\n columnState: Column[]\r\n homeIndicatorEnabled: boolean\r\n orderableFieldName?: string\r\n parentFieldSlug: string\r\n query: ListQuery\r\n sourceDocs: PageTreeSourceDoc[]\r\n useAsTitle: string\r\n}\r\n\r\ntype PageTreeListViewClientProps = Omit<ListViewClientProps, 'columnState' | 'Table'> &\r\n PageTreeListViewClientOwnProps\r\n\r\ntype SelectableRowData = React.ComponentProps<typeof SelectRow>['rowData']\r\ntype PageTreeDragData = {\r\n dragType?: 'move'\r\n rowID?: string\r\n}\r\ntype ReorderDirection = 'greater' | 'less'\r\n\r\nconst MANUAL_ORDER_COLUMN_ACCESSOR = '_dragHandle'\r\nconst SILENT_MOVE_MESSAGES = new Set([CANCEL_DRAG_MESSAGE])\r\n\r\nfunction getRowDropID(rowID: string): string {\r\n return `page-drop:${rowID}`\r\n}\r\n\r\nfunction getPageTreeDragData(value: unknown): PageTreeDragData {\r\n return value && typeof value === 'object' ? (value as PageTreeDragData) : {}\r\n}\r\n\r\nfunction getPayloadDocID(doc: PageTreeDoc): number | string | undefined {\r\n return typeof doc.id === 'number' || typeof doc.id === 'string' ? doc.id : undefined\r\n}\r\n\r\nfunction getManualOrderDropValidation(args: {\r\n activeDoc: PageTreeDoc\r\n targetDoc?: PageTreeDoc\r\n}): PageTreeDropValidation {\r\n const { activeDoc, targetDoc } = args\r\n\r\n if (!targetDoc) {\r\n return {\r\n isValid: true,\r\n parentID: null,\r\n }\r\n }\r\n\r\n if (targetDoc.__pageTreeID === activeDoc.__pageTreeID) {\r\n return {\r\n isValid: false,\r\n message: CANCEL_DRAG_MESSAGE,\r\n parentID: targetDoc.__pageTreeID,\r\n }\r\n }\r\n\r\n if (targetDoc.__pageTreeAncestorIDs.includes(activeDoc.__pageTreeID)) {\r\n return {\r\n isValid: false,\r\n message: 'A document cannot be moved under one of its descendants.',\r\n parentID: targetDoc.__pageTreeID,\r\n }\r\n }\r\n\r\n return {\r\n isValid: true,\r\n parentID: targetDoc.__pageTreeID,\r\n }\r\n}\r\n\r\nfunction getDropValidationForMode(args: {\r\n activeDoc: PageTreeDoc\r\n allowSameParent: boolean\r\n targetDoc?: PageTreeDoc\r\n}): PageTreeDropValidation {\r\n const { activeDoc, allowSameParent, targetDoc } = args\r\n\r\n if (allowSameParent) {\r\n return getManualOrderDropValidation({\r\n activeDoc,\r\n targetDoc,\r\n })\r\n }\r\n\r\n return getDropValidation({\r\n activeDoc,\r\n targetDoc,\r\n })\r\n}\r\n\r\nfunction getCurrentOrderPlacement(args: {\r\n activeDoc: PageTreeDoc\r\n docs: PageTreeDoc[]\r\n}): PageTreeOrderPlacement {\r\n const { activeDoc, docs } = args\r\n const activeIndex = docs.findIndex((doc) => doc.__pageTreeID === activeDoc.__pageTreeID)\r\n const movingSubtreeIDs = new Set(\r\n docs\r\n .filter(\r\n (doc) =>\r\n doc.__pageTreeID === activeDoc.__pageTreeID ||\r\n doc.__pageTreeAncestorIDs.includes(activeDoc.__pageTreeID),\r\n )\r\n .map((doc) => doc.__pageTreeID),\r\n )\r\n const siblingIsNotMoving = (doc: PageTreeDoc) =>\r\n doc.__pageTreeParentID === activeDoc.__pageTreeParentID &&\r\n !movingSubtreeIDs.has(doc.__pageTreeID)\r\n\r\n if (activeIndex < 0) {\r\n return {\r\n nextSiblingID: null,\r\n parentID: activeDoc.__pageTreeParentID,\r\n previousSiblingID: null,\r\n }\r\n }\r\n\r\n return {\r\n nextSiblingID: docs.slice(activeIndex + 1).find(siblingIsNotMoving)?.__pageTreeID ?? null,\r\n parentID: activeDoc.__pageTreeParentID,\r\n previousSiblingID:\r\n docs.slice(0, activeIndex).filter(siblingIsNotMoving).at(-1)?.__pageTreeID ?? null,\r\n }\r\n}\r\n\r\nfunction orderPlacementHasChanged(\r\n currentPlacement: PageTreeOrderPlacement,\r\n nextPlacement: PageTreeOrderPlacement,\r\n): boolean {\r\n return (\r\n currentPlacement.parentID !== nextPlacement.parentID ||\r\n currentPlacement.previousSiblingID !== nextPlacement.previousSiblingID ||\r\n currentPlacement.nextSiblingID !== nextPlacement.nextSiblingID\r\n )\r\n}\r\n\r\nfunction getReorderTargetFromPlacement(args: {\r\n currentSort?: string\r\n docsByID: ReadonlyMap<string, PageTreeDoc>\r\n orderableFieldName: string\r\n placement: PageTreeOrderPlacement\r\n}): {\r\n newKeyWillBe: ReorderDirection\r\n targetDoc: PageTreeDoc\r\n} | null {\r\n const { currentSort, docsByID, orderableFieldName, placement } = args\r\n const targetDocID = placement.previousSiblingID ?? placement.nextSiblingID\r\n\r\n if (!targetDocID) {\r\n return null\r\n }\r\n\r\n const targetDoc = docsByID.get(targetDocID)\r\n\r\n if (!targetDoc) {\r\n return null\r\n }\r\n\r\n return {\r\n newKeyWillBe:\r\n (placement.previousSiblingID !== null && currentSort === orderableFieldName) ||\r\n (placement.previousSiblingID === null && currentSort === `-${orderableFieldName}`)\r\n ? 'greater'\r\n : 'less',\r\n targetDoc,\r\n }\r\n}\r\n\r\nfunction buildPaginatedData(\r\n docs: PageTreeDoc[],\r\n limit: number,\r\n requestedPage: number,\r\n): PaginatedDocs {\r\n const totalDocs = docs.length\r\n const totalPages = totalDocs > 0 ? Math.max(1, Math.ceil(totalDocs / limit)) : 1\r\n const page = Math.min(Math.max(requestedPage, 1), totalPages)\r\n const startIndex = (page - 1) * limit\r\n const pageDocs = docs.slice(startIndex, startIndex + limit)\r\n\r\n return {\r\n docs: pageDocs,\r\n hasNextPage: page < totalPages,\r\n hasPrevPage: page > 1,\r\n limit,\r\n nextPage: page < totalPages ? page + 1 : null,\r\n page,\r\n pagingCounter: totalDocs === 0 ? 0 : startIndex + 1,\r\n prevPage: page > 1 ? page - 1 : null,\r\n totalDocs,\r\n totalPages,\r\n }\r\n}\r\n\r\nfunction normalizeSort(value: string | string[] | undefined): string | undefined {\r\n if (Array.isArray(value)) {\r\n const sortValues = value.filter((entry) => typeof entry === 'string' && entry.length > 0)\r\n return sortValues.length > 0 ? sortValues.join(',') : undefined\r\n }\r\n\r\n return typeof value === 'string' && value.length > 0 ? value : undefined\r\n}\r\n\r\nfunction normalizePositiveInt(value: null | string, fallback: number): number {\r\n if (typeof value !== 'string') {\r\n return fallback\r\n }\r\n\r\n const parsedValue = Number.parseInt(value, 10)\r\n return Number.isNaN(parsedValue) || parsedValue <= 0 ? fallback : parsedValue\r\n}\r\n\r\nfunction normalizePageTreeColumnState(columnState: Column[], useAsTitle: string): Column[] {\r\n return columnState\r\n .filter((column) => column.accessor !== MANUAL_ORDER_COLUMN_ACCESSOR)\r\n .map((column) =>\r\n column.accessor === useAsTitle\r\n ? {\r\n ...column,\r\n active: true,\r\n }\r\n : column,\r\n )\r\n}\r\n\r\nfunction sliceColumnState(\r\n columnState: Column[],\r\n docs: PageTreeDoc[],\r\n renderedCellIndexByDocID: ReadonlyMap<string, number>,\r\n): Column[] {\r\n return columnState.map((column) => ({\r\n ...column,\r\n renderedCells: docs.map((doc) => {\r\n const renderedCellIndex =\r\n renderedCellIndexByDocID.get(doc.__pageTreeID) ?? doc.__pageTreeOrderIndex\r\n\r\n return column.renderedCells?.[renderedCellIndex] ?? null\r\n }),\r\n }))\r\n}\r\n\r\nfunction getSelectableRowData(doc: PageTreeDoc): SelectableRowData {\r\n const record = doc as Record<string, unknown>\r\n\r\n return {\r\n id: String(doc.id ?? doc.__pageTreeID),\r\n _isLocked: Boolean(record._isLocked),\r\n _userEditing: record._userEditing as SelectableRowData['_userEditing'],\r\n }\r\n}\r\n\r\nfunction shouldSilenceMoveMessage(message?: string): boolean {\r\n return typeof message === 'string' && SILENT_MOVE_MESSAGES.has(message)\r\n}\r\n\r\nfunction getStatusClassName(\r\n status: PageTreeDisplayStatus,\r\n): 'changed' | 'draft' | 'published' | 'unknown' {\r\n if (status === 'changed' || status === 'draft' || status === 'published') {\r\n return status\r\n }\r\n\r\n return 'unknown'\r\n}\r\n\r\nfunction renderStatusBadge(args: {\r\n badgeConfig: NestedDocsPageTreePluginResolvedBadgeConfig\r\n doc: PageTreeDoc\r\n index: number\r\n t: (key: 'general:noValue' | 'version:changed' | 'version:draft' | 'version:published') => string\r\n}): React.ReactNode {\r\n const { badgeConfig, doc, index, t } = args\r\n const status = getPageTreeDisplayStatus(doc)\r\n const customColor = getPageTreeBadgeColor({\r\n badgeColors: badgeConfig.colors,\r\n status,\r\n })\r\n const statusClass = getStatusClassName(status)\r\n const style = customColor\r\n ? ({ '--page-tree-badge-base': customColor } as React.CSSProperties)\r\n : undefined\r\n\r\n return (\r\n <span\r\n className={[\r\n 'pages-hierarchy-status-badge',\r\n `pages-hierarchy-status-badge--${statusClass}`,\r\n ].join(' ')}\r\n data-custom-color={customColor ? 'true' : undefined}\r\n key={doc.__pageTreeID ?? index}\r\n style={style}\r\n >\r\n {getPageTreeBadgeLabel({\r\n badgeLabels: badgeConfig.labels,\r\n status,\r\n t,\r\n })}\r\n </span>\r\n )\r\n}\r\n\r\nfunction createManualOrderColumn(docs: PageTreeDoc[]): Column {\r\n return {\r\n accessor: MANUAL_ORDER_COLUMN_ACCESSOR,\r\n active: true,\r\n field: { hidden: true } as Column['field'],\r\n Heading: <SortHeader />,\r\n renderedCells: docs.map(() => null),\r\n }\r\n}\r\n\r\nfunction insertManualOrderColumn(columns: Column[], orderColumn: Column): Column[] {\r\n const selectColumnIndex = columns.findIndex((column) => column.accessor === '_select')\r\n const insertIndex = selectColumnIndex >= 0 ? selectColumnIndex + 1 : 0\r\n\r\n return [\r\n ...columns.slice(0, insertIndex),\r\n orderColumn,\r\n ...columns.slice(insertIndex),\r\n ]\r\n}\r\n\r\nfunction buildTableColumns(args: {\r\n badgeConfig: NestedDocsPageTreePluginResolvedBadgeConfig\r\n columnState: Column[]\r\n docs: PageTreeDoc[]\r\n enableRowSelections?: boolean\r\n homeIndicatorEnabled: boolean\r\n orderableFieldName?: string\r\n parentFieldSlug: string\r\n t: (key: 'general:noValue' | 'version:changed' | 'version:draft' | 'version:published') => string\r\n useAsTitle: string\r\n}): Column[] {\r\n const {\r\n badgeConfig,\r\n columnState,\r\n docs,\r\n enableRowSelections,\r\n homeIndicatorEnabled,\r\n orderableFieldName,\r\n parentFieldSlug,\r\n t,\r\n useAsTitle,\r\n } = args\r\n const columnsToUse = columnState.map((column) => {\r\n if (column.accessor === useAsTitle) {\r\n return {\r\n ...column,\r\n active: true,\r\n renderedCells: docs.map((doc, index) => (\r\n <PageTreeTitleCell\r\n doc={doc}\r\n homeIndicatorEnabled={homeIndicatorEnabled}\r\n key={doc.__pageTreeID ?? index}\r\n >\r\n {column.renderedCells?.[index] ?? getDocDisplayLabel(doc)}\r\n </PageTreeTitleCell>\r\n )),\r\n }\r\n }\r\n\r\n if (column.accessor === '_status') {\r\n return {\r\n ...column,\r\n renderedCells: docs.map((doc, index) =>\r\n renderStatusBadge({\r\n badgeConfig,\r\n doc,\r\n index,\r\n t,\r\n }),\r\n ),\r\n }\r\n }\r\n\r\n if (column.accessor === parentFieldSlug) {\r\n return {\r\n ...column,\r\n renderedCells: docs.map((doc, index) =>\r\n doc.__pageTreeParentID !== null ? (\r\n column.renderedCells?.[index] ?? null\r\n ) : (\r\n <span className=\"pages-hierarchy-empty-cell\" key={doc.__pageTreeID ?? index}>\r\n -\r\n </span>\r\n ),\r\n ),\r\n }\r\n }\r\n\r\n return column\r\n })\r\n\r\n if (enableRowSelections) {\r\n columnsToUse.unshift({\r\n accessor: '_select',\r\n active: true,\r\n field: { hidden: true } as Column['field'],\r\n Heading: <SelectAll />,\r\n renderedCells: docs.map((doc, index) => (\r\n <SelectRow key={doc.__pageTreeID ?? index} rowData={getSelectableRowData(doc)} />\r\n )),\r\n })\r\n }\r\n\r\n if (\r\n orderableFieldName &&\r\n !columnsToUse.some((column) => column.accessor === MANUAL_ORDER_COLUMN_ACCESSOR)\r\n ) {\r\n return insertManualOrderColumn(columnsToUse, createManualOrderColumn(docs))\r\n }\r\n\r\n return columnsToUse\r\n}\r\n\r\nfunction HierarchyInsertRow({\r\n activeColumnsCount,\r\n activeDragRowID,\r\n dropTarget,\r\n dropValidation,\r\n isMovePending,\r\n}: {\r\n activeColumnsCount: number\r\n activeDragRowID: null | string\r\n dropTarget: Extract<PageTreeDropTarget, { dropType: 'insert' }>\r\n dropValidation?: PageTreeDropValidation\r\n isMovePending: boolean\r\n}) {\r\n const { isOver, setNodeRef } = useDroppable({\r\n id: dropTarget.dropID,\r\n data: dropTarget,\r\n disabled: isMovePending,\r\n })\r\n const hasActiveDrag = Boolean(activeDragRowID)\r\n\r\n return (\r\n <tr\r\n className=\"pages-hierarchy-insert-row\"\r\n data-drag-over={isOver ? 'true' : 'false'}\r\n data-drop-valid={hasActiveDrag ? (dropValidation?.isValid ? 'true' : 'false') : undefined}\r\n data-page-tree-insert=\"true\"\r\n >\r\n <td colSpan={activeColumnsCount}>\r\n <div\r\n className=\"pages-hierarchy-insert-row__target\"\r\n data-insert-depth={dropTarget.depth}\r\n ref={setNodeRef}\r\n />\r\n </td>\r\n </tr>\r\n )\r\n}\r\n\r\nfunction HierarchyTableRow({\r\n activeColumns,\r\n activeDragRowID,\r\n doc,\r\n dropValidation,\r\n insertAfterDropID,\r\n insertBeforeDropID,\r\n isMovePending,\r\n rowIndex,\r\n titleCellAccessor,\r\n}: {\r\n activeColumns: Column[]\r\n activeDragRowID: null | string\r\n doc: PageTreeDoc\r\n dropValidation?: PageTreeDropValidation\r\n insertAfterDropID: string\r\n insertBeforeDropID: string\r\n isMovePending: boolean\r\n rowIndex: number\r\n titleCellAccessor: string\r\n}) {\r\n const { isOver, setNodeRef } = useDroppable({\r\n id: getRowDropID(doc.__pageTreeID),\r\n data: {\r\n dropType: 'row',\r\n insertAfterDropID,\r\n insertBeforeDropID,\r\n rowID: doc.__pageTreeID,\r\n } satisfies Extract<PageTreeDropTarget, { dropType: 'row' }>,\r\n disabled: isMovePending,\r\n })\r\n const hasActiveDrag = Boolean(activeDragRowID)\r\n const isActiveDragRow = activeDragRowID === doc.__pageTreeID\r\n\r\n return (\r\n <tr\r\n className={`row-${rowIndex + 1}`}\r\n data-drag-over={isOver ? 'true' : 'false'}\r\n data-drop-valid={hasActiveDrag ? (dropValidation?.isValid ? 'true' : 'false') : undefined}\r\n data-id={doc.id}\r\n data-is-drag-source={isActiveDragRow ? 'true' : 'false'}\r\n data-page-tree-row=\"true\"\r\n ref={setNodeRef}\r\n >\r\n {activeColumns.map((column, columnIndex) => {\r\n const { accessor } = column\r\n\r\n return (\r\n <td\r\n className={`cell-${accessor.replace(/\\./g, '__')}`}\r\n data-page-tree-manual-order-cell={\r\n accessor === MANUAL_ORDER_COLUMN_ACCESSOR ? 'true' : undefined\r\n }\r\n data-page-tree-title-cell={accessor === titleCellAccessor ? 'true' : undefined}\r\n key={columnIndex}\r\n >\r\n {column.renderedCells?.[rowIndex] ?? null}\r\n </td>\r\n )\r\n })}\r\n </tr>\r\n )\r\n}\r\n\r\nfunction HierarchyTable({\r\n activeDragRowID,\r\n allDocsByID,\r\n allowSameParentDrops,\r\n columns,\r\n data,\r\n isMovePending,\r\n titleCellAccessor,\r\n}: {\r\n activeDragRowID: null | string\r\n allDocsByID: ReadonlyMap<string, PageTreeDoc>\r\n allowSameParentDrops: boolean\r\n columns: Column[]\r\n data: PageTreeDoc[]\r\n isMovePending: boolean\r\n titleCellAccessor: string\r\n}) {\r\n const activeColumns = React.useMemo(\r\n () => columns.filter((column) => column?.active),\r\n [columns],\r\n )\r\n const hasManualOrderColumn = React.useMemo(\r\n () => activeColumns.some((column) => column.accessor === MANUAL_ORDER_COLUMN_ACCESSOR),\r\n [activeColumns],\r\n )\r\n const insertDropTargets = React.useMemo(() => buildInsertDropTargets(data), [data])\r\n const activeDoc = activeDragRowID ? allDocsByID.get(activeDragRowID) ?? null : null\r\n const rowDropValidationByID = React.useMemo(() => {\r\n if (!activeDoc) {\r\n return new Map<string, PageTreeDropValidation>()\r\n }\r\n\r\n return new Map(\r\n data.map((doc) => [\r\n doc.__pageTreeID,\r\n getDropValidationForMode({\r\n activeDoc,\r\n allowSameParent: allowSameParentDrops,\r\n targetDoc: doc,\r\n }),\r\n ]),\r\n )\r\n }, [activeDoc, allowSameParentDrops, data])\r\n const insertDropValidationByID = React.useMemo(() => {\r\n if (!activeDoc) {\r\n return new Map<string, PageTreeDropValidation>()\r\n }\r\n\r\n return new Map(\r\n insertDropTargets.map((dropTarget) => [\r\n dropTarget.dropID,\r\n getDropValidationForMode({\r\n activeDoc,\r\n allowSameParent: allowSameParentDrops,\r\n targetDoc:\r\n dropTarget.parentID === null\r\n ? undefined\r\n : allDocsByID.get(dropTarget.parentID) ?? undefined,\r\n }),\r\n ]),\r\n )\r\n }, [activeDoc, allowSameParentDrops, allDocsByID, insertDropTargets])\r\n\r\n if (activeColumns.length === 0) {\r\n return <div>No columns selected</div>\r\n }\r\n\r\n return (\r\n <div\r\n className={[\r\n 'table-wrap pages-hierarchy-table',\r\n activeDoc ? 'pages-hierarchy-table--dragging' : '',\r\n ]\r\n .filter(Boolean)\r\n .join(' ')}\r\n data-page-tree-orderable={hasManualOrderColumn ? 'true' : undefined}\r\n >\r\n <div className=\"table table--appearance-default\">\r\n <table cellPadding=\"0\" cellSpacing=\"0\">\r\n <thead>\r\n <tr>\r\n {activeColumns.map((column, index) => (\r\n <th\r\n data-page-tree-manual-order-cell={\r\n column.accessor === MANUAL_ORDER_COLUMN_ACCESSOR ? 'true' : undefined\r\n }\r\n data-page-tree-title-cell={\r\n column.accessor === titleCellAccessor ? 'true' : undefined\r\n }\r\n id={`heading-${column.accessor.replace(/\\./g, '__')}`}\r\n key={index}\r\n >\r\n {column.Heading}\r\n </th>\r\n ))}\r\n </tr>\r\n </thead>\r\n <tbody>\r\n {insertDropTargets[0] ? (\r\n <HierarchyInsertRow\r\n activeColumnsCount={activeColumns.length}\r\n activeDragRowID={activeDragRowID}\r\n dropTarget={insertDropTargets[0]}\r\n dropValidation={insertDropValidationByID.get(insertDropTargets[0].dropID)}\r\n isMovePending={isMovePending}\r\n key={insertDropTargets[0].dropID}\r\n />\r\n ) : null}\r\n {data.map((doc, rowIndex) => (\r\n <React.Fragment key={doc.__pageTreeID}>\r\n <HierarchyTableRow\r\n activeColumns={activeColumns}\r\n activeDragRowID={activeDragRowID}\r\n doc={doc}\r\n dropValidation={rowDropValidationByID.get(doc.__pageTreeID)}\r\n insertAfterDropID={insertDropTargets[rowIndex + 1].dropID}\r\n insertBeforeDropID={insertDropTargets[rowIndex].dropID}\r\n isMovePending={isMovePending}\r\n rowIndex={rowIndex}\r\n titleCellAccessor={titleCellAccessor}\r\n />\r\n {insertDropTargets[rowIndex + 1] ? (\r\n <HierarchyInsertRow\r\n activeColumnsCount={activeColumns.length}\r\n activeDragRowID={activeDragRowID}\r\n dropTarget={insertDropTargets[rowIndex + 1]}\r\n dropValidation={insertDropValidationByID.get(\r\n insertDropTargets[rowIndex + 1].dropID,\r\n )}\r\n isMovePending={isMovePending}\r\n key={insertDropTargets[rowIndex + 1].dropID}\r\n />\r\n ) : null}\r\n </React.Fragment>\r\n ))}\r\n </tbody>\r\n </table>\r\n </div>\r\n </div>\r\n )\r\n}\r\n\r\nexport default function PageTreeListViewClient({\r\n allDocs,\r\n badgeConfig,\r\n canMoveDocs,\r\n columnState,\r\n homeIndicatorEnabled,\r\n orderableFieldName,\r\n parentFieldSlug,\r\n query,\r\n sourceDocs,\r\n useAsTitle,\r\n ...props\r\n}: PageTreeListViewClientProps) {\r\n const router = useRouter()\r\n const searchParams = useSearchParams()\r\n const { config } = useConfig()\r\n const locale = useLocale()\r\n const { i18n } = useTranslation()\r\n const [activeDragRowID, setActiveDragRowID] = React.useState<null | string>(null)\r\n const [activeDropTarget, setActiveDropTarget] = React.useState<null | PageTreeDropTarget>(null)\r\n const [collapsedIDs, setCollapsedIDs] = React.useState<Set<string>>(() => new Set())\r\n const [localSourceDocs, setLocalSourceDocs] = React.useState(sourceDocs)\r\n const [pendingMoveRowID, setPendingMoveRowID] = React.useState<null | string>(null)\r\n\r\n React.useEffect(() => {\r\n setLocalSourceDocs(sourceDocs)\r\n }, [sourceDocs])\r\n\r\n const toggleRow = React.useCallback((rowID: string) => {\r\n setCollapsedIDs((currentState) => {\r\n const nextState = new Set(currentState)\r\n\r\n if (nextState.has(rowID)) {\r\n nextState.delete(rowID)\r\n } else {\r\n nextState.add(rowID)\r\n }\r\n\r\n return nextState\r\n })\r\n }, [])\r\n const currentSort = React.useMemo(() => {\r\n const searchParamSort = searchParams.getAll('sort')\r\n\r\n if (searchParamSort.length > 0) {\r\n return normalizeSort(searchParamSort)\r\n }\r\n\r\n return normalizeSort(query.sort as string | string[] | undefined)\r\n }, [query.sort, searchParams])\r\n const manualOrderIsActive = Boolean(\r\n orderableFieldName &&\r\n (currentSort === orderableFieldName || currentSort === `-${orderableFieldName}`),\r\n )\r\n const currentLimit = React.useMemo(\r\n () =>\r\n normalizePositiveInt(\r\n searchParams.get('limit'),\r\n typeof query.limit === 'number' && query.limit > 0 ? query.limit : 10,\r\n ),\r\n [query.limit, searchParams],\r\n )\r\n const currentRequestedPage = React.useMemo(\r\n () =>\r\n normalizePositiveInt(\r\n searchParams.get('page'),\r\n typeof query.page === 'number' && query.page > 0 ? query.page : 1,\r\n ),\r\n [query.page, searchParams],\r\n )\r\n const liveAllDocs = React.useMemo(\r\n () =>\r\n buildPageTreeDocs(localSourceDocs, {\r\n parentFieldSlug,\r\n sort: currentSort,\r\n }),\r\n [currentSort, localSourceDocs, parentFieldSlug],\r\n )\r\n const collapseResetKey = React.useMemo(\r\n () => JSON.stringify([props.collectionSlug, props.viewType, searchParams.toString()]),\r\n [props.collectionSlug, props.viewType, searchParams],\r\n )\r\n const hierarchyValue = React.useMemo(\r\n () => ({\r\n activeDragRowID,\r\n canMoveDocs,\r\n collapsedIDs,\r\n pendingMoveRowID,\r\n toggleRow,\r\n }),\r\n [activeDragRowID, canMoveDocs, collapsedIDs, pendingMoveRowID, toggleRow],\r\n )\r\n\r\n React.useEffect(() => {\r\n setActiveDragRowID(null)\r\n setActiveDropTarget(null)\r\n setCollapsedIDs(new Set())\r\n }, [collapseResetKey])\r\n\r\n const visibleDocs = React.useMemo(\r\n () => getVisibleTreeDocs(liveAllDocs, collapsedIDs),\r\n [liveAllDocs, collapsedIDs],\r\n )\r\n const paginatedData = React.useMemo(\r\n () => buildPaginatedData(visibleDocs, currentLimit, currentRequestedPage),\r\n [currentLimit, currentRequestedPage, visibleDocs],\r\n )\r\n const paginatedDocs = paginatedData.docs as PageTreeDoc[]\r\n const allDocsByID = React.useMemo(\r\n () => new Map(liveAllDocs.map((doc) => [doc.__pageTreeID, doc])),\r\n [liveAllDocs],\r\n )\r\n const paginatedDocsByID = React.useMemo(\r\n () => new Map(paginatedDocs.map((doc) => [doc.__pageTreeID, doc])),\r\n [paginatedDocs],\r\n )\r\n const renderedCellIndexByDocID = React.useMemo(\r\n () => new Map(allDocs.map((doc, index) => [doc.__pageTreeID, index])),\r\n [allDocs],\r\n )\r\n const normalizedColumnState = React.useMemo(\r\n () => normalizePageTreeColumnState(columnState, useAsTitle),\r\n [columnState, useAsTitle],\r\n )\r\n const paginatedColumnState = React.useMemo(\r\n () => sliceColumnState(normalizedColumnState, paginatedDocs, renderedCellIndexByDocID),\r\n [normalizedColumnState, paginatedDocs, renderedCellIndexByDocID],\r\n )\r\n const tableColumns = React.useMemo(\r\n () =>\r\n buildTableColumns({\r\n badgeConfig,\r\n columnState: paginatedColumnState,\r\n docs: paginatedDocs,\r\n enableRowSelections: props.enableRowSelections,\r\n homeIndicatorEnabled,\r\n orderableFieldName,\r\n parentFieldSlug,\r\n t: i18n.t,\r\n useAsTitle,\r\n }),\r\n [\r\n paginatedColumnState,\r\n paginatedDocs,\r\n badgeConfig,\r\n homeIndicatorEnabled,\r\n orderableFieldName,\r\n parentFieldSlug,\r\n props.enableRowSelections,\r\n i18n.t,\r\n useAsTitle,\r\n ],\r\n )\r\n const activeDragDoc = activeDragRowID ? paginatedDocsByID.get(activeDragRowID) ?? null : null\r\n const activeDragPreviewPath = React.useMemo(() => {\r\n if (!activeDragDoc) {\r\n return null\r\n }\r\n\r\n if (!activeDropTarget) {\r\n return buildDocSlugPath({\r\n doc: activeDragDoc,\r\n docsByID: allDocsByID,\r\n })\r\n }\r\n\r\n const targetDoc = getDropTargetParentDoc({\r\n docsByID: allDocsByID,\r\n dropTarget: activeDropTarget,\r\n })\r\n const dropValidation = getDropValidationForMode({\r\n activeDoc: activeDragDoc,\r\n allowSameParent: manualOrderIsActive,\r\n targetDoc: targetDoc ?? undefined,\r\n })\r\n\r\n if (!dropValidation.isValid) {\r\n return buildDocSlugPath({\r\n doc: activeDragDoc,\r\n docsByID: allDocsByID,\r\n })\r\n }\r\n\r\n return buildProspectiveDocSlugPath({\r\n activeDoc: activeDragDoc,\r\n docsByID: allDocsByID,\r\n targetDoc: targetDoc ?? undefined,\r\n })\r\n }, [activeDragDoc, activeDropTarget, allDocsByID, manualOrderIsActive])\r\n const isMovePending = pendingMoveRowID !== null\r\n const sensors = useSensors(\r\n useSensor(PointerSensor, {\r\n activationConstraint: {\r\n distance: 4,\r\n },\r\n }),\r\n )\r\n const moveDocument = React.useCallback(\r\n async (args: { parentID: null | string; rowID: string }) => {\r\n const { parentID, rowID } = args\r\n const params = new URLSearchParams()\r\n\r\n if (locale?.code) {\r\n params.set('locale', locale.code)\r\n }\r\n\r\n const response = await fetch(\r\n `${config.routes.api}/${props.collectionSlug}/${encodeURIComponent(rowID)}/move${\r\n params.size > 0 ? `?${params.toString()}` : ''\r\n }`,\r\n {\r\n body: JSON.stringify({\r\n parentID,\r\n }),\r\n credentials: 'include',\r\n headers: {\r\n 'Accept-Language': i18n.language,\r\n 'Content-Type': 'application/json',\r\n },\r\n method: 'POST',\r\n },\r\n )\r\n const result = (await response.json().catch(() => null)) as\r\n | {\r\n message?: string\r\n }\r\n | null\r\n\r\n if (!response.ok) {\r\n throw new Error(result?.message ?? 'Could not move document.')\r\n }\r\n\r\n return result\r\n },\r\n [config.routes.api, i18n.language, locale?.code, props.collectionSlug],\r\n )\r\n const reorderDocument = React.useCallback(\r\n async (args: {\r\n movedDocID: number | string\r\n newKeyWillBe: ReorderDirection\r\n targetDoc: PageTreeDoc\r\n }) => {\r\n const { movedDocID, newKeyWillBe, targetDoc } = args\r\n const targetID = getPayloadDocID(targetDoc)\r\n\r\n if (!orderableFieldName || targetID === undefined) {\r\n return undefined\r\n }\r\n\r\n const params = new URLSearchParams()\r\n\r\n if (locale?.code) {\r\n params.set('locale', locale.code)\r\n }\r\n\r\n const response = await fetch(\r\n `${config.routes.api}/reorder${params.size > 0 ? `?${params.toString()}` : ''}`,\r\n {\r\n body: JSON.stringify({\r\n collectionSlug: props.collectionSlug,\r\n docsToMove: [movedDocID],\r\n newKeyWillBe,\r\n orderableFieldName,\r\n target: {\r\n id: targetID,\r\n key: targetDoc[orderableFieldName],\r\n },\r\n }),\r\n credentials: 'include',\r\n headers: {\r\n 'Accept-Language': i18n.language,\r\n 'Content-Type': 'application/json',\r\n },\r\n method: 'POST',\r\n },\r\n )\r\n const result = (await response.json().catch(() => null)) as\r\n | {\r\n message?: string\r\n orderValues?: unknown[]\r\n }\r\n | null\r\n\r\n if (response.status === 403) {\r\n throw new Error('You do not have permission to reorder these rows')\r\n }\r\n\r\n if (!response.ok) {\r\n throw new Error(\r\n 'Failed to reorder. This can happen if you reorder several rows too quickly. Please try again.',\r\n )\r\n }\r\n\r\n if (result?.message === 'initial migration') {\r\n throw new Error(\r\n 'You have enabled \"orderable\" on a collection with existing documents and this is the first time you have sorted documents. We have run an automatic migration to add an initial order to the documents. Please refresh the page and try again.',\r\n )\r\n }\r\n\r\n return result?.orderValues?.[0]\r\n },\r\n [\r\n config.routes.api,\r\n i18n.language,\r\n locale?.code,\r\n orderableFieldName,\r\n props.collectionSlug,\r\n ],\r\n )\r\n const handleManualOrderMoveEnd = React.useCallback(\r\n async (args: {\r\n activeDoc: PageTreeDoc\r\n dropTarget: PageTreeDropTarget\r\n rowID: string\r\n }) => {\r\n const { activeDoc, dropTarget, rowID } = args\r\n\r\n if (!orderableFieldName) {\r\n return\r\n }\r\n\r\n const targetDoc = getDropTargetParentDoc({\r\n docsByID: allDocsByID,\r\n dropTarget,\r\n })\r\n const dropValidation = getManualOrderDropValidation({\r\n activeDoc,\r\n targetDoc: targetDoc ?? undefined,\r\n })\r\n\r\n if (!dropValidation.isValid) {\r\n if (!shouldSilenceMoveMessage(dropValidation.message)) {\r\n toast.error(dropValidation.message ?? 'Could not move document.')\r\n }\r\n\r\n return\r\n }\r\n\r\n const placement = getOrderPlacementFromDropTarget({\r\n activeDoc,\r\n docs: paginatedDocs,\r\n docsByID: allDocsByID,\r\n dropTarget,\r\n })\r\n\r\n if (!placement) {\r\n return\r\n }\r\n\r\n const currentPlacement = getCurrentOrderPlacement({\r\n activeDoc,\r\n docs: paginatedDocs,\r\n })\r\n const parentChanged = activeDoc.__pageTreeParentID !== placement.parentID\r\n const orderChanged = orderPlacementHasChanged(currentPlacement, placement)\r\n const reorderTarget = orderChanged\r\n ? getReorderTargetFromPlacement({\r\n currentSort,\r\n docsByID: allDocsByID,\r\n orderableFieldName,\r\n placement,\r\n })\r\n : null\r\n\r\n if (!parentChanged && !reorderTarget) {\r\n return\r\n }\r\n\r\n const movedDocID = getPayloadDocID(activeDoc)\r\n\r\n if (movedDocID === undefined) {\r\n return\r\n }\r\n\r\n const parentDoc = placement.parentID ? allDocsByID.get(placement.parentID) : undefined\r\n const nextParentValue =\r\n placement.parentID === null\r\n ? null\r\n : parentDoc\r\n ? getPayloadDocID(parentDoc) ?? placement.parentID\r\n : placement.parentID\r\n let parentMoveSucceeded = false\r\n\r\n setPendingMoveRowID(rowID)\r\n\r\n try {\r\n if (parentChanged) {\r\n await moveDocument({\r\n parentID: placement.parentID,\r\n rowID,\r\n })\r\n parentMoveSucceeded = true\r\n }\r\n\r\n const nextOrderValue = reorderTarget\r\n ? await reorderDocument({\r\n movedDocID,\r\n newKeyWillBe: reorderTarget.newKeyWillBe,\r\n targetDoc: reorderTarget.targetDoc,\r\n })\r\n : undefined\r\n\r\n if (parentChanged || typeof nextOrderValue === 'string') {\r\n setLocalSourceDocs((currentDocs) =>\r\n currentDocs.map((doc) =>\r\n String(doc.id ?? '') === String(movedDocID)\r\n ? {\r\n ...doc,\r\n ...(parentChanged\r\n ? {\r\n [parentFieldSlug]: nextParentValue,\r\n }\r\n : {}),\r\n ...(typeof nextOrderValue === 'string'\r\n ? {\r\n [orderableFieldName]: nextOrderValue,\r\n }\r\n : {}),\r\n }\r\n : doc,\r\n ),\r\n )\r\n }\r\n\r\n if (parentChanged) {\r\n toast.success(`Moved \"${getDocDisplayLabel(activeDoc)}\".`)\r\n }\r\n\r\n React.startTransition(() => {\r\n router.refresh()\r\n })\r\n } catch (error) {\r\n const message =\r\n error instanceof Error && error.message ? error.message : 'Could not move document.'\r\n\r\n toast.error(\r\n parentMoveSucceeded\r\n ? `Moved \"${getDocDisplayLabel(activeDoc)}\", but could not update its manual order. ${message}`\r\n : message,\r\n )\r\n\r\n if (parentMoveSucceeded) {\r\n React.startTransition(() => {\r\n router.refresh()\r\n })\r\n }\r\n } finally {\r\n setPendingMoveRowID(null)\r\n }\r\n },\r\n [\r\n allDocsByID,\r\n currentSort,\r\n moveDocument,\r\n orderableFieldName,\r\n paginatedDocs,\r\n parentFieldSlug,\r\n reorderDocument,\r\n router,\r\n ],\r\n )\r\n const handleDragCancel = React.useCallback(() => {\r\n setActiveDragRowID(null)\r\n setActiveDropTarget(null)\r\n }, [])\r\n const handleDragStart = React.useCallback(\r\n (event: DragStartEvent) => {\r\n const dragData = getPageTreeDragData(event.active.data.current)\r\n\r\n if (!canMoveDocs || isMovePending) {\r\n return\r\n }\r\n\r\n const rowID = dragData.rowID\r\n\r\n if (typeof rowID === 'string' && paginatedDocsByID.has(rowID)) {\r\n setActiveDragRowID(rowID)\r\n setActiveDropTarget(null)\r\n }\r\n },\r\n [canMoveDocs, isMovePending, paginatedDocsByID],\r\n )\r\n const handleDragOver = React.useCallback((event: DragOverEvent) => {\r\n const overData = event.over?.data.current as PageTreeDropTarget | undefined\r\n\r\n if (!overData) {\r\n setActiveDropTarget(null)\r\n return\r\n }\r\n\r\n if (overData.dropType === 'insert') {\r\n setActiveDropTarget(overData)\r\n return\r\n }\r\n\r\n if (overData.dropType === 'row') {\r\n setActiveDropTarget(overData)\r\n return\r\n }\r\n\r\n setActiveDropTarget(null)\r\n }, [])\r\n const handleDragEnd = React.useCallback(\r\n async (event: DragEndEvent) => {\r\n const dragData = getPageTreeDragData(event.active.data.current)\r\n\r\n const rowID = dragData.rowID\r\n const activeDoc = typeof rowID === 'string' ? paginatedDocsByID.get(rowID) ?? null : null\r\n const overData = event.over?.data.current as PageTreeDropTarget | undefined\r\n\r\n setActiveDragRowID(null)\r\n setActiveDropTarget(null)\r\n\r\n if (!rowID || !activeDoc || !overData) {\r\n return\r\n }\r\n\r\n if (manualOrderIsActive && orderableFieldName) {\r\n await handleManualOrderMoveEnd({\r\n activeDoc,\r\n dropTarget: overData,\r\n rowID,\r\n })\r\n return\r\n }\r\n\r\n const targetDoc = getDropTargetParentDoc({\r\n docsByID: allDocsByID,\r\n dropTarget: overData,\r\n })\r\n const dropValidation = getDropValidation({\r\n activeDoc,\r\n targetDoc: targetDoc ?? undefined,\r\n })\r\n\r\n if (!dropValidation.isValid) {\r\n if (!shouldSilenceMoveMessage(dropValidation.message)) {\r\n toast.error(dropValidation.message ?? 'Could not move document.')\r\n }\r\n\r\n return\r\n }\r\n\r\n setPendingMoveRowID(rowID)\r\n\r\n try {\r\n await moveDocument({\r\n parentID: dropValidation.parentID,\r\n rowID,\r\n })\r\n\r\n toast.success(`Moved \"${getDocDisplayLabel(activeDoc)}\".`)\r\n React.startTransition(() => {\r\n router.refresh()\r\n })\r\n } catch (error) {\r\n const message =\r\n error instanceof Error && error.message ? error.message : 'Could not move document.'\r\n\r\n if (shouldSilenceMoveMessage(message)) {\r\n return\r\n }\r\n\r\n toast.error(message)\r\n } finally {\r\n setPendingMoveRowID(null)\r\n }\r\n },\r\n [\r\n allDocsByID,\r\n handleManualOrderMoveEnd,\r\n manualOrderIsActive,\r\n moveDocument,\r\n orderableFieldName,\r\n paginatedDocsByID,\r\n router,\r\n ],\r\n )\r\n const handleDragEndSync = React.useCallback(\r\n (event: DragEndEvent) => {\r\n void handleDragEnd(event)\r\n },\r\n [handleDragEnd],\r\n )\r\n\r\n const tableNode = React.useMemo(\r\n () => (\r\n <DndContext\r\n collisionDetection={pageTreeCollisionDetectionStrategy}\r\n onDragCancel={handleDragCancel}\r\n onDragEnd={handleDragEndSync}\r\n onDragOver={handleDragOver}\r\n onDragStart={handleDragStart}\r\n sensors={sensors}\r\n >\r\n <HierarchyTable\r\n activeDragRowID={activeDragRowID}\r\n allDocsByID={allDocsByID}\r\n allowSameParentDrops={manualOrderIsActive}\r\n columns={tableColumns}\r\n data={paginatedDocs}\r\n isMovePending={isMovePending}\r\n titleCellAccessor={useAsTitle}\r\n />\r\n <DragOverlay dropAnimation={null} style={{ cursor: 'grabbing' }}>\r\n {activeDragPreviewPath ? (\r\n <div className=\"pages-hierarchy-drag-overlay\">{activeDragPreviewPath}</div>\r\n ) : null}\r\n </DragOverlay>\r\n </DndContext>\r\n ),\r\n [\r\n activeDragPreviewPath,\r\n activeDragRowID,\r\n handleDragCancel,\r\n handleDragEndSync,\r\n handleDragOver,\r\n handleDragStart,\r\n isMovePending,\r\n allDocsByID,\r\n manualOrderIsActive,\r\n paginatedDocs,\r\n sensors,\r\n tableColumns,\r\n useAsTitle,\r\n ],\r\n )\r\n\r\n return (\r\n <div className={styles.root}>\r\n <PageTreeProvider value={hierarchyValue}>\r\n <ListQueryProvider\r\n collectionSlug={props.collectionSlug}\r\n data={paginatedData}\r\n modifySearchParams\r\n orderableFieldName={orderableFieldName}\r\n query={{\r\n ...query,\r\n limit: currentLimit,\r\n page: paginatedData.page,\r\n sort: currentSort,\r\n }}\r\n >\r\n <DefaultListView {...props} columnState={paginatedColumnState} Table={tableNode} />\r\n </ListQueryProvider>\r\n </PageTreeProvider>\r\n </div>\r\n )\r\n}\r\n"],"names":["DndContext","DragOverlay","PointerSensor","useDroppable","useSensor","useSensors","DefaultListView","ListQueryProvider","SelectAll","SelectRow","SortHeader","toast","useConfig","useLocale","useTranslation","useRouter","useSearchParams","React","buildInsertDropTargets","getDropTargetParentDoc","getOrderPlacementFromDropTarget","CANCEL_DRAG_MESSAGE","getDropValidation","buildDocSlugPath","buildPageTreeDocs","buildProspectiveDocSlugPath","getDocDisplayLabel","getVisibleTreeDocs","pageTreeCollisionDetectionStrategy","getPageTreeBadgeColor","getPageTreeBadgeLabel","getPageTreeDisplayStatus","PageTreeProvider","styles","PageTreeTitleCell","MANUAL_ORDER_COLUMN_ACCESSOR","SILENT_MOVE_MESSAGES","Set","getRowDropID","rowID","getPageTreeDragData","value","getPayloadDocID","doc","id","undefined","getManualOrderDropValidation","args","activeDoc","targetDoc","isValid","parentID","__pageTreeID","message","__pageTreeAncestorIDs","includes","getDropValidationForMode","allowSameParent","getCurrentOrderPlacement","docs","activeIndex","findIndex","movingSubtreeIDs","filter","map","siblingIsNotMoving","__pageTreeParentID","has","nextSiblingID","previousSiblingID","slice","find","at","orderPlacementHasChanged","currentPlacement","nextPlacement","getReorderTargetFromPlacement","currentSort","docsByID","orderableFieldName","placement","targetDocID","get","newKeyWillBe","buildPaginatedData","limit","requestedPage","totalDocs","length","totalPages","Math","max","ceil","page","min","startIndex","pageDocs","hasNextPage","hasPrevPage","nextPage","pagingCounter","prevPage","normalizeSort","Array","isArray","sortValues","entry","join","normalizePositiveInt","fallback","parsedValue","Number","parseInt","isNaN","normalizePageTreeColumnState","columnState","useAsTitle","column","accessor","active","sliceColumnState","renderedCellIndexByDocID","renderedCells","renderedCellIndex","__pageTreeOrderIndex","getSelectableRowData","record","String","_isLocked","Boolean","_userEditing","shouldSilenceMoveMessage","getStatusClassName","status","renderStatusBadge","badgeConfig","index","t","customColor","badgeColors","colors","statusClass","style","span","className","data-custom-color","badgeLabels","labels","createManualOrderColumn","field","hidden","Heading","insertManualOrderColumn","columns","orderColumn","selectColumnIndex","insertIndex","buildTableColumns","enableRowSelections","homeIndicatorEnabled","parentFieldSlug","columnsToUse","unshift","rowData","some","HierarchyInsertRow","activeColumnsCount","activeDragRowID","dropTarget","dropValidation","isMovePending","isOver","setNodeRef","dropID","data","disabled","hasActiveDrag","tr","data-drag-over","data-drop-valid","data-page-tree-insert","td","colSpan","div","data-insert-depth","depth","ref","HierarchyTableRow","activeColumns","insertAfterDropID","insertBeforeDropID","rowIndex","titleCellAccessor","dropType","isActiveDragRow","data-id","data-is-drag-source","data-page-tree-row","columnIndex","replace","data-page-tree-manual-order-cell","data-page-tree-title-cell","HierarchyTable","allDocsByID","allowSameParentDrops","useMemo","hasManualOrderColumn","insertDropTargets","rowDropValidationByID","Map","insertDropValidationByID","data-page-tree-orderable","table","cellPadding","cellSpacing","thead","th","tbody","Fragment","PageTreeListViewClient","allDocs","canMoveDocs","query","sourceDocs","props","router","searchParams","config","locale","i18n","setActiveDragRowID","useState","activeDropTarget","setActiveDropTarget","collapsedIDs","setCollapsedIDs","localSourceDocs","setLocalSourceDocs","pendingMoveRowID","setPendingMoveRowID","useEffect","toggleRow","useCallback","currentState","nextState","delete","add","searchParamSort","getAll","sort","manualOrderIsActive","currentLimit","currentRequestedPage","liveAllDocs","collapseResetKey","JSON","stringify","collectionSlug","viewType","toString","hierarchyValue","visibleDocs","paginatedData","paginatedDocs","paginatedDocsByID","normalizedColumnState","paginatedColumnState","tableColumns","activeDragDoc","activeDragPreviewPath","sensors","activationConstraint","distance","moveDocument","params","URLSearchParams","code","set","response","fetch","routes","api","encodeURIComponent","size","body","credentials","headers","language","method","result","json","catch","ok","Error","reorderDocument","movedDocID","targetID","docsToMove","target","key","orderValues","handleManualOrderMoveEnd","error","parentChanged","orderChanged","reorderTarget","parentDoc","nextParentValue","parentMoveSucceeded","nextOrderValue","currentDocs","success","startTransition","refresh","handleDragCancel","handleDragStart","event","dragData","current","handleDragOver","overData","over","handleDragEnd","handleDragEndSync","tableNode","collisionDetection","onDragCancel","onDragEnd","onDragOver","onDragStart","dropAnimation","cursor","root","modifySearchParams","Table"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../src/components/PageTreeListView.client.tsx"],"sourcesContent":["'use client'\r\n\r\nimport type { Column, ListQuery, ListViewClientProps, PaginatedDocs } from 'payload'\r\n\r\nimport {\r\n DndContext,\r\n type DragEndEvent,\r\n type DragOverEvent,\r\n DragOverlay,\r\n type DragStartEvent,\r\n PointerSensor,\r\n useDroppable,\r\n useSensor,\r\n useSensors,\r\n} from '@dnd-kit/core'\r\nimport {\r\n DefaultListView,\r\n ListQueryProvider,\r\n SelectAll,\r\n SelectRow,\r\n SortHeader,\r\n toast,\r\n useConfig,\r\n useLocale,\r\n useTranslation,\r\n} from '@payloadcms/ui'\r\nimport { useRouter, useSearchParams } from 'next/navigation'\r\nimport React from 'react'\r\n\r\nimport {\n pageTreeMoveRequestHeader,\n pageTreeMoveRequestHeaderValue,\n type NestedDocsPageTreePluginResolvedBadgeConfig,\n type PageTreeSourceDoc,\n} from '../types.js'\n\r\nimport {\r\n buildInsertDropTargets,\r\n getDropTargetParentDoc,\r\n getOrderPlacementFromDropTarget,\r\n type PageTreeDropTarget,\r\n type PageTreeOrderPlacement,\r\n} from '../utilities/dropTargets.js'\r\nimport {\r\n CANCEL_DRAG_MESSAGE,\r\n getDropValidation,\r\n type PageTreeDropValidation,\r\n} from '../utilities/moveValidation.js'\r\nimport {\r\n buildDocSlugPath,\r\n buildPageTreeDocs,\r\n buildProspectiveDocSlugPath,\r\n getDocDisplayLabel,\r\n getVisibleTreeDocs,\r\n type PageTreeDoc,\r\n} from '../utilities/pageTree.js'\r\nimport { pageTreeCollisionDetectionStrategy } from '../utilities/pageTreeCollision.js'\r\nimport {\r\n getPageTreeBadgeColor,\r\n getPageTreeBadgeLabel,\r\n getPageTreeDisplayStatus,\r\n type PageTreeDisplayStatus,\r\n} from '../utilities/status.js'\r\nimport { PageTreeProvider } from './PageTreeContext.js'\r\nimport styles from './PageTreeListView.module.css'\r\nimport { PageTreeTitleCell } from './PageTreeTitleCell.js'\r\n\r\ntype PageTreeListViewClientOwnProps = {\r\n allDocs: PageTreeDoc[]\r\n badgeConfig: NestedDocsPageTreePluginResolvedBadgeConfig\r\n canMoveDocs: boolean\r\n columnState: Column[]\r\n homeIndicatorEnabled: boolean\r\n orderableFieldName?: string\r\n parentFieldSlug: string\r\n query: ListQuery\r\n sourceDocs: PageTreeSourceDoc[]\r\n useAsTitle: string\r\n}\r\n\r\ntype PageTreeListViewClientProps = Omit<ListViewClientProps, 'columnState' | 'Table'> &\r\n PageTreeListViewClientOwnProps\r\n\r\ntype SelectableRowData = React.ComponentProps<typeof SelectRow>['rowData']\r\ntype PageTreeDragData = {\r\n dragType?: 'move'\r\n rowID?: string\r\n}\r\ntype ReorderDirection = 'greater' | 'less'\r\n\r\nconst MANUAL_ORDER_COLUMN_ACCESSOR = '_dragHandle'\r\nconst SILENT_MOVE_MESSAGES = new Set([CANCEL_DRAG_MESSAGE])\r\n\r\nfunction getRowDropID(rowID: string): string {\r\n return `page-drop:${rowID}`\r\n}\r\n\r\nfunction getPageTreeDragData(value: unknown): PageTreeDragData {\r\n return value && typeof value === 'object' ? (value as PageTreeDragData) : {}\r\n}\r\n\r\nfunction getPayloadDocID(doc: PageTreeDoc): number | string | undefined {\r\n return typeof doc.id === 'number' || typeof doc.id === 'string' ? doc.id : undefined\r\n}\r\n\r\nfunction getManualOrderDropValidation(args: {\r\n activeDoc: PageTreeDoc\r\n targetDoc?: PageTreeDoc\r\n}): PageTreeDropValidation {\r\n const { activeDoc, targetDoc } = args\r\n\r\n if (!targetDoc) {\r\n return {\r\n isValid: true,\r\n parentID: null,\r\n }\r\n }\r\n\r\n if (targetDoc.__pageTreeID === activeDoc.__pageTreeID) {\r\n return {\r\n isValid: false,\r\n message: CANCEL_DRAG_MESSAGE,\r\n parentID: targetDoc.__pageTreeID,\r\n }\r\n }\r\n\r\n if (targetDoc.__pageTreeAncestorIDs.includes(activeDoc.__pageTreeID)) {\r\n return {\r\n isValid: false,\r\n message: 'A document cannot be moved under one of its descendants.',\r\n parentID: targetDoc.__pageTreeID,\r\n }\r\n }\r\n\r\n return {\r\n isValid: true,\r\n parentID: targetDoc.__pageTreeID,\r\n }\r\n}\r\n\r\nfunction getDropValidationForMode(args: {\r\n activeDoc: PageTreeDoc\r\n allowSameParent: boolean\r\n targetDoc?: PageTreeDoc\r\n}): PageTreeDropValidation {\r\n const { activeDoc, allowSameParent, targetDoc } = args\r\n\r\n if (allowSameParent) {\r\n return getManualOrderDropValidation({\r\n activeDoc,\r\n targetDoc,\r\n })\r\n }\r\n\r\n return getDropValidation({\r\n activeDoc,\r\n targetDoc,\r\n })\r\n}\r\n\r\nfunction getCurrentOrderPlacement(args: {\r\n activeDoc: PageTreeDoc\r\n docs: PageTreeDoc[]\r\n}): PageTreeOrderPlacement {\r\n const { activeDoc, docs } = args\r\n const activeIndex = docs.findIndex((doc) => doc.__pageTreeID === activeDoc.__pageTreeID)\r\n const movingSubtreeIDs = new Set(\r\n docs\r\n .filter(\r\n (doc) =>\r\n doc.__pageTreeID === activeDoc.__pageTreeID ||\r\n doc.__pageTreeAncestorIDs.includes(activeDoc.__pageTreeID),\r\n )\r\n .map((doc) => doc.__pageTreeID),\r\n )\r\n const siblingIsNotMoving = (doc: PageTreeDoc) =>\r\n doc.__pageTreeParentID === activeDoc.__pageTreeParentID &&\r\n !movingSubtreeIDs.has(doc.__pageTreeID)\r\n\r\n if (activeIndex < 0) {\r\n return {\r\n nextSiblingID: null,\r\n parentID: activeDoc.__pageTreeParentID,\r\n previousSiblingID: null,\r\n }\r\n }\r\n\r\n return {\r\n nextSiblingID: docs.slice(activeIndex + 1).find(siblingIsNotMoving)?.__pageTreeID ?? null,\r\n parentID: activeDoc.__pageTreeParentID,\r\n previousSiblingID:\r\n docs.slice(0, activeIndex).filter(siblingIsNotMoving).at(-1)?.__pageTreeID ?? null,\r\n }\r\n}\r\n\r\nfunction orderPlacementHasChanged(\r\n currentPlacement: PageTreeOrderPlacement,\r\n nextPlacement: PageTreeOrderPlacement,\r\n): boolean {\r\n return (\r\n currentPlacement.parentID !== nextPlacement.parentID ||\r\n currentPlacement.previousSiblingID !== nextPlacement.previousSiblingID ||\r\n currentPlacement.nextSiblingID !== nextPlacement.nextSiblingID\r\n )\r\n}\r\n\r\nfunction getReorderTargetFromPlacement(args: {\r\n currentSort?: string\r\n docsByID: ReadonlyMap<string, PageTreeDoc>\r\n orderableFieldName: string\r\n placement: PageTreeOrderPlacement\r\n}): {\r\n newKeyWillBe: ReorderDirection\r\n targetDoc: PageTreeDoc\r\n} | null {\r\n const { currentSort, docsByID, orderableFieldName, placement } = args\r\n const targetDocID = placement.previousSiblingID ?? placement.nextSiblingID\r\n\r\n if (!targetDocID) {\r\n return null\r\n }\r\n\r\n const targetDoc = docsByID.get(targetDocID)\r\n\r\n if (!targetDoc) {\r\n return null\r\n }\r\n\r\n return {\r\n newKeyWillBe:\r\n (placement.previousSiblingID !== null && currentSort === orderableFieldName) ||\r\n (placement.previousSiblingID === null && currentSort === `-${orderableFieldName}`)\r\n ? 'greater'\r\n : 'less',\r\n targetDoc,\r\n }\r\n}\r\n\r\nfunction buildPaginatedData(\r\n docs: PageTreeDoc[],\r\n limit: number,\r\n requestedPage: number,\r\n): PaginatedDocs {\r\n const totalDocs = docs.length\r\n const totalPages = totalDocs > 0 ? Math.max(1, Math.ceil(totalDocs / limit)) : 1\r\n const page = Math.min(Math.max(requestedPage, 1), totalPages)\r\n const startIndex = (page - 1) * limit\r\n const pageDocs = docs.slice(startIndex, startIndex + limit)\r\n\r\n return {\r\n docs: pageDocs,\r\n hasNextPage: page < totalPages,\r\n hasPrevPage: page > 1,\r\n limit,\r\n nextPage: page < totalPages ? page + 1 : null,\r\n page,\r\n pagingCounter: totalDocs === 0 ? 0 : startIndex + 1,\r\n prevPage: page > 1 ? page - 1 : null,\r\n totalDocs,\r\n totalPages,\r\n }\r\n}\r\n\r\nfunction normalizeSort(value: string | string[] | undefined): string | undefined {\r\n if (Array.isArray(value)) {\r\n const sortValues = value.filter((entry) => typeof entry === 'string' && entry.length > 0)\r\n return sortValues.length > 0 ? sortValues.join(',') : undefined\r\n }\r\n\r\n return typeof value === 'string' && value.length > 0 ? value : undefined\r\n}\r\n\r\nfunction normalizePositiveInt(value: null | string, fallback: number): number {\r\n if (typeof value !== 'string') {\r\n return fallback\r\n }\r\n\r\n const parsedValue = Number.parseInt(value, 10)\r\n return Number.isNaN(parsedValue) || parsedValue <= 0 ? fallback : parsedValue\r\n}\r\n\r\nfunction normalizePageTreeColumnState(columnState: Column[], useAsTitle: string): Column[] {\r\n return columnState\r\n .filter((column) => column.accessor !== MANUAL_ORDER_COLUMN_ACCESSOR)\r\n .map((column) =>\r\n column.accessor === useAsTitle\r\n ? {\r\n ...column,\r\n active: true,\r\n }\r\n : column,\r\n )\r\n}\r\n\r\nfunction sliceColumnState(\r\n columnState: Column[],\r\n docs: PageTreeDoc[],\r\n renderedCellIndexByDocID: ReadonlyMap<string, number>,\r\n): Column[] {\r\n return columnState.map((column) => ({\r\n ...column,\r\n renderedCells: docs.map((doc) => {\r\n const renderedCellIndex =\r\n renderedCellIndexByDocID.get(doc.__pageTreeID) ?? doc.__pageTreeOrderIndex\r\n\r\n return column.renderedCells?.[renderedCellIndex] ?? null\r\n }),\r\n }))\r\n}\r\n\r\nfunction getSelectableRowData(doc: PageTreeDoc): SelectableRowData {\r\n const record = doc as Record<string, unknown>\r\n\r\n return {\r\n id: String(doc.id ?? doc.__pageTreeID),\r\n _isLocked: Boolean(record._isLocked),\r\n _userEditing: record._userEditing as SelectableRowData['_userEditing'],\r\n }\r\n}\r\n\r\nfunction shouldSilenceMoveMessage(message?: string): boolean {\r\n return typeof message === 'string' && SILENT_MOVE_MESSAGES.has(message)\r\n}\r\n\r\nfunction getStatusClassName(\r\n status: PageTreeDisplayStatus,\r\n): 'changed' | 'draft' | 'published' | 'unknown' {\r\n if (status === 'changed' || status === 'draft' || status === 'published') {\r\n return status\r\n }\r\n\r\n return 'unknown'\r\n}\r\n\r\nfunction renderStatusBadge(args: {\r\n badgeConfig: NestedDocsPageTreePluginResolvedBadgeConfig\r\n doc: PageTreeDoc\r\n index: number\r\n t: (key: 'general:noValue' | 'version:changed' | 'version:draft' | 'version:published') => string\r\n}): React.ReactNode {\r\n const { badgeConfig, doc, index, t } = args\r\n const status = getPageTreeDisplayStatus(doc)\r\n const customColor = getPageTreeBadgeColor({\r\n badgeColors: badgeConfig.colors,\r\n status,\r\n })\r\n const statusClass = getStatusClassName(status)\r\n const style = customColor\r\n ? ({ '--page-tree-badge-base': customColor } as React.CSSProperties)\r\n : undefined\r\n\r\n return (\r\n <span\r\n className={[\r\n 'pages-hierarchy-status-badge',\r\n `pages-hierarchy-status-badge--${statusClass}`,\r\n ].join(' ')}\r\n data-custom-color={customColor ? 'true' : undefined}\r\n key={doc.__pageTreeID ?? index}\r\n style={style}\r\n >\r\n {getPageTreeBadgeLabel({\r\n badgeLabels: badgeConfig.labels,\r\n status,\r\n t,\r\n })}\r\n </span>\r\n )\r\n}\r\n\r\nfunction createManualOrderColumn(docs: PageTreeDoc[]): Column {\r\n return {\r\n accessor: MANUAL_ORDER_COLUMN_ACCESSOR,\r\n active: true,\r\n field: { hidden: true } as Column['field'],\r\n Heading: <SortHeader />,\r\n renderedCells: docs.map(() => null),\r\n }\r\n}\r\n\r\nfunction insertManualOrderColumn(columns: Column[], orderColumn: Column): Column[] {\r\n const selectColumnIndex = columns.findIndex((column) => column.accessor === '_select')\r\n const insertIndex = selectColumnIndex >= 0 ? selectColumnIndex + 1 : 0\r\n\r\n return [\r\n ...columns.slice(0, insertIndex),\r\n orderColumn,\r\n ...columns.slice(insertIndex),\r\n ]\r\n}\r\n\r\nfunction buildTableColumns(args: {\r\n badgeConfig: NestedDocsPageTreePluginResolvedBadgeConfig\r\n columnState: Column[]\r\n docs: PageTreeDoc[]\r\n enableRowSelections?: boolean\r\n homeIndicatorEnabled: boolean\r\n orderableFieldName?: string\r\n parentFieldSlug: string\r\n t: (key: 'general:noValue' | 'version:changed' | 'version:draft' | 'version:published') => string\r\n useAsTitle: string\r\n}): Column[] {\r\n const {\r\n badgeConfig,\r\n columnState,\r\n docs,\r\n enableRowSelections,\r\n homeIndicatorEnabled,\r\n orderableFieldName,\r\n parentFieldSlug,\r\n t,\r\n useAsTitle,\r\n } = args\r\n const columnsToUse = columnState.map((column) => {\r\n if (column.accessor === useAsTitle) {\r\n return {\r\n ...column,\r\n active: true,\r\n renderedCells: docs.map((doc, index) => (\r\n <PageTreeTitleCell\r\n doc={doc}\r\n homeIndicatorEnabled={homeIndicatorEnabled}\r\n key={doc.__pageTreeID ?? index}\r\n >\r\n {column.renderedCells?.[index] ?? getDocDisplayLabel(doc)}\r\n </PageTreeTitleCell>\r\n )),\r\n }\r\n }\r\n\r\n if (column.accessor === '_status') {\r\n return {\r\n ...column,\r\n renderedCells: docs.map((doc, index) =>\r\n renderStatusBadge({\r\n badgeConfig,\r\n doc,\r\n index,\r\n t,\r\n }),\r\n ),\r\n }\r\n }\r\n\r\n if (column.accessor === parentFieldSlug) {\r\n return {\r\n ...column,\r\n renderedCells: docs.map((doc, index) =>\r\n doc.__pageTreeParentID !== null ? (\r\n column.renderedCells?.[index] ?? null\r\n ) : (\r\n <span className=\"pages-hierarchy-empty-cell\" key={doc.__pageTreeID ?? index}>\r\n -\r\n </span>\r\n ),\r\n ),\r\n }\r\n }\r\n\r\n return column\r\n })\r\n\r\n if (enableRowSelections) {\r\n columnsToUse.unshift({\r\n accessor: '_select',\r\n active: true,\r\n field: { hidden: true } as Column['field'],\r\n Heading: <SelectAll />,\r\n renderedCells: docs.map((doc, index) => (\r\n <SelectRow key={doc.__pageTreeID ?? index} rowData={getSelectableRowData(doc)} />\r\n )),\r\n })\r\n }\r\n\r\n if (\r\n orderableFieldName &&\r\n !columnsToUse.some((column) => column.accessor === MANUAL_ORDER_COLUMN_ACCESSOR)\r\n ) {\r\n return insertManualOrderColumn(columnsToUse, createManualOrderColumn(docs))\r\n }\r\n\r\n return columnsToUse\r\n}\r\n\r\nfunction HierarchyInsertRow({\r\n activeColumnsCount,\r\n activeDragRowID,\r\n dropTarget,\r\n dropValidation,\r\n isMovePending,\r\n}: {\r\n activeColumnsCount: number\r\n activeDragRowID: null | string\r\n dropTarget: Extract<PageTreeDropTarget, { dropType: 'insert' }>\r\n dropValidation?: PageTreeDropValidation\r\n isMovePending: boolean\r\n}) {\r\n const { isOver, setNodeRef } = useDroppable({\r\n id: dropTarget.dropID,\r\n data: dropTarget,\r\n disabled: isMovePending,\r\n })\r\n const hasActiveDrag = Boolean(activeDragRowID)\r\n\r\n return (\r\n <tr\r\n className=\"pages-hierarchy-insert-row\"\r\n data-drag-over={isOver ? 'true' : 'false'}\r\n data-drop-valid={hasActiveDrag ? (dropValidation?.isValid ? 'true' : 'false') : undefined}\r\n data-page-tree-insert=\"true\"\r\n >\r\n <td colSpan={activeColumnsCount}>\r\n <div\r\n className=\"pages-hierarchy-insert-row__target\"\r\n data-insert-depth={dropTarget.depth}\r\n ref={setNodeRef}\r\n />\r\n </td>\r\n </tr>\r\n )\r\n}\r\n\r\nfunction HierarchyTableRow({\r\n activeColumns,\r\n activeDragRowID,\r\n doc,\r\n dropValidation,\r\n insertAfterDropID,\r\n insertBeforeDropID,\r\n isMovePending,\r\n rowIndex,\r\n titleCellAccessor,\r\n}: {\r\n activeColumns: Column[]\r\n activeDragRowID: null | string\r\n doc: PageTreeDoc\r\n dropValidation?: PageTreeDropValidation\r\n insertAfterDropID: string\r\n insertBeforeDropID: string\r\n isMovePending: boolean\r\n rowIndex: number\r\n titleCellAccessor: string\r\n}) {\r\n const { isOver, setNodeRef } = useDroppable({\r\n id: getRowDropID(doc.__pageTreeID),\r\n data: {\r\n dropType: 'row',\r\n insertAfterDropID,\r\n insertBeforeDropID,\r\n rowID: doc.__pageTreeID,\r\n } satisfies Extract<PageTreeDropTarget, { dropType: 'row' }>,\r\n disabled: isMovePending,\r\n })\r\n const hasActiveDrag = Boolean(activeDragRowID)\r\n const isActiveDragRow = activeDragRowID === doc.__pageTreeID\r\n\r\n return (\r\n <tr\r\n className={`row-${rowIndex + 1}`}\r\n data-drag-over={isOver ? 'true' : 'false'}\r\n data-drop-valid={hasActiveDrag ? (dropValidation?.isValid ? 'true' : 'false') : undefined}\r\n data-id={doc.id}\r\n data-is-drag-source={isActiveDragRow ? 'true' : 'false'}\r\n data-page-tree-row=\"true\"\r\n ref={setNodeRef}\r\n >\r\n {activeColumns.map((column, columnIndex) => {\r\n const { accessor } = column\r\n\r\n return (\r\n <td\r\n className={`cell-${accessor.replace(/\\./g, '__')}`}\r\n data-page-tree-manual-order-cell={\r\n accessor === MANUAL_ORDER_COLUMN_ACCESSOR ? 'true' : undefined\r\n }\r\n data-page-tree-title-cell={accessor === titleCellAccessor ? 'true' : undefined}\r\n key={columnIndex}\r\n >\r\n {column.renderedCells?.[rowIndex] ?? null}\r\n </td>\r\n )\r\n })}\r\n </tr>\r\n )\r\n}\r\n\r\nfunction HierarchyTable({\r\n activeDragRowID,\r\n allDocsByID,\r\n allowSameParentDrops,\r\n columns,\r\n data,\r\n isMovePending,\r\n titleCellAccessor,\r\n}: {\r\n activeDragRowID: null | string\r\n allDocsByID: ReadonlyMap<string, PageTreeDoc>\r\n allowSameParentDrops: boolean\r\n columns: Column[]\r\n data: PageTreeDoc[]\r\n isMovePending: boolean\r\n titleCellAccessor: string\r\n}) {\r\n const activeColumns = React.useMemo(\r\n () => columns.filter((column) => column?.active),\r\n [columns],\r\n )\r\n const hasManualOrderColumn = React.useMemo(\r\n () => activeColumns.some((column) => column.accessor === MANUAL_ORDER_COLUMN_ACCESSOR),\r\n [activeColumns],\r\n )\r\n const insertDropTargets = React.useMemo(() => buildInsertDropTargets(data), [data])\r\n const activeDoc = activeDragRowID ? allDocsByID.get(activeDragRowID) ?? null : null\r\n const rowDropValidationByID = React.useMemo(() => {\r\n if (!activeDoc) {\r\n return new Map<string, PageTreeDropValidation>()\r\n }\r\n\r\n return new Map(\r\n data.map((doc) => [\r\n doc.__pageTreeID,\r\n getDropValidationForMode({\r\n activeDoc,\r\n allowSameParent: allowSameParentDrops,\r\n targetDoc: doc,\r\n }),\r\n ]),\r\n )\r\n }, [activeDoc, allowSameParentDrops, data])\r\n const insertDropValidationByID = React.useMemo(() => {\r\n if (!activeDoc) {\r\n return new Map<string, PageTreeDropValidation>()\r\n }\r\n\r\n return new Map(\r\n insertDropTargets.map((dropTarget) => [\r\n dropTarget.dropID,\r\n getDropValidationForMode({\r\n activeDoc,\r\n allowSameParent: allowSameParentDrops,\r\n targetDoc:\r\n dropTarget.parentID === null\r\n ? undefined\r\n : allDocsByID.get(dropTarget.parentID) ?? undefined,\r\n }),\r\n ]),\r\n )\r\n }, [activeDoc, allowSameParentDrops, allDocsByID, insertDropTargets])\r\n\r\n if (activeColumns.length === 0) {\r\n return <div>No columns selected</div>\r\n }\r\n\r\n return (\r\n <div\r\n className={[\r\n 'table-wrap pages-hierarchy-table',\r\n activeDoc ? 'pages-hierarchy-table--dragging' : '',\r\n ]\r\n .filter(Boolean)\r\n .join(' ')}\r\n data-page-tree-orderable={hasManualOrderColumn ? 'true' : undefined}\r\n >\r\n <div className=\"table table--appearance-default\">\r\n <table cellPadding=\"0\" cellSpacing=\"0\">\r\n <thead>\r\n <tr>\r\n {activeColumns.map((column, index) => (\r\n <th\r\n data-page-tree-manual-order-cell={\r\n column.accessor === MANUAL_ORDER_COLUMN_ACCESSOR ? 'true' : undefined\r\n }\r\n data-page-tree-title-cell={\r\n column.accessor === titleCellAccessor ? 'true' : undefined\r\n }\r\n id={`heading-${column.accessor.replace(/\\./g, '__')}`}\r\n key={index}\r\n >\r\n {column.Heading}\r\n </th>\r\n ))}\r\n </tr>\r\n </thead>\r\n <tbody>\r\n {insertDropTargets[0] ? (\r\n <HierarchyInsertRow\r\n activeColumnsCount={activeColumns.length}\r\n activeDragRowID={activeDragRowID}\r\n dropTarget={insertDropTargets[0]}\r\n dropValidation={insertDropValidationByID.get(insertDropTargets[0].dropID)}\r\n isMovePending={isMovePending}\r\n key={insertDropTargets[0].dropID}\r\n />\r\n ) : null}\r\n {data.map((doc, rowIndex) => (\r\n <React.Fragment key={doc.__pageTreeID}>\r\n <HierarchyTableRow\r\n activeColumns={activeColumns}\r\n activeDragRowID={activeDragRowID}\r\n doc={doc}\r\n dropValidation={rowDropValidationByID.get(doc.__pageTreeID)}\r\n insertAfterDropID={insertDropTargets[rowIndex + 1].dropID}\r\n insertBeforeDropID={insertDropTargets[rowIndex].dropID}\r\n isMovePending={isMovePending}\r\n rowIndex={rowIndex}\r\n titleCellAccessor={titleCellAccessor}\r\n />\r\n {insertDropTargets[rowIndex + 1] ? (\r\n <HierarchyInsertRow\r\n activeColumnsCount={activeColumns.length}\r\n activeDragRowID={activeDragRowID}\r\n dropTarget={insertDropTargets[rowIndex + 1]}\r\n dropValidation={insertDropValidationByID.get(\r\n insertDropTargets[rowIndex + 1].dropID,\r\n )}\r\n isMovePending={isMovePending}\r\n key={insertDropTargets[rowIndex + 1].dropID}\r\n />\r\n ) : null}\r\n </React.Fragment>\r\n ))}\r\n </tbody>\r\n </table>\r\n </div>\r\n </div>\r\n )\r\n}\r\n\r\nexport default function PageTreeListViewClient({\r\n allDocs,\r\n badgeConfig,\r\n canMoveDocs,\r\n columnState,\r\n homeIndicatorEnabled,\r\n orderableFieldName,\r\n parentFieldSlug,\r\n query,\r\n sourceDocs,\r\n useAsTitle,\r\n ...props\r\n}: PageTreeListViewClientProps) {\r\n const router = useRouter()\r\n const searchParams = useSearchParams()\r\n const { config } = useConfig()\r\n const locale = useLocale()\r\n const { i18n } = useTranslation()\r\n const [activeDragRowID, setActiveDragRowID] = React.useState<null | string>(null)\r\n const [activeDropTarget, setActiveDropTarget] = React.useState<null | PageTreeDropTarget>(null)\r\n const [collapsedIDs, setCollapsedIDs] = React.useState<Set<string>>(() => new Set())\r\n const [localSourceDocs, setLocalSourceDocs] = React.useState(sourceDocs)\r\n const [pendingMoveRowID, setPendingMoveRowID] = React.useState<null | string>(null)\r\n\r\n React.useEffect(() => {\r\n setLocalSourceDocs(sourceDocs)\r\n }, [sourceDocs])\r\n\r\n const toggleRow = React.useCallback((rowID: string) => {\r\n setCollapsedIDs((currentState) => {\r\n const nextState = new Set(currentState)\r\n\r\n if (nextState.has(rowID)) {\r\n nextState.delete(rowID)\r\n } else {\r\n nextState.add(rowID)\r\n }\r\n\r\n return nextState\r\n })\r\n }, [])\r\n const currentSort = React.useMemo(() => {\r\n const searchParamSort = searchParams.getAll('sort')\r\n\r\n if (searchParamSort.length > 0) {\r\n return normalizeSort(searchParamSort)\r\n }\r\n\r\n return normalizeSort(query.sort as string | string[] | undefined)\r\n }, [query.sort, searchParams])\r\n const manualOrderIsActive = Boolean(\r\n orderableFieldName &&\r\n (currentSort === orderableFieldName || currentSort === `-${orderableFieldName}`),\r\n )\r\n const currentLimit = React.useMemo(\r\n () =>\r\n normalizePositiveInt(\r\n searchParams.get('limit'),\r\n typeof query.limit === 'number' && query.limit > 0 ? query.limit : 10,\r\n ),\r\n [query.limit, searchParams],\r\n )\r\n const currentRequestedPage = React.useMemo(\r\n () =>\r\n normalizePositiveInt(\r\n searchParams.get('page'),\r\n typeof query.page === 'number' && query.page > 0 ? query.page : 1,\r\n ),\r\n [query.page, searchParams],\r\n )\r\n const liveAllDocs = React.useMemo(\r\n () =>\r\n buildPageTreeDocs(localSourceDocs, {\r\n parentFieldSlug,\r\n sort: currentSort,\r\n }),\r\n [currentSort, localSourceDocs, parentFieldSlug],\r\n )\r\n const collapseResetKey = React.useMemo(\r\n () => JSON.stringify([props.collectionSlug, props.viewType, searchParams.toString()]),\r\n [props.collectionSlug, props.viewType, searchParams],\r\n )\r\n const hierarchyValue = React.useMemo(\r\n () => ({\r\n activeDragRowID,\r\n canMoveDocs,\r\n collapsedIDs,\r\n pendingMoveRowID,\r\n toggleRow,\r\n }),\r\n [activeDragRowID, canMoveDocs, collapsedIDs, pendingMoveRowID, toggleRow],\r\n )\r\n\r\n React.useEffect(() => {\r\n setActiveDragRowID(null)\r\n setActiveDropTarget(null)\r\n setCollapsedIDs(new Set())\r\n }, [collapseResetKey])\r\n\r\n const visibleDocs = React.useMemo(\r\n () => getVisibleTreeDocs(liveAllDocs, collapsedIDs),\r\n [liveAllDocs, collapsedIDs],\r\n )\r\n const paginatedData = React.useMemo(\r\n () => buildPaginatedData(visibleDocs, currentLimit, currentRequestedPage),\r\n [currentLimit, currentRequestedPage, visibleDocs],\r\n )\r\n const paginatedDocs = paginatedData.docs as PageTreeDoc[]\r\n const allDocsByID = React.useMemo(\r\n () => new Map(liveAllDocs.map((doc) => [doc.__pageTreeID, doc])),\r\n [liveAllDocs],\r\n )\r\n const paginatedDocsByID = React.useMemo(\r\n () => new Map(paginatedDocs.map((doc) => [doc.__pageTreeID, doc])),\r\n [paginatedDocs],\r\n )\r\n const renderedCellIndexByDocID = React.useMemo(\r\n () => new Map(allDocs.map((doc, index) => [doc.__pageTreeID, index])),\r\n [allDocs],\r\n )\r\n const normalizedColumnState = React.useMemo(\r\n () => normalizePageTreeColumnState(columnState, useAsTitle),\r\n [columnState, useAsTitle],\r\n )\r\n const paginatedColumnState = React.useMemo(\r\n () => sliceColumnState(normalizedColumnState, paginatedDocs, renderedCellIndexByDocID),\r\n [normalizedColumnState, paginatedDocs, renderedCellIndexByDocID],\r\n )\r\n const tableColumns = React.useMemo(\r\n () =>\r\n buildTableColumns({\r\n badgeConfig,\r\n columnState: paginatedColumnState,\r\n docs: paginatedDocs,\r\n enableRowSelections: props.enableRowSelections,\r\n homeIndicatorEnabled,\r\n orderableFieldName,\r\n parentFieldSlug,\r\n t: i18n.t,\r\n useAsTitle,\r\n }),\r\n [\r\n paginatedColumnState,\r\n paginatedDocs,\r\n badgeConfig,\r\n homeIndicatorEnabled,\r\n orderableFieldName,\r\n parentFieldSlug,\r\n props.enableRowSelections,\r\n i18n.t,\r\n useAsTitle,\r\n ],\r\n )\r\n const activeDragDoc = activeDragRowID ? paginatedDocsByID.get(activeDragRowID) ?? null : null\r\n const activeDragPreviewPath = React.useMemo(() => {\r\n if (!activeDragDoc) {\r\n return null\r\n }\r\n\r\n if (!activeDropTarget) {\r\n return buildDocSlugPath({\r\n doc: activeDragDoc,\r\n docsByID: allDocsByID,\r\n })\r\n }\r\n\r\n const targetDoc = getDropTargetParentDoc({\r\n docsByID: allDocsByID,\r\n dropTarget: activeDropTarget,\r\n })\r\n const dropValidation = getDropValidationForMode({\r\n activeDoc: activeDragDoc,\r\n allowSameParent: manualOrderIsActive,\r\n targetDoc: targetDoc ?? undefined,\r\n })\r\n\r\n if (!dropValidation.isValid) {\r\n return buildDocSlugPath({\r\n doc: activeDragDoc,\r\n docsByID: allDocsByID,\r\n })\r\n }\r\n\r\n return buildProspectiveDocSlugPath({\r\n activeDoc: activeDragDoc,\r\n docsByID: allDocsByID,\r\n targetDoc: targetDoc ?? undefined,\r\n })\r\n }, [activeDragDoc, activeDropTarget, allDocsByID, manualOrderIsActive])\r\n const isMovePending = pendingMoveRowID !== null\r\n const sensors = useSensors(\r\n useSensor(PointerSensor, {\r\n activationConstraint: {\r\n distance: 4,\r\n },\r\n }),\r\n )\r\n const moveDocument = React.useCallback(\r\n async (args: { parentID: null | string; rowID: string }) => {\r\n const { parentID, rowID } = args\r\n const params = new URLSearchParams()\r\n\r\n if (locale?.code) {\r\n params.set('locale', locale.code)\r\n }\r\n\r\n const response = await fetch(\r\n `${config.routes.api}/${props.collectionSlug}/${encodeURIComponent(rowID)}/move${\r\n params.size > 0 ? `?${params.toString()}` : ''\r\n }`,\r\n {\r\n body: JSON.stringify({\r\n parentID,\r\n }),\r\n credentials: 'include',\r\n headers: {\n 'Accept-Language': i18n.language,\n 'Content-Type': 'application/json',\n [pageTreeMoveRequestHeader]: pageTreeMoveRequestHeaderValue,\n },\n method: 'POST',\n },\n )\r\n const result = (await response.json().catch(() => null)) as\r\n | {\r\n message?: string\r\n }\r\n | null\r\n\r\n if (!response.ok) {\r\n throw new Error(result?.message ?? 'Could not move document.')\r\n }\r\n\r\n return result\r\n },\r\n [config.routes.api, i18n.language, locale?.code, props.collectionSlug],\r\n )\r\n const reorderDocument = React.useCallback(\r\n async (args: {\r\n movedDocID: number | string\r\n newKeyWillBe: ReorderDirection\r\n targetDoc: PageTreeDoc\r\n }) => {\r\n const { movedDocID, newKeyWillBe, targetDoc } = args\r\n const targetID = getPayloadDocID(targetDoc)\r\n\r\n if (!orderableFieldName || targetID === undefined) {\r\n return undefined\r\n }\r\n\r\n const params = new URLSearchParams()\r\n\r\n if (locale?.code) {\r\n params.set('locale', locale.code)\r\n }\r\n\r\n const response = await fetch(\r\n `${config.routes.api}/reorder${params.size > 0 ? `?${params.toString()}` : ''}`,\r\n {\r\n body: JSON.stringify({\r\n collectionSlug: props.collectionSlug,\r\n docsToMove: [movedDocID],\r\n newKeyWillBe,\r\n orderableFieldName,\r\n target: {\r\n id: targetID,\r\n key: targetDoc[orderableFieldName],\r\n },\r\n }),\r\n credentials: 'include',\r\n headers: {\n 'Accept-Language': i18n.language,\n 'Content-Type': 'application/json',\n [pageTreeMoveRequestHeader]: pageTreeMoveRequestHeaderValue,\n },\n method: 'POST',\n },\n )\r\n const result = (await response.json().catch(() => null)) as\r\n | {\r\n message?: string\r\n orderValues?: unknown[]\r\n }\r\n | null\r\n\r\n if (response.status === 403) {\r\n throw new Error('You do not have permission to reorder these rows')\r\n }\r\n\r\n if (!response.ok) {\r\n throw new Error(\r\n 'Failed to reorder. This can happen if you reorder several rows too quickly. Please try again.',\r\n )\r\n }\r\n\r\n if (result?.message === 'initial migration') {\r\n throw new Error(\r\n 'You have enabled \"orderable\" on a collection with existing documents and this is the first time you have sorted documents. We have run an automatic migration to add an initial order to the documents. Please refresh the page and try again.',\r\n )\r\n }\r\n\r\n return result?.orderValues?.[0]\r\n },\r\n [\r\n config.routes.api,\r\n i18n.language,\r\n locale?.code,\r\n orderableFieldName,\r\n props.collectionSlug,\r\n ],\r\n )\r\n const handleManualOrderMoveEnd = React.useCallback(\r\n async (args: {\r\n activeDoc: PageTreeDoc\r\n dropTarget: PageTreeDropTarget\r\n rowID: string\r\n }) => {\r\n const { activeDoc, dropTarget, rowID } = args\r\n\r\n if (!orderableFieldName) {\r\n return\r\n }\r\n\r\n const targetDoc = getDropTargetParentDoc({\r\n docsByID: allDocsByID,\r\n dropTarget,\r\n })\r\n const dropValidation = getManualOrderDropValidation({\r\n activeDoc,\r\n targetDoc: targetDoc ?? undefined,\r\n })\r\n\r\n if (!dropValidation.isValid) {\r\n if (!shouldSilenceMoveMessage(dropValidation.message)) {\r\n toast.error(dropValidation.message ?? 'Could not move document.')\r\n }\r\n\r\n return\r\n }\r\n\r\n const placement = getOrderPlacementFromDropTarget({\r\n activeDoc,\r\n docs: paginatedDocs,\r\n docsByID: allDocsByID,\r\n dropTarget,\r\n })\r\n\r\n if (!placement) {\r\n return\r\n }\r\n\r\n const currentPlacement = getCurrentOrderPlacement({\r\n activeDoc,\r\n docs: paginatedDocs,\r\n })\r\n const parentChanged = activeDoc.__pageTreeParentID !== placement.parentID\r\n const orderChanged = orderPlacementHasChanged(currentPlacement, placement)\r\n const reorderTarget = orderChanged\r\n ? getReorderTargetFromPlacement({\r\n currentSort,\r\n docsByID: allDocsByID,\r\n orderableFieldName,\r\n placement,\r\n })\r\n : null\r\n\r\n if (!parentChanged && !reorderTarget) {\r\n return\r\n }\r\n\r\n const movedDocID = getPayloadDocID(activeDoc)\r\n\r\n if (movedDocID === undefined) {\r\n return\r\n }\r\n\r\n const parentDoc = placement.parentID ? allDocsByID.get(placement.parentID) : undefined\r\n const nextParentValue =\r\n placement.parentID === null\r\n ? null\r\n : parentDoc\r\n ? getPayloadDocID(parentDoc) ?? placement.parentID\r\n : placement.parentID\r\n let parentMoveSucceeded = false\r\n\r\n setPendingMoveRowID(rowID)\r\n\r\n try {\r\n if (parentChanged) {\r\n await moveDocument({\r\n parentID: placement.parentID,\r\n rowID,\r\n })\r\n parentMoveSucceeded = true\r\n }\r\n\r\n const nextOrderValue = reorderTarget\r\n ? await reorderDocument({\r\n movedDocID,\r\n newKeyWillBe: reorderTarget.newKeyWillBe,\r\n targetDoc: reorderTarget.targetDoc,\r\n })\r\n : undefined\r\n\r\n if (parentChanged || typeof nextOrderValue === 'string') {\r\n setLocalSourceDocs((currentDocs) =>\r\n currentDocs.map((doc) =>\r\n String(doc.id ?? '') === String(movedDocID)\r\n ? {\r\n ...doc,\r\n ...(parentChanged\r\n ? {\r\n [parentFieldSlug]: nextParentValue,\r\n }\r\n : {}),\r\n ...(typeof nextOrderValue === 'string'\r\n ? {\r\n [orderableFieldName]: nextOrderValue,\r\n }\r\n : {}),\r\n }\r\n : doc,\r\n ),\r\n )\r\n }\r\n\r\n if (parentChanged) {\r\n toast.success(`Moved \"${getDocDisplayLabel(activeDoc)}\".`)\r\n }\r\n\r\n React.startTransition(() => {\r\n router.refresh()\r\n })\r\n } catch (error) {\r\n const message =\r\n error instanceof Error && error.message ? error.message : 'Could not move document.'\r\n\r\n toast.error(\r\n parentMoveSucceeded\r\n ? `Moved \"${getDocDisplayLabel(activeDoc)}\", but could not update its manual order. ${message}`\r\n : message,\r\n )\r\n\r\n if (parentMoveSucceeded) {\r\n React.startTransition(() => {\r\n router.refresh()\r\n })\r\n }\r\n } finally {\r\n setPendingMoveRowID(null)\r\n }\r\n },\r\n [\r\n allDocsByID,\r\n currentSort,\r\n moveDocument,\r\n orderableFieldName,\r\n paginatedDocs,\r\n parentFieldSlug,\r\n reorderDocument,\r\n router,\r\n ],\r\n )\r\n const handleDragCancel = React.useCallback(() => {\r\n setActiveDragRowID(null)\r\n setActiveDropTarget(null)\r\n }, [])\r\n const handleDragStart = React.useCallback(\r\n (event: DragStartEvent) => {\r\n const dragData = getPageTreeDragData(event.active.data.current)\r\n\r\n if (!canMoveDocs || isMovePending) {\r\n return\r\n }\r\n\r\n const rowID = dragData.rowID\r\n\r\n if (typeof rowID === 'string' && paginatedDocsByID.has(rowID)) {\r\n setActiveDragRowID(rowID)\r\n setActiveDropTarget(null)\r\n }\r\n },\r\n [canMoveDocs, isMovePending, paginatedDocsByID],\r\n )\r\n const handleDragOver = React.useCallback((event: DragOverEvent) => {\r\n const overData = event.over?.data.current as PageTreeDropTarget | undefined\r\n\r\n if (!overData) {\r\n setActiveDropTarget(null)\r\n return\r\n }\r\n\r\n if (overData.dropType === 'insert') {\r\n setActiveDropTarget(overData)\r\n return\r\n }\r\n\r\n if (overData.dropType === 'row') {\r\n setActiveDropTarget(overData)\r\n return\r\n }\r\n\r\n setActiveDropTarget(null)\r\n }, [])\r\n const handleDragEnd = React.useCallback(\r\n async (event: DragEndEvent) => {\r\n const dragData = getPageTreeDragData(event.active.data.current)\r\n\r\n const rowID = dragData.rowID\r\n const activeDoc = typeof rowID === 'string' ? paginatedDocsByID.get(rowID) ?? null : null\r\n const overData = event.over?.data.current as PageTreeDropTarget | undefined\r\n\r\n setActiveDragRowID(null)\r\n setActiveDropTarget(null)\r\n\r\n if (!rowID || !activeDoc || !overData) {\r\n return\r\n }\r\n\r\n if (manualOrderIsActive && orderableFieldName) {\r\n await handleManualOrderMoveEnd({\r\n activeDoc,\r\n dropTarget: overData,\r\n rowID,\r\n })\r\n return\r\n }\r\n\r\n const targetDoc = getDropTargetParentDoc({\r\n docsByID: allDocsByID,\r\n dropTarget: overData,\r\n })\r\n const dropValidation = getDropValidation({\r\n activeDoc,\r\n targetDoc: targetDoc ?? undefined,\r\n })\r\n\r\n if (!dropValidation.isValid) {\r\n if (!shouldSilenceMoveMessage(dropValidation.message)) {\r\n toast.error(dropValidation.message ?? 'Could not move document.')\r\n }\r\n\r\n return\r\n }\r\n\r\n setPendingMoveRowID(rowID)\r\n\r\n try {\r\n await moveDocument({\r\n parentID: dropValidation.parentID,\r\n rowID,\r\n })\r\n\r\n toast.success(`Moved \"${getDocDisplayLabel(activeDoc)}\".`)\r\n React.startTransition(() => {\r\n router.refresh()\r\n })\r\n } catch (error) {\r\n const message =\r\n error instanceof Error && error.message ? error.message : 'Could not move document.'\r\n\r\n if (shouldSilenceMoveMessage(message)) {\r\n return\r\n }\r\n\r\n toast.error(message)\r\n } finally {\r\n setPendingMoveRowID(null)\r\n }\r\n },\r\n [\r\n allDocsByID,\r\n handleManualOrderMoveEnd,\r\n manualOrderIsActive,\r\n moveDocument,\r\n orderableFieldName,\r\n paginatedDocsByID,\r\n router,\r\n ],\r\n )\r\n const handleDragEndSync = React.useCallback(\r\n (event: DragEndEvent) => {\r\n void handleDragEnd(event)\r\n },\r\n [handleDragEnd],\r\n )\r\n\r\n const tableNode = React.useMemo(\r\n () => (\r\n <DndContext\r\n collisionDetection={pageTreeCollisionDetectionStrategy}\r\n onDragCancel={handleDragCancel}\r\n onDragEnd={handleDragEndSync}\r\n onDragOver={handleDragOver}\r\n onDragStart={handleDragStart}\r\n sensors={sensors}\r\n >\r\n <HierarchyTable\r\n activeDragRowID={activeDragRowID}\r\n allDocsByID={allDocsByID}\r\n allowSameParentDrops={manualOrderIsActive}\r\n columns={tableColumns}\r\n data={paginatedDocs}\r\n isMovePending={isMovePending}\r\n titleCellAccessor={useAsTitle}\r\n />\r\n <DragOverlay dropAnimation={null} style={{ cursor: 'grabbing' }}>\r\n {activeDragPreviewPath ? (\r\n <div className=\"pages-hierarchy-drag-overlay\">{activeDragPreviewPath}</div>\r\n ) : null}\r\n </DragOverlay>\r\n </DndContext>\r\n ),\r\n [\r\n activeDragPreviewPath,\r\n activeDragRowID,\r\n handleDragCancel,\r\n handleDragEndSync,\r\n handleDragOver,\r\n handleDragStart,\r\n isMovePending,\r\n allDocsByID,\r\n manualOrderIsActive,\r\n paginatedDocs,\r\n sensors,\r\n tableColumns,\r\n useAsTitle,\r\n ],\r\n )\r\n\r\n return (\r\n <div className={styles.root}>\r\n <PageTreeProvider value={hierarchyValue}>\r\n <ListQueryProvider\r\n collectionSlug={props.collectionSlug}\r\n data={paginatedData}\r\n modifySearchParams\r\n orderableFieldName={orderableFieldName}\r\n query={{\r\n ...query,\r\n limit: currentLimit,\r\n page: paginatedData.page,\r\n sort: currentSort,\r\n }}\r\n >\r\n <DefaultListView {...props} columnState={paginatedColumnState} Table={tableNode} />\r\n </ListQueryProvider>\r\n </PageTreeProvider>\r\n </div>\r\n )\r\n}\r\n"],"names":["DndContext","DragOverlay","PointerSensor","useDroppable","useSensor","useSensors","DefaultListView","ListQueryProvider","SelectAll","SelectRow","SortHeader","toast","useConfig","useLocale","useTranslation","useRouter","useSearchParams","React","pageTreeMoveRequestHeader","pageTreeMoveRequestHeaderValue","buildInsertDropTargets","getDropTargetParentDoc","getOrderPlacementFromDropTarget","CANCEL_DRAG_MESSAGE","getDropValidation","buildDocSlugPath","buildPageTreeDocs","buildProspectiveDocSlugPath","getDocDisplayLabel","getVisibleTreeDocs","pageTreeCollisionDetectionStrategy","getPageTreeBadgeColor","getPageTreeBadgeLabel","getPageTreeDisplayStatus","PageTreeProvider","styles","PageTreeTitleCell","MANUAL_ORDER_COLUMN_ACCESSOR","SILENT_MOVE_MESSAGES","Set","getRowDropID","rowID","getPageTreeDragData","value","getPayloadDocID","doc","id","undefined","getManualOrderDropValidation","args","activeDoc","targetDoc","isValid","parentID","__pageTreeID","message","__pageTreeAncestorIDs","includes","getDropValidationForMode","allowSameParent","getCurrentOrderPlacement","docs","activeIndex","findIndex","movingSubtreeIDs","filter","map","siblingIsNotMoving","__pageTreeParentID","has","nextSiblingID","previousSiblingID","slice","find","at","orderPlacementHasChanged","currentPlacement","nextPlacement","getReorderTargetFromPlacement","currentSort","docsByID","orderableFieldName","placement","targetDocID","get","newKeyWillBe","buildPaginatedData","limit","requestedPage","totalDocs","length","totalPages","Math","max","ceil","page","min","startIndex","pageDocs","hasNextPage","hasPrevPage","nextPage","pagingCounter","prevPage","normalizeSort","Array","isArray","sortValues","entry","join","normalizePositiveInt","fallback","parsedValue","Number","parseInt","isNaN","normalizePageTreeColumnState","columnState","useAsTitle","column","accessor","active","sliceColumnState","renderedCellIndexByDocID","renderedCells","renderedCellIndex","__pageTreeOrderIndex","getSelectableRowData","record","String","_isLocked","Boolean","_userEditing","shouldSilenceMoveMessage","getStatusClassName","status","renderStatusBadge","badgeConfig","index","t","customColor","badgeColors","colors","statusClass","style","span","className","data-custom-color","badgeLabels","labels","createManualOrderColumn","field","hidden","Heading","insertManualOrderColumn","columns","orderColumn","selectColumnIndex","insertIndex","buildTableColumns","enableRowSelections","homeIndicatorEnabled","parentFieldSlug","columnsToUse","unshift","rowData","some","HierarchyInsertRow","activeColumnsCount","activeDragRowID","dropTarget","dropValidation","isMovePending","isOver","setNodeRef","dropID","data","disabled","hasActiveDrag","tr","data-drag-over","data-drop-valid","data-page-tree-insert","td","colSpan","div","data-insert-depth","depth","ref","HierarchyTableRow","activeColumns","insertAfterDropID","insertBeforeDropID","rowIndex","titleCellAccessor","dropType","isActiveDragRow","data-id","data-is-drag-source","data-page-tree-row","columnIndex","replace","data-page-tree-manual-order-cell","data-page-tree-title-cell","HierarchyTable","allDocsByID","allowSameParentDrops","useMemo","hasManualOrderColumn","insertDropTargets","rowDropValidationByID","Map","insertDropValidationByID","data-page-tree-orderable","table","cellPadding","cellSpacing","thead","th","tbody","Fragment","PageTreeListViewClient","allDocs","canMoveDocs","query","sourceDocs","props","router","searchParams","config","locale","i18n","setActiveDragRowID","useState","activeDropTarget","setActiveDropTarget","collapsedIDs","setCollapsedIDs","localSourceDocs","setLocalSourceDocs","pendingMoveRowID","setPendingMoveRowID","useEffect","toggleRow","useCallback","currentState","nextState","delete","add","searchParamSort","getAll","sort","manualOrderIsActive","currentLimit","currentRequestedPage","liveAllDocs","collapseResetKey","JSON","stringify","collectionSlug","viewType","toString","hierarchyValue","visibleDocs","paginatedData","paginatedDocs","paginatedDocsByID","normalizedColumnState","paginatedColumnState","tableColumns","activeDragDoc","activeDragPreviewPath","sensors","activationConstraint","distance","moveDocument","params","URLSearchParams","code","set","response","fetch","routes","api","encodeURIComponent","size","body","credentials","headers","language","method","result","json","catch","ok","Error","reorderDocument","movedDocID","targetID","docsToMove","target","key","orderValues","handleManualOrderMoveEnd","error","parentChanged","orderChanged","reorderTarget","parentDoc","nextParentValue","parentMoveSucceeded","nextOrderValue","currentDocs","success","startTransition","refresh","handleDragCancel","handleDragStart","event","dragData","current","handleDragOver","overData","over","handleDragEnd","handleDragEndSync","tableNode","collisionDetection","onDragCancel","onDragEnd","onDragOver","onDragStart","dropAnimation","cursor","root","modifySearchParams","Table"],"mappings":"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"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { CANCEL_DRAG_MESSAGE } from '../utilities/moveValidation.js';
|
|
2
2
|
import { buildChildrenByParentID, collectDescendantIDs, getDocParentID, stringifyDocID } from '../utilities/pageTree.js';
|
|
3
|
+
import { pageTreeMoveContextKey } from '../types.js';
|
|
3
4
|
function respond(status, body) {
|
|
4
5
|
return Response.json(body, {
|
|
5
6
|
status
|
|
@@ -234,6 +235,9 @@ export function createMovePageEndpoint(args) {
|
|
|
234
235
|
}
|
|
235
236
|
await req.payload.update({
|
|
236
237
|
collection: collectionSlug,
|
|
238
|
+
context: {
|
|
239
|
+
[pageTreeMoveContextKey]: true
|
|
240
|
+
},
|
|
237
241
|
data: {
|
|
238
242
|
[parentFieldSlug]: body.parentID === null ? null : toCollectionID({
|
|
239
243
|
collectionSlug,
|
|
@@ -1 +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":"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"}
|
|
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 { pageTreeMoveContextKey, 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 context: {\r\n [pageTreeMoveContextKey]: true,\r\n },\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","pageTreeMoveContextKey","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","context","ok","method","path"],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Config } from 'payload';
|
|
2
2
|
import type { NestedDocsPageTreePluginConfig } from './types.js';
|
|
3
|
-
export type { NestedDocsPageTreePluginBadgeConfig, NestedDocsPageTreePluginBadgeMap, NestedDocsPageTreePluginBadgeStatus, NestedDocsPageTreePluginConfig, NestedDocsPageTreePluginHomeIndicatorConfig, } from './types.js';
|
|
3
|
+
export type { NestedDocsPageTreePluginBadgeConfig, NestedDocsPageTreePluginBadgeMap, NestedDocsPageTreePluginBadgeStatus, NestedDocsPageTreePluginConfig, NestedDocsPageTreePluginHomeIndicatorConfig, PageTreeMoveContext, } from './types.js';
|
|
4
|
+
export { pageTreeMoveContextKey } from './types.js';
|
|
4
5
|
export declare const nestedDocsPageTreePlugin: (pluginOptions: NestedDocsPageTreePluginConfig) => (config: Config) => Config;
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createMovePageEndpoint } from './endpoints/createMovePageEndpoint.js';
|
|
2
|
-
import { nestedDocsPageTreePluginCustomKey } from './types.js';
|
|
2
|
+
import { nestedDocsPageTreePluginCustomKey, pageTreeMoveContextKey, pageTreeMoveRequestHeader, pageTreeMoveRequestHeaderValue } from './types.js';
|
|
3
3
|
import { normalizeNestedDocsPageTreePluginBadgeConfig } from './utilities/badgeConfig.js';
|
|
4
4
|
const DEFAULT_BREADCRUMBS_FIELD_SLUG = 'breadcrumbs';
|
|
5
5
|
const DEFAULT_HOME_INDICATOR_COLLECTIONS = [
|
|
@@ -8,6 +8,25 @@ const DEFAULT_HOME_INDICATOR_COLLECTIONS = [
|
|
|
8
8
|
const DEFAULT_LIMIT = 100;
|
|
9
9
|
const DEFAULT_PARENT_FIELD_SLUG = 'parent';
|
|
10
10
|
const PAGE_TREE_LIST_VIEW_PATH = 'payload-nested-docs-page-tree/rsc#NestedDocsPageTreeListView';
|
|
11
|
+
// Page-tree owns parent moves, so those pass Local API context directly.
|
|
12
|
+
// Reorders go through Payload's shared /api/reorder endpoint; this hook
|
|
13
|
+
// bridges the plugin-owned request signal into the same hook context flag.
|
|
14
|
+
// The bridge requires an authenticated request — the header alone is not a
|
|
15
|
+
// trust boundary, but rejecting anonymous callers closes the only path that
|
|
16
|
+
// could set the flag without already holding update access.
|
|
17
|
+
const tagPageTreeMoveContextHook = ({ data, req })=>{
|
|
18
|
+
if (req.headers?.get(pageTreeMoveRequestHeader) !== pageTreeMoveRequestHeaderValue) {
|
|
19
|
+
return data;
|
|
20
|
+
}
|
|
21
|
+
if (!req.user) {
|
|
22
|
+
return data;
|
|
23
|
+
}
|
|
24
|
+
if (!req.context) {
|
|
25
|
+
req.context = {};
|
|
26
|
+
}
|
|
27
|
+
req.context[pageTreeMoveContextKey] = true;
|
|
28
|
+
return data;
|
|
29
|
+
};
|
|
11
30
|
function getTopLevelField(collection, fieldName) {
|
|
12
31
|
return collection.fields.find((field)=>'name' in field && field.name === fieldName);
|
|
13
32
|
}
|
|
@@ -69,6 +88,7 @@ function getHomeIndicatorCollectionSlugs(homeIndicator) {
|
|
|
69
88
|
}
|
|
70
89
|
return new Set(homeIndicator?.collections ?? DEFAULT_HOME_INDICATOR_COLLECTIONS);
|
|
71
90
|
}
|
|
91
|
+
export { pageTreeMoveContextKey } from './types.js';
|
|
72
92
|
export const nestedDocsPageTreePlugin = (pluginOptions)=>(config)=>{
|
|
73
93
|
if (!pluginOptions.collections?.length) {
|
|
74
94
|
throw new Error('payload-nested-docs-page-tree requires at least one collection slug.');
|
|
@@ -140,7 +160,14 @@ export const nestedDocsPageTreePlugin = (pluginOptions)=>(config)=>{
|
|
|
140
160
|
breadcrumbsFieldSlug,
|
|
141
161
|
field,
|
|
142
162
|
hideBreadcrumbs
|
|
143
|
-
}))
|
|
163
|
+
})),
|
|
164
|
+
hooks: collection.orderable ? {
|
|
165
|
+
...collection.hooks ?? {},
|
|
166
|
+
beforeChange: [
|
|
167
|
+
tagPageTreeMoveContextHook,
|
|
168
|
+
...collection.hooks?.beforeChange ?? []
|
|
169
|
+
]
|
|
170
|
+
} : collection.hooks
|
|
144
171
|
};
|
|
145
172
|
});
|
|
146
173
|
const missingCollections = pluginOptions.collections.filter((collectionSlug)=>!foundCollectionSlugs.has(collectionSlug));
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import type { CollectionConfig, Config } from 'payload'\r\n\r\nimport { createMovePageEndpoint } from './endpoints/createMovePageEndpoint.js'\r\nimport type {\r\n NestedDocsPageTreePluginCollectionCustom,\r\n NestedDocsPageTreePluginConfig,\r\n} from './types.js'\r\nimport { nestedDocsPageTreePluginCustomKey } from './types.js'\r\nimport { normalizeNestedDocsPageTreePluginBadgeConfig } from './utilities/badgeConfig.js'\r\n\r\nconst DEFAULT_BREADCRUMBS_FIELD_SLUG = 'breadcrumbs'\nconst DEFAULT_HOME_INDICATOR_COLLECTIONS = ['pages']\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\r\nfunction getTopLevelField(\r\n collection: Pick<CollectionConfig, 'fields'>,\r\n fieldName: string,\r\n) {\r\n return collection.fields.find((field) => 'name' in field && field.name === fieldName)\r\n}\r\n\r\nfunction getCollectionEndpoints(collection: CollectionConfig): CollectionEndpoint[] {\r\n return Array.isArray(collection.endpoints) ? [...collection.endpoints] : []\r\n}\r\n\r\nfunction patchBreadcrumbField<TField extends CollectionConfig['fields'][number]>(args: {\r\n breadcrumbsFieldSlug: string\r\n field: TField\r\n hideBreadcrumbs: boolean\r\n}): TField {\r\n const { breadcrumbsFieldSlug, field, hideBreadcrumbs } = args\r\n\r\n if (!('name' in field) || field.name !== breadcrumbsFieldSlug) {\r\n return field\r\n }\r\n\r\n return {\r\n ...field,\r\n admin: {\r\n ...(field.admin ?? {}),\r\n hidden: hideBreadcrumbs,\r\n },\r\n } as TField\r\n}\r\n\r\nfunction validateTargetCollection(args: {\r\n breadcrumbsFieldSlug: string\r\n collection: CollectionConfig\r\n parentFieldSlug: string\r\n}) {\r\n const { breadcrumbsFieldSlug, collection, parentFieldSlug } = args\r\n\r\n if (typeof collection.admin?.useAsTitle !== 'string' || collection.admin.useAsTitle.includes('.')) {\r\n throw new Error(\r\n `payload-nested-docs-page-tree requires \"${collection.slug}\" to define a top-level admin.useAsTitle field.`,\r\n )\r\n }\r\n\r\n if (!getTopLevelField(collection, collection.admin.useAsTitle)) {\r\n throw new Error(\r\n `payload-nested-docs-page-tree could not find the useAsTitle field \"${collection.admin.useAsTitle}\" on \"${collection.slug}\".`,\r\n )\r\n }\r\n\r\n if (!getTopLevelField(collection, parentFieldSlug)) {\r\n throw new Error(\r\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.`,\r\n )\r\n }\r\n\r\n if (!getTopLevelField(collection, breadcrumbsFieldSlug)) {\r\n throw new Error(\r\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.`,\r\n )\r\n }\r\n\r\n const existingListView = collection.admin?.components?.views?.list?.Component\r\n\r\n if (existingListView && existingListView !== PAGE_TREE_LIST_VIEW_PATH) {\r\n throw new Error(\r\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.`,\r\n )\r\n }\r\n\r\n const existingMoveEndpoint = getCollectionEndpoints(collection).find(\r\n (endpoint) => endpoint.path === '/:id/move',\r\n )\r\n\r\n if (existingMoveEndpoint) {\r\n throw new Error(\r\n `payload-nested-docs-page-tree cannot add the move endpoint to \"${collection.slug}\" because the collection already defines POST /:id/move.`,\r\n )\r\n }\r\n}\r\n\r\nfunction buildCollectionCustom(args: {\n badges: NestedDocsPageTreePluginCollectionCustom['badges']\n breadcrumbsFieldSlug: string\n defaultLimit: number\n hideBreadcrumbs: boolean\n homeIndicator: NestedDocsPageTreePluginCollectionCustom['homeIndicator']\n parentFieldSlug: string\n}): NestedDocsPageTreePluginCollectionCustom {\n const {\n badges,\n breadcrumbsFieldSlug,\n defaultLimit,\n hideBreadcrumbs,\n homeIndicator,\n parentFieldSlug,\n } = args\n\n return {\n badges,\n breadcrumbsFieldSlug,\n defaultLimit,\n hideBreadcrumbs,\n homeIndicator,\n parentFieldSlug,\n }\n}\n\nfunction getHomeIndicatorCollectionSlugs(\n homeIndicator: NestedDocsPageTreePluginConfig['homeIndicator'],\n): Set<string> {\n if (homeIndicator === false) {\n return new Set()\n }\n\n return new Set(homeIndicator?.collections ?? DEFAULT_HOME_INDICATOR_COLLECTIONS)\n}\n\r\nexport type {\r\n NestedDocsPageTreePluginBadgeConfig,\n NestedDocsPageTreePluginBadgeMap,\n NestedDocsPageTreePluginBadgeStatus,\n NestedDocsPageTreePluginConfig,\n NestedDocsPageTreePluginHomeIndicatorConfig,\n} from './types.js'\n\r\nexport const nestedDocsPageTreePlugin =\r\n (pluginOptions: NestedDocsPageTreePluginConfig) =>\r\n (config: Config): Config => {\r\n if (!pluginOptions.collections?.length) {\r\n throw new Error('payload-nested-docs-page-tree requires at least one collection slug.')\r\n }\r\n\r\n if (pluginOptions.disabled) {\r\n return config\r\n }\r\n\r\n const breadcrumbsFieldSlug =\r\n pluginOptions.breadcrumbsFieldSlug ?? DEFAULT_BREADCRUMBS_FIELD_SLUG\r\n const defaultLimit = pluginOptions.defaultLimit ?? DEFAULT_LIMIT\r\n const hideBreadcrumbs = pluginOptions.hideBreadcrumbs ?? true\n const parentFieldSlug = pluginOptions.parentFieldSlug ?? DEFAULT_PARENT_FIELD_SLUG\n const badges = normalizeNestedDocsPageTreePluginBadgeConfig(pluginOptions.badges)\n const homeIndicatorCollectionSlugs = getHomeIndicatorCollectionSlugs(\n pluginOptions.homeIndicator,\n )\n const targetedCollectionSlugs = new Set<string>(pluginOptions.collections)\n\r\n if (!config.collections?.length) {\r\n throw new Error('payload-nested-docs-page-tree could not find any collections to patch.')\r\n }\r\n\r\n const foundCollectionSlugs = new Set<string>()\r\n const nextCollections = config.collections.map((collection) => {\r\n if (!targetedCollectionSlugs.has(collection.slug)) {\r\n return collection\r\n }\r\n\r\n foundCollectionSlugs.add(collection.slug)\r\n validateTargetCollection({\r\n breadcrumbsFieldSlug,\r\n collection,\r\n parentFieldSlug,\r\n })\r\n\r\n return {\r\n ...collection,\r\n admin: {\r\n ...(collection.admin ?? {}),\r\n components: {\r\n ...(collection.admin?.components ?? {}),\r\n views: {\r\n ...(collection.admin?.components?.views ?? {}),\r\n list: {\r\n ...(collection.admin?.components?.views?.list ?? {}),\r\n Component: PAGE_TREE_LIST_VIEW_PATH,\r\n },\r\n },\r\n },\r\n pagination: {\r\n ...(collection.admin?.pagination ?? {}),\r\n defaultLimit:\r\n collection.admin?.pagination?.defaultLimit === undefined\r\n ? defaultLimit\r\n : collection.admin.pagination.defaultLimit,\r\n },\r\n },\r\n custom: {\r\n ...(collection.custom ?? {}),\r\n [nestedDocsPageTreePluginCustomKey]: buildCollectionCustom({\n badges,\n breadcrumbsFieldSlug,\n defaultLimit,\n hideBreadcrumbs,\n homeIndicator: {\n enabled: homeIndicatorCollectionSlugs.has(collection.slug),\n },\n parentFieldSlug,\n }),\n },\n endpoints: [\r\n ...getCollectionEndpoints(collection),\r\n createMovePageEndpoint({\r\n collectionSlug: collection.slug,\r\n parentFieldSlug,\r\n }),\r\n ],\r\n fields: collection.fields.map((field) =>\r\n patchBreadcrumbField({\r\n breadcrumbsFieldSlug,\r\n field,\r\n hideBreadcrumbs,\r\n }),\r\n ),\r\n }\r\n })\r\n\r\n const missingCollections = pluginOptions.collections.filter(\r\n (collectionSlug) => !foundCollectionSlugs.has(collectionSlug),\r\n )\r\n\r\n if (missingCollections.length > 0) {\r\n throw new Error(\r\n `payload-nested-docs-page-tree could not find the following collections: ${missingCollections.join(', ')}`,\r\n )\r\n }\r\n\r\n return {\r\n ...config,\r\n collections: nextCollections as CollectionConfig[],\r\n }\r\n }\r\n"],"names":["createMovePageEndpoint","nestedDocsPageTreePluginCustomKey","normalizeNestedDocsPageTreePluginBadgeConfig","DEFAULT_BREADCRUMBS_FIELD_SLUG","DEFAULT_HOME_INDICATOR_COLLECTIONS","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","homeIndicator","getHomeIndicatorCollectionSlugs","Set","collections","nestedDocsPageTreePlugin","pluginOptions","config","length","disabled","homeIndicatorCollectionSlugs","targetedCollectionSlugs","foundCollectionSlugs","nextCollections","map","has","add","pagination","undefined","custom","enabled","collectionSlug","missingCollections","filter","join"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import type { CollectionBeforeChangeHook, CollectionConfig, Config } from 'payload'\r\n\r\nimport { createMovePageEndpoint } from './endpoints/createMovePageEndpoint.js'\r\nimport type {\r\n NestedDocsPageTreePluginCollectionCustom,\r\n NestedDocsPageTreePluginConfig,\r\n} from './types.js'\r\nimport {\r\n nestedDocsPageTreePluginCustomKey,\r\n pageTreeMoveContextKey,\r\n pageTreeMoveRequestHeader,\r\n pageTreeMoveRequestHeaderValue,\r\n} from './types.js'\r\nimport { normalizeNestedDocsPageTreePluginBadgeConfig } from './utilities/badgeConfig.js'\r\n\r\nconst DEFAULT_BREADCRUMBS_FIELD_SLUG = 'breadcrumbs'\r\nconst DEFAULT_HOME_INDICATOR_COLLECTIONS = ['pages']\r\nconst DEFAULT_LIMIT = 100\r\nconst DEFAULT_PARENT_FIELD_SLUG = 'parent'\r\nconst PAGE_TREE_LIST_VIEW_PATH =\r\n 'payload-nested-docs-page-tree/rsc#NestedDocsPageTreeListView'\r\ntype CollectionEndpoint = NonNullable<Exclude<CollectionConfig['endpoints'], false>>[number]\r\n\r\n// Page-tree owns parent moves, so those pass Local API context directly.\r\n// Reorders go through Payload's shared /api/reorder endpoint; this hook\r\n// bridges the plugin-owned request signal into the same hook context flag.\r\n// The bridge requires an authenticated request — the header alone is not a\r\n// trust boundary, but rejecting anonymous callers closes the only path that\r\n// could set the flag without already holding update access.\r\nconst tagPageTreeMoveContextHook: CollectionBeforeChangeHook = ({ data, req }) => {\r\n if (req.headers?.get(pageTreeMoveRequestHeader) !== pageTreeMoveRequestHeaderValue) {\r\n return data\r\n }\r\n\r\n if (!req.user) {\r\n return data\r\n }\r\n\r\n if (!req.context) {\r\n req.context = {}\r\n }\r\n\r\n req.context[pageTreeMoveContextKey] = true\r\n\r\n return data\r\n}\r\n\r\nfunction getTopLevelField(\r\n collection: Pick<CollectionConfig, 'fields'>,\r\n fieldName: string,\r\n) {\r\n return collection.fields.find((field) => 'name' in field && field.name === fieldName)\r\n}\r\n\r\nfunction getCollectionEndpoints(collection: CollectionConfig): CollectionEndpoint[] {\r\n return Array.isArray(collection.endpoints) ? [...collection.endpoints] : []\r\n}\r\n\r\nfunction patchBreadcrumbField<TField extends CollectionConfig['fields'][number]>(args: {\r\n breadcrumbsFieldSlug: string\r\n field: TField\r\n hideBreadcrumbs: boolean\r\n}): TField {\r\n const { breadcrumbsFieldSlug, field, hideBreadcrumbs } = args\r\n\r\n if (!('name' in field) || field.name !== breadcrumbsFieldSlug) {\r\n return field\r\n }\r\n\r\n return {\r\n ...field,\r\n admin: {\r\n ...(field.admin ?? {}),\r\n hidden: hideBreadcrumbs,\r\n },\r\n } as TField\r\n}\r\n\r\nfunction validateTargetCollection(args: {\r\n breadcrumbsFieldSlug: string\r\n collection: CollectionConfig\r\n parentFieldSlug: string\r\n}) {\r\n const { breadcrumbsFieldSlug, collection, parentFieldSlug } = args\r\n\r\n if (typeof collection.admin?.useAsTitle !== 'string' || collection.admin.useAsTitle.includes('.')) {\r\n throw new Error(\r\n `payload-nested-docs-page-tree requires \"${collection.slug}\" to define a top-level admin.useAsTitle field.`,\r\n )\r\n }\r\n\r\n if (!getTopLevelField(collection, collection.admin.useAsTitle)) {\r\n throw new Error(\r\n `payload-nested-docs-page-tree could not find the useAsTitle field \"${collection.admin.useAsTitle}\" on \"${collection.slug}\".`,\r\n )\r\n }\r\n\r\n if (!getTopLevelField(collection, parentFieldSlug)) {\r\n throw new Error(\r\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.`,\r\n )\r\n }\r\n\r\n if (!getTopLevelField(collection, breadcrumbsFieldSlug)) {\r\n throw new Error(\r\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.`,\r\n )\r\n }\r\n\r\n const existingListView = collection.admin?.components?.views?.list?.Component\r\n\r\n if (existingListView && existingListView !== PAGE_TREE_LIST_VIEW_PATH) {\r\n throw new Error(\r\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.`,\r\n )\r\n }\r\n\r\n const existingMoveEndpoint = getCollectionEndpoints(collection).find(\r\n (endpoint) => endpoint.path === '/:id/move',\r\n )\r\n\r\n if (existingMoveEndpoint) {\r\n throw new Error(\r\n `payload-nested-docs-page-tree cannot add the move endpoint to \"${collection.slug}\" because the collection already defines POST /:id/move.`,\r\n )\r\n }\r\n}\r\n\r\nfunction buildCollectionCustom(args: {\r\n badges: NestedDocsPageTreePluginCollectionCustom['badges']\r\n breadcrumbsFieldSlug: string\r\n defaultLimit: number\r\n hideBreadcrumbs: boolean\r\n homeIndicator: NestedDocsPageTreePluginCollectionCustom['homeIndicator']\r\n parentFieldSlug: string\r\n}): NestedDocsPageTreePluginCollectionCustom {\r\n const {\r\n badges,\r\n breadcrumbsFieldSlug,\r\n defaultLimit,\r\n hideBreadcrumbs,\r\n homeIndicator,\r\n parentFieldSlug,\r\n } = args\r\n\r\n return {\r\n badges,\r\n breadcrumbsFieldSlug,\r\n defaultLimit,\r\n hideBreadcrumbs,\r\n homeIndicator,\r\n parentFieldSlug,\r\n }\r\n}\r\n\r\nfunction getHomeIndicatorCollectionSlugs(\r\n homeIndicator: NestedDocsPageTreePluginConfig['homeIndicator'],\r\n): Set<string> {\r\n if (homeIndicator === false) {\r\n return new Set()\r\n }\r\n\r\n return new Set(homeIndicator?.collections ?? DEFAULT_HOME_INDICATOR_COLLECTIONS)\r\n}\r\n\r\nexport type {\r\n NestedDocsPageTreePluginBadgeConfig,\r\n NestedDocsPageTreePluginBadgeMap,\r\n NestedDocsPageTreePluginBadgeStatus,\r\n NestedDocsPageTreePluginConfig,\r\n NestedDocsPageTreePluginHomeIndicatorConfig,\r\n PageTreeMoveContext,\r\n} from './types.js'\r\n\r\nexport { pageTreeMoveContextKey } from './types.js'\r\n\r\nexport const nestedDocsPageTreePlugin =\r\n (pluginOptions: NestedDocsPageTreePluginConfig) =>\r\n (config: Config): Config => {\r\n if (!pluginOptions.collections?.length) {\r\n throw new Error('payload-nested-docs-page-tree requires at least one collection slug.')\r\n }\r\n\r\n if (pluginOptions.disabled) {\r\n return config\r\n }\r\n\r\n const breadcrumbsFieldSlug =\r\n pluginOptions.breadcrumbsFieldSlug ?? DEFAULT_BREADCRUMBS_FIELD_SLUG\r\n const defaultLimit = pluginOptions.defaultLimit ?? DEFAULT_LIMIT\r\n const hideBreadcrumbs = pluginOptions.hideBreadcrumbs ?? true\r\n const parentFieldSlug = pluginOptions.parentFieldSlug ?? DEFAULT_PARENT_FIELD_SLUG\r\n const badges = normalizeNestedDocsPageTreePluginBadgeConfig(pluginOptions.badges)\r\n const homeIndicatorCollectionSlugs = getHomeIndicatorCollectionSlugs(\r\n pluginOptions.homeIndicator,\r\n )\r\n const targetedCollectionSlugs = new Set<string>(pluginOptions.collections)\r\n\r\n if (!config.collections?.length) {\r\n throw new Error('payload-nested-docs-page-tree could not find any collections to patch.')\r\n }\r\n\r\n const foundCollectionSlugs = new Set<string>()\r\n const nextCollections = config.collections.map((collection) => {\r\n if (!targetedCollectionSlugs.has(collection.slug)) {\r\n return collection\r\n }\r\n\r\n foundCollectionSlugs.add(collection.slug)\r\n validateTargetCollection({\r\n breadcrumbsFieldSlug,\r\n collection,\r\n parentFieldSlug,\r\n })\r\n\r\n return {\r\n ...collection,\r\n admin: {\r\n ...(collection.admin ?? {}),\r\n components: {\r\n ...(collection.admin?.components ?? {}),\r\n views: {\r\n ...(collection.admin?.components?.views ?? {}),\r\n list: {\r\n ...(collection.admin?.components?.views?.list ?? {}),\r\n Component: PAGE_TREE_LIST_VIEW_PATH,\r\n },\r\n },\r\n },\r\n pagination: {\r\n ...(collection.admin?.pagination ?? {}),\r\n defaultLimit:\r\n collection.admin?.pagination?.defaultLimit === undefined\r\n ? defaultLimit\r\n : collection.admin.pagination.defaultLimit,\r\n },\r\n },\r\n custom: {\r\n ...(collection.custom ?? {}),\r\n [nestedDocsPageTreePluginCustomKey]: buildCollectionCustom({\r\n badges,\r\n breadcrumbsFieldSlug,\r\n defaultLimit,\r\n hideBreadcrumbs,\r\n homeIndicator: {\r\n enabled: homeIndicatorCollectionSlugs.has(collection.slug),\r\n },\r\n parentFieldSlug,\r\n }),\r\n },\r\n endpoints: [\r\n ...getCollectionEndpoints(collection),\r\n createMovePageEndpoint({\r\n collectionSlug: collection.slug,\r\n parentFieldSlug,\r\n }),\r\n ],\r\n fields: collection.fields.map((field) =>\r\n patchBreadcrumbField({\r\n breadcrumbsFieldSlug,\r\n field,\r\n hideBreadcrumbs,\r\n }),\r\n ),\r\n hooks: collection.orderable\r\n ? {\r\n ...(collection.hooks ?? {}),\r\n beforeChange: [\r\n tagPageTreeMoveContextHook,\r\n ...(collection.hooks?.beforeChange ?? []),\r\n ],\r\n }\r\n : collection.hooks,\r\n }\r\n })\r\n\r\n const missingCollections = pluginOptions.collections.filter(\r\n (collectionSlug) => !foundCollectionSlugs.has(collectionSlug),\r\n )\r\n\r\n if (missingCollections.length > 0) {\r\n throw new Error(\r\n `payload-nested-docs-page-tree could not find the following collections: ${missingCollections.join(', ')}`,\r\n )\r\n }\r\n\r\n return {\r\n ...config,\r\n collections: nextCollections as CollectionConfig[],\r\n }\r\n }\r\n"],"names":["createMovePageEndpoint","nestedDocsPageTreePluginCustomKey","pageTreeMoveContextKey","pageTreeMoveRequestHeader","pageTreeMoveRequestHeaderValue","normalizeNestedDocsPageTreePluginBadgeConfig","DEFAULT_BREADCRUMBS_FIELD_SLUG","DEFAULT_HOME_INDICATOR_COLLECTIONS","DEFAULT_LIMIT","DEFAULT_PARENT_FIELD_SLUG","PAGE_TREE_LIST_VIEW_PATH","tagPageTreeMoveContextHook","data","req","headers","get","user","context","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","homeIndicator","getHomeIndicatorCollectionSlugs","Set","collections","nestedDocsPageTreePlugin","pluginOptions","config","length","disabled","homeIndicatorCollectionSlugs","targetedCollectionSlugs","foundCollectionSlugs","nextCollections","map","has","add","pagination","undefined","custom","enabled","collectionSlug","hooks","orderable","beforeChange","missingCollections","filter","join"],"mappings":"AAEA,SAASA,sBAAsB,QAAQ,wCAAuC;AAK9E,SACEC,iCAAiC,EACjCC,sBAAsB,EACtBC,yBAAyB,EACzBC,8BAA8B,QACzB,aAAY;AACnB,SAASC,4CAA4C,QAAQ,6BAA4B;AAEzF,MAAMC,iCAAiC;AACvC,MAAMC,qCAAqC;IAAC;CAAQ;AACpD,MAAMC,gBAAgB;AACtB,MAAMC,4BAA4B;AAClC,MAAMC,2BACJ;AAGF,yEAAyE;AACzE,wEAAwE;AACxE,2EAA2E;AAC3E,2EAA2E;AAC3E,4EAA4E;AAC5E,4DAA4D;AAC5D,MAAMC,6BAAyD,CAAC,EAAEC,IAAI,EAAEC,GAAG,EAAE;IAC3E,IAAIA,IAAIC,OAAO,EAAEC,IAAIZ,+BAA+BC,gCAAgC;QAClF,OAAOQ;IACT;IAEA,IAAI,CAACC,IAAIG,IAAI,EAAE;QACb,OAAOJ;IACT;IAEA,IAAI,CAACC,IAAII,OAAO,EAAE;QAChBJ,IAAII,OAAO,GAAG,CAAC;IACjB;IAEAJ,IAAII,OAAO,CAACf,uBAAuB,GAAG;IAEtC,OAAOU;AACT;AAEA,SAASM,iBACPC,UAA4C,EAC5CC,SAAiB;IAEjB,OAAOD,WAAWE,MAAM,CAACC,IAAI,CAAC,CAACC,QAAU,UAAUA,SAASA,MAAMC,IAAI,KAAKJ;AAC7E;AAEA,SAASK,uBAAuBN,UAA4B;IAC1D,OAAOO,MAAMC,OAAO,CAACR,WAAWS,SAAS,IAAI;WAAIT,WAAWS,SAAS;KAAC,GAAG,EAAE;AAC7E;AAEA,SAASC,qBAAwEC,IAIhF;IACC,MAAM,EAAEC,oBAAoB,EAAER,KAAK,EAAES,eAAe,EAAE,GAAGF;IAEzD,IAAI,CAAE,CAAA,UAAUP,KAAI,KAAMA,MAAMC,IAAI,KAAKO,sBAAsB;QAC7D,OAAOR;IACT;IAEA,OAAO;QACL,GAAGA,KAAK;QACRU,OAAO;YACL,GAAIV,MAAMU,KAAK,IAAI,CAAC,CAAC;YACrBC,QAAQF;QACV;IACF;AACF;AAEA,SAASG,yBAAyBL,IAIjC;IACC,MAAM,EAAEC,oBAAoB,EAAEZ,UAAU,EAAEiB,eAAe,EAAE,GAAGN;IAE9D,IAAI,OAAOX,WAAWc,KAAK,EAAEI,eAAe,YAAYlB,WAAWc,KAAK,CAACI,UAAU,CAACC,QAAQ,CAAC,MAAM;QACjG,MAAM,IAAIC,MACR,CAAC,wCAAwC,EAAEpB,WAAWqB,IAAI,CAAC,+CAA+C,CAAC;IAE/G;IAEA,IAAI,CAACtB,iBAAiBC,YAAYA,WAAWc,KAAK,CAACI,UAAU,GAAG;QAC9D,MAAM,IAAIE,MACR,CAAC,mEAAmE,EAAEpB,WAAWc,KAAK,CAACI,UAAU,CAAC,MAAM,EAAElB,WAAWqB,IAAI,CAAC,EAAE,CAAC;IAEjI;IAEA,IAAI,CAACtB,iBAAiBC,YAAYiB,kBAAkB;QAClD,MAAM,IAAIG,MACR,CAAC,wCAAwC,EAAEpB,WAAWqB,IAAI,CAAC,kDAAkD,EAAEJ,gBAAgB,gFAAgF,CAAC;IAEpN;IAEA,IAAI,CAAClB,iBAAiBC,YAAYY,uBAAuB;QACvD,MAAM,IAAIQ,MACR,CAAC,wCAAwC,EAAEpB,WAAWqB,IAAI,CAAC,uDAAuD,EAAET,qBAAqB,gFAAgF,CAAC;IAE9N;IAEA,MAAMU,mBAAmBtB,WAAWc,KAAK,EAAES,YAAYC,OAAOC,MAAMC;IAEpE,IAAIJ,oBAAoBA,qBAAqB/B,0BAA0B;QACrE,MAAM,IAAI6B,MACR,CAAC,8CAA8C,EAAEpB,WAAWqB,IAAI,CAAC,kGAAkG,CAAC;IAExK;IAEA,MAAMM,uBAAuBrB,uBAAuBN,YAAYG,IAAI,CAClE,CAACyB,WAAaA,SAASC,IAAI,KAAK;IAGlC,IAAIF,sBAAsB;QACxB,MAAM,IAAIP,MACR,CAAC,+DAA+D,EAAEpB,WAAWqB,IAAI,CAAC,wDAAwD,CAAC;IAE/I;AACF;AAEA,SAASS,sBAAsBnB,IAO9B;IACC,MAAM,EACJoB,MAAM,EACNnB,oBAAoB,EACpBoB,YAAY,EACZnB,eAAe,EACfoB,aAAa,EACbhB,eAAe,EAChB,GAAGN;IAEJ,OAAO;QACLoB;QACAnB;QACAoB;QACAnB;QACAoB;QACAhB;IACF;AACF;AAEA,SAASiB,gCACPD,aAA8D;IAE9D,IAAIA,kBAAkB,OAAO;QAC3B,OAAO,IAAIE;IACb;IAEA,OAAO,IAAIA,IAAIF,eAAeG,eAAehD;AAC/C;AAWA,SAASL,sBAAsB,QAAQ,aAAY;AAEnD,OAAO,MAAMsD,2BACX,CAACC,gBACD,CAACC;QACC,IAAI,CAACD,cAAcF,WAAW,EAAEI,QAAQ;YACtC,MAAM,IAAIpB,MAAM;QAClB;QAEA,IAAIkB,cAAcG,QAAQ,EAAE;YAC1B,OAAOF;QACT;QAEA,MAAM3B,uBACJ0B,cAAc1B,oBAAoB,IAAIzB;QACxC,MAAM6C,eAAeM,cAAcN,YAAY,IAAI3C;QACnD,MAAMwB,kBAAkByB,cAAczB,eAAe,IAAI;QACzD,MAAMI,kBAAkBqB,cAAcrB,eAAe,IAAI3B;QACzD,MAAMyC,SAAS7C,6CAA6CoD,cAAcP,MAAM;QAChF,MAAMW,+BAA+BR,gCACnCI,cAAcL,aAAa;QAE7B,MAAMU,0BAA0B,IAAIR,IAAYG,cAAcF,WAAW;QAEzE,IAAI,CAACG,OAAOH,WAAW,EAAEI,QAAQ;YAC/B,MAAM,IAAIpB,MAAM;QAClB;QAEA,MAAMwB,uBAAuB,IAAIT;QACjC,MAAMU,kBAAkBN,OAAOH,WAAW,CAACU,GAAG,CAAC,CAAC9C;YAC9C,IAAI,CAAC2C,wBAAwBI,GAAG,CAAC/C,WAAWqB,IAAI,GAAG;gBACjD,OAAOrB;YACT;YAEA4C,qBAAqBI,GAAG,CAAChD,WAAWqB,IAAI;YACxCL,yBAAyB;gBACvBJ;gBACAZ;gBACAiB;YACF;YAEA,OAAO;gBACL,GAAGjB,UAAU;gBACbc,OAAO;oBACL,GAAId,WAAWc,KAAK,IAAI,CAAC,CAAC;oBAC1BS,YAAY;wBACV,GAAIvB,WAAWc,KAAK,EAAES,cAAc,CAAC,CAAC;wBACtCC,OAAO;4BACL,GAAIxB,WAAWc,KAAK,EAAES,YAAYC,SAAS,CAAC,CAAC;4BAC7CC,MAAM;gCACJ,GAAIzB,WAAWc,KAAK,EAAES,YAAYC,OAAOC,QAAQ,CAAC,CAAC;gCACnDC,WAAWnC;4BACb;wBACF;oBACF;oBACA0D,YAAY;wBACV,GAAIjD,WAAWc,KAAK,EAAEmC,cAAc,CAAC,CAAC;wBACtCjB,cACEhC,WAAWc,KAAK,EAAEmC,YAAYjB,iBAAiBkB,YAC3ClB,eACAhC,WAAWc,KAAK,CAACmC,UAAU,CAACjB,YAAY;oBAChD;gBACF;gBACAmB,QAAQ;oBACN,GAAInD,WAAWmD,MAAM,IAAI,CAAC,CAAC;oBAC3B,CAACrE,kCAAkC,EAAEgD,sBAAsB;wBACzDC;wBACAnB;wBACAoB;wBACAnB;wBACAoB,eAAe;4BACbmB,SAASV,6BAA6BK,GAAG,CAAC/C,WAAWqB,IAAI;wBAC3D;wBACAJ;oBACF;gBACF;gBACAR,WAAW;uBACNH,uBAAuBN;oBAC1BnB,uBAAuB;wBACrBwE,gBAAgBrD,WAAWqB,IAAI;wBAC/BJ;oBACF;iBACD;gBACDf,QAAQF,WAAWE,MAAM,CAAC4C,GAAG,CAAC,CAAC1C,QAC7BM,qBAAqB;wBACnBE;wBACAR;wBACAS;oBACF;gBAEFyC,OAAOtD,WAAWuD,SAAS,GACvB;oBACE,GAAIvD,WAAWsD,KAAK,IAAI,CAAC,CAAC;oBAC1BE,cAAc;wBACZhE;2BACIQ,WAAWsD,KAAK,EAAEE,gBAAgB,EAAE;qBACzC;gBACH,IACAxD,WAAWsD,KAAK;YACtB;QACF;QAEA,MAAMG,qBAAqBnB,cAAcF,WAAW,CAACsB,MAAM,CACzD,CAACL,iBAAmB,CAACT,qBAAqBG,GAAG,CAACM;QAGhD,IAAII,mBAAmBjB,MAAM,GAAG,GAAG;YACjC,MAAM,IAAIpB,MACR,CAAC,wEAAwE,EAAEqC,mBAAmBE,IAAI,CAAC,OAAO;QAE9G;QAEA,OAAO;YACL,GAAGpB,MAAM;YACTH,aAAaS;QACf;IACF,EAAC"}
|
package/dist/types.d.ts
CHANGED
|
@@ -41,3 +41,9 @@ export type PageTreeSourceDoc = Record<string, unknown> & {
|
|
|
41
41
|
slug?: null | string;
|
|
42
42
|
};
|
|
43
43
|
export declare const nestedDocsPageTreePluginCustomKey = "nestedDocsPageTreePlugin";
|
|
44
|
+
export declare const pageTreeMoveContextKey = "pageTreeMove";
|
|
45
|
+
export declare const pageTreeMoveRequestHeader = "x-payload-nested-docs-page-tree-move";
|
|
46
|
+
export declare const pageTreeMoveRequestHeaderValue = "true";
|
|
47
|
+
export type PageTreeMoveContext = {
|
|
48
|
+
[pageTreeMoveContextKey]?: boolean;
|
|
49
|
+
};
|
package/dist/types.js
CHANGED
|
@@ -4,5 +4,8 @@ export const nestedDocsPageTreePluginBadgeStatuses = [
|
|
|
4
4
|
'draft'
|
|
5
5
|
];
|
|
6
6
|
export const nestedDocsPageTreePluginCustomKey = 'nestedDocsPageTreePlugin';
|
|
7
|
+
export const pageTreeMoveContextKey = 'pageTreeMove';
|
|
8
|
+
export const pageTreeMoveRequestHeader = 'x-payload-nested-docs-page-tree-move';
|
|
9
|
+
export const pageTreeMoveRequestHeaderValue = 'true';
|
|
7
10
|
|
|
8
11
|
//# sourceMappingURL=types.js.map
|
package/dist/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/types.ts"],"sourcesContent":["import type { CollectionSlug } from 'payload'\
|
|
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 NestedDocsPageTreePluginHomeIndicatorConfig =\n | false\n | {\n collections?: CollectionSlug[]\n }\n\nexport type NestedDocsPageTreePluginResolvedHomeIndicatorConfig = {\n enabled: boolean\n}\n\nexport type NestedDocsPageTreePluginConfig = {\n badges?: NestedDocsPageTreePluginBadgeConfig\n breadcrumbsFieldSlug?: string\n collections: CollectionSlug[]\n defaultLimit?: number\n disabled?: boolean\n hideBreadcrumbs?: boolean\n homeIndicator?: NestedDocsPageTreePluginHomeIndicatorConfig\n parentFieldSlug?: string\n}\n\nexport type NestedDocsPageTreePluginCollectionCustom = {\n badges: NestedDocsPageTreePluginResolvedBadgeConfig\n breadcrumbsFieldSlug: string\n defaultLimit: number\n hideBreadcrumbs: boolean\n homeIndicator: NestedDocsPageTreePluginResolvedHomeIndicatorConfig\n parentFieldSlug: string\n}\n\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\nexport const pageTreeMoveContextKey = 'pageTreeMove'\n\nexport const pageTreeMoveRequestHeader = 'x-payload-nested-docs-page-tree-move'\n\nexport const pageTreeMoveRequestHeaderValue = 'true'\n\nexport type PageTreeMoveContext = {\n [pageTreeMoveContextKey]?: boolean\n}\n"],"names":["nestedDocsPageTreePluginBadgeStatuses","nestedDocsPageTreePluginCustomKey","pageTreeMoveContextKey","pageTreeMoveRequestHeader","pageTreeMoveRequestHeaderValue"],"mappings":"AAEA,OAAO,MAAMA,wCAAwC;IAAC;IAAa;IAAW;CAAQ,CAAS;AAwD/F,OAAO,MAAMC,oCAAoC,2BAA0B;AAE3E,OAAO,MAAMC,yBAAyB,eAAc;AAEpD,OAAO,MAAMC,4BAA4B,uCAAsC;AAE/E,OAAO,MAAMC,iCAAiC,OAAM"}
|
|
@@ -175,10 +175,18 @@ function compareSortValues(leftValue, rightValue) {
|
|
|
175
175
|
}
|
|
176
176
|
return leftValue < rightValue ? -1 : 1;
|
|
177
177
|
}
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
178
|
+
// Plain lexicographic comparison. Required for fractional-indexing keys (e.g. `_order`
|
|
179
|
+
// values like `a5`, `a53`, `a5i`), which encode position as raw lex order — using
|
|
180
|
+
// `localeCompare` with `numeric: true` would interpret digit runs as numbers and
|
|
181
|
+
// produce a different ordering than the database (e.g. `a53 > a5i` numerically vs
|
|
182
|
+
// `a53 < a5i` lexicographically). It also matches MongoDB's default string ordering,
|
|
183
|
+
// so children sort consistently between server-side and client-side.
|
|
184
|
+
const leftString = String(leftValue);
|
|
185
|
+
const rightString = String(rightValue);
|
|
186
|
+
if (leftString === rightString) {
|
|
187
|
+
return 0;
|
|
188
|
+
}
|
|
189
|
+
return leftString < rightString ? -1 : 1;
|
|
182
190
|
}
|
|
183
191
|
function createTreeNodeComparator(sort) {
|
|
184
192
|
const sortTokens = parseSortTokens(sort);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/utilities/pageTree.ts"],"sourcesContent":["import type { PageTreeSourceDoc } from '../types.js'\r\nexport type { PageTreeSourceDoc } from '../types.js'\r\n\r\nexport type PageTreeMeta = {\r\n __pageTreeAncestorIDs: string[]\r\n __pageTreeDepth: number\r\n __pageTreeHasChildren: boolean\r\n __pageTreeID: string\r\n __pageTreeOrderIndex: number\r\n __pageTreeParentID: null | string\r\n __pageTreeShadeLevel: number\r\n}\r\n\r\nexport type PageTreeDoc = PageTreeMeta & PageTreeSourceDoc\r\n\r\ntype SortToken = {\r\n descending: boolean\r\n path: string[]\r\n}\r\n\r\ntype SortValue = null | number | string\r\n\r\ntype TreeNode = {\r\n doc: PageTreeSourceDoc\r\n id: string\r\n originalIndex: number\r\n parentID: null | string\r\n}\r\n\r\nconst dateLikePattern = /^\\d{4}-\\d{2}-\\d{2}(?:[T\\s].*)?$/\r\n\r\nexport type BuildPageTreeDocsOptions = {\r\n parentFieldSlug?: string\r\n sort?: string\r\n}\r\n\r\nexport function stringifyDocID(id: number | string | undefined): string {\r\n return String(id ?? '')\r\n}\r\n\r\nexport function getRelationshipID(value: unknown): null | string {\r\n if (typeof value === 'number' || typeof value === 'string') {\r\n return stringifyDocID(value)\r\n }\r\n\r\n if (value && typeof value === 'object' && 'id' in value) {\r\n const relationshipID = (value as { id?: number | string }).id\r\n\r\n if (typeof relationshipID === 'number' || typeof relationshipID === 'string') {\r\n return stringifyDocID(relationshipID)\r\n }\r\n }\r\n\r\n return null\r\n}\r\n\r\nexport function getDocParentID(\r\n doc: PageTreeSourceDoc,\r\n parentFieldSlug = 'parent',\r\n): null | string {\r\n return getRelationshipID(doc[parentFieldSlug])\r\n}\r\n\r\nexport function getDocDisplayLabel(doc: PageTreeDoc): string {\r\n const title = doc.title\r\n\r\n if (typeof title === 'string' && title.trim().length > 0) {\r\n return title\r\n }\r\n\r\n if (typeof doc.slug === 'string' && doc.slug.trim().length > 0) {\r\n return doc.slug\r\n }\r\n\r\n return doc.__pageTreeID\r\n}\r\n\r\nexport function getDocSlugSegment(doc: PageTreeDoc): string {\r\n if (typeof doc.slug === 'string' && doc.slug.trim().length > 0) {\r\n return doc.slug.trim().replace(/^\\/+|\\/+$/g, '')\r\n }\r\n\r\n return doc.__pageTreeID\r\n}\r\n\r\nexport function buildDocSlugPath(args: {\r\n doc: PageTreeDoc\r\n docsByID: Map<string, PageTreeDoc>\r\n}): string {\r\n const { doc, docsByID } = args\r\n const segments = doc.__pageTreeAncestorIDs\r\n .map((ancestorID) => docsByID.get(ancestorID))\r\n .filter((ancestorDoc): ancestorDoc is PageTreeDoc => Boolean(ancestorDoc))\r\n .map(getDocSlugSegment)\r\n\r\n segments.push(getDocSlugSegment(doc))\r\n\r\n return `/${segments.filter(Boolean).join('/')}`\r\n}\r\n\r\nexport function buildProspectiveDocSlugPath(args: {\r\n activeDoc: PageTreeDoc\r\n docsByID: Map<string, PageTreeDoc>\r\n targetDoc?: PageTreeDoc\r\n}): string {\r\n const { activeDoc, docsByID, targetDoc } = args\r\n\r\n if (!targetDoc) {\r\n return `/${getDocSlugSegment(activeDoc)}`\r\n }\r\n\r\n const segments = targetDoc.__pageTreeAncestorIDs\r\n .map((ancestorID) => docsByID.get(ancestorID))\r\n .filter((ancestorDoc): ancestorDoc is PageTreeDoc => Boolean(ancestorDoc))\r\n .map(getDocSlugSegment)\r\n\r\n segments.push(getDocSlugSegment(targetDoc), getDocSlugSegment(activeDoc))\r\n\r\n return `/${segments.filter(Boolean).join('/')}`\r\n}\r\n\r\nexport function buildChildrenByParentID(args: {\r\n docs: PageTreeSourceDoc[]\r\n parentFieldSlug?: string\r\n}): Map<null | string, string[]> {\r\n const { docs, parentFieldSlug = 'parent' } = args\r\n const childrenByParentID = new Map<null | string, string[]>()\r\n\r\n for (const doc of docs) {\r\n const docID = stringifyDocID(doc.id)\r\n const parentID = getDocParentID(doc, parentFieldSlug)\r\n const existingChildren = childrenByParentID.get(parentID) ?? []\r\n\r\n existingChildren.push(docID)\r\n childrenByParentID.set(parentID, existingChildren)\r\n }\r\n\r\n return childrenByParentID\r\n}\r\n\r\nexport function collectDescendantIDs(\r\n rootID: string,\r\n childrenByParentID: Map<null | string, string[]>,\r\n): string[] {\r\n const descendantIDs: string[] = []\r\n const stack = [...(childrenByParentID.get(rootID) ?? [])]\r\n\r\n while (stack.length > 0) {\r\n const currentID = stack.pop()\r\n\r\n if (!currentID) {\r\n continue\r\n }\r\n\r\n descendantIDs.push(currentID)\r\n stack.push(...(childrenByParentID.get(currentID) ?? []))\r\n }\r\n\r\n return descendantIDs\r\n}\r\n\r\nfunction getCycleNodeIDs(nodes: TreeNode[], nodesByID: Map<string, TreeNode>): Set<string> {\r\n const cycleNodeIDs = new Set<string>()\r\n const pathStack: string[] = []\r\n const visitState = new Map<string, 'done' | 'visiting'>()\r\n\r\n const walk = (node: TreeNode) => {\r\n const currentState = visitState.get(node.id)\r\n\r\n if (currentState === 'done') {\r\n return\r\n }\r\n\r\n if (currentState === 'visiting') {\r\n const cycleStartIndex = pathStack.lastIndexOf(node.id)\r\n const cycleIDs = cycleStartIndex >= 0 ? pathStack.slice(cycleStartIndex) : [node.id]\r\n\r\n for (const cycleID of cycleIDs) {\r\n cycleNodeIDs.add(cycleID)\r\n }\r\n\r\n return\r\n }\r\n\r\n visitState.set(node.id, 'visiting')\r\n pathStack.push(node.id)\r\n\r\n if (node.parentID !== null) {\r\n const parentNode = nodesByID.get(node.parentID)\r\n\r\n if (parentNode) {\r\n walk(parentNode)\r\n }\r\n }\r\n\r\n pathStack.pop()\r\n visitState.set(node.id, 'done')\r\n }\r\n\r\n for (const node of nodes) {\r\n walk(node)\r\n }\r\n\r\n return cycleNodeIDs\r\n}\r\n\r\nfunction parseSortTokens(sort?: string): SortToken[] {\r\n if (typeof sort !== 'string' || sort.trim().length === 0) {\r\n return []\r\n }\r\n\r\n return sort\r\n .split(',')\r\n .map((token) => token.trim())\r\n .filter((token) => token.length > 0)\r\n .map((token) => {\r\n const descending = token.startsWith('-')\r\n const normalizedToken = descending ? token.slice(1) : token\r\n\r\n return {\r\n descending,\r\n path: normalizedToken.split('.').filter(Boolean),\r\n }\r\n })\r\n .filter((token) => token.path.length > 0)\r\n}\r\n\r\nfunction resolveSortValue(source: unknown, path: string[]): SortValue | undefined {\r\n let currentValue = source\r\n\r\n for (const segment of path) {\r\n if (!currentValue || typeof currentValue !== 'object' || Array.isArray(currentValue)) {\r\n return undefined\r\n }\r\n\r\n if (!(segment in currentValue)) {\r\n return undefined\r\n }\r\n\r\n currentValue = (currentValue as Record<string, unknown>)[segment]\r\n }\r\n\r\n if (currentValue === null || currentValue === undefined) {\r\n return null\r\n }\r\n\r\n if (currentValue instanceof Date) {\r\n const timestamp = currentValue.getTime()\r\n\r\n return Number.isNaN(timestamp) ? undefined : timestamp\r\n }\r\n\r\n if (typeof currentValue === 'boolean') {\r\n return currentValue ? 1 : 0\r\n }\r\n\r\n if (typeof currentValue === 'number') {\r\n return Number.isFinite(currentValue) ? currentValue : undefined\r\n }\r\n\r\n if (typeof currentValue !== 'string') {\r\n return undefined\r\n }\r\n\r\n const normalizedValue = currentValue.trim()\r\n\r\n if (dateLikePattern.test(normalizedValue)) {\r\n const timestamp = Date.parse(normalizedValue)\r\n\r\n if (!Number.isNaN(timestamp)) {\r\n return timestamp\r\n }\r\n }\r\n\r\n return normalizedValue\r\n}\r\n\r\nfunction compareSortValues(leftValue: SortValue, rightValue: SortValue): number {\r\n if (leftValue === null && rightValue === null) {\r\n return 0\r\n }\r\n\r\n if (leftValue === null) {\r\n return -1\r\n }\r\n\r\n if (rightValue === null) {\r\n return 1\r\n }\r\n\r\n if (typeof leftValue === 'number' && typeof rightValue === 'number') {\r\n if (leftValue === rightValue) {\r\n return 0\r\n }\r\n\r\n return leftValue < rightValue ? -1 : 1\r\n }\r\n\r\n return String(leftValue).localeCompare(String(rightValue), undefined, {\r\n numeric: true,\r\n sensitivity: 'base',\r\n })\r\n}\r\n\r\nfunction createTreeNodeComparator(sort?: string) {\r\n const sortTokens = parseSortTokens(sort)\r\n\r\n if (sortTokens.length === 0) {\r\n return null\r\n }\r\n\r\n return (leftNode: TreeNode, rightNode: TreeNode): number => {\r\n for (const sortToken of sortTokens) {\r\n const leftValue = resolveSortValue(leftNode.doc, sortToken.path)\r\n const rightValue = resolveSortValue(rightNode.doc, sortToken.path)\r\n\r\n if (leftValue === undefined || rightValue === undefined) {\r\n continue\r\n }\r\n\r\n const comparison = compareSortValues(leftValue, rightValue)\r\n\r\n if (comparison !== 0) {\r\n return sortToken.descending ? -comparison : comparison\r\n }\r\n }\r\n\r\n return leftNode.originalIndex - rightNode.originalIndex\r\n }\r\n}\r\n\r\nexport function buildPageTreeDocs(\r\n docs: PageTreeSourceDoc[],\r\n options: BuildPageTreeDocsOptions = {},\r\n): PageTreeDoc[] {\r\n const parentFieldSlug = options.parentFieldSlug ?? 'parent'\r\n const nodes: TreeNode[] = docs.map((doc, index) => ({\r\n doc,\r\n id: stringifyDocID(doc.id),\r\n originalIndex: index,\r\n parentID: getDocParentID(doc, parentFieldSlug),\r\n }))\r\n const nodesByID = new Map(nodes.map((node) => [node.id, node]))\r\n const cycleNodeIDs = getCycleNodeIDs(nodes, nodesByID)\r\n const effectiveParentIDByNodeID = new Map<string, null | string>()\r\n const childrenByParentID = new Map<null | string, TreeNode[]>()\r\n const compareTreeNodes = createTreeNodeComparator(options.sort)\r\n\r\n for (const node of nodes) {\r\n const parentExists = node.parentID !== null && nodesByID.has(node.parentID)\r\n const effectiveParentID =\r\n parentExists && !cycleNodeIDs.has(node.id) ? node.parentID : null\r\n\r\n effectiveParentIDByNodeID.set(node.id, effectiveParentID)\r\n\r\n const currentChildren = childrenByParentID.get(effectiveParentID) ?? []\r\n currentChildren.push(node)\r\n childrenByParentID.set(effectiveParentID, currentChildren)\r\n }\r\n\r\n if (compareTreeNodes) {\r\n for (const children of childrenByParentID.values()) {\r\n children.sort(compareTreeNodes)\r\n }\r\n }\r\n\r\n const orderedDocs: PageTreeDoc[] = []\r\n const subtreeDepthByID = new Map<string, number>()\r\n const visitedNodeIDs = new Set<string>()\r\n\r\n const getShadeLevel = (rootMaxDepth: number, depth: number): number => {\r\n if (rootMaxDepth === 0) {\r\n return 0\r\n }\r\n\r\n return Math.max(rootMaxDepth - depth + 1, 1)\r\n }\r\n\r\n const getSubtreeDepth = (node: TreeNode): number => {\r\n const cachedDepth = subtreeDepthByID.get(node.id)\r\n\r\n if (typeof cachedDepth === 'number') {\r\n return cachedDepth\r\n }\r\n\r\n const children = childrenByParentID.get(node.id) ?? []\r\n\r\n if (children.length === 0) {\r\n subtreeDepthByID.set(node.id, 0)\r\n return 0\r\n }\r\n\r\n const depth = Math.max(...children.map((child) => getSubtreeDepth(child) + 1))\r\n subtreeDepthByID.set(node.id, depth)\r\n return depth\r\n }\r\n\r\n const visit = (node: TreeNode, ancestorIDs: string[], rootMaxDepth: number) => {\r\n if (visitedNodeIDs.has(node.id)) {\r\n return\r\n }\r\n\r\n visitedNodeIDs.add(node.id)\r\n\r\n const children = childrenByParentID.get(node.id) ?? []\r\n const depth = ancestorIDs.length\r\n const shadeLevel = getShadeLevel(rootMaxDepth, depth)\r\n\r\n orderedDocs.push({\r\n ...(node.doc as PageTreeSourceDoc),\r\n __pageTreeAncestorIDs: ancestorIDs,\r\n __pageTreeDepth: depth,\r\n __pageTreeHasChildren: children.length > 0,\r\n __pageTreeID: node.id,\r\n __pageTreeOrderIndex: orderedDocs.length,\r\n __pageTreeParentID: effectiveParentIDByNodeID.get(node.id) ?? null,\r\n __pageTreeShadeLevel: shadeLevel,\r\n })\r\n\r\n for (const child of children) {\r\n visit(child, [...ancestorIDs, node.id], rootMaxDepth)\r\n }\r\n }\r\n\r\n const roots = [...(childrenByParentID.get(null) ?? [])]\r\n\r\n for (const root of roots) {\r\n visit(root, [], getSubtreeDepth(root))\r\n }\r\n\r\n const fallbackNodes = compareTreeNodes ? [...nodes].sort(compareTreeNodes) : nodes\r\n\r\n for (const node of fallbackNodes) {\r\n if (!visitedNodeIDs.has(node.id)) {\r\n visit(node, [], getSubtreeDepth(node))\r\n }\r\n }\r\n\r\n return orderedDocs\r\n}\r\n\r\nexport function getVisibleTreeDocs(\r\n docs: PageTreeDoc[],\r\n collapsedIDs: ReadonlySet<string>,\r\n): PageTreeDoc[] {\r\n return docs.filter((doc) =>\r\n doc.__pageTreeAncestorIDs.every((ancestorID) => !collapsedIDs.has(ancestorID)),\r\n )\r\n}\r\n"],"names":["dateLikePattern","stringifyDocID","id","String","getRelationshipID","value","relationshipID","getDocParentID","doc","parentFieldSlug","getDocDisplayLabel","title","trim","length","slug","__pageTreeID","getDocSlugSegment","replace","buildDocSlugPath","args","docsByID","segments","__pageTreeAncestorIDs","map","ancestorID","get","filter","ancestorDoc","Boolean","push","join","buildProspectiveDocSlugPath","activeDoc","targetDoc","buildChildrenByParentID","docs","childrenByParentID","Map","docID","parentID","existingChildren","set","collectDescendantIDs","rootID","descendantIDs","stack","currentID","pop","getCycleNodeIDs","nodes","nodesByID","cycleNodeIDs","Set","pathStack","visitState","walk","node","currentState","cycleStartIndex","lastIndexOf","cycleIDs","slice","cycleID","add","parentNode","parseSortTokens","sort","split","token","descending","startsWith","normalizedToken","path","resolveSortValue","source","currentValue","segment","Array","isArray","undefined","Date","timestamp","getTime","Number","isNaN","isFinite","normalizedValue","test","parse","compareSortValues","leftValue","rightValue","localeCompare","numeric","sensitivity","createTreeNodeComparator","sortTokens","leftNode","rightNode","sortToken","comparison","originalIndex","buildPageTreeDocs","options","index","effectiveParentIDByNodeID","compareTreeNodes","parentExists","has","effectiveParentID","currentChildren","children","values","orderedDocs","subtreeDepthByID","visitedNodeIDs","getShadeLevel","rootMaxDepth","depth","Math","max","getSubtreeDepth","cachedDepth","child","visit","ancestorIDs","shadeLevel","__pageTreeDepth","__pageTreeHasChildren","__pageTreeOrderIndex","__pageTreeParentID","__pageTreeShadeLevel","roots","root","fallbackNodes","getVisibleTreeDocs","collapsedIDs","every"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../src/utilities/pageTree.ts"],"sourcesContent":["import type { PageTreeSourceDoc } from '../types.js'\r\nexport type { PageTreeSourceDoc } from '../types.js'\r\n\r\nexport type PageTreeMeta = {\r\n __pageTreeAncestorIDs: string[]\r\n __pageTreeDepth: number\r\n __pageTreeHasChildren: boolean\r\n __pageTreeID: string\r\n __pageTreeOrderIndex: number\r\n __pageTreeParentID: null | string\r\n __pageTreeShadeLevel: number\r\n}\r\n\r\nexport type PageTreeDoc = PageTreeMeta & PageTreeSourceDoc\r\n\r\ntype SortToken = {\r\n descending: boolean\r\n path: string[]\r\n}\r\n\r\ntype SortValue = null | number | string\r\n\r\ntype TreeNode = {\r\n doc: PageTreeSourceDoc\r\n id: string\r\n originalIndex: number\r\n parentID: null | string\r\n}\r\n\r\nconst dateLikePattern = /^\\d{4}-\\d{2}-\\d{2}(?:[T\\s].*)?$/\r\n\r\nexport type BuildPageTreeDocsOptions = {\r\n parentFieldSlug?: string\r\n sort?: string\r\n}\r\n\r\nexport function stringifyDocID(id: number | string | undefined): string {\r\n return String(id ?? '')\r\n}\r\n\r\nexport function getRelationshipID(value: unknown): null | string {\r\n if (typeof value === 'number' || typeof value === 'string') {\r\n return stringifyDocID(value)\r\n }\r\n\r\n if (value && typeof value === 'object' && 'id' in value) {\r\n const relationshipID = (value as { id?: number | string }).id\r\n\r\n if (typeof relationshipID === 'number' || typeof relationshipID === 'string') {\r\n return stringifyDocID(relationshipID)\r\n }\r\n }\r\n\r\n return null\r\n}\r\n\r\nexport function getDocParentID(\r\n doc: PageTreeSourceDoc,\r\n parentFieldSlug = 'parent',\r\n): null | string {\r\n return getRelationshipID(doc[parentFieldSlug])\r\n}\r\n\r\nexport function getDocDisplayLabel(doc: PageTreeDoc): string {\r\n const title = doc.title\r\n\r\n if (typeof title === 'string' && title.trim().length > 0) {\r\n return title\r\n }\r\n\r\n if (typeof doc.slug === 'string' && doc.slug.trim().length > 0) {\r\n return doc.slug\r\n }\r\n\r\n return doc.__pageTreeID\r\n}\r\n\r\nexport function getDocSlugSegment(doc: PageTreeDoc): string {\r\n if (typeof doc.slug === 'string' && doc.slug.trim().length > 0) {\r\n return doc.slug.trim().replace(/^\\/+|\\/+$/g, '')\r\n }\r\n\r\n return doc.__pageTreeID\r\n}\r\n\r\nexport function buildDocSlugPath(args: {\r\n doc: PageTreeDoc\r\n docsByID: Map<string, PageTreeDoc>\r\n}): string {\r\n const { doc, docsByID } = args\r\n const segments = doc.__pageTreeAncestorIDs\r\n .map((ancestorID) => docsByID.get(ancestorID))\r\n .filter((ancestorDoc): ancestorDoc is PageTreeDoc => Boolean(ancestorDoc))\r\n .map(getDocSlugSegment)\r\n\r\n segments.push(getDocSlugSegment(doc))\r\n\r\n return `/${segments.filter(Boolean).join('/')}`\r\n}\r\n\r\nexport function buildProspectiveDocSlugPath(args: {\r\n activeDoc: PageTreeDoc\r\n docsByID: Map<string, PageTreeDoc>\r\n targetDoc?: PageTreeDoc\r\n}): string {\r\n const { activeDoc, docsByID, targetDoc } = args\r\n\r\n if (!targetDoc) {\r\n return `/${getDocSlugSegment(activeDoc)}`\r\n }\r\n\r\n const segments = targetDoc.__pageTreeAncestorIDs\r\n .map((ancestorID) => docsByID.get(ancestorID))\r\n .filter((ancestorDoc): ancestorDoc is PageTreeDoc => Boolean(ancestorDoc))\r\n .map(getDocSlugSegment)\r\n\r\n segments.push(getDocSlugSegment(targetDoc), getDocSlugSegment(activeDoc))\r\n\r\n return `/${segments.filter(Boolean).join('/')}`\r\n}\r\n\r\nexport function buildChildrenByParentID(args: {\r\n docs: PageTreeSourceDoc[]\r\n parentFieldSlug?: string\r\n}): Map<null | string, string[]> {\r\n const { docs, parentFieldSlug = 'parent' } = args\r\n const childrenByParentID = new Map<null | string, string[]>()\r\n\r\n for (const doc of docs) {\r\n const docID = stringifyDocID(doc.id)\r\n const parentID = getDocParentID(doc, parentFieldSlug)\r\n const existingChildren = childrenByParentID.get(parentID) ?? []\r\n\r\n existingChildren.push(docID)\r\n childrenByParentID.set(parentID, existingChildren)\r\n }\r\n\r\n return childrenByParentID\r\n}\r\n\r\nexport function collectDescendantIDs(\r\n rootID: string,\r\n childrenByParentID: Map<null | string, string[]>,\r\n): string[] {\r\n const descendantIDs: string[] = []\r\n const stack = [...(childrenByParentID.get(rootID) ?? [])]\r\n\r\n while (stack.length > 0) {\r\n const currentID = stack.pop()\r\n\r\n if (!currentID) {\r\n continue\r\n }\r\n\r\n descendantIDs.push(currentID)\r\n stack.push(...(childrenByParentID.get(currentID) ?? []))\r\n }\r\n\r\n return descendantIDs\r\n}\r\n\r\nfunction getCycleNodeIDs(nodes: TreeNode[], nodesByID: Map<string, TreeNode>): Set<string> {\r\n const cycleNodeIDs = new Set<string>()\r\n const pathStack: string[] = []\r\n const visitState = new Map<string, 'done' | 'visiting'>()\r\n\r\n const walk = (node: TreeNode) => {\r\n const currentState = visitState.get(node.id)\r\n\r\n if (currentState === 'done') {\r\n return\r\n }\r\n\r\n if (currentState === 'visiting') {\r\n const cycleStartIndex = pathStack.lastIndexOf(node.id)\r\n const cycleIDs = cycleStartIndex >= 0 ? pathStack.slice(cycleStartIndex) : [node.id]\r\n\r\n for (const cycleID of cycleIDs) {\r\n cycleNodeIDs.add(cycleID)\r\n }\r\n\r\n return\r\n }\r\n\r\n visitState.set(node.id, 'visiting')\r\n pathStack.push(node.id)\r\n\r\n if (node.parentID !== null) {\r\n const parentNode = nodesByID.get(node.parentID)\r\n\r\n if (parentNode) {\r\n walk(parentNode)\r\n }\r\n }\r\n\r\n pathStack.pop()\r\n visitState.set(node.id, 'done')\r\n }\r\n\r\n for (const node of nodes) {\r\n walk(node)\r\n }\r\n\r\n return cycleNodeIDs\r\n}\r\n\r\nfunction parseSortTokens(sort?: string): SortToken[] {\r\n if (typeof sort !== 'string' || sort.trim().length === 0) {\r\n return []\r\n }\r\n\r\n return sort\r\n .split(',')\r\n .map((token) => token.trim())\r\n .filter((token) => token.length > 0)\r\n .map((token) => {\r\n const descending = token.startsWith('-')\r\n const normalizedToken = descending ? token.slice(1) : token\r\n\r\n return {\r\n descending,\r\n path: normalizedToken.split('.').filter(Boolean),\r\n }\r\n })\r\n .filter((token) => token.path.length > 0)\r\n}\r\n\r\nfunction resolveSortValue(source: unknown, path: string[]): SortValue | undefined {\r\n let currentValue = source\r\n\r\n for (const segment of path) {\r\n if (!currentValue || typeof currentValue !== 'object' || Array.isArray(currentValue)) {\r\n return undefined\r\n }\r\n\r\n if (!(segment in currentValue)) {\r\n return undefined\r\n }\r\n\r\n currentValue = (currentValue as Record<string, unknown>)[segment]\r\n }\r\n\r\n if (currentValue === null || currentValue === undefined) {\r\n return null\r\n }\r\n\r\n if (currentValue instanceof Date) {\r\n const timestamp = currentValue.getTime()\r\n\r\n return Number.isNaN(timestamp) ? undefined : timestamp\r\n }\r\n\r\n if (typeof currentValue === 'boolean') {\r\n return currentValue ? 1 : 0\r\n }\r\n\r\n if (typeof currentValue === 'number') {\r\n return Number.isFinite(currentValue) ? currentValue : undefined\r\n }\r\n\r\n if (typeof currentValue !== 'string') {\r\n return undefined\r\n }\r\n\r\n const normalizedValue = currentValue.trim()\r\n\r\n if (dateLikePattern.test(normalizedValue)) {\r\n const timestamp = Date.parse(normalizedValue)\r\n\r\n if (!Number.isNaN(timestamp)) {\r\n return timestamp\r\n }\r\n }\r\n\r\n return normalizedValue\r\n}\r\n\r\nfunction compareSortValues(leftValue: SortValue, rightValue: SortValue): number {\r\n if (leftValue === null && rightValue === null) {\r\n return 0\r\n }\r\n\r\n if (leftValue === null) {\r\n return -1\r\n }\r\n\r\n if (rightValue === null) {\r\n return 1\r\n }\r\n\r\n if (typeof leftValue === 'number' && typeof rightValue === 'number') {\r\n if (leftValue === rightValue) {\r\n return 0\r\n }\r\n\r\n return leftValue < rightValue ? -1 : 1\r\n }\r\n\r\n // Plain lexicographic comparison. Required for fractional-indexing keys (e.g. `_order`\r\n // values like `a5`, `a53`, `a5i`), which encode position as raw lex order — using\r\n // `localeCompare` with `numeric: true` would interpret digit runs as numbers and\r\n // produce a different ordering than the database (e.g. `a53 > a5i` numerically vs\r\n // `a53 < a5i` lexicographically). It also matches MongoDB's default string ordering,\r\n // so children sort consistently between server-side and client-side.\r\n const leftString = String(leftValue)\r\n const rightString = String(rightValue)\r\n\r\n if (leftString === rightString) {\r\n return 0\r\n }\r\n\r\n return leftString < rightString ? -1 : 1\r\n}\r\n\r\nfunction createTreeNodeComparator(sort?: string) {\r\n const sortTokens = parseSortTokens(sort)\r\n\r\n if (sortTokens.length === 0) {\r\n return null\r\n }\r\n\r\n return (leftNode: TreeNode, rightNode: TreeNode): number => {\r\n for (const sortToken of sortTokens) {\r\n const leftValue = resolveSortValue(leftNode.doc, sortToken.path)\r\n const rightValue = resolveSortValue(rightNode.doc, sortToken.path)\r\n\r\n if (leftValue === undefined || rightValue === undefined) {\r\n continue\r\n }\r\n\r\n const comparison = compareSortValues(leftValue, rightValue)\r\n\r\n if (comparison !== 0) {\r\n return sortToken.descending ? -comparison : comparison\r\n }\r\n }\r\n\r\n return leftNode.originalIndex - rightNode.originalIndex\r\n }\r\n}\r\n\r\nexport function buildPageTreeDocs(\r\n docs: PageTreeSourceDoc[],\r\n options: BuildPageTreeDocsOptions = {},\r\n): PageTreeDoc[] {\r\n const parentFieldSlug = options.parentFieldSlug ?? 'parent'\r\n const nodes: TreeNode[] = docs.map((doc, index) => ({\r\n doc,\r\n id: stringifyDocID(doc.id),\r\n originalIndex: index,\r\n parentID: getDocParentID(doc, parentFieldSlug),\r\n }))\r\n const nodesByID = new Map(nodes.map((node) => [node.id, node]))\r\n const cycleNodeIDs = getCycleNodeIDs(nodes, nodesByID)\r\n const effectiveParentIDByNodeID = new Map<string, null | string>()\r\n const childrenByParentID = new Map<null | string, TreeNode[]>()\r\n const compareTreeNodes = createTreeNodeComparator(options.sort)\r\n\r\n for (const node of nodes) {\r\n const parentExists = node.parentID !== null && nodesByID.has(node.parentID)\r\n const effectiveParentID =\r\n parentExists && !cycleNodeIDs.has(node.id) ? node.parentID : null\r\n\r\n effectiveParentIDByNodeID.set(node.id, effectiveParentID)\r\n\r\n const currentChildren = childrenByParentID.get(effectiveParentID) ?? []\r\n currentChildren.push(node)\r\n childrenByParentID.set(effectiveParentID, currentChildren)\r\n }\r\n\r\n if (compareTreeNodes) {\r\n for (const children of childrenByParentID.values()) {\r\n children.sort(compareTreeNodes)\r\n }\r\n }\r\n\r\n const orderedDocs: PageTreeDoc[] = []\r\n const subtreeDepthByID = new Map<string, number>()\r\n const visitedNodeIDs = new Set<string>()\r\n\r\n const getShadeLevel = (rootMaxDepth: number, depth: number): number => {\r\n if (rootMaxDepth === 0) {\r\n return 0\r\n }\r\n\r\n return Math.max(rootMaxDepth - depth + 1, 1)\r\n }\r\n\r\n const getSubtreeDepth = (node: TreeNode): number => {\r\n const cachedDepth = subtreeDepthByID.get(node.id)\r\n\r\n if (typeof cachedDepth === 'number') {\r\n return cachedDepth\r\n }\r\n\r\n const children = childrenByParentID.get(node.id) ?? []\r\n\r\n if (children.length === 0) {\r\n subtreeDepthByID.set(node.id, 0)\r\n return 0\r\n }\r\n\r\n const depth = Math.max(...children.map((child) => getSubtreeDepth(child) + 1))\r\n subtreeDepthByID.set(node.id, depth)\r\n return depth\r\n }\r\n\r\n const visit = (node: TreeNode, ancestorIDs: string[], rootMaxDepth: number) => {\r\n if (visitedNodeIDs.has(node.id)) {\r\n return\r\n }\r\n\r\n visitedNodeIDs.add(node.id)\r\n\r\n const children = childrenByParentID.get(node.id) ?? []\r\n const depth = ancestorIDs.length\r\n const shadeLevel = getShadeLevel(rootMaxDepth, depth)\r\n\r\n orderedDocs.push({\r\n ...(node.doc as PageTreeSourceDoc),\r\n __pageTreeAncestorIDs: ancestorIDs,\r\n __pageTreeDepth: depth,\r\n __pageTreeHasChildren: children.length > 0,\r\n __pageTreeID: node.id,\r\n __pageTreeOrderIndex: orderedDocs.length,\r\n __pageTreeParentID: effectiveParentIDByNodeID.get(node.id) ?? null,\r\n __pageTreeShadeLevel: shadeLevel,\r\n })\r\n\r\n for (const child of children) {\r\n visit(child, [...ancestorIDs, node.id], rootMaxDepth)\r\n }\r\n }\r\n\r\n const roots = [...(childrenByParentID.get(null) ?? [])]\r\n\r\n for (const root of roots) {\r\n visit(root, [], getSubtreeDepth(root))\r\n }\r\n\r\n const fallbackNodes = compareTreeNodes ? [...nodes].sort(compareTreeNodes) : nodes\r\n\r\n for (const node of fallbackNodes) {\r\n if (!visitedNodeIDs.has(node.id)) {\r\n visit(node, [], getSubtreeDepth(node))\r\n }\r\n }\r\n\r\n return orderedDocs\r\n}\r\n\r\nexport function getVisibleTreeDocs(\r\n docs: PageTreeDoc[],\r\n collapsedIDs: ReadonlySet<string>,\r\n): PageTreeDoc[] {\r\n return docs.filter((doc) =>\r\n doc.__pageTreeAncestorIDs.every((ancestorID) => !collapsedIDs.has(ancestorID)),\r\n )\r\n}\r\n"],"names":["dateLikePattern","stringifyDocID","id","String","getRelationshipID","value","relationshipID","getDocParentID","doc","parentFieldSlug","getDocDisplayLabel","title","trim","length","slug","__pageTreeID","getDocSlugSegment","replace","buildDocSlugPath","args","docsByID","segments","__pageTreeAncestorIDs","map","ancestorID","get","filter","ancestorDoc","Boolean","push","join","buildProspectiveDocSlugPath","activeDoc","targetDoc","buildChildrenByParentID","docs","childrenByParentID","Map","docID","parentID","existingChildren","set","collectDescendantIDs","rootID","descendantIDs","stack","currentID","pop","getCycleNodeIDs","nodes","nodesByID","cycleNodeIDs","Set","pathStack","visitState","walk","node","currentState","cycleStartIndex","lastIndexOf","cycleIDs","slice","cycleID","add","parentNode","parseSortTokens","sort","split","token","descending","startsWith","normalizedToken","path","resolveSortValue","source","currentValue","segment","Array","isArray","undefined","Date","timestamp","getTime","Number","isNaN","isFinite","normalizedValue","test","parse","compareSortValues","leftValue","rightValue","leftString","rightString","createTreeNodeComparator","sortTokens","leftNode","rightNode","sortToken","comparison","originalIndex","buildPageTreeDocs","options","index","effectiveParentIDByNodeID","compareTreeNodes","parentExists","has","effectiveParentID","currentChildren","children","values","orderedDocs","subtreeDepthByID","visitedNodeIDs","getShadeLevel","rootMaxDepth","depth","Math","max","getSubtreeDepth","cachedDepth","child","visit","ancestorIDs","shadeLevel","__pageTreeDepth","__pageTreeHasChildren","__pageTreeOrderIndex","__pageTreeParentID","__pageTreeShadeLevel","roots","root","fallbackNodes","getVisibleTreeDocs","collapsedIDs","every"],"mappings":"AA6BA,MAAMA,kBAAkB;AAOxB,OAAO,SAASC,eAAeC,EAA+B;IAC5D,OAAOC,OAAOD,MAAM;AACtB;AAEA,OAAO,SAASE,kBAAkBC,KAAc;IAC9C,IAAI,OAAOA,UAAU,YAAY,OAAOA,UAAU,UAAU;QAC1D,OAAOJ,eAAeI;IACxB;IAEA,IAAIA,SAAS,OAAOA,UAAU,YAAY,QAAQA,OAAO;QACvD,MAAMC,iBAAiB,AAACD,MAAmCH,EAAE;QAE7D,IAAI,OAAOI,mBAAmB,YAAY,OAAOA,mBAAmB,UAAU;YAC5E,OAAOL,eAAeK;QACxB;IACF;IAEA,OAAO;AACT;AAEA,OAAO,SAASC,eACdC,GAAsB,EACtBC,kBAAkB,QAAQ;IAE1B,OAAOL,kBAAkBI,GAAG,CAACC,gBAAgB;AAC/C;AAEA,OAAO,SAASC,mBAAmBF,GAAgB;IACjD,MAAMG,QAAQH,IAAIG,KAAK;IAEvB,IAAI,OAAOA,UAAU,YAAYA,MAAMC,IAAI,GAAGC,MAAM,GAAG,GAAG;QACxD,OAAOF;IACT;IAEA,IAAI,OAAOH,IAAIM,IAAI,KAAK,YAAYN,IAAIM,IAAI,CAACF,IAAI,GAAGC,MAAM,GAAG,GAAG;QAC9D,OAAOL,IAAIM,IAAI;IACjB;IAEA,OAAON,IAAIO,YAAY;AACzB;AAEA,OAAO,SAASC,kBAAkBR,GAAgB;IAChD,IAAI,OAAOA,IAAIM,IAAI,KAAK,YAAYN,IAAIM,IAAI,CAACF,IAAI,GAAGC,MAAM,GAAG,GAAG;QAC9D,OAAOL,IAAIM,IAAI,CAACF,IAAI,GAAGK,OAAO,CAAC,cAAc;IAC/C;IAEA,OAAOT,IAAIO,YAAY;AACzB;AAEA,OAAO,SAASG,iBAAiBC,IAGhC;IACC,MAAM,EAAEX,GAAG,EAAEY,QAAQ,EAAE,GAAGD;IAC1B,MAAME,WAAWb,IAAIc,qBAAqB,CACvCC,GAAG,CAAC,CAACC,aAAeJ,SAASK,GAAG,CAACD,aACjCE,MAAM,CAAC,CAACC,cAA4CC,QAAQD,cAC5DJ,GAAG,CAACP;IAEPK,SAASQ,IAAI,CAACb,kBAAkBR;IAEhC,OAAO,CAAC,CAAC,EAAEa,SAASK,MAAM,CAACE,SAASE,IAAI,CAAC,MAAM;AACjD;AAEA,OAAO,SAASC,4BAA4BZ,IAI3C;IACC,MAAM,EAAEa,SAAS,EAAEZ,QAAQ,EAAEa,SAAS,EAAE,GAAGd;IAE3C,IAAI,CAACc,WAAW;QACd,OAAO,CAAC,CAAC,EAAEjB,kBAAkBgB,YAAY;IAC3C;IAEA,MAAMX,WAAWY,UAAUX,qBAAqB,CAC7CC,GAAG,CAAC,CAACC,aAAeJ,SAASK,GAAG,CAACD,aACjCE,MAAM,CAAC,CAACC,cAA4CC,QAAQD,cAC5DJ,GAAG,CAACP;IAEPK,SAASQ,IAAI,CAACb,kBAAkBiB,YAAYjB,kBAAkBgB;IAE9D,OAAO,CAAC,CAAC,EAAEX,SAASK,MAAM,CAACE,SAASE,IAAI,CAAC,MAAM;AACjD;AAEA,OAAO,SAASI,wBAAwBf,IAGvC;IACC,MAAM,EAAEgB,IAAI,EAAE1B,kBAAkB,QAAQ,EAAE,GAAGU;IAC7C,MAAMiB,qBAAqB,IAAIC;IAE/B,KAAK,MAAM7B,OAAO2B,KAAM;QACtB,MAAMG,QAAQrC,eAAeO,IAAIN,EAAE;QACnC,MAAMqC,WAAWhC,eAAeC,KAAKC;QACrC,MAAM+B,mBAAmBJ,mBAAmBX,GAAG,CAACc,aAAa,EAAE;QAE/DC,iBAAiBX,IAAI,CAACS;QACtBF,mBAAmBK,GAAG,CAACF,UAAUC;IACnC;IAEA,OAAOJ;AACT;AAEA,OAAO,SAASM,qBACdC,MAAc,EACdP,kBAAgD;IAEhD,MAAMQ,gBAA0B,EAAE;IAClC,MAAMC,QAAQ;WAAKT,mBAAmBX,GAAG,CAACkB,WAAW,EAAE;KAAE;IAEzD,MAAOE,MAAMhC,MAAM,GAAG,EAAG;QACvB,MAAMiC,YAAYD,MAAME,GAAG;QAE3B,IAAI,CAACD,WAAW;YACd;QACF;QAEAF,cAAcf,IAAI,CAACiB;QACnBD,MAAMhB,IAAI,IAAKO,mBAAmBX,GAAG,CAACqB,cAAc,EAAE;IACxD;IAEA,OAAOF;AACT;AAEA,SAASI,gBAAgBC,KAAiB,EAAEC,SAAgC;IAC1E,MAAMC,eAAe,IAAIC;IACzB,MAAMC,YAAsB,EAAE;IAC9B,MAAMC,aAAa,IAAIjB;IAEvB,MAAMkB,OAAO,CAACC;QACZ,MAAMC,eAAeH,WAAW7B,GAAG,CAAC+B,KAAKtD,EAAE;QAE3C,IAAIuD,iBAAiB,QAAQ;YAC3B;QACF;QAEA,IAAIA,iBAAiB,YAAY;YAC/B,MAAMC,kBAAkBL,UAAUM,WAAW,CAACH,KAAKtD,EAAE;YACrD,MAAM0D,WAAWF,mBAAmB,IAAIL,UAAUQ,KAAK,CAACH,mBAAmB;gBAACF,KAAKtD,EAAE;aAAC;YAEpF,KAAK,MAAM4D,WAAWF,SAAU;gBAC9BT,aAAaY,GAAG,CAACD;YACnB;YAEA;QACF;QAEAR,WAAWb,GAAG,CAACe,KAAKtD,EAAE,EAAE;QACxBmD,UAAUxB,IAAI,CAAC2B,KAAKtD,EAAE;QAEtB,IAAIsD,KAAKjB,QAAQ,KAAK,MAAM;YAC1B,MAAMyB,aAAad,UAAUzB,GAAG,CAAC+B,KAAKjB,QAAQ;YAE9C,IAAIyB,YAAY;gBACdT,KAAKS;YACP;QACF;QAEAX,UAAUN,GAAG;QACbO,WAAWb,GAAG,CAACe,KAAKtD,EAAE,EAAE;IAC1B;IAEA,KAAK,MAAMsD,QAAQP,MAAO;QACxBM,KAAKC;IACP;IAEA,OAAOL;AACT;AAEA,SAASc,gBAAgBC,IAAa;IACpC,IAAI,OAAOA,SAAS,YAAYA,KAAKtD,IAAI,GAAGC,MAAM,KAAK,GAAG;QACxD,OAAO,EAAE;IACX;IAEA,OAAOqD,KACJC,KAAK,CAAC,KACN5C,GAAG,CAAC,CAAC6C,QAAUA,MAAMxD,IAAI,IACzBc,MAAM,CAAC,CAAC0C,QAAUA,MAAMvD,MAAM,GAAG,GACjCU,GAAG,CAAC,CAAC6C;QACJ,MAAMC,aAAaD,MAAME,UAAU,CAAC;QACpC,MAAMC,kBAAkBF,aAAaD,MAAMP,KAAK,CAAC,KAAKO;QAEtD,OAAO;YACLC;YACAG,MAAMD,gBAAgBJ,KAAK,CAAC,KAAKzC,MAAM,CAACE;QAC1C;IACF,GACCF,MAAM,CAAC,CAAC0C,QAAUA,MAAMI,IAAI,CAAC3D,MAAM,GAAG;AAC3C;AAEA,SAAS4D,iBAAiBC,MAAe,EAAEF,IAAc;IACvD,IAAIG,eAAeD;IAEnB,KAAK,MAAME,WAAWJ,KAAM;QAC1B,IAAI,CAACG,gBAAgB,OAAOA,iBAAiB,YAAYE,MAAMC,OAAO,CAACH,eAAe;YACpF,OAAOI;QACT;QAEA,IAAI,CAAEH,CAAAA,WAAWD,YAAW,GAAI;YAC9B,OAAOI;QACT;QAEAJ,eAAe,AAACA,YAAwC,CAACC,QAAQ;IACnE;IAEA,IAAID,iBAAiB,QAAQA,iBAAiBI,WAAW;QACvD,OAAO;IACT;IAEA,IAAIJ,wBAAwBK,MAAM;QAChC,MAAMC,YAAYN,aAAaO,OAAO;QAEtC,OAAOC,OAAOC,KAAK,CAACH,aAAaF,YAAYE;IAC/C;IAEA,IAAI,OAAON,iBAAiB,WAAW;QACrC,OAAOA,eAAe,IAAI;IAC5B;IAEA,IAAI,OAAOA,iBAAiB,UAAU;QACpC,OAAOQ,OAAOE,QAAQ,CAACV,gBAAgBA,eAAeI;IACxD;IAEA,IAAI,OAAOJ,iBAAiB,UAAU;QACpC,OAAOI;IACT;IAEA,MAAMO,kBAAkBX,aAAa/D,IAAI;IAEzC,IAAIZ,gBAAgBuF,IAAI,CAACD,kBAAkB;QACzC,MAAML,YAAYD,KAAKQ,KAAK,CAACF;QAE7B,IAAI,CAACH,OAAOC,KAAK,CAACH,YAAY;YAC5B,OAAOA;QACT;IACF;IAEA,OAAOK;AACT;AAEA,SAASG,kBAAkBC,SAAoB,EAAEC,UAAqB;IACpE,IAAID,cAAc,QAAQC,eAAe,MAAM;QAC7C,OAAO;IACT;IAEA,IAAID,cAAc,MAAM;QACtB,OAAO,CAAC;IACV;IAEA,IAAIC,eAAe,MAAM;QACvB,OAAO;IACT;IAEA,IAAI,OAAOD,cAAc,YAAY,OAAOC,eAAe,UAAU;QACnE,IAAID,cAAcC,YAAY;YAC5B,OAAO;QACT;QAEA,OAAOD,YAAYC,aAAa,CAAC,IAAI;IACvC;IAEA,uFAAuF;IACvF,kFAAkF;IAClF,iFAAiF;IACjF,kFAAkF;IAClF,qFAAqF;IACrF,qEAAqE;IACrE,MAAMC,aAAazF,OAAOuF;IAC1B,MAAMG,cAAc1F,OAAOwF;IAE3B,IAAIC,eAAeC,aAAa;QAC9B,OAAO;IACT;IAEA,OAAOD,aAAaC,cAAc,CAAC,IAAI;AACzC;AAEA,SAASC,yBAAyB5B,IAAa;IAC7C,MAAM6B,aAAa9B,gBAAgBC;IAEnC,IAAI6B,WAAWlF,MAAM,KAAK,GAAG;QAC3B,OAAO;IACT;IAEA,OAAO,CAACmF,UAAoBC;QAC1B,KAAK,MAAMC,aAAaH,WAAY;YAClC,MAAML,YAAYjB,iBAAiBuB,SAASxF,GAAG,EAAE0F,UAAU1B,IAAI;YAC/D,MAAMmB,aAAalB,iBAAiBwB,UAAUzF,GAAG,EAAE0F,UAAU1B,IAAI;YAEjE,IAAIkB,cAAcX,aAAaY,eAAeZ,WAAW;gBACvD;YACF;YAEA,MAAMoB,aAAaV,kBAAkBC,WAAWC;YAEhD,IAAIQ,eAAe,GAAG;gBACpB,OAAOD,UAAU7B,UAAU,GAAG,CAAC8B,aAAaA;YAC9C;QACF;QAEA,OAAOH,SAASI,aAAa,GAAGH,UAAUG,aAAa;IACzD;AACF;AAEA,OAAO,SAASC,kBACdlE,IAAyB,EACzBmE,UAAoC,CAAC,CAAC;IAEtC,MAAM7F,kBAAkB6F,QAAQ7F,eAAe,IAAI;IACnD,MAAMwC,QAAoBd,KAAKZ,GAAG,CAAC,CAACf,KAAK+F,QAAW,CAAA;YAClD/F;YACAN,IAAID,eAAeO,IAAIN,EAAE;YACzBkG,eAAeG;YACfhE,UAAUhC,eAAeC,KAAKC;QAChC,CAAA;IACA,MAAMyC,YAAY,IAAIb,IAAIY,MAAM1B,GAAG,CAAC,CAACiC,OAAS;YAACA,KAAKtD,EAAE;YAAEsD;SAAK;IAC7D,MAAML,eAAeH,gBAAgBC,OAAOC;IAC5C,MAAMsD,4BAA4B,IAAInE;IACtC,MAAMD,qBAAqB,IAAIC;IAC/B,MAAMoE,mBAAmBX,yBAAyBQ,QAAQpC,IAAI;IAE9D,KAAK,MAAMV,QAAQP,MAAO;QACxB,MAAMyD,eAAelD,KAAKjB,QAAQ,KAAK,QAAQW,UAAUyD,GAAG,CAACnD,KAAKjB,QAAQ;QAC1E,MAAMqE,oBACJF,gBAAgB,CAACvD,aAAawD,GAAG,CAACnD,KAAKtD,EAAE,IAAIsD,KAAKjB,QAAQ,GAAG;QAE/DiE,0BAA0B/D,GAAG,CAACe,KAAKtD,EAAE,EAAE0G;QAEvC,MAAMC,kBAAkBzE,mBAAmBX,GAAG,CAACmF,sBAAsB,EAAE;QACvEC,gBAAgBhF,IAAI,CAAC2B;QACrBpB,mBAAmBK,GAAG,CAACmE,mBAAmBC;IAC5C;IAEA,IAAIJ,kBAAkB;QACpB,KAAK,MAAMK,YAAY1E,mBAAmB2E,MAAM,GAAI;YAClDD,SAAS5C,IAAI,CAACuC;QAChB;IACF;IAEA,MAAMO,cAA6B,EAAE;IACrC,MAAMC,mBAAmB,IAAI5E;IAC7B,MAAM6E,iBAAiB,IAAI9D;IAE3B,MAAM+D,gBAAgB,CAACC,cAAsBC;QAC3C,IAAID,iBAAiB,GAAG;YACtB,OAAO;QACT;QAEA,OAAOE,KAAKC,GAAG,CAACH,eAAeC,QAAQ,GAAG;IAC5C;IAEA,MAAMG,kBAAkB,CAAChE;QACvB,MAAMiE,cAAcR,iBAAiBxF,GAAG,CAAC+B,KAAKtD,EAAE;QAEhD,IAAI,OAAOuH,gBAAgB,UAAU;YACnC,OAAOA;QACT;QAEA,MAAMX,WAAW1E,mBAAmBX,GAAG,CAAC+B,KAAKtD,EAAE,KAAK,EAAE;QAEtD,IAAI4G,SAASjG,MAAM,KAAK,GAAG;YACzBoG,iBAAiBxE,GAAG,CAACe,KAAKtD,EAAE,EAAE;YAC9B,OAAO;QACT;QAEA,MAAMmH,QAAQC,KAAKC,GAAG,IAAIT,SAASvF,GAAG,CAAC,CAACmG,QAAUF,gBAAgBE,SAAS;QAC3ET,iBAAiBxE,GAAG,CAACe,KAAKtD,EAAE,EAAEmH;QAC9B,OAAOA;IACT;IAEA,MAAMM,QAAQ,CAACnE,MAAgBoE,aAAuBR;QACpD,IAAIF,eAAeP,GAAG,CAACnD,KAAKtD,EAAE,GAAG;YAC/B;QACF;QAEAgH,eAAenD,GAAG,CAACP,KAAKtD,EAAE;QAE1B,MAAM4G,WAAW1E,mBAAmBX,GAAG,CAAC+B,KAAKtD,EAAE,KAAK,EAAE;QACtD,MAAMmH,QAAQO,YAAY/G,MAAM;QAChC,MAAMgH,aAAaV,cAAcC,cAAcC;QAE/CL,YAAYnF,IAAI,CAAC;YACf,GAAI2B,KAAKhD,GAAG;YACZc,uBAAuBsG;YACvBE,iBAAiBT;YACjBU,uBAAuBjB,SAASjG,MAAM,GAAG;YACzCE,cAAcyC,KAAKtD,EAAE;YACrB8H,sBAAsBhB,YAAYnG,MAAM;YACxCoH,oBAAoBzB,0BAA0B/E,GAAG,CAAC+B,KAAKtD,EAAE,KAAK;YAC9DgI,sBAAsBL;QACxB;QAEA,KAAK,MAAMH,SAASZ,SAAU;YAC5Ba,MAAMD,OAAO;mBAAIE;gBAAapE,KAAKtD,EAAE;aAAC,EAAEkH;QAC1C;IACF;IAEA,MAAMe,QAAQ;WAAK/F,mBAAmBX,GAAG,CAAC,SAAS,EAAE;KAAE;IAEvD,KAAK,MAAM2G,QAAQD,MAAO;QACxBR,MAAMS,MAAM,EAAE,EAAEZ,gBAAgBY;IAClC;IAEA,MAAMC,gBAAgB5B,mBAAmB;WAAIxD;KAAM,CAACiB,IAAI,CAACuC,oBAAoBxD;IAE7E,KAAK,MAAMO,QAAQ6E,cAAe;QAChC,IAAI,CAACnB,eAAeP,GAAG,CAACnD,KAAKtD,EAAE,GAAG;YAChCyH,MAAMnE,MAAM,EAAE,EAAEgE,gBAAgBhE;QAClC;IACF;IAEA,OAAOwD;AACT;AAEA,OAAO,SAASsB,mBACdnG,IAAmB,EACnBoG,YAAiC;IAEjC,OAAOpG,KAAKT,MAAM,CAAC,CAAClB,MAClBA,IAAIc,qBAAqB,CAACkH,KAAK,CAAC,CAAChH,aAAe,CAAC+G,aAAa5B,GAAG,CAACnF;AAEtE"}
|