@aphexcms/cms-core 9.6.0 → 9.8.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/dist/agent-chat-state.svelte.d.ts +38 -0
- package/dist/agent-chat-state.svelte.d.ts.map +1 -0
- package/dist/agent-chat-state.svelte.js +86 -0
- package/dist/ai/content-workspace-tools.d.ts +3 -0
- package/dist/ai/content-workspace-tools.d.ts.map +1 -0
- package/dist/ai/content-workspace-tools.js +50 -0
- package/dist/ai/default-system-prompt.d.ts +2 -0
- package/dist/ai/default-system-prompt.d.ts.map +1 -0
- package/dist/ai/default-system-prompt.js +15 -0
- package/dist/ai/index.d.ts +2 -0
- package/dist/ai/index.d.ts.map +1 -0
- package/dist/ai/index.js +4 -0
- package/dist/ai/interfaces/ai-provider.d.ts +67 -0
- package/dist/ai/interfaces/ai-provider.d.ts.map +1 -0
- package/dist/ai/interfaces/ai-provider.js +16 -0
- package/dist/ai/run-agent-turn.d.ts +29 -0
- package/dist/ai/run-agent-turn.d.ts.map +1 -0
- package/dist/ai/run-agent-turn.js +166 -0
- package/dist/api/agent-chat.d.ts +27 -0
- package/dist/api/agent-chat.d.ts.map +1 -0
- package/dist/api/agent-chat.js +64 -0
- package/dist/api/documents.d.ts +36 -3
- package/dist/api/documents.d.ts.map +1 -1
- package/dist/api/documents.js +24 -6
- package/dist/api/schemas/agent-chat.d.ts +45 -0
- package/dist/api/schemas/agent-chat.d.ts.map +1 -0
- package/dist/api/schemas/agent-chat.js +35 -0
- package/dist/api/schemas/agent-operations.d.ts +13 -0
- package/dist/api/schemas/agent-operations.d.ts.map +1 -0
- package/dist/api/schemas/agent-operations.js +15 -0
- package/dist/api/schemas/documents.d.ts +41 -0
- package/dist/api/schemas/documents.d.ts.map +1 -1
- package/dist/api/schemas/documents.js +38 -2
- package/dist/chunk-recovery.d.ts +33 -0
- package/dist/chunk-recovery.d.ts.map +1 -0
- package/dist/chunk-recovery.js +131 -0
- package/dist/client/index.d.ts +1 -0
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +1 -0
- package/dist/client/ui.d.ts +2 -0
- package/dist/client/ui.d.ts.map +1 -1
- package/dist/client/ui.js +3 -0
- package/dist/components/AdminApp.svelte +37 -3
- package/dist/components/AdminApp.svelte.d.ts.map +1 -1
- package/dist/components/admin/ActivityView.svelte +436 -0
- package/dist/components/admin/ActivityView.svelte.d.ts +4 -0
- package/dist/components/admin/ActivityView.svelte.d.ts.map +1 -0
- package/dist/components/admin/AgentChat.svelte +977 -0
- package/dist/components/admin/AgentChat.svelte.d.ts +17 -0
- package/dist/components/admin/AgentChat.svelte.d.ts.map +1 -0
- package/dist/components/admin/DocumentEditor.svelte +469 -70
- package/dist/components/admin/DocumentEditor.svelte.d.ts +6 -0
- package/dist/components/admin/DocumentEditor.svelte.d.ts.map +1 -1
- package/dist/components/admin/ObjectModal.svelte +4 -2
- package/dist/components/admin/ScheduleDialog.svelte +174 -0
- package/dist/components/admin/ScheduleDialog.svelte.d.ts +20 -0
- package/dist/components/admin/ScheduleDialog.svelte.d.ts.map +1 -0
- package/dist/components/admin/fields/ArrayField.svelte +4 -1
- package/dist/components/admin/fields/ReferenceField.svelte +12 -1
- package/dist/components/admin/fields/ReferenceField.svelte.d.ts.map +1 -1
- package/dist/components/index.d.ts +1 -0
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/index.js +1 -0
- package/dist/components/layout/OrganizationSwitcher.svelte +3 -3
- package/dist/components/layout/Sidebar.svelte +26 -2
- package/dist/components/layout/Sidebar.svelte.d.ts +1 -0
- package/dist/components/layout/Sidebar.svelte.d.ts.map +1 -1
- package/dist/components/layout/sidebar/NavUser.svelte +5 -5
- package/dist/db/interfaces/agent-change-sets.d.ts +17 -0
- package/dist/db/interfaces/agent-change-sets.d.ts.map +1 -0
- package/dist/db/interfaces/agent-change-sets.js +1 -0
- package/dist/db/interfaces/document.d.ts +25 -3
- package/dist/db/interfaces/document.d.ts.map +1 -1
- package/dist/db/interfaces/document.js +19 -1
- package/dist/db/interfaces/events.d.ts +55 -0
- package/dist/db/interfaces/events.d.ts.map +1 -0
- package/dist/db/interfaces/events.js +1 -0
- package/dist/db/interfaces/index.d.ts +13 -2
- package/dist/db/interfaces/index.d.ts.map +1 -1
- package/dist/db/interfaces/index.js +1 -1
- package/dist/db/interfaces/plugin-storage.d.ts +39 -0
- package/dist/db/interfaces/plugin-storage.d.ts.map +1 -0
- package/dist/db/interfaces/plugin-storage.js +1 -0
- package/dist/document-refresh.svelte.d.ts +2 -0
- package/dist/document-refresh.svelte.d.ts.map +1 -1
- package/dist/document-refresh.svelte.js +15 -0
- package/dist/document-workspace-registry.svelte.d.ts +15 -0
- package/dist/document-workspace-registry.svelte.d.ts.map +1 -0
- package/dist/document-workspace-registry.svelte.js +30 -0
- package/dist/events/catalog.d.ts +8 -0
- package/dist/events/catalog.d.ts.map +1 -0
- package/dist/events/catalog.js +11 -0
- package/dist/events/consumer.d.ts +79 -0
- package/dist/events/consumer.d.ts.map +1 -0
- package/dist/events/consumer.js +76 -0
- package/dist/events/define-event.d.ts +17 -0
- package/dist/events/define-event.d.ts.map +1 -0
- package/dist/events/define-event.js +7 -0
- package/dist/events/emit.d.ts +11 -0
- package/dist/events/emit.d.ts.map +1 -0
- package/dist/events/emit.js +20 -0
- package/dist/events/index.d.ts +4 -0
- package/dist/events/index.d.ts.map +1 -0
- package/dist/events/index.js +3 -0
- package/dist/field-validation/rule.d.ts.map +1 -1
- package/dist/field-validation/rule.js +15 -0
- package/dist/field-validation/utils.d.ts.map +1 -1
- package/dist/field-validation/utils.js +211 -29
- package/dist/forms/define-form.d.ts +25 -0
- package/dist/forms/define-form.d.ts.map +1 -0
- package/dist/forms/define-form.js +22 -0
- package/dist/forms/index.d.ts +4 -0
- package/dist/forms/index.d.ts.map +1 -0
- package/dist/forms/index.js +5 -0
- package/dist/forms/types.d.ts +49 -0
- package/dist/forms/types.d.ts.map +1 -0
- package/dist/forms/types.js +1 -0
- package/dist/forms/validate.d.ts +9 -0
- package/dist/forms/validate.d.ts.map +1 -0
- package/dist/forms/validate.js +18 -0
- package/dist/hooks.d.ts +2 -0
- package/dist/hooks.d.ts.map +1 -1
- package/dist/hooks.js +17 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -0
- package/dist/jobs/document-jobs.d.ts +27 -0
- package/dist/jobs/document-jobs.d.ts.map +1 -0
- package/dist/jobs/document-jobs.js +42 -0
- package/dist/jobs/embedded-runner.d.ts +25 -0
- package/dist/jobs/embedded-runner.d.ts.map +1 -0
- package/dist/jobs/embedded-runner.js +46 -0
- package/dist/jobs/index.d.ts +7 -0
- package/dist/jobs/index.d.ts.map +1 -0
- package/dist/jobs/index.js +8 -0
- package/dist/jobs/relay.d.ts +27 -0
- package/dist/jobs/relay.d.ts.map +1 -0
- package/dist/jobs/relay.js +60 -0
- package/dist/jobs/run-batch.d.ts +52 -0
- package/dist/jobs/run-batch.d.ts.map +1 -0
- package/dist/jobs/run-batch.js +61 -0
- package/dist/jobs/run-due-jobs.d.ts +30 -0
- package/dist/jobs/run-due-jobs.d.ts.map +1 -0
- package/dist/jobs/run-due-jobs.js +69 -0
- package/dist/jobs/types.d.ts +18 -0
- package/dist/jobs/types.d.ts.map +1 -0
- package/dist/jobs/types.js +1 -0
- package/dist/lib/agent-chat-state.svelte.d.ts +38 -0
- package/dist/lib/agent-chat-state.svelte.d.ts.map +1 -0
- package/dist/lib/agent-chat-state.svelte.js +87 -0
- package/dist/lib/agent-chat-state.svelte.js.map +1 -0
- package/dist/lib/ai/content-workspace-tools.d.ts +3 -0
- package/dist/lib/ai/content-workspace-tools.d.ts.map +1 -0
- package/dist/lib/ai/content-workspace-tools.js +51 -0
- package/dist/lib/ai/content-workspace-tools.js.map +1 -0
- package/dist/lib/ai/default-system-prompt.d.ts +2 -0
- package/dist/lib/ai/default-system-prompt.d.ts.map +1 -0
- package/dist/lib/ai/default-system-prompt.js +16 -0
- package/dist/lib/ai/default-system-prompt.js.map +1 -0
- package/dist/lib/ai/index.d.ts +2 -0
- package/dist/lib/ai/index.d.ts.map +1 -0
- package/dist/lib/ai/index.js +5 -0
- package/dist/lib/ai/index.js.map +1 -0
- package/dist/lib/ai/interfaces/ai-provider.d.ts +67 -0
- package/dist/lib/ai/interfaces/ai-provider.d.ts.map +1 -0
- package/dist/lib/ai/interfaces/ai-provider.js +17 -0
- package/dist/lib/ai/interfaces/ai-provider.js.map +1 -0
- package/dist/lib/ai/run-agent-turn.d.ts +29 -0
- package/dist/lib/ai/run-agent-turn.d.ts.map +1 -0
- package/dist/lib/ai/run-agent-turn.js +167 -0
- package/dist/lib/ai/run-agent-turn.js.map +1 -0
- package/dist/lib/api/agent-chat.d.ts +27 -0
- package/dist/lib/api/agent-chat.d.ts.map +1 -0
- package/dist/lib/api/agent-chat.js +65 -0
- package/dist/lib/api/agent-chat.js.map +1 -0
- package/dist/lib/api/documents.d.ts +36 -3
- package/dist/lib/api/documents.d.ts.map +1 -1
- package/dist/lib/api/documents.js +24 -6
- package/dist/lib/api/documents.js.map +1 -1
- package/dist/lib/api/schemas/agent-chat.d.ts +45 -0
- package/dist/lib/api/schemas/agent-chat.d.ts.map +1 -0
- package/dist/lib/api/schemas/agent-chat.js +36 -0
- package/dist/lib/api/schemas/agent-chat.js.map +1 -0
- package/dist/lib/api/schemas/agent-operations.d.ts +13 -0
- package/dist/lib/api/schemas/agent-operations.d.ts.map +1 -0
- package/dist/lib/api/schemas/agent-operations.js +16 -0
- package/dist/lib/api/schemas/agent-operations.js.map +1 -0
- package/dist/lib/api/schemas/documents.d.ts +41 -0
- package/dist/lib/api/schemas/documents.d.ts.map +1 -1
- package/dist/lib/api/schemas/documents.js +38 -2
- package/dist/lib/api/schemas/documents.js.map +1 -1
- package/dist/lib/chunk-recovery.d.ts +33 -0
- package/dist/lib/chunk-recovery.d.ts.map +1 -0
- package/dist/lib/chunk-recovery.js +132 -0
- package/dist/lib/chunk-recovery.js.map +1 -0
- package/dist/lib/client/index.d.ts +1 -0
- package/dist/lib/client/index.d.ts.map +1 -1
- package/dist/lib/client/index.js +1 -0
- package/dist/lib/client/index.js.map +1 -1
- package/dist/lib/client/ui.d.ts +2 -0
- package/dist/lib/client/ui.d.ts.map +1 -1
- package/dist/lib/client/ui.js +3 -0
- package/dist/lib/client/ui.js.map +1 -1
- package/dist/lib/components/index.d.ts +1 -0
- package/dist/lib/components/index.d.ts.map +1 -1
- package/dist/lib/components/index.js +1 -0
- package/dist/lib/components/index.js.map +1 -1
- package/dist/lib/db/interfaces/agent-change-sets.d.ts +17 -0
- package/dist/lib/db/interfaces/agent-change-sets.d.ts.map +1 -0
- package/dist/lib/db/interfaces/agent-change-sets.js +2 -0
- package/dist/lib/db/interfaces/agent-change-sets.js.map +1 -0
- package/dist/lib/db/interfaces/document.d.ts +25 -3
- package/dist/lib/db/interfaces/document.d.ts.map +1 -1
- package/dist/lib/db/interfaces/document.js +19 -1
- package/dist/lib/db/interfaces/document.js.map +1 -1
- package/dist/lib/db/interfaces/events.d.ts +55 -0
- package/dist/lib/db/interfaces/events.d.ts.map +1 -0
- package/dist/lib/db/interfaces/events.js +2 -0
- package/dist/lib/db/interfaces/events.js.map +1 -0
- package/dist/lib/db/interfaces/index.d.ts +13 -2
- package/dist/lib/db/interfaces/index.d.ts.map +1 -1
- package/dist/lib/db/interfaces/index.js +1 -1
- package/dist/lib/db/interfaces/index.js.map +1 -1
- package/dist/lib/db/interfaces/plugin-storage.d.ts +39 -0
- package/dist/lib/db/interfaces/plugin-storage.d.ts.map +1 -0
- package/dist/lib/db/interfaces/plugin-storage.js +2 -0
- package/dist/lib/db/interfaces/plugin-storage.js.map +1 -0
- package/dist/lib/document-refresh.svelte.d.ts +2 -0
- package/dist/lib/document-refresh.svelte.d.ts.map +1 -1
- package/dist/lib/document-refresh.svelte.js +15 -0
- package/dist/lib/document-refresh.svelte.js.map +1 -1
- package/dist/lib/document-workspace-registry.svelte.d.ts +15 -0
- package/dist/lib/document-workspace-registry.svelte.d.ts.map +1 -0
- package/dist/lib/document-workspace-registry.svelte.js +31 -0
- package/dist/lib/document-workspace-registry.svelte.js.map +1 -0
- package/dist/lib/events/catalog.d.ts +8 -0
- package/dist/lib/events/catalog.d.ts.map +1 -0
- package/dist/lib/events/catalog.js +12 -0
- package/dist/lib/events/catalog.js.map +1 -0
- package/dist/lib/events/consumer.d.ts +79 -0
- package/dist/lib/events/consumer.d.ts.map +1 -0
- package/dist/lib/events/consumer.js +77 -0
- package/dist/lib/events/consumer.js.map +1 -0
- package/dist/lib/events/define-event.d.ts +17 -0
- package/dist/lib/events/define-event.d.ts.map +1 -0
- package/dist/lib/events/define-event.js +8 -0
- package/dist/lib/events/define-event.js.map +1 -0
- package/dist/lib/events/emit.d.ts +11 -0
- package/dist/lib/events/emit.d.ts.map +1 -0
- package/dist/lib/events/emit.js +21 -0
- package/dist/lib/events/emit.js.map +1 -0
- package/dist/lib/events/index.d.ts +4 -0
- package/dist/lib/events/index.d.ts.map +1 -0
- package/dist/lib/events/index.js +4 -0
- package/dist/lib/events/index.js.map +1 -0
- package/dist/lib/field-validation/rule.d.ts.map +1 -1
- package/dist/lib/field-validation/rule.js +15 -0
- package/dist/lib/field-validation/rule.js.map +1 -1
- package/dist/lib/field-validation/utils.d.ts.map +1 -1
- package/dist/lib/field-validation/utils.js +211 -29
- package/dist/lib/field-validation/utils.js.map +1 -1
- package/dist/lib/forms/define-form.d.ts +25 -0
- package/dist/lib/forms/define-form.d.ts.map +1 -0
- package/dist/lib/forms/define-form.js +23 -0
- package/dist/lib/forms/define-form.js.map +1 -0
- package/dist/lib/forms/index.d.ts +4 -0
- package/dist/lib/forms/index.d.ts.map +1 -0
- package/dist/lib/forms/index.js +6 -0
- package/dist/lib/forms/index.js.map +1 -0
- package/dist/lib/forms/types.d.ts +49 -0
- package/dist/lib/forms/types.d.ts.map +1 -0
- package/dist/lib/forms/types.js +2 -0
- package/dist/lib/forms/types.js.map +1 -0
- package/dist/lib/forms/validate.d.ts +9 -0
- package/dist/lib/forms/validate.d.ts.map +1 -0
- package/dist/lib/forms/validate.js +19 -0
- package/dist/lib/forms/validate.js.map +1 -0
- package/dist/lib/hooks.d.ts +2 -0
- package/dist/lib/hooks.d.ts.map +1 -1
- package/dist/lib/hooks.js +17 -0
- package/dist/lib/hooks.js.map +1 -1
- package/dist/lib/index.d.ts +2 -0
- package/dist/lib/index.d.ts.map +1 -1
- package/dist/lib/index.js +6 -0
- package/dist/lib/index.js.map +1 -1
- package/dist/lib/jobs/document-jobs.d.ts +27 -0
- package/dist/lib/jobs/document-jobs.d.ts.map +1 -0
- package/dist/lib/jobs/document-jobs.js +43 -0
- package/dist/lib/jobs/document-jobs.js.map +1 -0
- package/dist/lib/jobs/embedded-runner.d.ts +25 -0
- package/dist/lib/jobs/embedded-runner.d.ts.map +1 -0
- package/dist/lib/jobs/embedded-runner.js +47 -0
- package/dist/lib/jobs/embedded-runner.js.map +1 -0
- package/dist/lib/jobs/index.d.ts +7 -0
- package/dist/lib/jobs/index.d.ts.map +1 -0
- package/dist/lib/jobs/index.js +9 -0
- package/dist/lib/jobs/index.js.map +1 -0
- package/dist/lib/jobs/relay.d.ts +27 -0
- package/dist/lib/jobs/relay.d.ts.map +1 -0
- package/dist/lib/jobs/relay.js +61 -0
- package/dist/lib/jobs/relay.js.map +1 -0
- package/dist/lib/jobs/run-batch.d.ts +52 -0
- package/dist/lib/jobs/run-batch.d.ts.map +1 -0
- package/dist/lib/jobs/run-batch.js +62 -0
- package/dist/lib/jobs/run-batch.js.map +1 -0
- package/dist/lib/jobs/run-due-jobs.d.ts +30 -0
- package/dist/lib/jobs/run-due-jobs.d.ts.map +1 -0
- package/dist/lib/jobs/run-due-jobs.js +70 -0
- package/dist/lib/jobs/run-due-jobs.js.map +1 -0
- package/dist/lib/jobs/types.d.ts +18 -0
- package/dist/lib/jobs/types.d.ts.map +1 -0
- package/dist/lib/jobs/types.js +2 -0
- package/dist/lib/jobs/types.js.map +1 -0
- package/dist/lib/local-api/collection-api.d.ts +49 -2
- package/dist/lib/local-api/collection-api.d.ts.map +1 -1
- package/dist/lib/local-api/collection-api.js +193 -27
- package/dist/lib/local-api/collection-api.js.map +1 -1
- package/dist/lib/mcp/tools.d.ts +39 -4
- package/dist/lib/mcp/tools.d.ts.map +1 -1
- package/dist/lib/mcp/tools.js +546 -362
- package/dist/lib/mcp/tools.js.map +1 -1
- package/dist/lib/plugins/resolver.d.ts +19 -1
- package/dist/lib/plugins/resolver.d.ts.map +1 -1
- package/dist/lib/plugins/resolver.js +17 -1
- package/dist/lib/plugins/resolver.js.map +1 -1
- package/dist/lib/plugins/types.d.ts +68 -2
- package/dist/lib/plugins/types.d.ts.map +1 -1
- package/dist/lib/plugins/types.js.map +1 -1
- package/dist/lib/preview/stega.d.ts +2 -2
- package/dist/lib/preview/stega.d.ts.map +1 -1
- package/dist/lib/preview/stega.js +52 -29
- package/dist/lib/preview/stega.js.map +1 -1
- package/dist/lib/schema-utils/validator.d.ts.map +1 -1
- package/dist/lib/schema-utils/validator.js +5 -2
- package/dist/lib/schema-utils/validator.js.map +1 -1
- package/dist/lib/server/api/index.d.ts.map +1 -1
- package/dist/lib/server/api/index.js +16 -0
- package/dist/lib/server/api/index.js.map +1 -1
- package/dist/lib/server/api/routes/agent-change-sets.d.ts +4 -0
- package/dist/lib/server/api/routes/agent-change-sets.d.ts.map +1 -0
- package/dist/lib/server/api/routes/agent-change-sets.js +132 -0
- package/dist/lib/server/api/routes/agent-change-sets.js.map +1 -0
- package/dist/lib/server/api/routes/agent-chat.d.ts +14 -0
- package/dist/lib/server/api/routes/agent-chat.d.ts.map +1 -0
- package/dist/lib/server/api/routes/agent-chat.js +224 -0
- package/dist/lib/server/api/routes/agent-chat.js.map +1 -0
- package/dist/lib/server/api/routes/document-versions.d.ts.map +1 -1
- package/dist/lib/server/api/routes/document-versions.js +16 -2
- package/dist/lib/server/api/routes/document-versions.js.map +1 -1
- package/dist/lib/server/api/routes/documents-by-id.d.ts.map +1 -1
- package/dist/lib/server/api/routes/documents-by-id.js +11 -1
- package/dist/lib/server/api/routes/documents-by-id.js.map +1 -1
- package/dist/lib/server/api/routes/documents-publish.d.ts.map +1 -1
- package/dist/lib/server/api/routes/documents-publish.js +145 -2
- package/dist/lib/server/api/routes/documents-publish.js.map +1 -1
- package/dist/lib/server/api/routes/jobs.d.ts +4 -0
- package/dist/lib/server/api/routes/jobs.d.ts.map +1 -0
- package/dist/lib/server/api/routes/jobs.js +95 -0
- package/dist/lib/server/api/routes/jobs.js.map +1 -0
- package/dist/lib/server/api/routes/resolve-created-by.d.ts +13 -0
- package/dist/lib/server/api/routes/resolve-created-by.d.ts.map +1 -0
- package/dist/lib/server/api/routes/resolve-created-by.js +31 -0
- package/dist/lib/server/api/routes/resolve-created-by.js.map +1 -0
- package/dist/lib/server/api/routes/workers-run.d.ts +4 -0
- package/dist/lib/server/api/routes/workers-run.d.ts.map +1 -0
- package/dist/lib/server/api/routes/workers-run.js +41 -0
- package/dist/lib/server/api/routes/workers-run.js.map +1 -0
- package/dist/lib/server/index.d.ts +2 -0
- package/dist/lib/server/index.d.ts.map +1 -1
- package/dist/lib/server/index.js +3 -0
- package/dist/lib/server/index.js.map +1 -1
- package/dist/lib/services/version-service.d.ts +19 -3
- package/dist/lib/services/version-service.d.ts.map +1 -1
- package/dist/lib/services/version-service.js +75 -69
- package/dist/lib/services/version-service.js.map +1 -1
- package/dist/lib/type-gen.d.ts.map +1 -1
- package/dist/lib/type-gen.js +11 -0
- package/dist/lib/type-gen.js.map +1 -1
- package/dist/lib/types/agent-change-sets.d.ts +70 -0
- package/dist/lib/types/agent-change-sets.d.ts.map +1 -0
- package/dist/lib/types/agent-change-sets.js +7 -0
- package/dist/lib/types/agent-change-sets.js.map +1 -0
- package/dist/lib/types/agent-stream.d.ts +60 -0
- package/dist/lib/types/agent-stream.d.ts.map +1 -0
- package/dist/lib/types/agent-stream.js +12 -0
- package/dist/lib/types/agent-stream.js.map +1 -0
- package/dist/lib/types/agent-tools.d.ts +65 -0
- package/dist/lib/types/agent-tools.d.ts.map +1 -0
- package/dist/lib/types/agent-tools.js +2 -0
- package/dist/lib/types/agent-tools.js.map +1 -0
- package/dist/lib/types/config.d.ts +62 -0
- package/dist/lib/types/config.d.ts.map +1 -1
- package/dist/lib/types/document-workspace.d.ts +53 -0
- package/dist/lib/types/document-workspace.d.ts.map +1 -0
- package/dist/lib/types/document-workspace.js +15 -0
- package/dist/lib/types/document-workspace.js.map +1 -0
- package/dist/lib/types/document.d.ts +5 -0
- package/dist/lib/types/document.d.ts.map +1 -1
- package/dist/lib/types/events.d.ts +134 -0
- package/dist/lib/types/events.d.ts.map +1 -0
- package/dist/lib/types/events.js +4 -0
- package/dist/lib/types/events.js.map +1 -0
- package/dist/lib/types/index.d.ts +3 -0
- package/dist/lib/types/index.d.ts.map +1 -1
- package/dist/lib/types/index.js +3 -0
- package/dist/lib/types/index.js.map +1 -1
- package/dist/lib/types/schemas.js +1 -1
- package/dist/lib/types/schemas.js.map +1 -1
- package/dist/lib/utils/fetch-remote-file.d.ts +11 -0
- package/dist/lib/utils/fetch-remote-file.d.ts.map +1 -0
- package/dist/lib/utils/fetch-remote-file.js +169 -0
- package/dist/lib/utils/fetch-remote-file.js.map +1 -0
- package/dist/lib/utils/index.d.ts +1 -1
- package/dist/lib/utils/index.d.ts.map +1 -1
- package/dist/lib/utils/index.js.map +1 -1
- package/dist/local-api/collection-api.d.ts +49 -2
- package/dist/local-api/collection-api.d.ts.map +1 -1
- package/dist/local-api/collection-api.js +193 -27
- package/dist/mcp/tools.d.ts +39 -4
- package/dist/mcp/tools.d.ts.map +1 -1
- package/dist/mcp/tools.js +546 -362
- package/dist/plugins/resolver.d.ts +19 -1
- package/dist/plugins/resolver.d.ts.map +1 -1
- package/dist/plugins/resolver.js +17 -1
- package/dist/plugins/types.d.ts +68 -2
- package/dist/plugins/types.d.ts.map +1 -1
- package/dist/preview/stega.d.ts +2 -2
- package/dist/preview/stega.d.ts.map +1 -1
- package/dist/preview/stega.js +52 -29
- package/dist/schema-utils/validator.d.ts.map +1 -1
- package/dist/schema-utils/validator.js +5 -2
- package/dist/server/api/index.d.ts.map +1 -1
- package/dist/server/api/index.js +16 -0
- package/dist/server/api/routes/agent-change-sets.d.ts +4 -0
- package/dist/server/api/routes/agent-change-sets.d.ts.map +1 -0
- package/dist/server/api/routes/agent-change-sets.js +131 -0
- package/dist/server/api/routes/agent-chat.d.ts +14 -0
- package/dist/server/api/routes/agent-chat.d.ts.map +1 -0
- package/dist/server/api/routes/agent-chat.js +223 -0
- package/dist/server/api/routes/document-versions.d.ts.map +1 -1
- package/dist/server/api/routes/document-versions.js +16 -2
- package/dist/server/api/routes/documents-by-id.d.ts.map +1 -1
- package/dist/server/api/routes/documents-by-id.js +11 -1
- package/dist/server/api/routes/documents-publish.d.ts.map +1 -1
- package/dist/server/api/routes/documents-publish.js +145 -2
- package/dist/server/api/routes/jobs.d.ts +4 -0
- package/dist/server/api/routes/jobs.d.ts.map +1 -0
- package/dist/server/api/routes/jobs.js +94 -0
- package/dist/server/api/routes/resolve-created-by.d.ts +13 -0
- package/dist/server/api/routes/resolve-created-by.d.ts.map +1 -0
- package/dist/server/api/routes/resolve-created-by.js +30 -0
- package/dist/server/api/routes/workers-run.d.ts +4 -0
- package/dist/server/api/routes/workers-run.d.ts.map +1 -0
- package/dist/server/api/routes/workers-run.js +40 -0
- package/dist/server/index.d.ts +2 -0
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +3 -0
- package/dist/services/version-service.d.ts +19 -3
- package/dist/services/version-service.d.ts.map +1 -1
- package/dist/services/version-service.js +75 -69
- package/dist/type-gen.d.ts.map +1 -1
- package/dist/type-gen.js +11 -0
- package/dist/types/agent-change-sets.d.ts +70 -0
- package/dist/types/agent-change-sets.d.ts.map +1 -0
- package/dist/types/agent-change-sets.js +6 -0
- package/dist/types/agent-stream.d.ts +60 -0
- package/dist/types/agent-stream.d.ts.map +1 -0
- package/dist/types/agent-stream.js +11 -0
- package/dist/types/agent-tools.d.ts +65 -0
- package/dist/types/agent-tools.d.ts.map +1 -0
- package/dist/types/agent-tools.js +1 -0
- package/dist/types/config.d.ts +62 -0
- package/dist/types/config.d.ts.map +1 -1
- package/dist/types/document-workspace.d.ts +53 -0
- package/dist/types/document-workspace.d.ts.map +1 -0
- package/dist/types/document-workspace.js +14 -0
- package/dist/types/document.d.ts +5 -0
- package/dist/types/document.d.ts.map +1 -1
- package/dist/types/events.d.ts +134 -0
- package/dist/types/events.d.ts.map +1 -0
- package/dist/types/events.js +3 -0
- package/dist/types/index.d.ts +3 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +3 -0
- package/dist/types/schemas.js +1 -1
- package/dist/utils/fetch-remote-file.d.ts +11 -0
- package/dist/utils/fetch-remote-file.d.ts.map +1 -0
- package/dist/utils/fetch-remote-file.js +168 -0
- package/dist/utils/index.d.ts +1 -1
- package/dist/utils/index.d.ts.map +1 -1
- package/package.json +5 -1
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
import { setSaveStateContext } from '../../save-state-context.svelte';
|
|
15
15
|
import { usePermissions } from '../../permissions-context.svelte';
|
|
16
16
|
import AdminSlot from './AdminSlot.svelte';
|
|
17
|
+
import ScheduleDialog from './ScheduleDialog.svelte';
|
|
17
18
|
import { createPartResolver } from '../../plugins/resolver';
|
|
18
19
|
import type { CMSPlugin, DocumentActionProps } from '../../plugins/types';
|
|
19
20
|
import { getDefaultValueForFieldType } from '../../utils/field-defaults';
|
|
@@ -37,11 +38,19 @@
|
|
|
37
38
|
Smartphone,
|
|
38
39
|
ZoomIn,
|
|
39
40
|
ZoomOut,
|
|
40
|
-
ArrowLeft
|
|
41
|
+
ArrowLeft,
|
|
42
|
+
CalendarClock,
|
|
43
|
+
X,
|
|
44
|
+
Lock
|
|
41
45
|
} from '@lucide/svelte';
|
|
42
46
|
import { stegaEncodeDocument } from '../../preview/stega.js';
|
|
43
47
|
import { collectAssetRefs, injectAssetData, type ResolvedAsset } from '../../preview/assets.js';
|
|
44
48
|
import { setRichtextEditorRegistry } from '../../richtext-context.svelte.js';
|
|
49
|
+
import { documentWorkspaceRegistry } from '../../document-workspace-registry.svelte';
|
|
50
|
+
import type {
|
|
51
|
+
DocumentWorkspace,
|
|
52
|
+
DocumentWorkspaceOperation
|
|
53
|
+
} from '../../types/document-workspace';
|
|
45
54
|
|
|
46
55
|
interface Props {
|
|
47
56
|
schemas: SchemaType[];
|
|
@@ -68,6 +77,12 @@
|
|
|
68
77
|
createdAt?: string;
|
|
69
78
|
} | null;
|
|
70
79
|
isReadOnly?: boolean;
|
|
80
|
+
/** Suppresses the bottom action bar (Publish / Schedule / Unpublish / Delete).
|
|
81
|
+
* Set by the host when another editor is stacked on top of this one and owns
|
|
82
|
+
* the actions instead — two action bars in the same corner give no clue which
|
|
83
|
+
* document each one publishes. This hides the bar only; the document keeps
|
|
84
|
+
* auto-saving and its status stays visible in the header. */
|
|
85
|
+
hideActionBar?: boolean;
|
|
71
86
|
/** When true, the host has hidden side panels — show a Minimize toggle. */
|
|
72
87
|
focusMode?: boolean;
|
|
73
88
|
/** Toggle host-driven focus mode. Omit to hide the focus button entirely. */
|
|
@@ -105,6 +120,7 @@
|
|
|
105
120
|
onOpenVersionHistory,
|
|
106
121
|
externalVersionPreview = null,
|
|
107
122
|
isReadOnly = false,
|
|
123
|
+
hideActionBar = false,
|
|
108
124
|
focusMode = false,
|
|
109
125
|
onToggleFocus,
|
|
110
126
|
presentationMode = false,
|
|
@@ -160,6 +176,14 @@
|
|
|
160
176
|
let publishedData = $state<Record<string, any> | null>(null);
|
|
161
177
|
const isViewingPublished = $derived(perspective === 'published');
|
|
162
178
|
|
|
179
|
+
// The scheduled action follows the active perspective — the tab IS the intent:
|
|
180
|
+
// Draft tab → publish (send this draft live later); Published tab → unpublish (take it
|
|
181
|
+
// down later). No toggle in the dialog. The control is gated on the matching permission.
|
|
182
|
+
const scheduleAction = $derived<'publish' | 'unpublish'>(
|
|
183
|
+
perspective === 'published' ? 'unpublish' : 'publish'
|
|
184
|
+
);
|
|
185
|
+
const canScheduleNow = $derived(scheduleAction === 'publish' ? canPublishDoc : canUnpublishDoc);
|
|
186
|
+
|
|
163
187
|
// Plugin document actions applicable to this type. Capability-gated, with
|
|
164
188
|
// built-in privileged roles bypassing. Cheap to rebuild from the plugin list.
|
|
165
189
|
const pluginDocumentActions = $derived(
|
|
@@ -198,6 +222,80 @@
|
|
|
198
222
|
: null
|
|
199
223
|
);
|
|
200
224
|
|
|
225
|
+
// A live handle onto this document's editable state — the seam an external caller (today:
|
|
226
|
+
// the agent's content_patch_fields/content_save_draft bridge tools) plugs into instead of
|
|
227
|
+
// reaching into this component's internals directly. See types/document-workspace.ts for
|
|
228
|
+
// why this is shaped generically rather than as an AI-specific bridge.
|
|
229
|
+
const documentWorkspace: DocumentWorkspace = {
|
|
230
|
+
getSnapshot() {
|
|
231
|
+
return {
|
|
232
|
+
documentId: documentId ?? fullDocument?.id ?? null,
|
|
233
|
+
collection: documentType,
|
|
234
|
+
data: $state.snapshot(documentData),
|
|
235
|
+
status: !documentId
|
|
236
|
+
? 'new'
|
|
237
|
+
: fullDocument?._meta?.status === 'published'
|
|
238
|
+
? 'published'
|
|
239
|
+
: fullDocument?._meta?.status === 'unpublished'
|
|
240
|
+
? 'unpublished'
|
|
241
|
+
: 'draft',
|
|
242
|
+
revision: (fullDocument?._meta?.revision as number | undefined) ?? null
|
|
243
|
+
};
|
|
244
|
+
},
|
|
245
|
+
getSelection() {
|
|
246
|
+
return { fieldName: focusedFieldName };
|
|
247
|
+
},
|
|
248
|
+
apply(operation: DocumentWorkspaceOperation) {
|
|
249
|
+
if (operation.type === 'patchFields') {
|
|
250
|
+
documentData = { ...documentData, ...operation.fields };
|
|
251
|
+
hasUnsavedChanges = true;
|
|
252
|
+
}
|
|
253
|
+
},
|
|
254
|
+
async validate() {
|
|
255
|
+
const invalid = await validateAllFields();
|
|
256
|
+
return {
|
|
257
|
+
isValid: invalid.length === 0,
|
|
258
|
+
errors: invalid.map((f) => ({ field: f.name, errors: f.messages }))
|
|
259
|
+
};
|
|
260
|
+
},
|
|
261
|
+
async flushSave(_expectedRevision) {
|
|
262
|
+
return await saveDocument(false);
|
|
263
|
+
},
|
|
264
|
+
async publish(_expectedRevision) {
|
|
265
|
+
await publishDocument();
|
|
266
|
+
if (saveError) {
|
|
267
|
+
return { success: false, conflict: saveError.startsWith('Conflict'), error: saveError };
|
|
268
|
+
}
|
|
269
|
+
return {
|
|
270
|
+
success: true,
|
|
271
|
+
revision: (fullDocument?._meta?.revision as number | undefined) ?? undefined
|
|
272
|
+
};
|
|
273
|
+
},
|
|
274
|
+
beginBatch(_source) {
|
|
275
|
+
batchActive = true;
|
|
276
|
+
},
|
|
277
|
+
endBatch() {
|
|
278
|
+
batchActive = false;
|
|
279
|
+
}
|
|
280
|
+
};
|
|
281
|
+
|
|
282
|
+
// Registers/clears this document's workspace handle in the shared registry
|
|
283
|
+
// (document-workspace-registry.svelte.ts) whenever the active document id changes —
|
|
284
|
+
// covers create→save (id appears), navigating between two open documents, and unmount.
|
|
285
|
+
$effect(() => {
|
|
286
|
+
const activeId = documentId ?? fullDocument?.id ?? null;
|
|
287
|
+
if (activeId) {
|
|
288
|
+
documentWorkspaceRegistry.register({
|
|
289
|
+
documentId: activeId,
|
|
290
|
+
collection: documentType,
|
|
291
|
+
workspace: documentWorkspace
|
|
292
|
+
});
|
|
293
|
+
}
|
|
294
|
+
return () => {
|
|
295
|
+
if (activeId) documentWorkspaceRegistry.clear(activeId);
|
|
296
|
+
};
|
|
297
|
+
});
|
|
298
|
+
|
|
201
299
|
// Field-level access: mirrors the server's strip/drop logic so the form
|
|
202
300
|
// only shows fields the user can see and disables fields they can't write.
|
|
203
301
|
function fieldRoleAllowed(list: string[] | undefined): boolean {
|
|
@@ -299,7 +397,9 @@
|
|
|
299
397
|
type: 'aphex:data',
|
|
300
398
|
documentType,
|
|
301
399
|
documentId: documentId ?? undefined,
|
|
302
|
-
document: iframeStega
|
|
400
|
+
document: iframeStega
|
|
401
|
+
? stegaEncodeDocument(snapshot, schema?.fields ?? [], schemas)
|
|
402
|
+
: snapshot
|
|
303
403
|
},
|
|
304
404
|
'*'
|
|
305
405
|
);
|
|
@@ -620,6 +720,39 @@
|
|
|
620
720
|
return;
|
|
621
721
|
}
|
|
622
722
|
|
|
723
|
+
// 2a. Object array item — objectPath like "[0].heading" (or "[0]" alone). The
|
|
724
|
+
// item's fields live behind ObjectModal, so open that item's modal, then focus
|
|
725
|
+
// the subfield by the remaining dotted path (the modal renders subfields with
|
|
726
|
+
// bare data-field-path, e.g. "heading" or "seo.title").
|
|
727
|
+
if (objectPath) {
|
|
728
|
+
const itemMatch = objectPath.match(/^\[(\d+)\](?:\.(.*))?$/);
|
|
729
|
+
if (itemMatch) {
|
|
730
|
+
const itemIndex = Number(itemMatch[1]);
|
|
731
|
+
const subPath = itemMatch[2] ?? '';
|
|
732
|
+
const card = container.querySelector<HTMLElement>(`[data-array-item-index="${itemIndex}"]`);
|
|
733
|
+
if (card) {
|
|
734
|
+
card.click(); // opens the item's ObjectModal
|
|
735
|
+
if (subPath) {
|
|
736
|
+
// The modal mounts/animates in; poll a few frames for the subfield.
|
|
737
|
+
for (let attempt = 0; attempt < 20; attempt++) {
|
|
738
|
+
await tick();
|
|
739
|
+
const target = document.querySelector<HTMLElement>(`[data-field-path="${subPath}"]`);
|
|
740
|
+
if (target) {
|
|
741
|
+
target.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
|
|
742
|
+
const focusable = target.querySelector<HTMLElement>(
|
|
743
|
+
'input:not([disabled]):not([readonly]), textarea:not([disabled]):not([readonly])'
|
|
744
|
+
);
|
|
745
|
+
focusable?.focus();
|
|
746
|
+
break;
|
|
747
|
+
}
|
|
748
|
+
await new Promise((r) => requestAnimationFrame(r));
|
|
749
|
+
}
|
|
750
|
+
}
|
|
751
|
+
return;
|
|
752
|
+
}
|
|
753
|
+
}
|
|
754
|
+
}
|
|
755
|
+
|
|
623
756
|
// 2. Nested object subfield — find the subfield container by its dotted path
|
|
624
757
|
if (objectPath) {
|
|
625
758
|
const subContainer = container.querySelector<HTMLElement>(
|
|
@@ -635,7 +768,30 @@
|
|
|
635
768
|
}
|
|
636
769
|
}
|
|
637
770
|
|
|
638
|
-
//
|
|
771
|
+
// 3a. Object / reference array — reveal the Nth *row* rather than opening it.
|
|
772
|
+
// These rows are the drag-to-reorder handles, so surfacing the row in place is
|
|
773
|
+
// what lets an author act on it (reorder, remove, or click in themselves);
|
|
774
|
+
// auto-opening the row's editor would take that away and, for a reference row,
|
|
775
|
+
// navigate off the document entirely.
|
|
776
|
+
if (arrayIndex != null) {
|
|
777
|
+
const row = container.querySelector<HTMLElement>(`[data-array-index="${arrayIndex}"]`);
|
|
778
|
+
if (row) {
|
|
779
|
+
row.scrollIntoView({ behavior: 'smooth', block: 'center' });
|
|
780
|
+
// Animated directly rather than via `focusedFieldName` state: that ring is
|
|
781
|
+
// field-wide, and plumbing a per-row index down through SchemaField →
|
|
782
|
+
// ArrayField would add a prop to every array just for a 1.2s flash.
|
|
783
|
+
row.animate(
|
|
784
|
+
[
|
|
785
|
+
{ outline: '2px solid var(--primary)', outlineOffset: '3px', borderRadius: '6px' },
|
|
786
|
+
{ outline: '2px solid transparent', outlineOffset: '8px', borderRadius: '6px' }
|
|
787
|
+
],
|
|
788
|
+
{ duration: 1200, easing: 'ease-out', fill: 'none' }
|
|
789
|
+
);
|
|
790
|
+
return;
|
|
791
|
+
}
|
|
792
|
+
}
|
|
793
|
+
|
|
794
|
+
// 3b. Primitive array — focus the Nth input inside the array field
|
|
639
795
|
if (arrayIndex != null) {
|
|
640
796
|
const inputs = container.querySelectorAll<HTMLElement>(
|
|
641
797
|
'input:not([disabled]):not([readonly]), textarea:not([disabled]):not([readonly])'
|
|
@@ -706,6 +862,53 @@
|
|
|
706
862
|
|
|
707
863
|
// Header options dropdown
|
|
708
864
|
let showHeaderMenu = $state(false);
|
|
865
|
+
let showScheduleDialog = $state(false);
|
|
866
|
+
|
|
867
|
+
// Pending scheduled publish/unpublish for this document (replace semantics → at most one).
|
|
868
|
+
type ScheduledJob = { jobId: string; type: string; runAt: string; status: string };
|
|
869
|
+
let scheduledJobs = $state<ScheduledJob[]>([]);
|
|
870
|
+
// The soonest pending schedule — what the header indicator shows.
|
|
871
|
+
const nextSchedule = $derived(
|
|
872
|
+
[...scheduledJobs].sort(
|
|
873
|
+
(a, b) => new Date(a.runAt).getTime() - new Date(b.runAt).getTime()
|
|
874
|
+
)[0] ?? null
|
|
875
|
+
);
|
|
876
|
+
|
|
877
|
+
async function loadSchedule() {
|
|
878
|
+
if (!documentId) {
|
|
879
|
+
scheduledJobs = [];
|
|
880
|
+
return;
|
|
881
|
+
}
|
|
882
|
+
try {
|
|
883
|
+
const res = await documents.getSchedule(documentId);
|
|
884
|
+
scheduledJobs = res.success ? (res.data ?? []) : [];
|
|
885
|
+
} catch {
|
|
886
|
+
scheduledJobs = [];
|
|
887
|
+
}
|
|
888
|
+
}
|
|
889
|
+
|
|
890
|
+
// Optimistic: the schedule call returns the created job, so show the badge immediately.
|
|
891
|
+
// Replace semantics on the server mean this new job supersedes any prior one. Reconcile
|
|
892
|
+
// with a background fetch so we converge on server truth (id, exact runAt).
|
|
893
|
+
function onScheduleCreated(job: ScheduledJob) {
|
|
894
|
+
scheduledJobs = [job];
|
|
895
|
+
loadSchedule();
|
|
896
|
+
}
|
|
897
|
+
|
|
898
|
+
async function cancelSchedule() {
|
|
899
|
+
if (!documentId) return;
|
|
900
|
+
// Optimistically clear the badge; restore from the server if the cancel fails.
|
|
901
|
+
const previous = scheduledJobs;
|
|
902
|
+
scheduledJobs = [];
|
|
903
|
+
const res = await documents.cancelSchedule(documentId);
|
|
904
|
+
if (res.success) {
|
|
905
|
+
toast.success('Schedule cancelled');
|
|
906
|
+
loadSchedule();
|
|
907
|
+
} else {
|
|
908
|
+
scheduledJobs = previous;
|
|
909
|
+
toast.error(res.error || 'Failed to cancel schedule');
|
|
910
|
+
}
|
|
911
|
+
}
|
|
709
912
|
|
|
710
913
|
// Version history
|
|
711
914
|
let showVersionHistory = $state(false);
|
|
@@ -775,9 +978,40 @@
|
|
|
775
978
|
|
|
776
979
|
const savedAgoText = $derived(lastSaved ? `Saved ${timeAgo(lastSaved)}` : null);
|
|
777
980
|
|
|
981
|
+
// Relative future time for the scheduled-publish indicator ("in 3h"). Reads `now` so it ticks.
|
|
982
|
+
function timeUntil(date: Date): string {
|
|
983
|
+
const seconds = Math.floor((date.getTime() - now) / 1000);
|
|
984
|
+
if (seconds <= 0) return 'now';
|
|
985
|
+
if (seconds < 60) return `in ${seconds}s`;
|
|
986
|
+
const minutes = Math.floor(seconds / 60);
|
|
987
|
+
if (minutes < 60) return `in ${minutes}m`;
|
|
988
|
+
const hours = Math.floor(minutes / 60);
|
|
989
|
+
if (hours < 24) return `in ${hours}h`;
|
|
990
|
+
const days = Math.floor(hours / 24);
|
|
991
|
+
return `in ${days}d`;
|
|
992
|
+
}
|
|
993
|
+
|
|
994
|
+
// Human phrasing for the schedule banner: "today/tomorrow at 8:00 AM", "on Monday at …",
|
|
995
|
+
// or "on Nov 10 at …" further out. Reads `now` so it stays current.
|
|
996
|
+
function humanizeSchedule(date: Date): string {
|
|
997
|
+
const time = date.toLocaleTimeString(undefined, { hour: 'numeric', minute: '2-digit' });
|
|
998
|
+
const startOfDay = (x: Date) => new Date(x.getFullYear(), x.getMonth(), x.getDate()).getTime();
|
|
999
|
+
const days = Math.round((startOfDay(date) - startOfDay(new Date(now))) / 86_400_000);
|
|
1000
|
+
let day: string;
|
|
1001
|
+
if (days <= 0) day = 'today';
|
|
1002
|
+
else if (days === 1) day = 'tomorrow';
|
|
1003
|
+
else if (days < 7) day = `on ${date.toLocaleDateString(undefined, { weekday: 'long' })}`;
|
|
1004
|
+
else day = `on ${date.toLocaleDateString(undefined, { month: 'short', day: 'numeric' })}`;
|
|
1005
|
+
return `${day} at ${time}`;
|
|
1006
|
+
}
|
|
1007
|
+
|
|
778
1008
|
// Auto-save functionality (every 2 seconds when there are changes)
|
|
779
1009
|
let hasUnsavedChanges = $state(false);
|
|
780
1010
|
let autoSaveTimer: ReturnType<typeof setTimeout> | null = null;
|
|
1011
|
+
// Set while a `DocumentWorkspace` batch (currently: one agent turn) is applying a burst of
|
|
1012
|
+
// `apply()` patches — suppresses autosave so N patches don't produce N separate CAS writes;
|
|
1013
|
+
// the batch's caller is responsible for one explicit `flushSave` before/at `endBatch()`.
|
|
1014
|
+
let batchActive = $state(false);
|
|
781
1015
|
let hasValidationErrors = $state(false);
|
|
782
1016
|
// Snapshot of the default-initialized data for a brand-new (unsaved) document.
|
|
783
1017
|
// Used to detect real user edits without relying on "is the value truthy" heuristics,
|
|
@@ -817,6 +1051,14 @@
|
|
|
817
1051
|
(hasUnpublishedContent || isUnpublished) && !saving && documentId && !hasValidationErrors
|
|
818
1052
|
);
|
|
819
1053
|
|
|
1054
|
+
// The schedule button mirrors the inline action button's enabled state (permission is checked
|
|
1055
|
+
// separately, for visibility): scheduling a PUBLISH is enabled exactly when the Publish button
|
|
1056
|
+
// is (`canPublish` — there are unpublished, valid changes), so you can't queue a no-op publish;
|
|
1057
|
+
// scheduling an UNPUBLISH mirrors the Unpublish button (enabled whenever not mid-save).
|
|
1058
|
+
const canScheduleActionNow = $derived(
|
|
1059
|
+
scheduleAction === 'publish' ? Boolean(canPublish) : !saving
|
|
1060
|
+
);
|
|
1061
|
+
|
|
820
1062
|
// Get preview title based on schema config. When viewing in published
|
|
821
1063
|
// perspective, read from the loaded published snapshot — otherwise the
|
|
822
1064
|
// header shows the draft's title even though the body shows published
|
|
@@ -884,6 +1126,14 @@
|
|
|
884
1126
|
}
|
|
885
1127
|
});
|
|
886
1128
|
|
|
1129
|
+
// Keep the schedule indicator in sync with the current document.
|
|
1130
|
+
$effect(() => {
|
|
1131
|
+
// Reference documentId so this re-runs when the editor switches documents.
|
|
1132
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-expressions -- reactive dependency
|
|
1133
|
+
documentId;
|
|
1134
|
+
loadSchedule();
|
|
1135
|
+
});
|
|
1136
|
+
|
|
887
1137
|
// Load existing document data when editing
|
|
888
1138
|
$effect(() => {
|
|
889
1139
|
if (!isCreating && documentId) {
|
|
@@ -1084,7 +1334,7 @@
|
|
|
1084
1334
|
// Debounced auto-save. Comparing against the initial-defaults snapshot (for new
|
|
1085
1335
|
// docs) or the saved draft (for existing docs) means any real user edit triggers
|
|
1086
1336
|
// save — including unchecking a boolean or clearing a field.
|
|
1087
|
-
if (hasChanges && schema && canWriteCurrentDoc) {
|
|
1337
|
+
if (hasChanges && schema && canWriteCurrentDoc && !batchActive) {
|
|
1088
1338
|
autoSaveTimer = setTimeout(() => {
|
|
1089
1339
|
cmsLogger.debug(
|
|
1090
1340
|
'[Document Editor]',
|
|
@@ -1106,12 +1356,15 @@
|
|
|
1106
1356
|
};
|
|
1107
1357
|
});
|
|
1108
1358
|
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1359
|
+
/** The actual persist — no toasts, no side-effect UI updates, just the write + CAS-conflict
|
|
1360
|
+
* detection, returning a result `DocumentWorkspace.flushSave` can also consume directly.
|
|
1361
|
+
* `saveDocument` (below) is the UI-facing wrapper that adds toasts/state-sync around this. */
|
|
1362
|
+
async function performSave(): Promise<{
|
|
1363
|
+
success: boolean;
|
|
1364
|
+
revision?: number;
|
|
1365
|
+
conflict?: boolean;
|
|
1366
|
+
error?: string;
|
|
1367
|
+
}> {
|
|
1115
1368
|
try {
|
|
1116
1369
|
let response;
|
|
1117
1370
|
|
|
@@ -1142,12 +1395,15 @@
|
|
|
1142
1395
|
// Always call onSaved to switch to edit mode after creation
|
|
1143
1396
|
onSaved?.(response.data.id);
|
|
1144
1397
|
} else {
|
|
1145
|
-
|
|
1398
|
+
return { success: false, error: response?.error || 'Failed to create document' };
|
|
1146
1399
|
}
|
|
1147
1400
|
} else if (documentId) {
|
|
1148
|
-
// Update existing document
|
|
1401
|
+
// Update existing document. Send the revision we last read so a stale
|
|
1402
|
+
// write (another tab, an AI agent) surfaces as a 409 conflict below
|
|
1403
|
+
// instead of silently overwriting whatever changed in between.
|
|
1149
1404
|
response = await documents.updateById(documentId, {
|
|
1150
|
-
data: documentData
|
|
1405
|
+
data: documentData,
|
|
1406
|
+
expectedRevision: fullDocument?._meta?.revision as number | undefined
|
|
1151
1407
|
});
|
|
1152
1408
|
|
|
1153
1409
|
// Update fullDocument with the response to keep saved data in sync
|
|
@@ -1167,47 +1423,84 @@
|
|
|
1167
1423
|
}
|
|
1168
1424
|
|
|
1169
1425
|
if (response?.success) {
|
|
1170
|
-
|
|
1171
|
-
hasUnsavedChanges = false;
|
|
1172
|
-
if (response.data?.id) notifyDocumentChanged(response.data.id);
|
|
1173
|
-
if (presentationMode && iframeRef?.contentWindow) {
|
|
1174
|
-
iframeRef.contentWindow.postMessage({ type: 'aphex:refresh' }, '*');
|
|
1175
|
-
}
|
|
1176
|
-
if (isAutoSave) {
|
|
1177
|
-
// Trigger validation on all fields after auto-save
|
|
1178
|
-
validateAllFields(); // Update validation status
|
|
1179
|
-
schemaFields.forEach((fieldComponent, index) => {
|
|
1180
|
-
const field = schema?.fields[index];
|
|
1181
|
-
if (fieldComponent && field) {
|
|
1182
|
-
fieldComponent.performValidation(documentData[field.name], {});
|
|
1183
|
-
}
|
|
1184
|
-
}); // Notify parent of autosave with current title
|
|
1185
|
-
if (onAutoSaved && documentId) {
|
|
1186
|
-
onAutoSaved(documentId, getPreviewTitle());
|
|
1187
|
-
}
|
|
1188
|
-
}
|
|
1189
|
-
if (showVersionHistory) {
|
|
1190
|
-
loadVersions();
|
|
1191
|
-
}
|
|
1192
|
-
} else {
|
|
1193
|
-
throw new Error(response?.error || 'Failed to save document');
|
|
1426
|
+
return { success: true, revision: fullDocument?._meta?.revision as number | undefined };
|
|
1194
1427
|
}
|
|
1428
|
+
return { success: false, error: response?.error || 'Failed to save document' };
|
|
1195
1429
|
} catch (err) {
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
//
|
|
1430
|
+
// A 409 means someone else (another tab, an AI agent) saved this document
|
|
1431
|
+
// since we last read it — surface that distinctly rather than a generic
|
|
1432
|
+
// error, and never retry with a blind overwrite. The caller must reload to
|
|
1433
|
+
// see the other writer's change before saving again.
|
|
1434
|
+
if (err instanceof ApiError && err.status === 409) {
|
|
1435
|
+
return {
|
|
1436
|
+
success: false,
|
|
1437
|
+
conflict: true,
|
|
1438
|
+
error:
|
|
1439
|
+
'Conflict: this document was updated by someone else. Reload the page to continue editing.'
|
|
1440
|
+
};
|
|
1441
|
+
}
|
|
1199
1442
|
if (err instanceof ApiError && err.response?.validationErrors) {
|
|
1200
1443
|
const validationErrors = err.response.validationErrors;
|
|
1201
1444
|
const errorMessages = validationErrors
|
|
1202
1445
|
.map((ve: any) => `${ve.field}: ${ve.errors.join(', ')}`)
|
|
1203
1446
|
.join('; ');
|
|
1204
|
-
|
|
1447
|
+
return { success: false, error: `Validation failed: ${errorMessages}` };
|
|
1448
|
+
}
|
|
1449
|
+
return {
|
|
1450
|
+
success: false,
|
|
1451
|
+
error: err instanceof ApiError ? err.message : 'Failed to save document'
|
|
1452
|
+
};
|
|
1453
|
+
}
|
|
1454
|
+
}
|
|
1455
|
+
|
|
1456
|
+
async function saveDocument(isAutoSave = false) {
|
|
1457
|
+
if (saving)
|
|
1458
|
+
return { success: false, error: 'Already saving' } as {
|
|
1459
|
+
success: boolean;
|
|
1460
|
+
revision?: number;
|
|
1461
|
+
conflict?: boolean;
|
|
1462
|
+
error?: string;
|
|
1463
|
+
};
|
|
1464
|
+
|
|
1465
|
+
saving = true;
|
|
1466
|
+
saveError = null;
|
|
1467
|
+
|
|
1468
|
+
const result = await performSave();
|
|
1469
|
+
|
|
1470
|
+
if (result.success) {
|
|
1471
|
+
lastSaved = new Date();
|
|
1472
|
+
hasUnsavedChanges = false;
|
|
1473
|
+
if (fullDocument?.id) notifyDocumentChanged(fullDocument.id);
|
|
1474
|
+
if (presentationMode && iframeRef?.contentWindow) {
|
|
1475
|
+
iframeRef.contentWindow.postMessage({ type: 'aphex:refresh' }, '*');
|
|
1476
|
+
}
|
|
1477
|
+
if (isAutoSave) {
|
|
1478
|
+
// Trigger validation on all fields after auto-save
|
|
1479
|
+
validateAllFields(); // Update validation status
|
|
1480
|
+
schemaFields.forEach((fieldComponent, index) => {
|
|
1481
|
+
const field = schema?.fields[index];
|
|
1482
|
+
if (fieldComponent && field) {
|
|
1483
|
+
fieldComponent.performValidation(documentData[field.name], {});
|
|
1484
|
+
}
|
|
1485
|
+
}); // Notify parent of autosave with current title
|
|
1486
|
+
if (onAutoSaved && documentId) {
|
|
1487
|
+
onAutoSaved(documentId, getPreviewTitle());
|
|
1488
|
+
}
|
|
1489
|
+
}
|
|
1490
|
+
if (showVersionHistory) {
|
|
1491
|
+
loadVersions();
|
|
1492
|
+
}
|
|
1493
|
+
} else {
|
|
1494
|
+
if (result.conflict) {
|
|
1495
|
+
toast.error('This document was changed elsewhere. Reload to see the latest version.');
|
|
1205
1496
|
} else {
|
|
1206
|
-
|
|
1497
|
+
toast.error(result.error ?? 'Failed to save document');
|
|
1207
1498
|
}
|
|
1208
|
-
|
|
1209
|
-
saving = false;
|
|
1499
|
+
saveError = result.error ?? 'Failed to save document';
|
|
1210
1500
|
}
|
|
1501
|
+
|
|
1502
|
+
saving = false;
|
|
1503
|
+
return result;
|
|
1211
1504
|
}
|
|
1212
1505
|
|
|
1213
1506
|
async function publishDocument() {
|
|
@@ -1287,7 +1580,9 @@
|
|
|
1287
1580
|
saveError = null;
|
|
1288
1581
|
|
|
1289
1582
|
try {
|
|
1290
|
-
const response = await documents.publish(documentId
|
|
1583
|
+
const response = await documents.publish(documentId, {
|
|
1584
|
+
expectedRevision: fullDocument?._meta?.revision as number | undefined
|
|
1585
|
+
});
|
|
1291
1586
|
|
|
1292
1587
|
if (response.success && response.data) {
|
|
1293
1588
|
// Update local state with new published hash. Sync documentData from
|
|
@@ -1315,17 +1610,23 @@
|
|
|
1315
1610
|
throw new Error(response.error || 'Failed to publish document');
|
|
1316
1611
|
}
|
|
1317
1612
|
} catch (err) {
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
const validationErrors = err.response.validationErrors;
|
|
1323
|
-
const errorMessages = validationErrors
|
|
1324
|
-
.map((ve: any) => `${ve.field}: ${ve.errors.join(', ')}`)
|
|
1325
|
-
.join('; ');
|
|
1326
|
-
saveError = `Cannot publish - Validation failed: ${errorMessages}`;
|
|
1613
|
+
if (err instanceof ApiError && err.status === 409) {
|
|
1614
|
+
toast.error('This document was changed elsewhere. Reload to see the latest version.');
|
|
1615
|
+
saveError =
|
|
1616
|
+
'Conflict: this document was updated by someone else. Reload the page to continue editing.';
|
|
1327
1617
|
} else {
|
|
1328
|
-
|
|
1618
|
+
toast.error(err instanceof ApiError ? err.message : 'Failed to publish document');
|
|
1619
|
+
|
|
1620
|
+
// Extract validation errors if present
|
|
1621
|
+
if (err instanceof ApiError && err.response?.validationErrors) {
|
|
1622
|
+
const validationErrors = err.response.validationErrors;
|
|
1623
|
+
const errorMessages = validationErrors
|
|
1624
|
+
.map((ve: any) => `${ve.field}: ${ve.errors.join(', ')}`)
|
|
1625
|
+
.join('; ');
|
|
1626
|
+
saveError = `Cannot publish - Validation failed: ${errorMessages}`;
|
|
1627
|
+
} else {
|
|
1628
|
+
saveError = err instanceof ApiError ? err.message : 'Failed to publish document';
|
|
1629
|
+
}
|
|
1329
1630
|
}
|
|
1330
1631
|
} finally {
|
|
1331
1632
|
saving = false;
|
|
@@ -1388,7 +1689,9 @@
|
|
|
1388
1689
|
saveError = null;
|
|
1389
1690
|
|
|
1390
1691
|
try {
|
|
1391
|
-
const response = await documents.unpublish(documentId
|
|
1692
|
+
const response = await documents.unpublish(documentId, {
|
|
1693
|
+
expectedRevision: fullDocument?._meta?.revision as number | undefined
|
|
1694
|
+
});
|
|
1392
1695
|
if (response.success) {
|
|
1393
1696
|
fullDocument = {
|
|
1394
1697
|
...fullDocument,
|
|
@@ -1403,7 +1706,11 @@
|
|
|
1403
1706
|
throw new Error(response.error || 'Failed to unpublish');
|
|
1404
1707
|
}
|
|
1405
1708
|
} catch (err) {
|
|
1406
|
-
|
|
1709
|
+
if (err instanceof ApiError && err.status === 409) {
|
|
1710
|
+
toast.error('This document was changed elsewhere. Reload to see the latest version.');
|
|
1711
|
+
} else {
|
|
1712
|
+
toast.error(err instanceof ApiError ? err.message : 'Failed to unpublish document');
|
|
1713
|
+
}
|
|
1407
1714
|
} finally {
|
|
1408
1715
|
saving = false;
|
|
1409
1716
|
}
|
|
@@ -1775,6 +2082,41 @@
|
|
|
1775
2082
|
{/if}
|
|
1776
2083
|
|
|
1777
2084
|
<div class="relative flex h-full w-full min-w-0 flex-col overflow-hidden">
|
|
2085
|
+
<!-- Scheduled publish/unpublish banner — a full-width strip pinned to the very top edge of
|
|
2086
|
+
the editor, above the hero header (breadcrumb + actions), so a pending schedule is the
|
|
2087
|
+
first thing seen. Inner padding matches the hero's (px-4 lg:px-6) so its text lines up
|
|
2088
|
+
with the title below. -->
|
|
2089
|
+
{#if !presentationMode && nextSchedule}
|
|
2090
|
+
{@const isPub = nextSchedule.type === 'document.publish'}
|
|
2091
|
+
{@const runAtDate = new Date(nextSchedule.runAt)}
|
|
2092
|
+
<div
|
|
2093
|
+
class="border-primary/15 bg-primary/5 text-primary flex w-full flex-wrap items-center gap-x-2 gap-y-1 border-b px-4 py-2.5 lg:px-6"
|
|
2094
|
+
>
|
|
2095
|
+
<Lock class="h-4 w-4 shrink-0" />
|
|
2096
|
+
<span class="min-w-0 text-[0.9375rem] leading-tight font-medium">
|
|
2097
|
+
Scheduled to be {isPub ? 'published' : 'unpublished'}
|
|
2098
|
+
{humanizeSchedule(runAtDate)}
|
|
2099
|
+
<span class="text-primary/50 font-normal">· {timeUntil(runAtDate)}</span>
|
|
2100
|
+
</span>
|
|
2101
|
+
<div class="ml-auto flex items-center gap-1">
|
|
2102
|
+
<button
|
|
2103
|
+
type="button"
|
|
2104
|
+
class="hover:bg-primary/10 rounded px-2 py-1 text-xs font-medium transition-colors"
|
|
2105
|
+
onclick={() => (showScheduleDialog = true)}
|
|
2106
|
+
>
|
|
2107
|
+
Reschedule
|
|
2108
|
+
</button>
|
|
2109
|
+
<button
|
|
2110
|
+
type="button"
|
|
2111
|
+
class="hover:bg-primary/10 flex items-center gap-1 rounded px-2 py-1 text-xs font-medium transition-colors"
|
|
2112
|
+
onclick={cancelSchedule}
|
|
2113
|
+
>
|
|
2114
|
+
<X class="h-3 w-3" /> Cancel
|
|
2115
|
+
</button>
|
|
2116
|
+
</div>
|
|
2117
|
+
</div>
|
|
2118
|
+
{/if}
|
|
2119
|
+
|
|
1778
2120
|
<!-- Hero Header -->
|
|
1779
2121
|
{#if !presentationMode}
|
|
1780
2122
|
<div class="bg-background w-full min-w-0 overflow-x-clip px-4 pt-4 pb-5 lg:px-6 lg:pt-5">
|
|
@@ -1795,7 +2137,7 @@
|
|
|
1795
2137
|
<!-- Always one line (`truncate`); font shrinks where space is tight (narrow
|
|
1796
2138
|
editor / reference panel) so more of the title fits before the ellipsis,
|
|
1797
2139
|
and stays large on wide screens. -->
|
|
1798
|
-
<h1 class="block w-full min-w-0 truncate text-
|
|
2140
|
+
<h1 class="block w-full min-w-0 truncate text-2xl font-semibold tracking-tight lg:text-4xl">
|
|
1799
2141
|
{getPreviewTitle()}
|
|
1800
2142
|
</h1>
|
|
1801
2143
|
|
|
@@ -2205,7 +2547,7 @@
|
|
|
2205
2547
|
</div>
|
|
2206
2548
|
|
|
2207
2549
|
<!-- Sanity-style bottom bar -->
|
|
2208
|
-
{#if documentId}
|
|
2550
|
+
{#if documentId && !hideActionBar}
|
|
2209
2551
|
<div class="border-rule bg-background relative z-50 border-t p-4">
|
|
2210
2552
|
{#if isPreviewingVersion && activePreview}
|
|
2211
2553
|
<!-- Version preview footer -->
|
|
@@ -2221,7 +2563,9 @@
|
|
|
2221
2563
|
onclick={async () => {
|
|
2222
2564
|
if (!documentId || !activePreview) return;
|
|
2223
2565
|
try {
|
|
2224
|
-
await documents.restoreVersion(documentId, activePreview.versionNumber
|
|
2566
|
+
await documents.restoreVersion(documentId, activePreview.versionNumber, {
|
|
2567
|
+
expectedRevision: fullDocument?._meta?.revision as number | undefined
|
|
2568
|
+
});
|
|
2225
2569
|
const docRes = await documents.getById(documentId);
|
|
2226
2570
|
if (docRes.success && docRes.data) {
|
|
2227
2571
|
const doc = docRes.data as Record<string, any>;
|
|
@@ -2245,8 +2589,14 @@
|
|
|
2245
2589
|
if (onRestored && documentId) {
|
|
2246
2590
|
onRestored(documentId);
|
|
2247
2591
|
}
|
|
2248
|
-
} catch {
|
|
2249
|
-
|
|
2592
|
+
} catch (err) {
|
|
2593
|
+
if (err instanceof ApiError && err.status === 409) {
|
|
2594
|
+
toast.error(
|
|
2595
|
+
'This document was changed elsewhere. Reload to see the latest version.'
|
|
2596
|
+
);
|
|
2597
|
+
} else {
|
|
2598
|
+
toast.error('Failed to restore revision');
|
|
2599
|
+
}
|
|
2250
2600
|
}
|
|
2251
2601
|
}}
|
|
2252
2602
|
>
|
|
@@ -2272,15 +2622,37 @@
|
|
|
2272
2622
|
: 'Unknown'}
|
|
2273
2623
|
{/if}
|
|
2274
2624
|
</p>
|
|
2275
|
-
|
|
2276
|
-
{#if
|
|
2277
|
-
<Button
|
|
2625
|
+
<div class="flex items-center gap-2">
|
|
2626
|
+
{#if documentId && canScheduleNow}
|
|
2627
|
+
<Button
|
|
2628
|
+
variant="ghost"
|
|
2629
|
+
size="icon"
|
|
2630
|
+
disabled={!canScheduleActionNow}
|
|
2631
|
+
onclick={() => (showScheduleDialog = true)}
|
|
2632
|
+
class="h-8 w-8 {canScheduleActionNow ? 'cursor-pointer' : ''} {nextSchedule
|
|
2633
|
+
? 'text-primary'
|
|
2634
|
+
: ''}"
|
|
2635
|
+
title={!canScheduleActionNow
|
|
2636
|
+
? 'Nothing to publish — make a change first'
|
|
2637
|
+
: nextSchedule
|
|
2638
|
+
? 'Reschedule'
|
|
2639
|
+
: scheduleAction === 'publish'
|
|
2640
|
+
? 'Schedule publish'
|
|
2641
|
+
: 'Schedule unpublish'}
|
|
2642
|
+
>
|
|
2643
|
+
<CalendarClock class="h-4 w-4" />
|
|
2644
|
+
</Button>
|
|
2278
2645
|
{/if}
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
2646
|
+
{#if fullDocument?._meta?.status === 'unpublished'}
|
|
2647
|
+
{#if canPublishDoc}
|
|
2648
|
+
<Button size="sm" onclick={publishDocument} disabled={saving}>Publish</Button>
|
|
2649
|
+
{/if}
|
|
2650
|
+
{:else if canUnpublishDoc}
|
|
2651
|
+
<Button size="sm" variant="secondary" onclick={unpublishDocument} disabled={saving}>
|
|
2652
|
+
Unpublish
|
|
2653
|
+
</Button>
|
|
2654
|
+
{/if}
|
|
2655
|
+
</div>
|
|
2284
2656
|
</div>
|
|
2285
2657
|
{:else}
|
|
2286
2658
|
<div class="flex items-center justify-between">
|
|
@@ -2293,6 +2665,24 @@
|
|
|
2293
2665
|
|
|
2294
2666
|
<!-- Right: Publish button + horizontal three dots menu -->
|
|
2295
2667
|
<div class="flex items-center gap-2">
|
|
2668
|
+
{#if documentId && canScheduleNow}
|
|
2669
|
+
<Button
|
|
2670
|
+
variant="ghost"
|
|
2671
|
+
size="icon"
|
|
2672
|
+
disabled={!canScheduleActionNow}
|
|
2673
|
+
onclick={() => (showScheduleDialog = true)}
|
|
2674
|
+
class="h-8 w-8 {canScheduleActionNow ? 'cursor-pointer' : ''} {nextSchedule
|
|
2675
|
+
? 'text-primary'
|
|
2676
|
+
: ''}"
|
|
2677
|
+
title={!canScheduleActionNow
|
|
2678
|
+
? 'Nothing to publish — make a change first'
|
|
2679
|
+
: nextSchedule
|
|
2680
|
+
? 'Reschedule'
|
|
2681
|
+
: 'Schedule publish'}
|
|
2682
|
+
>
|
|
2683
|
+
<CalendarClock class="h-4 w-4" />
|
|
2684
|
+
</Button>
|
|
2685
|
+
{/if}
|
|
2296
2686
|
{#if canPublishDoc && !isViewingPublished}
|
|
2297
2687
|
<Button
|
|
2298
2688
|
onclick={publishDocument}
|
|
@@ -2428,6 +2818,15 @@
|
|
|
2428
2818
|
{/if}
|
|
2429
2819
|
|
|
2430
2820
|
<!-- Inspect Modal -->
|
|
2821
|
+
{#if documentId}
|
|
2822
|
+
<ScheduleDialog
|
|
2823
|
+
bind:open={showScheduleDialog}
|
|
2824
|
+
{documentId}
|
|
2825
|
+
action={scheduleAction}
|
|
2826
|
+
onScheduled={onScheduleCreated}
|
|
2827
|
+
/>
|
|
2828
|
+
{/if}
|
|
2829
|
+
|
|
2431
2830
|
{#if showInspect}
|
|
2432
2831
|
<div class="absolute inset-0 z-50 flex items-center justify-center bg-black/50">
|
|
2433
2832
|
<div
|