@agent-native/core 0.102.2 → 0.103.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/corpus/README.md +1 -1
- package/corpus/core/CHANGELOG.md +6 -0
- package/corpus/core/docs/content/local-file-mode.mdx +99 -489
- package/corpus/core/docs/content/locales/ar-SA/local-file-mode.mdx +35 -490
- package/corpus/core/docs/content/locales/ar-SA/template-content.mdx +10 -24
- package/corpus/core/docs/content/locales/de-DE/local-file-mode.mdx +37 -491
- package/corpus/core/docs/content/locales/de-DE/template-content.mdx +10 -24
- package/corpus/core/docs/content/locales/es-ES/local-file-mode.mdx +35 -493
- package/corpus/core/docs/content/locales/es-ES/template-content.mdx +10 -24
- package/corpus/core/docs/content/locales/fr-FR/local-file-mode.mdx +38 -491
- package/corpus/core/docs/content/locales/fr-FR/template-content.mdx +10 -24
- package/corpus/core/docs/content/locales/hi-IN/local-file-mode.mdx +33 -492
- package/corpus/core/docs/content/locales/hi-IN/template-content.mdx +10 -24
- package/corpus/core/docs/content/locales/ja-JP/local-file-mode.mdx +36 -492
- package/corpus/core/docs/content/locales/ja-JP/template-content.mdx +10 -24
- package/corpus/core/docs/content/locales/ko-KR/local-file-mode.mdx +35 -490
- package/corpus/core/docs/content/locales/ko-KR/template-content.mdx +10 -24
- package/corpus/core/docs/content/locales/pt-BR/local-file-mode.mdx +35 -493
- package/corpus/core/docs/content/locales/pt-BR/template-content.mdx +10 -24
- package/corpus/core/docs/content/locales/zh-CN/local-file-mode.mdx +31 -489
- package/corpus/core/docs/content/locales/zh-CN/template-content.mdx +9 -24
- package/corpus/core/docs/content/locales/zh-TW/local-file-mode.mdx +31 -489
- package/corpus/core/docs/content/locales/zh-TW/template-content.mdx +9 -24
- package/corpus/core/docs/content/template-content.mdx +26 -42
- package/corpus/core/package.json +1 -1
- package/corpus/core/src/cli/content-local.ts +86 -18
- package/corpus/core/src/cli/index.ts +2 -2
- package/corpus/core/src/cli/skills-content/content-skill.ts +36 -25
- package/corpus/core/src/cli/skills.ts +47 -13
- package/corpus/core/src/local-artifacts/index.ts +65 -0
- package/corpus/templates/assets/app/components/library/GenerationPresetsPanel.tsx +325 -0
- package/corpus/templates/assets/app/hooks/use-navigation-state.ts +12 -0
- package/corpus/templates/assets/app/i18n/zh-TW.ts +21 -0
- package/corpus/templates/assets/app/i18n-data.ts +215 -0
- package/corpus/templates/assets/app/routes/brand-kits.$id.tsx +19 -479
- package/corpus/templates/assets/app/routes/brand-kits.$id_.presets.$presetId.tsx +1 -1
- package/corpus/templates/assets/app/routes/brand-kits.$id_.settings.tsx +446 -0
- package/corpus/templates/clips/app/components/editor/editor-layout.tsx +12 -2
- package/corpus/templates/clips/app/components/player/settings-panel.tsx +30 -12
- package/corpus/templates/clips/app/components/player/video-player.tsx +5 -1
- package/corpus/templates/clips/app/components/recorder/microphone-visualizer.tsx +22 -3
- package/corpus/templates/clips/app/i18n/ar-SA.ts +3 -2
- package/corpus/templates/clips/app/i18n/de-DE.ts +4 -2
- package/corpus/templates/clips/app/i18n/en-US.ts +3 -2
- package/corpus/templates/clips/app/i18n/es-ES.ts +4 -2
- package/corpus/templates/clips/app/i18n/fr-FR.ts +3 -2
- package/corpus/templates/clips/app/i18n/hi-IN.ts +3 -2
- package/corpus/templates/clips/app/i18n/ja-JP.ts +4 -1
- package/corpus/templates/clips/app/i18n/ko-KR.ts +3 -2
- package/corpus/templates/clips/app/i18n/pt-BR.ts +4 -2
- package/corpus/templates/clips/app/i18n/zh-CN.ts +3 -2
- package/corpus/templates/clips/app/i18n/zh-TW.ts +3 -2
- package/corpus/templates/clips/app/routes/r.$recordingId.tsx +27 -1
- package/corpus/templates/clips/server/lib/share-password.ts +6 -3
- package/corpus/templates/content/.agents/skills/content/SKILL.md +26 -39
- package/corpus/templates/content/AGENTS.md +25 -30
- package/corpus/templates/content/actions/_builder-docs-client.ts +23 -0
- package/corpus/templates/content/actions/_content-database-source-adapters.ts +21 -3
- package/corpus/templates/content/actions/_content-files.ts +338 -0
- package/corpus/templates/content/actions/_content-space-access.ts +135 -0
- package/corpus/templates/content/actions/_content-spaces.ts +640 -0
- package/corpus/templates/content/actions/_database-source-utils.ts +90 -7
- package/corpus/templates/content/actions/_database-utils.ts +7 -1
- package/corpus/templates/content/actions/_local-file-documents.ts +0 -9
- package/corpus/templates/content/actions/_local-folder-source.ts +53 -0
- package/corpus/templates/content/actions/_property-utils.ts +9 -4
- package/corpus/templates/content/actions/add-database-item.ts +108 -65
- package/corpus/templates/content/actions/backfill-content-files.ts +22 -0
- package/corpus/templates/content/actions/connect-local-folder-source.ts +221 -0
- package/corpus/templates/content/actions/create-content-database.ts +129 -3
- package/corpus/templates/content/actions/create-document.ts +65 -55
- package/corpus/templates/content/actions/create-inline-content-database.ts +6 -1
- package/corpus/templates/content/actions/delete-content-database.ts +3 -0
- package/corpus/templates/content/actions/delete-document.ts +7 -11
- package/corpus/templates/content/actions/disconnect-local-folder-source.ts +175 -0
- package/corpus/templates/content/actions/duplicate-database-item.ts +10 -0
- package/corpus/templates/content/actions/duplicate-database-items.ts +13 -0
- package/corpus/templates/content/actions/edit-document.ts +2 -28
- package/corpus/templates/content/actions/ensure-content-spaces.ts +26 -0
- package/corpus/templates/content/actions/export-content-source.ts +47 -9
- package/corpus/templates/content/actions/get-document.ts +0 -14
- package/corpus/templates/content/actions/import-content-source.ts +43 -3
- package/corpus/templates/content/actions/list-content-spaces.ts +103 -0
- package/corpus/templates/content/actions/list-documents.ts +12 -9
- package/corpus/templates/content/actions/move-document.ts +3 -14
- package/corpus/templates/content/actions/pull-document.ts +0 -23
- package/corpus/templates/content/actions/remove-local-file-source.ts +50 -29
- package/corpus/templates/content/actions/resolve-local-folder-conflict.ts +442 -0
- package/corpus/templates/content/actions/reveal-local-source-file.ts +6 -17
- package/corpus/templates/content/actions/search-documents.ts +0 -34
- package/corpus/templates/content/actions/share-local-file-document.ts +25 -1
- package/corpus/templates/content/actions/submit-content-database-form.ts +12 -0
- package/corpus/templates/content/actions/sync-local-folder-source.ts +731 -0
- package/corpus/templates/content/actions/sync-manifest-local-folder-source.ts +123 -0
- package/corpus/templates/content/actions/update-content-database-view.ts +10 -1
- package/corpus/templates/content/actions/update-document.ts +0 -15
- package/corpus/templates/content/actions/view-screen.ts +2 -50
- package/corpus/templates/content/app/components/editor/SlashCommandMenu.tsx +76 -62
- package/corpus/templates/content/app/components/editor/database/DatabaseView.tsx +70 -22
- package/corpus/templates/content/app/components/editor/database/grouping.ts +2 -1
- package/corpus/templates/content/app/components/editor/database/settings.tsx +23 -20
- package/corpus/templates/content/app/components/editor/database/shared.tsx +2 -0
- package/corpus/templates/content/app/components/editor/database/sidebar.tsx +330 -0
- package/corpus/templates/content/app/components/editor/database/types.ts +1 -0
- package/corpus/templates/content/app/components/editor/database/view-config.ts +3 -1
- package/corpus/templates/content/app/components/layout/Layout.tsx +25 -1
- package/corpus/templates/content/app/components/sidebar/DocumentSidebar.tsx +209 -113
- package/corpus/templates/content/app/components/sidebar/select-content-space.ts +31 -0
- package/corpus/templates/content/app/hooks/use-content-database.ts +16 -0
- package/corpus/templates/content/app/hooks/use-content-spaces.ts +39 -0
- package/corpus/templates/content/app/i18n/zh-TW.ts +11 -0
- package/corpus/templates/content/app/i18n-data.ts +75 -0
- package/corpus/templates/content/app/routes/_app.local-files.tsx +174 -65
- package/corpus/templates/content/changelog/2026-07-16-content-callouts-can-now-be-reviewed-and-published-to-builder.md +6 -0
- package/corpus/templates/content/changelog/2026-07-16-heading-5-and-heading-6-are-available-from-the-editor-slash-.md +6 -0
- package/corpus/templates/content/changelog/2026-07-16-organize-every-workspace-through-a-customizable-files-databa.md +6 -0
- package/corpus/templates/content/parity/matrix.md +2 -1
- package/corpus/templates/content/parity/matrix.ts +37 -1
- package/corpus/templates/content/scripts/dev-database.mjs +7 -5
- package/corpus/templates/content/server/db/schema.ts +113 -40
- package/corpus/templates/content/server/lib/document-context.ts +15 -1
- package/corpus/templates/content/server/lib/notion-sync.ts +6 -0
- package/corpus/templates/content/server/plugins/db.ts +153 -0
- package/corpus/templates/content/shared/api.ts +17 -3
- package/corpus/templates/content/shared/builder-mdx.ts +163 -16
- package/corpus/templates/design/.agents/skills/design-templates/SKILL.md +59 -0
- package/corpus/templates/design/AGENTS.md +6 -1
- package/corpus/templates/design/actions/create-design-from-template.ts +19 -7
- package/corpus/templates/design/actions/list-design-templates.ts +69 -21
- package/corpus/templates/design/actions/navigate.ts +2 -2
- package/corpus/templates/design/actions/view-screen.ts +15 -2
- package/corpus/templates/design/agent-native.app-skill.json +5 -0
- package/corpus/templates/design/app/components/editor/PromptDialog.tsx +281 -56
- package/corpus/templates/design/app/components/templates/TemplatePreview.tsx +14 -2
- package/corpus/templates/design/app/hooks/use-navigation-state.ts +3 -2
- package/corpus/templates/design/app/i18n/zh-TW.ts +3 -3
- package/corpus/templates/design/app/i18n-data.ts +21 -2
- package/corpus/templates/design/app/i18n-template-feature.ts +218 -10
- package/corpus/templates/design/app/pages/Index.tsx +195 -24
- package/corpus/templates/design/app/pages/Templates.tsx +144 -55
- package/corpus/templates/design/app/pages/design-editor/generation-prompt-directives.ts +12 -1
- package/corpus/templates/design/changelog/2026-07-14-templates-now-appear-in-the-new-design-picker-with-previews-.md +6 -0
- package/corpus/templates/design/changelog/2026-07-15-templates-now-open-immediately-after-copying-even-while-the-.md +6 -0
- package/corpus/templates/design/server/plugins/agent-chat.ts +1 -1
- package/corpus/templates/mail/AGENTS.md +23 -18
- package/corpus/templates/mail/actions/bulk-archive.ts +32 -28
- package/corpus/templates/mail/actions/mark-read.ts +131 -20
- package/corpus/templates/mail/actions/mark-thread-read.ts +1 -1
- package/corpus/templates/mail/actions/move-email.ts +30 -24
- package/corpus/templates/mail/actions/send-email.ts +73 -68
- package/corpus/templates/mail/changelog/2026-07-15-unread-inbox-cleanup-now-completes-reliably.md +6 -0
- package/corpus/templates/mail/server/handlers/emails.ts +218 -209
- package/corpus/templates/mail/server/lib/bulk-mark-read.ts +30 -0
- package/corpus/templates/mail/server/lib/email-state.ts +198 -113
- package/corpus/templates/mail/server/lib/google-auth.ts +218 -25
- package/corpus/templates/mail/server/lib/jobs.ts +69 -74
- package/corpus/templates/mail/server/lib/local-email-store.ts +265 -0
- package/corpus/templates/mail/server/plugins/agent-chat.ts +6 -0
- package/dist/cli/content-local.d.ts +1 -0
- package/dist/cli/content-local.d.ts.map +1 -1
- package/dist/cli/content-local.js +75 -17
- package/dist/cli/content-local.js.map +1 -1
- package/dist/cli/index.js +2 -2
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/skills-content/content-skill.d.ts +1 -1
- package/dist/cli/skills-content/content-skill.d.ts.map +1 -1
- package/dist/cli/skills-content/content-skill.js +36 -25
- package/dist/cli/skills-content/content-skill.js.map +1 -1
- package/dist/cli/skills.d.ts.map +1 -1
- package/dist/cli/skills.js +47 -14
- package/dist/cli/skills.js.map +1 -1
- package/dist/collab/awareness.d.ts +2 -2
- package/dist/collab/awareness.d.ts.map +1 -1
- package/dist/collab/struct-routes.d.ts +1 -1
- package/dist/local-artifacts/index.d.ts +10 -0
- package/dist/local-artifacts/index.d.ts.map +1 -1
- package/dist/local-artifacts/index.js +39 -0
- package/dist/local-artifacts/index.js.map +1 -1
- package/dist/notifications/routes.d.ts +1 -1
- package/dist/observability/routes.d.ts +5 -5
- package/dist/resources/handlers.d.ts +1 -1
- package/dist/secrets/routes.d.ts +9 -9
- package/docs/content/local-file-mode.mdx +99 -489
- package/docs/content/locales/ar-SA/local-file-mode.mdx +35 -490
- package/docs/content/locales/ar-SA/template-content.mdx +10 -24
- package/docs/content/locales/de-DE/local-file-mode.mdx +37 -491
- package/docs/content/locales/de-DE/template-content.mdx +10 -24
- package/docs/content/locales/es-ES/local-file-mode.mdx +35 -493
- package/docs/content/locales/es-ES/template-content.mdx +10 -24
- package/docs/content/locales/fr-FR/local-file-mode.mdx +38 -491
- package/docs/content/locales/fr-FR/template-content.mdx +10 -24
- package/docs/content/locales/hi-IN/local-file-mode.mdx +33 -492
- package/docs/content/locales/hi-IN/template-content.mdx +10 -24
- package/docs/content/locales/ja-JP/local-file-mode.mdx +36 -492
- package/docs/content/locales/ja-JP/template-content.mdx +10 -24
- package/docs/content/locales/ko-KR/local-file-mode.mdx +35 -490
- package/docs/content/locales/ko-KR/template-content.mdx +10 -24
- package/docs/content/locales/pt-BR/local-file-mode.mdx +35 -493
- package/docs/content/locales/pt-BR/template-content.mdx +10 -24
- package/docs/content/locales/zh-CN/local-file-mode.mdx +31 -489
- package/docs/content/locales/zh-CN/template-content.mdx +9 -24
- package/docs/content/locales/zh-TW/local-file-mode.mdx +31 -489
- package/docs/content/locales/zh-TW/template-content.mdx +9 -24
- package/docs/content/template-content.mdx +26 -42
- package/package.json +1 -1
- package/corpus/templates/assets/app/components/library/EditLibraryDialog.tsx +0 -126
|
@@ -2,6 +2,7 @@ import {
|
|
|
2
2
|
DevDatabaseLink,
|
|
3
3
|
FeedbackButton,
|
|
4
4
|
appPath,
|
|
5
|
+
setClientAppState,
|
|
5
6
|
useActionMutation,
|
|
6
7
|
useCodeMode,
|
|
7
8
|
useT,
|
|
@@ -10,7 +11,11 @@ import {
|
|
|
10
11
|
ExtensionSlot,
|
|
11
12
|
ExtensionsSidebarSection,
|
|
12
13
|
} from "@agent-native/core/client/extensions";
|
|
13
|
-
import {
|
|
14
|
+
import {
|
|
15
|
+
OrgSwitcher,
|
|
16
|
+
useOrg,
|
|
17
|
+
useSwitchOrg,
|
|
18
|
+
} from "@agent-native/core/client/org";
|
|
14
19
|
import {
|
|
15
20
|
closestCenter,
|
|
16
21
|
DndContext,
|
|
@@ -45,10 +50,18 @@ import {
|
|
|
45
50
|
IconTrash,
|
|
46
51
|
} from "@tabler/icons-react";
|
|
47
52
|
import { useQueryClient } from "@tanstack/react-query";
|
|
48
|
-
import {
|
|
53
|
+
import {
|
|
54
|
+
useCallback,
|
|
55
|
+
useEffect,
|
|
56
|
+
useMemo,
|
|
57
|
+
useRef,
|
|
58
|
+
useState,
|
|
59
|
+
type ReactNode,
|
|
60
|
+
} from "react";
|
|
49
61
|
import { Link, useLocation, useNavigate } from "react-router";
|
|
50
62
|
import { toast } from "sonner";
|
|
51
63
|
|
|
64
|
+
import { ContentFilesSidebarView } from "@/components/editor/database/sidebar";
|
|
52
65
|
import { QueryErrorState } from "@/components/QueryErrorState";
|
|
53
66
|
import { ThemeToggle } from "@/components/ThemeToggle";
|
|
54
67
|
import {
|
|
@@ -76,11 +89,18 @@ import {
|
|
|
76
89
|
TooltipTrigger,
|
|
77
90
|
} from "@/components/ui/tooltip";
|
|
78
91
|
import {
|
|
92
|
+
useContentDatabaseById,
|
|
93
|
+
useContentDatabasePersonalView,
|
|
94
|
+
useUpdateContentDatabasePersonalView,
|
|
79
95
|
useCreateContentDatabase,
|
|
80
96
|
useDeleteContentDatabase,
|
|
81
97
|
useRestoreContentDatabase,
|
|
82
98
|
useTrashedContentDatabases,
|
|
83
99
|
} from "@/hooks/use-content-database";
|
|
100
|
+
import {
|
|
101
|
+
useContentSpaces,
|
|
102
|
+
useEnsureContentSpaces,
|
|
103
|
+
} from "@/hooks/use-content-spaces";
|
|
84
104
|
import {
|
|
85
105
|
useDocuments,
|
|
86
106
|
useCreateDocument,
|
|
@@ -99,6 +119,10 @@ import {
|
|
|
99
119
|
} from "./document-sidebar-sections";
|
|
100
120
|
import { DocumentSidebarIcon, DocumentTreeItem } from "./DocumentTreeItem";
|
|
101
121
|
import { NotionButton } from "./NotionButton";
|
|
122
|
+
import {
|
|
123
|
+
contentSpaceForActiveOrg,
|
|
124
|
+
selectContentSpace,
|
|
125
|
+
} from "./select-content-space";
|
|
102
126
|
|
|
103
127
|
function nanoid(size = 12): string {
|
|
104
128
|
const chars =
|
|
@@ -163,6 +187,7 @@ type CollapsedSectionsState = Record<SidebarSectionId, boolean>;
|
|
|
163
187
|
|
|
164
188
|
const SIDEBAR_SECTION_COLLAPSE_STORAGE_KEY =
|
|
165
189
|
"content-sidebar-collapsed-sections";
|
|
190
|
+
const SELECTED_CONTENT_SPACE_STORAGE_KEY = "content-selected-space";
|
|
166
191
|
|
|
167
192
|
const DEFAULT_COLLAPSED_SECTIONS: CollapsedSectionsState = {
|
|
168
193
|
"local-files": false,
|
|
@@ -212,6 +237,79 @@ export function DocumentSidebar({
|
|
|
212
237
|
const { data: trashedDatabases } = useTrashedContentDatabases();
|
|
213
238
|
const { isCodeMode } = useCodeMode();
|
|
214
239
|
const updateDocument = useUpdateDocument();
|
|
240
|
+
const contentSpacesQuery = useContentSpaces();
|
|
241
|
+
const ensureContentSpaces = useEnsureContentSpaces();
|
|
242
|
+
const { data: activeOrg } = useOrg();
|
|
243
|
+
const switchOrg = useSwitchOrg();
|
|
244
|
+
const contentSpaces = contentSpacesQuery.data?.spaces ?? [];
|
|
245
|
+
const spaceProvisionAttemptedRef = useRef(false);
|
|
246
|
+
useEffect(() => {
|
|
247
|
+
if (
|
|
248
|
+
contentSpacesQuery.isSuccess &&
|
|
249
|
+
!spaceProvisionAttemptedRef.current &&
|
|
250
|
+
!ensureContentSpaces.isPending
|
|
251
|
+
) {
|
|
252
|
+
spaceProvisionAttemptedRef.current = true;
|
|
253
|
+
ensureContentSpaces.mutate({});
|
|
254
|
+
}
|
|
255
|
+
}, [
|
|
256
|
+
contentSpacesQuery.isSuccess,
|
|
257
|
+
ensureContentSpaces,
|
|
258
|
+
ensureContentSpaces.isPending,
|
|
259
|
+
]);
|
|
260
|
+
const [storedSpaceId, setStoredSpaceId] = useLocalStorage<string | null>(
|
|
261
|
+
SELECTED_CONTENT_SPACE_STORAGE_KEY,
|
|
262
|
+
null,
|
|
263
|
+
);
|
|
264
|
+
const selectedSpace = contentSpaceForActiveOrg({
|
|
265
|
+
spaces: contentSpaces,
|
|
266
|
+
storedSpaceId,
|
|
267
|
+
activeOrgId: activeOrg?.orgId,
|
|
268
|
+
});
|
|
269
|
+
useEffect(() => {
|
|
270
|
+
if (selectedSpace && selectedSpace.id !== storedSpaceId) {
|
|
271
|
+
setStoredSpaceId(selectedSpace.id);
|
|
272
|
+
}
|
|
273
|
+
}, [selectedSpace, setStoredSpaceId, storedSpaceId]);
|
|
274
|
+
const handleSelectContentSpace = useCallback(
|
|
275
|
+
async (space: (typeof contentSpaces)[number]) => {
|
|
276
|
+
try {
|
|
277
|
+
await selectContentSpace({
|
|
278
|
+
space,
|
|
279
|
+
activeOrgId: activeOrg?.orgId,
|
|
280
|
+
switchOrg: (orgId) => switchOrg.mutateAsync(orgId),
|
|
281
|
+
persistSelection: setStoredSpaceId,
|
|
282
|
+
});
|
|
283
|
+
} catch (error) {
|
|
284
|
+
toast.error(error instanceof Error ? error.message : String(error));
|
|
285
|
+
}
|
|
286
|
+
},
|
|
287
|
+
[activeOrg?.orgId, setStoredSpaceId, switchOrg, t],
|
|
288
|
+
);
|
|
289
|
+
useEffect(() => {
|
|
290
|
+
if (!selectedSpace) return;
|
|
291
|
+
void setClientAppState(
|
|
292
|
+
"content-space",
|
|
293
|
+
{
|
|
294
|
+
spaceId: selectedSpace.id,
|
|
295
|
+
name: selectedSpace.name,
|
|
296
|
+
kind: selectedSpace.kind,
|
|
297
|
+
filesDatabaseId: selectedSpace.filesDatabaseId,
|
|
298
|
+
},
|
|
299
|
+
{ requestSource: "content-sidebar" },
|
|
300
|
+
).catch(() => {
|
|
301
|
+
// Space selection remains usable when best-effort agent context sync fails.
|
|
302
|
+
});
|
|
303
|
+
}, [selectedSpace]);
|
|
304
|
+
const filesDatabase = useContentDatabaseById(
|
|
305
|
+
selectedSpace?.filesDatabaseId ?? null,
|
|
306
|
+
);
|
|
307
|
+
const filesPersonalView = useContentDatabasePersonalView(
|
|
308
|
+
selectedSpace?.filesDatabaseId ?? null,
|
|
309
|
+
);
|
|
310
|
+
const updateFilesPersonalView = useUpdateContentDatabasePersonalView(
|
|
311
|
+
selectedSpace?.filesDatabaseId ?? null,
|
|
312
|
+
);
|
|
215
313
|
const removeLocalFileSource = useActionMutation<
|
|
216
314
|
RemoveLocalFileSourceResult,
|
|
217
315
|
{ sourceRootPath?: string | null }
|
|
@@ -283,10 +381,6 @@ export function DocumentSidebar({
|
|
|
283
381
|
} = getDocumentSidebarSections(documents, treeDocuments);
|
|
284
382
|
const localFileTree = buildDocumentTree(localSourceDocuments);
|
|
285
383
|
const databaseTree = buildDocumentTree(databaseDocuments);
|
|
286
|
-
const privateTree = databaseTree.filter((node) => node.visibility !== "org");
|
|
287
|
-
const organizationTree = databaseTree.filter(
|
|
288
|
-
(node) => node.visibility === "org",
|
|
289
|
-
);
|
|
290
384
|
const importedLocalFileCount = localFileMode
|
|
291
385
|
? 0
|
|
292
386
|
: localSourceDocuments.filter(
|
|
@@ -348,6 +442,7 @@ export function DocumentSidebar({
|
|
|
348
442
|
const created = await createDocument.mutateAsync({
|
|
349
443
|
title: "",
|
|
350
444
|
parentId: parentId ?? undefined,
|
|
445
|
+
spaceId: selectedSpace?.id,
|
|
351
446
|
});
|
|
352
447
|
queryClient.setQueryData(
|
|
353
448
|
["action", "get-document", { id: created.id }],
|
|
@@ -402,6 +497,7 @@ export function DocumentSidebar({
|
|
|
402
497
|
id,
|
|
403
498
|
title: "",
|
|
404
499
|
parentId: parentId ?? undefined,
|
|
500
|
+
spaceId: selectedSpace?.id,
|
|
405
501
|
});
|
|
406
502
|
const nextId = created?.id || id;
|
|
407
503
|
if (nextId !== id) {
|
|
@@ -444,6 +540,7 @@ export function DocumentSidebar({
|
|
|
444
540
|
navigateToDocument,
|
|
445
541
|
onNavigate,
|
|
446
542
|
queryClient,
|
|
543
|
+
selectedSpace?.id,
|
|
447
544
|
],
|
|
448
545
|
);
|
|
449
546
|
|
|
@@ -452,6 +549,7 @@ export function DocumentSidebar({
|
|
|
452
549
|
try {
|
|
453
550
|
const result = await createDatabase.mutateAsync({
|
|
454
551
|
parentId: parentId ?? null,
|
|
552
|
+
spaceId: parentId ? undefined : selectedSpace?.id,
|
|
455
553
|
title: t("editor.untitledDatabase"),
|
|
456
554
|
});
|
|
457
555
|
navigateToDocument(result.database.documentId);
|
|
@@ -463,7 +561,7 @@ export function DocumentSidebar({
|
|
|
463
561
|
});
|
|
464
562
|
}
|
|
465
563
|
},
|
|
466
|
-
[createDatabase, navigateToDocument, onNavigate, t],
|
|
564
|
+
[createDatabase, navigateToDocument, onNavigate, selectedSpace?.id, t],
|
|
467
565
|
);
|
|
468
566
|
|
|
469
567
|
const handleDelete = useCallback(
|
|
@@ -723,71 +821,51 @@ export function DocumentSidebar({
|
|
|
723
821
|
</SortableContext>
|
|
724
822
|
);
|
|
725
823
|
|
|
726
|
-
const renderNewButton = () =>
|
|
727
|
-
|
|
728
|
-
<
|
|
824
|
+
const renderNewButton = () =>
|
|
825
|
+
selectedSpace ? (
|
|
826
|
+
<div className="flex items-center gap-1">
|
|
729
827
|
<button
|
|
730
828
|
type="button"
|
|
731
|
-
className="flex w-
|
|
732
|
-
disabled={createDocument.isPending || createDatabase.isPending}
|
|
733
|
-
>
|
|
734
|
-
<IconPlus size={14} className="shrink-0" />
|
|
735
|
-
<span>{t("sidebar.new")}</span>
|
|
736
|
-
</button>
|
|
737
|
-
</DropdownMenuTrigger>
|
|
738
|
-
<DropdownMenuContent align="start" className="w-44">
|
|
739
|
-
<DropdownMenuItem
|
|
829
|
+
className="flex min-w-0 flex-1 items-center gap-2 rounded-md px-3 py-[5px] text-sm text-muted-foreground hover:bg-accent/50 hover:text-foreground"
|
|
740
830
|
disabled={createDocument.isPending}
|
|
741
831
|
onClick={() => void handleCreatePage()}
|
|
742
832
|
>
|
|
743
|
-
<
|
|
744
|
-
{t("sidebar.
|
|
745
|
-
</
|
|
746
|
-
<
|
|
747
|
-
|
|
748
|
-
onClick={() => void handleCreateDatabase(null)}
|
|
749
|
-
>
|
|
750
|
-
<IconDatabase className="me-2 size-4" />
|
|
751
|
-
{t("sidebar.database")}
|
|
752
|
-
</DropdownMenuItem>
|
|
753
|
-
</DropdownMenuContent>
|
|
754
|
-
</DropdownMenu>
|
|
755
|
-
);
|
|
756
|
-
|
|
757
|
-
const renderCollapsedNewButton = () => (
|
|
758
|
-
<DropdownMenu>
|
|
759
|
-
<Tooltip>
|
|
760
|
-
<TooltipTrigger asChild>
|
|
761
|
-
<DropdownMenuTrigger asChild>
|
|
833
|
+
<IconPlus size={14} className="shrink-0" />
|
|
834
|
+
<span>{t("sidebar.newPage")}</span>
|
|
835
|
+
</button>
|
|
836
|
+
<Tooltip>
|
|
837
|
+
<TooltipTrigger asChild>
|
|
762
838
|
<button
|
|
763
839
|
type="button"
|
|
764
|
-
className="
|
|
765
|
-
disabled={
|
|
840
|
+
className="flex size-7 shrink-0 items-center justify-center rounded-md text-muted-foreground hover:bg-accent/50 hover:text-foreground"
|
|
841
|
+
disabled={createDatabase.isPending}
|
|
842
|
+
aria-label={t("sidebar.newDatabase")}
|
|
843
|
+
onClick={() => void handleCreateDatabase()}
|
|
766
844
|
>
|
|
767
|
-
<
|
|
845
|
+
<IconDatabase size={14} />
|
|
768
846
|
</button>
|
|
769
|
-
</
|
|
847
|
+
</TooltipTrigger>
|
|
848
|
+
<TooltipContent>{t("sidebar.newDatabase")}</TooltipContent>
|
|
849
|
+
</Tooltip>
|
|
850
|
+
</div>
|
|
851
|
+
) : null;
|
|
852
|
+
|
|
853
|
+
const renderCollapsedNewButton = () =>
|
|
854
|
+
selectedSpace ? (
|
|
855
|
+
<Tooltip>
|
|
856
|
+
<TooltipTrigger asChild>
|
|
857
|
+
<button
|
|
858
|
+
type="button"
|
|
859
|
+
className="w-10 h-10 flex items-center justify-center rounded-lg hover:bg-accent text-muted-foreground hover:text-foreground"
|
|
860
|
+
disabled={createDocument.isPending}
|
|
861
|
+
onClick={() => void handleCreatePage()}
|
|
862
|
+
>
|
|
863
|
+
<IconPlus size={16} />
|
|
864
|
+
</button>
|
|
770
865
|
</TooltipTrigger>
|
|
771
|
-
<TooltipContent>{t("sidebar.
|
|
866
|
+
<TooltipContent>{t("sidebar.newPage")}</TooltipContent>
|
|
772
867
|
</Tooltip>
|
|
773
|
-
|
|
774
|
-
<DropdownMenuItem
|
|
775
|
-
disabled={createDocument.isPending}
|
|
776
|
-
onClick={() => void handleCreatePage()}
|
|
777
|
-
>
|
|
778
|
-
<IconFileText className="me-2 size-4" />
|
|
779
|
-
{t("sidebar.page")}
|
|
780
|
-
</DropdownMenuItem>
|
|
781
|
-
<DropdownMenuItem
|
|
782
|
-
disabled={createDatabase.isPending}
|
|
783
|
-
onClick={() => void handleCreateDatabase(null)}
|
|
784
|
-
>
|
|
785
|
-
<IconDatabase className="me-2 size-4" />
|
|
786
|
-
{t("sidebar.database")}
|
|
787
|
-
</DropdownMenuItem>
|
|
788
|
-
</DropdownMenuContent>
|
|
789
|
-
</DropdownMenu>
|
|
790
|
-
);
|
|
868
|
+
) : null;
|
|
791
869
|
|
|
792
870
|
const renderLocalFilesNavButton = () => (
|
|
793
871
|
<Link
|
|
@@ -987,6 +1065,73 @@ export function DocumentSidebar({
|
|
|
987
1065
|
);
|
|
988
1066
|
};
|
|
989
1067
|
|
|
1068
|
+
const renderWorkspaceNavigation = () => (
|
|
1069
|
+
<div className="mb-2 space-y-1 px-2">
|
|
1070
|
+
<div className="px-1 py-1.5 text-[10px] font-semibold uppercase tracking-wider text-muted-foreground">
|
|
1071
|
+
{t("sidebar.workspaces")}
|
|
1072
|
+
</div>
|
|
1073
|
+
{contentSpaces.map((space) => (
|
|
1074
|
+
<button
|
|
1075
|
+
key={space.id}
|
|
1076
|
+
type="button"
|
|
1077
|
+
className={cn(
|
|
1078
|
+
"flex h-8 w-full min-w-0 items-center rounded-md px-2 text-sm",
|
|
1079
|
+
selectedSpace?.id === space.id
|
|
1080
|
+
? "bg-accent text-accent-foreground"
|
|
1081
|
+
: "text-muted-foreground hover:bg-accent/50 hover:text-foreground",
|
|
1082
|
+
)}
|
|
1083
|
+
onClick={() => void handleSelectContentSpace(space)}
|
|
1084
|
+
disabled={switchOrg.isPending}
|
|
1085
|
+
>
|
|
1086
|
+
<span className="min-w-0 flex-1 truncate text-start">
|
|
1087
|
+
{space.name}
|
|
1088
|
+
</span>
|
|
1089
|
+
</button>
|
|
1090
|
+
))}
|
|
1091
|
+
</div>
|
|
1092
|
+
);
|
|
1093
|
+
|
|
1094
|
+
const renderFilesDatabase = () => (
|
|
1095
|
+
<div className="min-w-0">
|
|
1096
|
+
<div className="px-3 py-1.5 text-[10px] font-semibold uppercase tracking-wider text-muted-foreground">
|
|
1097
|
+
{t("sidebar.files")}
|
|
1098
|
+
</div>
|
|
1099
|
+
{selectedSpace ? (
|
|
1100
|
+
<>
|
|
1101
|
+
<ContentFilesSidebarView
|
|
1102
|
+
data={filesDatabase.data}
|
|
1103
|
+
overrides={filesPersonalView.data?.overrides}
|
|
1104
|
+
isLoading={filesDatabase.isLoading || filesPersonalView.isLoading}
|
|
1105
|
+
onSelectView={(viewId) => {
|
|
1106
|
+
if (!selectedSpace) return;
|
|
1107
|
+
const current = filesPersonalView.data?.overrides;
|
|
1108
|
+
updateFilesPersonalView.mutate({
|
|
1109
|
+
databaseId: selectedSpace.filesDatabaseId,
|
|
1110
|
+
overrides: {
|
|
1111
|
+
version: current?.version ?? 1,
|
|
1112
|
+
activeViewId: viewId,
|
|
1113
|
+
views: current?.views ?? [],
|
|
1114
|
+
},
|
|
1115
|
+
});
|
|
1116
|
+
}}
|
|
1117
|
+
labels={{
|
|
1118
|
+
loadingLabel: t("sidebar.loadingFiles"),
|
|
1119
|
+
noMatchesLabel: t("database.noRowsMatchThisView"),
|
|
1120
|
+
clearLabel: t("database.clearSearchAndFilters"),
|
|
1121
|
+
navigationLabel: t("sidebar.files"),
|
|
1122
|
+
untitledLabel: t("sidebar.untitled"),
|
|
1123
|
+
}}
|
|
1124
|
+
/>
|
|
1125
|
+
{renderNewButton()}
|
|
1126
|
+
</>
|
|
1127
|
+
) : (
|
|
1128
|
+
<div className="px-3 py-4 text-center text-sm text-muted-foreground">
|
|
1129
|
+
{t("sidebar.noWorkspaces")}
|
|
1130
|
+
</div>
|
|
1131
|
+
)}
|
|
1132
|
+
</div>
|
|
1133
|
+
);
|
|
1134
|
+
|
|
990
1135
|
const renderTrashSection = () => {
|
|
991
1136
|
if (trashItems.length === 0) return null;
|
|
992
1137
|
const collapsed = collapsedSections.trash;
|
|
@@ -1309,58 +1454,9 @@ export function DocumentSidebar({
|
|
|
1309
1454
|
</div>
|
|
1310
1455
|
)}
|
|
1311
1456
|
|
|
1312
|
-
{
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
id: "local-files",
|
|
1316
|
-
label: t("sidebar.localFiles"),
|
|
1317
|
-
nodes: localFileTree,
|
|
1318
|
-
emptyLabel: t("sidebar.noFilesYet"),
|
|
1319
|
-
headerActions: renderLocalFilesSectionActions(),
|
|
1320
|
-
footer: renderNewButton(),
|
|
1321
|
-
})}
|
|
1322
|
-
{databaseTree.length > 0
|
|
1323
|
-
? renderTreeSection({
|
|
1324
|
-
id: "shared-copies",
|
|
1325
|
-
label: t("sidebar.sharedCopies"),
|
|
1326
|
-
nodes: databaseTree,
|
|
1327
|
-
emptyLabel: t("sidebar.noSharedCopiesYet"),
|
|
1328
|
-
className: "mt-3",
|
|
1329
|
-
})
|
|
1330
|
-
: null}
|
|
1331
|
-
{renderTrashSection()}
|
|
1332
|
-
</>
|
|
1333
|
-
) : (
|
|
1334
|
-
<>
|
|
1335
|
-
{localFileTree.length > 0 &&
|
|
1336
|
-
renderTreeSection({
|
|
1337
|
-
id: "local-files",
|
|
1338
|
-
label: t("sidebar.localFiles"),
|
|
1339
|
-
nodes: localFileTree,
|
|
1340
|
-
emptyLabel: t("sidebar.noLocalFilesYet"),
|
|
1341
|
-
className: "mb-2",
|
|
1342
|
-
headerActions: renderLocalFilesSectionActions(),
|
|
1343
|
-
})}
|
|
1344
|
-
|
|
1345
|
-
{renderTreeSection({
|
|
1346
|
-
id: "private",
|
|
1347
|
-
label: t("sidebar.private"),
|
|
1348
|
-
nodes: privateTree,
|
|
1349
|
-
emptyLabel: t("sidebar.noPrivatePagesYet"),
|
|
1350
|
-
footer: renderNewButton(),
|
|
1351
|
-
})}
|
|
1352
|
-
|
|
1353
|
-
{!isLoading &&
|
|
1354
|
-
renderTreeSection({
|
|
1355
|
-
id: "organization",
|
|
1356
|
-
label: t("sidebar.organization"),
|
|
1357
|
-
nodes: organizationTree,
|
|
1358
|
-
emptyLabel: t("sidebar.noOrganizationPagesYet"),
|
|
1359
|
-
className: "mt-3",
|
|
1360
|
-
})}
|
|
1361
|
-
{renderTrashSection()}
|
|
1362
|
-
</>
|
|
1363
|
-
)}
|
|
1457
|
+
{renderWorkspaceNavigation()}
|
|
1458
|
+
{renderFilesDatabase()}
|
|
1459
|
+
{renderTrashSection()}
|
|
1364
1460
|
</>
|
|
1365
1461
|
)}
|
|
1366
1462
|
</div>
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { ContentSpaceSummary } from "@/hooks/use-content-spaces";
|
|
2
|
+
|
|
3
|
+
export function contentSpaceForActiveOrg(args: {
|
|
4
|
+
spaces: ContentSpaceSummary[];
|
|
5
|
+
storedSpaceId: string | null;
|
|
6
|
+
activeOrgId: string | null | undefined;
|
|
7
|
+
}) {
|
|
8
|
+
if (args.activeOrgId === undefined) return null;
|
|
9
|
+
const stored = args.spaces.find((space) => space.id === args.storedSpaceId);
|
|
10
|
+
if (stored?.orgId === args.activeOrgId) return stored;
|
|
11
|
+
const matching = args.spaces.filter(
|
|
12
|
+
(space) => space.orgId === args.activeOrgId,
|
|
13
|
+
);
|
|
14
|
+
return args.activeOrgId === null
|
|
15
|
+
? (matching.find((space) => space.kind === "personal") ??
|
|
16
|
+
matching[0] ??
|
|
17
|
+
null)
|
|
18
|
+
: (matching[0] ?? null);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export async function selectContentSpace(args: {
|
|
22
|
+
space: ContentSpaceSummary;
|
|
23
|
+
activeOrgId: string | null | undefined;
|
|
24
|
+
switchOrg: (orgId: string | null) => Promise<unknown>;
|
|
25
|
+
persistSelection: (spaceId: string) => void;
|
|
26
|
+
}) {
|
|
27
|
+
if (args.activeOrgId !== args.space.orgId) {
|
|
28
|
+
await args.switchOrg(args.space.orgId);
|
|
29
|
+
}
|
|
30
|
+
args.persistSelection(args.space.id);
|
|
31
|
+
}
|
|
@@ -52,6 +52,10 @@ export function contentDatabaseQueryKey(documentId: string) {
|
|
|
52
52
|
return ["action", "get-content-database", { documentId }] as const;
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
+
export function contentDatabaseByIdQueryKey(databaseId: string) {
|
|
56
|
+
return ["action", "get-content-database", { databaseId }] as const;
|
|
57
|
+
}
|
|
58
|
+
|
|
55
59
|
function isContentDatabaseQueryForDocument(
|
|
56
60
|
queryKey: readonly unknown[],
|
|
57
61
|
documentId: string,
|
|
@@ -454,6 +458,18 @@ export function useContentDatabase(documentId: string | null, limit?: number) {
|
|
|
454
458
|
);
|
|
455
459
|
}
|
|
456
460
|
|
|
461
|
+
export function useContentDatabaseById(databaseId: string | null) {
|
|
462
|
+
return useActionQuery<ContentDatabaseResponse>(
|
|
463
|
+
"get-content-database",
|
|
464
|
+
databaseId ? { databaseId } : undefined,
|
|
465
|
+
{
|
|
466
|
+
enabled: !!databaseId,
|
|
467
|
+
retry: false,
|
|
468
|
+
placeholderData: (previous) => previous,
|
|
469
|
+
},
|
|
470
|
+
);
|
|
471
|
+
}
|
|
472
|
+
|
|
457
473
|
export function useCreateContentDatabase(documentId: string | null) {
|
|
458
474
|
const queryClient = useQueryClient();
|
|
459
475
|
return useActionMutation<ContentDatabaseResponse, CreateDatabaseRequest>(
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { useActionMutation, useActionQuery } from "@agent-native/core/client";
|
|
2
|
+
import { useQueryClient } from "@tanstack/react-query";
|
|
3
|
+
|
|
4
|
+
export type ContentSpaceSummary = {
|
|
5
|
+
id: string;
|
|
6
|
+
name: string;
|
|
7
|
+
kind: string;
|
|
8
|
+
filesDatabaseId: string;
|
|
9
|
+
orgId: string | null;
|
|
10
|
+
role: "owner" | "editor" | "viewer";
|
|
11
|
+
catalogItemId: string;
|
|
12
|
+
catalogDocumentId: string;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export type ListContentSpacesResponse = {
|
|
16
|
+
catalogDatabaseId: string;
|
|
17
|
+
spaces: ContentSpaceSummary[];
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export function useContentSpaces() {
|
|
21
|
+
return useActionQuery<ListContentSpacesResponse>(
|
|
22
|
+
"list-content-spaces",
|
|
23
|
+
undefined,
|
|
24
|
+
{
|
|
25
|
+
placeholderData: (previous) => previous,
|
|
26
|
+
},
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export function useEnsureContentSpaces() {
|
|
31
|
+
const queryClient = useQueryClient();
|
|
32
|
+
return useActionMutation("ensure-content-spaces", {
|
|
33
|
+
onSuccess: () => {
|
|
34
|
+
queryClient.invalidateQueries({
|
|
35
|
+
queryKey: ["action", "list-content-spaces"],
|
|
36
|
+
});
|
|
37
|
+
},
|
|
38
|
+
});
|
|
39
|
+
}
|
|
@@ -85,6 +85,8 @@ const messages = {
|
|
|
85
85
|
heading2: "標題 2",
|
|
86
86
|
heading3: "標題 3",
|
|
87
87
|
heading4: "標題 4",
|
|
88
|
+
heading5: "標題 5",
|
|
89
|
+
heading6: "標題 6",
|
|
88
90
|
link: "連結",
|
|
89
91
|
comment: "評論",
|
|
90
92
|
pasteLink: "貼上連結...",
|
|
@@ -414,6 +416,8 @@ const messages = {
|
|
|
414
416
|
heading2Description: "中標題",
|
|
415
417
|
heading3Description: "小標題",
|
|
416
418
|
heading4Description: "副標題",
|
|
419
|
+
heading5Description: "較小標題",
|
|
420
|
+
heading6Description: "最小標題",
|
|
417
421
|
image: "圖片",
|
|
418
422
|
imageDescription: "上傳或嵌入圖片",
|
|
419
423
|
inlineEquation: "行內公式",
|
|
@@ -1008,6 +1012,8 @@ const messages = {
|
|
|
1008
1012
|
summaryUnchanged: "{{count}} 個未更改",
|
|
1009
1013
|
summarySkipped: "已跳過 {{count}} 個",
|
|
1010
1014
|
summaryErrors: "{{count}} 個錯誤",
|
|
1015
|
+
summaryConflicts: "{{count}} 個衝突",
|
|
1016
|
+
conflictNeedsReview: "Content 和資料夾都已變更;需要進行審查。",
|
|
1011
1017
|
pageTitle: "本機檔案",
|
|
1012
1018
|
foldersRemembered: "已記住的資料夾",
|
|
1013
1019
|
linkedCount: "已連結 {{count}} 個",
|
|
@@ -1110,7 +1116,10 @@ const messages = {
|
|
|
1110
1116
|
"「{{title}}」及其所有子頁面將被永久刪除。此操作無法復原。",
|
|
1111
1117
|
deletePageQuestion: "刪除頁面?",
|
|
1112
1118
|
localFiles: "本機檔案",
|
|
1119
|
+
files: "檔案",
|
|
1120
|
+
loadingFiles: "正在載入檔案…",
|
|
1113
1121
|
new: "新增",
|
|
1122
|
+
newDatabase: "新增資料庫",
|
|
1114
1123
|
newPage: "新頁面",
|
|
1115
1124
|
nextStep: "下一步",
|
|
1116
1125
|
notionConfigureOAuthAuthorize: "設定 OAuth,然後授權你的工作區。",
|
|
@@ -1139,6 +1148,7 @@ const messages = {
|
|
|
1139
1148
|
notionSyncDocumentsDescription: "與 Notion 工作區同步檔案。",
|
|
1140
1149
|
notionUploadCredentialsJson: "上傳憑證 JSON",
|
|
1141
1150
|
noFilesYet: "還沒有檔案",
|
|
1151
|
+
noWorkspaces: "還沒有工作區",
|
|
1142
1152
|
noLocalFilesYet: "還沒有本機檔案",
|
|
1143
1153
|
noOrganizationPagesYet: "還沒有組織頁面",
|
|
1144
1154
|
noPagesFound: "未找到頁面",
|
|
@@ -1160,6 +1170,7 @@ const messages = {
|
|
|
1160
1170
|
trash: "垃圾桶",
|
|
1161
1171
|
favorites: "釘選",
|
|
1162
1172
|
untitled: "無標題",
|
|
1173
|
+
workspaces: "工作區",
|
|
1163
1174
|
},
|
|
1164
1175
|
};
|
|
1165
1176
|
|