@revealui/core 0.2.1 → 0.3.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/api/compression.d.ts.map +1 -1
- package/dist/api/payload-optimization.d.ts.map +1 -1
- package/dist/api/rate-limit.d.ts +29 -28
- package/dist/api/rate-limit.d.ts.map +1 -1
- package/dist/api/rate-limit.js +63 -3
- package/dist/api/response-cache.d.ts.map +1 -1
- package/dist/api/response-cache.js +1 -1
- package/dist/api/rest.d.ts.map +1 -1
- package/dist/api/rest.js +3 -2
- package/dist/auth/access.d.ts.map +1 -1
- package/dist/auth/index.d.ts.map +1 -1
- package/dist/cache/query-cache.d.ts +12 -10
- package/dist/cache/query-cache.d.ts.map +1 -1
- package/dist/cache/query-cache.js +38 -42
- package/dist/caching/app-cache.d.ts +5 -0
- package/dist/caching/app-cache.d.ts.map +1 -1
- package/dist/caching/app-cache.js +9 -1
- package/dist/caching/cdn-config.d.ts.map +1 -1
- package/dist/caching/cdn-config.js +4 -0
- package/dist/caching/edge-cache.d.ts +1 -1
- package/dist/caching/edge-cache.d.ts.map +1 -1
- package/dist/caching/edge-cache.js +36 -7
- package/dist/caching/index.d.ts +6 -0
- package/dist/caching/index.d.ts.map +1 -0
- package/dist/caching/index.js +5 -0
- package/dist/caching/service-worker.d.ts +6 -3
- package/dist/caching/service-worker.d.ts.map +1 -1
- package/dist/caching/service-worker.js +3 -2
- package/dist/client/admin/RichText.d.ts +1 -1
- package/dist/client/admin/RichText.d.ts.map +1 -1
- package/dist/client/admin/components/AdminDashboard.d.ts.map +1 -1
- package/dist/client/admin/components/AdminDashboard.js +178 -205
- package/dist/client/admin/components/CollectionList.d.ts.map +1 -1
- package/dist/client/admin/components/DocumentForm.d.ts.map +1 -1
- package/dist/client/admin/components/DocumentForm.js +130 -6
- package/dist/client/admin/components/GlobalForm.d.ts.map +1 -1
- package/dist/client/admin/context/ServerFunctionContext.d.ts +8 -0
- package/dist/client/admin/context/ServerFunctionContext.d.ts.map +1 -0
- package/dist/client/admin/context/ServerFunctionContext.js +15 -0
- package/dist/client/admin/i18n/en.d.ts.map +1 -1
- package/dist/client/admin/index.d.ts +1 -0
- package/dist/client/admin/index.d.ts.map +1 -1
- package/dist/client/admin/index.js +1 -0
- package/dist/client/admin/layout.d.ts +1 -1
- package/dist/client/admin/layout.d.ts.map +1 -1
- package/dist/client/admin/layout.js +3 -2
- package/dist/client/admin/page.d.ts.map +1 -1
- package/dist/client/admin/utils/apiClient.d.ts.map +1 -1
- package/dist/client/admin/utils/apiClient.js +0 -4
- package/dist/client/admin/utils/index.d.ts +0 -1
- package/dist/client/admin/utils/index.d.ts.map +1 -1
- package/dist/client/admin/utils/index.js +0 -1
- package/dist/client/admin/utils/serializeConfig.d.ts.map +1 -1
- package/dist/client/hooks.d.ts.map +1 -1
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/richtext/RichTextEditor.d.ts.map +1 -1
- package/dist/client/richtext/components/ImageNodeComponent.d.ts.map +1 -1
- package/dist/client/richtext/components/ImageNodeComponent.js +0 -1
- package/dist/client/richtext/components/ImageUploadButton.d.ts +2 -0
- package/dist/client/richtext/components/ImageUploadButton.d.ts.map +1 -1
- package/dist/client/richtext/components/ImageUploadButton.js +30 -15
- package/dist/client/richtext/index.d.ts.map +1 -1
- package/dist/client/richtext/nodes/DecoratorBlockNode.d.ts.map +1 -1
- package/dist/client/richtext/nodes/ImageNode.d.ts.map +1 -1
- package/dist/client/richtext/plugins/CollaborationPlugin.d.ts.map +1 -1
- package/dist/client/richtext/plugins/CursorsOverlayPlugin.d.ts.map +1 -1
- package/dist/client/richtext/plugins/FloatingToolbarPlugin.d.ts.map +1 -1
- package/dist/client/richtext/plugins/ImagePlugin.d.ts.map +1 -1
- package/dist/client/richtext/plugins/ToolbarPlugin.d.ts.map +1 -1
- package/dist/client/ui/index.d.ts.map +1 -1
- package/dist/client/ui/index.js +1 -1
- package/dist/collections/CollectionOperations.d.ts +7 -7
- package/dist/collections/CollectionOperations.d.ts.map +1 -1
- package/dist/collections/CollectionOperations.js +15 -1
- package/dist/collections/hooks.d.ts.map +1 -1
- package/dist/collections/index.d.ts.map +1 -1
- package/dist/collections/operations/create.d.ts +2 -4
- package/dist/collections/operations/create.d.ts.map +1 -1
- package/dist/collections/operations/create.js +7 -5
- package/dist/collections/operations/createMany.d.ts +12 -0
- package/dist/collections/operations/createMany.d.ts.map +1 -0
- package/dist/collections/operations/createMany.js +43 -0
- package/dist/collections/operations/delete.d.ts +1 -1
- package/dist/collections/operations/delete.d.ts.map +1 -1
- package/dist/collections/operations/delete.js +31 -2
- package/dist/collections/operations/deleteMany.d.ts +11 -0
- package/dist/collections/operations/deleteMany.d.ts.map +1 -0
- package/dist/collections/operations/deleteMany.js +50 -0
- package/dist/collections/operations/fieldHooks.d.ts +2 -2
- package/dist/collections/operations/fieldHooks.d.ts.map +1 -1
- package/dist/collections/operations/fieldHooks.js +4 -4
- package/dist/collections/operations/find.d.ts +2 -4
- package/dist/collections/operations/find.d.ts.map +1 -1
- package/dist/collections/operations/find.js +115 -8
- package/dist/collections/operations/findById.d.ts +3 -4
- package/dist/collections/operations/findById.d.ts.map +1 -1
- package/dist/collections/operations/findById.js +53 -1
- package/dist/collections/operations/sqlAdapter.d.ts +23 -0
- package/dist/collections/operations/sqlAdapter.d.ts.map +1 -0
- package/dist/collections/operations/sqlAdapter.js +76 -0
- package/dist/collections/operations/update.d.ts +3 -5
- package/dist/collections/operations/update.d.ts.map +1 -1
- package/dist/collections/operations/update.js +103 -11
- package/dist/collections/operations/updateMany.d.ts +11 -0
- package/dist/collections/operations/updateMany.d.ts.map +1 -0
- package/dist/collections/operations/updateMany.js +52 -0
- package/dist/collections/registry.d.ts +12 -0
- package/dist/collections/registry.d.ts.map +1 -0
- package/dist/collections/registry.js +38 -0
- package/dist/config/index.d.ts.map +1 -1
- package/dist/config/runtime.d.ts.map +1 -1
- package/dist/config/utils.d.ts +0 -10
- package/dist/config/utils.d.ts.map +1 -1
- package/dist/config/utils.js +0 -13
- package/dist/database/index.d.ts +3 -0
- package/dist/database/index.d.ts.map +1 -1
- package/dist/database/index.js +1 -5
- package/dist/database/safe-parse.d.ts.map +1 -1
- package/dist/database/ssl-config.d.ts.map +1 -1
- package/dist/database/type-adapter.d.ts.map +1 -1
- package/dist/database/universal-postgres.d.ts.map +1 -1
- package/dist/database/universal-postgres.js +6 -1
- package/dist/dataloader.d.ts.map +1 -1
- package/dist/error-handling/circuit-breaker.d.ts +1 -1
- package/dist/error-handling/circuit-breaker.d.ts.map +1 -1
- package/dist/error-handling/circuit-breaker.js +11 -3
- package/dist/error-handling/error-boundary.d.ts.map +1 -1
- package/dist/error-handling/error-reporter.d.ts +1 -1
- package/dist/error-handling/error-reporter.d.ts.map +1 -1
- package/dist/error-handling/error-reporter.js +19 -5
- package/dist/error-handling/fallback-components.d.ts.map +1 -1
- package/dist/error-handling/fallback-components.js +1 -1
- package/dist/error-handling/index.d.ts +2 -4
- package/dist/error-handling/index.d.ts.map +1 -1
- package/dist/error-handling/index.js +1 -4
- package/dist/error-handling/retry.d.ts.map +1 -1
- package/dist/error-handling/retry.js +13 -8
- package/dist/factories/builders.d.ts.map +1 -1
- package/dist/factories/index.d.ts.map +1 -1
- package/dist/features.d.ts +0 -4
- package/dist/features.d.ts.map +1 -1
- package/dist/features.js +0 -2
- package/dist/fieldTraversal.d.ts.map +1 -1
- package/dist/fields/config/types.d.ts.map +1 -1
- package/dist/fields/getDefaultValue.d.ts.map +1 -1
- package/dist/fields/getFieldPaths.d.ts.map +1 -1
- package/dist/fields/hooks/afterRead/index.d.ts.map +1 -1
- package/dist/fields/hooks/afterRead/promise.d.ts.map +1 -1
- package/dist/fields/hooks/afterRead/traverseFields.d.ts.map +1 -1
- package/dist/generated/types/cms.d.ts.map +1 -1
- package/dist/generated/types/cms.js +0 -1
- package/dist/generated/types/neon.d.ts.map +1 -1
- package/dist/generated/types/neon.js +4 -2
- package/dist/globals/GlobalOperations.d.ts.map +1 -1
- package/dist/globals/GlobalOperations.js +4 -2
- package/dist/globals/index.d.ts.map +1 -1
- package/dist/index.d.ts +4 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -4
- package/dist/instance/RevealUIInstance.d.ts.map +1 -1
- package/dist/instance/RevealUIInstance.js +6 -19
- package/dist/instance/index.d.ts.map +1 -1
- package/dist/instance/logger.d.ts.map +1 -1
- package/dist/instance/methods/create.d.ts.map +1 -1
- package/dist/instance/methods/create.js +0 -3
- package/dist/instance/methods/delete.d.ts.map +1 -1
- package/dist/instance/methods/delete.js +1 -4
- package/dist/instance/methods/find.d.ts.map +1 -1
- package/dist/instance/methods/find.js +0 -3
- package/dist/instance/methods/findById.d.ts.map +1 -1
- package/dist/instance/methods/findById.js +0 -3
- package/dist/instance/methods/hooks.d.ts.map +1 -1
- package/dist/instance/methods/update.d.ts.map +1 -1
- package/dist/instance/methods/update.js +0 -3
- package/dist/jobs/index.d.ts +16 -0
- package/dist/jobs/index.d.ts.map +1 -0
- package/dist/jobs/index.js +14 -0
- package/dist/jobs/queue.d.ts +57 -0
- package/dist/jobs/queue.d.ts.map +1 -0
- package/dist/jobs/queue.js +134 -0
- package/dist/license-encryption.d.ts +21 -0
- package/dist/license-encryption.d.ts.map +1 -0
- package/dist/license-encryption.js +74 -0
- package/dist/license.d.ts +20 -3
- package/dist/license.d.ts.map +1 -1
- package/dist/license.js +73 -6
- package/dist/monitoring/alerts.d.ts.map +1 -1
- package/dist/monitoring/cleanup-manager.d.ts.map +1 -1
- package/dist/monitoring/health-monitor.d.ts.map +1 -1
- package/dist/monitoring/index.d.ts.map +1 -1
- package/dist/monitoring/process-registry.d.ts.map +1 -1
- package/dist/monitoring/query-monitor.d.ts.map +1 -1
- package/dist/monitoring/types.d.ts.map +1 -1
- package/dist/monitoring/zombie-detector.d.ts.map +1 -1
- package/dist/monitoring/zombie-detector.js +5 -0
- package/dist/nextjs/index.d.ts.map +1 -1
- package/dist/nextjs/utilities.d.ts.map +1 -1
- package/dist/nextjs/withRevealUI.d.ts.map +1 -1
- package/dist/observability/alerts.d.ts.map +1 -1
- package/dist/observability/alerts.js +1 -2
- package/dist/observability/health-check.d.ts +0 -4
- package/dist/observability/health-check.d.ts.map +1 -1
- package/dist/observability/health-check.js +0 -36
- package/dist/observability/index.d.ts.map +1 -1
- package/dist/observability/logger.d.ts.map +1 -1
- package/dist/observability/logger.js +1 -1
- package/dist/observability/metrics.d.ts.map +1 -1
- package/dist/observability/tracing.d.ts.map +1 -1
- package/dist/observability/tracing.js +0 -1
- package/dist/optimization/asset-optimizer.d.ts +6 -2
- package/dist/optimization/asset-optimizer.d.ts.map +1 -1
- package/dist/optimization/asset-optimizer.js +31 -7
- package/dist/optimization/bundle-analyzer.d.ts +1 -1
- package/dist/optimization/bundle-analyzer.d.ts.map +1 -1
- package/dist/optimization/bundle-analyzer.js +29 -5
- package/dist/optimization/code-splitting.d.ts +0 -10
- package/dist/optimization/code-splitting.d.ts.map +1 -1
- package/dist/optimization/code-splitting.js +0 -16
- package/dist/plugins/form-builder.d.ts.map +1 -1
- package/dist/plugins/index.d.ts.map +1 -1
- package/dist/plugins/nested-docs.d.ts +4 -0
- package/dist/plugins/nested-docs.d.ts.map +1 -1
- package/dist/plugins/nested-docs.js +50 -5
- package/dist/plugins/redirects.d.ts.map +1 -1
- package/dist/queries/index.d.ts.map +1 -1
- package/dist/queries/queryBuilder.d.ts.map +1 -1
- package/dist/queries/queryBuilder.js +9 -2
- package/dist/relationships/analyzer.d.ts.map +1 -1
- package/dist/relationships/analyzer.js +8 -0
- package/dist/relationships/index.d.ts.map +1 -1
- package/dist/relationships/populate-core.d.ts +57 -0
- package/dist/relationships/populate-core.d.ts.map +1 -0
- package/dist/relationships/populate-core.js +116 -0
- package/dist/relationships/populate-helpers.d.ts +5 -51
- package/dist/relationships/populate-helpers.d.ts.map +1 -1
- package/dist/relationships/populate-helpers.js +4 -109
- package/dist/relationships/population.d.ts +1 -9
- package/dist/relationships/population.d.ts.map +1 -1
- package/dist/relationships/population.js +8 -3
- package/dist/revealui.d.ts.map +1 -1
- package/dist/richtext/exports/client/rcc.d.ts.map +1 -1
- package/dist/richtext/exports/client/rcc.js +1 -1
- package/dist/richtext/exports/server/rsc.d.ts +17 -0
- package/dist/richtext/exports/server/rsc.d.ts.map +1 -1
- package/dist/richtext/exports/server/rsc.js +61 -5
- package/dist/richtext/index.d.ts.map +1 -1
- package/dist/richtext/lexical.d.ts.map +1 -1
- package/dist/security/audit.d.ts +1 -1
- package/dist/security/audit.d.ts.map +1 -1
- package/dist/security/audit.js +4 -2
- package/dist/security/auth.d.ts +29 -160
- package/dist/security/auth.d.ts.map +1 -1
- package/dist/security/auth.js +148 -367
- package/dist/security/authorization.d.ts +7 -31
- package/dist/security/authorization.d.ts.map +1 -1
- package/dist/security/authorization.js +72 -14
- package/dist/security/encryption.d.ts +56 -44
- package/dist/security/encryption.d.ts.map +1 -1
- package/dist/security/encryption.js +113 -96
- package/dist/security/gdpr-storage.d.ts +102 -0
- package/dist/security/gdpr-storage.d.ts.map +1 -0
- package/dist/security/gdpr-storage.js +65 -0
- package/dist/security/gdpr.d.ts +57 -37
- package/dist/security/gdpr.d.ts.map +1 -1
- package/dist/security/gdpr.js +155 -89
- package/dist/security/headers.d.ts +4 -2
- package/dist/security/headers.d.ts.map +1 -1
- package/dist/security/headers.js +35 -17
- package/dist/security/index.d.ts +3 -16
- package/dist/security/index.d.ts.map +1 -1
- package/dist/security/index.js +3 -16
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/renderPage.d.ts.map +1 -1
- package/dist/storage/index.d.ts +1 -0
- package/dist/storage/index.d.ts.map +1 -1
- package/dist/storage/index.js +2 -4
- package/dist/storage/vercel-blob.d.ts.map +1 -1
- package/dist/translations/index.d.ts.map +1 -1
- package/dist/types/access.d.ts.map +1 -1
- package/dist/types/api.d.ts.map +1 -1
- package/dist/types/cms.d.ts.map +1 -1
- package/dist/types/config.d.ts.map +1 -1
- package/dist/types/core.d.ts.map +1 -1
- package/dist/types/extensions.d.ts.map +1 -1
- package/dist/types/frontend.d.ts.map +1 -1
- package/dist/types/generated.d.ts.map +1 -1
- package/dist/types/hooks.d.ts.map +1 -1
- package/dist/types/index.d.ts +1 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/interfaces/app.d.ts.map +1 -1
- package/dist/types/jobs.d.ts.map +1 -1
- package/dist/types/legacy.d.ts.map +1 -1
- package/dist/types/plugins.d.ts.map +1 -1
- package/dist/types/query.d.ts.map +1 -1
- package/dist/types/request.d.ts.map +1 -1
- package/dist/types/richtext.d.ts.map +1 -1
- package/dist/types/runtime.d.ts +59 -1
- package/dist/types/runtime.d.ts.map +1 -1
- package/dist/types/schema.d.ts.map +1 -1
- package/dist/types/user.d.ts.map +1 -1
- package/dist/utils/access-conversion.d.ts.map +1 -1
- package/dist/utils/api-wrapper.d.ts.map +1 -1
- package/dist/utils/api-wrapper.js +1 -1
- package/dist/utils/block-conversion.d.ts.map +1 -1
- package/dist/utils/cache.d.ts.map +1 -1
- package/dist/utils/deep-clone.js +0 -1
- package/dist/utils/error-responses.d.ts.map +1 -1
- package/dist/utils/errors.d.ts +36 -0
- package/dist/utils/errors.d.ts.map +1 -1
- package/dist/utils/errors.js +103 -0
- package/dist/utils/field-conversion.d.ts +1 -1
- package/dist/utils/field-conversion.d.ts.map +1 -1
- package/dist/utils/flattenResult.d.ts.map +1 -1
- package/dist/utils/flattenResult.js +0 -1
- package/dist/utils/getBlockSelect.d.ts.map +1 -1
- package/dist/utils/getSelectMode.d.ts.map +1 -1
- package/dist/utils/isValidID.d.ts.map +1 -1
- package/dist/utils/json-parsing.d.ts.map +1 -1
- package/dist/utils/logger-client.d.ts.map +1 -1
- package/dist/utils/logger-server.d.ts.map +1 -1
- package/dist/utils/logger.d.ts.map +1 -1
- package/dist/utils/request-context.d.ts.map +1 -1
- package/dist/utils/stripUnselectedFields.d.ts.map +1 -1
- package/dist/utils/type-guards.d.ts.map +1 -1
- package/package.json +39 -7
|
@@ -1,193 +1,217 @@
|
|
|
1
1
|
'use client';
|
|
2
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
3
|
import { logger } from '@revealui/core/utils/logger';
|
|
4
|
-
import { useEffect,
|
|
4
|
+
import { useEffect, useReducer } from 'react';
|
|
5
5
|
import { APIError, APIErrorType, apiClient } from '../utils/index.js';
|
|
6
6
|
import { CollectionList } from './CollectionList.js';
|
|
7
7
|
import { DocumentForm } from './DocumentForm.js';
|
|
8
8
|
import { GlobalForm } from './GlobalForm.js';
|
|
9
|
+
const initialState = {
|
|
10
|
+
view: { type: 'dashboard' },
|
|
11
|
+
documents: [],
|
|
12
|
+
totalDocs: 0,
|
|
13
|
+
page: 1,
|
|
14
|
+
totalPages: 1,
|
|
15
|
+
collectionLoading: false,
|
|
16
|
+
globalDocument: null,
|
|
17
|
+
globalLoading: false,
|
|
18
|
+
saving: false,
|
|
19
|
+
deleting: null,
|
|
20
|
+
error: null,
|
|
21
|
+
successMessage: null,
|
|
22
|
+
};
|
|
23
|
+
function reducer(state, action) {
|
|
24
|
+
switch (action.type) {
|
|
25
|
+
case 'NAVIGATE':
|
|
26
|
+
return { ...state, view: action.view, error: null, successMessage: null };
|
|
27
|
+
case 'COLLECTION_LOADING':
|
|
28
|
+
return { ...state, collectionLoading: true };
|
|
29
|
+
case 'COLLECTION_LOADED':
|
|
30
|
+
return {
|
|
31
|
+
...state,
|
|
32
|
+
documents: action.documents,
|
|
33
|
+
totalDocs: action.totalDocs,
|
|
34
|
+
page: action.page,
|
|
35
|
+
totalPages: action.totalPages,
|
|
36
|
+
collectionLoading: false,
|
|
37
|
+
};
|
|
38
|
+
case 'GLOBAL_LOADING':
|
|
39
|
+
return { ...state, globalDocument: null, globalLoading: true };
|
|
40
|
+
case 'GLOBAL_LOADED':
|
|
41
|
+
return { ...state, globalDocument: action.document, globalLoading: false };
|
|
42
|
+
case 'SET_SAVING':
|
|
43
|
+
return { ...state, saving: action.saving };
|
|
44
|
+
case 'SET_DELETING':
|
|
45
|
+
return { ...state, deleting: action.id };
|
|
46
|
+
case 'SET_ERROR':
|
|
47
|
+
return { ...state, error: action.error };
|
|
48
|
+
case 'SET_SUCCESS':
|
|
49
|
+
return { ...state, successMessage: action.message };
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
// =============================================================================
|
|
53
|
+
// Shared sub-components
|
|
54
|
+
// =============================================================================
|
|
55
|
+
function AdminHeader({ title, onBack }) {
|
|
56
|
+
return (_jsx("header", { className: "bg-white shadow-sm border-b", children: _jsx("div", { className: "max-w-7xl mx-auto px-4 sm:px-6 lg:px-8", children: _jsx("div", { className: "flex justify-between items-center py-4", children: _jsxs("div", { className: "flex items-center space-x-4", children: [_jsx("button", { type: "button", onClick: onBack, className: "text-gray-400 hover:text-gray-600", children: "\u2190 Back to Dashboard" }), _jsx("h1", { className: "text-2xl font-bold text-gray-900 capitalize", children: title })] }) }) }) }));
|
|
57
|
+
}
|
|
58
|
+
function StatusBanners({ error, successMessage, }) {
|
|
59
|
+
return (_jsxs(_Fragment, { children: [error && (_jsxs("div", { className: "mb-4 bg-red-50 border border-red-200 text-red-800 px-4 py-3 rounded", children: [_jsx("p", { className: "font-medium", children: "Error" }), _jsx("p", { className: "text-sm", children: error })] })), successMessage && (_jsxs("div", { className: "mb-4 bg-green-50 border border-green-200 text-green-800 px-4 py-3 rounded", children: [_jsx("p", { className: "font-medium", children: "Success" }), _jsx("p", { className: "text-sm", children: successMessage })] }))] }));
|
|
60
|
+
}
|
|
61
|
+
function LoadingSpinner() {
|
|
62
|
+
return (_jsxs("div", { className: "mb-4 text-center py-8", children: [_jsx("div", { className: "inline-block animate-spin rounded-full h-8 w-8 border-b-2 border-gray-900" }), _jsx("p", { className: "mt-2 text-sm text-gray-600", children: "Loading..." })] }));
|
|
63
|
+
}
|
|
64
|
+
// =============================================================================
|
|
65
|
+
// Dashboard home view
|
|
66
|
+
// =============================================================================
|
|
67
|
+
function DashboardHome({ collections, globals, onCollectionClick, onGlobalClick, }) {
|
|
68
|
+
return (_jsxs("div", { className: "min-h-screen bg-gray-50", children: [_jsx("header", { className: "bg-white shadow-sm border-b", children: _jsx("div", { className: "max-w-7xl mx-auto px-4 sm:px-6 lg:px-8", children: _jsxs("div", { className: "flex justify-between items-center py-4", children: [_jsx("div", { className: "flex items-center", children: _jsx("h1", { className: "text-2xl font-bold text-gray-900", children: "RevealUI Admin" }) }), _jsx("div", { className: "flex items-center space-x-4", children: _jsx("span", { className: "text-sm text-gray-500", children: "v0.1.0" }) })] }) }) }), _jsx("main", { className: "max-w-7xl mx-auto py-6 sm:px-6 lg:px-8", children: _jsx("div", { className: "px-4 py-6 sm:px-0", children: _jsxs("div", { className: "grid grid-cols-1 gap-6 sm:grid-cols-2 lg:grid-cols-3", children: [_jsxs("div", { className: "bg-white overflow-hidden shadow rounded-lg", children: [_jsx("div", { className: "p-5", children: _jsxs("div", { className: "flex items-center", children: [_jsx("div", { className: "flex-shrink-0", children: _jsxs("svg", { className: "h-8 w-8 text-gray-400", "aria-label": "Collections", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", role: "img", children: [_jsx("title", { children: "Collections" }), _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M19 11H5m14 0a2 2 0 012 2v6a2 2 0 01-2 2H5a2 2 0 01-2-2v-6a2 2 0 012-2m14 0V9a2 2 0 00-2-2M5 11V9a2 2 0 012-2m0 0V5a2 2 0 012-2h6a2 2 0 012 2v2M7 7h10" })] }) }), _jsx("div", { className: "ml-5 w-0 flex-1", children: _jsxs("dl", { children: [_jsx("dt", { className: "text-sm font-medium text-gray-500 truncate", children: "Collections" }), _jsx("dd", { className: "text-lg font-medium text-gray-900", children: collections.length })] }) })] }) }), _jsx("div", { className: "bg-gray-50 px-5 py-3", children: _jsx("div", { className: "text-sm", children: collections.length > 0 ? (_jsx("ul", { className: "space-y-1 max-h-48 overflow-y-auto", children: collections.map((collection) => (_jsx("li", { className: "text-gray-600 hover:text-gray-900", children: _jsx("button", { type: "button", onClick: () => onCollectionClick(collection), className: "hover:underline cursor-pointer", children: String(collection.slug) }) }, String(collection.slug)))) })) : (_jsx("p", { className: "text-gray-500", children: "No collections configured" })) }) })] }), _jsxs("div", { className: "bg-white overflow-hidden shadow rounded-lg", children: [_jsx("div", { className: "p-5", children: _jsxs("div", { className: "flex items-center", children: [_jsx("div", { className: "flex-shrink-0", children: _jsxs("svg", { className: "h-8 w-8 text-gray-400", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", "aria-labelledby": "globals-icon-title", role: "img", children: [_jsx("title", { id: "globals-icon-title", children: "Globals" }), _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M12 6V4m0 2a2 2 0 100 4m0-4a2 2 0 110 4m-6 8a2 2 0 100-4m0 4a2 2 0 100 4m0-4v2m0-6V4m6 6v10m6-2a2 2 0 100-4m0 4a2 2 0 100 4m0-4v2m0-6V4" })] }) }), _jsx("div", { className: "ml-5 w-0 flex-1", children: _jsxs("dl", { children: [_jsx("dt", { className: "text-sm font-medium text-gray-500 truncate", children: "Globals" }), _jsx("dd", { className: "text-lg font-medium text-gray-900", children: globals.length })] }) })] }) }), _jsx("div", { className: "bg-gray-50 px-5 py-3", children: _jsx("div", { className: "text-sm", children: globals.length > 0 ? (_jsx("ul", { className: "space-y-1 max-h-32 overflow-y-auto", children: globals.map((global) => (_jsx("li", { className: "text-gray-600 hover:text-gray-900", children: _jsx("button", { type: "button", onClick: () => onGlobalClick(global), className: "hover:underline cursor-pointer", children: global.label || String(global.slug) }) }, String(global.slug)))) })) : (_jsx("p", { className: "text-gray-500", children: "No globals configured" })) }) })] }), _jsxs("div", { className: "bg-white overflow-hidden shadow rounded-lg", children: [_jsx("div", { className: "p-5", children: _jsxs("div", { className: "flex items-center", children: [_jsx("div", { className: "flex-shrink-0", children: _jsx("div", { className: "h-8 w-8 bg-green-100 rounded-full flex items-center justify-center", children: _jsxs("svg", { className: "h-5 w-5 text-green-600", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", "aria-labelledby": "system-status-icon-title", role: "img", children: [_jsx("title", { id: "system-status-icon-title", children: "System Status: Healthy" }), _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M5 13l4 4L19 7" })] }) }) }), _jsx("div", { className: "ml-5 w-0 flex-1", children: _jsxs("dl", { children: [_jsx("dt", { className: "text-sm font-medium text-gray-500 truncate", children: "System Status" }), _jsx("dd", { className: "text-lg font-medium text-gray-900", children: "Healthy" })] }) })] }) }), _jsx("div", { className: "bg-gray-50 px-5 py-3", children: _jsx("div", { className: "text-sm text-gray-600", children: "RevealUI CMS is running successfully" }) })] })] }) }) })] }));
|
|
69
|
+
}
|
|
70
|
+
// =============================================================================
|
|
71
|
+
// Error handling helpers
|
|
72
|
+
// =============================================================================
|
|
73
|
+
function extractErrorMessage(err, fallback) {
|
|
74
|
+
return err instanceof APIError ? err.message : fallback;
|
|
75
|
+
}
|
|
76
|
+
function logApiError(err, context) {
|
|
77
|
+
logger.error(context, { error: err });
|
|
78
|
+
if (err instanceof APIError && err.type === APIErrorType.Authentication) {
|
|
79
|
+
logger.warn('Authentication required');
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
// =============================================================================
|
|
83
|
+
// Main component
|
|
84
|
+
// =============================================================================
|
|
9
85
|
export function AdminDashboard({ config }) {
|
|
10
|
-
const [
|
|
11
|
-
type: 'dashboard',
|
|
12
|
-
});
|
|
13
|
-
const [collectionData, setCollectionData] = useState({
|
|
14
|
-
documents: [],
|
|
15
|
-
totalDocs: 0,
|
|
16
|
-
page: 1,
|
|
17
|
-
totalPages: 1,
|
|
18
|
-
loading: false,
|
|
19
|
-
error: null,
|
|
20
|
-
});
|
|
21
|
-
const [saving, setSaving] = useState(false);
|
|
22
|
-
const [deleting, setDeleting] = useState(null);
|
|
23
|
-
const [error, setError] = useState(null);
|
|
24
|
-
const [successMessage, setSuccessMessage] = useState(null);
|
|
25
|
-
const [globalData, setGlobalData] = useState({
|
|
26
|
-
document: null,
|
|
27
|
-
loading: false,
|
|
28
|
-
error: null,
|
|
29
|
-
});
|
|
86
|
+
const [state, dispatch] = useReducer(reducer, initialState);
|
|
30
87
|
const collections = config.collections || [];
|
|
31
88
|
const globals = config.globals || [];
|
|
32
89
|
// Auto-dismiss success messages
|
|
33
90
|
useEffect(() => {
|
|
34
|
-
if (successMessage) {
|
|
35
|
-
const timer = setTimeout(() =>
|
|
91
|
+
if (state.successMessage) {
|
|
92
|
+
const timer = setTimeout(() => dispatch({ type: 'SET_SUCCESS', message: null }), 3000);
|
|
36
93
|
return () => clearTimeout(timer);
|
|
37
94
|
}
|
|
38
95
|
return;
|
|
39
|
-
}, [successMessage]);
|
|
96
|
+
}, [state.successMessage]);
|
|
40
97
|
// Auto-dismiss error messages
|
|
41
98
|
useEffect(() => {
|
|
42
|
-
if (error) {
|
|
43
|
-
const timer = setTimeout(() =>
|
|
99
|
+
if (state.error) {
|
|
100
|
+
const timer = setTimeout(() => dispatch({ type: 'SET_ERROR', error: null }), 5000);
|
|
44
101
|
return () => clearTimeout(timer);
|
|
45
102
|
}
|
|
46
103
|
return;
|
|
47
|
-
}, [error]);
|
|
48
|
-
const
|
|
49
|
-
|
|
50
|
-
setError(null);
|
|
51
|
-
setSuccessMessage(null);
|
|
104
|
+
}, [state.error]);
|
|
105
|
+
const goToDashboard = () => dispatch({ type: 'NAVIGATE', view: { type: 'dashboard' } });
|
|
106
|
+
const fetchCollection = async (collection, page = 1) => {
|
|
52
107
|
try {
|
|
53
|
-
|
|
54
|
-
setCollectionData((prev) => ({ ...prev, loading: true, error: null }));
|
|
55
|
-
// Fetch first page of documents
|
|
108
|
+
dispatch({ type: 'COLLECTION_LOADING' });
|
|
56
109
|
const response = await apiClient.find({
|
|
57
110
|
collection: String(collection.slug),
|
|
58
|
-
page
|
|
111
|
+
page,
|
|
59
112
|
limit: 10,
|
|
60
113
|
});
|
|
61
|
-
|
|
114
|
+
dispatch({
|
|
115
|
+
type: 'COLLECTION_LOADED',
|
|
62
116
|
documents: response.docs || [],
|
|
63
117
|
totalDocs: response.totalDocs || 0,
|
|
64
118
|
page: response.page || 1,
|
|
65
119
|
totalPages: response.totalPages || 1,
|
|
66
|
-
loading: false,
|
|
67
|
-
error: null,
|
|
68
120
|
});
|
|
69
121
|
}
|
|
70
122
|
catch (err) {
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
if (err instanceof APIError && err.type === APIErrorType.Authentication) {
|
|
82
|
-
// Redirect to login would be handled by the auth system
|
|
83
|
-
logger.warn('Authentication required');
|
|
84
|
-
}
|
|
123
|
+
const msg = extractErrorMessage(err, 'Failed to fetch collection data. Please try again.');
|
|
124
|
+
logApiError(err, 'Failed to fetch collection data');
|
|
125
|
+
dispatch({
|
|
126
|
+
type: 'COLLECTION_LOADED',
|
|
127
|
+
documents: state.documents,
|
|
128
|
+
totalDocs: state.totalDocs,
|
|
129
|
+
page: state.page,
|
|
130
|
+
totalPages: state.totalPages,
|
|
131
|
+
});
|
|
132
|
+
dispatch({ type: 'SET_ERROR', error: msg });
|
|
85
133
|
}
|
|
86
134
|
};
|
|
135
|
+
const handleCollectionClick = async (collection) => {
|
|
136
|
+
dispatch({ type: 'NAVIGATE', view: { type: 'collection', collection } });
|
|
137
|
+
await fetchCollection(collection);
|
|
138
|
+
};
|
|
87
139
|
const handleGlobalClick = async (global) => {
|
|
88
|
-
|
|
89
|
-
setError(null);
|
|
90
|
-
setSuccessMessage(null);
|
|
140
|
+
dispatch({ type: 'NAVIGATE', view: { type: 'global', global } });
|
|
91
141
|
try {
|
|
92
|
-
|
|
93
|
-
setGlobalData({ document: null, loading: true, error: null });
|
|
94
|
-
// Fetch global data
|
|
142
|
+
dispatch({ type: 'GLOBAL_LOADING' });
|
|
95
143
|
const document = await apiClient.findGlobal({
|
|
96
144
|
slug: String(global.slug),
|
|
97
145
|
depth: 0,
|
|
98
146
|
});
|
|
99
|
-
|
|
100
|
-
document,
|
|
101
|
-
loading: false,
|
|
102
|
-
error: null,
|
|
103
|
-
});
|
|
147
|
+
dispatch({ type: 'GLOBAL_LOADED', document });
|
|
104
148
|
}
|
|
105
149
|
catch (err) {
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
setGlobalData({
|
|
110
|
-
document: null,
|
|
111
|
-
loading: false,
|
|
112
|
-
error: errorMessage,
|
|
113
|
-
});
|
|
114
|
-
setError(errorMessage);
|
|
115
|
-
// Handle authentication errors
|
|
116
|
-
if (err instanceof APIError && err.type === APIErrorType.Authentication) {
|
|
117
|
-
logger.warn('Authentication required');
|
|
118
|
-
}
|
|
150
|
+
const msg = extractErrorMessage(err, 'Failed to fetch global data. Please try again.');
|
|
151
|
+
logApiError(err, 'Failed to fetch global data');
|
|
152
|
+
dispatch({ type: 'SET_ERROR', error: msg });
|
|
119
153
|
}
|
|
120
154
|
};
|
|
121
155
|
const handleCreate = () => {
|
|
122
|
-
if (
|
|
123
|
-
|
|
156
|
+
if (state.view.collection) {
|
|
157
|
+
dispatch({
|
|
158
|
+
type: 'NAVIGATE',
|
|
159
|
+
view: { type: 'edit', collection: state.view.collection },
|
|
160
|
+
});
|
|
124
161
|
}
|
|
125
162
|
};
|
|
126
163
|
const handleEdit = (document) => {
|
|
127
|
-
if (
|
|
128
|
-
|
|
129
|
-
type: '
|
|
130
|
-
collection:
|
|
131
|
-
document,
|
|
164
|
+
if (state.view.collection) {
|
|
165
|
+
dispatch({
|
|
166
|
+
type: 'NAVIGATE',
|
|
167
|
+
view: { type: 'edit', collection: state.view.collection, document },
|
|
132
168
|
});
|
|
133
169
|
}
|
|
134
170
|
};
|
|
135
171
|
const handleDelete = async (document) => {
|
|
136
|
-
if (!(
|
|
172
|
+
if (!(state.view.collection && document.id))
|
|
137
173
|
return;
|
|
138
|
-
|
|
139
|
-
const confirmed = window.confirm(`Are you sure you want to delete this ${String(currentView.collection.slug)}? This action cannot be undone.`);
|
|
174
|
+
const confirmed = window.confirm(`Are you sure you want to delete this ${String(state.view.collection.slug)}? This action cannot be undone.`);
|
|
140
175
|
if (!confirmed)
|
|
141
176
|
return;
|
|
142
177
|
try {
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
setSuccessMessage(null);
|
|
178
|
+
dispatch({ type: 'SET_DELETING', id: String(document.id) });
|
|
179
|
+
dispatch({ type: 'SET_ERROR', error: null });
|
|
146
180
|
await apiClient.delete({
|
|
147
|
-
collection: String(
|
|
181
|
+
collection: String(state.view.collection.slug),
|
|
148
182
|
id: String(document.id),
|
|
149
183
|
});
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
await handleCollectionClick(currentView.collection);
|
|
184
|
+
if (state.view.collection) {
|
|
185
|
+
await fetchCollection(state.view.collection);
|
|
153
186
|
}
|
|
154
|
-
|
|
155
|
-
setSuccessMessage('Document deleted successfully');
|
|
187
|
+
dispatch({ type: 'SET_SUCCESS', message: 'Document deleted successfully' });
|
|
156
188
|
}
|
|
157
189
|
catch (err) {
|
|
158
|
-
const
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
// Handle authentication errors
|
|
162
|
-
if (err instanceof APIError && err.type === APIErrorType.Authentication) {
|
|
163
|
-
logger.warn('Authentication required');
|
|
164
|
-
}
|
|
190
|
+
const msg = extractErrorMessage(err, 'Failed to delete document. Please try again.');
|
|
191
|
+
logApiError(err, 'Failed to delete document');
|
|
192
|
+
dispatch({ type: 'SET_ERROR', error: msg });
|
|
165
193
|
}
|
|
166
194
|
finally {
|
|
167
|
-
|
|
195
|
+
dispatch({ type: 'SET_DELETING', id: null });
|
|
168
196
|
}
|
|
169
197
|
};
|
|
170
198
|
const handleSave = async (data) => {
|
|
171
|
-
if (!
|
|
199
|
+
if (!state.view.collection)
|
|
172
200
|
return;
|
|
173
201
|
try {
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
if (currentView.document?.id) {
|
|
178
|
-
// Update existing document
|
|
202
|
+
dispatch({ type: 'SET_SAVING', saving: true });
|
|
203
|
+
dispatch({ type: 'SET_ERROR', error: null });
|
|
204
|
+
if (state.view.document?.id) {
|
|
179
205
|
await apiClient.update({
|
|
180
|
-
collection: String(
|
|
181
|
-
id: String(
|
|
206
|
+
collection: String(state.view.collection.slug),
|
|
207
|
+
id: String(state.view.document.id),
|
|
182
208
|
data,
|
|
183
209
|
});
|
|
184
|
-
|
|
210
|
+
dispatch({ type: 'SET_SUCCESS', message: 'Document updated successfully' });
|
|
185
211
|
}
|
|
186
212
|
else {
|
|
187
|
-
// Auto-generate slug from title if
|
|
188
|
-
|
|
189
|
-
// so we replicate the slug-generation logic here as a reliable client-side fallback.
|
|
190
|
-
const hasSlugField = currentView.collection.fields.some((f) => 'name' in f && f.name === 'slug');
|
|
213
|
+
// Auto-generate slug from title if needed
|
|
214
|
+
const hasSlugField = state.view.collection.fields.some((f) => 'name' in f && f.name === 'slug');
|
|
191
215
|
const submitData = hasSlugField && !data.slug && typeof data.title === 'string'
|
|
192
216
|
? {
|
|
193
217
|
...data,
|
|
@@ -197,122 +221,71 @@ export function AdminDashboard({ config }) {
|
|
|
197
221
|
.toLowerCase(),
|
|
198
222
|
}
|
|
199
223
|
: data;
|
|
200
|
-
// Create new document
|
|
201
224
|
await apiClient.create({
|
|
202
|
-
collection: String(
|
|
225
|
+
collection: String(state.view.collection.slug),
|
|
203
226
|
data: submitData,
|
|
204
227
|
});
|
|
205
|
-
|
|
206
|
-
}
|
|
207
|
-
// Refresh collection list
|
|
208
|
-
if (currentView.collection) {
|
|
209
|
-
await handleCollectionClick(currentView.collection);
|
|
228
|
+
dispatch({ type: 'SET_SUCCESS', message: 'Document created successfully' });
|
|
210
229
|
}
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
type: '
|
|
214
|
-
collection:
|
|
230
|
+
await fetchCollection(state.view.collection);
|
|
231
|
+
dispatch({
|
|
232
|
+
type: 'NAVIGATE',
|
|
233
|
+
view: { type: 'collection', collection: state.view.collection },
|
|
215
234
|
});
|
|
216
235
|
}
|
|
217
236
|
catch (err) {
|
|
218
|
-
const
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
// Handle validation errors
|
|
237
|
+
const msg = extractErrorMessage(err, 'Failed to save document. Please try again.');
|
|
238
|
+
logApiError(err, 'Failed to save document');
|
|
239
|
+
dispatch({ type: 'SET_ERROR', error: msg });
|
|
222
240
|
if (err instanceof APIError && err.type === APIErrorType.Validation) {
|
|
223
|
-
|
|
224
|
-
logger.warn('Validation error', {
|
|
225
|
-
field: err.field,
|
|
226
|
-
message: err.message,
|
|
227
|
-
});
|
|
228
|
-
}
|
|
229
|
-
// Handle authentication errors
|
|
230
|
-
if (err instanceof APIError && err.type === APIErrorType.Authentication) {
|
|
231
|
-
logger.warn('Authentication required');
|
|
241
|
+
logger.warn('Validation error', { field: err.field, message: err.message });
|
|
232
242
|
}
|
|
233
243
|
}
|
|
234
244
|
finally {
|
|
235
|
-
|
|
245
|
+
dispatch({ type: 'SET_SAVING', saving: false });
|
|
236
246
|
}
|
|
237
247
|
};
|
|
238
248
|
const handleSaveGlobal = async (data) => {
|
|
239
|
-
if (!
|
|
249
|
+
if (!state.view.global)
|
|
240
250
|
return;
|
|
241
251
|
try {
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
setSuccessMessage(null);
|
|
245
|
-
// Update global
|
|
252
|
+
dispatch({ type: 'SET_SAVING', saving: true });
|
|
253
|
+
dispatch({ type: 'SET_ERROR', error: null });
|
|
246
254
|
await apiClient.updateGlobal({
|
|
247
|
-
slug: String(
|
|
255
|
+
slug: String(state.view.global.slug),
|
|
248
256
|
data,
|
|
249
257
|
});
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
setCurrentView({ type: 'dashboard' });
|
|
258
|
+
dispatch({ type: 'SET_SUCCESS', message: 'Global updated successfully' });
|
|
259
|
+
goToDashboard();
|
|
253
260
|
}
|
|
254
261
|
catch (err) {
|
|
255
|
-
const
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
// Handle validation errors
|
|
262
|
+
const msg = extractErrorMessage(err, 'Failed to save global. Please try again.');
|
|
263
|
+
logApiError(err, 'Failed to save global');
|
|
264
|
+
dispatch({ type: 'SET_ERROR', error: msg });
|
|
259
265
|
if (err instanceof APIError && err.type === APIErrorType.Validation) {
|
|
260
|
-
logger.warn('Validation error', {
|
|
261
|
-
field: err.field,
|
|
262
|
-
message: err.message,
|
|
263
|
-
});
|
|
264
|
-
}
|
|
265
|
-
// Handle authentication errors
|
|
266
|
-
if (err instanceof APIError && err.type === APIErrorType.Authentication) {
|
|
267
|
-
logger.warn('Authentication required');
|
|
266
|
+
logger.warn('Validation error', { field: err.field, message: err.message });
|
|
268
267
|
}
|
|
269
268
|
}
|
|
270
269
|
finally {
|
|
271
|
-
|
|
272
|
-
}
|
|
273
|
-
};
|
|
274
|
-
const handleCancel = () => {
|
|
275
|
-
setCurrentView({ type: 'dashboard' });
|
|
276
|
-
};
|
|
277
|
-
const handlePageChange = async (page) => {
|
|
278
|
-
if (!currentView.collection)
|
|
279
|
-
return;
|
|
280
|
-
try {
|
|
281
|
-
setCollectionData((prev) => ({ ...prev, loading: true, error: null }));
|
|
282
|
-
const response = await apiClient.find({
|
|
283
|
-
collection: String(currentView.collection.slug),
|
|
284
|
-
page,
|
|
285
|
-
limit: 10,
|
|
286
|
-
});
|
|
287
|
-
setCollectionData({
|
|
288
|
-
documents: response.docs || [],
|
|
289
|
-
totalDocs: response.totalDocs || 0,
|
|
290
|
-
page: response.page || 1,
|
|
291
|
-
totalPages: response.totalPages || 1,
|
|
292
|
-
loading: false,
|
|
293
|
-
error: null,
|
|
294
|
-
});
|
|
295
|
-
}
|
|
296
|
-
catch (err) {
|
|
297
|
-
const errorMessage = err instanceof APIError ? err.message : 'Failed to fetch page. Please try again.';
|
|
298
|
-
logger.error('Failed to fetch page', { error: err });
|
|
299
|
-
setCollectionData((prev) => ({
|
|
300
|
-
...prev,
|
|
301
|
-
loading: false,
|
|
302
|
-
error: errorMessage,
|
|
303
|
-
}));
|
|
304
|
-
setError(errorMessage);
|
|
270
|
+
dispatch({ type: 'SET_SAVING', saving: false });
|
|
305
271
|
}
|
|
306
272
|
};
|
|
307
|
-
|
|
308
|
-
|
|
273
|
+
// ── Collection list view ──────────────────────────────────────────────
|
|
274
|
+
if (state.view.type === 'collection' && state.view.collection) {
|
|
275
|
+
return (_jsxs("div", { className: "min-h-screen bg-gray-50", children: [_jsx(AdminHeader, { title: String(state.view.collection.slug), onBack: goToDashboard }), _jsxs("main", { className: "max-w-7xl mx-auto py-6 sm:px-6 lg:px-8", children: [_jsx(StatusBanners, { error: state.error, successMessage: state.successMessage }), state.collectionLoading && _jsx(LoadingSpinner, {}), _jsx(CollectionList, { collection: state.view.collection, documents: state.documents, totalDocs: state.totalDocs, page: state.page, totalPages: state.totalPages, onCreate: handleCreate, onEdit: handleEdit, onDelete: (document) => void handleDelete(document), onPageChange: (nextPage) => {
|
|
276
|
+
const collection = state.view.collection;
|
|
277
|
+
if (collection)
|
|
278
|
+
void fetchCollection(collection, nextPage);
|
|
279
|
+
}, deleting: state.deleting })] })] }));
|
|
309
280
|
}
|
|
310
|
-
|
|
311
|
-
|
|
281
|
+
// ── Document edit/create view ─────────────────────────────────────────
|
|
282
|
+
if (state.view.type === 'edit' && state.view.collection) {
|
|
283
|
+
return (_jsxs("div", { className: "min-h-screen bg-gray-50", children: [_jsx(AdminHeader, { title: `${state.view.document ? 'Edit' : 'Create'} ${String(state.view.collection.slug).slice(0, -1)}`, onBack: goToDashboard }), _jsx("main", { className: "max-w-7xl mx-auto py-6 sm:px-6 lg:px-8", children: _jsxs("div", { className: "max-w-3xl", children: [_jsx(StatusBanners, { error: state.error, successMessage: state.successMessage }), _jsx(DocumentForm, { collection: state.view.collection, document: state.view.document, onSave: (data) => void handleSave(data), onCancel: goToDashboard, isLoading: state.saving })] }) })] }));
|
|
312
284
|
}
|
|
313
|
-
|
|
314
|
-
|
|
285
|
+
// ── Global edit view ──────────────────────────────────────────────────
|
|
286
|
+
if (state.view.type === 'global' && state.view.global) {
|
|
287
|
+
return (_jsxs("div", { className: "min-h-screen bg-gray-50", children: [_jsx(AdminHeader, { title: state.view.global.label || String(state.view.global.slug), onBack: goToDashboard }), _jsx("main", { className: "max-w-7xl mx-auto py-6 sm:px-6 lg:px-8", children: _jsxs("div", { className: "max-w-3xl", children: [_jsx(StatusBanners, { error: state.error, successMessage: state.successMessage }), state.globalLoading && _jsx(LoadingSpinner, {}), !state.globalLoading && state.globalDocument && (_jsx(GlobalForm, { global: state.view.global, document: state.globalDocument, onSave: (data) => void handleSaveGlobal(data), onCancel: goToDashboard, isLoading: state.saving }))] }) })] }));
|
|
315
288
|
}
|
|
316
|
-
// Dashboard
|
|
317
|
-
return (
|
|
289
|
+
// ── Dashboard home ────────────────────────────────────────────────────
|
|
290
|
+
return (_jsx(DashboardHome, { collections: collections, globals: globals, onCollectionClick: (c) => void handleCollectionClick(c), onGlobalClick: (g) => void handleGlobalClick(g) }));
|
|
318
291
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CollectionList.d.ts","sourceRoot":"","sources":["../../../../src/client/admin/components/CollectionList.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"CollectionList.d.ts","sourceRoot":"","sources":["../../../../src/client/admin/components/CollectionList.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,sBAAsB,EACtB,cAAc,EAEf,MAAM,yBAAyB,CAAC;AAoCjC,UAAU,mBAAmB;IAC3B,UAAU,EAAE,sBAAsB,CAAC;IACnC,SAAS,EAAE,cAAc,EAAE,CAAC;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,MAAM,EAAE,CAAC,GAAG,EAAE,cAAc,KAAK,IAAI,CAAC;IACtC,QAAQ,EAAE,CAAC,GAAG,EAAE,cAAc,KAAK,IAAI,CAAC;IACxC,YAAY,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACrC,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED,wBAAgB,cAAc,CAAC,EAC7B,UAAU,EACV,SAAS,EACT,SAAS,EACT,IAAI,EACJ,UAAU,EACV,QAAQ,EACR,MAAM,EACN,QAAQ,EACR,YAAY,EACZ,QAAQ,GACT,EAAE,mBAAmB,2CAqKrB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DocumentForm.d.ts","sourceRoot":"","sources":["../../../../src/client/admin/components/DocumentForm.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"DocumentForm.d.ts","sourceRoot":"","sources":["../../../../src/client/admin/components/DocumentForm.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,sBAAsB,EACtB,cAAc,EAEf,MAAM,yBAAyB,CAAC;AAiEjC,UAAU,iBAAiB;IACzB,UAAU,EAAE,sBAAsB,CAAC;IACnC,QAAQ,CAAC,EAAE,cAAc,CAAC;IAC1B,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;IAChD,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,wBAAgB,YAAY,CAAC,EAC3B,UAAU,EACV,QAAQ,EACR,MAAM,EACN,QAAQ,EACR,SAAiB,GAClB,EAAE,iBAAiB,2CA0DnB"}
|