@agent-native/core 0.128.1 → 0.128.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/corpus/README.md +2 -2
- package/corpus/core/CHANGELOG.md +12 -0
- package/corpus/core/package.json +2 -1
- package/corpus/core/src/server/email-template.ts +33 -0
- package/corpus/templates/chat/_gitignore +2 -0
- package/corpus/templates/clips/AGENTS.md +6 -1
- package/corpus/templates/clips/actions/complete-transactional-email-summary.ts +56 -0
- package/corpus/templates/clips/actions/import-loom-recording.ts +258 -76
- package/corpus/templates/clips/actions/lib/direct-video.ts +96 -0
- package/corpus/templates/clips/actions/lib/loom-import-job.ts +53 -2
- package/corpus/templates/clips/actions/lib/loom-video.ts +2 -62
- package/corpus/templates/clips/actions/lib/video-download-limits.ts +62 -0
- package/corpus/templates/clips/actions/list-transactional-email-ai-requests.ts +249 -0
- package/corpus/templates/clips/app/components/library/library-grid.tsx +65 -0
- package/corpus/templates/clips/app/components/library/library-layout.tsx +55 -0
- package/corpus/templates/clips/app/components/recorder/pre-record-panel.tsx +28 -126
- package/corpus/templates/clips/app/global.css +23 -0
- package/corpus/templates/clips/app/hooks/use-transactional-email-bridge.ts +98 -0
- package/corpus/templates/clips/app/i18n/en-US.ts +20 -0
- package/corpus/templates/clips/app/routes/_app.tsx +2 -0
- package/corpus/templates/clips/app/routes/import.tsx +396 -0
- package/corpus/templates/clips/app/routes/r.$recordingId.tsx +8 -6
- package/corpus/templates/clips/app/routes/record.tsx +13 -71
- package/corpus/templates/clips/changelog/2026-07-25-two-clip-emails-now-include-a-concise-summary-generated-secu.md +6 -0
- package/corpus/templates/clips/data/clips-transactional-emails/config.json +3 -0
- package/corpus/templates/clips/server/jobs/transactional-emails.ts +1034 -0
- package/corpus/templates/clips/server/lib/transactional-email-store.ts +865 -0
- package/corpus/templates/clips/server/lib/transactional-email-templates.ts +270 -0
- package/corpus/templates/clips/server/plugins/calendar-jobs.ts +2 -0
- package/corpus/templates/clips/server/routes/api/view-event.post.ts +59 -2
- package/corpus/templates/content/.agents/skills/document-editing/references/databases.md +8 -2
- package/corpus/templates/content/AGENTS.md +8 -0
- package/corpus/templates/content/actions/_content-database-personal-view.ts +28 -3
- package/corpus/templates/content/actions/_property-utils.ts +32 -2
- package/corpus/templates/content/actions/configure-document-property.ts +12 -2
- package/corpus/templates/content/actions/delete-document-property.ts +13 -3
- package/corpus/templates/content/actions/duplicate-document-property.ts +13 -3
- package/corpus/templates/content/actions/list-content-spaces.ts +5 -2
- package/corpus/templates/content/actions/list-document-properties.ts +12 -3
- package/corpus/templates/content/actions/move-database-item.ts +74 -55
- package/corpus/templates/content/actions/reorder-document-property.ts +20 -4
- package/corpus/templates/content/actions/set-document-property.ts +10 -1
- package/corpus/templates/content/actions/update-content-database-personal-view.ts +7 -0
- package/corpus/templates/content/app/components/editor/DocumentBlockFields.tsx +31 -21
- package/corpus/templates/content/app/components/editor/DocumentEditor.tsx +30 -3
- package/corpus/templates/content/app/components/editor/DocumentInfoPanel.tsx +8 -1
- package/corpus/templates/content/app/components/editor/DocumentProperties.tsx +72 -20
- package/corpus/templates/content/app/components/editor/database/DatabaseView.tsx +79 -10
- package/corpus/templates/content/app/components/editor/database/TimelineView.tsx +8 -1
- package/corpus/templates/content/app/components/editor/database/settings.tsx +6 -0
- package/corpus/templates/content/app/components/editor/database/sidebar.tsx +246 -26
- package/corpus/templates/content/app/components/sidebar/DocumentSidebar.tsx +491 -197
- package/corpus/templates/content/app/components/sidebar/DocumentTreeItem.tsx +3 -3
- package/corpus/templates/content/app/components/sidebar/sidebar-reorder.tsx +409 -0
- package/corpus/templates/content/app/hooks/use-content-database.ts +117 -3
- package/corpus/templates/content/app/hooks/use-content-spaces.ts +1 -0
- package/corpus/templates/content/app/hooks/use-document-properties.ts +62 -18
- package/corpus/templates/content/app/hooks/use-documents.ts +13 -5
- package/corpus/templates/content/app/i18n-data.ts +261 -3
- package/corpus/templates/content/app/routes/_app.page.$id.tsx +9 -2
- package/corpus/templates/content/changelog/2026-07-24-database-page-properties-keep-their-context.md +6 -0
- package/corpus/templates/content/changelog/2026-07-26-sidebar-references-can-now-be-personally-reordered.md +6 -0
- package/corpus/templates/content/docs/solutions/2026-07-24-database-property-context-switch-diagnosis.md +249 -0
- package/corpus/templates/content/docs/solutions/content-sidebar-order-shape.md +389 -0
- package/corpus/templates/content/shared/api.ts +28 -0
- package/corpus/toolkit/CHANGELOG.md +6 -0
- package/corpus/toolkit/package.json +1 -1
- package/corpus/toolkit/src/editor/DragHandle.ts +63 -9
- package/dist/collab/struct-routes.d.ts +1 -1
- package/dist/server/email-template.d.ts +7 -0
- package/dist/server/email-template.d.ts.map +1 -1
- package/dist/server/email-template.js +24 -0
- package/dist/server/email-template.js.map +1 -1
- package/dist/server/realtime-token.d.ts +1 -1
- package/dist/templates/chat/_gitignore +2 -0
- package/package.json +3 -2
- package/src/server/email-template.ts +33 -0
- package/src/templates/chat/_gitignore +2 -0
- package/corpus/core/src/cli/sync-builder-starter-manifest.ts +0 -631
- package/dist/cli/sync-builder-starter-manifest.d.ts +0 -79
- package/dist/cli/sync-builder-starter-manifest.d.ts.map +0 -1
- package/dist/cli/sync-builder-starter-manifest.js +0 -426
- package/dist/cli/sync-builder-starter-manifest.js.map +0 -1
- package/src/cli/sync-builder-starter-manifest.ts +0 -631
|
@@ -6,6 +6,10 @@ import { z } from "zod";
|
|
|
6
6
|
|
|
7
7
|
import { getDb, schema } from "../server/db/index.js";
|
|
8
8
|
import { getContentDatabaseResponse } from "./_database-utils.js";
|
|
9
|
+
import {
|
|
10
|
+
databaseItemsPositionScope,
|
|
11
|
+
withPositionLock,
|
|
12
|
+
} from "./_position-utils.js";
|
|
9
13
|
|
|
10
14
|
function clamp(value: number, min: number, max: number) {
|
|
11
15
|
return Math.min(Math.max(value, min), max);
|
|
@@ -21,13 +25,15 @@ function positionCaseSql(
|
|
|
21
25
|
}
|
|
22
26
|
|
|
23
27
|
export default defineAction({
|
|
24
|
-
description:
|
|
28
|
+
description:
|
|
29
|
+
"Move an exact page membership to a new position in a content database without changing the page's parent or access.",
|
|
25
30
|
schema: z.object({
|
|
31
|
+
databaseId: z.string().optional().describe("Database ID"),
|
|
26
32
|
itemId: z.string().optional().describe("Database item ID"),
|
|
27
33
|
documentId: z.string().optional().describe("Database row document ID"),
|
|
28
34
|
position: z.coerce.number().int().describe("New zero-based row position"),
|
|
29
35
|
}),
|
|
30
|
-
run: async ({ itemId, documentId, position }) => {
|
|
36
|
+
run: async ({ databaseId, itemId, documentId, position }) => {
|
|
31
37
|
if (!itemId && !documentId) {
|
|
32
38
|
throw new Error("Either itemId or documentId is required.");
|
|
33
39
|
}
|
|
@@ -48,6 +54,9 @@ export default defineAction({
|
|
|
48
54
|
itemId
|
|
49
55
|
? eq(schema.contentDatabaseItems.id, itemId)
|
|
50
56
|
: eq(schema.contentDatabaseItems.documentId, documentId!),
|
|
57
|
+
databaseId
|
|
58
|
+
? eq(schema.contentDatabaseItems.databaseId, databaseId)
|
|
59
|
+
: undefined,
|
|
51
60
|
isNull(schema.contentDatabases.deletedAt),
|
|
52
61
|
),
|
|
53
62
|
);
|
|
@@ -56,63 +65,73 @@ export default defineAction({
|
|
|
56
65
|
|
|
57
66
|
await assertAccess("document", row.database.documentId, "editor");
|
|
58
67
|
|
|
59
|
-
|
|
60
|
-
.
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
68
|
+
await withPositionLock(
|
|
69
|
+
databaseItemsPositionScope(row.item.databaseId),
|
|
70
|
+
() =>
|
|
71
|
+
db.transaction(async (tx) => {
|
|
72
|
+
const items = await tx
|
|
73
|
+
.select()
|
|
74
|
+
.from(schema.contentDatabaseItems)
|
|
75
|
+
.where(
|
|
76
|
+
eq(schema.contentDatabaseItems.databaseId, row.item.databaseId),
|
|
77
|
+
)
|
|
78
|
+
.orderBy(asc(schema.contentDatabaseItems.position));
|
|
79
|
+
const currentIndex = items.findIndex(
|
|
80
|
+
(item) => item.id === row.item.id,
|
|
81
|
+
);
|
|
82
|
+
if (currentIndex < 0) throw new Error("Database row not found.");
|
|
67
83
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
return getContentDatabaseResponse(row.item.databaseId);
|
|
71
|
-
}
|
|
84
|
+
const nextIndex = clamp(position, 0, items.length - 1);
|
|
85
|
+
if (nextIndex === currentIndex) return;
|
|
72
86
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
87
|
+
const nextItems = [...items];
|
|
88
|
+
const [moved] = nextItems.splice(currentIndex, 1);
|
|
89
|
+
nextItems.splice(nextIndex, 0, moved);
|
|
90
|
+
const now = new Date().toISOString();
|
|
91
|
+
const itemIds = nextItems.map((item) => item.id);
|
|
92
|
+
const documentIds = nextItems.map((item) => item.documentId);
|
|
79
93
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
);
|
|
94
|
+
await tx
|
|
95
|
+
.update(schema.contentDatabaseItems)
|
|
96
|
+
.set({
|
|
97
|
+
position: positionCaseSql(
|
|
98
|
+
schema.contentDatabaseItems.id,
|
|
99
|
+
schema.contentDatabaseItems.position,
|
|
100
|
+
itemIds,
|
|
101
|
+
),
|
|
102
|
+
updatedAt: now,
|
|
103
|
+
})
|
|
104
|
+
.where(
|
|
105
|
+
and(
|
|
106
|
+
eq(schema.contentDatabaseItems.databaseId, row.item.databaseId),
|
|
107
|
+
inArray(schema.contentDatabaseItems.id, itemIds),
|
|
108
|
+
),
|
|
109
|
+
);
|
|
97
110
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
111
|
+
if (
|
|
112
|
+
row.database.systemRole !== "favorites" &&
|
|
113
|
+
row.database.systemRole !== "workspaces"
|
|
114
|
+
) {
|
|
115
|
+
await tx
|
|
116
|
+
.update(schema.documents)
|
|
117
|
+
.set({
|
|
118
|
+
position: positionCaseSql(
|
|
119
|
+
schema.documents.id,
|
|
120
|
+
schema.documents.position,
|
|
121
|
+
documentIds,
|
|
122
|
+
),
|
|
123
|
+
updatedAt: now,
|
|
124
|
+
})
|
|
125
|
+
.where(
|
|
126
|
+
and(
|
|
127
|
+
eq(schema.documents.ownerEmail, row.database.ownerEmail),
|
|
128
|
+
eq(schema.documents.parentId, row.database.documentId),
|
|
129
|
+
inArray(schema.documents.id, documentIds),
|
|
130
|
+
),
|
|
131
|
+
);
|
|
132
|
+
}
|
|
133
|
+
}),
|
|
134
|
+
);
|
|
116
135
|
|
|
117
136
|
await writeAppState("refresh-signal", { ts: Date.now() });
|
|
118
137
|
|
|
@@ -15,6 +15,12 @@ export default defineAction({
|
|
|
15
15
|
"Reorder a property definition within its database by moving it before or after another property. Used for reordering Blocks fields on the page.",
|
|
16
16
|
schema: z.object({
|
|
17
17
|
documentId: z.string().describe("Document ID used to scope access"),
|
|
18
|
+
databaseId: z
|
|
19
|
+
.string()
|
|
20
|
+
.optional()
|
|
21
|
+
.describe(
|
|
22
|
+
"Database ID that owns the properties; omit only for context-free entry points",
|
|
23
|
+
),
|
|
18
24
|
propertyId: z.string().describe("Property definition ID to move"),
|
|
19
25
|
targetPropertyId: z.string().describe("Property to position relative to"),
|
|
20
26
|
position: z
|
|
@@ -22,11 +28,21 @@ export default defineAction({
|
|
|
22
28
|
.default("before")
|
|
23
29
|
.describe("Place the moved property before or after the target"),
|
|
24
30
|
}),
|
|
25
|
-
run: async ({
|
|
31
|
+
run: async ({
|
|
32
|
+
documentId,
|
|
33
|
+
databaseId,
|
|
34
|
+
propertyId,
|
|
35
|
+
targetPropertyId,
|
|
36
|
+
position,
|
|
37
|
+
}) => {
|
|
26
38
|
const access = await assertAccess("document", documentId, "editor");
|
|
27
39
|
const document = access.resource;
|
|
28
40
|
const db = getDb();
|
|
29
|
-
const database = await resolvePropertyDatabaseForDocument(
|
|
41
|
+
const database = await resolvePropertyDatabaseForDocument(
|
|
42
|
+
document,
|
|
43
|
+
databaseId,
|
|
44
|
+
"editor",
|
|
45
|
+
);
|
|
30
46
|
if (!database) throw new Error("Document is not part of a database.");
|
|
31
47
|
|
|
32
48
|
const definitions = await db
|
|
@@ -55,7 +71,7 @@ export default defineAction({
|
|
|
55
71
|
return {
|
|
56
72
|
documentId,
|
|
57
73
|
databaseId: database.id,
|
|
58
|
-
properties: await listPropertiesForDocument(document),
|
|
74
|
+
properties: await listPropertiesForDocument(document, database.id),
|
|
59
75
|
};
|
|
60
76
|
}
|
|
61
77
|
|
|
@@ -83,7 +99,7 @@ export default defineAction({
|
|
|
83
99
|
return {
|
|
84
100
|
documentId,
|
|
85
101
|
databaseId: database.id,
|
|
86
|
-
properties: await listPropertiesForDocument(document),
|
|
102
|
+
properties: await listPropertiesForDocument(document, database.id),
|
|
87
103
|
};
|
|
88
104
|
},
|
|
89
105
|
});
|
|
@@ -26,10 +26,16 @@ export default defineAction({
|
|
|
26
26
|
description: "Set a Notion-style property value on a document.",
|
|
27
27
|
schema: z.object({
|
|
28
28
|
documentId: z.string().describe("Document ID (required)"),
|
|
29
|
+
databaseId: z
|
|
30
|
+
.string()
|
|
31
|
+
.optional()
|
|
32
|
+
.describe(
|
|
33
|
+
"Database ID that owns the property; omit only for context-free entry points",
|
|
34
|
+
),
|
|
29
35
|
propertyId: z.string().describe("Property definition ID"),
|
|
30
36
|
value: z.unknown().describe("Value for the property type"),
|
|
31
37
|
}),
|
|
32
|
-
run: async ({ documentId, propertyId, value }) => {
|
|
38
|
+
run: async ({ documentId, databaseId, propertyId, value }) => {
|
|
33
39
|
const db = getDb();
|
|
34
40
|
const [definition] = await db
|
|
35
41
|
.select()
|
|
@@ -39,6 +45,9 @@ export default defineAction({
|
|
|
39
45
|
if (!definition.databaseId) {
|
|
40
46
|
throw new Error(`Property "${propertyId}" is not attached to a database`);
|
|
41
47
|
}
|
|
48
|
+
if (databaseId && definition.databaseId !== databaseId) {
|
|
49
|
+
throw new Error(`Property "${propertyId}" not found`);
|
|
50
|
+
}
|
|
42
51
|
const database = await getDatabaseById(definition.databaseId);
|
|
43
52
|
if (!database) throw new Error("Document database not found.");
|
|
44
53
|
await assertAccess("document", database.documentId, "editor");
|
|
@@ -4,9 +4,11 @@ import { z } from "zod";
|
|
|
4
4
|
|
|
5
5
|
import {
|
|
6
6
|
assertContentDatabaseViewerAccess,
|
|
7
|
+
normalizePersonalDatabaseViewOverrides,
|
|
7
8
|
personalDatabaseViewSettingKey,
|
|
8
9
|
personalViewOverridesSchema,
|
|
9
10
|
} from "./_content-database-personal-view.js";
|
|
11
|
+
import { getContentDatabaseResponse } from "./_database-utils.js";
|
|
10
12
|
|
|
11
13
|
export default defineAction({
|
|
12
14
|
description:
|
|
@@ -21,6 +23,11 @@ export default defineAction({
|
|
|
21
23
|
|
|
22
24
|
const key = personalDatabaseViewSettingKey(databaseId);
|
|
23
25
|
if (overrides) {
|
|
26
|
+
const visibleDatabase = await getContentDatabaseResponse(databaseId);
|
|
27
|
+
overrides = normalizePersonalDatabaseViewOverrides(
|
|
28
|
+
overrides,
|
|
29
|
+
new Set(visibleDatabase.items.map((item) => item.id)),
|
|
30
|
+
);
|
|
24
31
|
await putUserSetting(ctx.userEmail, key, overrides);
|
|
25
32
|
} else {
|
|
26
33
|
await deleteUserSetting(ctx.userEmail, key);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { useT } from "@agent-native/core/client/i18n";
|
|
2
|
-
import type { DocumentProperty } from "@shared/api";
|
|
2
|
+
import type { DocumentPropertiesResponse, DocumentProperty } from "@shared/api";
|
|
3
3
|
import {
|
|
4
4
|
blocksRenderMode,
|
|
5
5
|
blocksStorageTarget,
|
|
@@ -17,9 +17,12 @@ import {
|
|
|
17
17
|
type PointerEvent as ReactPointerEvent,
|
|
18
18
|
} from "react";
|
|
19
19
|
|
|
20
|
-
import {
|
|
21
|
-
|
|
22
|
-
|
|
20
|
+
import {
|
|
21
|
+
documentPropertiesResponseMatchesScope,
|
|
22
|
+
useDocumentProperties,
|
|
23
|
+
useReorderDocumentProperty,
|
|
24
|
+
useSetDocumentProperty,
|
|
25
|
+
} from "@/hooks/use-document-properties";
|
|
23
26
|
import { cn } from "@/lib/utils";
|
|
24
27
|
|
|
25
28
|
import {
|
|
@@ -38,6 +41,7 @@ const BLOCK_FIELD_DRAG_THRESHOLD = 6;
|
|
|
38
41
|
|
|
39
42
|
interface DocumentBlockFieldsProps {
|
|
40
43
|
documentId: string;
|
|
44
|
+
databaseId: string;
|
|
41
45
|
databaseDocumentId: string;
|
|
42
46
|
canEdit: boolean;
|
|
43
47
|
/**
|
|
@@ -191,17 +195,18 @@ export type BlockFieldsRenderState =
|
|
|
191
195
|
| { kind: "solo"; field: DocumentProperty; target: BlocksStorageTarget }
|
|
192
196
|
| { kind: "multi"; fields: DocumentProperty[] };
|
|
193
197
|
|
|
194
|
-
// Whether the query data we are holding
|
|
198
|
+
// Whether the query data we are holding belongs to the current row and database.
|
|
195
199
|
// `useDocumentProperties` keeps the previous document's data as placeholder
|
|
196
|
-
// across a
|
|
200
|
+
// across a scope change, so both identities must be confirmed before the field
|
|
197
201
|
// layout is trusted — otherwise the old doc's solo-primary layout could route
|
|
198
202
|
// the new doc's edits to the body. The response carries its own `documentId`
|
|
199
203
|
// (shared/api.ts → DocumentPropertiesResponse).
|
|
200
204
|
export function isLoadedForDocument(
|
|
201
205
|
documentId: string,
|
|
202
|
-
|
|
206
|
+
databaseId: string,
|
|
207
|
+
data: DocumentPropertiesResponse | undefined,
|
|
203
208
|
): boolean {
|
|
204
|
-
return
|
|
209
|
+
return documentPropertiesResponseMatchesScope(documentId, databaseId, data);
|
|
205
210
|
}
|
|
206
211
|
|
|
207
212
|
export function blockFieldsRenderState(args: {
|
|
@@ -239,28 +244,22 @@ export function blockFieldsRenderState(args: {
|
|
|
239
244
|
*/
|
|
240
245
|
export function DocumentBlockFields({
|
|
241
246
|
documentId,
|
|
247
|
+
databaseId,
|
|
242
248
|
databaseDocumentId,
|
|
243
249
|
canEdit,
|
|
244
250
|
primaryEditor,
|
|
245
251
|
}: DocumentBlockFieldsProps) {
|
|
246
252
|
const t = useT();
|
|
247
|
-
const query = useDocumentProperties(documentId);
|
|
253
|
+
const query = useDocumentProperties(documentId, databaseId);
|
|
248
254
|
const properties = query.data?.properties ?? [];
|
|
249
255
|
const blockFields = useMemo(
|
|
250
256
|
() => blockFieldsFromProperties(properties),
|
|
251
257
|
[properties],
|
|
252
258
|
);
|
|
253
259
|
|
|
254
|
-
//
|
|
255
|
-
//
|
|
256
|
-
|
|
257
|
-
// document's field layout for a tick. Trusting it would let the old doc's
|
|
258
|
-
// solo-primary layout route the NEW doc's edits to the body (clobbering a
|
|
259
|
-
// non-primary field). The response carries its own `documentId`
|
|
260
|
-
// (shared/api.ts → DocumentPropertiesResponse), so we gate on an identity
|
|
261
|
-
// match: until the data is for THIS document, treat the row as still loading
|
|
262
|
-
// (a non-editable placeholder), never a writable body editor.
|
|
263
|
-
const loaded = isLoadedForDocument(documentId, query.data);
|
|
260
|
+
// Placeholder data may belong to the previous row or database. Trust it only
|
|
261
|
+
// after both response identities match the active scope.
|
|
262
|
+
const loaded = isLoadedForDocument(documentId, databaseId, query.data);
|
|
264
263
|
const state = blockFieldsRenderState({ loaded, blockFields });
|
|
265
264
|
|
|
266
265
|
switch (state.kind) {
|
|
@@ -321,6 +320,7 @@ export function DocumentBlockFields({
|
|
|
321
320
|
return (
|
|
322
321
|
<MultiBlockFields
|
|
323
322
|
documentId={documentId}
|
|
323
|
+
databaseId={databaseId}
|
|
324
324
|
databaseDocumentId={databaseDocumentId}
|
|
325
325
|
canEdit={canEdit}
|
|
326
326
|
blockFields={state.fields}
|
|
@@ -333,6 +333,7 @@ export function DocumentBlockFields({
|
|
|
333
333
|
|
|
334
334
|
function MultiBlockFields({
|
|
335
335
|
documentId,
|
|
336
|
+
databaseId,
|
|
336
337
|
databaseDocumentId,
|
|
337
338
|
canEdit,
|
|
338
339
|
blockFields,
|
|
@@ -340,13 +341,18 @@ function MultiBlockFields({
|
|
|
340
341
|
t,
|
|
341
342
|
}: {
|
|
342
343
|
documentId: string;
|
|
344
|
+
databaseId: string;
|
|
343
345
|
databaseDocumentId: string;
|
|
344
346
|
canEdit: boolean;
|
|
345
347
|
blockFields: DocumentProperty[];
|
|
346
348
|
primaryEditor: ReactNode;
|
|
347
349
|
t: ReturnType<typeof useT>;
|
|
348
350
|
}) {
|
|
349
|
-
const reorder = useReorderDocumentProperty(
|
|
351
|
+
const reorder = useReorderDocumentProperty(
|
|
352
|
+
documentId,
|
|
353
|
+
databaseId,
|
|
354
|
+
databaseDocumentId,
|
|
355
|
+
);
|
|
350
356
|
const [dragId, setDragId] = useState<string | null>(null);
|
|
351
357
|
const [dragOverGapIndex, setDragOverGapIndex] = useState<number | null>(null);
|
|
352
358
|
const [dragPreview, setDragPreview] =
|
|
@@ -805,7 +811,11 @@ function AdditionalBlockEditor({
|
|
|
805
811
|
property: DocumentProperty;
|
|
806
812
|
canEdit: boolean;
|
|
807
813
|
}) {
|
|
808
|
-
const setProperty = useSetDocumentProperty(
|
|
814
|
+
const setProperty = useSetDocumentProperty(
|
|
815
|
+
documentId,
|
|
816
|
+
property.definition.databaseId!,
|
|
817
|
+
databaseDocumentId,
|
|
818
|
+
);
|
|
809
819
|
const propertyId = property.definition.id;
|
|
810
820
|
const initialContent =
|
|
811
821
|
typeof property.value === "string" ? property.value : "";
|
|
@@ -109,6 +109,8 @@ const TAB_ID = generateTabId();
|
|
|
109
109
|
|
|
110
110
|
interface DocumentEditorProps {
|
|
111
111
|
documentId: string;
|
|
112
|
+
databaseId?: string | null;
|
|
113
|
+
databaseDocumentId?: string | null;
|
|
112
114
|
}
|
|
113
115
|
|
|
114
116
|
type FieldSaveWatermark = { title: string; updatedAt: string | null };
|
|
@@ -240,7 +242,11 @@ function DocumentUnavailable({ onOpenHome }: { onOpenHome: () => void }) {
|
|
|
240
242
|
* only mount once we know the doc exists. Otherwise an invalid id triggers
|
|
241
243
|
* an infinite spinner plus repeating 404/403 polls in the console.
|
|
242
244
|
*/
|
|
243
|
-
export function DocumentEditor({
|
|
245
|
+
export function DocumentEditor({
|
|
246
|
+
documentId,
|
|
247
|
+
databaseId,
|
|
248
|
+
databaseDocumentId,
|
|
249
|
+
}: DocumentEditorProps) {
|
|
244
250
|
const documentQuery = useDocument(documentId);
|
|
245
251
|
const {
|
|
246
252
|
data: queriedDocument,
|
|
@@ -271,7 +277,14 @@ export function DocumentEditor({ documentId }: DocumentEditorProps) {
|
|
|
271
277
|
return <DocumentEditorSkeleton />;
|
|
272
278
|
}
|
|
273
279
|
|
|
274
|
-
return
|
|
280
|
+
return (
|
|
281
|
+
<DocumentEditorBody
|
|
282
|
+
documentId={documentId}
|
|
283
|
+
document={document}
|
|
284
|
+
databaseId={databaseId}
|
|
285
|
+
databaseDocumentId={databaseDocumentId}
|
|
286
|
+
/>
|
|
287
|
+
);
|
|
275
288
|
}
|
|
276
289
|
|
|
277
290
|
export function shouldAwaitAuthoritativeDocument({
|
|
@@ -287,6 +300,8 @@ export function shouldAwaitAuthoritativeDocument({
|
|
|
287
300
|
interface DocumentEditorBodyProps {
|
|
288
301
|
documentId: string;
|
|
289
302
|
document: Document;
|
|
303
|
+
databaseId?: string | null;
|
|
304
|
+
databaseDocumentId?: string | null;
|
|
290
305
|
}
|
|
291
306
|
|
|
292
307
|
type PendingDocumentSave = {
|
|
@@ -508,7 +523,12 @@ export function documentEditorBreadcrumbNavigationItems(
|
|
|
508
523
|
return navigationItems;
|
|
509
524
|
}
|
|
510
525
|
|
|
511
|
-
function DocumentEditorBody({
|
|
526
|
+
function DocumentEditorBody({
|
|
527
|
+
documentId,
|
|
528
|
+
document,
|
|
529
|
+
databaseId,
|
|
530
|
+
databaseDocumentId,
|
|
531
|
+
}: DocumentEditorBodyProps) {
|
|
512
532
|
const t = useT();
|
|
513
533
|
const updateDocument = useUpdateDocument();
|
|
514
534
|
const createDatabase = useCreateContentDatabase(documentId);
|
|
@@ -1674,6 +1694,8 @@ function DocumentEditorBody({ documentId, document }: DocumentEditorBodyProps) {
|
|
|
1674
1694
|
{utilityPanel === "info" ? (
|
|
1675
1695
|
<DocumentInfoPanel
|
|
1676
1696
|
document={document}
|
|
1697
|
+
databaseId={databaseId}
|
|
1698
|
+
databaseDocumentId={databaseDocumentId}
|
|
1677
1699
|
canEdit={editorCanEdit}
|
|
1678
1700
|
onSaveDescription={(description) =>
|
|
1679
1701
|
persistDocumentUpdates({ description })
|
|
@@ -1970,7 +1992,12 @@ function DocumentEditorBody({ documentId, document }: DocumentEditorBodyProps) {
|
|
|
1970
1992
|
return (
|
|
1971
1993
|
<DocumentBlockFields
|
|
1972
1994
|
documentId={documentId}
|
|
1995
|
+
databaseId={
|
|
1996
|
+
databaseId ??
|
|
1997
|
+
document.databaseMembership.databaseId
|
|
1998
|
+
}
|
|
1973
1999
|
databaseDocumentId={
|
|
2000
|
+
databaseDocumentId ??
|
|
1974
2001
|
document.databaseMembership.databaseDocumentId
|
|
1975
2002
|
}
|
|
1976
2003
|
canEdit={editorCanEdit}
|
|
@@ -6,12 +6,16 @@ import { DocumentProperties } from "./DocumentProperties";
|
|
|
6
6
|
|
|
7
7
|
interface DocumentInfoPanelProps {
|
|
8
8
|
document: Document;
|
|
9
|
+
databaseId?: string | null;
|
|
10
|
+
databaseDocumentId?: string | null;
|
|
9
11
|
canEdit: boolean;
|
|
10
12
|
onSaveDescription: (description: string) => Promise<unknown> | unknown;
|
|
11
13
|
}
|
|
12
14
|
|
|
13
15
|
export function DocumentInfoPanel({
|
|
14
16
|
document,
|
|
17
|
+
databaseId,
|
|
18
|
+
databaseDocumentId,
|
|
15
19
|
canEdit,
|
|
16
20
|
onSaveDescription,
|
|
17
21
|
}: DocumentInfoPanelProps) {
|
|
@@ -34,7 +38,10 @@ export function DocumentInfoPanel({
|
|
|
34
38
|
{document.databaseMembership && !isLocalFileDocument ? (
|
|
35
39
|
<DocumentProperties
|
|
36
40
|
documentId={document.id}
|
|
37
|
-
|
|
41
|
+
databaseId={databaseId ?? document.databaseMembership.databaseId}
|
|
42
|
+
databaseDocumentId={
|
|
43
|
+
databaseDocumentId ?? document.databaseMembership.databaseDocumentId
|
|
44
|
+
}
|
|
38
45
|
canEdit={canEdit}
|
|
39
46
|
/>
|
|
40
47
|
) : null}
|