@agent-native/core 0.101.6 → 0.101.10
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 +1 -1
- package/corpus/core/CHANGELOG.md +28 -0
- package/corpus/core/docs/content/deployment.mdx +9 -7
- package/corpus/core/docs/content/locales/ar-SA/deployment.mdx +9 -7
- package/corpus/core/docs/content/locales/de-DE/deployment.mdx +9 -7
- package/corpus/core/docs/content/locales/es-ES/deployment.mdx +9 -7
- package/corpus/core/docs/content/locales/fr-FR/deployment.mdx +9 -7
- package/corpus/core/docs/content/locales/hi-IN/deployment.mdx +9 -7
- package/corpus/core/docs/content/locales/ja-JP/deployment.mdx +9 -7
- package/corpus/core/docs/content/locales/ko-KR/deployment.mdx +9 -7
- package/corpus/core/docs/content/locales/pt-BR/deployment.mdx +9 -7
- package/corpus/core/docs/content/locales/zh-CN/deployment.mdx +9 -7
- package/corpus/core/docs/content/locales/zh-TW/deployment.mdx +9 -7
- package/corpus/core/package.json +1 -1
- package/corpus/core/src/a2a/artifact-response.ts +255 -12
- package/corpus/core/src/agent/thread-data-builder.ts +84 -11
- package/corpus/core/src/client/review/ReviewCommentComposer.tsx +9 -1
- package/corpus/core/src/client/review/ReviewThreadPanel.tsx +17 -2
- package/corpus/core/src/client/settings/SettingsPanel.tsx +41 -21
- package/corpus/core/src/client/settings/useBuilderStatus.ts +28 -9
- package/corpus/core/src/client/setup-connections/BuilderConnectCard.tsx +2 -7
- package/corpus/core/src/integrations/a2a-continuation-processor.ts +99 -7
- package/corpus/core/src/integrations/adapters/discord.ts +3 -1
- package/corpus/core/src/integrations/adapters/email.ts +4 -1
- package/corpus/core/src/integrations/adapters/google-docs.ts +4 -1
- package/corpus/core/src/integrations/adapters/microsoft-teams.ts +3 -1
- package/corpus/core/src/integrations/adapters/slack.ts +38 -9
- package/corpus/core/src/integrations/adapters/telegram.ts +32 -10
- package/corpus/core/src/integrations/adapters/whatsapp.ts +5 -1
- package/corpus/core/src/integrations/index.ts +1 -0
- package/corpus/core/src/integrations/types.ts +9 -2
- package/corpus/core/src/integrations/webhook-handler.ts +69 -45
- package/corpus/core/src/server/agent-chat/action-filters-a2a.ts +1 -0
- package/corpus/core/src/server/auth.ts +25 -1
- package/corpus/core/src/server/builder-browser.ts +353 -1
- package/corpus/core/src/server/core-routes-plugin.ts +601 -223
- package/corpus/templates/calendar/app/components/calendar/DayView.tsx +80 -1
- package/corpus/templates/calendar/app/components/calendar/EventCard.tsx +28 -3
- package/corpus/templates/calendar/app/components/calendar/EventDetailPanel.tsx +5 -1
- package/corpus/templates/calendar/app/components/calendar/EventDetailPopover.tsx +30 -3
- package/corpus/templates/calendar/app/components/calendar/OutOfOfficeEvent.tsx +196 -0
- package/corpus/templates/calendar/app/components/calendar/WeekView.tsx +115 -1
- package/corpus/templates/calendar/app/lib/out-of-office.ts +45 -0
- package/corpus/templates/calendar/changelog/2026-07-14-out-of-office-blocks-now-sit-behind-meetings-and-event-stack.md +6 -0
- package/corpus/templates/content/.agents/skills/content/SKILL.md +31 -0
- package/corpus/templates/content/.agents/skills/document-editing/SKILL.md +35 -21
- package/corpus/templates/content/AGENTS.md +32 -9
- package/corpus/templates/content/actions/_builder-cms-intent-lookup.ts +87 -0
- package/corpus/templates/content/actions/_builder-cms-read-client.ts +173 -25
- package/corpus/templates/content/actions/_builder-cms-source-adapter.ts +1 -0
- package/corpus/templates/content/actions/_builder-cms-write-adapter.ts +427 -18
- package/corpus/templates/content/actions/_builder-cms-write-client.ts +17 -73
- package/corpus/templates/content/actions/_builder-cms-write-settings.ts +27 -7
- package/corpus/templates/content/actions/_builder-source-execution-claim.ts +124 -0
- package/corpus/templates/content/actions/_builder-source-execution-preservation.ts +21 -0
- package/corpus/templates/content/actions/_builder-source-timings.ts +57 -0
- package/corpus/templates/content/actions/_database-source-utils.ts +1071 -170
- package/corpus/templates/content/actions/_database-utils.ts +104 -13
- package/corpus/templates/content/actions/_local-file-documents.ts +53 -1
- package/corpus/templates/content/actions/_preview-document-draft.ts +31 -0
- package/corpus/templates/content/actions/_property-utils.ts +7 -1
- package/corpus/templates/content/actions/cancel-prepared-builder-source-update.ts +309 -0
- package/corpus/templates/content/actions/configure-document-property.ts +11 -0
- package/corpus/templates/content/actions/create-content-database.ts +11 -0
- package/corpus/templates/content/actions/create-document.ts +9 -0
- package/corpus/templates/content/actions/create-inline-content-database.ts +3 -0
- package/corpus/templates/content/actions/execute-builder-source-batch.ts +120 -49
- package/corpus/templates/content/actions/execute-builder-source-execution.ts +608 -264
- package/corpus/templates/content/actions/export-content-source.ts +1 -0
- package/corpus/templates/content/actions/get-content-database.ts +13 -1
- package/corpus/templates/content/actions/get-document.ts +12 -2
- package/corpus/templates/content/actions/get-preview-document-draft.ts +26 -0
- package/corpus/templates/content/actions/import-content-source.ts +6 -0
- package/corpus/templates/content/actions/list-documents.ts +3 -0
- package/corpus/templates/content/actions/materialize-builder-required-fields.ts +550 -0
- package/corpus/templates/content/actions/prepare-builder-source-execution.ts +112 -65
- package/corpus/templates/content/actions/prepare-builder-source-review.ts +463 -170
- package/corpus/templates/content/actions/preview-builder-source-review.ts +99 -0
- package/corpus/templates/content/actions/pull-document.ts +2 -0
- package/corpus/templates/content/actions/search-documents.ts +5 -1
- package/corpus/templates/content/actions/set-content-database-source-write-mode.ts +2 -2
- package/corpus/templates/content/actions/update-document.ts +16 -1
- package/corpus/templates/content/actions/update-preview-document-draft.ts +153 -0
- package/corpus/templates/content/actions/view-screen.ts +15 -2
- package/corpus/templates/content/app/components/editor/DescriptionField.tsx +121 -0
- package/corpus/templates/content/app/components/editor/DocumentEditor.tsx +14 -0
- package/corpus/templates/content/app/components/editor/DocumentProperties.tsx +250 -49
- package/corpus/templates/content/app/components/editor/VisualEditor.tsx +57 -5
- package/corpus/templates/content/app/components/editor/body-hydration.ts +27 -0
- package/corpus/templates/content/app/components/editor/database/DatabaseView.tsx +2414 -589
- package/corpus/templates/content/app/components/editor/database/settings.tsx +13 -10
- package/corpus/templates/content/app/components/editor/database-sources/BuilderSourceReviewDialog.tsx +358 -75
- package/corpus/templates/content/app/components/editor/previewDocumentSaveController.ts +124 -29
- package/corpus/templates/content/app/components/editor/previewDocumentSaveRegistry.ts +2 -0
- package/corpus/templates/content/app/global.css +18 -1
- package/corpus/templates/content/app/hooks/use-content-database.ts +68 -0
- package/corpus/templates/content/app/hooks/use-documents.ts +53 -4
- package/corpus/templates/content/app/i18n/zh-TW.ts +30 -0
- package/corpus/templates/content/app/i18n-data.ts +339 -0
- package/corpus/templates/content/changelog/2026-07-10-builder-backed-preview-edits-are-preserved-when-article-bodi.md +6 -0
- package/corpus/templates/content/changelog/2026-07-10-builder-cms-sources-can-now-be-enabled-for-guarded-staged-or.md +6 -0
- package/corpus/templates/content/changelog/2026-07-13-builder-connection-setup-is-now-available-directly-from-conn.md +6 -0
- package/corpus/templates/content/changelog/2026-07-13-builder-reviews-now-hide-already-applied-writes-detect-nativ.md +6 -0
- package/corpus/templates/content/changelog/2026-07-13-required-builder-publishing-fields-can-now-be-added-directly.md +6 -0
- package/corpus/templates/content/changelog/2026-07-13-you-can-now-cancel-a-prepared-builder-update-safely-before-i.md +6 -0
- package/corpus/templates/content/changelog/2026-07-14-builder-account-connection-now-remains-available-when-branch.md +6 -0
- package/corpus/templates/content/changelog/2026-07-14-builder-backed-articles-now-preserve-fifth-and-sixth-level-h.md +6 -0
- package/corpus/templates/content/changelog/2026-07-14-builder-sources-now-review-and-publish-rich-article-updates-.md +6 -0
- package/corpus/templates/content/changelog/2026-07-14-builder-writes-now-stop-retries-when-reconciliation-is-needed.md +6 -0
- package/corpus/templates/content/changelog/2026-07-14-file-and-media-links-now-validate-before-saving.md +6 -0
- package/corpus/templates/content/changelog/2026-07-14-pages-and-databases-can-describe-themselves-with-guidance-fo.md +6 -0
- package/corpus/templates/content/changelog/2026-07-14-slack-follow-ups-now-retain-created-content-identity-and-per.md +6 -0
- package/corpus/templates/content/parity/matrix.md +27 -25
- package/corpus/templates/content/parity/matrix.ts +50 -2
- package/corpus/templates/content/server/db/schema.ts +51 -0
- package/corpus/templates/content/server/lib/document-context.ts +76 -0
- package/corpus/templates/content/server/lib/public-documents.ts +3 -0
- package/corpus/templates/content/server/plugins/auth.ts +1 -0
- package/corpus/templates/content/server/plugins/db.ts +59 -0
- package/corpus/templates/content/server/routes/api/document-agent-context.json.get.ts +5 -0
- package/corpus/templates/content/shared/api.ts +87 -1
- package/corpus/templates/content/shared/builder-mdx.ts +705 -15
- package/corpus/templates/content/shared/content-source.ts +7 -0
- package/corpus/templates/content/shared/nfm.ts +3 -3
- package/corpus/templates/content/shared/properties.ts +2 -0
- package/corpus/templates/design/app/components/design/ReadOnlyDesignBanner.tsx +52 -7
- package/corpus/templates/design/app/components/design/ReviewCommentsPanel.tsx +36 -4
- package/corpus/templates/design/app/components/visual-editor/ReviewCanvasPins.tsx +4 -1
- package/corpus/templates/design/app/i18n/ar-SA.ts +1 -0
- package/corpus/templates/design/app/i18n/de-DE.ts +1 -0
- package/corpus/templates/design/app/i18n/en-US.ts +1 -0
- package/corpus/templates/design/app/i18n/es-ES.ts +1 -0
- package/corpus/templates/design/app/i18n/fr-FR.ts +1 -0
- package/corpus/templates/design/app/i18n/hi-IN.ts +1 -0
- package/corpus/templates/design/app/i18n/ja-JP.ts +1 -0
- package/corpus/templates/design/app/i18n/ko-KR.ts +1 -0
- package/corpus/templates/design/app/i18n/pt-BR.ts +1 -0
- package/corpus/templates/design/app/i18n/zh-CN.ts +1 -0
- package/corpus/templates/design/app/i18n/zh-TW.ts +1 -0
- package/corpus/templates/design/app/pages/design-editor/selection-state.ts +8 -0
- package/corpus/templates/design/app/pages/design-editor/tool-state.ts +11 -0
- package/corpus/templates/design/changelog/2026-07-14-reviewers-can-now-pin-comments-from-the-canvas-toolbar-targe.md +6 -0
- package/corpus/templates/design/changelog/2026-07-15-viewer-comment-controls-now-sit-inside-the-read-only-notice-.md +6 -0
- package/corpus/templates/design/shared/review-anchor.ts +48 -0
- package/corpus/templates/plan/server/plan-mdx.ts +53 -7
- package/dist/a2a/artifact-response.d.ts +15 -0
- package/dist/a2a/artifact-response.d.ts.map +1 -1
- package/dist/a2a/artifact-response.js +204 -5
- package/dist/a2a/artifact-response.js.map +1 -1
- package/dist/agent/thread-data-builder.d.ts +6 -0
- package/dist/agent/thread-data-builder.d.ts.map +1 -1
- package/dist/agent/thread-data-builder.js +71 -8
- package/dist/agent/thread-data-builder.js.map +1 -1
- package/dist/client/review/ReviewCommentComposer.d.ts +2 -1
- package/dist/client/review/ReviewCommentComposer.d.ts.map +1 -1
- package/dist/client/review/ReviewCommentComposer.js +3 -3
- package/dist/client/review/ReviewCommentComposer.js.map +1 -1
- package/dist/client/review/ReviewThreadPanel.d.ts +9 -1
- package/dist/client/review/ReviewThreadPanel.d.ts.map +1 -1
- package/dist/client/review/ReviewThreadPanel.js +6 -4
- package/dist/client/review/ReviewThreadPanel.js.map +1 -1
- package/dist/client/settings/SettingsPanel.d.ts +3 -0
- package/dist/client/settings/SettingsPanel.d.ts.map +1 -1
- package/dist/client/settings/SettingsPanel.js +11 -4
- package/dist/client/settings/SettingsPanel.js.map +1 -1
- package/dist/client/settings/useBuilderStatus.d.ts +8 -4
- package/dist/client/settings/useBuilderStatus.d.ts.map +1 -1
- package/dist/client/settings/useBuilderStatus.js +19 -6
- package/dist/client/settings/useBuilderStatus.js.map +1 -1
- package/dist/client/setup-connections/BuilderConnectCard.d.ts.map +1 -1
- package/dist/client/setup-connections/BuilderConnectCard.js +2 -5
- package/dist/client/setup-connections/BuilderConnectCard.js.map +1 -1
- package/dist/collab/awareness.d.ts +2 -2
- package/dist/collab/awareness.d.ts.map +1 -1
- package/dist/integrations/a2a-continuation-processor.d.ts.map +1 -1
- package/dist/integrations/a2a-continuation-processor.js +72 -6
- package/dist/integrations/a2a-continuation-processor.js.map +1 -1
- package/dist/integrations/adapters/discord.d.ts.map +1 -1
- package/dist/integrations/adapters/discord.js +1 -0
- package/dist/integrations/adapters/discord.js.map +1 -1
- package/dist/integrations/adapters/email.d.ts.map +1 -1
- package/dist/integrations/adapters/email.js +2 -0
- package/dist/integrations/adapters/email.js.map +1 -1
- package/dist/integrations/adapters/google-docs.d.ts.map +1 -1
- package/dist/integrations/adapters/google-docs.js +2 -0
- package/dist/integrations/adapters/google-docs.js.map +1 -1
- package/dist/integrations/adapters/microsoft-teams.d.ts.map +1 -1
- package/dist/integrations/adapters/microsoft-teams.js +1 -0
- package/dist/integrations/adapters/microsoft-teams.js.map +1 -1
- package/dist/integrations/adapters/slack.d.ts.map +1 -1
- package/dist/integrations/adapters/slack.js +21 -6
- package/dist/integrations/adapters/slack.js.map +1 -1
- package/dist/integrations/adapters/telegram.d.ts.map +1 -1
- package/dist/integrations/adapters/telegram.js +11 -2
- package/dist/integrations/adapters/telegram.js.map +1 -1
- package/dist/integrations/adapters/whatsapp.d.ts.map +1 -1
- package/dist/integrations/adapters/whatsapp.js +3 -0
- package/dist/integrations/adapters/whatsapp.js.map +1 -1
- package/dist/integrations/index.d.ts +1 -1
- package/dist/integrations/index.d.ts.map +1 -1
- package/dist/integrations/index.js.map +1 -1
- package/dist/integrations/types.d.ts +8 -2
- package/dist/integrations/types.d.ts.map +1 -1
- package/dist/integrations/types.js.map +1 -1
- package/dist/integrations/webhook-handler.d.ts.map +1 -1
- package/dist/integrations/webhook-handler.js +40 -43
- package/dist/integrations/webhook-handler.js.map +1 -1
- package/dist/observability/routes.d.ts +5 -5
- package/dist/provider-api/corpus-jobs.d.ts +2 -2
- package/dist/secrets/routes.d.ts +9 -9
- package/dist/server/agent-chat/action-filters-a2a.d.ts.map +1 -1
- package/dist/server/agent-chat/action-filters-a2a.js +1 -0
- package/dist/server/agent-chat/action-filters-a2a.js.map +1 -1
- package/dist/server/auth.d.ts +1 -0
- package/dist/server/auth.d.ts.map +1 -1
- package/dist/server/auth.js +19 -2
- package/dist/server/auth.js.map +1 -1
- package/dist/server/builder-browser.d.ts +78 -0
- package/dist/server/builder-browser.d.ts.map +1 -1
- package/dist/server/builder-browser.js +246 -1
- package/dist/server/builder-browser.js.map +1 -1
- package/dist/server/core-routes-plugin.d.ts +41 -0
- package/dist/server/core-routes-plugin.d.ts.map +1 -1
- package/dist/server/core-routes-plugin.js +260 -14
- package/dist/server/core-routes-plugin.js.map +1 -1
- package/docs/content/deployment.mdx +9 -7
- package/docs/content/locales/ar-SA/deployment.mdx +9 -7
- package/docs/content/locales/de-DE/deployment.mdx +9 -7
- package/docs/content/locales/es-ES/deployment.mdx +9 -7
- package/docs/content/locales/fr-FR/deployment.mdx +9 -7
- package/docs/content/locales/hi-IN/deployment.mdx +9 -7
- package/docs/content/locales/ja-JP/deployment.mdx +9 -7
- package/docs/content/locales/ko-KR/deployment.mdx +9 -7
- package/docs/content/locales/pt-BR/deployment.mdx +9 -7
- package/docs/content/locales/zh-CN/deployment.mdx +9 -7
- package/docs/content/locales/zh-TW/deployment.mdx +9 -7
- package/package.json +2 -2
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { defineAction } from "@agent-native/core";
|
|
2
|
+
import { assertAccess } from "@agent-native/core/sharing";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
|
|
5
|
+
import type {
|
|
6
|
+
PreviewBuilderSourceReviewRequest,
|
|
7
|
+
PreviewBuilderSourceReviewResponse,
|
|
8
|
+
} from "../shared/api.js";
|
|
9
|
+
import {
|
|
10
|
+
getContentDatabaseSourceSnapshotForWrite,
|
|
11
|
+
resolveDatabaseForSourceMutation,
|
|
12
|
+
} from "./_database-source-utils.js";
|
|
13
|
+
import {
|
|
14
|
+
BUILDER_SOURCE_REVIEW_PREPARE_LIMIT,
|
|
15
|
+
buildBuilderSourceReviewPayload,
|
|
16
|
+
reviewPreparePriority,
|
|
17
|
+
withAuthoritativeBuilderTargetRows,
|
|
18
|
+
} from "./prepare-builder-source-review.js";
|
|
19
|
+
|
|
20
|
+
export default defineAction({
|
|
21
|
+
description:
|
|
22
|
+
"Preview complete Builder CMS review diffs, including document body changes, without approving or writing anything.",
|
|
23
|
+
schema: z.object({
|
|
24
|
+
databaseId: z.string().optional().describe("Database ID"),
|
|
25
|
+
documentId: z.string().optional().describe("Database document/page ID"),
|
|
26
|
+
sourceId: z.string().optional().describe("Specific Builder source ID"),
|
|
27
|
+
scope: z.enum(["selected", "all"]).optional().default("all"),
|
|
28
|
+
documentIds: z
|
|
29
|
+
.array(z.string())
|
|
30
|
+
.max(BUILDER_SOURCE_REVIEW_PREPARE_LIMIT)
|
|
31
|
+
.optional()
|
|
32
|
+
.describe("Optional selected document IDs that bound the preview"),
|
|
33
|
+
}),
|
|
34
|
+
http: { method: "GET" },
|
|
35
|
+
readOnly: true,
|
|
36
|
+
run: async (
|
|
37
|
+
args: PreviewBuilderSourceReviewRequest,
|
|
38
|
+
): Promise<PreviewBuilderSourceReviewResponse> => {
|
|
39
|
+
const database = await resolveDatabaseForSourceMutation(args);
|
|
40
|
+
if (!database) throw new Error("Database not found.");
|
|
41
|
+
await assertAccess("document", database.documentId, "editor");
|
|
42
|
+
|
|
43
|
+
const source = await getContentDatabaseSourceSnapshotForWrite(
|
|
44
|
+
database,
|
|
45
|
+
args.sourceId,
|
|
46
|
+
);
|
|
47
|
+
if (!source || source.sourceType !== "builder-cms") {
|
|
48
|
+
throw new Error("Attach a Builder CMS source before reviewing updates.");
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const selectedDocumentIds = new Set(args.documentIds ?? []);
|
|
52
|
+
if (args.scope === "selected" && selectedDocumentIds.size === 0) {
|
|
53
|
+
throw new Error("Select at least one Builder row before reviewing it.");
|
|
54
|
+
}
|
|
55
|
+
const allReviewableChanges = source.changeSets.filter((changeSet) => {
|
|
56
|
+
if (
|
|
57
|
+
changeSet.direction !== "outbound" ||
|
|
58
|
+
(changeSet.state !== "pending_push" &&
|
|
59
|
+
changeSet.state !== "staged_revision" &&
|
|
60
|
+
changeSet.state !== "approved")
|
|
61
|
+
) {
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
64
|
+
return (
|
|
65
|
+
args.scope === "all" ||
|
|
66
|
+
(!!changeSet.documentId &&
|
|
67
|
+
selectedDocumentIds.has(changeSet.documentId))
|
|
68
|
+
);
|
|
69
|
+
});
|
|
70
|
+
const changeSets = [...allReviewableChanges]
|
|
71
|
+
.sort(
|
|
72
|
+
(left, right) =>
|
|
73
|
+
reviewPreparePriority(left) - reviewPreparePriority(right),
|
|
74
|
+
)
|
|
75
|
+
.slice(0, BUILDER_SOURCE_REVIEW_PREPARE_LIMIT);
|
|
76
|
+
const authoritativeSource = await withAuthoritativeBuilderTargetRows({
|
|
77
|
+
source,
|
|
78
|
+
changeSets,
|
|
79
|
+
});
|
|
80
|
+
const review =
|
|
81
|
+
changeSets.length > 0
|
|
82
|
+
? buildBuilderSourceReviewPayload({
|
|
83
|
+
source: authoritativeSource,
|
|
84
|
+
changeSets,
|
|
85
|
+
})
|
|
86
|
+
: null;
|
|
87
|
+
if (review) {
|
|
88
|
+
review.totalRowCount = allReviewableChanges.length;
|
|
89
|
+
review.preparedRowLimit = changeSets.length;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return {
|
|
93
|
+
sourceId: source.id,
|
|
94
|
+
sourceTable: source.sourceTable,
|
|
95
|
+
changeSetIds: changeSets.map((changeSet) => changeSet.id),
|
|
96
|
+
review,
|
|
97
|
+
};
|
|
98
|
+
},
|
|
99
|
+
});
|
|
@@ -73,6 +73,7 @@ export default defineAction({
|
|
|
73
73
|
return {
|
|
74
74
|
id: doc.id,
|
|
75
75
|
title: doc.title,
|
|
76
|
+
description: doc.description ?? "",
|
|
76
77
|
content: formatDocumentContent(doc.content ?? "", format),
|
|
77
78
|
format,
|
|
78
79
|
deepLink: buildDeepLink({
|
|
@@ -104,6 +105,7 @@ export default defineAction({
|
|
|
104
105
|
return {
|
|
105
106
|
id: doc.id,
|
|
106
107
|
title: doc.title,
|
|
108
|
+
description: (doc.description as string | null | undefined) ?? "",
|
|
107
109
|
content,
|
|
108
110
|
format,
|
|
109
111
|
deepLink: buildDeepLink({
|
|
@@ -59,6 +59,7 @@ export default defineAction({
|
|
|
59
59
|
(doc) =>
|
|
60
60
|
!normalizedQuery ||
|
|
61
61
|
doc.title.toLowerCase().includes(normalizedQuery) ||
|
|
62
|
+
(doc.description ?? "").toLowerCase().includes(normalizedQuery) ||
|
|
62
63
|
doc.content.toLowerCase().includes(normalizedQuery),
|
|
63
64
|
)
|
|
64
65
|
.sort((a, b) => b.updatedAt.localeCompare(a.updatedAt))
|
|
@@ -69,6 +70,7 @@ export default defineAction({
|
|
|
69
70
|
id: doc.id,
|
|
70
71
|
parentId: doc.parentId,
|
|
71
72
|
title: doc.title,
|
|
73
|
+
description: doc.description,
|
|
72
74
|
icon: doc.icon,
|
|
73
75
|
snippet: makeSnippet(doc.content, query),
|
|
74
76
|
contentLength: doc.content.length,
|
|
@@ -95,6 +97,7 @@ export default defineAction({
|
|
|
95
97
|
id: schema.documents.id,
|
|
96
98
|
parentId: schema.documents.parentId,
|
|
97
99
|
title: schema.documents.title,
|
|
100
|
+
description: schema.documents.description,
|
|
98
101
|
icon: schema.documents.icon,
|
|
99
102
|
contentPreview: sql<string>`substr(${schema.documents.content}, 1, 5000)`,
|
|
100
103
|
contentLength: sql<number>`length(${schema.documents.content})`,
|
|
@@ -106,7 +109,7 @@ export default defineAction({
|
|
|
106
109
|
and(
|
|
107
110
|
accessFilter(schema.documents, schema.documentShares),
|
|
108
111
|
documentDiscoveryFilter(),
|
|
109
|
-
sql`(${schema.documents.title} LIKE ${pattern} ESCAPE '\\' OR ${schema.documents.content} LIKE ${pattern} ESCAPE '\\')`,
|
|
112
|
+
sql`(${schema.documents.title} LIKE ${pattern} ESCAPE '\\' OR ${schema.documents.description} LIKE ${pattern} ESCAPE '\\' OR ${schema.documents.content} LIKE ${pattern} ESCAPE '\\')`,
|
|
110
113
|
),
|
|
111
114
|
)
|
|
112
115
|
.orderBy(sql`${schema.documents.updatedAt} DESC`)
|
|
@@ -117,6 +120,7 @@ export default defineAction({
|
|
|
117
120
|
id: doc.id,
|
|
118
121
|
parentId: doc.parentId,
|
|
119
122
|
title: doc.title,
|
|
123
|
+
description: doc.description,
|
|
120
124
|
icon: doc.icon,
|
|
121
125
|
snippet: makeSnippet(doc.contentPreview, query),
|
|
122
126
|
contentLength: Number(doc.contentLength) || 0,
|
|
@@ -38,7 +38,7 @@ function executableWriteModes(
|
|
|
38
38
|
|
|
39
39
|
export default defineAction({
|
|
40
40
|
description:
|
|
41
|
-
"Set the tiered Builder CMS write mode for one source. Writes stay off by default and
|
|
41
|
+
"Set the tiered Builder CMS write mode for one source. Writes stay off by default and require document administrator access to enable or change.",
|
|
42
42
|
schema: z.object({
|
|
43
43
|
databaseId: z.string().optional().describe("Database ID"),
|
|
44
44
|
documentId: z.string().optional().describe("Database document/page ID"),
|
|
@@ -79,7 +79,7 @@ export default defineAction({
|
|
|
79
79
|
): Promise<ContentDatabaseResponse> => {
|
|
80
80
|
const database = await resolveDatabaseForSourceMutation(args);
|
|
81
81
|
if (!database) throw new Error("Database not found.");
|
|
82
|
-
await assertAccess("document", database.documentId, "
|
|
82
|
+
await assertAccess("document", database.documentId, "admin");
|
|
83
83
|
|
|
84
84
|
const db = getDb();
|
|
85
85
|
const source = await getExistingSourceForWrite(database.id, args.sourceId);
|
|
@@ -152,6 +152,10 @@ export default defineAction({
|
|
|
152
152
|
id: z.string().optional().describe("Document ID (required)"),
|
|
153
153
|
title: z.string().optional().describe("New title"),
|
|
154
154
|
content: z.string().optional().describe("New markdown content"),
|
|
155
|
+
description: z
|
|
156
|
+
.string()
|
|
157
|
+
.optional()
|
|
158
|
+
.describe("Stable page guidance; this does not alter page content"),
|
|
155
159
|
icon: z.string().nullable().optional().describe("New emoji icon"),
|
|
156
160
|
isFavorite: z.coerce
|
|
157
161
|
.boolean()
|
|
@@ -285,8 +289,15 @@ export default defineAction({
|
|
|
285
289
|
const favoriteChanged =
|
|
286
290
|
args.isFavorite !== undefined &&
|
|
287
291
|
(args.isFavorite ? 1 : 0) !== (existing.isFavorite ?? 0);
|
|
292
|
+
const descriptionChanged =
|
|
293
|
+
args.description !== undefined &&
|
|
294
|
+
args.description.trim() !== existing.description;
|
|
288
295
|
const anyChange =
|
|
289
|
-
titleChanged ||
|
|
296
|
+
titleChanged ||
|
|
297
|
+
contentChanged ||
|
|
298
|
+
iconChanged ||
|
|
299
|
+
favoriteChanged ||
|
|
300
|
+
descriptionChanged;
|
|
290
301
|
|
|
291
302
|
// Snapshot the current state before applying content/title changes.
|
|
292
303
|
// Versions are scoped to the document owner, not the caller — an editor
|
|
@@ -338,6 +349,8 @@ export default defineAction({
|
|
|
338
349
|
};
|
|
339
350
|
|
|
340
351
|
if (titleChanged) updates.title = args.title;
|
|
352
|
+
if (args.description !== undefined)
|
|
353
|
+
updates.description = args.description.trim();
|
|
341
354
|
if (contentChanged) updates.content = content;
|
|
342
355
|
if (iconChanged) updates.icon = args.icon;
|
|
343
356
|
if (favoriteChanged) updates.isFavorite = args.isFavorite ? 1 : 0;
|
|
@@ -373,6 +386,7 @@ export default defineAction({
|
|
|
373
386
|
parentId: current.parentId,
|
|
374
387
|
title: current.title,
|
|
375
388
|
content: current.content,
|
|
389
|
+
description: current.description,
|
|
376
390
|
icon: current.icon,
|
|
377
391
|
position: current.position,
|
|
378
392
|
isFavorite: parseDocumentFavorite(current.isFavorite),
|
|
@@ -449,6 +463,7 @@ export default defineAction({
|
|
|
449
463
|
parentId: doc.parentId,
|
|
450
464
|
title: doc.title,
|
|
451
465
|
content: doc.content,
|
|
466
|
+
description: doc.description,
|
|
452
467
|
icon: doc.icon,
|
|
453
468
|
position: doc.position,
|
|
454
469
|
isFavorite: parseDocumentFavorite(doc.isFavorite),
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import { defineAction } from "@agent-native/core";
|
|
2
|
+
import {
|
|
3
|
+
getRequestOrgId,
|
|
4
|
+
getRequestUserEmail,
|
|
5
|
+
} from "@agent-native/core/server";
|
|
6
|
+
import { assertAccess } from "@agent-native/core/sharing";
|
|
7
|
+
import { and, eq, sql } from "drizzle-orm";
|
|
8
|
+
import { z } from "zod";
|
|
9
|
+
|
|
10
|
+
import { getDb, schema } from "../server/db/index.js";
|
|
11
|
+
import { readPreviewDocumentDraft } from "./_preview-document-draft.js";
|
|
12
|
+
|
|
13
|
+
const draftPayload = z.object({
|
|
14
|
+
title: z.string().max(10_000),
|
|
15
|
+
content: z.string().max(500_000),
|
|
16
|
+
baseDocumentUpdatedAt: z.string().max(100).nullable(),
|
|
17
|
+
loadedContentWasEmpty: z.boolean(),
|
|
18
|
+
deferredReason: z.enum(["hydration", "conflict"]).nullable(),
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
function draftId() {
|
|
22
|
+
return crypto.randomUUID();
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export default defineAction({
|
|
26
|
+
description:
|
|
27
|
+
"Atomically save or delete the current user's private preview draft.",
|
|
28
|
+
schema: z.discriminatedUnion("operation", [
|
|
29
|
+
z.object({
|
|
30
|
+
operation: z.literal("upsert"),
|
|
31
|
+
documentId: z.string().min(1),
|
|
32
|
+
expectedVersion: z.number().int().positive().nullable(),
|
|
33
|
+
draft: draftPayload,
|
|
34
|
+
}),
|
|
35
|
+
z.object({
|
|
36
|
+
operation: z.literal("delete"),
|
|
37
|
+
documentId: z.string().min(1),
|
|
38
|
+
expectedVersion: z.number().int().positive(),
|
|
39
|
+
expectedTitle: z.string().max(10_000),
|
|
40
|
+
expectedContent: z.string().max(500_000),
|
|
41
|
+
}),
|
|
42
|
+
]),
|
|
43
|
+
agentTool: false,
|
|
44
|
+
toolCallable: false,
|
|
45
|
+
run: async (args, ctx) => {
|
|
46
|
+
const userEmail = getRequestUserEmail();
|
|
47
|
+
const orgId = getRequestOrgId() ?? "";
|
|
48
|
+
if (!userEmail) throw new Error("Not authenticated.");
|
|
49
|
+
await assertAccess("document", args.documentId, "editor");
|
|
50
|
+
const db = getDb();
|
|
51
|
+
const ownerFilter = and(
|
|
52
|
+
eq(schema.documentPreviewDrafts.ownerEmail, userEmail),
|
|
53
|
+
eq(schema.documentPreviewDrafts.orgId, orgId),
|
|
54
|
+
eq(schema.documentPreviewDrafts.documentId, args.documentId),
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
if (args.operation === "delete") {
|
|
58
|
+
const deleted = await db
|
|
59
|
+
.delete(schema.documentPreviewDrafts)
|
|
60
|
+
.where(
|
|
61
|
+
and(
|
|
62
|
+
ownerFilter,
|
|
63
|
+
eq(schema.documentPreviewDrafts.version, args.expectedVersion),
|
|
64
|
+
eq(schema.documentPreviewDrafts.title, args.expectedTitle),
|
|
65
|
+
eq(schema.documentPreviewDrafts.content, args.expectedContent),
|
|
66
|
+
),
|
|
67
|
+
)
|
|
68
|
+
.returning({ id: schema.documentPreviewDrafts.id });
|
|
69
|
+
if (deleted.length > 0)
|
|
70
|
+
return { status: "deleted" as const, draft: null };
|
|
71
|
+
return {
|
|
72
|
+
status: "conflict" as const,
|
|
73
|
+
draft: await readPreviewDocumentDraft(
|
|
74
|
+
userEmail,
|
|
75
|
+
orgId,
|
|
76
|
+
args.documentId,
|
|
77
|
+
),
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const now = new Date().toISOString();
|
|
82
|
+
if (args.expectedVersion === null) {
|
|
83
|
+
const inserted = await db
|
|
84
|
+
.insert(schema.documentPreviewDrafts)
|
|
85
|
+
.values({
|
|
86
|
+
id: draftId(),
|
|
87
|
+
ownerEmail: userEmail,
|
|
88
|
+
orgId,
|
|
89
|
+
documentId: args.documentId,
|
|
90
|
+
title: args.draft.title,
|
|
91
|
+
content: args.draft.content,
|
|
92
|
+
baseDocumentUpdatedAt: args.draft.baseDocumentUpdatedAt,
|
|
93
|
+
loadedContentWasEmpty: args.draft.loadedContentWasEmpty ? 1 : 0,
|
|
94
|
+
deferredReason: args.draft.deferredReason,
|
|
95
|
+
version: 1,
|
|
96
|
+
createdAt: now,
|
|
97
|
+
updatedAt: now,
|
|
98
|
+
})
|
|
99
|
+
.onConflictDoNothing({
|
|
100
|
+
target: [
|
|
101
|
+
schema.documentPreviewDrafts.ownerEmail,
|
|
102
|
+
schema.documentPreviewDrafts.orgId,
|
|
103
|
+
schema.documentPreviewDrafts.documentId,
|
|
104
|
+
],
|
|
105
|
+
})
|
|
106
|
+
.returning({ version: schema.documentPreviewDrafts.version });
|
|
107
|
+
if (inserted.length > 0) {
|
|
108
|
+
return {
|
|
109
|
+
status: "saved" as const,
|
|
110
|
+
draft: await readPreviewDocumentDraft(
|
|
111
|
+
userEmail,
|
|
112
|
+
orgId,
|
|
113
|
+
args.documentId,
|
|
114
|
+
),
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
} else {
|
|
118
|
+
const updated = await db
|
|
119
|
+
.update(schema.documentPreviewDrafts)
|
|
120
|
+
.set({
|
|
121
|
+
title: args.draft.title,
|
|
122
|
+
content: args.draft.content,
|
|
123
|
+
baseDocumentUpdatedAt: args.draft.baseDocumentUpdatedAt,
|
|
124
|
+
loadedContentWasEmpty: args.draft.loadedContentWasEmpty ? 1 : 0,
|
|
125
|
+
deferredReason: args.draft.deferredReason,
|
|
126
|
+
version: sql`${schema.documentPreviewDrafts.version} + 1`,
|
|
127
|
+
updatedAt: now,
|
|
128
|
+
})
|
|
129
|
+
.where(
|
|
130
|
+
and(
|
|
131
|
+
ownerFilter,
|
|
132
|
+
eq(schema.documentPreviewDrafts.version, args.expectedVersion),
|
|
133
|
+
),
|
|
134
|
+
)
|
|
135
|
+
.returning({ version: schema.documentPreviewDrafts.version });
|
|
136
|
+
if (updated.length > 0) {
|
|
137
|
+
return {
|
|
138
|
+
status: "saved" as const,
|
|
139
|
+
draft: await readPreviewDocumentDraft(
|
|
140
|
+
userEmail,
|
|
141
|
+
orgId,
|
|
142
|
+
args.documentId,
|
|
143
|
+
),
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
return {
|
|
149
|
+
status: "conflict" as const,
|
|
150
|
+
draft: await readPreviewDocumentDraft(userEmail, orgId, args.documentId),
|
|
151
|
+
};
|
|
152
|
+
},
|
|
153
|
+
});
|
|
@@ -34,11 +34,13 @@ import {
|
|
|
34
34
|
getContentDatabaseResponse,
|
|
35
35
|
getDatabaseByDocumentId,
|
|
36
36
|
getDatabaseItemByDocumentId,
|
|
37
|
+
getDocumentContextPath,
|
|
37
38
|
serializeDatabaseMembership,
|
|
38
39
|
} from "./_database-utils.js";
|
|
39
40
|
import { serializeDocumentSource } from "./_document-source.js";
|
|
40
41
|
import {
|
|
41
42
|
getLocalFileDocument,
|
|
43
|
+
getLocalDocumentContextPath,
|
|
42
44
|
isContentLocalFileMode,
|
|
43
45
|
isLocalDocumentId,
|
|
44
46
|
localContentViewScreenSummary,
|
|
@@ -675,7 +677,10 @@ export default defineAction({
|
|
|
675
677
|
],
|
|
676
678
|
};
|
|
677
679
|
if (nav?.documentId && isLocalDocumentId(nav.documentId)) {
|
|
678
|
-
screen.document =
|
|
680
|
+
screen.document = {
|
|
681
|
+
...(await getLocalFileDocument(nav.documentId)),
|
|
682
|
+
contextPath: await getLocalDocumentContextPath(nav.documentId),
|
|
683
|
+
};
|
|
679
684
|
} else if (nav?.documentId) {
|
|
680
685
|
const access = await resolveAccess("document", nav.documentId);
|
|
681
686
|
if (access) {
|
|
@@ -685,6 +690,7 @@ export default defineAction({
|
|
|
685
690
|
parentId: doc.parentId,
|
|
686
691
|
title: doc.title,
|
|
687
692
|
content: doc.content,
|
|
693
|
+
description: doc.description,
|
|
688
694
|
icon: doc.icon,
|
|
689
695
|
position: doc.position,
|
|
690
696
|
isFavorite: parseDocumentFavorite(doc.isFavorite),
|
|
@@ -693,6 +699,7 @@ export default defineAction({
|
|
|
693
699
|
source: serializeDocumentSource(doc),
|
|
694
700
|
createdAt: doc.createdAt,
|
|
695
701
|
updatedAt: doc.updatedAt,
|
|
702
|
+
contextPath: await getDocumentContextPath(doc),
|
|
696
703
|
};
|
|
697
704
|
}
|
|
698
705
|
}
|
|
@@ -725,18 +732,22 @@ export default defineAction({
|
|
|
725
732
|
parentId: doc.parentId,
|
|
726
733
|
title: doc.title,
|
|
727
734
|
content: doc.content,
|
|
735
|
+
description: doc.description,
|
|
728
736
|
icon: doc.icon,
|
|
729
737
|
position: doc.position,
|
|
730
738
|
isFavorite: parseDocumentFavorite(doc.isFavorite),
|
|
731
739
|
hideFromSearch: parseDocumentHideFromSearch(doc.hideFromSearch),
|
|
732
740
|
visibility: doc.visibility,
|
|
733
|
-
database: database
|
|
741
|
+
database: database
|
|
742
|
+
? serializeDatabase(database, doc.description)
|
|
743
|
+
: undefined,
|
|
734
744
|
databaseMembership: databaseMembership
|
|
735
745
|
? serializeDatabaseMembership(databaseMembership)
|
|
736
746
|
: undefined,
|
|
737
747
|
properties: await listPropertiesForDocument(doc),
|
|
738
748
|
createdAt: doc.createdAt,
|
|
739
749
|
updatedAt: doc.updatedAt,
|
|
750
|
+
contextPath: await getDocumentContextPath(doc),
|
|
740
751
|
};
|
|
741
752
|
if (database) {
|
|
742
753
|
const databaseResponse = await getContentDatabaseResponse(
|
|
@@ -774,6 +785,7 @@ export default defineAction({
|
|
|
774
785
|
parentId: previewDoc.parentId,
|
|
775
786
|
title: previewDoc.title,
|
|
776
787
|
content: previewDoc.content,
|
|
788
|
+
description: previewDoc.description,
|
|
777
789
|
icon: previewDoc.icon,
|
|
778
790
|
position: previewDoc.position,
|
|
779
791
|
isFavorite: parseDocumentFavorite(previewDoc.isFavorite),
|
|
@@ -786,6 +798,7 @@ export default defineAction({
|
|
|
786
798
|
properties: await listPropertiesForDocument(previewDoc),
|
|
787
799
|
createdAt: previewDoc.createdAt,
|
|
788
800
|
updatedAt: previewDoc.updatedAt,
|
|
801
|
+
contextPath: await getDocumentContextPath(previewDoc),
|
|
789
802
|
},
|
|
790
803
|
};
|
|
791
804
|
}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { useEffect, useRef, useState } from "react";
|
|
2
|
+
|
|
3
|
+
import { Textarea } from "@/components/ui/textarea";
|
|
4
|
+
import { cn } from "@/lib/utils";
|
|
5
|
+
|
|
6
|
+
export function descriptionFieldSavedValue(
|
|
7
|
+
draft: string,
|
|
8
|
+
savedDescription: string | null | undefined,
|
|
9
|
+
) {
|
|
10
|
+
const next = draft.trim();
|
|
11
|
+
return next === (savedDescription ?? "") ? null : next;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function descriptionFieldEscapeDraft(
|
|
15
|
+
savedDescription: string | null | undefined,
|
|
16
|
+
) {
|
|
17
|
+
return savedDescription ?? "";
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Quiet, stable guidance attached to a page or database. This intentionally
|
|
22
|
+
* renders the owned description only; ancestor context is assembled for agent
|
|
23
|
+
* reads rather than copied into the surface.
|
|
24
|
+
*/
|
|
25
|
+
export function DescriptionField({
|
|
26
|
+
description,
|
|
27
|
+
canEdit,
|
|
28
|
+
label = "Description",
|
|
29
|
+
placeholder = "Add a description…",
|
|
30
|
+
className,
|
|
31
|
+
onSave,
|
|
32
|
+
}: {
|
|
33
|
+
description: string | null | undefined;
|
|
34
|
+
canEdit: boolean;
|
|
35
|
+
label?: string;
|
|
36
|
+
placeholder?: string;
|
|
37
|
+
className?: string;
|
|
38
|
+
onSave: (description: string) => Promise<unknown> | unknown;
|
|
39
|
+
}) {
|
|
40
|
+
const [draft, setDraft] = useState(description ?? "");
|
|
41
|
+
const [editing, setEditing] = useState(false);
|
|
42
|
+
const skipNextBlurSaveRef = useRef(false);
|
|
43
|
+
const saveQueueRef = useRef<Promise<void>>(Promise.resolve());
|
|
44
|
+
const saveRevisionRef = useRef(0);
|
|
45
|
+
const confirmedDescriptionRef = useRef(description ?? "");
|
|
46
|
+
|
|
47
|
+
useEffect(() => {
|
|
48
|
+
confirmedDescriptionRef.current = description ?? "";
|
|
49
|
+
}, [description]);
|
|
50
|
+
|
|
51
|
+
useEffect(() => {
|
|
52
|
+
if (!editing) setDraft(description ?? "");
|
|
53
|
+
}, [description, editing]);
|
|
54
|
+
|
|
55
|
+
const save = async () => {
|
|
56
|
+
const next = descriptionFieldSavedValue(draft, description);
|
|
57
|
+
if (next === null) return;
|
|
58
|
+
|
|
59
|
+
const revision = ++saveRevisionRef.current;
|
|
60
|
+
const request = saveQueueRef.current.then(() => onSave(next));
|
|
61
|
+
saveQueueRef.current = request.then(
|
|
62
|
+
() => undefined,
|
|
63
|
+
() => undefined,
|
|
64
|
+
);
|
|
65
|
+
|
|
66
|
+
try {
|
|
67
|
+
await request;
|
|
68
|
+
confirmedDescriptionRef.current = next;
|
|
69
|
+
} catch {
|
|
70
|
+
if (saveRevisionRef.current === revision) {
|
|
71
|
+
setDraft(confirmedDescriptionRef.current);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
if (!canEdit && !description) return null;
|
|
77
|
+
|
|
78
|
+
if (!canEdit) {
|
|
79
|
+
return (
|
|
80
|
+
<p
|
|
81
|
+
className={cn(
|
|
82
|
+
"mt-2 text-sm leading-6 text-muted-foreground",
|
|
83
|
+
className,
|
|
84
|
+
)}
|
|
85
|
+
>
|
|
86
|
+
{description}
|
|
87
|
+
</p>
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return (
|
|
92
|
+
<Textarea
|
|
93
|
+
aria-label={label}
|
|
94
|
+
rows={editing || draft ? 2 : 1}
|
|
95
|
+
value={draft}
|
|
96
|
+
placeholder={placeholder}
|
|
97
|
+
onFocus={() => setEditing(true)}
|
|
98
|
+
onChange={(event) => setDraft(event.target.value)}
|
|
99
|
+
onBlur={() => {
|
|
100
|
+
setEditing(false);
|
|
101
|
+
if (skipNextBlurSaveRef.current) {
|
|
102
|
+
skipNextBlurSaveRef.current = false;
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
void save();
|
|
106
|
+
}}
|
|
107
|
+
onKeyDown={(event) => {
|
|
108
|
+
if (event.key === "Escape") {
|
|
109
|
+
event.preventDefault();
|
|
110
|
+
skipNextBlurSaveRef.current = true;
|
|
111
|
+
setDraft(descriptionFieldEscapeDraft(description));
|
|
112
|
+
event.currentTarget.blur();
|
|
113
|
+
}
|
|
114
|
+
}}
|
|
115
|
+
className={cn(
|
|
116
|
+
"mt-2 block w-full resize-none overflow-hidden rounded border-0 bg-transparent px-0 py-0 text-sm leading-6 text-muted-foreground outline-none placeholder:text-muted-foreground/45 hover:bg-muted/30 focus:bg-muted/30 focus:px-1 focus:outline-none focus:ring-1 focus:ring-ring",
|
|
117
|
+
className,
|
|
118
|
+
)}
|
|
119
|
+
/>
|
|
120
|
+
);
|
|
121
|
+
}
|
|
@@ -61,6 +61,7 @@ import {
|
|
|
61
61
|
import { BuilderBodySyncingNotice } from "./BuilderBodySyncingNotice";
|
|
62
62
|
import type { CommentTextAnchor } from "./comment-anchors";
|
|
63
63
|
import { CommentsSidebar } from "./CommentsSidebar";
|
|
64
|
+
import { DescriptionField } from "./DescriptionField";
|
|
64
65
|
import { DocumentBlockFields } from "./DocumentBlockFields";
|
|
65
66
|
import { DocumentDatabase } from "./DocumentDatabase";
|
|
66
67
|
import { DocumentEditorSkeleton } from "./DocumentEditorSkeleton";
|
|
@@ -629,6 +630,7 @@ function DocumentEditorBody({ documentId, document }: DocumentEditorBodyProps) {
|
|
|
629
630
|
updates: {
|
|
630
631
|
title?: string;
|
|
631
632
|
content?: string;
|
|
633
|
+
description?: string;
|
|
632
634
|
icon?: string | null;
|
|
633
635
|
},
|
|
634
636
|
options: DocumentSaveOptions = {},
|
|
@@ -645,6 +647,7 @@ function DocumentEditorBody({ documentId, document }: DocumentEditorBodyProps) {
|
|
|
645
647
|
...document,
|
|
646
648
|
title: updates.title ?? localTitleRef.current,
|
|
647
649
|
content: updates.content ?? localContentRef.current,
|
|
650
|
+
description: updates.description ?? document.description,
|
|
648
651
|
icon: updates.icon !== undefined ? updates.icon : document.icon,
|
|
649
652
|
updatedAt: nextSavedAt,
|
|
650
653
|
source: localSource,
|
|
@@ -1431,6 +1434,17 @@ function DocumentEditorBody({ documentId, document }: DocumentEditorBodyProps) {
|
|
|
1431
1434
|
isDatabasePage ? "text-3xl" : "text-3xl md:text-4xl",
|
|
1432
1435
|
)}
|
|
1433
1436
|
/>
|
|
1437
|
+
{!document.database ? (
|
|
1438
|
+
<DescriptionField
|
|
1439
|
+
description={document.description}
|
|
1440
|
+
canEdit={editorCanEdit}
|
|
1441
|
+
label={t("editor.properties.description")}
|
|
1442
|
+
placeholder={t("editor.properties.addPageDescription")}
|
|
1443
|
+
onSave={(description) =>
|
|
1444
|
+
persistDocumentUpdates({ description })
|
|
1445
|
+
}
|
|
1446
|
+
/>
|
|
1447
|
+
) : null}
|
|
1434
1448
|
{document.databaseMembership && !isLocalFileDocument ? (
|
|
1435
1449
|
<DocumentProperties
|
|
1436
1450
|
documentId={documentId}
|