@agent-native/core 0.114.0 → 0.114.1
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/corpus/README.md +2 -2
- package/corpus/core/CHANGELOG.md +9 -0
- package/corpus/core/package.json +1 -1
- package/corpus/core/src/client/build-compatibility.ts +77 -0
- package/corpus/core/src/client/route-chunk-recovery/index.ts +1 -0
- package/corpus/core/src/client/use-action.ts +32 -1
- package/corpus/core/src/deploy/build.ts +4 -1
- package/corpus/core/src/org/context.ts +56 -30
- package/corpus/core/src/server/action-routes.ts +52 -2
- package/corpus/core/src/server/auth-plugin.ts +9 -4
- package/corpus/core/src/server/better-auth-instance.ts +5 -1
- package/corpus/core/src/shared/mcp-embed-headers.ts +1 -1
- package/corpus/core/src/vite/client.ts +17 -0
- package/corpus/templates/content/AGENTS.md +2 -0
- package/corpus/templates/content/actions/_content-database-personal-view.ts +49 -5
- package/corpus/templates/content/actions/_content-document-access.ts +21 -0
- package/corpus/templates/content/actions/_content-favorites.ts +91 -0
- package/corpus/templates/content/actions/_content-files.ts +79 -23
- package/corpus/templates/content/actions/_content-sidebar-state.ts +24 -0
- package/corpus/templates/content/actions/_content-space-access.ts +15 -17
- package/corpus/templates/content/actions/_content-space-catalog-guards.ts +20 -0
- package/corpus/templates/content/actions/_content-spaces.ts +364 -167
- package/corpus/templates/content/actions/_database-source-utils.ts +8 -0
- package/corpus/templates/content/actions/_database-utils.ts +249 -15
- package/corpus/templates/content/actions/_delete-content-space.ts +84 -0
- package/corpus/templates/content/actions/_files-system-properties.ts +499 -0
- package/corpus/templates/content/actions/_local-file-documents.ts +0 -1
- package/corpus/templates/content/actions/_property-utils.ts +18 -9
- package/corpus/templates/content/actions/bind-content-database-source-field.ts +3 -0
- package/corpus/templates/content/actions/configure-document-property.ts +3 -0
- package/corpus/templates/content/actions/create-content-database.ts +2 -2
- package/corpus/templates/content/actions/create-content-space.ts +34 -0
- package/corpus/templates/content/actions/create-document.ts +4 -1
- package/corpus/templates/content/actions/delete-content-space.ts +19 -0
- package/corpus/templates/content/actions/delete-database-items.ts +28 -1
- package/corpus/templates/content/actions/delete-document-property.ts +3 -0
- package/corpus/templates/content/actions/delete-document.ts +39 -2
- package/corpus/templates/content/actions/duplicate-database-item.ts +6 -0
- package/corpus/templates/content/actions/duplicate-database-items.ts +6 -0
- package/corpus/templates/content/actions/duplicate-document-property.ts +3 -0
- package/corpus/templates/content/actions/get-content-database.ts +11 -2
- package/corpus/templates/content/actions/get-content-sidebar-state.ts +23 -0
- package/corpus/templates/content/actions/get-document.ts +32 -7
- package/corpus/templates/content/actions/import-content-source.ts +33 -1
- package/corpus/templates/content/actions/list-content-spaces.ts +34 -2
- package/corpus/templates/content/actions/list-documents.ts +39 -7
- package/corpus/templates/content/actions/reorder-document-property.ts +9 -0
- package/corpus/templates/content/actions/set-document-property.ts +41 -23
- package/corpus/templates/content/actions/share-local-file-document.ts +15 -0
- package/corpus/templates/content/actions/submit-content-database-form.ts +7 -0
- package/corpus/templates/content/actions/sync-local-folder-source.ts +14 -0
- package/corpus/templates/content/actions/update-content-database-view.ts +1 -0
- package/corpus/templates/content/actions/update-content-sidebar-state.ts +27 -0
- package/corpus/templates/content/actions/update-document.ts +158 -66
- package/corpus/templates/content/app/components/EmptyState.tsx +4 -57
- package/corpus/templates/content/app/components/editor/CommentsSidebar.tsx +8 -1
- package/corpus/templates/content/app/components/editor/DocumentEditor.tsx +519 -178
- package/corpus/templates/content/app/components/editor/DocumentInfoPanel.tsx +39 -0
- package/corpus/templates/content/app/components/editor/DocumentProperties.tsx +1 -1
- package/corpus/templates/content/app/components/editor/DocumentToolbar.tsx +266 -7
- package/corpus/templates/content/app/components/editor/database/DatabaseView.tsx +430 -152
- package/corpus/templates/content/app/components/editor/database/sidebar.tsx +467 -66
- package/corpus/templates/content/app/components/editor/database/view-config.ts +9 -3
- package/corpus/templates/content/app/components/sidebar/DocumentSidebar.tsx +720 -196
- package/corpus/templates/content/app/components/sidebar/DocumentTreeItem.tsx +173 -1
- package/corpus/templates/content/app/components/sidebar/document-sidebar-sections.ts +1 -1
- package/corpus/templates/content/app/components/sidebar/select-content-space.ts +91 -16
- package/corpus/templates/content/app/entry.client.tsx +5 -1
- package/corpus/templates/content/app/hooks/use-content-database.ts +84 -3
- package/corpus/templates/content/app/hooks/use-content-spaces.ts +60 -2
- package/corpus/templates/content/app/hooks/use-create-page.ts +30 -0
- package/corpus/templates/content/app/hooks/use-documents.ts +270 -19
- package/corpus/templates/content/app/i18n-data.ts +243 -20
- package/corpus/templates/content/app/lib/local-folder-picker-safety.ts +54 -0
- package/corpus/templates/content/app/lib/local-folder-picker-support.ts +18 -0
- package/corpus/templates/content/app/routes/_app.favorites.tsx +30 -0
- package/corpus/templates/content/app/routes/_app.local-files.tsx +18 -6
- package/corpus/templates/content/changelog/2026-07-17-workspace-files-now-stay-in-a-loading-state-until-automatic-.md +6 -0
- package/corpus/templates/content/changelog/2026-07-17-workspace-switching-now-opens-the-selected-files-database-pr.md +6 -0
- package/corpus/templates/content/changelog/2026-07-17-workspaces-now-expand-above-their-own-files-list-without-dup.md +6 -0
- package/corpus/templates/content/changelog/2026-07-18-create-named-workspaces-each-with-its-own-private-files-data.md +6 -0
- package/corpus/templates/content/changelog/2026-07-18-favorites-align-with-workspace-and-file-rows-in-the-sidebar.md +6 -0
- package/corpus/templates/content/changelog/2026-07-18-local-folder-selection-no-longer-invokes-the-unsafe-native-p.md +6 -0
- package/corpus/templates/content/changelog/2026-07-18-made-content-workspaces-independently-expandable-restored-or.md +6 -0
- package/corpus/templates/content/changelog/2026-07-18-page-details-now-live-in-a-shared-info-and-comments-rail-dat.md +6 -0
- package/corpus/templates/content/changelog/2026-07-18-workspace-database-views-now-control-sidebar-workspace-navig.md +6 -0
- package/corpus/templates/content/changelog/2026-07-18-workspace-navigation-now-aligns-favorites-with-workspace-pag.md +6 -0
- package/corpus/templates/content/changelog/2026-07-19-favorites-now-open-as-a-table-and-compact-breadcrumbs-make-w.md +6 -0
- package/corpus/templates/content/changelog/2026-07-19-files-databases-now-start-unfiltered-sidebar-rows-exactly-fo.md +6 -0
- package/corpus/templates/content/changelog/2026-07-19-sidebar-page-trees-now-open-only-when-expanded-remember-thei.md +6 -0
- package/corpus/templates/content/changelog/2026-07-19-workspace-file-databases-now-use-the-workspace-name-open-as-.md +6 -0
- package/corpus/templates/content/changelog/2026-07-19-workspace-navigation-now-stays-stable-on-hover-uses-folder-i.md +6 -0
- package/corpus/templates/content/changelog/2026-07-19-workspace-rows-now-use-folder-icons-and-deleting-a-user-crea.md +6 -0
- package/corpus/templates/content/changelog/2026-07-19-workspaces-can-be-created-without-leaving-the-workspaces-dat.md +6 -0
- package/corpus/templates/content/e2e/global-setup.ts +3 -2
- package/corpus/templates/content/parity/matrix.md +28 -28
- package/corpus/templates/content/parity/matrix.ts +8 -2
- package/corpus/templates/content/server/db/index.ts +1 -0
- package/corpus/templates/content/server/db/schema.ts +10 -0
- package/corpus/templates/content/server/lib/documents.ts +12 -7
- package/corpus/templates/content/server/plugins/db.ts +17 -0
- package/corpus/templates/content/shared/api.ts +9 -0
- package/corpus/templates/content/shared/database-form.ts +11 -2
- package/corpus/templates/content/vite.config.ts +1 -0
- package/dist/client/build-compatibility.d.ts +11 -0
- package/dist/client/build-compatibility.d.ts.map +1 -0
- package/dist/client/build-compatibility.js +56 -0
- package/dist/client/build-compatibility.js.map +1 -0
- package/dist/client/route-chunk-recovery/index.d.ts +1 -0
- package/dist/client/route-chunk-recovery/index.d.ts.map +1 -1
- package/dist/client/route-chunk-recovery/index.js +1 -0
- package/dist/client/route-chunk-recovery/index.js.map +1 -1
- package/dist/client/use-action.d.ts.map +1 -1
- package/dist/client/use-action.js +19 -1
- package/dist/client/use-action.js.map +1 -1
- package/dist/collab/routes.d.ts +1 -1
- package/dist/collab/struct-routes.d.ts +1 -1
- package/dist/deploy/build.js +2 -1
- package/dist/deploy/build.js.map +1 -1
- package/dist/file-upload/actions/upload-image.d.ts +1 -1
- package/dist/notifications/routes.d.ts +1 -1
- package/dist/observability/routes.d.ts +5 -5
- package/dist/org/context.d.ts +4 -2
- package/dist/org/context.d.ts.map +1 -1
- package/dist/org/context.js +44 -22
- package/dist/org/context.js.map +1 -1
- package/dist/progress/routes.d.ts +1 -1
- package/dist/provider-api/actions/custom-provider-registration.d.ts +10 -10
- package/dist/provider-api/actions/provider-api.d.ts +12 -12
- package/dist/provider-api/corpus-jobs.d.ts +2 -2
- package/dist/resources/handlers.d.ts +1 -1
- package/dist/secrets/routes.d.ts +9 -9
- package/dist/server/action-routes.d.ts.map +1 -1
- package/dist/server/action-routes.js +32 -2
- package/dist/server/action-routes.js.map +1 -1
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/dist/server/auth-plugin.d.ts.map +1 -1
- package/dist/server/auth-plugin.js +9 -5
- package/dist/server/auth-plugin.js.map +1 -1
- package/dist/server/better-auth-instance.d.ts.map +1 -1
- package/dist/server/better-auth-instance.js +4 -1
- package/dist/server/better-auth-instance.js.map +1 -1
- package/dist/server/transcribe-voice.d.ts +1 -1
- package/dist/shared/mcp-embed-headers.d.ts +1 -1
- package/dist/shared/mcp-embed-headers.d.ts.map +1 -1
- package/dist/shared/mcp-embed-headers.js +1 -1
- package/dist/shared/mcp-embed-headers.js.map +1 -1
- package/dist/vite/client.d.ts +6 -0
- package/dist/vite/client.d.ts.map +1 -1
- package/dist/vite/client.js +8 -0
- package/dist/vite/client.js.map +1 -1
- package/package.json +1 -1
- package/src/client/build-compatibility.ts +77 -0
- package/src/client/route-chunk-recovery/index.ts +1 -0
- package/src/client/use-action.ts +32 -1
- package/src/deploy/build.ts +4 -1
- package/src/org/context.ts +56 -30
- package/src/server/action-routes.ts +52 -2
- package/src/server/auth-plugin.ts +9 -4
- package/src/server/better-auth-instance.ts +5 -1
- package/src/shared/mcp-embed-headers.ts +1 -1
- package/src/vite/client.ts +17 -0
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import { useCodeMode } from "@agent-native/core/client/agent-chat";
|
|
2
2
|
import { agentNativePath } from "@agent-native/core/client/api-path";
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
getBrowserTabId,
|
|
5
|
+
setClientAppState,
|
|
6
|
+
useSession,
|
|
7
|
+
} from "@agent-native/core/client/hooks";
|
|
4
8
|
import { useT } from "@agent-native/core/client/i18n";
|
|
5
9
|
import {
|
|
6
10
|
useBuilderConnectFlow,
|
|
@@ -48,6 +52,7 @@ import {
|
|
|
48
52
|
TooltipTrigger,
|
|
49
53
|
} from "@agent-native/toolkit/ui/tooltip";
|
|
50
54
|
import {
|
|
55
|
+
CONTENT_DATABASE_PERSONAL_VIEW_OVERRIDES_VERSION,
|
|
51
56
|
type BuilderCmsModelSummary,
|
|
52
57
|
type ContentDatabaseItem,
|
|
53
58
|
type ContentDatabaseResponse,
|
|
@@ -111,11 +116,11 @@ import {
|
|
|
111
116
|
IconEyeOff,
|
|
112
117
|
IconFilter,
|
|
113
118
|
IconFileText,
|
|
119
|
+
IconFolder,
|
|
114
120
|
IconForms,
|
|
115
121
|
IconGripVertical,
|
|
116
122
|
IconLayoutKanban,
|
|
117
123
|
IconLayoutGrid,
|
|
118
|
-
IconLayoutSidebar,
|
|
119
124
|
IconList,
|
|
120
125
|
IconLock,
|
|
121
126
|
IconMinus,
|
|
@@ -125,6 +130,7 @@ import {
|
|
|
125
130
|
IconPencil,
|
|
126
131
|
IconRefresh,
|
|
127
132
|
IconSearch,
|
|
133
|
+
IconStarOff,
|
|
128
134
|
IconTable,
|
|
129
135
|
IconTimeline,
|
|
130
136
|
IconTrash,
|
|
@@ -145,6 +151,12 @@ import {
|
|
|
145
151
|
import { Link, useLocation, useNavigate } from "react-router";
|
|
146
152
|
import { toast } from "sonner";
|
|
147
153
|
|
|
154
|
+
import {
|
|
155
|
+
contentSpaceForCatalogItem,
|
|
156
|
+
createContentSpaceSelectionQueue,
|
|
157
|
+
SELECTED_CONTENT_SPACE_STORAGE_KEY,
|
|
158
|
+
selectContentSpace,
|
|
159
|
+
} from "@/components/sidebar/select-content-space";
|
|
148
160
|
import {
|
|
149
161
|
isContentDatabaseUnavailable,
|
|
150
162
|
useAddDatabaseItem,
|
|
@@ -174,6 +186,11 @@ import {
|
|
|
174
186
|
useUpdateContentDatabasePersonalView,
|
|
175
187
|
useUpdateContentDatabaseView,
|
|
176
188
|
} from "@/hooks/use-content-database";
|
|
189
|
+
import {
|
|
190
|
+
useContentSpaces,
|
|
191
|
+
useCreateContentSpace,
|
|
192
|
+
useDeleteContentSpace,
|
|
193
|
+
} from "@/hooks/use-content-spaces";
|
|
177
194
|
import {
|
|
178
195
|
useConfigureDocumentProperty,
|
|
179
196
|
useSetDocumentProperty,
|
|
@@ -187,6 +204,7 @@ import {
|
|
|
187
204
|
useUpdatePreviewDocumentDraft,
|
|
188
205
|
useUpdateDocument,
|
|
189
206
|
} from "@/hooks/use-documents";
|
|
207
|
+
import { useLocalStorage } from "@/hooks/use-local-storage";
|
|
190
208
|
import { messagesByLocale } from "@/i18n-data";
|
|
191
209
|
import { cn } from "@/lib/utils";
|
|
192
210
|
|
|
@@ -210,7 +228,6 @@ import {
|
|
|
210
228
|
BuilderSourceReviewDialog,
|
|
211
229
|
type BuilderReviewPublicationTransitions,
|
|
212
230
|
} from "../database-sources/BuilderSourceReviewDialog";
|
|
213
|
-
import { DescriptionField } from "../DescriptionField";
|
|
214
231
|
import { DocumentBlockFields } from "../DocumentBlockFields";
|
|
215
232
|
import {
|
|
216
233
|
AddProperty,
|
|
@@ -248,7 +265,6 @@ import { VisualEditor } from "../VisualEditor";
|
|
|
248
265
|
import { DatabaseFormView } from "./FormView";
|
|
249
266
|
import { DatabaseGalleryView } from "./GalleryView";
|
|
250
267
|
import { DatabaseListView } from "./ListView";
|
|
251
|
-
import { DatabaseSidebarView } from "./sidebar";
|
|
252
268
|
import { DatabaseTimelineView } from "./TimelineView";
|
|
253
269
|
|
|
254
270
|
export interface DatabaseViewProps {
|
|
@@ -283,6 +299,26 @@ export function databaseSearchExpansionIsPending(
|
|
|
283
299
|
return !!searchQuery.trim() && responseLimit < requestedLimit;
|
|
284
300
|
}
|
|
285
301
|
|
|
302
|
+
export function databaseClientQueryExpandedItemLimit(
|
|
303
|
+
requiresCompleteDataset: boolean,
|
|
304
|
+
currentLimit: number,
|
|
305
|
+
totalItemCount: number,
|
|
306
|
+
) {
|
|
307
|
+
if (!requiresCompleteDataset) return currentLimit;
|
|
308
|
+
return Math.max(
|
|
309
|
+
currentLimit,
|
|
310
|
+
Math.min(totalItemCount, CONTENT_DATABASE_MAX_ITEM_LIMIT),
|
|
311
|
+
);
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
export function databaseClientQueryExpansionIsPending(
|
|
315
|
+
requiresCompleteDataset: boolean,
|
|
316
|
+
requestedLimit: number,
|
|
317
|
+
responseLimit: number,
|
|
318
|
+
) {
|
|
319
|
+
return requiresCompleteDataset && responseLimit < requestedLimit;
|
|
320
|
+
}
|
|
321
|
+
|
|
286
322
|
export type SortDirection = ContentDatabaseSortDirection;
|
|
287
323
|
export type DatabaseSort = ContentDatabaseSort;
|
|
288
324
|
export type FilterOperator = ContentDatabaseFilterOperator;
|
|
@@ -308,7 +344,6 @@ const DATABASE_VIEW_TYPES: ContentDatabaseViewType[] = [
|
|
|
308
344
|
"timeline",
|
|
309
345
|
"calendar",
|
|
310
346
|
"form",
|
|
311
|
-
"sidebar",
|
|
312
347
|
];
|
|
313
348
|
const DATABASE_OPEN_PAGES_IN: ContentDatabaseOpenPagesIn[] = [
|
|
314
349
|
"preview",
|
|
@@ -316,7 +351,8 @@ const DATABASE_OPEN_PAGES_IN: ContentDatabaseOpenPagesIn[] = [
|
|
|
316
351
|
];
|
|
317
352
|
const DATABASE_FILTER_MODES: DatabaseFilterMode[] = ["and", "or"];
|
|
318
353
|
const DATABASE_ADVANCED_FILTER_GROUP_ID = "advanced";
|
|
319
|
-
export const PERSONAL_DATABASE_VIEW_OVERRIDES_VERSION =
|
|
354
|
+
export const PERSONAL_DATABASE_VIEW_OVERRIDES_VERSION =
|
|
355
|
+
CONTENT_DATABASE_PERSONAL_VIEW_OVERRIDES_VERSION;
|
|
320
356
|
export const BUILDER_SOURCE_CONTINUATION_STALL_MS = 5_000;
|
|
321
357
|
export const BUILDER_SOURCE_CONTINUATION_MAX_BACKOFF_MS = 30_000;
|
|
322
358
|
|
|
@@ -350,6 +386,7 @@ export function previewDraftMissingCasRecovery(args: {
|
|
|
350
386
|
}
|
|
351
387
|
|
|
352
388
|
type DatabaseMessageKey = keyof (typeof messagesByLocale)["en-US"]["database"];
|
|
389
|
+
type SidebarMessageKey = keyof (typeof messagesByLocale)["en-US"]["sidebar"];
|
|
353
390
|
|
|
354
391
|
export function dbText(
|
|
355
392
|
key: DatabaseMessageKey,
|
|
@@ -370,6 +407,15 @@ export function dbText(
|
|
|
370
407
|
);
|
|
371
408
|
}
|
|
372
409
|
|
|
410
|
+
function sidebarText(key: SidebarMessageKey): string {
|
|
411
|
+
const locale =
|
|
412
|
+
typeof document === "undefined" ? "en-US" : document.documentElement.lang;
|
|
413
|
+
const messages =
|
|
414
|
+
messagesByLocale[locale as keyof typeof messagesByLocale] ??
|
|
415
|
+
messagesByLocale["en-US"];
|
|
416
|
+
return messages.sidebar[key] ?? messagesByLocale["en-US"].sidebar[key];
|
|
417
|
+
}
|
|
418
|
+
|
|
373
419
|
export type CreateDatabaseRowHandler = (
|
|
374
420
|
title?: string,
|
|
375
421
|
) => Promise<ContentDatabaseItem | null>;
|
|
@@ -595,10 +641,12 @@ export function DatabaseItemPageIcon({
|
|
|
595
641
|
document,
|
|
596
642
|
className,
|
|
597
643
|
fallbackClassName,
|
|
644
|
+
fallback = "page",
|
|
598
645
|
}: {
|
|
599
646
|
document: Pick<Document, "icon">;
|
|
600
647
|
className?: string;
|
|
601
648
|
fallbackClassName?: string;
|
|
649
|
+
fallback?: "page" | "folder";
|
|
602
650
|
}) {
|
|
603
651
|
const icon = databaseItemPageIconText(document);
|
|
604
652
|
if (icon) {
|
|
@@ -615,8 +663,9 @@ export function DatabaseItemPageIcon({
|
|
|
615
663
|
);
|
|
616
664
|
}
|
|
617
665
|
|
|
666
|
+
const FallbackIcon = fallback === "folder" ? IconFolder : IconFileText;
|
|
618
667
|
return (
|
|
619
|
-
<
|
|
668
|
+
<FallbackIcon
|
|
620
669
|
className={cn("shrink-0 text-muted-foreground", fallbackClassName)}
|
|
621
670
|
/>
|
|
622
671
|
);
|
|
@@ -667,11 +716,21 @@ function DatabaseTable({
|
|
|
667
716
|
const t = useT();
|
|
668
717
|
const navigate = useNavigate();
|
|
669
718
|
const queryClient = useQueryClient();
|
|
670
|
-
const
|
|
719
|
+
const contentSpacesQuery = useContentSpaces();
|
|
720
|
+
const [, setStoredSpaceId] = useLocalStorage<string | null>(
|
|
721
|
+
SELECTED_CONTENT_SPACE_STORAGE_KEY,
|
|
722
|
+
null,
|
|
723
|
+
);
|
|
724
|
+
const [manualDatabaseItemLimit, setManualDatabaseItemLimit] = useState(
|
|
725
|
+
CONTENT_DATABASE_PAGE_SIZE,
|
|
726
|
+
);
|
|
727
|
+
const [databaseRequestItemLimit, setDatabaseRequestItemLimit] = useState(
|
|
671
728
|
CONTENT_DATABASE_PAGE_SIZE,
|
|
672
729
|
);
|
|
673
|
-
const database = useContentDatabase(document.id,
|
|
730
|
+
const database = useContentDatabase(document.id, databaseRequestItemLimit);
|
|
674
731
|
const addItem = useAddDatabaseItem(document.id);
|
|
732
|
+
const createContentSpace = useCreateContentSpace();
|
|
733
|
+
const workspaceCreateRequestIdRef = useRef<string | null>(null);
|
|
675
734
|
const attachSource = useAttachContentDatabaseSource(document.id);
|
|
676
735
|
const changeSourceRole = useChangeContentDatabaseSourceRole(document.id);
|
|
677
736
|
const refreshSource = useRefreshContentDatabaseSource(document.id);
|
|
@@ -684,7 +743,6 @@ function DatabaseTable({
|
|
|
684
743
|
);
|
|
685
744
|
const setSourceWriteMode = useSetContentDatabaseSourceWriteMode(document.id);
|
|
686
745
|
const setProperty = useSetDocumentProperty(document.id, document.id);
|
|
687
|
-
const updateDatabaseDocument = useUpdateDocument();
|
|
688
746
|
const updateView = useUpdateContentDatabaseView(document.id);
|
|
689
747
|
// A deleted/missing database resolves to the unavailable union (no
|
|
690
748
|
// `database` field) — treat it as no data; the inline-block wrapper owns
|
|
@@ -692,16 +750,24 @@ function DatabaseTable({
|
|
|
692
750
|
const data = isContentDatabaseUnavailable(database.data)
|
|
693
751
|
? undefined
|
|
694
752
|
: database.data;
|
|
753
|
+
const isCreatingDatabaseItem =
|
|
754
|
+
data?.database.systemRole === "workspaces"
|
|
755
|
+
? createContentSpace.isPending
|
|
756
|
+
: addItem.isPending;
|
|
695
757
|
const isDatabaseInitialLoading = database.isLoading && !data;
|
|
696
758
|
const properties = data?.properties ?? [];
|
|
697
759
|
const items = data?.items ?? [];
|
|
698
760
|
const totalItemCount = data?.pagination?.totalItems ?? items.length;
|
|
699
761
|
const hasMoreItems =
|
|
700
762
|
data?.pagination?.hasMore === true &&
|
|
701
|
-
|
|
763
|
+
databaseRequestItemLimit < CONTENT_DATABASE_MAX_ITEM_LIMIT;
|
|
702
764
|
const isLoadingMoreItems =
|
|
703
|
-
database.isFetching && data?.pagination?.limit !==
|
|
765
|
+
database.isFetching && data?.pagination?.limit !== databaseRequestItemLimit;
|
|
704
766
|
const databaseId = data?.database.id ?? expectedDatabaseId;
|
|
767
|
+
const newDatabaseRowLabel =
|
|
768
|
+
data?.database.systemRole === "workspaces"
|
|
769
|
+
? t("sidebar.newWorkspace")
|
|
770
|
+
: dbText("newPage");
|
|
705
771
|
const personalView = useContentDatabasePersonalView(databaseId);
|
|
706
772
|
const updatePersonalView = useUpdateContentDatabasePersonalView(databaseId);
|
|
707
773
|
const source = data?.source ?? null;
|
|
@@ -726,18 +792,6 @@ function DatabaseTable({
|
|
|
726
792
|
>(null);
|
|
727
793
|
const [searchOpen, setSearchOpen] = useState(false);
|
|
728
794
|
const [searchQuery, setSearchQuery] = useState("");
|
|
729
|
-
const searchExpandedItemLimit = databaseSearchExpandedItemLimit(
|
|
730
|
-
searchQuery,
|
|
731
|
-
databaseItemLimit,
|
|
732
|
-
totalItemCount,
|
|
733
|
-
);
|
|
734
|
-
const isSearchExpansionPending = databaseSearchExpansionIsPending(
|
|
735
|
-
searchQuery,
|
|
736
|
-
searchExpandedItemLimit,
|
|
737
|
-
data?.pagination?.limit ?? items.length,
|
|
738
|
-
);
|
|
739
|
-
const isDatabaseViewLoading =
|
|
740
|
-
isDatabaseInitialLoading || isSearchExpansionPending;
|
|
741
795
|
const [settingsOpen, setSettingsOpen] = useState(false);
|
|
742
796
|
const [inlineFilterControlsOpen, setInlineFilterControlsOpen] =
|
|
743
797
|
useState(false);
|
|
@@ -753,10 +807,6 @@ function DatabaseTable({
|
|
|
753
807
|
);
|
|
754
808
|
const [builderReviewOpen, setBuilderReviewOpen] = useState(false);
|
|
755
809
|
|
|
756
|
-
useEffect(() => {
|
|
757
|
-
if (searchExpandedItemLimit === databaseItemLimit) return;
|
|
758
|
-
setDatabaseItemLimit(searchExpandedItemLimit);
|
|
759
|
-
}, [databaseItemLimit, searchExpandedItemLimit]);
|
|
760
810
|
const [builderReviewSourceId, setBuilderReviewSourceId] = useState<
|
|
761
811
|
string | null
|
|
762
812
|
>(null);
|
|
@@ -795,6 +845,7 @@ function DatabaseTable({
|
|
|
795
845
|
);
|
|
796
846
|
const sorts = activeView.sorts;
|
|
797
847
|
const filters = activeView.filters;
|
|
848
|
+
const visibleFilters = filters;
|
|
798
849
|
const filterMode = activeView.filterMode ?? "and";
|
|
799
850
|
const columnWidths = activeView.columnWidths;
|
|
800
851
|
const databaseGroupProperty = useMemo(
|
|
@@ -822,6 +873,7 @@ function DatabaseTable({
|
|
|
822
873
|
const builderContinuationWatchdogRef = useRef<Map<string, number>>(new Map());
|
|
823
874
|
const refreshSourceInFlightRef = useRef<string | null>(null);
|
|
824
875
|
const hydrationSourceInFlightRef = useRef<string | null>(null);
|
|
876
|
+
const workspaceSelectionQueueRef = useRef(createContentSpaceSelectionQueue());
|
|
825
877
|
const builderReviewGenerationRef = useRef(0);
|
|
826
878
|
const builderReviewSessionRef = useRef<BuilderReviewSession | null>(null);
|
|
827
879
|
const [
|
|
@@ -884,6 +936,32 @@ function DatabaseTable({
|
|
|
884
936
|
sorts,
|
|
885
937
|
filters,
|
|
886
938
|
);
|
|
939
|
+
const visibleConstraintCount = activeDatabaseConstraintCount(
|
|
940
|
+
searchQuery,
|
|
941
|
+
sorts,
|
|
942
|
+
visibleFilters,
|
|
943
|
+
);
|
|
944
|
+
const requiresCompleteClientDataset =
|
|
945
|
+
activeConstraintCount > 0 ||
|
|
946
|
+
!!databaseGroupProperty ||
|
|
947
|
+
activeView.type === "calendar" ||
|
|
948
|
+
activeView.type === "timeline";
|
|
949
|
+
const clientQueryExpandedItemLimit = databaseClientQueryExpandedItemLimit(
|
|
950
|
+
requiresCompleteClientDataset,
|
|
951
|
+
manualDatabaseItemLimit,
|
|
952
|
+
totalItemCount,
|
|
953
|
+
);
|
|
954
|
+
const isClientQueryExpansionPending = databaseClientQueryExpansionIsPending(
|
|
955
|
+
requiresCompleteClientDataset,
|
|
956
|
+
clientQueryExpandedItemLimit,
|
|
957
|
+
data?.pagination?.limit ?? items.length,
|
|
958
|
+
);
|
|
959
|
+
const isDatabaseViewLoading =
|
|
960
|
+
isDatabaseInitialLoading || isClientQueryExpansionPending;
|
|
961
|
+
useEffect(() => {
|
|
962
|
+
if (clientQueryExpandedItemLimit === databaseRequestItemLimit) return;
|
|
963
|
+
setDatabaseRequestItemLimit(clientQueryExpandedItemLimit);
|
|
964
|
+
}, [clientQueryExpandedItemLimit, databaseRequestItemLimit]);
|
|
887
965
|
const rowsAreManuallyOrdered =
|
|
888
966
|
!searchQuery.trim() &&
|
|
889
967
|
sorts.length === 0 &&
|
|
@@ -1239,6 +1317,7 @@ function DatabaseTable({
|
|
|
1239
1317
|
]);
|
|
1240
1318
|
|
|
1241
1319
|
function previewItemPage(item: ContentDatabaseItem) {
|
|
1320
|
+
if (openWorkspaceFiles(item)) return;
|
|
1242
1321
|
seedDatabaseItemDocumentCaches(queryClient, item);
|
|
1243
1322
|
prioritizeBuilderBodyHydrationForItem(item);
|
|
1244
1323
|
if (activeView.openPagesIn === "full_page") {
|
|
@@ -1278,11 +1357,50 @@ function DatabaseTable({
|
|
|
1278
1357
|
}
|
|
1279
1358
|
|
|
1280
1359
|
function openItemPage(item: ContentDatabaseItem) {
|
|
1360
|
+
if (openWorkspaceFiles(item)) return;
|
|
1281
1361
|
seedDatabaseItemDocumentCaches(queryClient, item);
|
|
1282
1362
|
prioritizeBuilderBodyHydrationForItem(item);
|
|
1283
1363
|
navigate(`/page/${item.document.id}`);
|
|
1284
1364
|
}
|
|
1285
1365
|
|
|
1366
|
+
function openWorkspaceFiles(item: ContentDatabaseItem) {
|
|
1367
|
+
if (data?.database.systemRole !== "workspaces") {
|
|
1368
|
+
return false;
|
|
1369
|
+
}
|
|
1370
|
+
const spacesResponse = contentSpacesQuery.data;
|
|
1371
|
+
if (!spacesResponse) return false;
|
|
1372
|
+
const space = contentSpaceForCatalogItem({
|
|
1373
|
+
databaseId,
|
|
1374
|
+
catalogDatabaseId: spacesResponse.catalogDatabaseId,
|
|
1375
|
+
documentId: item.document.id,
|
|
1376
|
+
spaces: spacesResponse.spaces,
|
|
1377
|
+
});
|
|
1378
|
+
if (!space) return false;
|
|
1379
|
+
void workspaceSelectionQueueRef
|
|
1380
|
+
.current(async () => {
|
|
1381
|
+
await selectContentSpace({
|
|
1382
|
+
space,
|
|
1383
|
+
syncApplicationState: (selected) =>
|
|
1384
|
+
setClientAppState(
|
|
1385
|
+
"content-space",
|
|
1386
|
+
{
|
|
1387
|
+
spaceId: selected.id,
|
|
1388
|
+
name: selected.name,
|
|
1389
|
+
kind: selected.kind,
|
|
1390
|
+
filesDatabaseId: selected.filesDatabaseId,
|
|
1391
|
+
},
|
|
1392
|
+
{ requestSource: "content-workspaces-database" },
|
|
1393
|
+
),
|
|
1394
|
+
persistSelection: setStoredSpaceId,
|
|
1395
|
+
openFiles: (documentId) => navigate(`/page/${documentId}`),
|
|
1396
|
+
});
|
|
1397
|
+
})
|
|
1398
|
+
.catch((error) => {
|
|
1399
|
+
toast.error(error instanceof Error ? error.message : String(error));
|
|
1400
|
+
});
|
|
1401
|
+
return true;
|
|
1402
|
+
}
|
|
1403
|
+
|
|
1286
1404
|
function prioritizeBuilderBodyHydrationForItem(item: ContentDatabaseItem) {
|
|
1287
1405
|
const builderSource = databaseBuilderHydrationSourceForItem(item, sources);
|
|
1288
1406
|
if (!builderSource) return;
|
|
@@ -1309,6 +1427,29 @@ function DatabaseTable({
|
|
|
1309
1427
|
} = {},
|
|
1310
1428
|
) {
|
|
1311
1429
|
if (!databaseId) return null;
|
|
1430
|
+
if (data?.database.systemRole === "workspaces") {
|
|
1431
|
+
const name = title.trim() || t("sidebar.newWorkspace");
|
|
1432
|
+
const requestId =
|
|
1433
|
+
workspaceCreateRequestIdRef.current ?? crypto.randomUUID();
|
|
1434
|
+
workspaceCreateRequestIdRef.current = requestId;
|
|
1435
|
+
try {
|
|
1436
|
+
await createContentSpace.mutateAsync({
|
|
1437
|
+
name,
|
|
1438
|
+
requestId,
|
|
1439
|
+
propertyValues:
|
|
1440
|
+
Object.keys(propertyValueOverrides).length > 0
|
|
1441
|
+
? propertyValueOverrides
|
|
1442
|
+
: undefined,
|
|
1443
|
+
});
|
|
1444
|
+
workspaceCreateRequestIdRef.current = null;
|
|
1445
|
+
} catch (err) {
|
|
1446
|
+
toast.error(dbText("failedToCreateRow"), {
|
|
1447
|
+
description:
|
|
1448
|
+
err instanceof Error ? err.message : dbText("somethingWentWrong"),
|
|
1449
|
+
});
|
|
1450
|
+
}
|
|
1451
|
+
return null;
|
|
1452
|
+
}
|
|
1312
1453
|
const propertyValues = {
|
|
1313
1454
|
...databasePropertyValuesForNewItem(filters, properties, filterMode),
|
|
1314
1455
|
...propertyValueOverrides,
|
|
@@ -2012,28 +2153,6 @@ function DatabaseTable({
|
|
|
2012
2153
|
orderedProperties,
|
|
2013
2154
|
visibleItems,
|
|
2014
2155
|
]);
|
|
2015
|
-
const sidebarGroups = useMemo(
|
|
2016
|
-
() =>
|
|
2017
|
-
databaseVisibleGroups(
|
|
2018
|
-
databaseViewItemGroups(
|
|
2019
|
-
visibleItems,
|
|
2020
|
-
orderedProperties,
|
|
2021
|
-
activeView.groupByPropertyId,
|
|
2022
|
-
),
|
|
2023
|
-
activeView.hideEmptyGroups === true,
|
|
2024
|
-
),
|
|
2025
|
-
[
|
|
2026
|
-
activeView.groupByPropertyId,
|
|
2027
|
-
activeView.hideEmptyGroups,
|
|
2028
|
-
orderedProperties,
|
|
2029
|
-
visibleItems,
|
|
2030
|
-
],
|
|
2031
|
-
);
|
|
2032
|
-
const sidebarIsGrouped = useMemo(
|
|
2033
|
-
() => !!databaseViewGroupingProperty(activeView, orderedProperties),
|
|
2034
|
-
[activeView, orderedProperties],
|
|
2035
|
-
);
|
|
2036
|
-
|
|
2037
2156
|
useEffect(() => {
|
|
2038
2157
|
if (!data?.database.id) return;
|
|
2039
2158
|
if (personalView.isLoading) return;
|
|
@@ -2155,19 +2274,6 @@ function DatabaseTable({
|
|
|
2155
2274
|
|
|
2156
2275
|
return (
|
|
2157
2276
|
<div className="mt-4 min-w-0 w-full max-w-[calc(100vw-var(--content-sidebar-width,0px)-1.5rem)]">
|
|
2158
|
-
<DescriptionField
|
|
2159
|
-
description={document.description}
|
|
2160
|
-
canEdit={canEdit}
|
|
2161
|
-
label={t("editor.properties.description")}
|
|
2162
|
-
placeholder={t("editor.properties.addDatabaseDescription")}
|
|
2163
|
-
className="mb-3"
|
|
2164
|
-
onSave={(description) =>
|
|
2165
|
-
updateDatabaseDocument.mutateAsync({
|
|
2166
|
-
id: document.id,
|
|
2167
|
-
description,
|
|
2168
|
-
})
|
|
2169
|
-
}
|
|
2170
|
-
/>
|
|
2171
2277
|
<div className="mb-1 flex min-h-8 flex-wrap items-center justify-between gap-x-3 gap-y-1 pb-1">
|
|
2172
2278
|
<DatabaseViewTabs
|
|
2173
2279
|
viewConfig={viewConfig}
|
|
@@ -2225,7 +2331,7 @@ function DatabaseTable({
|
|
|
2225
2331
|
onSortsChange={setActiveSorts}
|
|
2226
2332
|
/>
|
|
2227
2333
|
<FilterMenu
|
|
2228
|
-
filters={
|
|
2334
|
+
filters={visibleFilters}
|
|
2229
2335
|
properties={orderedProperties}
|
|
2230
2336
|
inlineOpen={inlineFilterControlsOpen}
|
|
2231
2337
|
open={toolbarFilterOpen}
|
|
@@ -2316,10 +2422,10 @@ function DatabaseTable({
|
|
|
2316
2422
|
type="button"
|
|
2317
2423
|
size="sm"
|
|
2318
2424
|
className="h-7 rounded-md bg-foreground px-2.5 text-xs font-medium text-background hover:bg-foreground/90"
|
|
2319
|
-
disabled={
|
|
2425
|
+
disabled={isCreatingDatabaseItem || !databaseId}
|
|
2320
2426
|
onClick={() => void createRow()}
|
|
2321
2427
|
>
|
|
2322
|
-
{
|
|
2428
|
+
{isCreatingDatabaseItem ? (
|
|
2323
2429
|
<Spinner className="mr-1.5 size-3.5" />
|
|
2324
2430
|
) : null}
|
|
2325
2431
|
New
|
|
@@ -2336,7 +2442,7 @@ function DatabaseTable({
|
|
|
2336
2442
|
filters={filters}
|
|
2337
2443
|
filterMode={filterMode}
|
|
2338
2444
|
properties={properties}
|
|
2339
|
-
constraintCount={
|
|
2445
|
+
constraintCount={visibleConstraintCount}
|
|
2340
2446
|
forceShow={inlineFilterControlsOpen}
|
|
2341
2447
|
addFilterOpen={inlineAddFilterOpen}
|
|
2342
2448
|
openSortIndex={inlineSortOpenIndex}
|
|
@@ -2436,7 +2542,7 @@ function DatabaseTable({
|
|
|
2436
2542
|
databaseDocumentId={document.id}
|
|
2437
2543
|
canEdit={canEdit}
|
|
2438
2544
|
isLoading={isDatabaseViewLoading}
|
|
2439
|
-
isCreating={
|
|
2545
|
+
isCreating={isCreatingDatabaseItem || setProperty.isPending}
|
|
2440
2546
|
hasActiveConstraints={!!searchQuery || activeFilters.length > 0}
|
|
2441
2547
|
isMoving={setProperty.isPending}
|
|
2442
2548
|
collapsedGroupIds={activeView.collapsedGroupIds ?? []}
|
|
@@ -2456,22 +2562,6 @@ function DatabaseTable({
|
|
|
2456
2562
|
onDeletedPreviewItem={handleDeletedPreviewItem}
|
|
2457
2563
|
onOpenPage={openItemPage}
|
|
2458
2564
|
/>
|
|
2459
|
-
) : activeView.type === "sidebar" ? (
|
|
2460
|
-
<DatabaseSidebarView
|
|
2461
|
-
key={activeView.id}
|
|
2462
|
-
groups={sidebarGroups}
|
|
2463
|
-
grouped={sidebarIsGrouped}
|
|
2464
|
-
isLoading={isDatabaseViewLoading}
|
|
2465
|
-
hasActiveConstraints={hasResultConstraints}
|
|
2466
|
-
openPagesIn={activeView.openPagesIn ?? "preview"}
|
|
2467
|
-
loadingLabel={dbText("loadingList")}
|
|
2468
|
-
noMatchesLabel={dbText("noRowsMatchThisView")}
|
|
2469
|
-
clearLabel={dbText("clearSearchAndFilters")}
|
|
2470
|
-
navigationLabel={dbText("databasePagePreview")}
|
|
2471
|
-
untitledLabel={dbText("untitled")}
|
|
2472
|
-
onClearResultConstraints={clearSearchAndFilters}
|
|
2473
|
-
onPreview={previewItemPage}
|
|
2474
|
-
/>
|
|
2475
2565
|
) : activeView.type === "list" ? (
|
|
2476
2566
|
<DatabaseListView
|
|
2477
2567
|
properties={tableProperties}
|
|
@@ -2480,7 +2570,7 @@ function DatabaseTable({
|
|
|
2480
2570
|
databaseDocumentId={document.id}
|
|
2481
2571
|
canEdit={canEdit}
|
|
2482
2572
|
isLoading={isDatabaseViewLoading}
|
|
2483
|
-
isCreating={
|
|
2573
|
+
isCreating={isCreatingDatabaseItem}
|
|
2484
2574
|
activeFilters={activeFilters}
|
|
2485
2575
|
hasSearch={!!searchQuery}
|
|
2486
2576
|
rowsAreManuallyOrdered={rowsAreManuallyOrdered}
|
|
@@ -2503,7 +2593,7 @@ function DatabaseTable({
|
|
|
2503
2593
|
databaseDocumentId={document.id}
|
|
2504
2594
|
canEdit={canEdit}
|
|
2505
2595
|
isLoading={isDatabaseViewLoading}
|
|
2506
|
-
isCreating={
|
|
2596
|
+
isCreating={isCreatingDatabaseItem}
|
|
2507
2597
|
activeFilters={activeFilters}
|
|
2508
2598
|
hasSearch={!!searchQuery}
|
|
2509
2599
|
rowsAreManuallyOrdered={rowsAreManuallyOrdered}
|
|
@@ -2526,7 +2616,7 @@ function DatabaseTable({
|
|
|
2526
2616
|
databaseDocumentId={document.id}
|
|
2527
2617
|
canEdit={canEdit}
|
|
2528
2618
|
isLoading={isDatabaseViewLoading}
|
|
2529
|
-
isCreating={
|
|
2619
|
+
isCreating={isCreatingDatabaseItem || setProperty.isPending}
|
|
2530
2620
|
activeFilters={activeFilters}
|
|
2531
2621
|
hasSearch={!!searchQuery}
|
|
2532
2622
|
dateProperty={dateViewProperty}
|
|
@@ -2552,7 +2642,7 @@ function DatabaseTable({
|
|
|
2552
2642
|
databaseDocumentId={document.id}
|
|
2553
2643
|
canEdit={canEdit}
|
|
2554
2644
|
isLoading={isDatabaseViewLoading}
|
|
2555
|
-
isCreating={
|
|
2645
|
+
isCreating={isCreatingDatabaseItem || setProperty.isPending}
|
|
2556
2646
|
activeFilters={activeFilters}
|
|
2557
2647
|
hasSearch={!!searchQuery}
|
|
2558
2648
|
dateProperty={dateViewProperty}
|
|
@@ -2578,6 +2668,7 @@ function DatabaseTable({
|
|
|
2578
2668
|
/>
|
|
2579
2669
|
) : (
|
|
2580
2670
|
<DatabaseTableView
|
|
2671
|
+
newRowLabel={newDatabaseRowLabel}
|
|
2581
2672
|
properties={tableProperties}
|
|
2582
2673
|
groupableProperties={orderedProperties}
|
|
2583
2674
|
items={visibleItems}
|
|
@@ -2586,7 +2677,7 @@ function DatabaseTable({
|
|
|
2586
2677
|
databaseDocumentId={document.id}
|
|
2587
2678
|
canEdit={canEdit}
|
|
2588
2679
|
isLoading={isDatabaseViewLoading}
|
|
2589
|
-
isCreating={
|
|
2680
|
+
isCreating={isCreatingDatabaseItem}
|
|
2590
2681
|
columnWidths={columnWidths}
|
|
2591
2682
|
sorts={sorts}
|
|
2592
2683
|
filters={filters}
|
|
@@ -2632,7 +2723,7 @@ function DatabaseTable({
|
|
|
2632
2723
|
/>
|
|
2633
2724
|
)}
|
|
2634
2725
|
|
|
2635
|
-
{hasMoreItems && !
|
|
2726
|
+
{hasMoreItems && !isClientQueryExpansionPending ? (
|
|
2636
2727
|
<div className="flex items-center justify-center border-t border-border/45 py-3">
|
|
2637
2728
|
<Button
|
|
2638
2729
|
type="button"
|
|
@@ -2640,7 +2731,7 @@ function DatabaseTable({
|
|
|
2640
2731
|
size="sm"
|
|
2641
2732
|
disabled={isLoadingMoreItems}
|
|
2642
2733
|
onClick={() =>
|
|
2643
|
-
|
|
2734
|
+
setManualDatabaseItemLimit((current) =>
|
|
2644
2735
|
Math.min(
|
|
2645
2736
|
current + CONTENT_DATABASE_PAGE_SIZE,
|
|
2646
2737
|
totalItemCount,
|
|
@@ -2684,7 +2775,9 @@ function DatabaseTable({
|
|
|
2684
2775
|
<DatabaseSettingsPanelSheet
|
|
2685
2776
|
open={settingsOpen}
|
|
2686
2777
|
panel={settingsPanel}
|
|
2778
|
+
databaseId={databaseId}
|
|
2687
2779
|
documentId={document.id}
|
|
2780
|
+
isFilesDatabase={document.database?.systemRole === "files"}
|
|
2688
2781
|
canEdit={canEdit}
|
|
2689
2782
|
canManage={document.canManage === true}
|
|
2690
2783
|
activeView={activeView}
|
|
@@ -3916,8 +4009,10 @@ function DatabaseItemPreview({
|
|
|
3916
4009
|
onOpenPage: () => void;
|
|
3917
4010
|
}) {
|
|
3918
4011
|
const queryClient = useQueryClient();
|
|
4012
|
+
const contentSpaces = useContentSpaces();
|
|
3919
4013
|
const updateDocument = useUpdateDocument();
|
|
3920
4014
|
const deleteDocument = useDeleteDocument();
|
|
4015
|
+
const deleteContentSpace = useDeleteContentSpace();
|
|
3921
4016
|
const duplicateItem = useDuplicateDatabaseItem(databaseDocumentId);
|
|
3922
4017
|
const { data: document, isLoading } = useDocument(item.document.id);
|
|
3923
4018
|
const { data: persistedPreviewDraft } = usePreviewDocumentDraft(
|
|
@@ -3984,6 +4079,15 @@ function DatabaseItemPreview({
|
|
|
3984
4079
|
const [confirmDeleteOpen, setConfirmDeleteOpen] = useState(false);
|
|
3985
4080
|
const [openingFullPage, setOpeningFullPage] = useState(false);
|
|
3986
4081
|
const titleInputRef = useRef<HTMLTextAreaElement>(null);
|
|
4082
|
+
const removesFavoriteMembership =
|
|
4083
|
+
contentSpaces.data?.favoritesDocumentId === databaseDocumentId;
|
|
4084
|
+
const workspaceSpace = contentSpaces.data?.spaces.find(
|
|
4085
|
+
(space) => space.catalogDocumentId === item.document.id,
|
|
4086
|
+
);
|
|
4087
|
+
const isWorkspaceCatalog =
|
|
4088
|
+
contentSpaces.data?.catalogDocumentId === databaseDocumentId;
|
|
4089
|
+
const canDeleteWorkspace =
|
|
4090
|
+
isWorkspaceCatalog && workspaceSpace?.kind === "user";
|
|
3987
4091
|
|
|
3988
4092
|
// The peek's primary title+body save runs through a flush-on-release controller
|
|
3989
4093
|
// so a pending debounced edit is PERSISTED — not dropped — when the row
|
|
@@ -4588,7 +4692,14 @@ function DatabaseItemPreview({
|
|
|
4588
4692
|
}
|
|
4589
4693
|
|
|
4590
4694
|
try {
|
|
4591
|
-
|
|
4695
|
+
if (canDeleteWorkspace && workspaceSpace) {
|
|
4696
|
+
await deleteContentSpace.mutateAsync({ spaceId: workspaceSpace.id });
|
|
4697
|
+
} else {
|
|
4698
|
+
await deleteDocument.mutateAsync({
|
|
4699
|
+
id: item.document.id,
|
|
4700
|
+
databaseDocumentId,
|
|
4701
|
+
});
|
|
4702
|
+
}
|
|
4592
4703
|
await queryClient.invalidateQueries({
|
|
4593
4704
|
queryKey: [
|
|
4594
4705
|
"action",
|
|
@@ -4673,7 +4784,7 @@ function DatabaseItemPreview({
|
|
|
4673
4784
|
)}
|
|
4674
4785
|
{openingFullPage ? dbText("opening") : dbText("openPage")}
|
|
4675
4786
|
</Button>
|
|
4676
|
-
{canEdit || canManage ? (
|
|
4787
|
+
{canEdit || canManage || removesFavoriteMembership ? (
|
|
4677
4788
|
<DropdownMenu
|
|
4678
4789
|
open={actionsMenuOpen}
|
|
4679
4790
|
onOpenChange={setActionsMenuOpen}
|
|
@@ -4694,7 +4805,7 @@ function DatabaseItemPreview({
|
|
|
4694
4805
|
className="w-44"
|
|
4695
4806
|
data-database-preview-portal=""
|
|
4696
4807
|
>
|
|
4697
|
-
{canEdit ? (
|
|
4808
|
+
{canEdit && !isWorkspaceCatalog ? (
|
|
4698
4809
|
<DropdownMenuItem
|
|
4699
4810
|
disabled={duplicateItem.isPending}
|
|
4700
4811
|
onSelect={(event) => {
|
|
@@ -4706,8 +4817,24 @@ function DatabaseItemPreview({
|
|
|
4706
4817
|
{dbText("duplicateRow")}
|
|
4707
4818
|
</DropdownMenuItem>
|
|
4708
4819
|
) : null}
|
|
4709
|
-
{canEdit &&
|
|
4710
|
-
|
|
4820
|
+
{canEdit &&
|
|
4821
|
+
!isWorkspaceCatalog &&
|
|
4822
|
+
(canManage || removesFavoriteMembership) ? (
|
|
4823
|
+
<DropdownMenuSeparator />
|
|
4824
|
+
) : null}
|
|
4825
|
+
{removesFavoriteMembership ? (
|
|
4826
|
+
<DropdownMenuItem
|
|
4827
|
+
onSelect={(event) => {
|
|
4828
|
+
event.preventDefault();
|
|
4829
|
+
setActionsMenuOpen(false);
|
|
4830
|
+
void deletePreviewRow();
|
|
4831
|
+
}}
|
|
4832
|
+
>
|
|
4833
|
+
<IconStarOff className="mr-2 size-4 text-muted-foreground" />
|
|
4834
|
+
{sidebarText("removeFromFavorites")}
|
|
4835
|
+
</DropdownMenuItem>
|
|
4836
|
+
) : canManage &&
|
|
4837
|
+
(!isWorkspaceCatalog || canDeleteWorkspace) ? (
|
|
4711
4838
|
<DropdownMenuItem
|
|
4712
4839
|
className="text-destructive focus:bg-destructive/10 focus:text-destructive"
|
|
4713
4840
|
onSelect={(event) => {
|
|
@@ -4717,7 +4844,9 @@ function DatabaseItemPreview({
|
|
|
4717
4844
|
}}
|
|
4718
4845
|
>
|
|
4719
4846
|
<IconTrash className="mr-2 size-4" />
|
|
4720
|
-
{
|
|
4847
|
+
{canDeleteWorkspace
|
|
4848
|
+
? "Delete workspace"
|
|
4849
|
+
: dbText("deleteRow")}
|
|
4721
4850
|
</DropdownMenuItem>
|
|
4722
4851
|
) : null}
|
|
4723
4852
|
</DropdownMenuContent>
|
|
@@ -4860,23 +4989,45 @@ function DatabaseItemPreview({
|
|
|
4860
4989
|
</div>
|
|
4861
4990
|
</div>
|
|
4862
4991
|
)}
|
|
4863
|
-
<AlertDialog
|
|
4992
|
+
<AlertDialog
|
|
4993
|
+
open={
|
|
4994
|
+
!removesFavoriteMembership &&
|
|
4995
|
+
(!isWorkspaceCatalog || canDeleteWorkspace) &&
|
|
4996
|
+
confirmDeleteOpen
|
|
4997
|
+
}
|
|
4998
|
+
onOpenChange={setConfirmDeleteOpen}
|
|
4999
|
+
>
|
|
4864
5000
|
<AlertDialogContent data-database-preview-portal="">
|
|
4865
5001
|
<AlertDialogHeader>
|
|
4866
|
-
<AlertDialogTitle>
|
|
5002
|
+
<AlertDialogTitle>
|
|
5003
|
+
{canDeleteWorkspace ? "Delete workspace?" : dbText("deleteRow2")}
|
|
5004
|
+
</AlertDialogTitle>
|
|
4867
5005
|
<AlertDialogDescription>
|
|
4868
|
-
|
|
4869
|
-
|
|
5006
|
+
{canDeleteWorkspace ? (
|
|
5007
|
+
<>
|
|
5008
|
+
“{previewTitle}” and every page and database
|
|
5009
|
+
inside it will be permanently deleted. This cannot be undone.
|
|
5010
|
+
</>
|
|
5011
|
+
) : (
|
|
5012
|
+
<>
|
|
5013
|
+
“{previewTitle}” and any sub-pages will be
|
|
5014
|
+
permanently deleted. This cannot be undone.
|
|
5015
|
+
</>
|
|
5016
|
+
)}
|
|
4870
5017
|
</AlertDialogDescription>
|
|
4871
5018
|
</AlertDialogHeader>
|
|
4872
5019
|
<AlertDialogFooter>
|
|
4873
5020
|
<AlertDialogCancel>Cancel</AlertDialogCancel>
|
|
4874
5021
|
<AlertDialogAction
|
|
4875
5022
|
className="bg-destructive text-destructive-foreground hover:bg-destructive/90"
|
|
4876
|
-
disabled={
|
|
5023
|
+
disabled={
|
|
5024
|
+
deleteDocument.isPending || deleteContentSpace.isPending
|
|
5025
|
+
}
|
|
4877
5026
|
onClick={() => void deletePreviewRow()}
|
|
4878
5027
|
>
|
|
4879
|
-
{deleteDocument.isPending
|
|
5028
|
+
{deleteDocument.isPending || deleteContentSpace.isPending
|
|
5029
|
+
? "Deleting..."
|
|
5030
|
+
: "Delete"}
|
|
4880
5031
|
</AlertDialogAction>
|
|
4881
5032
|
</AlertDialogFooter>
|
|
4882
5033
|
</AlertDialogContent>
|
|
@@ -4886,6 +5037,7 @@ function DatabaseItemPreview({
|
|
|
4886
5037
|
}
|
|
4887
5038
|
|
|
4888
5039
|
function DatabaseTableView({
|
|
5040
|
+
newRowLabel,
|
|
4889
5041
|
properties,
|
|
4890
5042
|
groupableProperties,
|
|
4891
5043
|
items,
|
|
@@ -4930,6 +5082,7 @@ function DatabaseTableView({
|
|
|
4930
5082
|
onDeletedPreviewItems,
|
|
4931
5083
|
onOpenPage,
|
|
4932
5084
|
}: {
|
|
5085
|
+
newRowLabel: string;
|
|
4933
5086
|
properties: DocumentProperty[];
|
|
4934
5087
|
groupableProperties: DocumentProperty[];
|
|
4935
5088
|
items: ContentDatabaseItem[];
|
|
@@ -4989,6 +5142,7 @@ function DatabaseTableView({
|
|
|
4989
5142
|
onOpenPage: (item: ContentDatabaseItem) => void;
|
|
4990
5143
|
}) {
|
|
4991
5144
|
const queryClient = useQueryClient();
|
|
5145
|
+
const contentSpaces = useContentSpaces();
|
|
4992
5146
|
const moveItem = useMoveDatabaseItem(databaseDocumentId);
|
|
4993
5147
|
const duplicateItems = useDuplicateDatabaseItems(databaseDocumentId);
|
|
4994
5148
|
const setProperty = useSetDocumentProperty(databaseDocumentId);
|
|
@@ -5009,6 +5163,10 @@ function DatabaseTableView({
|
|
|
5009
5163
|
const selectableCount = items.length;
|
|
5010
5164
|
const selectedIdSet = new Set(selectedItemIds);
|
|
5011
5165
|
const selectedItems = databaseSelectedItems(items, selectedItemIds);
|
|
5166
|
+
const removesFavoriteMembership =
|
|
5167
|
+
contentSpaces.data?.favoritesDocumentId === databaseDocumentId;
|
|
5168
|
+
const isWorkspaceCatalog =
|
|
5169
|
+
contentSpaces.data?.catalogDocumentId === databaseDocumentId;
|
|
5012
5170
|
const bulkEditableProperties = databaseBulkEditableProperties(properties);
|
|
5013
5171
|
const groups = databaseVisibleGroups(
|
|
5014
5172
|
databaseViewItemGroups(items, groupableProperties, groupByPropertyId),
|
|
@@ -5358,11 +5516,18 @@ function DatabaseTableView({
|
|
|
5358
5516
|
deleteItems.isPending
|
|
5359
5517
|
}
|
|
5360
5518
|
deleteDisabled={deleteItems.isPending}
|
|
5519
|
+
removesFavoriteMembership={removesFavoriteMembership}
|
|
5361
5520
|
updateDisabled={setProperty.isPending}
|
|
5362
5521
|
onClearSelection={onClearSelection}
|
|
5363
5522
|
onSetPropertyValue={setSelectedPropertyValue}
|
|
5364
5523
|
onDuplicateSelected={() => void duplicateSelectedRows()}
|
|
5365
|
-
onDeleteSelected={() =>
|
|
5524
|
+
onDeleteSelected={() => {
|
|
5525
|
+
if (removesFavoriteMembership) {
|
|
5526
|
+
void deleteSelectedRows();
|
|
5527
|
+
return;
|
|
5528
|
+
}
|
|
5529
|
+
setConfirmDeleteSelectedOpen(true);
|
|
5530
|
+
}}
|
|
5366
5531
|
/>
|
|
5367
5532
|
) : null}
|
|
5368
5533
|
<div
|
|
@@ -5466,11 +5631,13 @@ function DatabaseTableView({
|
|
|
5466
5631
|
properties={properties}
|
|
5467
5632
|
columnWidths={columnWidths}
|
|
5468
5633
|
databaseDocumentId={databaseDocumentId}
|
|
5634
|
+
workspaceCatalog={isWorkspaceCatalog}
|
|
5469
5635
|
canEdit={canEdit}
|
|
5470
5636
|
selectedIdSet={selectedIdSet}
|
|
5471
5637
|
wrapCells={wrapCells}
|
|
5472
5638
|
rowDensity={rowDensity}
|
|
5473
5639
|
isCreating={isCreating}
|
|
5640
|
+
newRowLabel={newRowLabel}
|
|
5474
5641
|
focusedTitleDocumentId={focusedTitleDocumentId}
|
|
5475
5642
|
collapsed={databaseGroupIsCollapsed(
|
|
5476
5643
|
collapsedGroupIds,
|
|
@@ -5493,6 +5660,7 @@ function DatabaseTableView({
|
|
|
5493
5660
|
key={item.id}
|
|
5494
5661
|
item={item}
|
|
5495
5662
|
databaseDocumentId={databaseDocumentId}
|
|
5663
|
+
workspaceCatalog={isWorkspaceCatalog}
|
|
5496
5664
|
properties={properties}
|
|
5497
5665
|
columnWidths={columnWidths}
|
|
5498
5666
|
canEdit={canEdit}
|
|
@@ -5531,6 +5699,7 @@ function DatabaseTableView({
|
|
|
5531
5699
|
))}
|
|
5532
5700
|
{canEdit && !grouped ? (
|
|
5533
5701
|
<NewDatabaseRow
|
|
5702
|
+
label={newRowLabel}
|
|
5534
5703
|
properties={properties}
|
|
5535
5704
|
columnWidths={columnWidths}
|
|
5536
5705
|
rowDensity={rowDensity}
|
|
@@ -5561,7 +5730,7 @@ function DatabaseTableView({
|
|
|
5561
5730
|
)}
|
|
5562
5731
|
</div>
|
|
5563
5732
|
<AlertDialog
|
|
5564
|
-
open={confirmDeleteSelectedOpen}
|
|
5733
|
+
open={!removesFavoriteMembership && confirmDeleteSelectedOpen}
|
|
5565
5734
|
onOpenChange={setConfirmDeleteSelectedOpen}
|
|
5566
5735
|
>
|
|
5567
5736
|
<AlertDialogContent>
|
|
@@ -5647,17 +5816,17 @@ function DatabaseActiveConstraintsBar({
|
|
|
5647
5816
|
onResetPersonalChanges: () => void;
|
|
5648
5817
|
onSaveForEveryone: () => void;
|
|
5649
5818
|
}) {
|
|
5819
|
+
const filterEntries = filters.map((filter, index) => ({ filter, index }));
|
|
5650
5820
|
if (
|
|
5651
5821
|
!forceShow &&
|
|
5652
5822
|
constraintCount === 0 &&
|
|
5653
|
-
|
|
5823
|
+
filterEntries.length === 0 &&
|
|
5654
5824
|
!hasPersonalQueryChanges
|
|
5655
5825
|
)
|
|
5656
5826
|
return null;
|
|
5657
5827
|
const hasSearchOrSortConstraints =
|
|
5658
5828
|
searchQuery.trim().length > 0 || sorts.length > 0;
|
|
5659
5829
|
const showViewActionControls = hasPersonalQueryChanges;
|
|
5660
|
-
const filterEntries = filters.map((filter, index) => ({ filter, index }));
|
|
5661
5830
|
const advancedFilterEntries = filterEntries.filter(({ filter }) =>
|
|
5662
5831
|
isAdvancedDatabaseFilter(filter),
|
|
5663
5832
|
);
|
|
@@ -5724,7 +5893,7 @@ function DatabaseActiveConstraintsBar({
|
|
|
5724
5893
|
))}
|
|
5725
5894
|
<DatabaseAddFilterButton
|
|
5726
5895
|
open={addFilterOpen}
|
|
5727
|
-
filters={
|
|
5896
|
+
filters={filterEntries.map(({ filter }) => filter)}
|
|
5728
5897
|
properties={properties}
|
|
5729
5898
|
onOpenChange={onAddFilterOpenChange}
|
|
5730
5899
|
onAddFilter={(key, label) => {
|
|
@@ -6976,7 +7145,9 @@ function NotionLogoMark({ className }: { className?: string }) {
|
|
|
6976
7145
|
function DatabaseSettingsPanelSheet({
|
|
6977
7146
|
open,
|
|
6978
7147
|
panel,
|
|
7148
|
+
databaseId,
|
|
6979
7149
|
documentId,
|
|
7150
|
+
isFilesDatabase,
|
|
6980
7151
|
canEdit,
|
|
6981
7152
|
canManage,
|
|
6982
7153
|
activeView,
|
|
@@ -7011,7 +7182,9 @@ function DatabaseSettingsPanelSheet({
|
|
|
7011
7182
|
}: {
|
|
7012
7183
|
open: boolean;
|
|
7013
7184
|
panel: DatabaseSettingsPanel;
|
|
7185
|
+
databaseId: string;
|
|
7014
7186
|
documentId: string;
|
|
7187
|
+
isFilesDatabase: boolean;
|
|
7015
7188
|
canEdit: boolean;
|
|
7016
7189
|
canManage: boolean;
|
|
7017
7190
|
activeView: ContentDatabaseView;
|
|
@@ -7124,7 +7297,9 @@ function DatabaseSettingsPanelSheet({
|
|
|
7124
7297
|
<DatabaseSettingsSourcePanel
|
|
7125
7298
|
source={source}
|
|
7126
7299
|
sources={sources}
|
|
7300
|
+
databaseId={databaseId}
|
|
7127
7301
|
documentId={documentId}
|
|
7302
|
+
isFilesDatabase={isFilesDatabase}
|
|
7128
7303
|
itemCount={items.length}
|
|
7129
7304
|
canEdit={canEdit}
|
|
7130
7305
|
canManage={canManage}
|
|
@@ -7506,7 +7681,9 @@ export function buildClientBuilderReviewPayload(
|
|
|
7506
7681
|
function DatabaseSettingsSourcePanel({
|
|
7507
7682
|
source,
|
|
7508
7683
|
sources,
|
|
7684
|
+
databaseId,
|
|
7509
7685
|
documentId,
|
|
7686
|
+
isFilesDatabase,
|
|
7510
7687
|
itemCount,
|
|
7511
7688
|
canEdit,
|
|
7512
7689
|
canManage,
|
|
@@ -7527,7 +7704,9 @@ function DatabaseSettingsSourcePanel({
|
|
|
7527
7704
|
}: {
|
|
7528
7705
|
source: ContentDatabaseSource | null;
|
|
7529
7706
|
sources: ContentDatabaseSource[];
|
|
7707
|
+
databaseId: string;
|
|
7530
7708
|
documentId: string;
|
|
7709
|
+
isFilesDatabase: boolean;
|
|
7531
7710
|
itemCount: number;
|
|
7532
7711
|
canEdit: boolean;
|
|
7533
7712
|
canManage: boolean;
|
|
@@ -7557,6 +7736,7 @@ function DatabaseSettingsSourcePanel({
|
|
|
7557
7736
|
sourcePendingOperations: DatabaseSourcePendingOperations;
|
|
7558
7737
|
}) {
|
|
7559
7738
|
const { isCodeMode } = useCodeMode();
|
|
7739
|
+
const navigate = useNavigate();
|
|
7560
7740
|
const builderSources = databaseAttachedBuilderSources(sources, source);
|
|
7561
7741
|
const builderStatus = useBuilderStatus();
|
|
7562
7742
|
const builderConfigured = builderStatus.status?.configured === true;
|
|
@@ -7603,6 +7783,10 @@ function DatabaseSettingsSourcePanel({
|
|
|
7603
7783
|
)
|
|
7604
7784
|
}
|
|
7605
7785
|
onOpenNotion={() => onNavPush({ kind: "addSource" })}
|
|
7786
|
+
onOpenLocalFolder={() =>
|
|
7787
|
+
navigate(`/local-files?databaseId=${databaseId}`)
|
|
7788
|
+
}
|
|
7789
|
+
showLocalFolder={isFilesDatabase}
|
|
7606
7790
|
onOpenSecondary={(secondary) =>
|
|
7607
7791
|
onNavPush({
|
|
7608
7792
|
kind: "secondarySource",
|
|
@@ -8262,6 +8446,8 @@ function SourcesListView({
|
|
|
8262
8446
|
reviewableCount,
|
|
8263
8447
|
onOpenBuilder,
|
|
8264
8448
|
onOpenNotion,
|
|
8449
|
+
onOpenLocalFolder,
|
|
8450
|
+
showLocalFolder,
|
|
8265
8451
|
onOpenSecondary,
|
|
8266
8452
|
onAddSource,
|
|
8267
8453
|
}: {
|
|
@@ -8272,9 +8458,12 @@ function SourcesListView({
|
|
|
8272
8458
|
reviewableCount: number;
|
|
8273
8459
|
onOpenBuilder: (source?: ContentDatabaseSource) => void;
|
|
8274
8460
|
onOpenNotion: () => void;
|
|
8461
|
+
onOpenLocalFolder: () => void;
|
|
8462
|
+
showLocalFolder: boolean;
|
|
8275
8463
|
onOpenSecondary: (source: ContentDatabaseSource) => void;
|
|
8276
8464
|
onAddSource: () => void;
|
|
8277
8465
|
}) {
|
|
8466
|
+
const t = useT();
|
|
8278
8467
|
const isBuilderSource = source?.sourceType === "builder-cms";
|
|
8279
8468
|
const connectedSources =
|
|
8280
8469
|
sources.length > 0 ? sources : source ? [source] : [];
|
|
@@ -8350,6 +8539,13 @@ function SourcesListView({
|
|
|
8350
8539
|
}
|
|
8351
8540
|
onClick={onOpenNotion}
|
|
8352
8541
|
/>
|
|
8542
|
+
{showLocalFolder ? (
|
|
8543
|
+
<DatabaseSettingsRow
|
|
8544
|
+
icon={<IconFolder className="size-4" />}
|
|
8545
|
+
label={t("sidebar.localFolder")}
|
|
8546
|
+
onClick={onOpenLocalFolder}
|
|
8547
|
+
/>
|
|
8548
|
+
) : null}
|
|
8353
8549
|
</div>
|
|
8354
8550
|
<div className="grid min-w-0 gap-1.5">
|
|
8355
8551
|
<div className="px-2 text-[11px] font-medium uppercase tracking-wide text-muted-foreground">
|
|
@@ -12617,6 +12813,7 @@ function NewBoardCard({
|
|
|
12617
12813
|
}
|
|
12618
12814
|
|
|
12619
12815
|
function NewDatabaseRow({
|
|
12816
|
+
label,
|
|
12620
12817
|
properties,
|
|
12621
12818
|
columnWidths,
|
|
12622
12819
|
rowDensity,
|
|
@@ -12625,6 +12822,7 @@ function NewDatabaseRow({
|
|
|
12625
12822
|
onCreate,
|
|
12626
12823
|
actionColumnWidth = ACTION_COLUMN_WIDTH,
|
|
12627
12824
|
}: {
|
|
12825
|
+
label: string;
|
|
12628
12826
|
properties: DocumentProperty[];
|
|
12629
12827
|
columnWidths: Record<string, number>;
|
|
12630
12828
|
rowDensity: DatabaseRowDensity;
|
|
@@ -12641,7 +12839,7 @@ function NewDatabaseRow({
|
|
|
12641
12839
|
return (
|
|
12642
12840
|
<button
|
|
12643
12841
|
type="button"
|
|
12644
|
-
aria-label={
|
|
12842
|
+
aria-label={label}
|
|
12645
12843
|
disabled={disabled}
|
|
12646
12844
|
className={cn(
|
|
12647
12845
|
"grid w-full border-t border-border/35 text-left text-sm text-muted-foreground transition-colors hover:bg-muted/35 hover:text-foreground focus-visible:bg-muted/35 focus-visible:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-60",
|
|
@@ -12668,9 +12866,7 @@ function NewDatabaseRow({
|
|
|
12668
12866
|
) : (
|
|
12669
12867
|
<IconPlus className="size-4 shrink-0" />
|
|
12670
12868
|
)}
|
|
12671
|
-
<span className="h-7 min-w-0 flex-1 truncate leading-7">
|
|
12672
|
-
{dbText("newPage")}
|
|
12673
|
-
</span>
|
|
12869
|
+
<span className="h-7 min-w-0 flex-1 truncate leading-7">{label}</span>
|
|
12674
12870
|
</span>
|
|
12675
12871
|
{properties.map((property) => (
|
|
12676
12872
|
<span
|
|
@@ -13025,18 +13221,22 @@ function normalizeClientDatabaseView(
|
|
|
13025
13221
|
value: Partial<ContentDatabaseView> | null | undefined,
|
|
13026
13222
|
) {
|
|
13027
13223
|
if (!value || typeof value.id !== "string" || !value.id.trim()) return null;
|
|
13224
|
+
const retiredSidebar = value.type === "sidebar";
|
|
13028
13225
|
const type =
|
|
13029
13226
|
value.type === "board" ||
|
|
13030
13227
|
value.type === "list" ||
|
|
13031
13228
|
value.type === "gallery" ||
|
|
13032
13229
|
value.type === "calendar" ||
|
|
13033
13230
|
value.type === "timeline" ||
|
|
13034
|
-
value.type === "form"
|
|
13035
|
-
value.type === "sidebar"
|
|
13231
|
+
value.type === "form"
|
|
13036
13232
|
? value.type
|
|
13037
13233
|
: "table";
|
|
13038
13234
|
return createDatabaseView(
|
|
13039
|
-
typeof value.name === "string"
|
|
13235
|
+
typeof value.name === "string"
|
|
13236
|
+
? retiredSidebar && value.name.trim() === "Sidebar"
|
|
13237
|
+
? "Table"
|
|
13238
|
+
: value.name
|
|
13239
|
+
: databaseViewDefaultName(type),
|
|
13040
13240
|
value.id,
|
|
13041
13241
|
{
|
|
13042
13242
|
sorts: Array.isArray(value.sorts)
|
|
@@ -13568,7 +13768,6 @@ function databaseViewIcon(type: ContentDatabaseViewType) {
|
|
|
13568
13768
|
if (type === "calendar") return IconCalendar;
|
|
13569
13769
|
if (type === "timeline") return IconTimeline;
|
|
13570
13770
|
if (type === "form") return IconForms;
|
|
13571
|
-
if (type === "sidebar") return IconLayoutSidebar;
|
|
13572
13771
|
return IconTable;
|
|
13573
13772
|
}
|
|
13574
13773
|
|
|
@@ -13579,7 +13778,6 @@ function databaseViewDefaultName(type: ContentDatabaseViewType) {
|
|
|
13579
13778
|
if (type === "calendar") return "Calendar";
|
|
13580
13779
|
if (type === "timeline") return "Timeline";
|
|
13581
13780
|
if (type === "form") return "Form";
|
|
13582
|
-
if (type === "sidebar") return "Sidebar";
|
|
13583
13781
|
return "Table";
|
|
13584
13782
|
}
|
|
13585
13783
|
|
|
@@ -14786,6 +14984,7 @@ function DatabaseSelectionBar({
|
|
|
14786
14984
|
selectedItems,
|
|
14787
14985
|
duplicateDisabled,
|
|
14788
14986
|
deleteDisabled,
|
|
14987
|
+
removesFavoriteMembership,
|
|
14789
14988
|
updateDisabled,
|
|
14790
14989
|
onClearSelection,
|
|
14791
14990
|
onSetPropertyValue,
|
|
@@ -14798,6 +14997,7 @@ function DatabaseSelectionBar({
|
|
|
14798
14997
|
selectedItems: ContentDatabaseItem[];
|
|
14799
14998
|
duplicateDisabled: boolean;
|
|
14800
14999
|
deleteDisabled: boolean;
|
|
15000
|
+
removesFavoriteMembership: boolean;
|
|
14801
15001
|
updateDisabled: boolean;
|
|
14802
15002
|
onClearSelection: () => void;
|
|
14803
15003
|
onSetPropertyValue: (
|
|
@@ -14837,12 +15037,20 @@ function DatabaseSelectionBar({
|
|
|
14837
15037
|
type="button"
|
|
14838
15038
|
variant="ghost"
|
|
14839
15039
|
size="sm"
|
|
14840
|
-
className=
|
|
15040
|
+
className={cn(
|
|
15041
|
+
"h-7 gap-1.5 px-2 text-xs",
|
|
15042
|
+
!removesFavoriteMembership &&
|
|
15043
|
+
"text-destructive hover:bg-destructive/10 hover:text-destructive",
|
|
15044
|
+
)}
|
|
14841
15045
|
disabled={deleteDisabled}
|
|
14842
15046
|
onClick={onDeleteSelected}
|
|
14843
15047
|
>
|
|
14844
|
-
|
|
14845
|
-
|
|
15048
|
+
{removesFavoriteMembership ? (
|
|
15049
|
+
<IconStarOff className="size-3.5" />
|
|
15050
|
+
) : (
|
|
15051
|
+
<IconTrash className="size-3.5" />
|
|
15052
|
+
)}
|
|
15053
|
+
{removesFavoriteMembership ? "Remove" : "Delete"}
|
|
14846
15054
|
</Button>
|
|
14847
15055
|
</>
|
|
14848
15056
|
) : null}
|
|
@@ -15534,6 +15742,7 @@ function DatabasePropertyHeader({
|
|
|
15534
15742
|
onResize: (event: ReactPointerEvent) => void;
|
|
15535
15743
|
}) {
|
|
15536
15744
|
const Icon = TYPE_ICONS[property.definition.type];
|
|
15745
|
+
const canReorder = canEdit && !property.definition.systemRole;
|
|
15537
15746
|
const columnState = databaseColumnHeaderState(
|
|
15538
15747
|
sorts,
|
|
15539
15748
|
filters,
|
|
@@ -15545,14 +15754,14 @@ function DatabasePropertyHeader({
|
|
|
15545
15754
|
data-database-property-id={property.definition.id}
|
|
15546
15755
|
className={cn(
|
|
15547
15756
|
"group relative flex h-8 min-w-0 items-center border-r border-border/35 px-1 transition-colors",
|
|
15548
|
-
|
|
15757
|
+
canReorder && "cursor-grab active:cursor-grabbing",
|
|
15549
15758
|
isDragging && "opacity-45",
|
|
15550
15759
|
dropSide && "bg-accent/40",
|
|
15551
15760
|
)}
|
|
15552
|
-
onPointerDown={onPointerDown}
|
|
15761
|
+
onPointerDown={canReorder ? onPointerDown : undefined}
|
|
15553
15762
|
>
|
|
15554
15763
|
<DatabaseDropIndicator side={dropSide} />
|
|
15555
|
-
{canEdit ? (
|
|
15764
|
+
{canEdit && !property.definition.systemRole ? (
|
|
15556
15765
|
<PropertyManagementPopover
|
|
15557
15766
|
property={property}
|
|
15558
15767
|
documentId={documentId}
|
|
@@ -17621,11 +17830,13 @@ function DatabaseGroupedTableSection({
|
|
|
17621
17830
|
properties,
|
|
17622
17831
|
columnWidths,
|
|
17623
17832
|
databaseDocumentId,
|
|
17833
|
+
workspaceCatalog,
|
|
17624
17834
|
canEdit,
|
|
17625
17835
|
selectedIdSet,
|
|
17626
17836
|
wrapCells,
|
|
17627
17837
|
rowDensity,
|
|
17628
17838
|
isCreating,
|
|
17839
|
+
newRowLabel,
|
|
17629
17840
|
focusedTitleDocumentId,
|
|
17630
17841
|
collapsed,
|
|
17631
17842
|
onCreateRow,
|
|
@@ -17641,11 +17852,13 @@ function DatabaseGroupedTableSection({
|
|
|
17641
17852
|
properties: DocumentProperty[];
|
|
17642
17853
|
columnWidths: Record<string, number>;
|
|
17643
17854
|
databaseDocumentId: string;
|
|
17855
|
+
workspaceCatalog: boolean;
|
|
17644
17856
|
canEdit: boolean;
|
|
17645
17857
|
selectedIdSet: Set<string>;
|
|
17646
17858
|
wrapCells: boolean;
|
|
17647
17859
|
rowDensity: DatabaseRowDensity;
|
|
17648
17860
|
isCreating: boolean;
|
|
17861
|
+
newRowLabel: string;
|
|
17649
17862
|
focusedTitleDocumentId: string | null;
|
|
17650
17863
|
collapsed: boolean;
|
|
17651
17864
|
onCreateRow: (
|
|
@@ -17677,6 +17890,7 @@ function DatabaseGroupedTableSection({
|
|
|
17677
17890
|
key={`${group.id}-${item.id}`}
|
|
17678
17891
|
item={item}
|
|
17679
17892
|
databaseDocumentId={databaseDocumentId}
|
|
17893
|
+
workspaceCatalog={workspaceCatalog}
|
|
17680
17894
|
properties={properties}
|
|
17681
17895
|
columnWidths={columnWidths}
|
|
17682
17896
|
canEdit={canEdit}
|
|
@@ -17705,6 +17919,7 @@ function DatabaseGroupedTableSection({
|
|
|
17705
17919
|
))}
|
|
17706
17920
|
{canEdit ? (
|
|
17707
17921
|
<NewDatabaseRow
|
|
17922
|
+
label={newRowLabel}
|
|
17708
17923
|
properties={properties}
|
|
17709
17924
|
columnWidths={columnWidths}
|
|
17710
17925
|
rowDensity={rowDensity}
|
|
@@ -17742,6 +17957,7 @@ function DatabaseTableRow({
|
|
|
17742
17957
|
properties,
|
|
17743
17958
|
columnWidths,
|
|
17744
17959
|
databaseDocumentId,
|
|
17960
|
+
workspaceCatalog,
|
|
17745
17961
|
canEdit,
|
|
17746
17962
|
rowIndex,
|
|
17747
17963
|
canReorder,
|
|
@@ -17767,6 +17983,7 @@ function DatabaseTableRow({
|
|
|
17767
17983
|
properties: ContentDatabaseItem["properties"];
|
|
17768
17984
|
columnWidths: Record<string, number>;
|
|
17769
17985
|
databaseDocumentId: string;
|
|
17986
|
+
workspaceCatalog: boolean;
|
|
17770
17987
|
canEdit: boolean;
|
|
17771
17988
|
rowIndex: number;
|
|
17772
17989
|
canReorder: boolean;
|
|
@@ -17809,6 +18026,7 @@ function DatabaseTableRow({
|
|
|
17809
18026
|
<RowNameCell
|
|
17810
18027
|
item={item}
|
|
17811
18028
|
databaseDocumentId={databaseDocumentId}
|
|
18029
|
+
workspaceCatalog={workspaceCatalog}
|
|
17812
18030
|
canEdit={canEdit}
|
|
17813
18031
|
canDragRow={canDragRow}
|
|
17814
18032
|
selected={selected}
|
|
@@ -17920,11 +18138,22 @@ export function RowActionsCell({
|
|
|
17920
18138
|
onOpenPage: () => void;
|
|
17921
18139
|
}) {
|
|
17922
18140
|
const queryClient = useQueryClient();
|
|
18141
|
+
const contentSpaces = useContentSpaces();
|
|
17923
18142
|
const deleteDocument = useDeleteDocument();
|
|
18143
|
+
const deleteContentSpace = useDeleteContentSpace();
|
|
17924
18144
|
const duplicateItem = useDuplicateDatabaseItem(databaseDocumentId);
|
|
17925
18145
|
const [menuOpen, setMenuOpen] = useState(false);
|
|
17926
18146
|
const [confirmDeleteOpen, setConfirmDeleteOpen] = useState(false);
|
|
17927
18147
|
const title = item.document.title || "Untitled";
|
|
18148
|
+
const removesFavoriteMembership =
|
|
18149
|
+
contentSpaces.data?.favoritesDocumentId === databaseDocumentId;
|
|
18150
|
+
const workspaceSpace = contentSpaces.data?.spaces.find(
|
|
18151
|
+
(space) => space.catalogDocumentId === item.document.id,
|
|
18152
|
+
);
|
|
18153
|
+
const isWorkspaceCatalog =
|
|
18154
|
+
contentSpaces.data?.catalogDocumentId === databaseDocumentId;
|
|
18155
|
+
const canDeleteWorkspace =
|
|
18156
|
+
isWorkspaceCatalog && workspaceSpace?.kind === "user";
|
|
17928
18157
|
|
|
17929
18158
|
async function duplicateRow() {
|
|
17930
18159
|
setMenuOpen(false);
|
|
@@ -17943,7 +18172,14 @@ export function RowActionsCell({
|
|
|
17943
18172
|
async function deleteRow() {
|
|
17944
18173
|
const previewMoved = onDeletedPreviewItem?.(item) ?? false;
|
|
17945
18174
|
try {
|
|
17946
|
-
|
|
18175
|
+
if (canDeleteWorkspace && workspaceSpace) {
|
|
18176
|
+
await deleteContentSpace.mutateAsync({ spaceId: workspaceSpace.id });
|
|
18177
|
+
} else {
|
|
18178
|
+
await deleteDocument.mutateAsync({
|
|
18179
|
+
id: item.document.id,
|
|
18180
|
+
databaseDocumentId,
|
|
18181
|
+
});
|
|
18182
|
+
}
|
|
17947
18183
|
await queryClient.invalidateQueries({
|
|
17948
18184
|
queryKey: [
|
|
17949
18185
|
"action",
|
|
@@ -17986,48 +18222,87 @@ export function RowActionsCell({
|
|
|
17986
18222
|
<IconExternalLink className="mr-2 size-4 text-muted-foreground" />
|
|
17987
18223
|
{dbText("openPage")}
|
|
17988
18224
|
</DropdownMenuItem>
|
|
17989
|
-
|
|
17990
|
-
|
|
17991
|
-
|
|
17992
|
-
event
|
|
17993
|
-
|
|
17994
|
-
|
|
17995
|
-
|
|
17996
|
-
|
|
17997
|
-
|
|
17998
|
-
|
|
17999
|
-
|
|
18000
|
-
|
|
18001
|
-
|
|
18002
|
-
|
|
18003
|
-
|
|
18004
|
-
|
|
18005
|
-
|
|
18006
|
-
|
|
18007
|
-
|
|
18008
|
-
|
|
18009
|
-
|
|
18010
|
-
|
|
18225
|
+
{!isWorkspaceCatalog ? (
|
|
18226
|
+
<DropdownMenuItem
|
|
18227
|
+
disabled={duplicateItem.isPending}
|
|
18228
|
+
onSelect={(event) => {
|
|
18229
|
+
event.preventDefault();
|
|
18230
|
+
void duplicateRow();
|
|
18231
|
+
}}
|
|
18232
|
+
>
|
|
18233
|
+
<IconCopy className="mr-2 size-4 text-muted-foreground" />
|
|
18234
|
+
{dbText("duplicateRow")}
|
|
18235
|
+
</DropdownMenuItem>
|
|
18236
|
+
) : null}
|
|
18237
|
+
{!isWorkspaceCatalog || canDeleteWorkspace ? (
|
|
18238
|
+
<DropdownMenuSeparator />
|
|
18239
|
+
) : null}
|
|
18240
|
+
{removesFavoriteMembership ? (
|
|
18241
|
+
<DropdownMenuItem
|
|
18242
|
+
onSelect={(event) => {
|
|
18243
|
+
event.preventDefault();
|
|
18244
|
+
setMenuOpen(false);
|
|
18245
|
+
void deleteRow();
|
|
18246
|
+
}}
|
|
18247
|
+
>
|
|
18248
|
+
<IconStarOff className="mr-2 size-4 text-muted-foreground" />
|
|
18249
|
+
{sidebarText("removeFromFavorites")}
|
|
18250
|
+
</DropdownMenuItem>
|
|
18251
|
+
) : !isWorkspaceCatalog || canDeleteWorkspace ? (
|
|
18252
|
+
<DropdownMenuItem
|
|
18253
|
+
className="text-destructive focus:bg-destructive/10 focus:text-destructive"
|
|
18254
|
+
onSelect={(event) => {
|
|
18255
|
+
event.preventDefault();
|
|
18256
|
+
setMenuOpen(false);
|
|
18257
|
+
setConfirmDeleteOpen(true);
|
|
18258
|
+
}}
|
|
18259
|
+
>
|
|
18260
|
+
<IconTrash className="mr-2 size-4" />
|
|
18261
|
+
{canDeleteWorkspace ? "Delete workspace" : dbText("deleteRow")}
|
|
18262
|
+
</DropdownMenuItem>
|
|
18263
|
+
) : null}
|
|
18011
18264
|
</DropdownMenuContent>
|
|
18012
18265
|
</DropdownMenu>
|
|
18013
18266
|
|
|
18014
|
-
<AlertDialog
|
|
18267
|
+
<AlertDialog
|
|
18268
|
+
open={
|
|
18269
|
+
!removesFavoriteMembership &&
|
|
18270
|
+
(!isWorkspaceCatalog || canDeleteWorkspace) &&
|
|
18271
|
+
confirmDeleteOpen
|
|
18272
|
+
}
|
|
18273
|
+
onOpenChange={setConfirmDeleteOpen}
|
|
18274
|
+
>
|
|
18015
18275
|
<AlertDialogContent>
|
|
18016
18276
|
<AlertDialogHeader>
|
|
18017
|
-
<AlertDialogTitle>
|
|
18277
|
+
<AlertDialogTitle>
|
|
18278
|
+
{canDeleteWorkspace ? "Delete workspace?" : dbText("deleteRow2")}
|
|
18279
|
+
</AlertDialogTitle>
|
|
18018
18280
|
<AlertDialogDescription>
|
|
18019
|
-
|
|
18020
|
-
|
|
18281
|
+
{canDeleteWorkspace ? (
|
|
18282
|
+
<>
|
|
18283
|
+
“{title}” and every page and database inside it
|
|
18284
|
+
will be permanently deleted. This cannot be undone.
|
|
18285
|
+
</>
|
|
18286
|
+
) : (
|
|
18287
|
+
<>
|
|
18288
|
+
“{title}” and any sub-pages will be permanently
|
|
18289
|
+
deleted. This cannot be undone.
|
|
18290
|
+
</>
|
|
18291
|
+
)}
|
|
18021
18292
|
</AlertDialogDescription>
|
|
18022
18293
|
</AlertDialogHeader>
|
|
18023
18294
|
<AlertDialogFooter>
|
|
18024
18295
|
<AlertDialogCancel>Cancel</AlertDialogCancel>
|
|
18025
18296
|
<AlertDialogAction
|
|
18026
18297
|
className="bg-destructive text-destructive-foreground hover:bg-destructive/90"
|
|
18027
|
-
disabled={
|
|
18298
|
+
disabled={
|
|
18299
|
+
deleteDocument.isPending || deleteContentSpace.isPending
|
|
18300
|
+
}
|
|
18028
18301
|
onClick={() => void deleteRow()}
|
|
18029
18302
|
>
|
|
18030
|
-
{deleteDocument.isPending
|
|
18303
|
+
{deleteDocument.isPending || deleteContentSpace.isPending
|
|
18304
|
+
? "Deleting..."
|
|
18305
|
+
: "Delete"}
|
|
18031
18306
|
</AlertDialogAction>
|
|
18032
18307
|
</AlertDialogFooter>
|
|
18033
18308
|
</AlertDialogContent>
|
|
@@ -18039,6 +18314,7 @@ export function RowActionsCell({
|
|
|
18039
18314
|
function RowNameCell({
|
|
18040
18315
|
item,
|
|
18041
18316
|
databaseDocumentId,
|
|
18317
|
+
workspaceCatalog,
|
|
18042
18318
|
canEdit,
|
|
18043
18319
|
canDragRow,
|
|
18044
18320
|
selected,
|
|
@@ -18052,6 +18328,7 @@ function RowNameCell({
|
|
|
18052
18328
|
}: {
|
|
18053
18329
|
item: ContentDatabaseItem;
|
|
18054
18330
|
databaseDocumentId: string;
|
|
18331
|
+
workspaceCatalog: boolean;
|
|
18055
18332
|
canEdit: boolean;
|
|
18056
18333
|
canDragRow: boolean;
|
|
18057
18334
|
selected: boolean;
|
|
@@ -18144,6 +18421,7 @@ function RowNameCell({
|
|
|
18144
18421
|
document={item.document}
|
|
18145
18422
|
className="size-4 text-sm"
|
|
18146
18423
|
fallbackClassName="size-4"
|
|
18424
|
+
fallback={workspaceCatalog ? "folder" : "page"}
|
|
18147
18425
|
/>
|
|
18148
18426
|
{canEdit && editingTitle ? (
|
|
18149
18427
|
<input
|