@prenta/admin 1.17.17 → 1.17.19

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 (47) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/__tests__/components/virtual-window.test.d.ts +2 -0
  3. package/dist/__tests__/components/virtual-window.test.d.ts.map +1 -0
  4. package/dist/__tests__/components/virtual-window.test.js +22 -0
  5. package/dist/__tests__/components/virtual-window.test.js.map +1 -0
  6. package/dist/__tests__/views/autosave.test.d.ts +2 -0
  7. package/dist/__tests__/views/autosave.test.d.ts.map +1 -0
  8. package/dist/__tests__/views/autosave.test.js +51 -0
  9. package/dist/__tests__/views/autosave.test.js.map +1 -0
  10. package/dist/components/virtual-window.d.ts +28 -0
  11. package/dist/components/virtual-window.d.ts.map +1 -0
  12. package/dist/components/virtual-window.js +62 -0
  13. package/dist/components/virtual-window.js.map +1 -0
  14. package/dist/prenta-admin.css +1 -1
  15. package/dist/views/CollectionList.d.ts.map +1 -1
  16. package/dist/views/CollectionList.js +25 -14
  17. package/dist/views/CollectionList.js.map +1 -1
  18. package/dist/views/MediaBrowser.d.ts.map +1 -1
  19. package/dist/views/MediaBrowser.js +80 -23
  20. package/dist/views/MediaBrowser.js.map +1 -1
  21. package/dist/views/Pages/PagesListView.d.ts.map +1 -1
  22. package/dist/views/Pages/PagesListView.js +35 -2
  23. package/dist/views/Pages/PagesListView.js.map +1 -1
  24. package/dist/views/Posts/PostsListView.d.ts.map +1 -1
  25. package/dist/views/Posts/PostsListView.js +14 -2
  26. package/dist/views/Posts/PostsListView.js.map +1 -1
  27. package/dist/views/page-editor/PageSectionEditor.d.ts.map +1 -1
  28. package/dist/views/page-editor/PageSectionEditor.js +26 -6
  29. package/dist/views/page-editor/PageSectionEditor.js.map +1 -1
  30. package/dist/views/page-editor/autosave.d.ts +16 -0
  31. package/dist/views/page-editor/autosave.d.ts.map +1 -0
  32. package/dist/views/page-editor/autosave.js +23 -0
  33. package/dist/views/page-editor/autosave.js.map +1 -0
  34. package/dist/views/post-editor/PostSectionEditor.d.ts.map +1 -1
  35. package/dist/views/post-editor/PostSectionEditor.js +23 -6
  36. package/dist/views/post-editor/PostSectionEditor.js.map +1 -1
  37. package/package.json +4 -3
  38. package/src/__tests__/components/virtual-window.test.tsx +29 -0
  39. package/src/__tests__/views/autosave.test.tsx +66 -0
  40. package/src/components/virtual-window.tsx +81 -0
  41. package/src/views/CollectionList.tsx +14 -1
  42. package/src/views/MediaBrowser.tsx +155 -90
  43. package/src/views/Pages/PagesListView.tsx +67 -27
  44. package/src/views/Posts/PostsListView.tsx +29 -12
  45. package/src/views/page-editor/PageSectionEditor.tsx +28 -7
  46. package/src/views/page-editor/autosave.ts +30 -0
  47. package/src/views/post-editor/PostSectionEditor.tsx +25 -7
@@ -1,6 +1,6 @@
1
1
  'use client'
2
2
 
3
- import { useCallback, useEffect, useMemo, useState } from 'react'
3
+ import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
4
4
  import { AlertTriangle, Loader2, Lock } from 'lucide-react'
5
5
  import { toast } from 'sonner'
6
6
  import { ConfirmDialog } from '../../components/ui/ConfirmDialog.js'
@@ -11,6 +11,7 @@ import { EditorRailTabs, type RailTab, type RailTabId } from '../../components/E
11
11
  import { SeoEditorPane } from '../../components/seo/SeoEditorPane.js'
12
12
  import { ErrorBoundary } from '../../components/ErrorBoundary.js'
13
13
  import { VersionHistoryPanel } from '../page-editor/VersionHistoryPanel.js'
14
+ import { useDebouncedAutosave } from '../page-editor/autosave.js'
14
15
  import { ReviewBar } from '../page-editor/ReviewBar.js'
15
16
  import {
16
17
  fetchPageVersions,
@@ -436,24 +437,34 @@ export function PostSectionEditor({
436
437
  }, [])
437
438
 
438
439
  // ─── Save / publish ──────────────────────────────────────────────────
440
+ const latestPost = useRef(post)
441
+ latestPost.current = post
442
+
439
443
  const handleSaveDraft = useCallback(
440
- async (options?: { navigate?: boolean }): Promise<EditorPost | false> => {
444
+ async (options?: { navigate?: boolean; silent?: boolean }): Promise<EditorPost | false> => {
441
445
  if (!post) return false
442
446
  const result = validatePost(post, false)
443
447
  if (result.errors.length > 0) {
444
- setValidation(result)
445
- toast.error(result.errors[0]!)
446
- setFieldsOpen(true)
448
+ if (!options?.silent) {
449
+ setValidation(result)
450
+ toast.error(result.errors[0]!)
451
+ setFieldsOpen(true)
452
+ }
447
453
  return false
448
454
  }
455
+ const snapshot = post
449
456
  setSaveState('saving')
450
457
  try {
451
- const saved = await savePostDraft(post)
458
+ const saved = await savePostDraft(snapshot)
459
+ if (latestPost.current !== snapshot) {
460
+ setSaveState('idle')
461
+ return false
462
+ }
452
463
  acceptPost(saved)
453
464
  setDirty(false)
454
465
  setSaveState('saved')
455
466
  setValidation(null)
456
- toast.success('Draft saved')
467
+ if (!options?.silent) toast.success('Draft saved')
457
468
  if ((options?.navigate ?? true) && !documentId && saved.id) {
458
469
  onNavigate(`/posts/${postType}/${saved.id}/edit`)
459
470
  }
@@ -557,6 +568,13 @@ export function PostSectionEditor({
557
568
  const effectiveCanEdit = canEdit && !reviewing
558
569
  const canRestoreVersion = canEdit
559
570
 
571
+ useDebouncedAutosave({
572
+ dirty,
573
+ enabled: Boolean(documentId) && effectiveCanEdit && !publishing,
574
+ revision: post,
575
+ save: () => handleSaveDraft({ navigate: false, silent: true }),
576
+ })
577
+
560
578
  const runWorkflow = useCallback(
561
579
  async (stage: WorkflowStage, note?: string, toastOk?: string) => {
562
580
  if (!post) return