@actuate-media/cms-admin 0.67.0 → 0.68.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 (146) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/dist/AdminRoot.d.ts.map +1 -1
  3. package/dist/AdminRoot.js +29 -5
  4. package/dist/AdminRoot.js.map +1 -1
  5. package/dist/__tests__/hooks/useIdleLogout.test.d.ts +2 -0
  6. package/dist/__tests__/hooks/useIdleLogout.test.d.ts.map +1 -0
  7. package/dist/__tests__/hooks/useIdleLogout.test.js +64 -0
  8. package/dist/__tests__/hooks/useIdleLogout.test.js.map +1 -0
  9. package/dist/__tests__/lib/post-types-service.test.d.ts +2 -0
  10. package/dist/__tests__/lib/post-types-service.test.d.ts.map +1 -0
  11. package/dist/__tests__/lib/post-types-service.test.js +88 -0
  12. package/dist/__tests__/lib/post-types-service.test.js.map +1 -0
  13. package/dist/__tests__/views/collection-list-nav.render.test.js +43 -5
  14. package/dist/__tests__/views/collection-list-nav.render.test.js.map +1 -1
  15. package/dist/__tests__/views/forms-list.render.test.js +25 -6
  16. package/dist/__tests__/views/forms-list.render.test.js.map +1 -1
  17. package/dist/__tests__/views/page-builder-sections-panel.render.test.d.ts +2 -0
  18. package/dist/__tests__/views/page-builder-sections-panel.render.test.d.ts.map +1 -0
  19. package/dist/__tests__/views/page-builder-sections-panel.render.test.js +121 -0
  20. package/dist/__tests__/views/page-builder-sections-panel.render.test.js.map +1 -0
  21. package/dist/__tests__/views/page-templates.render.test.d.ts +2 -0
  22. package/dist/__tests__/views/page-templates.render.test.d.ts.map +1 -0
  23. package/dist/__tests__/views/page-templates.render.test.js +105 -0
  24. package/dist/__tests__/views/page-templates.render.test.js.map +1 -0
  25. package/dist/__tests__/views/post-type-editor.render.test.d.ts +2 -0
  26. package/dist/__tests__/views/post-type-editor.render.test.d.ts.map +1 -0
  27. package/dist/__tests__/views/post-type-editor.render.test.js +102 -0
  28. package/dist/__tests__/views/post-type-editor.render.test.js.map +1 -0
  29. package/dist/__tests__/views/security-settings.render.test.js +85 -4
  30. package/dist/__tests__/views/security-settings.render.test.js.map +1 -1
  31. package/dist/__tests__/views/seo-content-pane.render.test.d.ts +2 -0
  32. package/dist/__tests__/views/seo-content-pane.render.test.d.ts.map +1 -0
  33. package/dist/__tests__/views/seo-content-pane.render.test.js +117 -0
  34. package/dist/__tests__/views/seo-content-pane.render.test.js.map +1 -0
  35. package/dist/actuate-admin.css +1 -1
  36. package/dist/components/collections/EntryDetailPane.d.ts +10 -0
  37. package/dist/components/collections/EntryDetailPane.d.ts.map +1 -0
  38. package/dist/components/collections/EntryDetailPane.js +92 -0
  39. package/dist/components/collections/EntryDetailPane.js.map +1 -0
  40. package/dist/components/forms/FieldsPanel.js +1 -1
  41. package/dist/components/forms/FieldsPanel.js.map +1 -1
  42. package/dist/components/forms/FormSchemaPane.d.ts +8 -0
  43. package/dist/components/forms/FormSchemaPane.d.ts.map +1 -0
  44. package/dist/components/forms/FormSchemaPane.js +95 -0
  45. package/dist/components/forms/FormSchemaPane.js.map +1 -0
  46. package/dist/components/seo/SeoEditorPane.d.ts +9 -0
  47. package/dist/components/seo/SeoEditorPane.d.ts.map +1 -0
  48. package/dist/components/seo/SeoEditorPane.js +175 -0
  49. package/dist/components/seo/SeoEditorPane.js.map +1 -0
  50. package/dist/components/ui/Badge.d.ts +1 -1
  51. package/dist/components/ui/Button.d.ts +1 -1
  52. package/dist/components/ui/StatusBadge.d.ts +1 -1
  53. package/dist/hooks/useIdleLogout.d.ts +18 -0
  54. package/dist/hooks/useIdleLogout.d.ts.map +1 -0
  55. package/dist/hooks/useIdleLogout.js +66 -0
  56. package/dist/hooks/useIdleLogout.js.map +1 -0
  57. package/dist/lib/api.d.ts +1 -0
  58. package/dist/lib/api.d.ts.map +1 -1
  59. package/dist/lib/api.js +7 -1
  60. package/dist/lib/api.js.map +1 -1
  61. package/dist/lib/post-types-service.d.ts +44 -0
  62. package/dist/lib/post-types-service.d.ts.map +1 -0
  63. package/dist/lib/post-types-service.js +83 -0
  64. package/dist/lib/post-types-service.js.map +1 -0
  65. package/dist/views/CollectionList.d.ts.map +1 -1
  66. package/dist/views/CollectionList.js +23 -4
  67. package/dist/views/CollectionList.js.map +1 -1
  68. package/dist/views/Forms.d.ts.map +1 -1
  69. package/dist/views/Forms.js +25 -21
  70. package/dist/views/Forms.js.map +1 -1
  71. package/dist/views/Posts/PostTypeEditor.d.ts +16 -0
  72. package/dist/views/Posts/PostTypeEditor.d.ts.map +1 -0
  73. package/dist/views/Posts/PostTypeEditor.js +159 -0
  74. package/dist/views/Posts/PostTypeEditor.js.map +1 -0
  75. package/dist/views/Posts/PostTypesView.d.ts +3 -2
  76. package/dist/views/Posts/PostTypesView.d.ts.map +1 -1
  77. package/dist/views/Posts/PostTypesView.js +1 -1
  78. package/dist/views/Posts/PostTypesView.js.map +1 -1
  79. package/dist/views/page-builder/BuilderSectionsPanel.d.ts +20 -0
  80. package/dist/views/page-builder/BuilderSectionsPanel.d.ts.map +1 -0
  81. package/dist/views/page-builder/BuilderSectionsPanel.js +105 -0
  82. package/dist/views/page-builder/BuilderSectionsPanel.js.map +1 -0
  83. package/dist/views/page-builder/PageBuilder.d.ts.map +1 -1
  84. package/dist/views/page-builder/PageBuilder.js +51 -2
  85. package/dist/views/page-builder/PageBuilder.js.map +1 -1
  86. package/dist/views/page-builder/PageTemplates.d.ts.map +1 -1
  87. package/dist/views/page-builder/PageTemplates.js +113 -6
  88. package/dist/views/page-builder/PageTemplates.js.map +1 -1
  89. package/dist/views/seo/ContentTab.d.ts.map +1 -1
  90. package/dist/views/seo/ContentTab.js +22 -6
  91. package/dist/views/seo/ContentTab.js.map +1 -1
  92. package/dist/views/settings/AccessProtectionCard.d.ts +5 -1
  93. package/dist/views/settings/AccessProtectionCard.d.ts.map +1 -1
  94. package/dist/views/settings/AccessProtectionCard.js +13 -10
  95. package/dist/views/settings/AccessProtectionCard.js.map +1 -1
  96. package/dist/views/settings/SecurityTab.d.ts.map +1 -1
  97. package/dist/views/settings/SecurityTab.js +3 -3
  98. package/dist/views/settings/SecurityTab.js.map +1 -1
  99. package/dist/views/settings/SessionPolicyCard.d.ts +1 -2
  100. package/dist/views/settings/SessionPolicyCard.d.ts.map +1 -1
  101. package/dist/views/settings/SessionPolicyCard.js +12 -5
  102. package/dist/views/settings/SessionPolicyCard.js.map +1 -1
  103. package/dist/views/settings/useSecuritySettings.d.ts +13 -1
  104. package/dist/views/settings/useSecuritySettings.d.ts.map +1 -1
  105. package/dist/views/settings/useSecuritySettings.js +47 -4
  106. package/dist/views/settings/useSecuritySettings.js.map +1 -1
  107. package/package.json +2 -2
  108. package/src/AdminRoot.tsx +36 -7
  109. package/src/__tests__/hooks/useIdleLogout.test.tsx +86 -0
  110. package/src/__tests__/lib/post-types-service.test.ts +112 -0
  111. package/src/__tests__/views/collection-list-nav.render.test.tsx +51 -5
  112. package/src/__tests__/views/forms-list.render.test.tsx +34 -6
  113. package/src/__tests__/views/page-builder-sections-panel.render.test.tsx +138 -0
  114. package/src/__tests__/views/page-templates.render.test.tsx +142 -0
  115. package/src/__tests__/views/post-type-editor.render.test.tsx +116 -0
  116. package/src/__tests__/views/security-settings.render.test.tsx +111 -4
  117. package/src/__tests__/views/seo-content-pane.render.test.tsx +142 -0
  118. package/src/components/collections/EntryDetailPane.tsx +182 -0
  119. package/src/components/forms/FieldsPanel.tsx +3 -1
  120. package/src/components/forms/FormSchemaPane.tsx +192 -0
  121. package/src/components/seo/SeoEditorPane.tsx +533 -0
  122. package/src/hooks/useIdleLogout.ts +77 -0
  123. package/src/lib/api.ts +8 -2
  124. package/src/lib/post-types-service.ts +129 -0
  125. package/src/views/CollectionList.tsx +158 -110
  126. package/src/views/Forms.tsx +154 -126
  127. package/src/views/Posts/PostTypeEditor.tsx +568 -0
  128. package/src/views/Posts/PostTypesView.tsx +5 -4
  129. package/src/views/page-builder/BuilderSectionsPanel.tsx +304 -0
  130. package/src/views/page-builder/PageBuilder.tsx +69 -2
  131. package/src/views/page-builder/PageTemplates.tsx +340 -57
  132. package/src/views/seo/ContentTab.tsx +113 -80
  133. package/src/views/settings/AccessProtectionCard.tsx +83 -53
  134. package/src/views/settings/SecurityTab.tsx +23 -2
  135. package/src/views/settings/SessionPolicyCard.tsx +45 -9
  136. package/src/views/settings/useSecuritySettings.ts +78 -22
  137. package/dist/components/forms/FormSchemaDrawer.d.ts +0 -9
  138. package/dist/components/forms/FormSchemaDrawer.d.ts.map +0 -1
  139. package/dist/components/forms/FormSchemaDrawer.js +0 -99
  140. package/dist/components/forms/FormSchemaDrawer.js.map +0 -1
  141. package/dist/components/seo/SeoEditorDrawer.d.ts +0 -8
  142. package/dist/components/seo/SeoEditorDrawer.d.ts.map +0 -1
  143. package/dist/components/seo/SeoEditorDrawer.js +0 -172
  144. package/dist/components/seo/SeoEditorDrawer.js.map +0 -1
  145. package/src/components/forms/FormSchemaDrawer.tsx +0 -192
  146. package/src/components/seo/SeoEditorDrawer.tsx +0 -529
@@ -1,192 +0,0 @@
1
- 'use client'
2
-
3
- /**
4
- * Form Schema drawer — the right-side panel opened from the Forms list "Schema"
5
- * action. Four tabs: Fields (versioned schema editor), Embed (public snippets
6
- * + domain restrictions), Notifications (email settings), Integrations (CRM
7
- * webhooks / Zapier).
8
- *
9
- * Saving the Fields tab creates a new schema version server-side; existing
10
- * submissions keep referencing the version they were captured against, so
11
- * historical entries never break when the schema changes.
12
- */
13
- import * as Tabs from '@radix-ui/react-tabs'
14
- import { useEffect, useState } from 'react'
15
- import { toast } from 'sonner'
16
- import { fetchFormSchema, saveFormSchema, type FormField } from '../../lib/forms-service.js'
17
- import type { FormListItem } from '../../lib/forms-service.js'
18
- import { emitFormsChanged } from '../../lib/forms-events.js'
19
- import { ConfirmDialog } from '../ui/ConfirmDialog.js'
20
- import { Drawer } from './Drawer.js'
21
- import { FieldsPanel } from './FieldsPanel.js'
22
- import { EmbedPanel } from './EmbedPanel.js'
23
- import { NotificationsPanel } from './NotificationsPanel.js'
24
- import { WebhooksPanel } from './WebhooksPanel.js'
25
- import { FormsErrorState, FormsLoading, btnPrimary, btnSecondary } from './primitives.js'
26
-
27
- const TABS = [
28
- { id: 'fields', label: 'Fields' },
29
- { id: 'embed', label: 'Embed' },
30
- { id: 'notifications', label: 'Notifications' },
31
- { id: 'integrations', label: 'Integrations' },
32
- ] as const
33
-
34
- export function FormSchemaDrawer({
35
- form,
36
- open,
37
- onOpenChange,
38
- onSaved,
39
- }: {
40
- form: FormListItem | null
41
- open: boolean
42
- onOpenChange: (open: boolean) => void
43
- /** Called after a schema/settings change so the list can refetch. */
44
- onSaved?: () => void
45
- }) {
46
- const [tab, setTab] = useState<string>('fields')
47
- const [fields, setFields] = useState<FormField[]>([])
48
- const [loading, setLoading] = useState(false)
49
- const [error, setError] = useState<string | null>(null)
50
- const [dirty, setDirty] = useState(false)
51
- const [saving, setSaving] = useState(false)
52
- const [confirmDiscard, setConfirmDiscard] = useState(false)
53
-
54
- const formId = form?.id ?? null
55
- const hasSubmissions = (form?.totalEntries ?? 0) > 0
56
-
57
- useEffect(() => {
58
- if (!open || !formId) return
59
- setTab('fields')
60
- setDirty(false)
61
- setLoading(true)
62
- setError(null)
63
- let active = true
64
- fetchFormSchema(formId)
65
- .then((schema) => {
66
- if (active) setFields(schema.fields)
67
- })
68
- .catch((e: unknown) => {
69
- if (active) setError(e instanceof Error ? e.message : 'Failed to load schema')
70
- })
71
- .finally(() => {
72
- if (active) setLoading(false)
73
- })
74
- return () => {
75
- active = false
76
- }
77
- }, [open, formId])
78
-
79
- function handleFieldsChange(next: FormField[]) {
80
- setFields(next)
81
- setDirty(true)
82
- }
83
-
84
- async function handleSave() {
85
- if (!formId) return
86
- setSaving(true)
87
- const res = await saveFormSchema(
88
- formId,
89
- fields.map((f, i) => ({ ...f, sortOrder: i })),
90
- )
91
- setSaving(false)
92
- if (res.error) {
93
- toast.error(res.error)
94
- return
95
- }
96
- setDirty(false)
97
- toast.success('Schema saved.')
98
- emitFormsChanged()
99
- onSaved?.()
100
- }
101
-
102
- function requestClose(next: boolean) {
103
- if (!next && dirty) {
104
- setConfirmDiscard(true)
105
- return
106
- }
107
- onOpenChange(next)
108
- }
109
-
110
- if (!form) return null
111
-
112
- return (
113
- <>
114
- <Drawer
115
- open={open}
116
- onOpenChange={requestClose}
117
- title={form.name}
118
- description={`/${form.slug}`}
119
- width="max-w-2xl"
120
- footer={
121
- tab === 'fields' ? (
122
- <>
123
- <button className={btnSecondary} onClick={() => requestClose(false)}>
124
- Close
125
- </button>
126
- <button className={btnPrimary} onClick={handleSave} disabled={saving || loading}>
127
- {saving ? 'Saving…' : 'Save Schema'}
128
- </button>
129
- </>
130
- ) : undefined
131
- }
132
- >
133
- <Tabs.Root value={tab} onValueChange={setTab}>
134
- <Tabs.List
135
- className="border-border mb-4 flex gap-1 border-b"
136
- aria-label="Form schema sections"
137
- >
138
- {TABS.map((t) => (
139
- <Tabs.Trigger
140
- key={t.id}
141
- value={t.id}
142
- className="text-muted-foreground hover:text-foreground data-[state=active]:text-foreground data-[state=active]:border-primary focus-visible:ring-ring -mb-px border-b-2 border-transparent px-3 py-2 text-sm font-medium transition-colors focus-visible:ring-2 focus-visible:outline-none"
143
- >
144
- {t.label}
145
- </Tabs.Trigger>
146
- ))}
147
- </Tabs.List>
148
-
149
- <Tabs.Content value="fields" tabIndex={-1}>
150
- {loading ? (
151
- <FormsLoading label="Loading schema…" />
152
- ) : error ? (
153
- <FormsErrorState message={error} onRetry={() => formId && setTab('fields')} />
154
- ) : (
155
- <FieldsPanel
156
- fields={fields}
157
- onChange={handleFieldsChange}
158
- hasSubmissions={hasSubmissions}
159
- />
160
- )}
161
- </Tabs.Content>
162
-
163
- <Tabs.Content value="embed" tabIndex={-1}>
164
- {formId && <EmbedPanel formId={formId} slug={form.slug} status={form.status} />}
165
- </Tabs.Content>
166
-
167
- <Tabs.Content value="notifications" tabIndex={-1}>
168
- {formId && <NotificationsPanel formId={formId} onChanged={onSaved} />}
169
- </Tabs.Content>
170
-
171
- <Tabs.Content value="integrations" tabIndex={-1}>
172
- {formId && <WebhooksPanel formId={formId} formSlug={form.slug} />}
173
- </Tabs.Content>
174
- </Tabs.Root>
175
- </Drawer>
176
-
177
- <ConfirmDialog
178
- open={confirmDiscard}
179
- onClose={() => setConfirmDiscard(false)}
180
- onConfirm={() => {
181
- setDirty(false)
182
- onOpenChange(false)
183
- }}
184
- title="Discard unsaved changes?"
185
- description="You have unsaved schema changes. Closing now will discard them."
186
- confirmLabel="Discard"
187
- cancelLabel="Keep editing"
188
- destructive
189
- />
190
- </>
191
- )
192
- }