@jant/core 0.3.24 → 0.3.26

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 (277) hide show
  1. package/dist/app.js +101 -571
  2. package/dist/client.js +1 -0
  3. package/dist/db/schema.js +1 -1
  4. package/dist/i18n/locales/en.js +1 -1
  5. package/dist/i18n/locales/zh-Hans.js +1 -1
  6. package/dist/i18n/locales/zh-Hant.js +1 -1
  7. package/dist/index.js +3 -9
  8. package/dist/lib/avatar-upload.js +134 -0
  9. package/dist/lib/config.js +39 -0
  10. package/dist/lib/constants.js +10 -9
  11. package/dist/lib/favicon.js +102 -0
  12. package/dist/lib/image.js +13 -17
  13. package/dist/lib/media-helpers.js +2 -2
  14. package/dist/lib/nav-reorder.js +1 -1
  15. package/dist/lib/navigation.js +48 -3
  16. package/dist/lib/pagination.js +44 -0
  17. package/dist/lib/render.js +16 -11
  18. package/dist/lib/schemas.js +34 -3
  19. package/dist/lib/theme.js +4 -4
  20. package/dist/lib/timeline.js +24 -48
  21. package/dist/lib/timezones.js +388 -0
  22. package/dist/lib/view.js +3 -3
  23. package/dist/routes/api/collections.js +124 -0
  24. package/dist/routes/api/nav-items.js +104 -0
  25. package/dist/routes/api/pages.js +91 -0
  26. package/dist/routes/api/posts.js +3 -3
  27. package/dist/routes/api/search.js +2 -2
  28. package/dist/routes/api/settings.js +68 -0
  29. package/dist/routes/api/upload.js +3 -3
  30. package/dist/routes/auth/reset.js +221 -0
  31. package/dist/routes/auth/setup.js +194 -0
  32. package/dist/routes/auth/signin.js +176 -0
  33. package/dist/routes/compose.js +48 -0
  34. package/dist/routes/dash/collections.js +24 -416
  35. package/dist/routes/dash/index.js +1 -1
  36. package/dist/routes/dash/media.js +13 -393
  37. package/dist/routes/dash/pages.js +112 -86
  38. package/dist/routes/dash/posts.js +3 -5
  39. package/dist/routes/dash/redirects.js +20 -14
  40. package/dist/routes/dash/settings.js +213 -518
  41. package/dist/routes/feed/rss.js +4 -3
  42. package/dist/routes/feed/sitemap.js +5 -3
  43. package/dist/routes/pages/archive.js +3 -6
  44. package/dist/routes/pages/collection.js +3 -6
  45. package/dist/routes/pages/collections.js +28 -0
  46. package/dist/routes/pages/featured.js +36 -0
  47. package/dist/routes/pages/home.js +33 -49
  48. package/dist/routes/pages/latest.js +45 -0
  49. package/dist/routes/pages/page.js +29 -32
  50. package/dist/routes/pages/post.js +3 -6
  51. package/dist/routes/pages/search.js +3 -6
  52. package/dist/services/page.js +5 -1
  53. package/dist/services/post.js +45 -31
  54. package/dist/services/search.js +1 -1
  55. package/dist/types/bindings.js +3 -0
  56. package/dist/types/config.js +147 -0
  57. package/dist/types/constants.js +27 -0
  58. package/dist/types/entities.js +3 -0
  59. package/dist/types/operations.js +3 -0
  60. package/dist/types/props.js +3 -0
  61. package/dist/types/views.js +5 -0
  62. package/dist/types.js +8 -111
  63. package/dist/{theme → ui}/color-themes.js +33 -33
  64. package/dist/ui/compose/ComposeDialog.js +467 -0
  65. package/dist/ui/compose/ComposePrompt.js +55 -0
  66. package/dist/{theme/components/TypeBadge.js → ui/dash/FormatBadge.js} +1 -2
  67. package/dist/{theme/components → ui/dash}/PageForm.js +21 -15
  68. package/dist/{theme/components → ui/dash}/PostForm.js +22 -43
  69. package/dist/{theme/components → ui/dash}/PostList.js +6 -6
  70. package/dist/{theme/components/VisibilityBadge.js → ui/dash/StatusBadge.js} +1 -2
  71. package/dist/ui/dash/collections/CollectionForm.js +152 -0
  72. package/dist/ui/dash/collections/CollectionsListContent.js +68 -0
  73. package/dist/ui/dash/collections/ViewCollectionContent.js +96 -0
  74. package/dist/{theme/components → ui/dash}/index.js +3 -6
  75. package/dist/ui/dash/media/MediaListContent.js +166 -0
  76. package/dist/ui/dash/media/ViewMediaContent.js +212 -0
  77. package/dist/ui/dash/pages/LinkFormContent.js +130 -0
  78. package/dist/ui/dash/pages/UnifiedPagesContent.js +193 -0
  79. package/dist/ui/dash/settings/AccountContent.js +209 -0
  80. package/dist/ui/dash/settings/AppearanceContent.js +259 -0
  81. package/dist/ui/dash/settings/GeneralContent.js +536 -0
  82. package/dist/ui/dash/settings/SettingsNav.js +41 -0
  83. package/dist/{themes/threads/timeline → ui/feed}/LinkCard.js +6 -2
  84. package/dist/{themes/threads/timeline → ui/feed}/NoteCard.js +11 -6
  85. package/dist/{themes/threads/timeline → ui/feed}/QuoteCard.js +10 -6
  86. package/dist/{themes/threads/timeline → ui/feed}/ThreadPreview.js +7 -9
  87. package/dist/ui/feed/TimelineFeed.js +41 -0
  88. package/dist/ui/feed/TimelineItem.js +27 -0
  89. package/dist/ui/font-themes.js +36 -0
  90. package/dist/{theme → ui}/layouts/BaseLayout.js +34 -2
  91. package/dist/{theme → ui}/layouts/DashLayout.js +0 -8
  92. package/dist/ui/layouts/SiteLayout.js +169 -0
  93. package/dist/{themes/threads → ui}/pages/ArchivePage.js +16 -14
  94. package/dist/{themes/threads → ui}/pages/CollectionPage.js +6 -1
  95. package/dist/ui/pages/CollectionsPage.js +76 -0
  96. package/dist/ui/pages/FeaturedPage.js +24 -0
  97. package/dist/ui/pages/HomePage.js +24 -0
  98. package/dist/{themes/threads → ui}/pages/PostPage.js +13 -8
  99. package/dist/{themes/threads → ui}/pages/SearchPage.js +9 -7
  100. package/dist/{themes/threads → ui}/pages/SinglePage.js +3 -2
  101. package/dist/{theme/components → ui/shared}/MediaGallery.js +1 -1
  102. package/dist/{theme/components → ui/shared}/Pagination.js +41 -2
  103. package/dist/{theme/components → ui/shared}/ThreadView.js +2 -2
  104. package/dist/ui/shared/index.js +5 -0
  105. package/package.json +1 -9
  106. package/src/__tests__/helpers/db.ts +3 -0
  107. package/src/app.tsx +131 -561
  108. package/src/client.ts +1 -0
  109. package/src/db/migrations/0006_rename_slug_to_path.sql +5 -0
  110. package/src/db/migrations/meta/_journal.json +7 -0
  111. package/src/db/schema.ts +1 -1
  112. package/src/i18n/locales/en.po +477 -261
  113. package/src/i18n/locales/en.ts +1 -1
  114. package/src/i18n/locales/zh-Hans.po +477 -261
  115. package/src/i18n/locales/zh-Hans.ts +1 -1
  116. package/src/i18n/locales/zh-Hant.po +477 -261
  117. package/src/i18n/locales/zh-Hant.ts +1 -1
  118. package/src/index.ts +7 -36
  119. package/src/lib/__tests__/config.test.ts +192 -0
  120. package/src/lib/__tests__/favicon.test.ts +151 -0
  121. package/src/lib/__tests__/image.test.ts +2 -6
  122. package/src/lib/__tests__/schemas.test.ts +60 -19
  123. package/src/lib/__tests__/timeline.test.ts +45 -81
  124. package/src/lib/__tests__/timezones.test.ts +61 -0
  125. package/src/lib/__tests__/view.test.ts +15 -9
  126. package/src/lib/avatar-upload.ts +165 -0
  127. package/src/lib/config.ts +47 -0
  128. package/src/lib/constants.ts +19 -10
  129. package/src/lib/favicon.ts +115 -0
  130. package/src/lib/image.ts +13 -21
  131. package/src/lib/media-helpers.ts +2 -2
  132. package/src/lib/nav-reorder.ts +1 -1
  133. package/src/lib/navigation.ts +73 -4
  134. package/src/lib/pagination.ts +50 -0
  135. package/src/lib/render.tsx +22 -15
  136. package/src/lib/schemas.ts +47 -6
  137. package/src/lib/theme.ts +5 -5
  138. package/src/lib/timeline.ts +28 -57
  139. package/src/lib/timezones.ts +325 -0
  140. package/src/lib/view.ts +3 -3
  141. package/src/preset.css +2 -1
  142. package/src/routes/__tests__/compose.test.ts +199 -0
  143. package/src/routes/api/__tests__/collections.test.ts +249 -0
  144. package/src/routes/api/__tests__/nav-items.test.ts +222 -0
  145. package/src/routes/api/__tests__/pages.test.ts +218 -0
  146. package/src/routes/api/__tests__/settings.test.ts +132 -0
  147. package/src/routes/api/collections.ts +143 -0
  148. package/src/routes/api/nav-items.ts +115 -0
  149. package/src/routes/api/pages.ts +101 -0
  150. package/src/routes/api/posts.ts +3 -3
  151. package/src/routes/api/search.ts +2 -2
  152. package/src/routes/api/settings.ts +91 -0
  153. package/src/routes/api/upload.ts +2 -3
  154. package/src/routes/auth/reset.tsx +239 -0
  155. package/src/routes/auth/setup.tsx +189 -0
  156. package/src/routes/auth/signin.tsx +163 -0
  157. package/src/routes/compose.ts +63 -0
  158. package/src/routes/dash/__tests__/pages.test.ts +225 -0
  159. package/src/routes/dash/__tests__/settings-avatar.test.ts +89 -0
  160. package/src/routes/dash/collections.tsx +18 -367
  161. package/src/routes/dash/index.tsx +1 -1
  162. package/src/routes/dash/media.tsx +13 -415
  163. package/src/routes/dash/pages.tsx +131 -98
  164. package/src/routes/dash/posts.tsx +3 -7
  165. package/src/routes/dash/redirects.tsx +22 -16
  166. package/src/routes/dash/settings.tsx +265 -478
  167. package/src/routes/feed/__tests__/rss.test.ts +141 -0
  168. package/src/routes/feed/rss.ts +5 -3
  169. package/src/routes/feed/sitemap.ts +5 -3
  170. package/src/routes/pages/__tests__/collections.test.ts +94 -0
  171. package/src/routes/pages/__tests__/featured.test.ts +94 -0
  172. package/src/routes/pages/archive.tsx +2 -6
  173. package/src/routes/pages/collection.tsx +2 -6
  174. package/src/routes/pages/collections.tsx +36 -0
  175. package/src/routes/pages/featured.tsx +44 -0
  176. package/src/routes/pages/home.tsx +30 -53
  177. package/src/routes/pages/latest.tsx +59 -0
  178. package/src/routes/pages/page.tsx +28 -30
  179. package/src/routes/pages/post.tsx +2 -5
  180. package/src/routes/pages/search.tsx +2 -6
  181. package/src/services/__tests__/page.test.ts +106 -0
  182. package/src/services/__tests__/post.test.ts +114 -15
  183. package/src/services/page.ts +13 -1
  184. package/src/services/post.ts +58 -40
  185. package/src/services/search.ts +2 -2
  186. package/src/styles/components.css +0 -65
  187. package/src/styles/tokens.css +47 -0
  188. package/src/styles/ui.css +475 -0
  189. package/src/types/bindings.ts +30 -0
  190. package/src/types/config.ts +183 -0
  191. package/src/types/constants.ts +26 -0
  192. package/src/types/entities.ts +109 -0
  193. package/src/types/operations.ts +88 -0
  194. package/src/types/props.ts +115 -0
  195. package/src/types/views.ts +172 -0
  196. package/src/types.ts +8 -774
  197. package/src/ui/__tests__/font-themes.test.ts +34 -0
  198. package/src/{theme → ui}/color-themes.ts +34 -34
  199. package/src/ui/compose/ComposeDialog.tsx +414 -0
  200. package/src/ui/compose/ComposePrompt.tsx +55 -0
  201. package/src/{theme/components/TypeBadge.tsx → ui/dash/FormatBadge.tsx} +2 -3
  202. package/src/{theme/components → ui/dash}/PageForm.tsx +25 -19
  203. package/src/{theme/components → ui/dash}/PostForm.tsx +26 -45
  204. package/src/{theme/components → ui/dash}/PostList.tsx +7 -7
  205. package/src/{theme/components/VisibilityBadge.tsx → ui/dash/StatusBadge.tsx} +2 -3
  206. package/src/ui/dash/collections/CollectionForm.tsx +153 -0
  207. package/src/ui/dash/collections/CollectionsListContent.tsx +85 -0
  208. package/src/ui/dash/collections/ViewCollectionContent.tsx +92 -0
  209. package/src/ui/dash/index.ts +10 -0
  210. package/src/ui/dash/media/MediaListContent.tsx +201 -0
  211. package/src/ui/dash/media/ViewMediaContent.tsx +208 -0
  212. package/src/ui/dash/pages/LinkFormContent.tsx +119 -0
  213. package/src/ui/dash/pages/UnifiedPagesContent.tsx +203 -0
  214. package/src/ui/dash/settings/AccountContent.tsx +176 -0
  215. package/src/ui/dash/settings/AppearanceContent.tsx +254 -0
  216. package/src/ui/dash/settings/GeneralContent.tsx +533 -0
  217. package/src/ui/dash/settings/SettingsNav.tsx +56 -0
  218. package/src/{themes/threads/timeline → ui/feed}/LinkCard.tsx +9 -4
  219. package/src/{themes/threads/timeline → ui/feed}/NoteCard.tsx +13 -8
  220. package/src/{themes/threads/timeline → ui/feed}/QuoteCard.tsx +13 -8
  221. package/src/{themes/threads/timeline → ui/feed}/ThreadPreview.tsx +7 -8
  222. package/src/ui/feed/TimelineFeed.tsx +49 -0
  223. package/src/ui/feed/TimelineItem.tsx +45 -0
  224. package/src/ui/font-themes.ts +54 -0
  225. package/src/{theme → ui}/layouts/BaseLayout.tsx +28 -1
  226. package/src/{theme → ui}/layouts/DashLayout.tsx +0 -10
  227. package/src/ui/layouts/SiteLayout.tsx +164 -0
  228. package/src/{themes/threads → ui}/pages/ArchivePage.tsx +22 -17
  229. package/src/{themes/threads → ui}/pages/CollectionPage.tsx +14 -5
  230. package/src/ui/pages/CollectionsPage.tsx +73 -0
  231. package/src/ui/pages/FeaturedPage.tsx +31 -0
  232. package/src/{themes/threads → ui}/pages/HomePage.tsx +11 -15
  233. package/src/{themes/threads → ui}/pages/PostPage.tsx +23 -14
  234. package/src/{themes/threads → ui}/pages/SearchPage.tsx +13 -11
  235. package/src/{themes/threads → ui}/pages/SinglePage.tsx +4 -4
  236. package/src/{theme/components → ui/shared}/MediaGallery.tsx +1 -1
  237. package/src/{theme/components → ui/shared}/Pagination.tsx +67 -4
  238. package/src/{theme/components → ui/shared}/ThreadView.tsx +2 -2
  239. package/src/ui/shared/__tests__/pagination.test.ts +46 -0
  240. package/src/ui/shared/index.ts +12 -0
  241. package/bin/jant.js +0 -185
  242. package/dist/lib/theme-components.js +0 -46
  243. package/dist/routes/dash/navigation.js +0 -289
  244. package/dist/theme/index.js +0 -18
  245. package/dist/theme/layouts/index.js +0 -2
  246. package/dist/themes/threads/ThreadsSiteLayout.js +0 -172
  247. package/dist/themes/threads/index.js +0 -81
  248. package/dist/themes/threads/pages/HomePage.js +0 -25
  249. package/dist/themes/threads/timeline/TimelineFeed.js +0 -58
  250. package/dist/themes/threads/timeline/TimelineItem.js +0 -36
  251. package/dist/themes/threads/timeline/TimelineLoadMore.js +0 -23
  252. package/dist/themes/threads/timeline/groupByDate.js +0 -22
  253. package/dist/themes/threads/timeline/timelineMore.js +0 -107
  254. package/src/lib/__tests__/theme-components.test.ts +0 -105
  255. package/src/lib/theme-components.ts +0 -65
  256. package/src/routes/dash/navigation.tsx +0 -317
  257. package/src/theme/components/index.ts +0 -23
  258. package/src/theme/index.ts +0 -22
  259. package/src/theme/layouts/index.ts +0 -7
  260. package/src/themes/threads/ThreadsSiteLayout.tsx +0 -194
  261. package/src/themes/threads/index.ts +0 -100
  262. package/src/themes/threads/style.css +0 -336
  263. package/src/themes/threads/timeline/TimelineFeed.tsx +0 -62
  264. package/src/themes/threads/timeline/TimelineItem.tsx +0 -67
  265. package/src/themes/threads/timeline/TimelineLoadMore.tsx +0 -35
  266. package/src/themes/threads/timeline/groupByDate.ts +0 -30
  267. package/src/themes/threads/timeline/timelineMore.tsx +0 -130
  268. /package/dist/{theme/components → ui/dash}/ActionButtons.js +0 -0
  269. /package/dist/{theme/components → ui/dash}/CrudPageHeader.js +0 -0
  270. /package/dist/{theme/components → ui/dash}/DangerZone.js +0 -0
  271. /package/dist/{theme/components → ui/dash}/ListItemRow.js +0 -0
  272. /package/dist/{theme/components → ui/shared}/EmptyState.js +0 -0
  273. /package/src/{theme/components → ui/dash}/ActionButtons.tsx +0 -0
  274. /package/src/{theme/components → ui/dash}/CrudPageHeader.tsx +0 -0
  275. /package/src/{theme/components → ui/dash}/DangerZone.tsx +0 -0
  276. /package/src/{theme/components → ui/dash}/ListItemRow.tsx +0 -0
  277. /package/src/{theme/components → ui/shared}/EmptyState.tsx +0 -0
@@ -1,85 +1,20 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "hono/jsx/jsx-runtime";
2
- import { getSiteName } from "../../lib/config.js";
3
2
  /**
4
- * Dashboard Pages Routes
3
+ * Dashboard Pages & Navigation Routes
5
4
  *
6
- * Management for standalone pages (about, now, etc.)
5
+ * Unified management for pages and navigation items.
7
6
  */ import { Hono } from "hono";
8
7
  import { useLingui as $_useLingui } from "@jant/core/i18n";
9
- import { DashLayout } from "../../theme/layouts/index.js";
10
- import { PageForm, EmptyState, ListItemRow, ActionButtons, CrudPageHeader, DangerZone } from "../../theme/components/index.js";
11
- import * as time from "../../lib/time.js";
12
- import { dsRedirect } from "../../lib/sse.js";
8
+ import { DashLayout } from "../../ui/layouts/DashLayout.js";
9
+ import { PageForm, ActionButtons, DangerZone } from "../../ui/dash/index.js";
10
+ import { dsRedirect, dsToast } from "../../lib/sse.js";
11
+ import { getSiteName } from "../../lib/config.js";
12
+ import { UnifiedPagesContent } from "../../ui/dash/pages/UnifiedPagesContent.js";
13
+ import { LinkFormContent } from "../../ui/dash/pages/LinkFormContent.js";
13
14
  export const pagesRoutes = new Hono();
14
- function PagesListContent({ pages }) {
15
- const { i18n: $__i18n, _: $__ } = $_useLingui();
16
- return /*#__PURE__*/ _jsxs(_Fragment, {
17
- children: [
18
- /*#__PURE__*/ _jsx(CrudPageHeader, {
19
- title: $__i18n._({
20
- id: "wRR604",
21
- message: "Pages"
22
- }),
23
- ctaLabel: $__i18n._({
24
- id: "GrZ6fH",
25
- message: "New Page"
26
- }),
27
- ctaHref: "/dash/pages/new"
28
- }),
29
- pages.length === 0 ? /*#__PURE__*/ _jsx(EmptyState, {
30
- message: $__i18n._({
31
- id: "LkvLQe",
32
- message: "No pages yet."
33
- }),
34
- ctaText: $__i18n._({
35
- id: "0JkyS7",
36
- message: "Create your first page"
37
- }),
38
- ctaHref: "/dash/pages/new"
39
- }) : /*#__PURE__*/ _jsx("div", {
40
- class: "flex flex-col divide-y",
41
- children: pages.map((page)=>/*#__PURE__*/ _jsxs(ListItemRow, {
42
- actions: /*#__PURE__*/ _jsx(ActionButtons, {
43
- editHref: `/dash/pages/${page.id}/edit`,
44
- editLabel: $__i18n._({
45
- id: "ePK91l",
46
- message: "Edit"
47
- }),
48
- viewHref: page.status !== "draft" ? `/${page.slug}` : undefined,
49
- viewLabel: $__i18n._({
50
- id: "jpctdh",
51
- message: "View"
52
- })
53
- }),
54
- children: [
55
- /*#__PURE__*/ _jsx("div", {
56
- class: "flex items-center gap-2 mb-1",
57
- children: /*#__PURE__*/ _jsx("span", {
58
- class: "text-xs text-muted-foreground",
59
- children: time.formatDate(page.updatedAt)
60
- })
61
- }),
62
- /*#__PURE__*/ _jsx("a", {
63
- href: `/dash/pages/${page.id}`,
64
- class: "font-medium hover:underline",
65
- children: page.title || $__i18n._({
66
- id: "wja8aL",
67
- message: "Untitled"
68
- })
69
- }),
70
- /*#__PURE__*/ _jsxs("p", {
71
- class: "text-sm text-muted-foreground mt-1",
72
- children: [
73
- "/",
74
- page.slug
75
- ]
76
- })
77
- ]
78
- }, page.id))
79
- })
80
- ]
81
- });
82
- }
15
+ // =============================================================================
16
+ // Inline components (small, tightly coupled to route params)
17
+ // =============================================================================
83
18
  function NewPageContent() {
84
19
  const { i18n: $__i18n, _: $__ } = $_useLingui();
85
20
  return /*#__PURE__*/ _jsxs(_Fragment, {
@@ -176,21 +111,26 @@ function EditPageContent({ page }) {
176
111
  ]
177
112
  });
178
113
  }
179
- // List pages
114
+ // =============================================================================
115
+ // Route handlers
116
+ // =============================================================================
180
117
  pagesRoutes.get("/", async (c)=>{
181
- const pages = await c.var.services.pages.list();
118
+ const [navItems, otherPages] = await Promise.all([
119
+ c.var.services.navItems.list(),
120
+ c.var.services.pages.listNotInNav()
121
+ ]);
182
122
  const siteName = await getSiteName(c);
183
123
  return c.html(/*#__PURE__*/ _jsx(DashLayout, {
184
124
  c: c,
185
125
  title: "Pages",
186
126
  siteName: siteName,
187
127
  currentPath: "/dash/pages",
188
- children: /*#__PURE__*/ _jsx(PagesListContent, {
189
- pages: pages
128
+ children: /*#__PURE__*/ _jsx(UnifiedPagesContent, {
129
+ navItems: navItems,
130
+ otherPages: otherPages
190
131
  })
191
132
  }));
192
133
  });
193
- // New page form
194
134
  pagesRoutes.get("/new", async (c)=>{
195
135
  const siteName = await getSiteName(c);
196
136
  return c.html(/*#__PURE__*/ _jsx(DashLayout, {
@@ -201,7 +141,74 @@ pagesRoutes.get("/new", async (c)=>{
201
141
  children: /*#__PURE__*/ _jsx(NewPageContent, {})
202
142
  }));
203
143
  });
204
- // Create page
144
+ pagesRoutes.get("/links/new", async (c)=>{
145
+ const siteName = await getSiteName(c);
146
+ return c.html(/*#__PURE__*/ _jsx(DashLayout, {
147
+ c: c,
148
+ title: "New Link",
149
+ siteName: siteName,
150
+ currentPath: "/dash/pages",
151
+ children: /*#__PURE__*/ _jsx(LinkFormContent, {})
152
+ }));
153
+ });
154
+ pagesRoutes.post("/links", async (c)=>{
155
+ const body = await c.req.json();
156
+ if (!body.label || !body.url) {
157
+ return dsToast("Label and URL are required", "error");
158
+ }
159
+ await c.var.services.navItems.create({
160
+ type: "link",
161
+ label: body.label,
162
+ url: body.url
163
+ });
164
+ return dsRedirect("/dash/pages");
165
+ });
166
+ pagesRoutes.post("/reorder", async (c)=>{
167
+ const body = await c.req.json();
168
+ if (!Array.isArray(body.ids)) {
169
+ return dsToast("Invalid request", "error");
170
+ }
171
+ await c.var.services.navItems.reorder(body.ids);
172
+ return dsToast("Order saved");
173
+ });
174
+ pagesRoutes.get("/links/:id/edit", async (c)=>{
175
+ const id = parseInt(c.req.param("id"), 10);
176
+ if (isNaN(id)) return c.notFound();
177
+ const item = await c.var.services.navItems.getById(id);
178
+ if (!item) return c.notFound();
179
+ const siteName = await getSiteName(c);
180
+ return c.html(/*#__PURE__*/ _jsx(DashLayout, {
181
+ c: c,
182
+ title: "Edit Link",
183
+ siteName: siteName,
184
+ currentPath: "/dash/pages",
185
+ children: /*#__PURE__*/ _jsx(LinkFormContent, {
186
+ item: item,
187
+ isEdit: true
188
+ })
189
+ }));
190
+ });
191
+ pagesRoutes.post("/links/:id", async (c)=>{
192
+ const id = parseInt(c.req.param("id"), 10);
193
+ if (isNaN(id)) return c.notFound();
194
+ const body = await c.req.json();
195
+ if (!body.label || !body.url) {
196
+ return dsToast("Label and URL are required", "error");
197
+ }
198
+ const updated = await c.var.services.navItems.update(id, {
199
+ label: body.label,
200
+ url: body.url
201
+ });
202
+ if (!updated) return c.notFound();
203
+ return dsRedirect("/dash/pages");
204
+ });
205
+ pagesRoutes.post("/links/:id/delete", async (c)=>{
206
+ const id = parseInt(c.req.param("id"), 10);
207
+ if (!isNaN(id)) {
208
+ await c.var.services.navItems.delete(id);
209
+ }
210
+ return dsRedirect("/dash/pages");
211
+ });
205
212
  pagesRoutes.post("/", async (c)=>{
206
213
  const body = await c.req.json();
207
214
  const page = await c.var.services.pages.create({
@@ -212,7 +219,29 @@ pagesRoutes.post("/", async (c)=>{
212
219
  });
213
220
  return dsRedirect(`/dash/pages/${page.id}`);
214
221
  });
215
- // View single page
222
+ pagesRoutes.post("/:id/add-to-nav", async (c)=>{
223
+ const id = parseInt(c.req.param("id"), 10);
224
+ if (isNaN(id)) return c.notFound();
225
+ const page = await c.var.services.pages.getById(id);
226
+ if (!page) return c.notFound();
227
+ await c.var.services.navItems.create({
228
+ type: "page",
229
+ label: page.title || page.slug,
230
+ url: `/${page.slug}`,
231
+ pageId: page.id
232
+ });
233
+ return dsRedirect("/dash/pages");
234
+ });
235
+ pagesRoutes.post("/:id/remove-from-nav", async (c)=>{
236
+ const pageId = parseInt(c.req.param("id"), 10);
237
+ if (isNaN(pageId)) return c.notFound();
238
+ const navItems = await c.var.services.navItems.list();
239
+ const navItem = navItems.find((item)=>item.pageId === pageId);
240
+ if (navItem) {
241
+ await c.var.services.navItems.delete(navItem.id);
242
+ }
243
+ return dsRedirect("/dash/pages");
244
+ });
216
245
  pagesRoutes.get("/:id", async (c)=>{
217
246
  const id = parseInt(c.req.param("id"), 10);
218
247
  if (isNaN(id)) return c.notFound();
@@ -229,7 +258,6 @@ pagesRoutes.get("/:id", async (c)=>{
229
258
  })
230
259
  }));
231
260
  });
232
- // Edit page form
233
261
  pagesRoutes.get("/:id/edit", async (c)=>{
234
262
  const id = parseInt(c.req.param("id"), 10);
235
263
  if (isNaN(id)) return c.notFound();
@@ -246,7 +274,6 @@ pagesRoutes.get("/:id/edit", async (c)=>{
246
274
  })
247
275
  }));
248
276
  });
249
- // Update page
250
277
  pagesRoutes.post("/:id", async (c)=>{
251
278
  const id = parseInt(c.req.param("id"), 10);
252
279
  if (isNaN(id)) return c.notFound();
@@ -259,7 +286,6 @@ pagesRoutes.post("/:id", async (c)=>{
259
286
  });
260
287
  return dsRedirect(`/dash/pages/${id}`);
261
288
  });
262
- // Delete page
263
289
  pagesRoutes.post("/:id/delete", async (c)=>{
264
290
  const id = parseInt(c.req.param("id"), 10);
265
291
  if (isNaN(id)) return c.notFound();
@@ -4,8 +4,8 @@ import { getSiteName } from "../../lib/config.js";
4
4
  * Dashboard Posts Routes
5
5
  */ import { Hono } from "hono";
6
6
  import { useLingui as $_useLingui } from "@jant/core/i18n";
7
- import { DashLayout } from "../../theme/layouts/index.js";
8
- import { PostForm, PostList, CrudPageHeader, ActionButtons } from "../../theme/components/index.js";
7
+ import { DashLayout } from "../../ui/layouts/DashLayout.js";
8
+ import { PostForm, PostList, CrudPageHeader, ActionButtons } from "../../ui/dash/index.js";
9
9
  import * as sqid from "../../lib/sqid.js";
10
10
  import { dsRedirect } from "../../lib/sse.js";
11
11
  export const postsRoutes = new Hono();
@@ -88,7 +88,6 @@ postsRoutes.post("/", async (c)=>{
88
88
  status: body.status,
89
89
  featured: body.featured,
90
90
  pinned: body.pinned,
91
- slug: body.slug || undefined,
92
91
  url: body.url || undefined,
93
92
  quoteText: body.quoteText || undefined,
94
93
  rating: body.rating || undefined,
@@ -106,7 +105,7 @@ function ViewPostContent({ post }) {
106
105
  id: "y28hnO",
107
106
  message: "Post"
108
107
  });
109
- const permalink = post.slug ? `/${post.slug}` : `/p/${sqid.encode(post.id)}`;
108
+ const permalink = post.path ? `/${post.path}` : `/p/${sqid.encode(post.id)}`;
110
109
  return /*#__PURE__*/ _jsxs(_Fragment, {
111
110
  children: [
112
111
  /*#__PURE__*/ _jsxs("div", {
@@ -224,7 +223,6 @@ postsRoutes.post("/:id", async (c)=>{
224
223
  status: body.status,
225
224
  featured: body.featured,
226
225
  pinned: body.pinned,
227
- slug: body.slug || null,
228
226
  url: body.url || null,
229
227
  quoteText: body.quoteText || null,
230
228
  rating: body.rating || null,
@@ -4,8 +4,8 @@ import { getSiteName } from "../../lib/config.js";
4
4
  * Dashboard Redirects Routes
5
5
  */ import { Hono } from "hono";
6
6
  import { useLingui as $_useLingui } from "@jant/core/i18n";
7
- import { DashLayout } from "../../theme/layouts/index.js";
8
- import { EmptyState, ListItemRow, ActionButtons, CrudPageHeader } from "../../theme/components/index.js";
7
+ import { DashLayout } from "../../ui/layouts/DashLayout.js";
8
+ import { EmptyState, ListItemRow, ActionButtons, CrudPageHeader } from "../../ui/dash/index.js";
9
9
  import { dsRedirect } from "../../lib/sse.js";
10
10
  export const redirectsRoutes = new Hono();
11
11
  function RedirectsListContent({ redirects }) {
@@ -176,21 +176,27 @@ function NewRedirectContent() {
176
176
  /*#__PURE__*/ _jsxs("button", {
177
177
  type: "submit",
178
178
  class: "btn",
179
- "data-attr-disabled": "$_loading",
179
+ "data-attr:disabled": "$_loading",
180
180
  children: [
181
- /*#__PURE__*/ _jsx("span", {
182
- "data-show": "!$_loading",
183
- children: $__i18n._({
184
- id: "Mhf/H/",
185
- message: "Create Redirect"
186
- })
187
- }),
188
- /*#__PURE__*/ _jsx("span", {
181
+ /*#__PURE__*/ _jsx("svg", {
189
182
  "data-show": "$_loading",
190
- children: $__i18n._({
191
- id: "k1ifdL",
192
- message: "Processing..."
183
+ style: "display:none",
184
+ class: "animate-spin size-4",
185
+ xmlns: "http://www.w3.org/2000/svg",
186
+ viewBox: "0 0 24 24",
187
+ fill: "none",
188
+ stroke: "currentColor",
189
+ "stroke-width": "2",
190
+ "stroke-linecap": "round",
191
+ "stroke-linejoin": "round",
192
+ role: "status",
193
+ children: /*#__PURE__*/ _jsx("path", {
194
+ d: "M21 12a9 9 0 1 1-6.219-8.56"
193
195
  })
196
+ }),
197
+ $__i18n._({
198
+ id: "Mhf/H/",
199
+ message: "Create Redirect"
194
200
  })
195
201
  ]
196
202
  }),