@actuate-media/cms-admin 0.7.0 → 0.7.2
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/AdminRoot.d.ts.map +1 -1
- package/dist/AdminRoot.js +8 -4
- package/dist/AdminRoot.js.map +1 -1
- package/dist/actuate-admin.css +1 -1
- package/dist/lib/search.d.ts +2 -2
- package/dist/lib/search.d.ts.map +1 -1
- package/dist/lib/search.js +5 -2
- package/dist/lib/search.js.map +1 -1
- package/dist/views/FormSubmissions.js +11 -11
- package/dist/views/FormSubmissions.js.map +1 -1
- package/dist/views/Forms.js +1 -1
- package/dist/views/Forms.js.map +1 -1
- package/dist/views/MediaBrowser.d.ts.map +1 -1
- package/dist/views/MediaBrowser.js +28 -8
- package/dist/views/MediaBrowser.js.map +1 -1
- package/dist/views/Pages.d.ts.map +1 -1
- package/dist/views/Pages.js +7 -4
- package/dist/views/Pages.js.map +1 -1
- package/dist/views/Posts.js +1 -1
- package/dist/views/Posts.js.map +1 -1
- package/dist/views/Redirects.js +2 -2
- package/dist/views/Redirects.js.map +1 -1
- package/dist/views/SEO.js +3 -3
- package/dist/views/SEO.js.map +1 -1
- package/dist/views/ScriptTags.d.ts.map +1 -1
- package/dist/views/ScriptTags.js +8 -6
- package/dist/views/ScriptTags.js.map +1 -1
- package/dist/views/Users.js +3 -3
- package/dist/views/Users.js.map +1 -1
- package/dist/views/page-builder/PageTemplates.d.ts +5 -0
- package/dist/views/page-builder/PageTemplates.d.ts.map +1 -0
- package/dist/views/page-builder/PageTemplates.js +13 -0
- package/dist/views/page-builder/PageTemplates.js.map +1 -0
- package/package.json +2 -2
- package/src/AdminRoot.tsx +10 -5
- package/src/lib/search.ts +8 -4
- package/src/views/FormSubmissions.tsx +12 -12
- package/src/views/Forms.tsx +1 -1
- package/src/views/MediaBrowser.tsx +46 -15
- package/src/views/Pages.tsx +8 -4
- package/src/views/Posts.tsx +1 -1
- package/src/views/Redirects.tsx +2 -2
- package/src/views/SEO.tsx +3 -3
- package/src/views/ScriptTags.tsx +8 -6
- package/src/views/Users.tsx +3 -3
- package/src/views/page-builder/PageTemplates.tsx +105 -0
package/src/views/SEO.tsx
CHANGED
|
@@ -44,7 +44,7 @@ export function SEO({ onNavigate, initialTab = 'pages' }: SEOProps) {
|
|
|
44
44
|
// --- Pages tab data ---
|
|
45
45
|
const filtered = seoPages
|
|
46
46
|
.filter((page: any) => {
|
|
47
|
-
const matchesSearch = page.url.toLowerCase().includes(searchQuery.toLowerCase()) || page.title.toLowerCase().includes(searchQuery.toLowerCase());
|
|
47
|
+
const matchesSearch = (page.url ?? '').toLowerCase().includes(searchQuery.toLowerCase()) || (page.title ?? '').toLowerCase().includes(searchQuery.toLowerCase());
|
|
48
48
|
const matchesScore = filterScore === 'all' || (filterScore === 'good' && page.score >= 80) || (filterScore === 'warning' && page.score >= 50 && page.score < 80) || (filterScore === 'critical' && page.score < 50);
|
|
49
49
|
return matchesSearch && matchesScore;
|
|
50
50
|
})
|
|
@@ -62,8 +62,8 @@ export function SEO({ onNavigate, initialTab = 'pages' }: SEOProps) {
|
|
|
62
62
|
|
|
63
63
|
// --- Redirects data ---
|
|
64
64
|
const filteredRedirects = redirects.filter((r: any) =>
|
|
65
|
-
r.from.toLowerCase().includes(redirectSearch.toLowerCase()) ||
|
|
66
|
-
r.to.toLowerCase().includes(redirectSearch.toLowerCase())
|
|
65
|
+
(r.from ?? '').toLowerCase().includes(redirectSearch.toLowerCase()) ||
|
|
66
|
+
(r.to ?? '').toLowerCase().includes(redirectSearch.toLowerCase())
|
|
67
67
|
);
|
|
68
68
|
|
|
69
69
|
const handleScan = async () => {
|
package/src/views/ScriptTags.tsx
CHANGED
|
@@ -36,16 +36,18 @@ const PLACEMENT_COLORS: Record<string, string> = {
|
|
|
36
36
|
};
|
|
37
37
|
|
|
38
38
|
function scopeLabel(tag: ScriptTag): string {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
39
|
+
const scope = String(tag.scope ?? '');
|
|
40
|
+
const targetPaths = Array.isArray(tag.targetPaths) ? tag.targetPaths : [];
|
|
41
|
+
if (scope === 'site') return 'Entire Site';
|
|
42
|
+
if (scope === 'parents') {
|
|
43
|
+
const count = targetPaths.length;
|
|
42
44
|
return `${count} parent path${count !== 1 ? 's' : ''} + children`;
|
|
43
45
|
}
|
|
44
|
-
if (
|
|
45
|
-
const count =
|
|
46
|
+
if (scope === 'urls') {
|
|
47
|
+
const count = targetPaths.length;
|
|
46
48
|
return `${count} URL${count !== 1 ? 's' : ''}`;
|
|
47
49
|
}
|
|
48
|
-
return
|
|
50
|
+
return scope || 'Custom';
|
|
49
51
|
}
|
|
50
52
|
|
|
51
53
|
export function ScriptTags({ onNavigate }: ScriptTagsProps) {
|
package/src/views/Users.tsx
CHANGED
|
@@ -28,9 +28,9 @@ export function Users({ onNavigate }: UsersProps) {
|
|
|
28
28
|
const filteredAndSorted = useMemo(() => {
|
|
29
29
|
let results = users.filter((user: any) => {
|
|
30
30
|
const matchesSearch =
|
|
31
|
-
user.name.toLowerCase().includes(searchQuery.toLowerCase()) ||
|
|
32
|
-
user.email.toLowerCase().includes(searchQuery.toLowerCase());
|
|
33
|
-
const matchesRole = filterRole === 'all' || user.role.toLowerCase() === filterRole.toLowerCase();
|
|
31
|
+
(user.name ?? '').toLowerCase().includes(searchQuery.toLowerCase()) ||
|
|
32
|
+
(user.email ?? '').toLowerCase().includes(searchQuery.toLowerCase());
|
|
33
|
+
const matchesRole = filterRole === 'all' || (user.role ?? '').toLowerCase() === filterRole.toLowerCase();
|
|
34
34
|
return matchesSearch && matchesRole;
|
|
35
35
|
});
|
|
36
36
|
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { AlertTriangle, Layers, Loader2, RefreshCw } from 'lucide-react';
|
|
4
|
+
import { useApiData } from '../../lib/useApiData.js';
|
|
5
|
+
|
|
6
|
+
interface PageTemplate {
|
|
7
|
+
id: string;
|
|
8
|
+
name?: string;
|
|
9
|
+
description?: string | null;
|
|
10
|
+
category?: string;
|
|
11
|
+
builtIn?: boolean;
|
|
12
|
+
updatedAt?: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface PageTemplatesProps {
|
|
16
|
+
onNavigate?: (path: string) => void;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function PageTemplates({ onNavigate }: PageTemplatesProps) {
|
|
20
|
+
const { data, loading, error, refetch } = useApiData<PageTemplate[]>('/page-templates');
|
|
21
|
+
const templates = data ?? [];
|
|
22
|
+
|
|
23
|
+
if (loading) {
|
|
24
|
+
return (
|
|
25
|
+
<div className="flex h-64 items-center justify-center p-4" role="status" aria-live="polite">
|
|
26
|
+
<Loader2 className="h-6 w-6 animate-spin text-primary" />
|
|
27
|
+
<span className="sr-only">Loading page templates</span>
|
|
28
|
+
</div>
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return (
|
|
33
|
+
<div className="p-4 pr-8">
|
|
34
|
+
{error && (
|
|
35
|
+
<div className="mb-4 flex items-center gap-3 rounded-lg border border-border bg-card p-3">
|
|
36
|
+
<AlertTriangle className="h-5 w-5 shrink-0 text-muted-foreground" />
|
|
37
|
+
<span className="flex-1 text-sm text-foreground">{error}</span>
|
|
38
|
+
<button
|
|
39
|
+
type="button"
|
|
40
|
+
onClick={refetch}
|
|
41
|
+
className="rounded-md border border-border px-3 py-1 text-sm text-foreground hover:bg-accent"
|
|
42
|
+
>
|
|
43
|
+
Retry
|
|
44
|
+
</button>
|
|
45
|
+
</div>
|
|
46
|
+
)}
|
|
47
|
+
|
|
48
|
+
<div className="mb-4 flex items-center justify-between">
|
|
49
|
+
<div>
|
|
50
|
+
<h1 className="mb-1 text-2xl font-medium text-foreground">Page Templates</h1>
|
|
51
|
+
<p className="text-sm text-muted-foreground">
|
|
52
|
+
{templates.length} saved template{templates.length === 1 ? '' : 's'}
|
|
53
|
+
</p>
|
|
54
|
+
</div>
|
|
55
|
+
<button
|
|
56
|
+
type="button"
|
|
57
|
+
onClick={refetch}
|
|
58
|
+
className="inline-flex items-center gap-2 rounded-md border border-border px-3 py-2 text-sm font-medium text-foreground hover:bg-accent"
|
|
59
|
+
>
|
|
60
|
+
<RefreshCw className="h-4 w-4" />
|
|
61
|
+
Refresh
|
|
62
|
+
</button>
|
|
63
|
+
</div>
|
|
64
|
+
|
|
65
|
+
{templates.length === 0 ? (
|
|
66
|
+
<div className="rounded-lg border border-border bg-card p-8 text-center">
|
|
67
|
+
<Layers className="mx-auto mb-3 h-8 w-8 text-muted-foreground" />
|
|
68
|
+
<h2 className="mb-1 text-lg font-medium text-foreground">No page templates yet</h2>
|
|
69
|
+
<p className="mb-4 text-sm text-muted-foreground">
|
|
70
|
+
Built-in templates are seeded by the CMS when the templates API is available.
|
|
71
|
+
</p>
|
|
72
|
+
<button
|
|
73
|
+
type="button"
|
|
74
|
+
onClick={() => onNavigate?.('/saved-sections')}
|
|
75
|
+
className="rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground hover:opacity-90"
|
|
76
|
+
>
|
|
77
|
+
View Saved Sections
|
|
78
|
+
</button>
|
|
79
|
+
</div>
|
|
80
|
+
) : (
|
|
81
|
+
<div className="grid grid-cols-1 gap-4 md:grid-cols-2 xl:grid-cols-3">
|
|
82
|
+
{templates.map((template) => (
|
|
83
|
+
<div key={template.id} className="rounded-lg border border-border bg-card p-4">
|
|
84
|
+
<div className="mb-3 flex items-start justify-between gap-3">
|
|
85
|
+
<div>
|
|
86
|
+
<h2 className="text-base font-medium text-foreground">{template.name ?? 'Untitled template'}</h2>
|
|
87
|
+
<p className="mt-1 text-sm text-muted-foreground">{template.description ?? 'No description provided.'}</p>
|
|
88
|
+
</div>
|
|
89
|
+
{template.builtIn && (
|
|
90
|
+
<span className="rounded-full bg-muted px-2 py-0.5 text-xs text-muted-foreground">
|
|
91
|
+
Built-in
|
|
92
|
+
</span>
|
|
93
|
+
)}
|
|
94
|
+
</div>
|
|
95
|
+
<div className="flex items-center justify-between text-sm text-muted-foreground">
|
|
96
|
+
<span>{template.category ?? 'content'}</span>
|
|
97
|
+
<span>{template.updatedAt ? new Date(template.updatedAt).toLocaleDateString() : ''}</span>
|
|
98
|
+
</div>
|
|
99
|
+
</div>
|
|
100
|
+
))}
|
|
101
|
+
</div>
|
|
102
|
+
)}
|
|
103
|
+
</div>
|
|
104
|
+
);
|
|
105
|
+
}
|