@acms-subir/core 0.2.0 → 0.3.1
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/CHANGELOG.md +87 -0
- package/cli/common.mjs +35 -0
- package/cli/legacy.mjs +317 -0
- package/cli/main.mjs +66 -0
- package/cli/palette.mjs +4 -0
- package/cli/preview.mjs +50 -0
- package/cli/remote.mjs +55 -0
- package/cli/themes.mjs +127 -0
- package/cli.mjs +2 -369
- package/deploy/Caddyfile +8 -0
- package/deploy/Dockerfile +34 -0
- package/deploy/compose.https.yml +21 -0
- package/deploy/compose.yml +46 -0
- package/docs/live-video.md +91 -0
- package/docs/theme-authoring.md +103 -0
- package/email-runner.mjs +32 -0
- package/integration.mjs +189 -2
- package/ops-check.mjs +27 -0
- package/package.json +27 -5
- package/src/actions/index.ts +578 -49
- package/src/components/AiCleaner.tsx +291 -0
- package/src/components/AiSettings.tsx +575 -0
- package/src/components/CommandPalette.tsx +200 -0
- package/src/components/ContentList.astro +246 -0
- package/src/components/DesignAccess.tsx +182 -0
- package/src/components/DesignManager.tsx +418 -46
- package/src/components/EmailSettings.tsx +521 -0
- package/src/components/EventPage.astro +178 -0
- package/src/components/LegalPage.astro +27 -0
- package/src/components/LinksManager.tsx +119 -58
- package/src/components/LiveCard.astro +174 -0
- package/src/components/LiveManager.tsx +910 -0
- package/src/components/NavManager.tsx +42 -43
- package/src/components/ThemeScript.astro +50 -0
- package/src/components/ThemeSections.astro +58 -0
- package/src/components/ThemeSectionsEditor.tsx +513 -0
- package/src/components/WidgetRenderer.astro +3 -0
- package/src/components/booking/BookingFlow.astro +150 -0
- package/src/components/booking/HoursEditor.astro +63 -0
- package/src/components/builder/PageBuilder.tsx +10 -2
- package/src/components/editor/EventPanel.tsx +401 -0
- package/src/components/editor/FormatDock.tsx +81 -0
- package/src/components/editor/LivePane.tsx +122 -0
- package/src/components/editor/MobileToolbar.tsx +93 -0
- package/src/components/editor/PostEditor.tsx +605 -223
- package/src/components/editor/PreviewOverlay.tsx +242 -43
- package/src/components/editor/extensions/calendar.tsx +51 -7
- package/src/components/editor/extensions/events.tsx +153 -0
- package/src/components/editor/extensions/slash.tsx +7 -1
- package/src/components/site/Pager.astro +24 -0
- package/src/components/site/PostCard.astro +64 -0
- package/src/components/site/TagLabel.astro +11 -0
- package/src/layouts/Admin.astro +289 -49
- package/src/layouts/Site.astro +352 -59
- package/src/lib/agent-api.ts +13 -0
- package/src/lib/agent-discovery.ts +40 -0
- package/src/lib/agent.ts +114 -0
- package/src/lib/ai-config.ts +58 -0
- package/src/lib/ai-schema.ts +22 -0
- package/src/lib/ai.ts +90 -0
- package/src/lib/api-keys.ts +65 -0
- package/src/lib/api.ts +56 -0
- package/src/lib/auth.ts +25 -5
- package/src/lib/backup/content.ts +36 -0
- package/src/lib/backup/unzip.ts +12 -1
- package/src/lib/backup/zip.ts +1 -1
- package/src/lib/booking/agent.ts +108 -0
- package/src/lib/booking/availability.ts +221 -0
- package/src/lib/booking/emails.ts +115 -0
- package/src/lib/booking/forms.ts +77 -0
- package/src/lib/booking/service.ts +277 -0
- package/src/lib/booking/view.ts +54 -0
- package/src/lib/calendar/agent-schema.ts +48 -0
- package/src/lib/calendar/agent.ts +136 -0
- package/src/lib/calendar/api.ts +81 -0
- package/src/lib/calendar/cards.ts +102 -0
- package/src/lib/calendar/config.ts +52 -0
- package/src/lib/calendar/data.ts +130 -0
- package/src/lib/calendar/events.ts +261 -0
- package/src/lib/calendar/feeds.ts +43 -0
- package/src/lib/calendar/hooks.ts +38 -0
- package/src/lib/calendar/http.ts +30 -0
- package/src/lib/calendar/ics-write.ts +120 -0
- package/src/lib/calendar/ics.ts +15 -5
- package/src/lib/calendar/import.ts +203 -0
- package/src/lib/calendar/render.ts +120 -37
- package/src/lib/calendar/rrule.ts +149 -0
- package/src/lib/calendar/seo.ts +48 -0
- package/src/lib/design-service.ts +58 -0
- package/src/lib/designDiff.ts +145 -0
- package/src/lib/designPreview.ts +110 -12
- package/src/lib/documents/cleanup.ts +31 -0
- package/src/lib/documents/extract.ts +154 -0
- package/src/lib/documents/vendor.d.ts +4 -0
- package/src/lib/drafts.ts +60 -6
- package/src/lib/dynamicBlocks.ts +40 -8
- package/src/lib/email/accounts.ts +55 -0
- package/src/lib/email/config.ts +86 -0
- package/src/lib/email/migration.ts +24 -0
- package/src/lib/email/providers.ts +89 -0
- package/src/lib/email/service.ts +78 -0
- package/src/lib/email/store.ts +167 -0
- package/src/lib/email/templates.ts +18 -0
- package/src/lib/email/types.ts +32 -0
- package/src/lib/email/webhooks.ts +87 -0
- package/src/lib/email.ts +15 -0
- package/src/lib/env.ts +1 -1
- package/src/lib/legal/index.ts +25 -0
- package/src/lib/live/client.ts +88 -0
- package/src/lib/live/crypto.ts +28 -0
- package/src/lib/live/migration.ts +15 -0
- package/src/lib/live/providers.ts +152 -0
- package/src/lib/live/service.ts +170 -0
- package/src/lib/live/signals.ts +89 -0
- package/src/lib/live/store.ts +49 -0
- package/src/lib/live/types.ts +52 -0
- package/src/lib/live/view.ts +78 -0
- package/src/lib/mobile/bookings.ts +73 -0
- package/src/lib/mobile/calendar.ts +85 -0
- package/src/lib/mobile/content.ts +85 -0
- package/src/lib/mobile/http.ts +63 -0
- package/src/lib/mobile/route.ts +20 -0
- package/src/lib/ops.ts +8 -0
- package/src/lib/preview.ts +21 -1
- package/src/lib/repo/migrations.ts +221 -0
- package/src/lib/repo/sql.ts +907 -68
- package/src/lib/repo/types.ts +125 -5
- package/src/lib/scheduler.ts +27 -0
- package/src/lib/schema.ts +316 -1
- package/src/lib/search-i18n.ts +3 -0
- package/src/lib/socialIcons.ts +32 -0
- package/src/lib/tagColor.ts +11 -0
- package/src/lib/theme.ts +59 -40
- package/src/lib/themeTokens.ts +183 -0
- package/src/lib/umami.ts +108 -0
- package/src/lib/webhook-sql.ts +68 -0
- package/src/lib/webhooks.ts +147 -0
- package/src/lib/widgets.ts +1 -0
- package/src/middleware.ts +45 -3
- package/src/pages/404.astro +23 -0
- package/src/pages/[...slug].astro +14 -5
- package/src/pages/account/[action].astro +53 -0
- package/src/pages/admin/ai.astro +12 -0
- package/src/pages/admin/c/[collection]/[id].astro +4 -1
- package/src/pages/admin/c/[collection]/index.astro +127 -92
- package/src/pages/admin/calendar/bookings.astro +400 -0
- package/src/pages/admin/calendar/calendars.astro +265 -0
- package/src/pages/admin/calendar/events/[id].astro +56 -0
- package/src/pages/admin/calendar/events/index.astro +408 -0
- package/src/pages/admin/calendar/index.ts +4 -0
- package/src/pages/admin/calendar/integrations.astro +4 -0
- package/src/pages/admin/calendar/resources/[id].astro +180 -0
- package/src/pages/admin/calendar/resources/index.astro +106 -0
- package/src/pages/admin/calendar/resources/link.astro +196 -0
- package/src/pages/admin/design.astro +10 -3
- package/src/pages/admin/email.astro +13 -0
- package/src/pages/admin/index.astro +232 -85
- package/src/pages/admin/integrations.astro +237 -0
- package/src/pages/admin/links.astro +3 -3
- package/src/pages/admin/live.astro +12 -0
- package/src/pages/admin/login.astro +14 -10
- package/src/pages/admin/navigation.astro +8 -2
- package/src/pages/admin/pages/[id].astro +4 -1
- package/src/pages/admin/pages/index.astro +41 -48
- package/src/pages/admin/settings.astro +418 -367
- package/src/pages/admin/tags.astro +4 -4
- package/src/pages/admin/users.astro +38 -28
- package/src/pages/api/agent/docs.ts +33 -0
- package/src/pages/api/agent/index.ts +21 -0
- package/src/pages/api/ai/clean.ts +13 -0
- package/src/pages/api/ai/draft.ts +14 -0
- package/src/pages/api/ai/settings.ts +53 -0
- package/src/pages/api/ai/test.ts +12 -0
- package/src/pages/api/backup.ts +8 -21
- package/src/pages/api/calendar/availability.ts +35 -0
- package/src/pages/api/calendar/bookings/[id].ts +49 -0
- package/src/pages/api/calendar/bookings/index.ts +73 -0
- package/src/pages/api/calendar/calendars.ts +35 -0
- package/src/pages/api/calendar/docs.ts +66 -0
- package/src/pages/api/calendar/events/[id].ts +63 -0
- package/src/pages/api/calendar/events/index.ts +112 -0
- package/src/pages/api/calendar/resources.ts +34 -0
- package/src/pages/api/design/capabilities.ts +10 -0
- package/src/pages/api/design/index.ts +58 -0
- package/src/pages/api/design/keys.ts +24 -0
- package/src/pages/api/design/media.ts +32 -0
- package/src/pages/api/email/run.ts +11 -0
- package/src/pages/api/email/settings.ts +61 -0
- package/src/pages/api/email/webhooks/[provider].ts +4 -0
- package/src/pages/api/live/oauth/youtube/callback.ts +19 -0
- package/src/pages/api/live/settings.ts +45 -0
- package/src/pages/api/live/status.ts +7 -0
- package/src/pages/api/live/thumb.ts +48 -0
- package/src/pages/api/mcp.ts +59 -0
- package/src/pages/api/media/upload.ts +2 -2
- package/src/pages/api/ops/status.ts +39 -0
- package/src/pages/api/restore.ts +27 -37
- package/src/pages/api/search.ts +18 -4
- package/src/pages/api/v1/availability.ts +7 -0
- package/src/pages/api/v1/bookings.ts +17 -0
- package/src/pages/api/v1/calendars.ts +7 -0
- package/src/pages/api/v1/content/[id].ts +7 -0
- package/src/pages/api/v1/content/index.ts +7 -0
- package/src/pages/api/v1/events.ts +7 -0
- package/src/pages/api/v1/resources.ts +7 -0
- package/src/pages/api/webhooks/docs.ts +61 -0
- package/src/pages/author/[slug].astro +43 -35
- package/src/pages/blog/[slug].astro +137 -66
- package/src/pages/blog/index.astro +95 -30
- package/src/pages/blog/tag/[slug].astro +45 -40
- package/src/pages/book/[resource]/[link].astro +70 -0
- package/src/pages/book/[resource]/index.astro +63 -0
- package/src/pages/book/[resource].ics.ts +38 -0
- package/src/pages/book/index.astro +47 -0
- package/src/pages/book/manage/[token].astro +108 -0
- package/src/pages/calendar/[slug].ics.ts +27 -0
- package/src/pages/calendar/feed.ics.ts +15 -0
- package/src/pages/calendar/index.astro +191 -0
- package/src/pages/embed/book/[resource]/[link].astro +33 -0
- package/src/pages/embed/calendar/[slug].astro +43 -0
- package/src/pages/events/[slug].astro +74 -0
- package/src/pages/events/[slug].ics.ts +25 -0
- package/src/pages/index.astro +12 -3
- package/src/pages/legal/privacy.astro +4 -0
- package/src/pages/legal/terms.astro +4 -0
- package/src/pages/links.astro +29 -3
- package/src/pages/llms.txt.ts +4 -0
- package/src/pages/preview/[type]/[id].astro +27 -6
- package/src/pages/search.astro +40 -20
- package/src/pages/sitemap.xml.ts +16 -1
- package/src/styles/admin.css +924 -105
- package/src/styles/cards.css +92 -74
- package/src/styles/editor.css +492 -114
- package/src/styles/email-settings.css +117 -0
- package/src/styles/live-admin.css +126 -0
- package/src/styles/live.css +199 -0
- package/src/styles/sections.css +12 -0
- package/src/styles/site.css +938 -281
- package/src/styles/theme-editor.css +135 -0
- package/src/theme-sdk/contract.d.mts +619 -0
- package/src/theme-sdk/contract.mjs +81 -0
- package/src/theme-sdk/index.ts +15 -0
- package/src/theme-sdk/tokens.d.mts +148 -0
- package/src/theme-sdk/tokens.mjs +55 -0
- package/src/themes/editorial/templates/home.astro +4 -4
- package/src/themes/editorial/templates/post-minimal.astro +2 -2
- package/src/themes/editorial/theme.css +27 -37
- package/src/themes/editorial/theme.json +25 -3
- package/src/themes/field/theme.json +27 -9
- package/src/themes/ink/theme.json +30 -12
- package/src/themes/night/theme.css +4 -7
- package/src/themes/night/theme.json +28 -10
- package/src/virtual.d.ts +14 -0
- package/src/worker.ts +5 -1
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
---
|
|
2
|
-
import { checkPassword, createSessionToken, verifyPassword,
|
|
2
|
+
import { checkPassword, createSessionToken, verifyPassword, validateSession, SESSION_COOKIE } from '../../lib/auth';
|
|
3
3
|
import { getRepo } from '../../lib/repo';
|
|
4
4
|
import { BRAND } from '../../lib/brand';
|
|
5
|
+
import ThemeScript from '../../components/ThemeScript.astro';
|
|
5
6
|
import '../../styles/admin.css';
|
|
6
7
|
|
|
7
|
-
if (
|
|
8
|
+
if ((await validateSession(Astro.cookies.get(SESSION_COOKIE)?.value, Astro.locals))) {
|
|
8
9
|
return Astro.redirect('/admin');
|
|
9
10
|
}
|
|
10
11
|
|
|
@@ -17,12 +18,13 @@ if (Astro.request.method === 'POST') {
|
|
|
17
18
|
// Email empty → the env master password (bootstrap owner). Email present →
|
|
18
19
|
// a user account created in /admin/users.
|
|
19
20
|
let sessionUserId: string | null = null;
|
|
21
|
+
let sessionVersion = 0;
|
|
20
22
|
if (!email && checkPassword(password)) {
|
|
21
23
|
sessionUserId = null; // default token = env owner
|
|
22
24
|
} else if (email) {
|
|
23
25
|
const repo = await getRepo(Astro.locals);
|
|
24
26
|
const auth = await repo.getUserAuth(email);
|
|
25
|
-
if (auth && (await verifyPassword(password, auth.passHash))) sessionUserId = auth.user.id;
|
|
27
|
+
if (auth && (await verifyPassword(password, auth.passHash))) { sessionUserId = auth.user.id; sessionVersion = auth.sessionVersion; }
|
|
26
28
|
else {
|
|
27
29
|
error = 'Wrong email or password.';
|
|
28
30
|
}
|
|
@@ -31,7 +33,7 @@ if (Astro.request.method === 'POST') {
|
|
|
31
33
|
}
|
|
32
34
|
|
|
33
35
|
if (!error) {
|
|
34
|
-
Astro.cookies.set(SESSION_COOKIE, sessionUserId ? createSessionToken(sessionUserId) : createSessionToken(), {
|
|
36
|
+
Astro.cookies.set(SESSION_COOKIE, sessionUserId ? createSessionToken(sessionUserId, sessionVersion) : createSessionToken(), {
|
|
35
37
|
httpOnly: true,
|
|
36
38
|
sameSite: 'lax',
|
|
37
39
|
path: '/',
|
|
@@ -47,7 +49,8 @@ if (Astro.request.method === 'POST') {
|
|
|
47
49
|
<html lang="en">
|
|
48
50
|
<head>
|
|
49
51
|
<meta charset="utf-8" />
|
|
50
|
-
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
52
|
+
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />
|
|
53
|
+
<ThemeScript />
|
|
51
54
|
<meta name="robots" content="noindex" />
|
|
52
55
|
<title>Sign in · {BRAND.name} admin</title>
|
|
53
56
|
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
|
@@ -58,9 +61,9 @@ if (Astro.request.method === 'POST') {
|
|
|
58
61
|
<div class="card card-pad login-card">
|
|
59
62
|
<div class="brand">
|
|
60
63
|
<svg width="26" height="26" viewBox="0 0 24 24" role="img" aria-label={BRAND.name}>
|
|
61
|
-
<rect x="1" y="3" width="22" height="4.4" rx="1.9" fill="
|
|
62
|
-
<rect x="1" y="10" width="12.5" height="4.4" rx="1.9" fill="
|
|
63
|
-
<rect x="1" y="17" width="17.5" height="4.4" rx="1.9" fill="
|
|
64
|
+
<rect x="1" y="3" width="22" height="4.4" rx="1.9" fill="currentColor" opacity="0.85" />
|
|
65
|
+
<rect x="1" y="10" width="12.5" height="4.4" rx="1.9" fill="var(--accent)" />
|
|
66
|
+
<rect x="1" y="17" width="17.5" height="4.4" rx="1.9" fill="currentColor" opacity="0.35" />
|
|
64
67
|
</svg>
|
|
65
68
|
<div class="brand-name">{BRAND.name}</div>
|
|
66
69
|
</div>
|
|
@@ -74,9 +77,10 @@ if (Astro.request.method === 'POST') {
|
|
|
74
77
|
<span>Password</span>
|
|
75
78
|
<input type="password" name="password" autofocus autocomplete="current-password" />
|
|
76
79
|
</label>
|
|
77
|
-
<button class="btn primary
|
|
80
|
+
<button class="btn primary block" type="submit">Sign in</button>
|
|
78
81
|
</form>
|
|
79
|
-
<p class="hint"
|
|
82
|
+
<p class="hint"><a href="/account/forgot">Forgot your password?</a></p>
|
|
83
|
+
<p class="hint login-note">No account? The owner password from <code>ADMIN_PASSWORD</code> in <code>.env</code> always works with email left empty.</p>
|
|
80
84
|
</div>
|
|
81
85
|
</div>
|
|
82
86
|
</body>
|
|
@@ -2,9 +2,14 @@
|
|
|
2
2
|
import Admin from '../../layouts/Admin.astro';
|
|
3
3
|
import { getRepo } from '../../lib/repo';
|
|
4
4
|
import NavManager from '../../components/NavManager';
|
|
5
|
+
import { draftNavItems, toNavItems } from '../../lib/drafts';
|
|
5
6
|
|
|
7
|
+
// Menus stage with the design: the editor shows the staged list when one
|
|
8
|
+
// exists, the live list otherwise.
|
|
6
9
|
const repo = await getRepo(Astro.locals);
|
|
7
|
-
const
|
|
10
|
+
const [live, settings] = await Promise.all([repo.listNavItems(), repo.getSettings()]);
|
|
11
|
+
const stagedList = draftNavItems(settings.draftDesign);
|
|
12
|
+
const items = stagedList ? toNavItems(stagedList) : live;
|
|
8
13
|
---
|
|
9
14
|
|
|
10
15
|
<Admin title="Navigation" section="navigation">
|
|
@@ -12,6 +17,7 @@ const items = await repo.listNavItems();
|
|
|
12
17
|
<h1>Navigation</h1>
|
|
13
18
|
<a class="btn sm" href="/" target="_blank" rel="noopener">View site ↗</a>
|
|
14
19
|
</div>
|
|
20
|
+
<p class="hint nm-intro">Menu changes are staged and go live with <b>Publish</b>, together with any staged design changes. Use Preview site to see them first.</p>
|
|
15
21
|
|
|
16
|
-
<NavManager client:only="react" items={items} />
|
|
22
|
+
<NavManager client:only="react" items={items} staged={Boolean(stagedList)} />
|
|
17
23
|
</Admin>
|
|
@@ -7,6 +7,7 @@ import { env } from '../../../lib/env';
|
|
|
7
7
|
import { BRAND } from '../../../lib/brand';
|
|
8
8
|
import { mergePageDraft } from '../../../lib/drafts';
|
|
9
9
|
import { localeHomeUrl } from '../../../lib/i18n';
|
|
10
|
+
import ThemeScript from '../../../components/ThemeScript.astro';
|
|
10
11
|
import PostEditor from '../../../components/editor/PostEditor';
|
|
11
12
|
import '../../../styles/admin.css';
|
|
12
13
|
import '../../../styles/editor.css';
|
|
@@ -35,7 +36,8 @@ const templates = Object.keys(resolveDesign(settings).theme.pageTemplates);
|
|
|
35
36
|
<html lang="en">
|
|
36
37
|
<head>
|
|
37
38
|
<meta charset="utf-8" />
|
|
38
|
-
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
39
|
+
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover, interactive-widget=resizes-visual" />
|
|
40
|
+
<ThemeScript />
|
|
39
41
|
<meta name="robots" content="noindex" />
|
|
40
42
|
<title>{page.title || 'Untitled'} · {BRAND.name} editor</title>
|
|
41
43
|
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
|
@@ -52,6 +54,7 @@ const templates = Object.keys(resolveDesign(settings).theme.pageTemplates);
|
|
|
52
54
|
sharePath={sharePath}
|
|
53
55
|
livePath={livePath}
|
|
54
56
|
templates={templates}
|
|
57
|
+
site={{ title: settings.siteTitle, url: settings.siteUrl }}
|
|
55
58
|
/>
|
|
56
59
|
</body>
|
|
57
60
|
</html>
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
---
|
|
2
2
|
import Admin from '../../../layouts/Admin.astro';
|
|
3
3
|
import Modal from '../../../components/Modal.astro';
|
|
4
|
+
import ContentList, { type ContentItem } from '../../../components/ContentList.astro';
|
|
4
5
|
import { getRepo } from '../../../lib/repo';
|
|
5
|
-
import { slugify } from '../../../lib/schema';
|
|
6
|
+
import { slugify, type Status } from '../../../lib/schema';
|
|
6
7
|
import { I18N, localeHomeUrl } from '../../../lib/i18n';
|
|
7
8
|
|
|
8
9
|
const repo = await getRepo(Astro.locals);
|
|
@@ -19,21 +20,44 @@ if (Astro.request.method === 'POST') {
|
|
|
19
20
|
const page = await repo.createPage({ title, slug });
|
|
20
21
|
return Astro.redirect(`/admin/pages/${page.id}`);
|
|
21
22
|
}
|
|
22
|
-
if (op === '
|
|
23
|
-
|
|
23
|
+
if (op === 'bulk') {
|
|
24
|
+
const to = String(form.get('to'));
|
|
25
|
+
for (const id of form.getAll('ids').map(String).filter(Boolean)) {
|
|
26
|
+
if (to === 'delete') await repo.deletePage(id);
|
|
27
|
+
else if (to === 'published' || to === 'draft' || to === 'archived') await repo.updatePage(id, { status: to as Status });
|
|
28
|
+
}
|
|
24
29
|
return Astro.redirect('/admin/pages');
|
|
25
30
|
}
|
|
26
31
|
}
|
|
27
32
|
|
|
28
|
-
const pages = await repo.listPages();
|
|
33
|
+
const [pages, settings] = await Promise.all([repo.listPages(), repo.getSettings()]);
|
|
29
34
|
const showNew = Astro.url.searchParams.has('new');
|
|
30
|
-
const
|
|
35
|
+
const items: ContentItem[] = [...pages]
|
|
36
|
+
.sort((a, b) => Number(b.isHome) - Number(a.isHome) || b.updatedAt - a.updatedAt)
|
|
37
|
+
.map((p) => {
|
|
38
|
+
const path = p.isHome ? localeHomeUrl(p.locale) : `/${p.slug}`;
|
|
39
|
+
return {
|
|
40
|
+
id: p.id,
|
|
41
|
+
href: `/admin/pages/${p.id}`,
|
|
42
|
+
title: p.title,
|
|
43
|
+
sub: path,
|
|
44
|
+
meta: p.isHome ? 'Home page' : '',
|
|
45
|
+
at: p.updatedAt,
|
|
46
|
+
status: p.status,
|
|
47
|
+
edited: Boolean(p.draft),
|
|
48
|
+
viewHref: p.status === 'published' ? path : undefined,
|
|
49
|
+
badges: I18N.enabled ? [(p.locale || I18N.defaultLocale).toUpperCase()] : [],
|
|
50
|
+
};
|
|
51
|
+
});
|
|
31
52
|
---
|
|
32
53
|
|
|
33
54
|
<Admin title="Pages" section="pages">
|
|
34
55
|
<div class="page-head">
|
|
35
|
-
<
|
|
36
|
-
|
|
56
|
+
<div>
|
|
57
|
+
<h1>Pages</h1>
|
|
58
|
+
<p class="sub">{pages.length} {pages.length === 1 ? 'page' : 'pages'} · static pages and your home page</p>
|
|
59
|
+
</div>
|
|
60
|
+
<div class="page-actions"><a class="btn" href="/admin/ai?kind=pages">Create from document</a><button class="btn primary" type="button" data-modal="new-page">New page</button></div>
|
|
37
61
|
</div>
|
|
38
62
|
|
|
39
63
|
<Modal id="new-page" title="New page" open={showNew}>
|
|
@@ -54,48 +78,17 @@ const fmt = (ts: number) => new Date(ts).toLocaleDateString('en-US', { month: 's
|
|
|
54
78
|
<button class="btn ghost" type="button" data-close>Cancel</button>
|
|
55
79
|
<button class="btn primary" type="submit">Create page</button>
|
|
56
80
|
</div>
|
|
57
|
-
<p class="hint
|
|
81
|
+
<p class="hint modal-note">Creates a draft and opens the editor.</p>
|
|
58
82
|
</form>
|
|
59
83
|
</Modal>
|
|
60
84
|
|
|
61
|
-
|
|
62
|
-
<
|
|
63
|
-
<
|
|
64
|
-
<
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
</td>
|
|
71
|
-
<td>
|
|
72
|
-
<span class={`pill ${p.status}`}>{p.status}</span>
|
|
73
|
-
{p.draft && <span class="pill edited" title="Has pending edits — press Update in the editor to push them live">edited</span>}
|
|
74
|
-
{p.isHome && <span class="pill home">home</span>}
|
|
75
|
-
{I18N.enabled && <span class="pill lang">{(p.locale || I18N.defaultLocale).toUpperCase()}</span>}
|
|
76
|
-
</td>
|
|
77
|
-
<td class="t-sub">{fmt(p.updatedAt)}</td>
|
|
78
|
-
<td style="text-align:right">
|
|
79
|
-
<form class="inline-form" method="post" onsubmit="return confirm('Delete this page?')">
|
|
80
|
-
<input type="hidden" name="op" value="delete" />
|
|
81
|
-
<input type="hidden" name="id" value={p.id} />
|
|
82
|
-
<button class="btn sm ghost danger" type="submit">Delete</button>
|
|
83
|
-
</form>
|
|
84
|
-
</td>
|
|
85
|
-
</tr>
|
|
86
|
-
))}
|
|
87
|
-
{pages.length === 0 && (
|
|
88
|
-
<tr>
|
|
89
|
-
<td colspan="4">
|
|
90
|
-
<div class="empty-state">
|
|
91
|
-
<b>No pages yet</b>
|
|
92
|
-
<p>Your site's static pages — about, contact, landing pages — live here.</p>
|
|
93
|
-
<button class="btn primary" type="button" data-modal="new-page">New page</button>
|
|
94
|
-
</div>
|
|
95
|
-
</td>
|
|
96
|
-
</tr>
|
|
97
|
-
)}
|
|
98
|
-
</tbody>
|
|
99
|
-
</table>
|
|
100
|
-
</div>
|
|
85
|
+
{pages.length === 0 ? (
|
|
86
|
+
<div class="empty-state">
|
|
87
|
+
<b>No pages yet</b>
|
|
88
|
+
<p>Your site's static pages — about, contact, landing pages — live here.</p>
|
|
89
|
+
<button class="btn primary" type="button" data-modal="new-page">New page</button>
|
|
90
|
+
</div>
|
|
91
|
+
) : (
|
|
92
|
+
<ContentList items={items} noun="page" timeZone={settings.timezone || undefined} groupByMonth={false} />
|
|
93
|
+
)}
|
|
101
94
|
</Admin>
|