@ampless/admin 1.0.0-alpha.85 → 1.0.0-beta.100
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/README.ja.md +2 -2
- package/README.md +2 -2
- package/dist/api/index.d.ts +1 -1
- package/dist/api/index.js +4 -2
- package/dist/{chunk-SQ6LFPXH.js → chunk-2TBGPB5H.js} +2 -2
- package/dist/{chunk-K44QF3MV.js → chunk-4OFRX6QX.js} +1 -1
- package/dist/{chunk-HANIMWMN.js → chunk-4WYMEUYU.js} +301 -222
- package/dist/chunk-7HSWOQWV.js +172 -0
- package/dist/{chunk-J6R356H3.js → chunk-7OZ23MLD.js} +1 -1
- package/dist/{chunk-OFPNBZKP.js → chunk-7W7LAQXY.js} +76 -8
- package/dist/{chunk-HN3UFHP7.js → chunk-ANME5KDN.js} +1 -1
- package/dist/{chunk-GGHN2RKQ.js → chunk-E5VF3Y65.js} +69 -3
- package/dist/{chunk-7LT6YPIT.js → chunk-JLCTF5HY.js} +8 -2
- package/dist/{chunk-R3TEJ32M.js → chunk-LXY3BRKQ.js} +2 -2
- package/dist/{chunk-MKWYNK4J.js → chunk-NHMG2MRJ.js} +2 -2
- package/dist/{chunk-AYESATAM.js → chunk-OPVLQOOB.js} +44 -13
- package/dist/{chunk-SMI7Y77B.js → chunk-ORXOMW7M.js} +265 -190
- package/dist/{chunk-W4VHP2JW.js → chunk-SYAEM5DM.js} +1 -1
- package/dist/{chunk-7NQERXNY.js → chunk-TJZ4FTU6.js} +1 -1
- package/dist/{chunk-CFIOUXVE.js → chunk-V5XORHKX.js} +1 -1
- package/dist/chunk-ZDIDJCSU.js +40 -0
- package/dist/components/account-view.d.ts +8 -0
- package/dist/components/account-view.js +10 -0
- package/dist/components/admin-dashboard.js +3 -3
- package/dist/components/edit-post-view.js +5 -5
- package/dist/components/index.d.ts +4 -2
- package/dist/components/index.js +7 -7
- package/dist/components/login-view.d.ts +3 -1
- package/dist/components/login-view.js +4 -3
- package/dist/components/mcp-tokens-view.js +3 -3
- package/dist/components/media-view.js +5 -5
- package/dist/components/new-post-view.js +5 -5
- package/dist/components/plugin-settings-form.d.ts +2 -10
- package/dist/components/plugin-settings-form.js +5 -7
- package/dist/components/posts-list-view.js +3 -3
- package/dist/components/users-list-view.js +3 -3
- package/dist/{i18n-DA-aakRX.d.ts → i18n-Bd8q9aTl.d.ts} +108 -5
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/metafile-esm.json +1 -1
- package/dist/pages/index.d.ts +21 -4
- package/dist/pages/index.js +54 -24
- package/package.json +5 -6
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import {
|
|
3
|
+
isWebAuthnSupported
|
|
4
|
+
} from "./chunk-ZDIDJCSU.js";
|
|
5
|
+
import {
|
|
6
|
+
useT
|
|
7
|
+
} from "./chunk-4OFRX6QX.js";
|
|
8
|
+
|
|
9
|
+
// src/components/account-view.tsx
|
|
10
|
+
import { useEffect, useState } from "react";
|
|
11
|
+
import {
|
|
12
|
+
Button,
|
|
13
|
+
Table,
|
|
14
|
+
TableBody,
|
|
15
|
+
TableCell,
|
|
16
|
+
TableHead,
|
|
17
|
+
TableHeader,
|
|
18
|
+
TableRow
|
|
19
|
+
} from "@ampless/runtime/ui";
|
|
20
|
+
|
|
21
|
+
// src/lib/passkey-store.ts
|
|
22
|
+
import {
|
|
23
|
+
associateWebAuthnCredential,
|
|
24
|
+
listWebAuthnCredentials,
|
|
25
|
+
deleteWebAuthnCredential
|
|
26
|
+
} from "aws-amplify/auth";
|
|
27
|
+
var defaultPasskeyApi = {
|
|
28
|
+
async register() {
|
|
29
|
+
await associateWebAuthnCredential();
|
|
30
|
+
},
|
|
31
|
+
async list() {
|
|
32
|
+
const credentials = [];
|
|
33
|
+
let nextToken;
|
|
34
|
+
do {
|
|
35
|
+
const page = await listWebAuthnCredentials(nextToken ? { nextToken } : void 0);
|
|
36
|
+
for (const cred of page.credentials) {
|
|
37
|
+
if (!cred.credentialId) continue;
|
|
38
|
+
credentials.push({
|
|
39
|
+
credentialId: cred.credentialId,
|
|
40
|
+
friendlyName: cred.friendlyCredentialName,
|
|
41
|
+
createdAt: cred.createdAt ? cred.createdAt.toISOString() : null
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
nextToken = page.nextToken;
|
|
45
|
+
} while (nextToken);
|
|
46
|
+
credentials.sort((a, b) => {
|
|
47
|
+
if (!a.createdAt) return 1;
|
|
48
|
+
if (!b.createdAt) return -1;
|
|
49
|
+
return b.createdAt.localeCompare(a.createdAt);
|
|
50
|
+
});
|
|
51
|
+
return credentials;
|
|
52
|
+
},
|
|
53
|
+
async remove(credentialId) {
|
|
54
|
+
await deleteWebAuthnCredential({ credentialId });
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
var api = defaultPasskeyApi;
|
|
58
|
+
function getPasskeyApi() {
|
|
59
|
+
return api;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// src/components/account-view.tsx
|
|
63
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
64
|
+
function formatDate(iso) {
|
|
65
|
+
if (!iso) return "";
|
|
66
|
+
const d = new Date(iso);
|
|
67
|
+
if (Number.isNaN(d.getTime())) return "";
|
|
68
|
+
return d.toLocaleString();
|
|
69
|
+
}
|
|
70
|
+
function AccountView({ currentUserEmail, passkeysEnabled }) {
|
|
71
|
+
const t = useT();
|
|
72
|
+
const [supported, setSupported] = useState(false);
|
|
73
|
+
const [supportResolved, setSupportResolved] = useState(false);
|
|
74
|
+
const [passkeys, setPasskeys] = useState(null);
|
|
75
|
+
const [loading, setLoading] = useState(true);
|
|
76
|
+
const [loadError, setLoadError] = useState(null);
|
|
77
|
+
const [adding, setAdding] = useState(false);
|
|
78
|
+
const [addError, setAddError] = useState(null);
|
|
79
|
+
async function loadPasskeys() {
|
|
80
|
+
setLoading(true);
|
|
81
|
+
setLoadError(null);
|
|
82
|
+
try {
|
|
83
|
+
const list = await getPasskeyApi().list();
|
|
84
|
+
setPasskeys(list);
|
|
85
|
+
} catch (err) {
|
|
86
|
+
console.error("[account-view] list passkeys failed", err);
|
|
87
|
+
setLoadError(err instanceof Error ? err.message : String(err));
|
|
88
|
+
} finally {
|
|
89
|
+
setLoading(false);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
useEffect(() => {
|
|
93
|
+
if (!passkeysEnabled) {
|
|
94
|
+
setSupportResolved(true);
|
|
95
|
+
setLoading(false);
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
const ok = isWebAuthnSupported();
|
|
99
|
+
setSupported(ok);
|
|
100
|
+
setSupportResolved(true);
|
|
101
|
+
if (ok) void loadPasskeys();
|
|
102
|
+
else setLoading(false);
|
|
103
|
+
}, [passkeysEnabled]);
|
|
104
|
+
async function handleAdd() {
|
|
105
|
+
setAdding(true);
|
|
106
|
+
setAddError(null);
|
|
107
|
+
try {
|
|
108
|
+
await getPasskeyApi().register();
|
|
109
|
+
await loadPasskeys();
|
|
110
|
+
} catch (err) {
|
|
111
|
+
console.error("[account-view] register passkey failed", err);
|
|
112
|
+
setAddError(err instanceof Error ? err.message : String(err));
|
|
113
|
+
} finally {
|
|
114
|
+
setAdding(false);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
async function handleRemove(credentialId) {
|
|
118
|
+
if (!confirm(t("account.passkeys.deleteConfirm"))) return;
|
|
119
|
+
try {
|
|
120
|
+
await getPasskeyApi().remove(credentialId);
|
|
121
|
+
await loadPasskeys();
|
|
122
|
+
} catch (err) {
|
|
123
|
+
console.error("[account-view] remove passkey failed", err);
|
|
124
|
+
alert(err instanceof Error ? err.message : String(err));
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
return /* @__PURE__ */ jsxs("div", { className: "mx-auto max-w-4xl space-y-8 p-4 md:p-8", children: [
|
|
128
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
129
|
+
/* @__PURE__ */ jsx("h1", { className: "text-2xl font-bold md:text-3xl", children: t("account.title") }),
|
|
130
|
+
/* @__PURE__ */ jsx("p", { className: "mt-1 text-sm text-muted-foreground", children: currentUserEmail })
|
|
131
|
+
] }),
|
|
132
|
+
/* @__PURE__ */ jsxs("section", { className: "space-y-4 rounded-md border bg-card p-4 md:p-6", children: [
|
|
133
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-4", children: [
|
|
134
|
+
/* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx("h2", { className: "text-lg font-semibold", children: t("account.passkeys.title") }) }),
|
|
135
|
+
passkeysEnabled && supportResolved && supported && /* @__PURE__ */ jsx(Button, { type: "button", disabled: adding, onClick: () => void handleAdd(), children: adding ? t("account.passkeys.adding") : t("account.passkeys.add") })
|
|
136
|
+
] }),
|
|
137
|
+
addError && /* @__PURE__ */ jsx("p", { className: "text-sm text-destructive", children: addError }),
|
|
138
|
+
!passkeysEnabled ? /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: t("account.passkeys.disabled") }) : supportResolved && !supported ? /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: t("account.passkeys.unsupported") }) : loading ? /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: t("account.passkeys.loading") }) : loadError ? /* @__PURE__ */ jsxs("p", { className: "text-sm text-destructive", children: [
|
|
139
|
+
t("account.passkeys.loadError"),
|
|
140
|
+
": ",
|
|
141
|
+
loadError
|
|
142
|
+
] }) : !passkeys || passkeys.length === 0 ? /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: t("account.passkeys.empty") }) : /* @__PURE__ */ jsx("div", { className: "overflow-x-auto rounded-md border", children: /* @__PURE__ */ jsxs(Table, { children: [
|
|
143
|
+
/* @__PURE__ */ jsx(TableHeader, { children: /* @__PURE__ */ jsxs(TableRow, { children: [
|
|
144
|
+
/* @__PURE__ */ jsx(TableHead, { children: t("account.passkeys.columnName") }),
|
|
145
|
+
/* @__PURE__ */ jsx(TableHead, { children: t("account.passkeys.columnCreated") }),
|
|
146
|
+
/* @__PURE__ */ jsx(TableHead, { className: "w-[1%] whitespace-nowrap", children: t("common.actions") })
|
|
147
|
+
] }) }),
|
|
148
|
+
/* @__PURE__ */ jsx(TableBody, { children: passkeys.map((pk) => /* @__PURE__ */ jsxs(TableRow, { children: [
|
|
149
|
+
/* @__PURE__ */ jsx(TableCell, { className: "font-medium", children: pk.friendlyName || /* @__PURE__ */ jsxs("span", { className: "font-mono text-xs text-muted-foreground", children: [
|
|
150
|
+
pk.credentialId.slice(0, 12),
|
|
151
|
+
"\u2026"
|
|
152
|
+
] }) }),
|
|
153
|
+
/* @__PURE__ */ jsx(TableCell, { className: "text-xs text-muted-foreground", children: pk.createdAt ? /* @__PURE__ */ jsx("span", { title: pk.createdAt, children: formatDate(pk.createdAt) }) : "" }),
|
|
154
|
+
/* @__PURE__ */ jsx(TableCell, { children: /* @__PURE__ */ jsx(
|
|
155
|
+
Button,
|
|
156
|
+
{
|
|
157
|
+
type: "button",
|
|
158
|
+
variant: "outline",
|
|
159
|
+
size: "sm",
|
|
160
|
+
onClick: () => void handleRemove(pk.credentialId),
|
|
161
|
+
children: t("account.passkeys.delete")
|
|
162
|
+
}
|
|
163
|
+
) })
|
|
164
|
+
] }, pk.credentialId)) })
|
|
165
|
+
] }) })
|
|
166
|
+
] })
|
|
167
|
+
] });
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
export {
|
|
171
|
+
AccountView
|
|
172
|
+
};
|
|
@@ -8,6 +8,7 @@ var en_default = {
|
|
|
8
8
|
edit: "Edit",
|
|
9
9
|
back: "Back",
|
|
10
10
|
loading: "Loading...",
|
|
11
|
+
loadError: "Failed to load.",
|
|
11
12
|
default: "Default",
|
|
12
13
|
remove: "Remove",
|
|
13
14
|
create: "Create",
|
|
@@ -41,7 +42,8 @@ var en_default = {
|
|
|
41
42
|
signOut: "Sign out",
|
|
42
43
|
site: "Site",
|
|
43
44
|
openMenu: "Open menu",
|
|
44
|
-
closeMenu: "Close menu"
|
|
45
|
+
closeMenu: "Close menu",
|
|
46
|
+
account: "Account"
|
|
45
47
|
},
|
|
46
48
|
dashboard: {
|
|
47
49
|
title: "Dashboard",
|
|
@@ -88,7 +90,7 @@ var en_default = {
|
|
|
88
90
|
excerpt: "Excerpt",
|
|
89
91
|
body: "Body",
|
|
90
92
|
format: "Format",
|
|
91
|
-
formatHint: "Tiptap is the rich editor. Markdown / HTML use a plain textarea.
|
|
93
|
+
formatHint: "Tiptap is the rich editor. Markdown / HTML use a plain textarea.",
|
|
92
94
|
insertMedia: "Insert media",
|
|
93
95
|
tabEdit: "Edit",
|
|
94
96
|
tabPreview: "Preview",
|
|
@@ -277,6 +279,10 @@ var en_default = {
|
|
|
277
279
|
deleteColumn: "Delete column",
|
|
278
280
|
toggleHeaderRow: "Toggle header row",
|
|
279
281
|
deleteTable: "Delete table"
|
|
282
|
+
},
|
|
283
|
+
codeBlock: {
|
|
284
|
+
languageLabel: "Language",
|
|
285
|
+
languagePlaceholder: "e.g. mermaid, ts"
|
|
280
286
|
}
|
|
281
287
|
},
|
|
282
288
|
auth: {
|
|
@@ -293,7 +299,8 @@ var en_default = {
|
|
|
293
299
|
description: "Sign in to manage your site.",
|
|
294
300
|
submit: "Sign in",
|
|
295
301
|
forgotPassword: "Forgot password?",
|
|
296
|
-
createAccount: "Create admin account"
|
|
302
|
+
createAccount: "Create admin account",
|
|
303
|
+
passkeyButton: "Sign in with passkey"
|
|
297
304
|
},
|
|
298
305
|
signUp: {
|
|
299
306
|
title: "Create admin account",
|
|
@@ -324,6 +331,14 @@ var en_default = {
|
|
|
324
331
|
invalidCredentials: "Invalid email or password.",
|
|
325
332
|
passwordTooShort: "Password must be at least 8 characters.",
|
|
326
333
|
userExists: "An account with this email already exists."
|
|
334
|
+
},
|
|
335
|
+
passkey: {
|
|
336
|
+
emailRequired: "Enter your email first, then sign in with your passkey.",
|
|
337
|
+
noneRegistered: "No passkey is registered for this account yet. Sign in with your password, then add one from the account page.",
|
|
338
|
+
cancelled: "Passkey sign-in was cancelled.",
|
|
339
|
+
unsupported: "This browser does not support passkeys.",
|
|
340
|
+
rpMismatch: "This site isn't configured for passkeys on this domain. Ask the site engineer to set the relyingPartyId in amplify/auth/resource.custom.ts.",
|
|
341
|
+
failed: "Passkey sign-in failed. Try again, or sign in with your password."
|
|
327
342
|
}
|
|
328
343
|
},
|
|
329
344
|
plugins: {
|
|
@@ -337,7 +352,8 @@ var en_default = {
|
|
|
337
352
|
saveError: "Save failed",
|
|
338
353
|
invalidValue: "One or more values are invalid \u2014 fix highlighted fields and try again.",
|
|
339
354
|
resetToDefault: "Reset to default",
|
|
340
|
-
resetDone: "Stored value cleared. Falling back to the manifest default."
|
|
355
|
+
resetDone: "Stored value cleared. Falling back to the manifest default.",
|
|
356
|
+
noChanges: "No changes to save."
|
|
341
357
|
},
|
|
342
358
|
mcpTokens: {
|
|
343
359
|
title: "MCP tokens",
|
|
@@ -384,6 +400,24 @@ var en_default = {
|
|
|
384
400
|
tagLabel: "Tag",
|
|
385
401
|
permalink: "Permalink",
|
|
386
402
|
shareOnX: "Share on X"
|
|
403
|
+
},
|
|
404
|
+
account: {
|
|
405
|
+
title: "Account",
|
|
406
|
+
passkeys: {
|
|
407
|
+
title: "Passkeys",
|
|
408
|
+
add: "Add passkey",
|
|
409
|
+
adding: "Adding...",
|
|
410
|
+
added: "Passkey added.",
|
|
411
|
+
loading: "Loading passkeys...",
|
|
412
|
+
empty: "No passkeys yet. Add one to sign in with Face ID, Touch ID, or your security key.",
|
|
413
|
+
columnName: "Name",
|
|
414
|
+
columnCreated: "Created",
|
|
415
|
+
delete: "Delete",
|
|
416
|
+
deleteConfirm: "Delete this passkey? You will no longer be able to sign in with it.",
|
|
417
|
+
loadError: "Failed to load passkeys",
|
|
418
|
+
unsupported: "This browser does not support passkeys.",
|
|
419
|
+
disabled: "Passkeys are disabled for this site."
|
|
420
|
+
}
|
|
387
421
|
}
|
|
388
422
|
};
|
|
389
423
|
|
|
@@ -397,6 +431,7 @@ var ja_default = {
|
|
|
397
431
|
edit: "\u7DE8\u96C6",
|
|
398
432
|
back: "\u623B\u308B",
|
|
399
433
|
loading: "\u8AAD\u307F\u8FBC\u307F\u4E2D...",
|
|
434
|
+
loadError: "\u8AAD\u307F\u8FBC\u307F\u306B\u5931\u6557\u3057\u307E\u3057\u305F\u3002",
|
|
400
435
|
default: "\u30C7\u30D5\u30A9\u30EB\u30C8",
|
|
401
436
|
remove: "\u524A\u9664",
|
|
402
437
|
create: "\u4F5C\u6210",
|
|
@@ -430,7 +465,8 @@ var ja_default = {
|
|
|
430
465
|
signOut: "\u30B5\u30A4\u30F3\u30A2\u30A6\u30C8",
|
|
431
466
|
site: "\u30B5\u30A4\u30C8",
|
|
432
467
|
openMenu: "\u30E1\u30CB\u30E5\u30FC\u3092\u958B\u304F",
|
|
433
|
-
closeMenu: "\u30E1\u30CB\u30E5\u30FC\u3092\u9589\u3058\u308B"
|
|
468
|
+
closeMenu: "\u30E1\u30CB\u30E5\u30FC\u3092\u9589\u3058\u308B",
|
|
469
|
+
account: "\u30A2\u30AB\u30A6\u30F3\u30C8"
|
|
434
470
|
},
|
|
435
471
|
dashboard: {
|
|
436
472
|
title: "\u30C0\u30C3\u30B7\u30E5\u30DC\u30FC\u30C9",
|
|
@@ -477,7 +513,7 @@ var ja_default = {
|
|
|
477
513
|
excerpt: "\u629C\u7C8B",
|
|
478
514
|
body: "\u672C\u6587",
|
|
479
515
|
format: "\u30D5\u30A9\u30FC\u30DE\u30C3\u30C8",
|
|
480
|
-
formatHint: "Tiptap \u306F\u30EA\u30C3\u30C1\u30A8\u30C7\u30A3\u30BF\u3002Markdown / HTML \u306F\u30D7\u30EC\u30FC\u30F3\u30C6\u30AD\u30B9\u30C8\u30A8\u30EA\u30A2\u3002
|
|
516
|
+
formatHint: "Tiptap \u306F\u30EA\u30C3\u30C1\u30A8\u30C7\u30A3\u30BF\u3002Markdown / HTML \u306F\u30D7\u30EC\u30FC\u30F3\u30C6\u30AD\u30B9\u30C8\u30A8\u30EA\u30A2\u3002",
|
|
481
517
|
insertMedia: "\u30E1\u30C7\u30A3\u30A2\u3092\u633F\u5165",
|
|
482
518
|
tabEdit: "\u7DE8\u96C6",
|
|
483
519
|
tabPreview: "\u30D7\u30EC\u30D3\u30E5\u30FC",
|
|
@@ -666,6 +702,10 @@ var ja_default = {
|
|
|
666
702
|
deleteColumn: "\u5217\u3092\u524A\u9664",
|
|
667
703
|
toggleHeaderRow: "\u30D8\u30C3\u30C0\u30FC\u884C\u3092\u5207\u66FF",
|
|
668
704
|
deleteTable: "\u30C6\u30FC\u30D6\u30EB\u3092\u524A\u9664"
|
|
705
|
+
},
|
|
706
|
+
codeBlock: {
|
|
707
|
+
languageLabel: "\u8A00\u8A9E",
|
|
708
|
+
languagePlaceholder: "\u4F8B: mermaid, ts"
|
|
669
709
|
}
|
|
670
710
|
},
|
|
671
711
|
auth: {
|
|
@@ -682,7 +722,8 @@ var ja_default = {
|
|
|
682
722
|
description: "\u30B5\u30A4\u30F3\u30A4\u30F3\u3057\u3066\u30B5\u30A4\u30C8\u3092\u7BA1\u7406\u3057\u307E\u3059\u3002",
|
|
683
723
|
submit: "\u30B5\u30A4\u30F3\u30A4\u30F3",
|
|
684
724
|
forgotPassword: "\u30D1\u30B9\u30EF\u30FC\u30C9\u3092\u304A\u5FD8\u308C\u3067\u3059\u304B?",
|
|
685
|
-
createAccount: "\u7BA1\u7406\u8005\u30A2\u30AB\u30A6\u30F3\u30C8\u3092\u4F5C\u6210"
|
|
725
|
+
createAccount: "\u7BA1\u7406\u8005\u30A2\u30AB\u30A6\u30F3\u30C8\u3092\u4F5C\u6210",
|
|
726
|
+
passkeyButton: "\u30D1\u30B9\u30AD\u30FC\u3067\u30B5\u30A4\u30F3\u30A4\u30F3"
|
|
686
727
|
},
|
|
687
728
|
signUp: {
|
|
688
729
|
title: "\u7BA1\u7406\u8005\u30A2\u30AB\u30A6\u30F3\u30C8\u306E\u4F5C\u6210",
|
|
@@ -713,6 +754,14 @@ var ja_default = {
|
|
|
713
754
|
invalidCredentials: "\u30E1\u30FC\u30EB\u30A2\u30C9\u30EC\u30B9\u307E\u305F\u306F\u30D1\u30B9\u30EF\u30FC\u30C9\u304C\u6B63\u3057\u304F\u3042\u308A\u307E\u305B\u3093\u3002",
|
|
714
755
|
passwordTooShort: "\u30D1\u30B9\u30EF\u30FC\u30C9\u306F8\u6587\u5B57\u4EE5\u4E0A\u5FC5\u8981\u3067\u3059\u3002",
|
|
715
756
|
userExists: "\u3053\u306E\u30E1\u30FC\u30EB\u30A2\u30C9\u30EC\u30B9\u306E\u30A2\u30AB\u30A6\u30F3\u30C8\u306F\u65E2\u306B\u5B58\u5728\u3057\u307E\u3059\u3002"
|
|
757
|
+
},
|
|
758
|
+
passkey: {
|
|
759
|
+
emailRequired: "\u30E1\u30FC\u30EB\u30A2\u30C9\u30EC\u30B9\u3092\u5165\u529B\u3057\u3066\u304B\u3089\u3001\u30D1\u30B9\u30AD\u30FC\u3067\u30B5\u30A4\u30F3\u30A4\u30F3\u3057\u3066\u304F\u3060\u3055\u3044\u3002",
|
|
760
|
+
noneRegistered: "\u3053\u306E\u30A2\u30AB\u30A6\u30F3\u30C8\u306B\u306F\u307E\u3060\u30D1\u30B9\u30AD\u30FC\u304C\u767B\u9332\u3055\u308C\u3066\u3044\u307E\u305B\u3093\u3002\u30D1\u30B9\u30EF\u30FC\u30C9\u3067\u30B5\u30A4\u30F3\u30A4\u30F3\u3057\u3001\u30A2\u30AB\u30A6\u30F3\u30C8\u30DA\u30FC\u30B8\u304B\u3089\u767B\u9332\u3057\u3066\u304F\u3060\u3055\u3044\u3002",
|
|
761
|
+
cancelled: "\u30D1\u30B9\u30AD\u30FC\u306E\u30B5\u30A4\u30F3\u30A4\u30F3\u304C\u30AD\u30E3\u30F3\u30BB\u30EB\u3055\u308C\u307E\u3057\u305F\u3002",
|
|
762
|
+
unsupported: "\u3053\u306E\u30D6\u30E9\u30A6\u30B6\u306F\u30D1\u30B9\u30AD\u30FC\u306B\u5BFE\u5FDC\u3057\u3066\u3044\u307E\u305B\u3093\u3002",
|
|
763
|
+
rpMismatch: "\u3053\u306E\u30C9\u30E1\u30A4\u30F3\u3067\u306F\u30D1\u30B9\u30AD\u30FC\u304C\u8A2D\u5B9A\u3055\u308C\u3066\u3044\u307E\u305B\u3093\u3002\u30B5\u30A4\u30C8\u30A8\u30F3\u30B8\u30CB\u30A2\u306B amplify/auth/resource.custom.ts \u306E relyingPartyId \u8A2D\u5B9A\u3092\u4F9D\u983C\u3057\u3066\u304F\u3060\u3055\u3044\u3002",
|
|
764
|
+
failed: "\u30D1\u30B9\u30AD\u30FC\u306E\u30B5\u30A4\u30F3\u30A4\u30F3\u306B\u5931\u6557\u3057\u307E\u3057\u305F\u3002\u3082\u3046\u4E00\u5EA6\u8A66\u3059\u304B\u3001\u30D1\u30B9\u30EF\u30FC\u30C9\u3067\u30B5\u30A4\u30F3\u30A4\u30F3\u3057\u3066\u304F\u3060\u3055\u3044\u3002"
|
|
716
765
|
}
|
|
717
766
|
},
|
|
718
767
|
plugins: {
|
|
@@ -726,7 +775,8 @@ var ja_default = {
|
|
|
726
775
|
saveError: "\u4FDD\u5B58\u306B\u5931\u6557\u3057\u307E\u3057\u305F",
|
|
727
776
|
invalidValue: "\u4E0D\u6B63\u306A\u5024\u304C\u542B\u307E\u308C\u3066\u3044\u307E\u3059 \u2014 \u30CF\u30A4\u30E9\u30A4\u30C8\u3055\u308C\u305F\u9805\u76EE\u3092\u4FEE\u6B63\u3057\u3066\u304F\u3060\u3055\u3044\u3002",
|
|
728
777
|
resetToDefault: "\u30C7\u30D5\u30A9\u30EB\u30C8\u306B\u623B\u3059",
|
|
729
|
-
resetDone: "\u4FDD\u5B58\u5024\u3092\u30AF\u30EA\u30A2\u3057\u307E\u3057\u305F\u3002\u30DE\u30CB\u30D5\u30A7\u30B9\u30C8\u306E\u30C7\u30D5\u30A9\u30EB\u30C8\u5024\u304C\u4F7F\u7528\u3055\u308C\u307E\u3059\u3002"
|
|
778
|
+
resetDone: "\u4FDD\u5B58\u5024\u3092\u30AF\u30EA\u30A2\u3057\u307E\u3057\u305F\u3002\u30DE\u30CB\u30D5\u30A7\u30B9\u30C8\u306E\u30C7\u30D5\u30A9\u30EB\u30C8\u5024\u304C\u4F7F\u7528\u3055\u308C\u307E\u3059\u3002",
|
|
779
|
+
noChanges: "\u5909\u66F4\u306F\u3042\u308A\u307E\u305B\u3093\u3002"
|
|
730
780
|
},
|
|
731
781
|
mcpTokens: {
|
|
732
782
|
title: "MCP \u30C8\u30FC\u30AF\u30F3",
|
|
@@ -773,6 +823,24 @@ var ja_default = {
|
|
|
773
823
|
tagLabel: "\u30BF\u30B0",
|
|
774
824
|
permalink: "\u30D1\u30FC\u30DE\u30EA\u30F3\u30AF",
|
|
775
825
|
shareOnX: "X\u3067\u5171\u6709"
|
|
826
|
+
},
|
|
827
|
+
account: {
|
|
828
|
+
title: "\u30A2\u30AB\u30A6\u30F3\u30C8",
|
|
829
|
+
passkeys: {
|
|
830
|
+
title: "\u30D1\u30B9\u30AD\u30FC",
|
|
831
|
+
add: "\u30D1\u30B9\u30AD\u30FC\u3092\u8FFD\u52A0",
|
|
832
|
+
adding: "\u8FFD\u52A0\u4E2D...",
|
|
833
|
+
added: "\u30D1\u30B9\u30AD\u30FC\u3092\u8FFD\u52A0\u3057\u307E\u3057\u305F\u3002",
|
|
834
|
+
loading: "\u30D1\u30B9\u30AD\u30FC\u3092\u8AAD\u307F\u8FBC\u307F\u4E2D...",
|
|
835
|
+
empty: "\u30D1\u30B9\u30AD\u30FC\u306F\u307E\u3060\u3042\u308A\u307E\u305B\u3093\u3002\u8FFD\u52A0\u3059\u308B\u3068 Face ID\u30FBTouch ID\u30FB\u30BB\u30AD\u30E5\u30EA\u30C6\u30A3\u30AD\u30FC\u3067\u30B5\u30A4\u30F3\u30A4\u30F3\u3067\u304D\u307E\u3059\u3002",
|
|
836
|
+
columnName: "\u540D\u524D",
|
|
837
|
+
columnCreated: "\u4F5C\u6210\u65E5",
|
|
838
|
+
delete: "\u524A\u9664",
|
|
839
|
+
deleteConfirm: "\u3053\u306E\u30D1\u30B9\u30AD\u30FC\u3092\u524A\u9664\u3057\u307E\u3059\u304B? \u3053\u306E\u30D1\u30B9\u30AD\u30FC\u3067\u306F\u30B5\u30A4\u30F3\u30A4\u30F3\u3067\u304D\u306A\u304F\u306A\u308A\u307E\u3059\u3002",
|
|
840
|
+
loadError: "\u30D1\u30B9\u30AD\u30FC\u306E\u8AAD\u307F\u8FBC\u307F\u306B\u5931\u6557\u3057\u307E\u3057\u305F",
|
|
841
|
+
unsupported: "\u3053\u306E\u30D6\u30E9\u30A6\u30B6\u306F\u30D1\u30B9\u30AD\u30FC\u306B\u5BFE\u5FDC\u3057\u3066\u3044\u307E\u305B\u3093\u3002",
|
|
842
|
+
disabled: "\u3053\u306E\u30B5\u30A4\u30C8\u3067\u306F\u30D1\u30B9\u30AD\u30FC\u306F\u7121\u52B9\u3067\u3059\u3002"
|
|
843
|
+
}
|
|
776
844
|
}
|
|
777
845
|
};
|
|
778
846
|
|
|
@@ -1,11 +1,17 @@
|
|
|
1
1
|
'use client';
|
|
2
|
+
import {
|
|
3
|
+
classifyPasskeyError,
|
|
4
|
+
isWebAuthnSupported,
|
|
5
|
+
signInWithPasskey
|
|
6
|
+
} from "./chunk-ZDIDJCSU.js";
|
|
2
7
|
import {
|
|
3
8
|
useT
|
|
4
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-4OFRX6QX.js";
|
|
5
10
|
|
|
6
11
|
// src/components/login-view.tsx
|
|
7
|
-
import { useState } from "react";
|
|
12
|
+
import { useEffect, useRef, useState } from "react";
|
|
8
13
|
import { useRouter } from "next/navigation";
|
|
14
|
+
import { Fingerprint } from "lucide-react";
|
|
9
15
|
import {
|
|
10
16
|
signIn,
|
|
11
17
|
signUp,
|
|
@@ -24,7 +30,8 @@ import {
|
|
|
24
30
|
CardDescription
|
|
25
31
|
} from "@ampless/runtime/ui";
|
|
26
32
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
27
|
-
|
|
33
|
+
var LAST_EMAIL_KEY = "ampless.lastSignInEmail";
|
|
34
|
+
function LoginPage({ passkeysEnabled = true }) {
|
|
28
35
|
const router = useRouter();
|
|
29
36
|
const t = useT();
|
|
30
37
|
const [mode, setMode] = useState("signIn");
|
|
@@ -34,6 +41,49 @@ function LoginPage() {
|
|
|
34
41
|
const [error, setError] = useState(null);
|
|
35
42
|
const [info, setInfo] = useState(null);
|
|
36
43
|
const [loading, setLoading] = useState(false);
|
|
44
|
+
const [passkeySupported, setPasskeySupported] = useState(false);
|
|
45
|
+
const emailRef = useRef(null);
|
|
46
|
+
useEffect(() => {
|
|
47
|
+
setPasskeySupported(isWebAuthnSupported());
|
|
48
|
+
try {
|
|
49
|
+
const last = window.localStorage.getItem(LAST_EMAIL_KEY);
|
|
50
|
+
if (last) setEmail(last);
|
|
51
|
+
} catch {
|
|
52
|
+
}
|
|
53
|
+
}, []);
|
|
54
|
+
function rememberEmail(value) {
|
|
55
|
+
try {
|
|
56
|
+
window.localStorage.setItem(LAST_EMAIL_KEY, value);
|
|
57
|
+
} catch {
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
async function handlePasskeySignIn() {
|
|
61
|
+
setError(null);
|
|
62
|
+
setInfo(null);
|
|
63
|
+
if (!email) {
|
|
64
|
+
setError(t("auth.passkey.emailRequired"));
|
|
65
|
+
emailRef.current?.focus();
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
setLoading(true);
|
|
69
|
+
try {
|
|
70
|
+
const outcome = await signInWithPasskey(email);
|
|
71
|
+
if (outcome.status === "signedIn") {
|
|
72
|
+
rememberEmail(email);
|
|
73
|
+
router.push("/admin");
|
|
74
|
+
router.refresh();
|
|
75
|
+
} else if (outcome.status === "noPasskey") {
|
|
76
|
+
setInfo(t("auth.passkey.noneRegistered"));
|
|
77
|
+
} else {
|
|
78
|
+
setError(t("auth.additionalStep", { step: outcome.step }));
|
|
79
|
+
}
|
|
80
|
+
} catch (err) {
|
|
81
|
+
console.error("[login-view] passkey sign-in failed", err);
|
|
82
|
+
setError(t(`auth.passkey.${classifyPasskeyError(err)}`));
|
|
83
|
+
} finally {
|
|
84
|
+
setLoading(false);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
37
87
|
function go(next) {
|
|
38
88
|
setMode(next);
|
|
39
89
|
setError(null);
|
|
@@ -50,6 +100,7 @@ function LoginPage() {
|
|
|
50
100
|
if (mode === "signIn") {
|
|
51
101
|
const result = await signIn({ username: email, password });
|
|
52
102
|
if (result.isSignedIn) {
|
|
103
|
+
rememberEmail(email);
|
|
53
104
|
router.push("/admin");
|
|
54
105
|
router.refresh();
|
|
55
106
|
} else {
|
|
@@ -109,6 +160,7 @@ function LoginPage() {
|
|
|
109
160
|
Input,
|
|
110
161
|
{
|
|
111
162
|
id: "email",
|
|
163
|
+
ref: emailRef,
|
|
112
164
|
type: "email",
|
|
113
165
|
required: true,
|
|
114
166
|
value: email,
|
|
@@ -149,6 +201,20 @@ function LoginPage() {
|
|
|
149
201
|
info && /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: info }),
|
|
150
202
|
error && /* @__PURE__ */ jsx("p", { className: "text-sm text-destructive", children: error }),
|
|
151
203
|
/* @__PURE__ */ jsx(Button, { type: "submit", className: "w-full", disabled: loading, children: loading ? t("auth.common.working") : t(`auth.${mode}.submit`) }),
|
|
204
|
+
mode === "signIn" && passkeysEnabled && passkeySupported && /* @__PURE__ */ jsxs(
|
|
205
|
+
Button,
|
|
206
|
+
{
|
|
207
|
+
type: "button",
|
|
208
|
+
variant: "outline",
|
|
209
|
+
className: "w-full gap-2",
|
|
210
|
+
disabled: loading,
|
|
211
|
+
onClick: () => void handlePasskeySignIn(),
|
|
212
|
+
children: [
|
|
213
|
+
/* @__PURE__ */ jsx(Fingerprint, { className: "h-4 w-4" }),
|
|
214
|
+
t("auth.signIn.passkeyButton")
|
|
215
|
+
]
|
|
216
|
+
}
|
|
217
|
+
),
|
|
152
218
|
/* @__PURE__ */ jsxs("div", { className: "space-y-1 text-center text-sm", children: [
|
|
153
219
|
mode === "signIn" && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
154
220
|
/* @__PURE__ */ jsx("p", { children: /* @__PURE__ */ jsx(
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import {
|
|
3
3
|
PostForm
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-4WYMEUYU.js";
|
|
5
5
|
import {
|
|
6
6
|
useT
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-4OFRX6QX.js";
|
|
8
8
|
|
|
9
9
|
// src/components/edit-post-view.tsx
|
|
10
10
|
import { useEffect, useState, use } from "react";
|
|
@@ -17,14 +17,20 @@ function EditPostPage({ params, previewEndpoint }) {
|
|
|
17
17
|
const [post, setPost] = useState(null);
|
|
18
18
|
const [loading, setLoading] = useState(true);
|
|
19
19
|
const [missing, setMissing] = useState(false);
|
|
20
|
+
const [error, setError] = useState(false);
|
|
20
21
|
useEffect(() => {
|
|
21
22
|
getPostById(postId).then((p) => {
|
|
22
23
|
if (!p) setMissing(true);
|
|
23
24
|
else setPost(p);
|
|
25
|
+
}).catch((err) => {
|
|
26
|
+
console.error("[ampless admin] failed to load post for editing:", err);
|
|
27
|
+
setError(true);
|
|
24
28
|
}).finally(() => setLoading(false));
|
|
25
29
|
}, [postId]);
|
|
26
30
|
if (loading)
|
|
27
31
|
return /* @__PURE__ */ jsx("div", { className: "mx-auto max-w-7xl p-4 md:p-8", children: t("common.loading") });
|
|
32
|
+
if (error)
|
|
33
|
+
return /* @__PURE__ */ jsx("div", { className: "mx-auto max-w-7xl p-4 md:p-8", children: t("common.loadError") });
|
|
28
34
|
if (missing) notFound();
|
|
29
35
|
return /* @__PURE__ */ jsxs("div", { className: "mx-auto max-w-7xl p-4 md:p-8", children: [
|
|
30
36
|
/* @__PURE__ */ jsx("h1", { className: "mb-6 text-2xl font-bold md:mb-8 md:text-3xl", children: t("posts.form.editTitle") }),
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import {
|
|
3
3
|
PostForm
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-4WYMEUYU.js";
|
|
5
5
|
import {
|
|
6
6
|
useT
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-4OFRX6QX.js";
|
|
8
8
|
|
|
9
9
|
// src/components/new-post-view.tsx
|
|
10
10
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import {
|
|
3
3
|
MediaUploader
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-2TBGPB5H.js";
|
|
5
5
|
import {
|
|
6
6
|
useT
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-4OFRX6QX.js";
|
|
8
8
|
|
|
9
9
|
// src/components/media-view.tsx
|
|
10
10
|
import { jsx, jsxs } from "react/jsx-runtime";
|