@actuate-media/cms-admin 0.18.0 → 0.19.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.
- package/dist/__tests__/lib/post-editor-service.test.js +75 -23
- package/dist/__tests__/lib/post-editor-service.test.js.map +1 -1
- package/dist/__tests__/lib/posts-service.test.js +132 -142
- package/dist/__tests__/lib/posts-service.test.js.map +1 -1
- package/dist/__tests__/views/posts-list-view.render.test.d.ts +2 -0
- package/dist/__tests__/views/posts-list-view.render.test.d.ts.map +1 -0
- package/dist/__tests__/views/posts-list-view.render.test.js +73 -0
- package/dist/__tests__/views/posts-list-view.render.test.js.map +1 -0
- package/dist/actuate-admin.css +1 -1
- package/dist/index.d.ts +0 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +0 -2
- package/dist/index.js.map +1 -1
- package/dist/lib/post-editor-service.d.ts +6 -4
- package/dist/lib/post-editor-service.d.ts.map +1 -1
- package/dist/lib/post-editor-service.js +32 -37
- package/dist/lib/post-editor-service.js.map +1 -1
- package/dist/lib/posts-service.d.ts.map +1 -1
- package/dist/lib/posts-service.js +91 -160
- package/dist/lib/posts-service.js.map +1 -1
- package/dist/views/Posts/NewPostPicker.d.ts +5 -4
- package/dist/views/Posts/NewPostPicker.d.ts.map +1 -1
- package/dist/views/Posts/NewPostPicker.js +5 -4
- package/dist/views/Posts/NewPostPicker.js.map +1 -1
- package/dist/views/Posts/PostTypesView.d.ts +5 -4
- package/dist/views/Posts/PostTypesView.d.ts.map +1 -1
- package/dist/views/Posts/PostTypesView.js.map +1 -1
- package/dist/views/Posts/PostsListView.d.ts.map +1 -1
- package/dist/views/Posts/PostsListView.js +8 -0
- package/dist/views/Posts/PostsListView.js.map +1 -1
- package/dist/views/page-editor/sections/ArticleBodySection.d.ts +6 -2
- package/dist/views/page-editor/sections/ArticleBodySection.d.ts.map +1 -1
- package/dist/views/page-editor/sections/ArticleBodySection.js +8 -8
- package/dist/views/page-editor/sections/ArticleBodySection.js.map +1 -1
- package/dist/views/post-editor/PostEditorCanvas.js +7 -1
- package/dist/views/post-editor/PostEditorCanvas.js.map +1 -1
- package/dist/views/post-editor/PostFieldsModal.d.ts.map +1 -1
- package/dist/views/post-editor/PostFieldsModal.js +10 -4
- package/dist/views/post-editor/PostFieldsModal.js.map +1 -1
- package/dist/views/post-editor/PostHeader.d.ts.map +1 -1
- package/dist/views/post-editor/PostHeader.js +4 -3
- package/dist/views/post-editor/PostHeader.js.map +1 -1
- package/dist/views/post-editor/PostPreview.d.ts.map +1 -1
- package/dist/views/post-editor/PostPreview.js +11 -1
- package/dist/views/post-editor/PostPreview.js.map +1 -1
- package/dist/views/post-editor/PostSectionEditor.d.ts +22 -2
- package/dist/views/post-editor/PostSectionEditor.d.ts.map +1 -1
- package/dist/views/post-editor/PostSectionEditor.js +4 -1
- package/dist/views/post-editor/PostSectionEditor.js.map +1 -1
- package/package.json +2 -2
- package/src/__tests__/lib/post-editor-service.test.ts +78 -23
- package/src/__tests__/lib/posts-service.test.ts +134 -163
- package/src/__tests__/views/posts-list-view.render.test.tsx +84 -0
- package/src/index.ts +0 -2
- package/src/lib/post-editor-service.ts +41 -40
- package/src/lib/posts-service.ts +109 -180
- package/src/views/Posts/NewPostPicker.tsx +5 -4
- package/src/views/Posts/PostTypesView.tsx +5 -4
- package/src/views/Posts/PostsListView.tsx +9 -0
- package/src/views/page-editor/sections/ArticleBodySection.tsx +12 -16
- package/src/views/post-editor/PostEditorCanvas.tsx +7 -1
- package/src/views/post-editor/PostFieldsModal.tsx +36 -21
- package/src/views/post-editor/PostHeader.tsx +4 -4
- package/src/views/post-editor/PostPreview.tsx +12 -1
- package/src/views/post-editor/PostSectionEditor.tsx +22 -5
- package/dist/views/PostEditor.d.ts +0 -6
- package/dist/views/PostEditor.d.ts.map +0 -1
- package/dist/views/PostEditor.js +0 -79
- package/dist/views/PostEditor.js.map +0 -1
- package/dist/views/Posts.d.ts +0 -5
- package/dist/views/Posts.d.ts.map +0 -1
- package/dist/views/Posts.js +0 -73
- package/dist/views/Posts.js.map +0 -1
- package/src/views/PostEditor.tsx +0 -257
- package/src/views/Posts.tsx +0 -375
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
import { useEffect, useState } from 'react'
|
|
4
4
|
import { Modal } from '../../components/ui/Modal.js'
|
|
5
5
|
import { Button } from '../../components/ui/Button.js'
|
|
6
|
+
import { MediaPickerModal } from '../../components/MediaPickerModal.js'
|
|
7
|
+
import { RichTextField } from '../../fields/RichTextField.js'
|
|
6
8
|
import type { EditorPost } from '../../lib/post-editor-service.js'
|
|
7
9
|
|
|
8
10
|
interface PostFieldsModalProps {
|
|
@@ -36,6 +38,7 @@ export function PostFieldsModal({ open, post, canEdit, onClose, onSave }: PostFi
|
|
|
36
38
|
const [seoTitle, setSeoTitle] = useState(post.seoTitle)
|
|
37
39
|
const [seoDescription, setSeoDescription] = useState(post.seoDescription)
|
|
38
40
|
const [slugTouched, setSlugTouched] = useState(Boolean(post.slug))
|
|
41
|
+
const [mediaOpen, setMediaOpen] = useState(false)
|
|
39
42
|
|
|
40
43
|
useEffect(() => {
|
|
41
44
|
if (!open) return
|
|
@@ -134,16 +137,26 @@ export function PostFieldsModal({ open, post, canEdit, onClose, onSave }: PostFi
|
|
|
134
137
|
</div>
|
|
135
138
|
<div>
|
|
136
139
|
<label className={LABEL} htmlFor="pf-image">
|
|
137
|
-
Featured image
|
|
140
|
+
Featured image
|
|
138
141
|
</label>
|
|
139
|
-
<
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
142
|
+
<div className="flex gap-2">
|
|
143
|
+
<input
|
|
144
|
+
id="pf-image"
|
|
145
|
+
className={`${INPUT} flex-1`}
|
|
146
|
+
value={featuredImage}
|
|
147
|
+
disabled={!canEdit}
|
|
148
|
+
placeholder="https://… or pick from the media library"
|
|
149
|
+
onChange={(e) => setFeaturedImage(e.target.value)}
|
|
150
|
+
/>
|
|
151
|
+
<button
|
|
152
|
+
type="button"
|
|
153
|
+
disabled={!canEdit}
|
|
154
|
+
onClick={() => setMediaOpen(true)}
|
|
155
|
+
className="bg-accent text-foreground border-border hover:bg-accent/80 shrink-0 rounded-md border px-3 py-1.5 text-xs font-medium disabled:opacity-50"
|
|
156
|
+
>
|
|
157
|
+
Browse
|
|
158
|
+
</button>
|
|
159
|
+
</div>
|
|
147
160
|
{featuredImage && (
|
|
148
161
|
<div className="border-border bg-muted mt-2 overflow-hidden rounded-md border">
|
|
149
162
|
<img src={featuredImage} alt="" className="h-28 w-full object-cover" />
|
|
@@ -151,20 +164,12 @@ export function PostFieldsModal({ open, post, canEdit, onClose, onSave }: PostFi
|
|
|
151
164
|
)}
|
|
152
165
|
</div>
|
|
153
166
|
<div>
|
|
154
|
-
<
|
|
155
|
-
Body
|
|
156
|
-
</label>
|
|
157
|
-
<textarea
|
|
158
|
-
id="pf-body"
|
|
159
|
-
className={`${INPUT} min-h-[120px] resize-y`}
|
|
167
|
+
<RichTextField
|
|
168
|
+
label="Body"
|
|
160
169
|
value={body}
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
onChange={(e) => setBody(e.target.value)}
|
|
170
|
+
onChange={canEdit ? setBody : () => {}}
|
|
171
|
+
helpText="Rendered by the Article Body section when its source is set to the post Body field."
|
|
164
172
|
/>
|
|
165
|
-
<p className="text-muted-foreground mt-1 text-xs">
|
|
166
|
-
Rendered by the Article Body section when its source is set to the post Body field.
|
|
167
|
-
</p>
|
|
168
173
|
</div>
|
|
169
174
|
<div>
|
|
170
175
|
<label className={LABEL} htmlFor="pf-seo-title">
|
|
@@ -191,6 +196,16 @@ export function PostFieldsModal({ open, post, canEdit, onClose, onSave }: PostFi
|
|
|
191
196
|
/>
|
|
192
197
|
</div>
|
|
193
198
|
</div>
|
|
199
|
+
|
|
200
|
+
<MediaPickerModal
|
|
201
|
+
open={mediaOpen}
|
|
202
|
+
onClose={() => setMediaOpen(false)}
|
|
203
|
+
onSelect={(url) => {
|
|
204
|
+
setFeaturedImage(url)
|
|
205
|
+
setMediaOpen(false)
|
|
206
|
+
}}
|
|
207
|
+
accept="image/*"
|
|
208
|
+
/>
|
|
194
209
|
</Modal>
|
|
195
210
|
)
|
|
196
211
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { computeReadingTime } from '@actuate-media/cms-core/page-sections'
|
|
1
2
|
import type { PostHeaderConfig } from '../page-editor/section-types.js'
|
|
2
3
|
import type { PostRenderContext } from '../page-editor/sections/index.js'
|
|
3
4
|
|
|
@@ -37,7 +38,7 @@ export function PostHeader({ config, context }: PostHeaderProps) {
|
|
|
37
38
|
)}
|
|
38
39
|
{config.showAuthor && <span>{context.author?.name || 'Author name'}</span>}
|
|
39
40
|
{date && <span>{date}</span>}
|
|
40
|
-
{config.showReadingTime && <span>
|
|
41
|
+
{config.showReadingTime && <span>{computeReadingTime(context.body)} min read</span>}
|
|
41
42
|
</div>
|
|
42
43
|
)
|
|
43
44
|
|
|
@@ -45,7 +46,7 @@ export function PostHeader({ config, context }: PostHeaderProps) {
|
|
|
45
46
|
return (
|
|
46
47
|
<header className="relative">
|
|
47
48
|
<img src={context.featuredImageUrl} alt="" className="h-[360px] w-full object-cover" />
|
|
48
|
-
<div className="absolute inset-0 bg-
|
|
49
|
+
<div className="absolute inset-0 bg-linear-to-t from-black/70 to-black/10" aria-hidden />
|
|
49
50
|
<div className="absolute inset-x-0 bottom-0 px-6 pb-8">
|
|
50
51
|
<div className={`mx-auto flex max-w-3xl flex-col ${align}`}>
|
|
51
52
|
<h1 className="text-3xl font-semibold tracking-tight text-white sm:text-4xl">
|
|
@@ -66,7 +67,6 @@ export function PostHeader({ config, context }: PostHeaderProps) {
|
|
|
66
67
|
<div
|
|
67
68
|
className={`flex max-w-3xl flex-col ${align} ${config.layout === 'centered' ? 'mx-auto' : ''}`}
|
|
68
69
|
>
|
|
69
|
-
{config.showCategory && context.category && config.layout !== 'centered' && null}
|
|
70
70
|
<h1 className="text-3xl font-semibold tracking-tight text-zinc-900 sm:text-4xl">{title}</h1>
|
|
71
71
|
{config.showExcerpt && context.excerpt && (
|
|
72
72
|
<p className="mt-3 max-w-2xl text-lg text-zinc-600">{context.excerpt}</p>
|
|
@@ -78,7 +78,7 @@ export function PostHeader({ config, context }: PostHeaderProps) {
|
|
|
78
78
|
<img
|
|
79
79
|
src={context.featuredImageUrl}
|
|
80
80
|
alt=""
|
|
81
|
-
className="aspect-
|
|
81
|
+
className="aspect-video w-full rounded-xl object-cover"
|
|
82
82
|
/>
|
|
83
83
|
</div>
|
|
84
84
|
)}
|
|
@@ -78,6 +78,17 @@ export function PostPreview({ postType, documentId, session, onNavigate }: PostP
|
|
|
78
78
|
}
|
|
79
79
|
const visible = post.sections.filter((s) => s.visible)
|
|
80
80
|
|
|
81
|
+
// `window.close()` only works for tabs JS opened (the "View preview" action
|
|
82
|
+
// opens this view via window.open). When the user reached it through in-app
|
|
83
|
+
// navigation there is no opener, so close() is a silent no-op — fall back to
|
|
84
|
+
// the editor after a tick so the Close button always does something.
|
|
85
|
+
const handleClose = () => {
|
|
86
|
+
window.close()
|
|
87
|
+
setTimeout(() => {
|
|
88
|
+
onNavigate(`/posts/${postType}/${documentId}/edit`)
|
|
89
|
+
}, 120)
|
|
90
|
+
}
|
|
91
|
+
|
|
81
92
|
return (
|
|
82
93
|
<div className="flex h-full flex-col">
|
|
83
94
|
{/* Slim preview bar. This view opens in its own browser tab, so
|
|
@@ -85,7 +96,7 @@ export function PostPreview({ postType, documentId, session, onNavigate }: PostP
|
|
|
85
96
|
<div className="bg-card border-border flex h-12 shrink-0 items-center justify-between border-b px-4">
|
|
86
97
|
<button
|
|
87
98
|
type="button"
|
|
88
|
-
onClick={
|
|
99
|
+
onClick={handleClose}
|
|
89
100
|
className="text-muted-foreground hover:text-foreground inline-flex items-center gap-1.5 text-sm"
|
|
90
101
|
aria-label="Close preview tab"
|
|
91
102
|
>
|
|
@@ -43,12 +43,23 @@ import { ValidationSummary } from '../page-editor/ValidationSummary.js'
|
|
|
43
43
|
import { PostEditorCanvas } from './PostEditorCanvas.js'
|
|
44
44
|
import { PostFieldsModal } from './PostFieldsModal.js'
|
|
45
45
|
|
|
46
|
+
/** The slice of the resolved CMS config this editor reads. */
|
|
47
|
+
interface EditorConfig {
|
|
48
|
+
collections?: Record<string, { labels?: { singular?: string }; urlPrefix?: string } | undefined>
|
|
49
|
+
seo?: { siteUrl?: string }
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/** The slice of the admin session this editor reads. */
|
|
53
|
+
interface EditorSession {
|
|
54
|
+
user?: { role?: string; name?: string; email?: string }
|
|
55
|
+
}
|
|
56
|
+
|
|
46
57
|
interface PostSectionEditorProps {
|
|
47
58
|
postType: string
|
|
48
59
|
/** undefined when creating a new post (`/posts/:type/new`) */
|
|
49
60
|
documentId?: string
|
|
50
|
-
config?:
|
|
51
|
-
session?:
|
|
61
|
+
config?: EditorConfig
|
|
62
|
+
session?: EditorSession
|
|
52
63
|
onNavigate: (path: string) => void
|
|
53
64
|
/**
|
|
54
65
|
* Open a preview route in a new browser tab. `prepare` runs before the tab
|
|
@@ -58,9 +69,15 @@ interface PostSectionEditorProps {
|
|
|
58
69
|
onOpenPreview?: (path: string, prepare?: () => Promise<boolean | void> | boolean | void) => void
|
|
59
70
|
}
|
|
60
71
|
|
|
61
|
-
function deriveCan(session:
|
|
62
|
-
|
|
63
|
-
|
|
72
|
+
function deriveCan(session: EditorSession | undefined): {
|
|
73
|
+
canEdit: boolean
|
|
74
|
+
canPublish: boolean
|
|
75
|
+
} {
|
|
76
|
+
const role = session?.user?.role
|
|
77
|
+
// Default closed: when we can't identify a role, hide the edit/publish
|
|
78
|
+
// affordances rather than exposing them. The server independently enforces
|
|
79
|
+
// access on every write, so this is a UX guard — but it should fail safe.
|
|
80
|
+
if (!role) return { canEdit: false, canPublish: false }
|
|
64
81
|
const editors = ['ADMIN', 'EDITOR', 'AUTHOR']
|
|
65
82
|
const publishers = ['ADMIN', 'EDITOR']
|
|
66
83
|
return { canEdit: editors.includes(role), canPublish: publishers.includes(role) }
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"PostEditor.d.ts","sourceRoot":"","sources":["../../src/views/PostEditor.tsx"],"names":[],"mappings":"AAUA,MAAM,WAAW,eAAe;IAC9B,EAAE,CAAC,EAAE,MAAM,CAAA;IACX,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;CACpC;AAED,wBAAgB,UAAU,CAAC,EAAE,EAAE,EAAE,UAAU,EAAE,EAAE,eAAe,2CAiP7D"}
|
package/dist/views/PostEditor.js
DELETED
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
-
import { useState, useEffect } from 'react';
|
|
4
|
-
import { ArrowLeft, Eye, Loader2, AlertTriangle } from 'lucide-react';
|
|
5
|
-
import { toast } from 'sonner';
|
|
6
|
-
import { TipTapEditor } from '../components/TipTapEditor.js';
|
|
7
|
-
import { SEOPanel } from '../components/SEOPanel.js';
|
|
8
|
-
import { useApiData } from '../lib/useApiData.js';
|
|
9
|
-
import { cmsApi } from '../lib/api.js';
|
|
10
|
-
export function PostEditor({ id, onNavigate }) {
|
|
11
|
-
const isNew = !id;
|
|
12
|
-
const { data, loading, error } = useApiData(isNew ? '' : `/collections/posts/${id}`);
|
|
13
|
-
const [title, setTitle] = useState('');
|
|
14
|
-
const [content, setContent] = useState('');
|
|
15
|
-
const [status, setStatus] = useState('draft');
|
|
16
|
-
const [slug, setSlug] = useState('');
|
|
17
|
-
const [saving, setSaving] = useState(false);
|
|
18
|
-
const [initialized, setInitialized] = useState(isNew);
|
|
19
|
-
const [seoData, setSeoData] = useState({});
|
|
20
|
-
useEffect(() => {
|
|
21
|
-
if (data && !initialized) {
|
|
22
|
-
setTitle(data.title ?? '');
|
|
23
|
-
setContent(data.content ?? data.data?.content ?? '');
|
|
24
|
-
setStatus(data.status === 'PUBLISHED' ? 'published' : 'draft');
|
|
25
|
-
setSlug(data.slug ?? '');
|
|
26
|
-
setInitialized(true);
|
|
27
|
-
}
|
|
28
|
-
}, [data, initialized]);
|
|
29
|
-
const savePost = async () => {
|
|
30
|
-
setSaving(true);
|
|
31
|
-
const body = JSON.stringify({
|
|
32
|
-
title,
|
|
33
|
-
content,
|
|
34
|
-
slug,
|
|
35
|
-
status: status === 'published' ? 'PUBLISHED' : 'DRAFT',
|
|
36
|
-
});
|
|
37
|
-
const res = isNew
|
|
38
|
-
? await cmsApi('/collections/posts', { method: 'POST', body })
|
|
39
|
-
: await cmsApi(`/collections/posts/${id}`, { method: 'PUT', body });
|
|
40
|
-
setSaving(false);
|
|
41
|
-
if (res.error) {
|
|
42
|
-
toast.error(res.error);
|
|
43
|
-
}
|
|
44
|
-
else {
|
|
45
|
-
toast.success('Post saved successfully!');
|
|
46
|
-
if (isNew && res.data?.id) {
|
|
47
|
-
onNavigate?.(`/posts/${res.data.id}`);
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
};
|
|
51
|
-
const publishPost = async () => {
|
|
52
|
-
setSaving(true);
|
|
53
|
-
const body = JSON.stringify({
|
|
54
|
-
title,
|
|
55
|
-
content,
|
|
56
|
-
slug,
|
|
57
|
-
status: 'PUBLISHED',
|
|
58
|
-
});
|
|
59
|
-
const endpoint = isNew ? '/collections/posts' : `/collections/posts/${id}`;
|
|
60
|
-
const method = isNew ? 'POST' : 'PUT';
|
|
61
|
-
const res = await cmsApi(endpoint, { method, body });
|
|
62
|
-
setSaving(false);
|
|
63
|
-
if (res.error) {
|
|
64
|
-
toast.error(res.error);
|
|
65
|
-
}
|
|
66
|
-
else {
|
|
67
|
-
setStatus('published');
|
|
68
|
-
toast.success('Post published!');
|
|
69
|
-
if (isNew && res.data?.id) {
|
|
70
|
-
onNavigate?.(`/posts/${res.data.id}`);
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
};
|
|
74
|
-
if (!isNew && loading) {
|
|
75
|
-
return (_jsx("div", { className: "flex h-full items-center justify-center", children: _jsx(Loader2, { className: "h-6 w-6 animate-spin text-blue-600" }) }));
|
|
76
|
-
}
|
|
77
|
-
return (_jsxs("div", { className: "flex h-full flex-col bg-white", children: [error && (_jsxs("div", { className: "mx-4 mt-3 flex items-center gap-3 rounded-lg border border-red-200 bg-red-50 p-3", children: [_jsx(AlertTriangle, { className: "h-5 w-5 shrink-0 text-red-600" }), _jsx("span", { className: "flex-1 text-sm text-red-800", children: error })] })), _jsx("div", { className: "border-b border-gray-200 px-3 py-3 sm:px-4", children: _jsxs("div", { className: "flex items-center justify-between", children: [_jsxs("button", { onClick: () => onNavigate?.('/posts'), className: "inline-flex items-center gap-2 text-sm text-gray-600 transition-colors hover:text-gray-900", children: [_jsx(ArrowLeft, { className: "h-4 w-4" }), _jsx("span", { className: "hidden sm:inline", children: "Back to Posts" }), _jsx("span", { className: "sm:hidden", children: "Back" })] }), _jsx("div", { className: "flex items-center gap-2", children: _jsxs("button", { className: "flex items-center gap-2 rounded-lg border border-gray-300 px-3 py-1.5 text-sm transition-colors hover:bg-gray-50", children: [_jsx(Eye, { className: "h-4 w-4" }), _jsx("span", { className: "hidden sm:inline", children: "Preview" })] }) })] }) }), _jsxs("div", { className: "flex flex-1 flex-col overflow-hidden lg:flex-row", children: [_jsx("div", { className: "flex-1 overflow-y-auto", children: _jsxs("div", { className: "mx-auto max-w-4xl p-3 pr-6 sm:p-4 sm:pr-8", children: [_jsx("input", { type: "text", value: title, onChange: (e) => setTitle(e.target.value), placeholder: "Post title", className: "mb-4 w-full border-none px-0 text-2xl font-bold placeholder:text-gray-300 focus:ring-0 focus:outline-none sm:text-3xl" }), _jsxs("div", { className: "mb-4", children: [_jsx("label", { className: "mb-1 block text-xs font-medium text-gray-600", children: "URL Slug" }), _jsx("input", { type: "text", value: slug, onChange: (e) => setSlug(e.target.value), placeholder: "url-slug", className: "w-full rounded-lg border border-gray-300 px-3 py-1.5 text-sm focus:ring-2 focus:ring-blue-500 focus:outline-none" })] }), _jsx("div", { className: "mb-4", children: _jsx(TipTapEditor, { content: content, onChange: setContent }) })] }) }), _jsx("div", { className: "hidden w-[30%] overflow-y-auto border-l border-gray-200 bg-gray-50 lg:block", children: _jsxs("div", { className: "space-y-4 p-4", children: [_jsxs("div", { className: "rounded-lg border border-gray-200 bg-white p-4", children: [_jsx("h3", { className: "mb-3 text-sm font-semibold text-gray-900", children: "Publish" }), _jsxs("div", { className: "space-y-3", children: [_jsxs("div", { children: [_jsx("label", { className: "mb-1 block text-xs font-medium text-gray-700", children: "Status" }), _jsxs("select", { value: status, onChange: (e) => setStatus(e.target.value), className: "w-full rounded-lg border border-gray-300 px-3 py-1.5 text-sm focus:ring-2 focus:ring-blue-500 focus:outline-none", children: [_jsx("option", { value: "draft", children: "Draft" }), _jsx("option", { value: "published", children: "Published" })] })] }), _jsxs("div", { children: [_jsx("label", { className: "mb-1 block text-xs font-medium text-gray-700", children: "Publish Date" }), _jsx("input", { type: "datetime-local", className: "w-full rounded-lg border border-gray-300 px-3 py-1.5 text-sm focus:ring-2 focus:ring-blue-500 focus:outline-none" })] }), _jsx("button", { onClick: savePost, disabled: saving, className: "w-full rounded-lg bg-blue-600 py-2 text-sm font-medium text-white transition-colors hover:bg-blue-700 disabled:opacity-50", children: saving ? 'Saving...' : 'Save Post' }), status === 'draft' && (_jsx("button", { onClick: publishPost, disabled: saving, className: "w-full rounded-lg bg-green-600 py-2 text-sm font-medium text-white transition-colors hover:bg-green-700 disabled:opacity-50", children: saving ? 'Publishing...' : 'Publish' }))] })] }), _jsxs("div", { className: "rounded-lg border border-gray-200 bg-white p-4", children: [_jsx("h3", { className: "mb-3 text-sm font-semibold text-gray-900", children: "Categories & Tags" }), _jsxs("div", { className: "space-y-3", children: [_jsxs("div", { children: [_jsx("label", { className: "mb-1 block text-xs font-medium text-gray-700", children: "Category" }), _jsxs("select", { className: "w-full rounded-lg border border-gray-300 px-3 py-1.5 text-sm focus:ring-2 focus:ring-blue-500 focus:outline-none", children: [_jsx("option", { children: "Technology" }), _jsx("option", { children: "Design" }), _jsx("option", { children: "Business" })] })] }), _jsxs("div", { children: [_jsx("label", { className: "mb-1 block text-xs font-medium text-gray-700", children: "Tags" }), _jsx("input", { type: "text", placeholder: "Add tags...", className: "w-full rounded-lg border border-gray-300 px-3 py-1.5 text-sm focus:ring-2 focus:ring-blue-500 focus:outline-none" })] })] })] }), _jsxs("div", { className: "rounded-lg border border-gray-200 bg-white p-4", children: [_jsx("h3", { className: "mb-3 text-sm font-semibold text-gray-900", children: "Featured Image" }), _jsx("button", { className: "w-full rounded-lg border-2 border-dashed border-gray-300 py-2 text-sm text-gray-600 transition-colors hover:border-gray-400", children: "Upload Image" })] }), _jsx(SEOPanel, { title: title, slug: slug, content: content, seoData: seoData, onChange: setSeoData })] }) }), _jsx("div", { className: "border-t border-gray-200 bg-white p-3 lg:hidden", children: _jsxs("div", { className: "flex gap-2", children: [_jsx("button", { onClick: savePost, disabled: saving, className: "flex-1 rounded-lg bg-blue-600 py-2 text-sm font-medium text-white transition-colors hover:bg-blue-700 disabled:opacity-50", children: saving ? 'Saving...' : 'Save Post' }), status === 'draft' && (_jsx("button", { onClick: publishPost, disabled: saving, className: "flex-1 rounded-lg bg-green-600 py-2 text-sm font-medium text-white transition-colors hover:bg-green-700 disabled:opacity-50", children: "Publish" }))] }) })] })] }));
|
|
78
|
-
}
|
|
79
|
-
//# sourceMappingURL=PostEditor.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"PostEditor.js","sourceRoot":"","sources":["../../src/views/PostEditor.tsx"],"names":[],"mappings":"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"}
|
package/dist/views/Posts.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Posts.d.ts","sourceRoot":"","sources":["../../src/views/Posts.tsx"],"names":[],"mappings":"AAsBA,MAAM,WAAW,UAAU;IACzB,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;CACpC;AAED,wBAAgB,KAAK,CAAC,EAAE,UAAU,EAAE,EAAE,UAAU,2CA4V/C"}
|
package/dist/views/Posts.js
DELETED
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
|
-
import { Plus, Search, Trash2, SlidersHorizontal, Pencil, ArrowUpDown, ArrowUp, ArrowDown, Loader2, AlertTriangle, } from 'lucide-react';
|
|
4
|
-
import { useState, useMemo } from 'react';
|
|
5
|
-
import { toast } from 'sonner';
|
|
6
|
-
import { sortByRelevance, toggleSort } from '../lib/search.js';
|
|
7
|
-
import { useApiData } from '../lib/useApiData.js';
|
|
8
|
-
import { cmsApi } from '../lib/api.js';
|
|
9
|
-
export function Posts({ onNavigate }) {
|
|
10
|
-
const { data, loading, error, refetch } = useApiData('/collections/posts?pageSize=100');
|
|
11
|
-
const [searchQuery, setSearchQuery] = useState('');
|
|
12
|
-
const [filterStatus, setFilterStatus] = useState('all');
|
|
13
|
-
const [filterCategory, setFilterCategory] = useState('all');
|
|
14
|
-
const [selectedPosts, setSelectedPosts] = useState([]);
|
|
15
|
-
const [sortConfig, setSortConfig] = useState(null);
|
|
16
|
-
const posts = data?.docs ?? [];
|
|
17
|
-
const filteredAndSorted = useMemo(() => {
|
|
18
|
-
let results = posts.filter((post) => {
|
|
19
|
-
const matchesSearch = (post.title ?? '').toLowerCase().includes(searchQuery.toLowerCase()) ||
|
|
20
|
-
(post.author ?? '').toLowerCase().includes(searchQuery.toLowerCase());
|
|
21
|
-
const matchesStatus = filterStatus === 'all' || (post.status ?? '').toLowerCase() === filterStatus.toLowerCase();
|
|
22
|
-
const matchesCategory = filterCategory === 'all' ||
|
|
23
|
-
(post.category ?? '').toLowerCase() === filterCategory.toLowerCase();
|
|
24
|
-
return matchesSearch && matchesStatus && matchesCategory;
|
|
25
|
-
});
|
|
26
|
-
if (searchQuery.trim()) {
|
|
27
|
-
results = sortByRelevance(results, searchQuery, (p) => [
|
|
28
|
-
p.title,
|
|
29
|
-
p.author ?? '',
|
|
30
|
-
p.category ?? '',
|
|
31
|
-
]);
|
|
32
|
-
}
|
|
33
|
-
else if (sortConfig) {
|
|
34
|
-
results = [...results].sort((a, b) => {
|
|
35
|
-
const aVal = a[sortConfig.key] ?? '';
|
|
36
|
-
const bVal = b[sortConfig.key] ?? '';
|
|
37
|
-
const cmp = String(aVal).localeCompare(String(bVal));
|
|
38
|
-
return sortConfig.direction === 'asc' ? cmp : -cmp;
|
|
39
|
-
});
|
|
40
|
-
}
|
|
41
|
-
return results;
|
|
42
|
-
}, [posts, searchQuery, filterStatus, filterCategory, sortConfig]);
|
|
43
|
-
const handleSelectAll = (checked) => {
|
|
44
|
-
setSelectedPosts(checked ? filteredAndSorted.map((p) => p.id) : []);
|
|
45
|
-
};
|
|
46
|
-
const handleSelectPost = (id) => {
|
|
47
|
-
setSelectedPosts((prev) => prev.includes(id) ? prev.filter((pid) => pid !== id) : [...prev, id]);
|
|
48
|
-
};
|
|
49
|
-
const handleBulkDelete = async () => {
|
|
50
|
-
for (const id of selectedPosts) {
|
|
51
|
-
await cmsApi(`/collections/posts/${id}`, { method: 'DELETE' });
|
|
52
|
-
}
|
|
53
|
-
toast.success(`${selectedPosts.length} posts deleted`);
|
|
54
|
-
setSelectedPosts([]);
|
|
55
|
-
refetch();
|
|
56
|
-
};
|
|
57
|
-
const handleDelete = async (id) => {
|
|
58
|
-
await cmsApi(`/collections/posts/${id}`, { method: 'DELETE' });
|
|
59
|
-
toast.success('Post deleted');
|
|
60
|
-
setSelectedPosts((prev) => prev.filter((pid) => pid !== id));
|
|
61
|
-
refetch();
|
|
62
|
-
};
|
|
63
|
-
function SortHeader({ label, sortKey }) {
|
|
64
|
-
const active = sortConfig?.key === sortKey;
|
|
65
|
-
return (_jsxs("button", { type: "button", onClick: () => setSortConfig(toggleSort(sortConfig, sortKey)), className: "flex items-center gap-1 text-xs font-medium text-gray-700 transition-colors hover:text-gray-900", children: [label, active ? (sortConfig.direction === 'asc' ? (_jsx(ArrowUp, { className: "h-3 w-3" })) : (_jsx(ArrowDown, { className: "h-3 w-3" }))) : (_jsx(ArrowUpDown, { className: "h-3 w-3 text-gray-400" }))] }));
|
|
66
|
-
}
|
|
67
|
-
if (loading) {
|
|
68
|
-
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: "h-6 w-6 animate-spin text-blue-600" }) }));
|
|
69
|
-
}
|
|
70
|
-
return (_jsxs("div", { className: "flex h-full flex-col p-3 pr-6 sm:p-4 sm:pr-8", children: [error && (_jsxs("div", { className: "mb-4 flex items-center gap-3 rounded-lg border border-red-200 bg-red-50 p-3", children: [_jsx(AlertTriangle, { className: "h-5 w-5 shrink-0 text-red-600" }), _jsx("span", { className: "flex-1 text-sm text-red-800", children: error }), _jsx("button", { onClick: refetch, className: "rounded-lg border border-red-300 px-3 py-1 text-sm text-red-700 transition-colors hover:bg-red-100", children: "Retry" })] })), _jsxs("div", { className: "mb-4 flex flex-col justify-between gap-3 sm:flex-row sm:items-center", children: [_jsxs("div", { children: [_jsx("h1", { className: "mb-1 text-xl font-semibold text-gray-900 sm:text-2xl", children: "Posts" }), _jsxs("p", { className: "text-sm text-gray-600", children: [filteredAndSorted.length, " total posts"] })] }), _jsxs("button", { onClick: () => onNavigate?.('/posts/new'), className: "flex items-center justify-center gap-2 rounded-lg bg-blue-600 px-4 py-2 text-sm text-white transition-colors hover:bg-blue-700", children: [_jsx(Plus, { className: "h-4 w-4" }), _jsx("span", { className: "hidden sm:inline", children: "New Post" }), _jsx("span", { className: "sm:hidden", children: "New" })] })] }), _jsx("div", { className: "mb-4 rounded-lg border border-gray-200 bg-white", children: _jsxs("div", { className: "flex flex-col gap-3 p-3", children: [_jsxs("div", { className: "relative", children: [_jsx(Search, { className: "absolute top-1/2 left-3 h-4 w-4 -translate-y-1/2 text-gray-400" }), _jsx("input", { type: "text", placeholder: "Search posts...", value: searchQuery, onChange: (e) => setSearchQuery(e.target.value), className: "w-full rounded-lg border border-gray-300 py-2 pr-3 pl-9 text-sm focus:ring-2 focus:ring-blue-500 focus:outline-none" })] }), _jsxs("div", { className: "flex flex-col gap-2 sm:flex-row", children: [_jsxs("select", { value: filterStatus, onChange: (e) => setFilterStatus(e.target.value), className: "flex-1 rounded-lg border border-gray-300 px-3 py-2 text-sm focus:ring-2 focus:ring-blue-500 focus:outline-none", children: [_jsx("option", { value: "all", children: "All Status" }), _jsx("option", { value: "published", children: "Published" }), _jsx("option", { value: "draft", children: "Draft" })] }), _jsxs("select", { value: filterCategory, onChange: (e) => setFilterCategory(e.target.value), className: "flex-1 rounded-lg border border-gray-300 px-3 py-2 text-sm focus:ring-2 focus:ring-blue-500 focus:outline-none", children: [_jsx("option", { value: "all", children: "All Categories" }), _jsx("option", { value: "technology", children: "Technology" }), _jsx("option", { value: "design", children: "Design" }), _jsx("option", { value: "business", children: "Business" })] }), _jsxs("button", { type: "button", className: "flex items-center justify-center gap-2 rounded-lg border border-gray-300 px-3 py-2 text-sm transition-colors hover:bg-gray-50", children: [_jsx(SlidersHorizontal, { className: "h-4 w-4" }), _jsx("span", { className: "hidden sm:inline", children: "More Filters" })] })] })] }) }), selectedPosts.length > 0 && (_jsx("div", { className: "mb-4 rounded-lg border border-blue-200 bg-blue-50 p-3", children: _jsxs("div", { className: "flex flex-col justify-between gap-2 sm:flex-row sm:items-center", children: [_jsxs("span", { className: "text-sm text-blue-900", children: [selectedPosts.length, " post", selectedPosts.length !== 1 ? 's' : '', " selected"] }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsx("button", { type: "button", onClick: handleBulkDelete, className: "flex-1 rounded-lg bg-red-600 px-3 py-1.5 text-sm text-white transition-colors hover:bg-red-700 sm:flex-none", children: "Delete" }), _jsx("button", { type: "button", onClick: () => setSelectedPosts([]), className: "flex-1 rounded-lg border border-gray-300 bg-white px-3 py-1.5 text-sm transition-colors hover:bg-gray-50 sm:flex-none", children: "Cancel" })] })] }) })), filteredAndSorted.length === 0 && !error ? (_jsxs("div", { className: "flex flex-1 flex-col items-center justify-center rounded-lg border border-gray-200 bg-white p-8 text-center", children: [_jsx("p", { className: "mb-2 text-sm text-gray-500", children: "No posts yet" }), _jsx("button", { onClick: () => onNavigate?.('/posts/new'), className: "rounded-lg bg-blue-600 px-4 py-2 text-sm text-white transition-colors hover:bg-blue-700", children: "Create your first post" })] })) : (_jsxs(_Fragment, { children: [_jsx("div", { className: "hidden flex-1 overflow-hidden rounded-lg border border-gray-200 bg-white md:block", children: _jsx("div", { className: "h-full overflow-x-auto", children: _jsxs("table", { className: "w-full", children: [_jsx("thead", { className: "sticky top-0 border-b border-gray-200 bg-gray-50", children: _jsxs("tr", { children: [_jsx("th", { className: "w-8 px-3 py-2 text-left", children: _jsx("input", { type: "checkbox", checked: selectedPosts.length === filteredAndSorted.length &&
|
|
71
|
-
filteredAndSorted.length > 0, onChange: (e) => handleSelectAll(e.target.checked), className: "rounded border-gray-300" }) }), _jsx("th", { className: "px-3 py-2 text-left", children: _jsx(SortHeader, { label: "Title", sortKey: "title" }) }), _jsx("th", { className: "px-3 py-2 text-left", children: _jsx(SortHeader, { label: "Author", sortKey: "author" }) }), _jsx("th", { className: "px-3 py-2 text-left", children: _jsx(SortHeader, { label: "Category", sortKey: "category" }) }), _jsx("th", { className: "px-3 py-2 text-left", children: _jsx(SortHeader, { label: "Status", sortKey: "status" }) }), _jsx("th", { className: "px-3 py-2 text-left", children: _jsx(SortHeader, { label: "Date", sortKey: "date" }) }), _jsx("th", { className: "px-3 py-2 text-left text-xs font-medium text-gray-700", children: "Actions" })] }) }), _jsx("tbody", { className: "divide-y divide-gray-200", children: filteredAndSorted.map((post) => (_jsxs("tr", { className: "transition-colors hover:bg-gray-50", children: [_jsx("td", { className: "px-3 py-2", children: _jsx("input", { type: "checkbox", checked: selectedPosts.includes(post.id), onChange: () => handleSelectPost(post.id), className: "rounded border-gray-300" }) }), _jsx("td", { className: "px-3 py-2", children: _jsx("button", { type: "button", onClick: () => onNavigate?.(`/posts/${post.id}`), className: "text-left text-sm font-medium text-gray-900 hover:text-blue-600", children: post.title }) }), _jsx("td", { className: "px-3 py-2 text-sm text-gray-600", children: post.author }), _jsx("td", { className: "px-3 py-2 text-sm text-gray-600", children: post.category }), _jsx("td", { className: "px-3 py-2", children: _jsx("span", { className: `inline-flex items-center rounded-full px-2 py-0.5 text-xs font-medium ${post.status === 'Published' ? 'bg-green-100 text-green-800' : 'bg-gray-100 text-gray-800'}`, children: post.status }) }), _jsx("td", { className: "px-3 py-2 text-sm text-gray-600", children: post.date }), _jsx("td", { className: "px-3 py-2", children: _jsxs("div", { className: "flex items-center gap-2", children: [_jsx("button", { type: "button", onClick: () => onNavigate?.(`/posts/${post.id}`), className: "rounded p-1.5 transition-colors hover:bg-gray-100", title: "Edit", children: _jsx(Pencil, { className: "h-4 w-4 text-gray-600" }) }), _jsx("button", { type: "button", onClick: () => handleDelete(post.id), className: "rounded p-1.5 transition-colors hover:bg-gray-100", title: "Delete", children: _jsx(Trash2, { className: "h-4 w-4 text-red-600" }) })] }) })] }, post.id))) })] }) }) }), _jsx("div", { className: "flex-1 overflow-auto rounded-lg border border-gray-200 bg-white md:hidden", children: _jsx("div", { className: "divide-y divide-gray-200", children: filteredAndSorted.map((post) => (_jsx("div", { className: "p-3", children: _jsxs("div", { className: "flex items-start gap-3", children: [_jsx("input", { type: "checkbox", checked: selectedPosts.includes(post.id), onChange: () => handleSelectPost(post.id), className: "mt-1 rounded border-gray-300" }), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsx("button", { type: "button", onClick: () => onNavigate?.(`/posts/${post.id}`), className: "mb-1 block text-left text-sm font-medium text-gray-900 hover:text-blue-600", children: post.title }), _jsxs("div", { className: "mb-2 flex flex-wrap items-center gap-2 text-xs text-gray-600", children: [_jsx("span", { children: post.author }), _jsx("span", { children: "\u2022" }), _jsx("span", { children: post.date }), _jsx("span", { className: `rounded-full px-2 py-0.5 text-xs font-medium ${post.status === 'Published' ? 'bg-green-100 text-green-800' : 'bg-gray-100 text-gray-800'}`, children: post.status })] })] }), _jsx("button", { type: "button", onClick: () => handleDelete(post.id), className: "rounded p-1.5 transition-colors hover:bg-gray-100", children: _jsx(Trash2, { className: "h-4 w-4 text-red-600" }) })] }) }, post.id))) }) })] }))] }));
|
|
72
|
-
}
|
|
73
|
-
//# sourceMappingURL=Posts.js.map
|
package/dist/views/Posts.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Posts.js","sourceRoot":"","sources":["../../src/views/Posts.tsx"],"names":[],"mappings":"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"}
|