@actuate-media/cms-admin 0.40.1 → 0.41.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.
Files changed (42) hide show
  1. package/dist/__tests__/views/page-section-editor.test.js +50 -0
  2. package/dist/__tests__/views/page-section-editor.test.js.map +1 -1
  3. package/dist/views/page-editor/EditorCanvas.d.ts +3 -1
  4. package/dist/views/page-editor/EditorCanvas.d.ts.map +1 -1
  5. package/dist/views/page-editor/EditorCanvas.js +8 -7
  6. package/dist/views/page-editor/EditorCanvas.js.map +1 -1
  7. package/dist/views/page-editor/EditorTopBar.d.ts +13 -1
  8. package/dist/views/page-editor/EditorTopBar.d.ts.map +1 -1
  9. package/dist/views/page-editor/EditorTopBar.js +11 -3
  10. package/dist/views/page-editor/EditorTopBar.js.map +1 -1
  11. package/dist/views/page-editor/PageSectionEditor.d.ts.map +1 -1
  12. package/dist/views/page-editor/PageSectionEditor.js +25 -1
  13. package/dist/views/page-editor/PageSectionEditor.js.map +1 -1
  14. package/dist/views/page-editor/StructureNotice.d.ts +10 -0
  15. package/dist/views/page-editor/StructureNotice.d.ts.map +1 -0
  16. package/dist/views/page-editor/StructureNotice.js +16 -0
  17. package/dist/views/page-editor/StructureNotice.js.map +1 -0
  18. package/dist/views/page-editor/sections/SectionRenderer.d.ts +2 -0
  19. package/dist/views/page-editor/sections/SectionRenderer.d.ts.map +1 -1
  20. package/dist/views/page-editor/sections/SectionRenderer.js +22 -0
  21. package/dist/views/page-editor/sections/SectionRenderer.js.map +1 -1
  22. package/dist/views/page-editor/sections/index.d.ts +1 -1
  23. package/dist/views/page-editor/sections/index.d.ts.map +1 -1
  24. package/dist/views/page-editor/sections/index.js +1 -1
  25. package/dist/views/page-editor/sections/index.js.map +1 -1
  26. package/dist/views/post-editor/PostEditorCanvas.d.ts +3 -1
  27. package/dist/views/post-editor/PostEditorCanvas.d.ts.map +1 -1
  28. package/dist/views/post-editor/PostEditorCanvas.js +3 -2
  29. package/dist/views/post-editor/PostEditorCanvas.js.map +1 -1
  30. package/dist/views/post-editor/PostSectionEditor.d.ts.map +1 -1
  31. package/dist/views/post-editor/PostSectionEditor.js +25 -1
  32. package/dist/views/post-editor/PostSectionEditor.js.map +1 -1
  33. package/package.json +2 -2
  34. package/src/__tests__/views/page-section-editor.test.tsx +70 -0
  35. package/src/views/page-editor/EditorCanvas.tsx +29 -22
  36. package/src/views/page-editor/EditorTopBar.tsx +58 -13
  37. package/src/views/page-editor/PageSectionEditor.tsx +42 -0
  38. package/src/views/page-editor/StructureNotice.tsx +27 -0
  39. package/src/views/page-editor/sections/SectionRenderer.tsx +24 -0
  40. package/src/views/page-editor/sections/index.ts +1 -1
  41. package/src/views/post-editor/PostEditorCanvas.tsx +5 -0
  42. package/src/views/post-editor/PostSectionEditor.tsx +42 -1
@@ -1,4 +1,4 @@
1
- export { SectionRenderer } from './SectionRenderer.js'
1
+ export { SectionRenderer, hasCanvasRenderer } from './SectionRenderer.js'
2
2
  export type { SectionRendererProps } from './SectionRenderer.js'
3
3
  export type { PostRenderContext } from './parts.js'
4
4
  export { HeroBannerSection } from './HeroBannerSection.js'
@@ -4,6 +4,7 @@ import { useCallback, useEffect, useLayoutEffect, useRef, useState } from 'react
4
4
  import { FileText, Plus } from 'lucide-react'
5
5
  import type { PageSection, PostHeaderConfig } from '../../lib/post-editor-service.js'
6
6
  import { SectionRenderer, type PostRenderContext } from '../page-editor/sections/index.js'
7
+ import { StructureNotice } from '../page-editor/StructureNotice.js'
7
8
  import { getViewport, type ViewportId } from '../page-editor/viewports.js'
8
9
  import { PostHeader } from './PostHeader.js'
9
10
 
@@ -15,6 +16,8 @@ interface PostEditorCanvasProps {
15
16
  viewport: ViewportId
16
17
  onSelect: (id: string) => void
17
18
  onAddSection: () => void
19
+ /** Section types rendered as placeholders — shows the "Structure view" notice. */
20
+ structuralTypes?: string[]
18
21
  }
19
22
 
20
23
  /**
@@ -31,6 +34,7 @@ export function PostEditorCanvas({
31
34
  viewport,
32
35
  onSelect,
33
36
  onAddSection,
37
+ structuralTypes = [],
34
38
  }: PostEditorCanvasProps) {
35
39
  const vp = getViewport(viewport)
36
40
  const containerRef = useRef<HTMLDivElement>(null)
@@ -70,6 +74,7 @@ export function PostEditorCanvas({
70
74
 
71
75
  return (
72
76
  <div ref={containerRef} className="bg-muted h-full overflow-auto p-6">
77
+ <StructureNotice structuralTypes={structuralTypes} />
73
78
  <div
74
79
  className="mx-auto"
75
80
  style={{ width: vp.width * scale, height: surfaceHeight ?? undefined }}
@@ -5,6 +5,7 @@ import { AlertTriangle, Loader2 } from 'lucide-react'
5
5
  import { toast } from 'sonner'
6
6
  import { ConfirmDialog } from '../../components/ui/ConfirmDialog.js'
7
7
  import { ErrorBoundary } from '../../components/ErrorBoundary.js'
8
+ import { VersionHistory } from '../../components/VersionHistory.js'
8
9
  import {
9
10
  addSection,
10
11
  createSection,
@@ -33,7 +34,7 @@ import {
33
34
  resolveSiteUrl,
34
35
  } from '../../lib/preview-link.js'
35
36
  import type { SectionSettings, SectionTypeId } from '../page-editor/section-types.js'
36
- import type { PostRenderContext } from '../page-editor/sections/index.js'
37
+ import { hasCanvasRenderer, type PostRenderContext } from '../page-editor/sections/index.js'
37
38
  import { DEFAULT_VIEWPORT, type ViewportId } from '../page-editor/viewports.js'
38
39
  import { EditorTopBar, type SaveState } from '../page-editor/EditorTopBar.js'
39
40
  import { SectionsPanel } from '../page-editor/SectionsPanel.js'
@@ -104,6 +105,7 @@ export function PostSectionEditor({
104
105
 
105
106
  const [addOpen, setAddOpen] = useState(false)
106
107
  const [fieldsOpen, setFieldsOpen] = useState(false)
108
+ const [historyOpen, setHistoryOpen] = useState(false)
107
109
  const [deleteTargetId, setDeleteTargetId] = useState<string | null>(null)
108
110
  const [confirmPublish, setConfirmPublish] = useState(false)
109
111
  const [leaveTarget, setLeaveTarget] = useState<string | null>(null)
@@ -302,6 +304,23 @@ export function PostSectionEditor({
302
304
  }
303
305
  }, [post, documentId, postType, onNavigate])
304
306
 
307
+ // After a version restore the server has already written the restored
308
+ // data — refetch so the editor reflects it instead of the stale state.
309
+ const handleRestored = useCallback(() => {
310
+ if (!post?.id) return
311
+ fetchPostForEditor(postType, post.id)
312
+ .then((p) => {
313
+ setPost(p)
314
+ setSelectedId(null)
315
+ setDirty(false)
316
+ setSaveState('idle')
317
+ setValidation(null)
318
+ })
319
+ .catch(() => {
320
+ toast.error('Version restored — refresh the page to see it.')
321
+ })
322
+ }, [postType, post?.id])
323
+
305
324
  const guardedNavigate = useCallback(
306
325
  (path: string) => {
307
326
  if (dirty) setLeaveTarget(path)
@@ -400,6 +419,15 @@ export function PostSectionEditor({
400
419
 
401
420
  const selected = post.sections.find((s) => s.id === selectedId) ?? null
402
421
 
422
+ // Section types the canvas renders as placeholders (custom + unmanaged).
423
+ // When present the editor surfaces "structure view" messaging and promotes
424
+ // "View on site" as the primary design preview.
425
+ const structuralTypes = Array.from(
426
+ new Set(
427
+ post.sections.filter((s) => !hasCanvasRenderer(s.sectionType)).map((s) => s.sectionType),
428
+ ),
429
+ )
430
+
403
431
  return (
404
432
  <ErrorBoundary>
405
433
  <div className="bg-background flex h-full flex-col overflow-hidden">
@@ -417,9 +445,11 @@ export function PostSectionEditor({
417
445
  onBack={() => guardedNavigate('/posts')}
418
446
  onPreview={handlePreview}
419
447
  onViewOnSite={post.id ? handleViewOnSite : undefined}
448
+ onHistory={post.id ? () => setHistoryOpen(true) : undefined}
420
449
  onOpenSettings={() => setFieldsOpen(true)}
421
450
  onSaveDraft={handleSaveDraft}
422
451
  onPublish={requestPublish}
452
+ structuralTypes={structuralTypes}
423
453
  />
424
454
 
425
455
  {validation && (
@@ -452,6 +482,7 @@ export function PostSectionEditor({
452
482
  viewport={viewport}
453
483
  onSelect={setSelectedId}
454
484
  onAddSection={() => setAddOpen(true)}
485
+ structuralTypes={structuralTypes}
455
486
  />
456
487
  </div>
457
488
 
@@ -476,6 +507,16 @@ export function PostSectionEditor({
476
507
  onAdd={handleAdd}
477
508
  />
478
509
 
510
+ {post.id && (
511
+ <VersionHistory
512
+ collectionSlug={postType}
513
+ documentId={post.id}
514
+ open={historyOpen}
515
+ onClose={() => setHistoryOpen(false)}
516
+ onRestore={handleRestored}
517
+ />
518
+ )}
519
+
479
520
  <PostFieldsModal
480
521
  open={fieldsOpen}
481
522
  post={post}