@jant/core 0.2.12 → 0.2.13
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/bin/jant.js +3 -1
- package/dist/app.d.ts.map +1 -1
- package/dist/app.js +112 -85
- package/dist/auth.d.ts +1 -0
- package/dist/auth.d.ts.map +1 -1
- package/dist/auth.js +2 -1
- package/dist/client.js +1 -1
- package/dist/db/schema.d.ts.map +1 -1
- package/dist/i18n/context.d.ts.map +1 -1
- package/dist/i18n/context.js +0 -3
- package/dist/i18n/detect.d.ts +0 -11
- package/dist/i18n/detect.d.ts.map +1 -1
- package/dist/i18n/detect.js +1 -52
- package/dist/i18n/i18n.d.ts +4 -14
- package/dist/i18n/i18n.d.ts.map +1 -1
- package/dist/i18n/i18n.js +19 -25
- package/dist/i18n/index.d.ts +1 -1
- package/dist/i18n/index.d.ts.map +1 -1
- package/dist/i18n/index.js +1 -1
- package/dist/i18n/middleware.d.ts +2 -5
- package/dist/i18n/middleware.d.ts.map +1 -1
- package/dist/i18n/middleware.js +12 -23
- package/dist/lib/constants.d.ts.map +1 -1
- package/dist/lib/image.d.ts.map +1 -1
- package/dist/lib/schemas.d.ts.map +1 -1
- package/dist/lib/sse.d.ts +45 -17
- package/dist/lib/sse.d.ts.map +1 -1
- package/dist/lib/sse.js +77 -37
- package/dist/middleware/auth.d.ts.map +1 -1
- package/dist/routes/api/posts.js +0 -1
- package/dist/routes/api/upload.js +3 -1
- package/dist/routes/dash/collections.d.ts.map +1 -1
- package/dist/routes/dash/collections.js +134 -142
- package/dist/routes/dash/index.js +25 -26
- package/dist/routes/dash/media.d.ts.map +1 -1
- package/dist/routes/dash/media.js +60 -56
- package/dist/routes/dash/pages.js +64 -66
- package/dist/routes/dash/posts.d.ts.map +1 -1
- package/dist/routes/dash/posts.js +50 -59
- package/dist/routes/dash/redirects.d.ts.map +1 -1
- package/dist/routes/dash/redirects.js +63 -60
- package/dist/routes/dash/settings.d.ts.map +1 -1
- package/dist/routes/dash/settings.js +249 -93
- package/dist/routes/feed/rss.js +6 -4
- package/dist/routes/pages/archive.js +60 -62
- package/dist/routes/pages/collection.js +8 -8
- package/dist/routes/pages/home.js +14 -14
- package/dist/routes/pages/page.js +7 -6
- package/dist/routes/pages/post.js +8 -8
- package/dist/routes/pages/search.js +25 -27
- package/dist/services/collection.d.ts.map +1 -1
- package/dist/services/index.d.ts.map +1 -1
- package/dist/services/media.d.ts.map +1 -1
- package/dist/services/post.d.ts.map +1 -1
- package/dist/services/redirect.d.ts.map +1 -1
- package/dist/services/settings.d.ts.map +1 -1
- package/dist/theme/components/ActionButtons.d.ts +1 -1
- package/dist/theme/components/ActionButtons.d.ts.map +1 -1
- package/dist/theme/components/ActionButtons.js +17 -21
- package/dist/theme/components/CrudPageHeader.d.ts.map +1 -1
- package/dist/theme/components/DangerZone.d.ts.map +1 -1
- package/dist/theme/components/DangerZone.js +12 -15
- package/dist/theme/components/EmptyState.d.ts.map +1 -1
- package/dist/theme/components/PageForm.d.ts.map +1 -1
- package/dist/theme/components/PageForm.js +58 -56
- package/dist/theme/components/Pagination.d.ts.map +1 -1
- package/dist/theme/components/Pagination.js +22 -25
- package/dist/theme/components/PostForm.d.ts +0 -1
- package/dist/theme/components/PostForm.d.ts.map +1 -1
- package/dist/theme/components/PostForm.js +85 -77
- package/dist/theme/components/PostList.d.ts.map +1 -1
- package/dist/theme/components/PostList.js +17 -17
- package/dist/theme/components/ThreadView.d.ts.map +1 -1
- package/dist/theme/components/ThreadView.js +15 -18
- package/dist/theme/components/TypeBadge.d.ts.map +1 -1
- package/dist/theme/components/TypeBadge.js +20 -20
- package/dist/theme/components/VisibilityBadge.d.ts.map +1 -1
- package/dist/theme/components/VisibilityBadge.js +14 -14
- package/dist/theme/components/index.d.ts +1 -1
- package/dist/theme/components/index.d.ts.map +1 -1
- package/dist/theme/layouts/BaseLayout.d.ts.map +1 -1
- package/dist/theme/layouts/BaseLayout.js +4 -2
- package/dist/theme/layouts/DashLayout.d.ts.map +1 -1
- package/dist/theme/layouts/DashLayout.js +29 -29
- package/dist/types/lingui-react-macro.d.js +9 -0
- package/dist/types.d.ts +2 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/vendor/datastar.js +1606 -0
- package/package.json +5 -2
- package/src/app.tsx +175 -56
- package/src/auth.ts +5 -1
- package/src/client.ts +1 -1
- package/src/db/schema.ts +22 -7
- package/src/i18n/EXAMPLES.md +34 -14
- package/src/i18n/README.md +19 -9
- package/src/i18n/context.tsx +1 -4
- package/src/i18n/detect.ts +1 -67
- package/src/i18n/i18n.ts +15 -19
- package/src/i18n/index.ts +0 -3
- package/src/i18n/middleware.ts +12 -24
- package/src/lib/constants.ts +2 -1
- package/src/lib/image-processor.ts +23 -7
- package/src/lib/image.ts +6 -2
- package/src/lib/schemas.ts +6 -2
- package/src/lib/sse.ts +138 -50
- package/src/middleware/auth.ts +6 -2
- package/src/routes/api/posts.ts +14 -5
- package/src/routes/api/upload.ts +25 -7
- package/src/routes/dash/collections.tsx +162 -70
- package/src/routes/dash/index.tsx +22 -7
- package/src/routes/dash/media.tsx +59 -16
- package/src/routes/dash/pages.tsx +102 -44
- package/src/routes/dash/posts.tsx +87 -54
- package/src/routes/dash/redirects.tsx +74 -26
- package/src/routes/dash/settings.tsx +250 -57
- package/src/routes/feed/rss.ts +6 -4
- package/src/routes/pages/archive.tsx +71 -21
- package/src/routes/pages/collection.tsx +21 -6
- package/src/routes/pages/home.tsx +30 -9
- package/src/routes/pages/page.tsx +14 -5
- package/src/routes/pages/post.tsx +21 -7
- package/src/routes/pages/search.tsx +42 -11
- package/src/services/collection.ts +34 -9
- package/src/services/index.ts +4 -1
- package/src/services/media.ts +15 -3
- package/src/services/post.ts +39 -10
- package/src/services/redirect.ts +4 -1
- package/src/services/settings.ts +14 -3
- package/src/theme/components/ActionButtons.tsx +26 -14
- package/src/theme/components/CrudPageHeader.tsx +6 -1
- package/src/theme/components/DangerZone.tsx +19 -13
- package/src/theme/components/EmptyState.tsx +6 -1
- package/src/theme/components/PageForm.tsx +71 -24
- package/src/theme/components/Pagination.tsx +26 -8
- package/src/theme/components/PostForm.tsx +72 -25
- package/src/theme/components/PostList.tsx +16 -5
- package/src/theme/components/ThreadView.tsx +25 -7
- package/src/theme/components/TypeBadge.tsx +13 -4
- package/src/theme/components/VisibilityBadge.tsx +17 -5
- package/src/theme/components/index.ts +4 -1
- package/src/theme/layouts/BaseLayout.tsx +5 -2
- package/src/theme/layouts/DashLayout.tsx +41 -12
- package/src/types/lingui-react-macro.d.ts +34 -0
- package/src/types.ts +16 -2
- package/src/vendor/datastar.js +9 -0
- package/src/vendor/datastar.js.map +7 -0
|
@@ -2,120 +2,235 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "hono/jsx/jsx-
|
|
|
2
2
|
/**
|
|
3
3
|
* Dashboard Settings Routes
|
|
4
4
|
*/ import { Hono } from "hono";
|
|
5
|
-
import { useLingui } from "
|
|
5
|
+
import { useLingui as $_useLingui } from "@jant/core/i18n";
|
|
6
6
|
import { DashLayout } from "../../theme/layouts/index.js";
|
|
7
|
+
import { sse } from "../../lib/sse.js";
|
|
7
8
|
export const settingsRoutes = new Hono();
|
|
8
|
-
function SettingsContent({ siteName, siteDescription, siteLanguage }) {
|
|
9
|
-
const {
|
|
9
|
+
function SettingsContent({ siteName, siteDescription, siteLanguage, saved }) {
|
|
10
|
+
const { i18n: $__i18n, _: $__ } = $_useLingui();
|
|
11
|
+
const generalSignals = JSON.stringify({
|
|
12
|
+
siteName,
|
|
13
|
+
siteDescription,
|
|
14
|
+
siteLanguage
|
|
15
|
+
}).replace(/</g, "\\u003c");
|
|
10
16
|
return /*#__PURE__*/ _jsxs(_Fragment, {
|
|
11
17
|
children: [
|
|
12
18
|
/*#__PURE__*/ _jsx("h1", {
|
|
13
19
|
class: "text-2xl font-semibold mb-6",
|
|
14
|
-
children:
|
|
15
|
-
|
|
16
|
-
|
|
20
|
+
children: $__i18n._({
|
|
21
|
+
id: "Tz0i8g",
|
|
22
|
+
message: "Settings"
|
|
17
23
|
})
|
|
18
24
|
}),
|
|
19
|
-
/*#__PURE__*/
|
|
20
|
-
|
|
21
|
-
|
|
25
|
+
saved && /*#__PURE__*/ _jsx("div", {
|
|
26
|
+
id: "settings-saved-toast",
|
|
27
|
+
class: "mb-4 max-w-lg rounded-md border border-green-200 bg-green-50 p-3 text-sm text-green-800 transition-opacity duration-300 dark:border-green-800 dark:bg-green-950 dark:text-green-200",
|
|
28
|
+
"data-init": `console.log('[toast] init fired at', Date.now()); history.replaceState({}, '', '/dash/settings'); setTimeout(() => { console.log('[toast] hiding at', Date.now()); const el = document.getElementById('settings-saved-toast'); if (el) { el.style.opacity = '0'; setTimeout(() => el.remove(), 300) } }, 3000)`,
|
|
29
|
+
children: $__i18n._({
|
|
30
|
+
id: "T0bsor",
|
|
31
|
+
message: "Settings saved successfully."
|
|
32
|
+
})
|
|
33
|
+
}),
|
|
34
|
+
/*#__PURE__*/ _jsxs("div", {
|
|
22
35
|
class: "flex flex-col gap-6 max-w-lg",
|
|
23
36
|
children: [
|
|
24
|
-
/*#__PURE__*/ _jsxs("
|
|
25
|
-
|
|
37
|
+
/*#__PURE__*/ _jsxs("form", {
|
|
38
|
+
"data-signals": generalSignals,
|
|
39
|
+
"data-on:submit__prevent": "@post('/dash/settings')",
|
|
26
40
|
children: [
|
|
27
|
-
/*#__PURE__*/ _jsx("
|
|
28
|
-
|
|
29
|
-
children: t({
|
|
30
|
-
message: "General",
|
|
31
|
-
comment: "@context: Settings section heading"
|
|
32
|
-
})
|
|
33
|
-
})
|
|
41
|
+
/*#__PURE__*/ _jsx("div", {
|
|
42
|
+
id: "settings-message"
|
|
34
43
|
}),
|
|
35
|
-
/*#__PURE__*/ _jsxs("
|
|
36
|
-
class: "
|
|
44
|
+
/*#__PURE__*/ _jsxs("div", {
|
|
45
|
+
class: "card",
|
|
37
46
|
children: [
|
|
38
|
-
/*#__PURE__*/
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
children: t({
|
|
44
|
-
message: "Site Name",
|
|
45
|
-
comment: "@context: Settings form field"
|
|
46
|
-
})
|
|
47
|
-
}),
|
|
48
|
-
/*#__PURE__*/ _jsx("input", {
|
|
49
|
-
type: "text",
|
|
50
|
-
name: "siteName",
|
|
51
|
-
class: "input",
|
|
52
|
-
value: siteName,
|
|
53
|
-
required: true
|
|
47
|
+
/*#__PURE__*/ _jsx("header", {
|
|
48
|
+
children: /*#__PURE__*/ _jsx("h2", {
|
|
49
|
+
children: $__i18n._({
|
|
50
|
+
id: "Weq9zb",
|
|
51
|
+
message: "General"
|
|
54
52
|
})
|
|
55
|
-
|
|
53
|
+
})
|
|
56
54
|
}),
|
|
57
|
-
/*#__PURE__*/ _jsxs("
|
|
58
|
-
class: "
|
|
55
|
+
/*#__PURE__*/ _jsxs("section", {
|
|
56
|
+
class: "flex flex-col gap-4",
|
|
59
57
|
children: [
|
|
60
|
-
/*#__PURE__*/
|
|
61
|
-
class: "
|
|
62
|
-
children:
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
58
|
+
/*#__PURE__*/ _jsxs("div", {
|
|
59
|
+
class: "field",
|
|
60
|
+
children: [
|
|
61
|
+
/*#__PURE__*/ _jsx("label", {
|
|
62
|
+
class: "label",
|
|
63
|
+
children: $__i18n._({
|
|
64
|
+
id: "SJmfuf",
|
|
65
|
+
message: "Site Name"
|
|
66
|
+
})
|
|
67
|
+
}),
|
|
68
|
+
/*#__PURE__*/ _jsx("input", {
|
|
69
|
+
type: "text",
|
|
70
|
+
"data-bind": "siteName",
|
|
71
|
+
class: "input",
|
|
72
|
+
required: true
|
|
73
|
+
})
|
|
74
|
+
]
|
|
66
75
|
}),
|
|
67
|
-
/*#__PURE__*/
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
76
|
+
/*#__PURE__*/ _jsxs("div", {
|
|
77
|
+
class: "field",
|
|
78
|
+
children: [
|
|
79
|
+
/*#__PURE__*/ _jsx("label", {
|
|
80
|
+
class: "label",
|
|
81
|
+
children: $__i18n._({
|
|
82
|
+
id: "u2f7vd",
|
|
83
|
+
message: "Site Description"
|
|
84
|
+
})
|
|
85
|
+
}),
|
|
86
|
+
/*#__PURE__*/ _jsx("textarea", {
|
|
87
|
+
"data-bind": "siteDescription",
|
|
88
|
+
class: "textarea",
|
|
89
|
+
rows: 3,
|
|
90
|
+
children: siteDescription
|
|
91
|
+
})
|
|
92
|
+
]
|
|
93
|
+
}),
|
|
94
|
+
/*#__PURE__*/ _jsxs("div", {
|
|
95
|
+
class: "field",
|
|
96
|
+
children: [
|
|
97
|
+
/*#__PURE__*/ _jsx("label", {
|
|
98
|
+
class: "label",
|
|
99
|
+
children: $__i18n._({
|
|
100
|
+
id: "vXIe7J",
|
|
101
|
+
message: "Language"
|
|
102
|
+
})
|
|
103
|
+
}),
|
|
104
|
+
/*#__PURE__*/ _jsxs("select", {
|
|
105
|
+
"data-bind": "siteLanguage",
|
|
106
|
+
class: "select",
|
|
107
|
+
children: [
|
|
108
|
+
/*#__PURE__*/ _jsx("option", {
|
|
109
|
+
value: "en",
|
|
110
|
+
selected: siteLanguage === "en",
|
|
111
|
+
children: "English"
|
|
112
|
+
}),
|
|
113
|
+
/*#__PURE__*/ _jsx("option", {
|
|
114
|
+
value: "zh-Hans",
|
|
115
|
+
selected: siteLanguage === "zh-Hans",
|
|
116
|
+
children: "简体中文"
|
|
117
|
+
}),
|
|
118
|
+
/*#__PURE__*/ _jsx("option", {
|
|
119
|
+
value: "zh-Hant",
|
|
120
|
+
selected: siteLanguage === "zh-Hant",
|
|
121
|
+
children: "繁體中文"
|
|
122
|
+
})
|
|
123
|
+
]
|
|
124
|
+
})
|
|
125
|
+
]
|
|
72
126
|
})
|
|
73
127
|
]
|
|
128
|
+
})
|
|
129
|
+
]
|
|
130
|
+
}),
|
|
131
|
+
/*#__PURE__*/ _jsx("button", {
|
|
132
|
+
type: "submit",
|
|
133
|
+
class: "btn mt-4",
|
|
134
|
+
children: $__i18n._({
|
|
135
|
+
id: "UGT5vp",
|
|
136
|
+
message: "Save Settings"
|
|
137
|
+
})
|
|
138
|
+
})
|
|
139
|
+
]
|
|
140
|
+
}),
|
|
141
|
+
/*#__PURE__*/ _jsxs("form", {
|
|
142
|
+
"data-signals": "{currentPassword: '', newPassword: '', confirmPassword: ''}",
|
|
143
|
+
"data-on:submit__prevent": "@post('/dash/settings/password')",
|
|
144
|
+
children: [
|
|
145
|
+
/*#__PURE__*/ _jsx("div", {
|
|
146
|
+
id: "password-message"
|
|
147
|
+
}),
|
|
148
|
+
/*#__PURE__*/ _jsxs("div", {
|
|
149
|
+
class: "card",
|
|
150
|
+
children: [
|
|
151
|
+
/*#__PURE__*/ _jsx("header", {
|
|
152
|
+
children: /*#__PURE__*/ _jsx("h2", {
|
|
153
|
+
children: $__i18n._({
|
|
154
|
+
id: "VhMDMg",
|
|
155
|
+
message: "Change Password"
|
|
156
|
+
})
|
|
157
|
+
})
|
|
74
158
|
}),
|
|
75
|
-
/*#__PURE__*/ _jsxs("
|
|
76
|
-
class: "
|
|
159
|
+
/*#__PURE__*/ _jsxs("section", {
|
|
160
|
+
class: "flex flex-col gap-4",
|
|
77
161
|
children: [
|
|
78
|
-
/*#__PURE__*/
|
|
79
|
-
class: "
|
|
80
|
-
children:
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
162
|
+
/*#__PURE__*/ _jsxs("div", {
|
|
163
|
+
class: "field",
|
|
164
|
+
children: [
|
|
165
|
+
/*#__PURE__*/ _jsx("label", {
|
|
166
|
+
class: "label",
|
|
167
|
+
children: $__i18n._({
|
|
168
|
+
id: "DCKkhU",
|
|
169
|
+
message: "Current Password"
|
|
170
|
+
})
|
|
171
|
+
}),
|
|
172
|
+
/*#__PURE__*/ _jsx("input", {
|
|
173
|
+
type: "password",
|
|
174
|
+
"data-bind": "currentPassword",
|
|
175
|
+
class: "input",
|
|
176
|
+
required: true,
|
|
177
|
+
autocomplete: "current-password"
|
|
178
|
+
})
|
|
179
|
+
]
|
|
84
180
|
}),
|
|
85
|
-
/*#__PURE__*/ _jsxs("
|
|
86
|
-
|
|
87
|
-
class: "select",
|
|
181
|
+
/*#__PURE__*/ _jsxs("div", {
|
|
182
|
+
class: "field",
|
|
88
183
|
children: [
|
|
89
|
-
/*#__PURE__*/ _jsx("
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
184
|
+
/*#__PURE__*/ _jsx("label", {
|
|
185
|
+
class: "label",
|
|
186
|
+
children: $__i18n._({
|
|
187
|
+
id: "7vhWI8",
|
|
188
|
+
message: "New Password"
|
|
189
|
+
})
|
|
93
190
|
}),
|
|
94
|
-
/*#__PURE__*/ _jsx("
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
191
|
+
/*#__PURE__*/ _jsx("input", {
|
|
192
|
+
type: "password",
|
|
193
|
+
"data-bind": "newPassword",
|
|
194
|
+
class: "input",
|
|
195
|
+
required: true,
|
|
196
|
+
minlength: 8,
|
|
197
|
+
autocomplete: "new-password"
|
|
198
|
+
})
|
|
199
|
+
]
|
|
200
|
+
}),
|
|
201
|
+
/*#__PURE__*/ _jsxs("div", {
|
|
202
|
+
class: "field",
|
|
203
|
+
children: [
|
|
204
|
+
/*#__PURE__*/ _jsx("label", {
|
|
205
|
+
class: "label",
|
|
206
|
+
children: $__i18n._({
|
|
207
|
+
id: "yjkELF",
|
|
208
|
+
message: "Confirm New Password"
|
|
209
|
+
})
|
|
98
210
|
}),
|
|
99
|
-
/*#__PURE__*/ _jsx("
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
211
|
+
/*#__PURE__*/ _jsx("input", {
|
|
212
|
+
type: "password",
|
|
213
|
+
"data-bind": "confirmPassword",
|
|
214
|
+
class: "input",
|
|
215
|
+
required: true,
|
|
216
|
+
minlength: 8,
|
|
217
|
+
autocomplete: "new-password"
|
|
103
218
|
})
|
|
104
219
|
]
|
|
105
220
|
})
|
|
106
221
|
]
|
|
107
222
|
})
|
|
108
223
|
]
|
|
224
|
+
}),
|
|
225
|
+
/*#__PURE__*/ _jsx("button", {
|
|
226
|
+
type: "submit",
|
|
227
|
+
class: "btn mt-4",
|
|
228
|
+
children: $__i18n._({
|
|
229
|
+
id: "VhMDMg",
|
|
230
|
+
message: "Change Password"
|
|
231
|
+
})
|
|
109
232
|
})
|
|
110
233
|
]
|
|
111
|
-
}),
|
|
112
|
-
/*#__PURE__*/ _jsx("button", {
|
|
113
|
-
type: "submit",
|
|
114
|
-
class: "btn",
|
|
115
|
-
children: t({
|
|
116
|
-
message: "Save Settings",
|
|
117
|
-
comment: "@context: Button to save settings"
|
|
118
|
-
})
|
|
119
234
|
})
|
|
120
235
|
]
|
|
121
236
|
})
|
|
@@ -124,9 +239,11 @@ function SettingsContent({ siteName, siteDescription, siteLanguage }) {
|
|
|
124
239
|
}
|
|
125
240
|
// Settings page
|
|
126
241
|
settingsRoutes.get("/", async (c)=>{
|
|
127
|
-
const
|
|
128
|
-
const
|
|
129
|
-
const
|
|
242
|
+
const all = await c.var.services.settings.getAll();
|
|
243
|
+
const siteName = all["SITE_NAME"] ?? "Jant";
|
|
244
|
+
const siteDescription = all["SITE_DESCRIPTION"] ?? "";
|
|
245
|
+
const siteLanguage = all["SITE_LANGUAGE"] ?? "en";
|
|
246
|
+
const saved = c.req.query("saved") !== undefined;
|
|
130
247
|
return c.html(/*#__PURE__*/ _jsx(DashLayout, {
|
|
131
248
|
c: c,
|
|
132
249
|
title: "Settings",
|
|
@@ -135,20 +252,59 @@ settingsRoutes.get("/", async (c)=>{
|
|
|
135
252
|
children: /*#__PURE__*/ _jsx(SettingsContent, {
|
|
136
253
|
siteName: siteName,
|
|
137
254
|
siteDescription: siteDescription,
|
|
138
|
-
siteLanguage: siteLanguage
|
|
255
|
+
siteLanguage: siteLanguage,
|
|
256
|
+
saved: saved
|
|
139
257
|
})
|
|
140
258
|
}));
|
|
141
259
|
});
|
|
142
260
|
// Update settings
|
|
143
261
|
settingsRoutes.post("/", async (c)=>{
|
|
144
|
-
const
|
|
145
|
-
const
|
|
146
|
-
const siteDescription = formData.get("siteDescription");
|
|
147
|
-
const siteLanguage = formData.get("siteLanguage");
|
|
262
|
+
const body = await c.req.json();
|
|
263
|
+
const oldLanguage = await c.var.services.settings.get("SITE_LANGUAGE") ?? "en";
|
|
148
264
|
await c.var.services.settings.setMany({
|
|
149
|
-
SITE_NAME: siteName,
|
|
150
|
-
SITE_DESCRIPTION: siteDescription,
|
|
151
|
-
SITE_LANGUAGE: siteLanguage
|
|
265
|
+
SITE_NAME: body.siteName,
|
|
266
|
+
SITE_DESCRIPTION: body.siteDescription,
|
|
267
|
+
SITE_LANGUAGE: body.siteLanguage
|
|
268
|
+
});
|
|
269
|
+
const languageChanged = oldLanguage !== body.siteLanguage;
|
|
270
|
+
return sse(c, async (stream)=>{
|
|
271
|
+
if (languageChanged) {
|
|
272
|
+
// Language changed - full reload needed to update all UI text
|
|
273
|
+
await stream.redirect("/dash/settings?saved");
|
|
274
|
+
} else {
|
|
275
|
+
// No language change - show inline success message
|
|
276
|
+
await stream.patchElements('<div id="settings-message"><div class="rounded-md border border-green-200 bg-green-50 p-3 text-sm text-green-800 dark:border-green-800 dark:bg-green-950 dark:text-green-200 mb-4 transition-opacity duration-300" data-init="setTimeout(() => { el.style.opacity = \'0\'; setTimeout(() => el.remove(), 300) }, 3000)">Settings saved successfully.</div></div>');
|
|
277
|
+
}
|
|
278
|
+
});
|
|
279
|
+
});
|
|
280
|
+
// Change password
|
|
281
|
+
settingsRoutes.post("/password", async (c)=>{
|
|
282
|
+
const body = await c.req.json();
|
|
283
|
+
if (body.newPassword !== body.confirmPassword) {
|
|
284
|
+
return sse(c, async (stream)=>{
|
|
285
|
+
await stream.patchElements('<div id="password-message"><div class="rounded-md border border-red-200 bg-red-50 p-3 text-sm text-red-800 dark:border-red-800 dark:bg-red-950 dark:text-red-200 mb-4">Passwords do not match.</div></div>');
|
|
286
|
+
});
|
|
287
|
+
}
|
|
288
|
+
try {
|
|
289
|
+
await c.var.auth.api.changePassword({
|
|
290
|
+
body: {
|
|
291
|
+
currentPassword: body.currentPassword,
|
|
292
|
+
newPassword: body.newPassword,
|
|
293
|
+
revokeOtherSessions: false
|
|
294
|
+
},
|
|
295
|
+
headers: c.req.raw.headers
|
|
296
|
+
});
|
|
297
|
+
} catch {
|
|
298
|
+
return sse(c, async (stream)=>{
|
|
299
|
+
await stream.patchElements('<div id="password-message"><div class="rounded-md border border-red-200 bg-red-50 p-3 text-sm text-red-800 dark:border-red-800 dark:bg-red-950 dark:text-red-200 mb-4">Current password is incorrect.</div></div>');
|
|
300
|
+
});
|
|
301
|
+
}
|
|
302
|
+
return sse(c, async (stream)=>{
|
|
303
|
+
await stream.patchElements('<div id="password-message"><div class="rounded-md border border-green-200 bg-green-50 p-3 text-sm text-green-800 dark:border-green-800 dark:bg-green-950 dark:text-green-200 mb-4">Password changed successfully.</div></div>');
|
|
304
|
+
await stream.patchSignals({
|
|
305
|
+
currentPassword: "",
|
|
306
|
+
newPassword: "",
|
|
307
|
+
confirmPassword: ""
|
|
308
|
+
});
|
|
152
309
|
});
|
|
153
|
-
return c.redirect("/dash/settings?saved=1");
|
|
154
310
|
});
|
package/dist/routes/feed/rss.js
CHANGED
|
@@ -6,8 +6,9 @@ import * as time from "../../lib/time.js";
|
|
|
6
6
|
export const rssRoutes = new Hono();
|
|
7
7
|
// RSS 2.0 Feed - main feed at /feed
|
|
8
8
|
rssRoutes.get("/", async (c)=>{
|
|
9
|
-
const
|
|
10
|
-
const
|
|
9
|
+
const all = await c.var.services.settings.getAll();
|
|
10
|
+
const siteName = all["SITE_NAME"] ?? "Jant";
|
|
11
|
+
const siteDescription = all["SITE_DESCRIPTION"] ?? "";
|
|
11
12
|
const siteUrl = c.env.SITE_URL;
|
|
12
13
|
const posts = await c.var.services.posts.list({
|
|
13
14
|
visibility: [
|
|
@@ -48,8 +49,9 @@ rssRoutes.get("/", async (c)=>{
|
|
|
48
49
|
});
|
|
49
50
|
// Atom Feed
|
|
50
51
|
rssRoutes.get("/atom.xml", async (c)=>{
|
|
51
|
-
const
|
|
52
|
-
const
|
|
52
|
+
const all = await c.var.services.settings.getAll();
|
|
53
|
+
const siteName = all["SITE_NAME"] ?? "Jant";
|
|
54
|
+
const siteDescription = all["SITE_DESCRIPTION"] ?? "";
|
|
53
55
|
const siteUrl = c.env.SITE_URL;
|
|
54
56
|
const posts = await c.var.services.posts.list({
|
|
55
57
|
visibility: [
|
|
@@ -4,7 +4,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "hono/jsx/jsx-runtime";
|
|
|
4
4
|
*
|
|
5
5
|
* Shows all posts, optionally filtered by type
|
|
6
6
|
*/ import { Hono } from "hono";
|
|
7
|
-
import { useLingui } from "
|
|
7
|
+
import { useLingui as $_useLingui } from "@jant/core/i18n";
|
|
8
8
|
import { BaseLayout } from "../../theme/layouts/index.js";
|
|
9
9
|
import { Pagination } from "../../theme/components/index.js";
|
|
10
10
|
import { POST_TYPES } from "../../types.js";
|
|
@@ -13,61 +13,61 @@ import * as time from "../../lib/time.js";
|
|
|
13
13
|
const PAGE_SIZE = 50;
|
|
14
14
|
export const archiveRoutes = new Hono();
|
|
15
15
|
function getTypeLabel(type) {
|
|
16
|
-
const {
|
|
16
|
+
const { i18n: $__i18n, _: $__ } = $_useLingui();
|
|
17
17
|
const labels = {
|
|
18
|
-
note:
|
|
19
|
-
|
|
20
|
-
|
|
18
|
+
note: $__i18n._({
|
|
19
|
+
id: "KiJn9B",
|
|
20
|
+
message: "Note"
|
|
21
21
|
}),
|
|
22
|
-
article:
|
|
23
|
-
|
|
24
|
-
|
|
22
|
+
article: $__i18n._({
|
|
23
|
+
id: "f6e0Ry",
|
|
24
|
+
message: "Article"
|
|
25
25
|
}),
|
|
26
|
-
link:
|
|
27
|
-
|
|
28
|
-
|
|
26
|
+
link: $__i18n._({
|
|
27
|
+
id: "yzF66j",
|
|
28
|
+
message: "Link"
|
|
29
29
|
}),
|
|
30
|
-
quote:
|
|
31
|
-
|
|
32
|
-
|
|
30
|
+
quote: $__i18n._({
|
|
31
|
+
id: "ZhhOwV",
|
|
32
|
+
message: "Quote"
|
|
33
33
|
}),
|
|
34
|
-
image:
|
|
35
|
-
|
|
36
|
-
|
|
34
|
+
image: $__i18n._({
|
|
35
|
+
id: "hG89Ed",
|
|
36
|
+
message: "Image"
|
|
37
37
|
}),
|
|
38
|
-
page:
|
|
39
|
-
|
|
40
|
-
|
|
38
|
+
page: $__i18n._({
|
|
39
|
+
id: "6WdDG7",
|
|
40
|
+
message: "Page"
|
|
41
41
|
})
|
|
42
42
|
};
|
|
43
43
|
return labels[type] ?? type;
|
|
44
44
|
}
|
|
45
45
|
function getTypeLabelPlural(type) {
|
|
46
|
-
const {
|
|
46
|
+
const { i18n: $__i18n, _: $__ } = $_useLingui();
|
|
47
47
|
const labels = {
|
|
48
|
-
note:
|
|
49
|
-
|
|
50
|
-
|
|
48
|
+
note: $__i18n._({
|
|
49
|
+
id: "1DBGsz",
|
|
50
|
+
message: "Notes"
|
|
51
51
|
}),
|
|
52
|
-
article:
|
|
53
|
-
|
|
54
|
-
|
|
52
|
+
article: $__i18n._({
|
|
53
|
+
id: "Tt5T6+",
|
|
54
|
+
message: "Articles"
|
|
55
55
|
}),
|
|
56
|
-
link:
|
|
57
|
-
|
|
58
|
-
|
|
56
|
+
link: $__i18n._({
|
|
57
|
+
id: "Rj01Fz",
|
|
58
|
+
message: "Links"
|
|
59
59
|
}),
|
|
60
|
-
quote:
|
|
61
|
-
|
|
62
|
-
|
|
60
|
+
quote: $__i18n._({
|
|
61
|
+
id: "eWLklq",
|
|
62
|
+
message: "Quotes"
|
|
63
63
|
}),
|
|
64
|
-
image:
|
|
65
|
-
|
|
66
|
-
|
|
64
|
+
image: $__i18n._({
|
|
65
|
+
id: "an5hVd",
|
|
66
|
+
message: "Images"
|
|
67
67
|
}),
|
|
68
|
-
page:
|
|
69
|
-
|
|
70
|
-
|
|
68
|
+
page: $__i18n._({
|
|
69
|
+
id: "wRR604",
|
|
70
|
+
message: "Pages"
|
|
71
71
|
})
|
|
72
72
|
};
|
|
73
73
|
return labels[type] ?? `${type}s`;
|
|
@@ -82,10 +82,10 @@ function formatYearMonth(yearMonth) {
|
|
|
82
82
|
});
|
|
83
83
|
}
|
|
84
84
|
function ArchiveContent({ displayPosts, hasMore, nextCursor, type, grouped, replyCounts }) {
|
|
85
|
-
const {
|
|
86
|
-
const title = type ? getTypeLabelPlural(type) :
|
|
87
|
-
|
|
88
|
-
|
|
85
|
+
const { i18n: $__i18n, _: $__ } = $_useLingui();
|
|
86
|
+
const title = type ? getTypeLabelPlural(type) : $__i18n._({
|
|
87
|
+
id: "B495Gs",
|
|
88
|
+
message: "Archive"
|
|
89
89
|
});
|
|
90
90
|
return /*#__PURE__*/ _jsxs("div", {
|
|
91
91
|
class: "container py-8",
|
|
@@ -103,9 +103,9 @@ function ArchiveContent({ displayPosts, hasMore, nextCursor, type, grouped, repl
|
|
|
103
103
|
/*#__PURE__*/ _jsx("a", {
|
|
104
104
|
href: "/archive",
|
|
105
105
|
class: `badge ${!type ? "badge-primary" : "badge-outline"}`,
|
|
106
|
-
children:
|
|
107
|
-
|
|
108
|
-
|
|
106
|
+
children: $__i18n._({
|
|
107
|
+
id: "N40H+G",
|
|
108
|
+
message: "All"
|
|
109
109
|
})
|
|
110
110
|
}),
|
|
111
111
|
POST_TYPES.filter((t)=>t !== "page").map((typeKey)=>/*#__PURE__*/ _jsx("a", {
|
|
@@ -120,9 +120,9 @@ function ArchiveContent({ displayPosts, hasMore, nextCursor, type, grouped, repl
|
|
|
120
120
|
/*#__PURE__*/ _jsx("main", {
|
|
121
121
|
children: displayPosts.length === 0 ? /*#__PURE__*/ _jsx("p", {
|
|
122
122
|
class: "text-muted-foreground",
|
|
123
|
-
children:
|
|
124
|
-
|
|
125
|
-
|
|
123
|
+
children: $__i18n._({
|
|
124
|
+
id: "Hzi9AA",
|
|
125
|
+
message: "No posts found."
|
|
126
126
|
})
|
|
127
127
|
}) : Array.from(grouped.entries()).map(([yearMonth, monthPosts])=>/*#__PURE__*/ _jsxs("section", {
|
|
128
128
|
class: "mb-8",
|
|
@@ -159,15 +159,12 @@ function ArchiveContent({ displayPosts, hasMore, nextCursor, type, grouped, repl
|
|
|
159
159
|
class: "ml-2 text-xs text-muted-foreground",
|
|
160
160
|
children: [
|
|
161
161
|
"(",
|
|
162
|
-
replyCount === 1 ?
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
}) :
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
values: {
|
|
169
|
-
count: String(replyCount)
|
|
170
|
-
}
|
|
162
|
+
replyCount === 1 ? $__i18n._({
|
|
163
|
+
id: "TxE+Mj",
|
|
164
|
+
message: "1 reply"
|
|
165
|
+
}) : $__i18n._({
|
|
166
|
+
id: "90Luob",
|
|
167
|
+
message: "{count} replies"
|
|
171
168
|
}),
|
|
172
169
|
")"
|
|
173
170
|
]
|
|
@@ -192,10 +189,11 @@ function ArchiveContent({ displayPosts, hasMore, nextCursor, type, grouped, repl
|
|
|
192
189
|
href: "/",
|
|
193
190
|
class: "text-sm hover:underline",
|
|
194
191
|
children: [
|
|
195
|
-
"←
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
192
|
+
"←",
|
|
193
|
+
" ",
|
|
194
|
+
$__i18n._({
|
|
195
|
+
id: "x4RuFo",
|
|
196
|
+
message: "Back to home"
|
|
199
197
|
})
|
|
200
198
|
]
|
|
201
199
|
})
|