@actuate-media/cms-admin 0.66.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 (244) hide show
  1. package/CHANGELOG.md +37 -0
  2. package/dist/AdminRoot.d.ts.map +1 -1
  3. package/dist/AdminRoot.js +36 -9
  4. package/dist/AdminRoot.js.map +1 -1
  5. package/dist/__tests__/components/inspector-pane.test.d.ts +2 -0
  6. package/dist/__tests__/components/inspector-pane.test.d.ts.map +1 -0
  7. package/dist/__tests__/components/inspector-pane.test.js +31 -0
  8. package/dist/__tests__/components/inspector-pane.test.js.map +1 -0
  9. package/dist/__tests__/hooks/useIdleLogout.test.d.ts +2 -0
  10. package/dist/__tests__/hooks/useIdleLogout.test.d.ts.map +1 -0
  11. package/dist/__tests__/hooks/useIdleLogout.test.js +64 -0
  12. package/dist/__tests__/hooks/useIdleLogout.test.js.map +1 -0
  13. package/dist/__tests__/lib/pages-tree.test.d.ts +2 -0
  14. package/dist/__tests__/lib/pages-tree.test.d.ts.map +1 -0
  15. package/dist/__tests__/lib/pages-tree.test.js +173 -0
  16. package/dist/__tests__/lib/pages-tree.test.js.map +1 -0
  17. package/dist/__tests__/lib/post-types-service.test.d.ts +2 -0
  18. package/dist/__tests__/lib/post-types-service.test.d.ts.map +1 -0
  19. package/dist/__tests__/lib/post-types-service.test.js +88 -0
  20. package/dist/__tests__/lib/post-types-service.test.js.map +1 -0
  21. package/dist/__tests__/views/collection-list-nav.render.test.js +43 -5
  22. package/dist/__tests__/views/collection-list-nav.render.test.js.map +1 -1
  23. package/dist/__tests__/views/dashboard.test.js +7 -3
  24. package/dist/__tests__/views/dashboard.test.js.map +1 -1
  25. package/dist/__tests__/views/forms-list.render.test.js +25 -6
  26. package/dist/__tests__/views/forms-list.render.test.js.map +1 -1
  27. package/dist/__tests__/views/media-seo-audit.render.test.d.ts +2 -0
  28. package/dist/__tests__/views/media-seo-audit.render.test.d.ts.map +1 -0
  29. package/dist/__tests__/views/media-seo-audit.render.test.js +102 -0
  30. package/dist/__tests__/views/media-seo-audit.render.test.js.map +1 -0
  31. package/dist/__tests__/views/onboarding-block.render.test.d.ts +2 -0
  32. package/dist/__tests__/views/onboarding-block.render.test.d.ts.map +1 -0
  33. package/dist/__tests__/views/onboarding-block.render.test.js +146 -0
  34. package/dist/__tests__/views/onboarding-block.render.test.js.map +1 -0
  35. package/dist/__tests__/views/page-builder-sections-panel.render.test.d.ts +2 -0
  36. package/dist/__tests__/views/page-builder-sections-panel.render.test.d.ts.map +1 -0
  37. package/dist/__tests__/views/page-builder-sections-panel.render.test.js +121 -0
  38. package/dist/__tests__/views/page-builder-sections-panel.render.test.js.map +1 -0
  39. package/dist/__tests__/views/page-templates.render.test.d.ts +2 -0
  40. package/dist/__tests__/views/page-templates.render.test.d.ts.map +1 -0
  41. package/dist/__tests__/views/page-templates.render.test.js +105 -0
  42. package/dist/__tests__/views/page-templates.render.test.js.map +1 -0
  43. package/dist/__tests__/views/pages-list-view.test.js +77 -1
  44. package/dist/__tests__/views/pages-list-view.test.js.map +1 -1
  45. package/dist/__tests__/views/post-type-editor.render.test.d.ts +2 -0
  46. package/dist/__tests__/views/post-type-editor.render.test.d.ts.map +1 -0
  47. package/dist/__tests__/views/post-type-editor.render.test.js +102 -0
  48. package/dist/__tests__/views/post-type-editor.render.test.js.map +1 -0
  49. package/dist/__tests__/views/security-settings.render.test.js +85 -4
  50. package/dist/__tests__/views/security-settings.render.test.js.map +1 -1
  51. package/dist/__tests__/views/seo-content-pane.render.test.d.ts +2 -0
  52. package/dist/__tests__/views/seo-content-pane.render.test.d.ts.map +1 -0
  53. package/dist/__tests__/views/seo-content-pane.render.test.js +117 -0
  54. package/dist/__tests__/views/seo-content-pane.render.test.js.map +1 -0
  55. package/dist/actuate-admin.css +1 -1
  56. package/dist/components/collections/EntryDetailPane.d.ts +10 -0
  57. package/dist/components/collections/EntryDetailPane.d.ts.map +1 -0
  58. package/dist/components/collections/EntryDetailPane.js +92 -0
  59. package/dist/components/collections/EntryDetailPane.js.map +1 -0
  60. package/dist/components/forms/FieldsPanel.js +1 -1
  61. package/dist/components/forms/FieldsPanel.js.map +1 -1
  62. package/dist/components/forms/FormSchemaPane.d.ts +8 -0
  63. package/dist/components/forms/FormSchemaPane.d.ts.map +1 -0
  64. package/dist/components/forms/FormSchemaPane.js +95 -0
  65. package/dist/components/forms/FormSchemaPane.js.map +1 -0
  66. package/dist/components/script-tags/ScriptTagEditorPane.d.ts +26 -0
  67. package/dist/components/script-tags/ScriptTagEditorPane.d.ts.map +1 -0
  68. package/dist/components/script-tags/ScriptTagEditorPane.js +160 -0
  69. package/dist/components/script-tags/ScriptTagEditorPane.js.map +1 -0
  70. package/dist/components/seo/SeoEditorPane.d.ts +9 -0
  71. package/dist/components/seo/SeoEditorPane.d.ts.map +1 -0
  72. package/dist/components/seo/SeoEditorPane.js +175 -0
  73. package/dist/components/seo/SeoEditorPane.js.map +1 -0
  74. package/dist/components/ui/Badge.d.ts +1 -1
  75. package/dist/components/ui/Button.d.ts +1 -1
  76. package/dist/components/ui/InspectorPane.d.ts +51 -0
  77. package/dist/components/ui/InspectorPane.d.ts.map +1 -0
  78. package/dist/components/ui/InspectorPane.js +42 -0
  79. package/dist/components/ui/InspectorPane.js.map +1 -0
  80. package/dist/components/ui/StatusBadge.d.ts +1 -1
  81. package/dist/components/ui/index.d.ts +2 -0
  82. package/dist/components/ui/index.d.ts.map +1 -1
  83. package/dist/components/ui/index.js +1 -0
  84. package/dist/components/ui/index.js.map +1 -1
  85. package/dist/hooks/useIdleLogout.d.ts +18 -0
  86. package/dist/hooks/useIdleLogout.d.ts.map +1 -0
  87. package/dist/hooks/useIdleLogout.js +66 -0
  88. package/dist/hooks/useIdleLogout.js.map +1 -0
  89. package/dist/lib/api.d.ts +1 -0
  90. package/dist/lib/api.d.ts.map +1 -1
  91. package/dist/lib/api.js +7 -1
  92. package/dist/lib/api.js.map +1 -1
  93. package/dist/lib/page-editor-service.d.ts +11 -2
  94. package/dist/lib/page-editor-service.d.ts.map +1 -1
  95. package/dist/lib/page-editor-service.js +8 -2
  96. package/dist/lib/page-editor-service.js.map +1 -1
  97. package/dist/lib/pages-tree.d.ts +44 -0
  98. package/dist/lib/pages-tree.d.ts.map +1 -0
  99. package/dist/lib/pages-tree.js +106 -0
  100. package/dist/lib/pages-tree.js.map +1 -0
  101. package/dist/lib/post-types-service.d.ts +44 -0
  102. package/dist/lib/post-types-service.d.ts.map +1 -0
  103. package/dist/lib/post-types-service.js +83 -0
  104. package/dist/lib/post-types-service.js.map +1 -0
  105. package/dist/views/CollectionList.d.ts.map +1 -1
  106. package/dist/views/CollectionList.js +23 -4
  107. package/dist/views/CollectionList.js.map +1 -1
  108. package/dist/views/Dashboard.d.ts.map +1 -1
  109. package/dist/views/Dashboard.js +31 -2
  110. package/dist/views/Dashboard.js.map +1 -1
  111. package/dist/views/Forms.d.ts.map +1 -1
  112. package/dist/views/Forms.js +25 -21
  113. package/dist/views/Forms.js.map +1 -1
  114. package/dist/views/MediaBrowser.d.ts.map +1 -1
  115. package/dist/views/MediaBrowser.js +28 -2
  116. package/dist/views/MediaBrowser.js.map +1 -1
  117. package/dist/views/MediaSeoAudit.d.ts +25 -0
  118. package/dist/views/MediaSeoAudit.d.ts.map +1 -0
  119. package/dist/views/MediaSeoAudit.js +97 -0
  120. package/dist/views/MediaSeoAudit.js.map +1 -0
  121. package/dist/views/Pages/PagesListView.d.ts.map +1 -1
  122. package/dist/views/Pages/PagesListView.js +90 -10
  123. package/dist/views/Pages/PagesListView.js.map +1 -1
  124. package/dist/views/Pages/PagesTreeTable.d.ts +35 -0
  125. package/dist/views/Pages/PagesTreeTable.d.ts.map +1 -0
  126. package/dist/views/Pages/PagesTreeTable.js +28 -0
  127. package/dist/views/Pages/PagesTreeTable.js.map +1 -0
  128. package/dist/views/Posts/PostTypeEditor.d.ts +16 -0
  129. package/dist/views/Posts/PostTypeEditor.d.ts.map +1 -0
  130. package/dist/views/Posts/PostTypeEditor.js +159 -0
  131. package/dist/views/Posts/PostTypeEditor.js.map +1 -0
  132. package/dist/views/Posts/PostTypesView.d.ts +3 -2
  133. package/dist/views/Posts/PostTypesView.d.ts.map +1 -1
  134. package/dist/views/Posts/PostTypesView.js +1 -1
  135. package/dist/views/Posts/PostTypesView.js.map +1 -1
  136. package/dist/views/ScriptTags.d.ts +5 -1
  137. package/dist/views/ScriptTags.d.ts.map +1 -1
  138. package/dist/views/ScriptTags.js +32 -7
  139. package/dist/views/ScriptTags.js.map +1 -1
  140. package/dist/views/dashboard/OnboardingBlock.d.ts +29 -0
  141. package/dist/views/dashboard/OnboardingBlock.d.ts.map +1 -0
  142. package/dist/views/dashboard/OnboardingBlock.js +71 -0
  143. package/dist/views/dashboard/OnboardingBlock.js.map +1 -0
  144. package/dist/views/page-builder/BuilderSectionsPanel.d.ts +20 -0
  145. package/dist/views/page-builder/BuilderSectionsPanel.d.ts.map +1 -0
  146. package/dist/views/page-builder/BuilderSectionsPanel.js +105 -0
  147. package/dist/views/page-builder/BuilderSectionsPanel.js.map +1 -0
  148. package/dist/views/page-builder/PageBuilder.d.ts.map +1 -1
  149. package/dist/views/page-builder/PageBuilder.js +51 -2
  150. package/dist/views/page-builder/PageBuilder.js.map +1 -1
  151. package/dist/views/page-builder/PageTemplates.d.ts.map +1 -1
  152. package/dist/views/page-builder/PageTemplates.js +113 -6
  153. package/dist/views/page-builder/PageTemplates.js.map +1 -1
  154. package/dist/views/page-editor/PageSectionEditor.d.ts +7 -1
  155. package/dist/views/page-editor/PageSectionEditor.d.ts.map +1 -1
  156. package/dist/views/page-editor/PageSectionEditor.js +3 -3
  157. package/dist/views/page-editor/PageSectionEditor.js.map +1 -1
  158. package/dist/views/page-editor/PageSettingsModal.d.ts +1 -1
  159. package/dist/views/page-editor/PageSettingsModal.d.ts.map +1 -1
  160. package/dist/views/page-editor/PageSettingsModal.js +42 -3
  161. package/dist/views/page-editor/PageSettingsModal.js.map +1 -1
  162. package/dist/views/seo/ContentTab.d.ts.map +1 -1
  163. package/dist/views/seo/ContentTab.js +22 -6
  164. package/dist/views/seo/ContentTab.js.map +1 -1
  165. package/dist/views/settings/AccessProtectionCard.d.ts +5 -1
  166. package/dist/views/settings/AccessProtectionCard.d.ts.map +1 -1
  167. package/dist/views/settings/AccessProtectionCard.js +13 -10
  168. package/dist/views/settings/AccessProtectionCard.js.map +1 -1
  169. package/dist/views/settings/SecurityTab.d.ts.map +1 -1
  170. package/dist/views/settings/SecurityTab.js +3 -3
  171. package/dist/views/settings/SecurityTab.js.map +1 -1
  172. package/dist/views/settings/SessionPolicyCard.d.ts +1 -2
  173. package/dist/views/settings/SessionPolicyCard.d.ts.map +1 -1
  174. package/dist/views/settings/SessionPolicyCard.js +12 -5
  175. package/dist/views/settings/SessionPolicyCard.js.map +1 -1
  176. package/dist/views/settings/useSecuritySettings.d.ts +13 -1
  177. package/dist/views/settings/useSecuritySettings.d.ts.map +1 -1
  178. package/dist/views/settings/useSecuritySettings.js +47 -4
  179. package/dist/views/settings/useSecuritySettings.js.map +1 -1
  180. package/package.json +2 -2
  181. package/src/AdminRoot.tsx +43 -10
  182. package/src/__tests__/components/inspector-pane.test.tsx +64 -0
  183. package/src/__tests__/hooks/useIdleLogout.test.tsx +86 -0
  184. package/src/__tests__/lib/pages-tree.test.ts +197 -0
  185. package/src/__tests__/lib/post-types-service.test.ts +112 -0
  186. package/src/__tests__/views/collection-list-nav.render.test.tsx +51 -5
  187. package/src/__tests__/views/dashboard.test.tsx +7 -3
  188. package/src/__tests__/views/forms-list.render.test.tsx +34 -6
  189. package/src/__tests__/views/media-seo-audit.render.test.tsx +117 -0
  190. package/src/__tests__/views/onboarding-block.render.test.tsx +193 -0
  191. package/src/__tests__/views/page-builder-sections-panel.render.test.tsx +138 -0
  192. package/src/__tests__/views/page-templates.render.test.tsx +142 -0
  193. package/src/__tests__/views/pages-list-view.test.tsx +93 -1
  194. package/src/__tests__/views/post-type-editor.render.test.tsx +116 -0
  195. package/src/__tests__/views/security-settings.render.test.tsx +111 -4
  196. package/src/__tests__/views/seo-content-pane.render.test.tsx +142 -0
  197. package/src/components/collections/EntryDetailPane.tsx +182 -0
  198. package/src/components/forms/FieldsPanel.tsx +3 -1
  199. package/src/components/forms/FormSchemaPane.tsx +192 -0
  200. package/src/components/script-tags/ScriptTagEditorPane.tsx +474 -0
  201. package/src/components/seo/SeoEditorPane.tsx +533 -0
  202. package/src/components/ui/InspectorPane.tsx +129 -0
  203. package/src/components/ui/index.ts +10 -0
  204. package/src/hooks/useIdleLogout.ts +77 -0
  205. package/src/lib/api.ts +8 -2
  206. package/src/lib/page-editor-service.ts +16 -2
  207. package/src/lib/pages-tree.ts +145 -0
  208. package/src/lib/post-types-service.ts +129 -0
  209. package/src/views/CollectionList.tsx +158 -110
  210. package/src/views/Dashboard.tsx +238 -196
  211. package/src/views/Forms.tsx +154 -126
  212. package/src/views/MediaBrowser.tsx +641 -511
  213. package/src/views/MediaSeoAudit.tsx +320 -0
  214. package/src/views/Pages/PagesListView.tsx +352 -183
  215. package/src/views/Pages/PagesTreeTable.tsx +339 -0
  216. package/src/views/Posts/PostTypeEditor.tsx +568 -0
  217. package/src/views/Posts/PostTypesView.tsx +5 -4
  218. package/src/views/ScriptTags.tsx +204 -129
  219. package/src/views/dashboard/OnboardingBlock.tsx +233 -0
  220. package/src/views/page-builder/BuilderSectionsPanel.tsx +304 -0
  221. package/src/views/page-builder/PageBuilder.tsx +69 -2
  222. package/src/views/page-builder/PageTemplates.tsx +340 -57
  223. package/src/views/page-editor/PageSectionEditor.tsx +9 -2
  224. package/src/views/page-editor/PageSettingsModal.tsx +75 -2
  225. package/src/views/seo/ContentTab.tsx +113 -80
  226. package/src/views/settings/AccessProtectionCard.tsx +83 -53
  227. package/src/views/settings/SecurityTab.tsx +23 -2
  228. package/src/views/settings/SessionPolicyCard.tsx +45 -9
  229. package/src/views/settings/useSecuritySettings.ts +78 -22
  230. package/dist/components/forms/FormSchemaDrawer.d.ts +0 -9
  231. package/dist/components/forms/FormSchemaDrawer.d.ts.map +0 -1
  232. package/dist/components/forms/FormSchemaDrawer.js +0 -99
  233. package/dist/components/forms/FormSchemaDrawer.js.map +0 -1
  234. package/dist/components/seo/SeoEditorDrawer.d.ts +0 -8
  235. package/dist/components/seo/SeoEditorDrawer.d.ts.map +0 -1
  236. package/dist/components/seo/SeoEditorDrawer.js +0 -172
  237. package/dist/components/seo/SeoEditorDrawer.js.map +0 -1
  238. package/dist/views/ScriptTagEditor.d.ts +0 -6
  239. package/dist/views/ScriptTagEditor.d.ts.map +0 -1
  240. package/dist/views/ScriptTagEditor.js +0 -111
  241. package/dist/views/ScriptTagEditor.js.map +0 -1
  242. package/src/components/forms/FormSchemaDrawer.tsx +0 -192
  243. package/src/components/seo/SeoEditorDrawer.tsx +0 -529
  244. package/src/views/ScriptTagEditor.tsx +0 -353
@@ -1,111 +0,0 @@
1
- 'use client';
2
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
- import { useState, useEffect } from 'react';
4
- import { ArrowLeft, Loader2, AlertTriangle, Trash2, X, Plus } from 'lucide-react';
5
- import { toast } from 'sonner';
6
- import { EnabledSwitch } from '../components/EnabledSwitch.js';
7
- import { useApiData } from '../lib/useApiData.js';
8
- import { cmsApi } from '../lib/api.js';
9
- export function ScriptTagEditor({ tagId, onNavigate }) {
10
- const isNew = !tagId;
11
- const { data, loading, error } = useApiData(tagId ? `/script-tags` : null);
12
- const [name, setName] = useState('');
13
- const [code, setCode] = useState('');
14
- const [placement, setPlacement] = useState('head');
15
- const [scope, setScope] = useState('site');
16
- const [targetPaths, setTargetPaths] = useState([]);
17
- const [pathInput, setPathInput] = useState('');
18
- const [priority, setPriority] = useState(100);
19
- const [enabled, setEnabled] = useState(true);
20
- const [saving, setSaving] = useState(false);
21
- const [deleting, setDeleting] = useState(false);
22
- const [showDeleteConfirm, setShowDeleteConfirm] = useState(false);
23
- useEffect(() => {
24
- if (data && tagId) {
25
- const tags = Array.isArray(data) ? data : [];
26
- const tag = tags.find((t) => t.id === tagId);
27
- if (tag) {
28
- setName(tag.name ?? '');
29
- setCode(tag.code ?? '');
30
- setPlacement(tag.placement ?? 'head');
31
- setScope(tag.scope ?? 'site');
32
- setTargetPaths(tag.targetPaths ?? []);
33
- setPriority(tag.priority ?? 100);
34
- setEnabled(tag.enabled ?? true);
35
- }
36
- }
37
- }, [data, tagId]);
38
- const addPath = () => {
39
- const trimmed = pathInput.trim();
40
- if (!trimmed)
41
- return;
42
- const normalized = trimmed.startsWith('/') ? trimmed : `/${trimmed}`;
43
- if (!targetPaths.includes(normalized)) {
44
- setTargetPaths([...targetPaths, normalized]);
45
- }
46
- setPathInput('');
47
- };
48
- const removePath = (path) => {
49
- setTargetPaths(targetPaths.filter((p) => p !== path));
50
- };
51
- const handleSave = async () => {
52
- if (!name.trim()) {
53
- toast.error('Name is required');
54
- return;
55
- }
56
- if (!code.trim()) {
57
- toast.error('Code snippet is required');
58
- return;
59
- }
60
- if (scope !== 'site' && targetPaths.length === 0) {
61
- toast.error('At least one target path is required for this scope');
62
- return;
63
- }
64
- setSaving(true);
65
- const payload = {
66
- name: name.trim(),
67
- code,
68
- placement,
69
- scope,
70
- targetPaths: scope === 'site' ? [] : targetPaths,
71
- priority,
72
- enabled,
73
- };
74
- const res = isNew
75
- ? await cmsApi('/script-tags', { method: 'POST', body: JSON.stringify(payload) })
76
- : await cmsApi(`/script-tags/${tagId}`, { method: 'PUT', body: JSON.stringify(payload) });
77
- setSaving(false);
78
- if (res.error) {
79
- toast.error(res.error);
80
- }
81
- else {
82
- toast.success(isNew ? 'Tag created' : 'Tag updated');
83
- onNavigate?.('/script-tags');
84
- }
85
- };
86
- const handleDelete = async () => {
87
- if (!tagId)
88
- return;
89
- setDeleting(true);
90
- const res = await cmsApi(`/script-tags/${tagId}`, { method: 'DELETE' });
91
- setDeleting(false);
92
- if (res.error) {
93
- toast.error(res.error);
94
- }
95
- else {
96
- toast.success('Tag deleted');
97
- onNavigate?.('/script-tags');
98
- }
99
- };
100
- if (loading && !isNew) {
101
- return (_jsx("div", { className: "flex h-64 items-center justify-center p-3 pr-6 sm:p-4 sm:pr-8", children: _jsx(Loader2, { className: "text-primary h-6 w-6 animate-spin" }) }));
102
- }
103
- return (_jsxs("div", { className: "max-w-3xl p-3 pr-6 sm:p-4 sm:pr-8", children: [error && (_jsxs("div", { className: "border-destructive/30 bg-destructive/10 mb-4 flex items-center gap-3 rounded-lg border p-3", children: [_jsx(AlertTriangle, { className: "text-destructive h-5 w-5 shrink-0" }), _jsx("span", { className: "text-destructive flex-1 text-sm", children: error })] })), _jsxs("div", { className: "mb-6", children: [_jsxs("button", { type: "button", onClick: () => onNavigate?.('/script-tags'), className: "text-muted-foreground hover:text-foreground mb-3 flex items-center gap-1.5 text-sm transition-colors", children: [_jsx(ArrowLeft, { className: "h-4 w-4" }), "Back to Script Tags"] }), _jsx("h1", { className: "text-foreground", children: isNew ? 'New Script Tag' : 'Edit Script Tag' })] }), _jsx("div", { className: "border-warning/30 bg-warning/10 mb-6 rounded-lg border p-3", children: _jsxs("div", { className: "flex items-start gap-2", children: [_jsx(AlertTriangle, { className: "text-warning mt-0.5 h-4 w-4 shrink-0" }), _jsx("p", { className: "text-warning text-sm", children: "This code will run on public pages matching the scope below. Only add trusted code from verified sources (e.g. Google Analytics, Meta Pixel)." })] }) }), _jsxs("div", { className: "space-y-6", children: [_jsxs("div", { className: "border-border bg-card space-y-4 rounded-lg border p-4", children: [_jsxs("div", { children: [_jsx("label", { className: "text-foreground mb-1 block text-sm font-medium", children: "Name" }), _jsx("input", { type: "text", value: name, onChange: (e) => setName(e.target.value), placeholder: "e.g. Google Tag Manager, Facebook Pixel", className: "border-input focus:ring-ring w-full rounded-lg border px-3 py-2 text-sm focus:ring-2 focus:outline-none" })] }), _jsxs("div", { children: [_jsx("label", { className: "text-foreground mb-1 block text-sm font-medium", children: "Code" }), _jsx("textarea", { value: code, onChange: (e) => setCode(e.target.value), placeholder: "Paste your HTML/JavaScript snippet here...", rows: 10, className: "border-input focus:ring-ring w-full rounded-lg border px-3 py-2 font-mono text-sm focus:ring-2 focus:outline-none", spellCheck: false }), _jsxs("p", { className: "text-muted-foreground mt-1 text-xs", children: ["Paste the full code snippet including ", '<script>', " tags."] })] })] }), _jsxs("div", { className: "border-border bg-card space-y-4 rounded-lg border p-4", children: [_jsx("h3", { className: "text-foreground text-sm font-medium", children: "Placement & Scope" }), _jsxs("div", { children: [_jsx("label", { className: "text-foreground mb-1 block text-sm font-medium", children: "Placement" }), _jsxs("select", { value: placement, onChange: (e) => setPlacement(e.target.value), className: "border-input focus:ring-ring w-full rounded-lg border px-3 py-2 text-sm focus:ring-2 focus:outline-none", children: [_jsxs("option", { value: "head", children: ["Head \u2014 inside ", '<head>'] }), _jsxs("option", { value: "body_open", children: ["Body Open \u2014 right after ", '<body>'] }), _jsxs("option", { value: "body_close", children: ["Body Close \u2014 before ", '</body>'] })] }), _jsxs("p", { className: "text-muted-foreground mt-1 text-xs", children: [placement === 'head' && 'Best for analytics scripts, meta tags, and custom CSS.', placement === 'body_open' && 'Best for GTM noscript tags and early-loading scripts.', placement === 'body_close' &&
104
- 'Best for chat widgets, deferred scripts, and tracking pixels.'] })] }), _jsxs("div", { children: [_jsx("label", { className: "text-foreground mb-1 block text-sm font-medium", children: "Scope" }), _jsxs("select", { value: scope, onChange: (e) => setScope(e.target.value), className: "border-input focus:ring-ring w-full rounded-lg border px-3 py-2 text-sm focus:ring-2 focus:outline-none", children: [_jsx("option", { value: "site", children: "Entire Website" }), _jsx("option", { value: "parents", children: "Specific Parent Pages (includes child pages)" }), _jsx("option", { value: "urls", children: "Specific URLs (exact match)" })] })] }), scope !== 'site' && (_jsxs("div", { children: [_jsx("label", { className: "text-foreground mb-1 block text-sm font-medium", children: scope === 'parents' ? 'Parent Paths' : 'URL Paths' }), _jsxs("div", { className: "flex gap-2", children: [_jsx("input", { type: "text", value: pathInput, onChange: (e) => setPathInput(e.target.value), onKeyDown: (e) => {
105
- if (e.key === 'Enter') {
106
- e.preventDefault();
107
- addPath();
108
- }
109
- }, placeholder: "/services", className: "border-input focus:ring-ring flex-1 rounded-lg border px-3 py-2 font-mono text-sm focus:ring-2 focus:outline-none" }), _jsx("button", { type: "button", onClick: addPath, className: "border-input hover:bg-muted rounded-lg border px-3 py-2 text-sm transition-colors", children: _jsx(Plus, { className: "h-4 w-4" }) })] }), scope === 'parents' && (_jsx("p", { className: "text-muted-foreground mt-1 text-xs", children: "This tag will also apply to all child pages under each path." })), targetPaths.length > 0 && (_jsx("div", { className: "mt-2 flex flex-wrap gap-2", children: targetPaths.map((p) => (_jsxs("span", { className: "bg-muted text-foreground inline-flex items-center gap-1 rounded-full px-3 py-1 font-mono text-xs", children: [p, _jsx("button", { type: "button", onClick: () => removePath(p), className: "text-muted-foreground hover:text-muted-foreground ml-0.5", children: _jsx(X, { className: "h-3 w-3" }) })] }, p))) }))] })), _jsxs("div", { className: "grid grid-cols-2 gap-4", children: [_jsxs("div", { children: [_jsx("label", { className: "text-foreground mb-1 block text-sm font-medium", children: "Priority" }), _jsx("input", { type: "number", value: priority, onChange: (e) => setPriority(parseInt(e.target.value, 10) || 0), min: 0, className: "border-input focus:ring-ring w-full rounded-lg border px-3 py-2 text-sm focus:ring-2 focus:outline-none" }), _jsx("p", { className: "text-muted-foreground mt-1 text-xs", children: "Lower numbers load first (e.g. 1 = first, 100 = default)" })] }), _jsxs("div", { children: [_jsx("label", { className: "text-foreground mb-1 block text-sm font-medium", children: "Enabled" }), _jsx("div", { className: "pt-2", children: _jsx(EnabledSwitch, { checked: enabled, onCheckedChange: setEnabled, "aria-label": enabled ? 'Disable script tag' : 'Enable script tag' }) })] })] })] }), _jsxs("div", { className: "flex items-center justify-between", children: [_jsx("div", { children: !isNew && (_jsx(_Fragment, { children: showDeleteConfirm ? (_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("span", { className: "text-destructive text-sm", children: "Delete this tag?" }), _jsx("button", { type: "button", onClick: handleDelete, disabled: deleting, className: "bg-destructive text-destructive-foreground hover:bg-destructive/90 rounded-lg px-3 py-1.5 text-sm disabled:opacity-50", children: deleting ? 'Deleting...' : 'Confirm' }), _jsx("button", { type: "button", onClick: () => setShowDeleteConfirm(false), className: "border-input hover:bg-muted rounded-lg border px-3 py-1.5 text-sm", children: "Cancel" })] })) : (_jsxs("button", { type: "button", onClick: () => setShowDeleteConfirm(true), className: "text-destructive hover:text-destructive flex items-center gap-1.5 text-sm transition-colors", children: [_jsx(Trash2, { className: "h-4 w-4" }), "Delete"] })) })) }), _jsxs("div", { className: "flex items-center gap-3", children: [_jsx("button", { type: "button", onClick: () => onNavigate?.('/script-tags'), className: "border-input text-foreground hover:bg-muted rounded-lg border px-4 py-2 text-sm transition-colors", children: "Cancel" }), _jsx("button", { type: "button", onClick: handleSave, disabled: saving, className: "bg-primary text-primary-foreground hover:bg-primary/90 rounded-lg px-6 py-2 text-sm transition-colors disabled:opacity-50", children: saving ? 'Saving...' : isNew ? 'Create Tag' : 'Save Changes' })] })] })] })] }));
110
- }
111
- //# sourceMappingURL=ScriptTagEditor.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"ScriptTagEditor.js","sourceRoot":"","sources":["../../src/views/ScriptTagEditor.tsx"],"names":[],"mappings":"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"}
@@ -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
- }