@ampless/admin 0.2.0-alpha.6 → 0.2.0-alpha.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api/index.d.ts +1 -1
- package/dist/{chunk-7WFZULH7.js → chunk-GXPSAOES.js} +200 -85
- package/dist/{chunk-FI7CM4LH.js → chunk-L5NHN3MY.js} +50 -2
- package/dist/components/index.d.ts +4 -2
- package/dist/components/index.js +2 -2
- package/dist/{i18n-ByHM_Bho.d.ts → i18n-Bc4SYgWx.d.ts} +74 -1
- 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 +9 -2
- package/dist/pages/index.js +184 -17
- package/package.json +3 -3
package/dist/pages/index.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
'use client';
|
|
1
2
|
import {
|
|
2
3
|
AdminDashboard,
|
|
3
4
|
AdminProviders,
|
|
@@ -10,9 +11,10 @@ import {
|
|
|
10
11
|
Sidebar,
|
|
11
12
|
SiteSelector,
|
|
12
13
|
SiteSettingsForm,
|
|
13
|
-
ThemeSettingsForm
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
ThemeSettingsForm,
|
|
15
|
+
useT
|
|
16
|
+
} from "../chunk-GXPSAOES.js";
|
|
17
|
+
import "../chunk-L5NHN3MY.js";
|
|
16
18
|
import "../chunk-VXEVLHGL.js";
|
|
17
19
|
|
|
18
20
|
// src/pages/admin-layout.tsx
|
|
@@ -35,9 +37,16 @@ function createAdminLayout(admin) {
|
|
|
35
37
|
const sites = admin.adminSiteOptions();
|
|
36
38
|
const currentSiteId = await admin.currentAdminSiteId();
|
|
37
39
|
const selector = sites.length > 0 ? /* @__PURE__ */ jsx(SiteSelector, { current: currentSiteId, sites }) : null;
|
|
38
|
-
return /* @__PURE__ */ jsx(AdminProviders, { outputs: admin.outputs, cmsConfig: sanitizeCmsConfigForClient(admin.cmsConfig), children: /* @__PURE__ */ jsx(I18nProvider, { locale: admin.locale, dict: admin.dict, children: /* @__PURE__ */ jsxs("div", { className: "flex min-h-screen", children: [
|
|
39
|
-
/* @__PURE__ */ jsx(
|
|
40
|
-
|
|
40
|
+
return /* @__PURE__ */ jsx(AdminProviders, { outputs: admin.outputs, cmsConfig: sanitizeCmsConfigForClient(admin.cmsConfig), children: /* @__PURE__ */ jsx(I18nProvider, { locale: admin.locale, dict: admin.dict, children: /* @__PURE__ */ jsxs("div", { className: "flex min-h-screen flex-col md:flex-row", children: [
|
|
41
|
+
/* @__PURE__ */ jsx(
|
|
42
|
+
Sidebar,
|
|
43
|
+
{
|
|
44
|
+
email: session.email,
|
|
45
|
+
siteSelector: selector,
|
|
46
|
+
isAdmin: admin.isAdmin(session)
|
|
47
|
+
}
|
|
48
|
+
),
|
|
49
|
+
/* @__PURE__ */ jsx("main", { className: "min-w-0 flex-1", children })
|
|
41
50
|
] }) }) });
|
|
42
51
|
}
|
|
43
52
|
return AdminLayout;
|
|
@@ -86,12 +95,12 @@ function createSitesListPage(admin) {
|
|
|
86
95
|
async function SitesPage() {
|
|
87
96
|
const multi = isMultiSite(cmsConfig);
|
|
88
97
|
const ids = multi ? Object.keys(cmsConfig.sites ?? {}) : [DEFAULT_SITE_ID];
|
|
89
|
-
return /* @__PURE__ */ jsxs2("div", { className: "p-8", children: [
|
|
90
|
-
/* @__PURE__ */ jsx2("div", { className: "mb-
|
|
91
|
-
/* @__PURE__ */ jsx2("h1", { className: "text-
|
|
98
|
+
return /* @__PURE__ */ jsxs2("div", { className: "mx-auto max-w-7xl p-4 md:p-8", children: [
|
|
99
|
+
/* @__PURE__ */ jsx2("div", { className: "mb-6 flex flex-wrap items-center justify-between gap-3 md:mb-8", children: /* @__PURE__ */ jsxs2("div", { children: [
|
|
100
|
+
/* @__PURE__ */ jsx2("h1", { className: "text-2xl font-bold md:text-3xl", children: t("sites.list.title") }),
|
|
92
101
|
/* @__PURE__ */ jsx2("p", { className: "mt-1 text-sm text-muted-foreground", children: t("sites.list.description") })
|
|
93
102
|
] }) }),
|
|
94
|
-
/* @__PURE__ */ jsx2("div", { className: "rounded-md border", children: /* @__PURE__ */ jsxs2(Table, { children: [
|
|
103
|
+
/* @__PURE__ */ jsx2("div", { className: "overflow-x-auto rounded-md border", children: /* @__PURE__ */ jsxs2(Table, { children: [
|
|
95
104
|
/* @__PURE__ */ jsx2(TableHeader, { children: /* @__PURE__ */ jsxs2(TableRow, { children: [
|
|
96
105
|
/* @__PURE__ */ jsx2(TableHead, { children: t("sites.list.columnSiteId") }),
|
|
97
106
|
/* @__PURE__ */ jsx2(TableHead, { children: t("sites.list.columnName") }),
|
|
@@ -144,8 +153,8 @@ function createSiteEditPage(admin) {
|
|
|
144
153
|
dateFormat: settings.dateFormat,
|
|
145
154
|
timezone: settings.timezone
|
|
146
155
|
};
|
|
147
|
-
return /* @__PURE__ */ jsxs3("div", { className: "p-8", children: [
|
|
148
|
-
/* @__PURE__ */ jsxs3("div", { className: "mb-8", children: [
|
|
156
|
+
return /* @__PURE__ */ jsxs3("div", { className: "mx-auto max-w-7xl p-4 md:p-8", children: [
|
|
157
|
+
/* @__PURE__ */ jsxs3("div", { className: "mb-6 md:mb-8", children: [
|
|
149
158
|
/* @__PURE__ */ jsxs3(
|
|
150
159
|
Link2,
|
|
151
160
|
{
|
|
@@ -157,7 +166,7 @@ function createSiteEditPage(admin) {
|
|
|
157
166
|
]
|
|
158
167
|
}
|
|
159
168
|
),
|
|
160
|
-
/* @__PURE__ */ jsx3("h1", { className: "mt-2 text-
|
|
169
|
+
/* @__PURE__ */ jsx3("h1", { className: "mt-2 text-2xl font-bold md:text-3xl", children: settings.site.name }),
|
|
161
170
|
/* @__PURE__ */ jsxs3("p", { className: "text-sm text-muted-foreground", children: [
|
|
162
171
|
t("common.siteId"),
|
|
163
172
|
": ",
|
|
@@ -193,8 +202,8 @@ function createSiteThemePage(admin, themeList) {
|
|
|
193
202
|
label: m.manifest.label,
|
|
194
203
|
description: m.manifest.description
|
|
195
204
|
}));
|
|
196
|
-
return /* @__PURE__ */ jsxs4("div", { className: "p-8", children: [
|
|
197
|
-
/* @__PURE__ */ jsxs4("div", { className: "mb-8", children: [
|
|
205
|
+
return /* @__PURE__ */ jsxs4("div", { className: "mx-auto max-w-7xl p-4 md:p-8", children: [
|
|
206
|
+
/* @__PURE__ */ jsxs4("div", { className: "mb-6 md:mb-8", children: [
|
|
198
207
|
/* @__PURE__ */ jsxs4(
|
|
199
208
|
Link3,
|
|
200
209
|
{
|
|
@@ -206,7 +215,7 @@ function createSiteThemePage(admin, themeList) {
|
|
|
206
215
|
]
|
|
207
216
|
}
|
|
208
217
|
),
|
|
209
|
-
/* @__PURE__ */ jsx4("h1", { className: "mt-2 text-
|
|
218
|
+
/* @__PURE__ */ jsx4("h1", { className: "mt-2 text-2xl font-bold md:text-3xl", children: t("theme.title") }),
|
|
210
219
|
/* @__PURE__ */ jsxs4("p", { className: "text-sm text-muted-foreground", children: [
|
|
211
220
|
t("common.active"),
|
|
212
221
|
":",
|
|
@@ -232,6 +241,163 @@ function createSiteThemePage(admin, themeList) {
|
|
|
232
241
|
return ThemePage;
|
|
233
242
|
}
|
|
234
243
|
|
|
244
|
+
// src/pages/users-list.tsx
|
|
245
|
+
import { redirect as redirect2 } from "next/navigation";
|
|
246
|
+
|
|
247
|
+
// src/components/users-list-view.tsx
|
|
248
|
+
import { useEffect, useState } from "react";
|
|
249
|
+
import { generateClient } from "aws-amplify/api";
|
|
250
|
+
import {
|
|
251
|
+
Button as Button2,
|
|
252
|
+
Table as Table2,
|
|
253
|
+
TableBody as TableBody2,
|
|
254
|
+
TableCell as TableCell2,
|
|
255
|
+
TableHead as TableHead2,
|
|
256
|
+
TableHeader as TableHeader2,
|
|
257
|
+
TableRow as TableRow2
|
|
258
|
+
} from "@ampless/runtime/ui";
|
|
259
|
+
import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
260
|
+
function isAdminRole(value) {
|
|
261
|
+
return value === "admin" || value === "editor" || value === "none";
|
|
262
|
+
}
|
|
263
|
+
function UsersListView({ currentUserId }) {
|
|
264
|
+
const t = useT();
|
|
265
|
+
const [users, setUsers] = useState(null);
|
|
266
|
+
const [loading, setLoading] = useState(true);
|
|
267
|
+
const [loadError, setLoadError] = useState(null);
|
|
268
|
+
const [rows, setRows] = useState({});
|
|
269
|
+
useEffect(() => {
|
|
270
|
+
const client = generateClient();
|
|
271
|
+
client.queries.listAdminUsers().then(({ data, errors }) => {
|
|
272
|
+
if (errors && errors.length > 0) {
|
|
273
|
+
const msg = errors[0]?.message ?? "listAdminUsers failed";
|
|
274
|
+
console.error("[users-list-view] listAdminUsers errors:", errors);
|
|
275
|
+
setLoadError(msg);
|
|
276
|
+
return;
|
|
277
|
+
}
|
|
278
|
+
const list = data ?? [];
|
|
279
|
+
setUsers(list);
|
|
280
|
+
setRows(
|
|
281
|
+
Object.fromEntries(
|
|
282
|
+
list.map((u) => [u.userId, { selected: u.role, saving: false, error: null }])
|
|
283
|
+
)
|
|
284
|
+
);
|
|
285
|
+
}).catch((err) => {
|
|
286
|
+
console.error("[users-list-view] listAdminUsers threw:", err);
|
|
287
|
+
setLoadError(err instanceof Error ? err.message : String(err));
|
|
288
|
+
}).finally(() => setLoading(false));
|
|
289
|
+
}, []);
|
|
290
|
+
function updateRow(userId, patch) {
|
|
291
|
+
setRows((prev) => ({
|
|
292
|
+
...prev,
|
|
293
|
+
[userId]: { ...prev[userId], ...patch }
|
|
294
|
+
}));
|
|
295
|
+
}
|
|
296
|
+
async function save(userId) {
|
|
297
|
+
const row = rows[userId];
|
|
298
|
+
if (!row) return;
|
|
299
|
+
updateRow(userId, { saving: true, error: null });
|
|
300
|
+
try {
|
|
301
|
+
const client = generateClient();
|
|
302
|
+
const { data, errors } = await client.mutations.setAdminUserRole({
|
|
303
|
+
userId,
|
|
304
|
+
role: row.selected
|
|
305
|
+
});
|
|
306
|
+
if (errors && errors.length > 0) {
|
|
307
|
+
const msg = errors[0]?.message ?? "setAdminUserRole failed";
|
|
308
|
+
console.error("[users-list-view] setAdminUserRole errors:", errors);
|
|
309
|
+
updateRow(userId, { saving: false, error: msg });
|
|
310
|
+
return;
|
|
311
|
+
}
|
|
312
|
+
if (data) {
|
|
313
|
+
setUsers(
|
|
314
|
+
(prev) => (prev ?? []).map((u) => u.userId === userId ? data : u)
|
|
315
|
+
);
|
|
316
|
+
updateRow(userId, { saving: false, selected: data.role, error: null });
|
|
317
|
+
} else {
|
|
318
|
+
updateRow(userId, { saving: false });
|
|
319
|
+
}
|
|
320
|
+
} catch (err) {
|
|
321
|
+
console.error("[users-list-view] setAdminUserRole threw:", err);
|
|
322
|
+
updateRow(userId, {
|
|
323
|
+
saving: false,
|
|
324
|
+
error: err instanceof Error ? err.message : String(err)
|
|
325
|
+
});
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
return /* @__PURE__ */ jsxs5("div", { className: "mx-auto max-w-7xl p-4 md:p-8", children: [
|
|
329
|
+
/* @__PURE__ */ jsxs5("div", { className: "mb-6 md:mb-8", children: [
|
|
330
|
+
/* @__PURE__ */ jsx5("h1", { className: "text-2xl font-bold md:text-3xl", children: t("users.list.title") }),
|
|
331
|
+
/* @__PURE__ */ jsx5("p", { className: "mt-1 text-sm text-muted-foreground", children: t("users.list.description") })
|
|
332
|
+
] }),
|
|
333
|
+
loading ? /* @__PURE__ */ jsx5("p", { className: "text-muted-foreground", children: t("users.list.loading") }) : loadError ? /* @__PURE__ */ jsxs5("p", { className: "text-sm text-destructive", children: [
|
|
334
|
+
t("users.list.error"),
|
|
335
|
+
": ",
|
|
336
|
+
loadError
|
|
337
|
+
] }) : !users || users.length === 0 ? /* @__PURE__ */ jsx5("p", { className: "text-muted-foreground", children: t("users.list.empty") }) : /* @__PURE__ */ jsx5("div", { className: "overflow-x-auto rounded-md border", children: /* @__PURE__ */ jsxs5(Table2, { children: [
|
|
338
|
+
/* @__PURE__ */ jsx5(TableHeader2, { children: /* @__PURE__ */ jsxs5(TableRow2, { children: [
|
|
339
|
+
/* @__PURE__ */ jsx5(TableHead2, { children: t("users.list.columnEmail") }),
|
|
340
|
+
/* @__PURE__ */ jsx5(TableHead2, { children: t("users.list.columnRole") }),
|
|
341
|
+
/* @__PURE__ */ jsx5(TableHead2, { className: "w-[1%] whitespace-nowrap", children: t("users.list.columnActions") })
|
|
342
|
+
] }) }),
|
|
343
|
+
/* @__PURE__ */ jsx5(TableBody2, { children: users.map((u) => {
|
|
344
|
+
const row = rows[u.userId];
|
|
345
|
+
if (!row) return null;
|
|
346
|
+
const isSelf = u.userId === currentUserId;
|
|
347
|
+
const dirty = row.selected !== u.role;
|
|
348
|
+
return /* @__PURE__ */ jsxs5(TableRow2, { children: [
|
|
349
|
+
/* @__PURE__ */ jsx5(TableCell2, { className: "font-medium", children: u.email || u.userId }),
|
|
350
|
+
/* @__PURE__ */ jsxs5(TableCell2, { children: [
|
|
351
|
+
/* @__PURE__ */ jsxs5(
|
|
352
|
+
"select",
|
|
353
|
+
{
|
|
354
|
+
className: "rounded-md border bg-background px-2 py-1.5 text-sm disabled:cursor-not-allowed disabled:opacity-60",
|
|
355
|
+
value: row.selected,
|
|
356
|
+
disabled: isSelf || row.saving,
|
|
357
|
+
onChange: (e) => {
|
|
358
|
+
const next = e.target.value;
|
|
359
|
+
if (isAdminRole(next)) {
|
|
360
|
+
updateRow(u.userId, { selected: next });
|
|
361
|
+
}
|
|
362
|
+
},
|
|
363
|
+
children: [
|
|
364
|
+
/* @__PURE__ */ jsx5("option", { value: "admin", children: t("users.list.roleAdmin") }),
|
|
365
|
+
/* @__PURE__ */ jsx5("option", { value: "editor", children: t("users.list.roleEditor") }),
|
|
366
|
+
/* @__PURE__ */ jsx5("option", { value: "none", children: t("users.list.roleNone") })
|
|
367
|
+
]
|
|
368
|
+
}
|
|
369
|
+
),
|
|
370
|
+
isSelf && /* @__PURE__ */ jsx5("p", { className: "mt-1 text-xs text-muted-foreground", children: t("users.list.cannotEditSelf") }),
|
|
371
|
+
row.error && /* @__PURE__ */ jsx5("p", { className: "mt-1 text-xs text-destructive", children: row.error })
|
|
372
|
+
] }),
|
|
373
|
+
/* @__PURE__ */ jsx5(TableCell2, { children: /* @__PURE__ */ jsx5(
|
|
374
|
+
Button2,
|
|
375
|
+
{
|
|
376
|
+
size: "sm",
|
|
377
|
+
disabled: isSelf || row.saving || !dirty,
|
|
378
|
+
onClick: () => save(u.userId),
|
|
379
|
+
children: row.saving ? t("users.list.saving") : t("users.list.save")
|
|
380
|
+
}
|
|
381
|
+
) })
|
|
382
|
+
] }, u.userId);
|
|
383
|
+
}) })
|
|
384
|
+
] }) })
|
|
385
|
+
] });
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
// src/pages/users-list.tsx
|
|
389
|
+
import { jsx as jsx6 } from "react/jsx-runtime";
|
|
390
|
+
function createUsersListPage(admin) {
|
|
391
|
+
async function UsersPage() {
|
|
392
|
+
const session = await admin.getServerSession();
|
|
393
|
+
if (!admin.isAdmin(session)) {
|
|
394
|
+
redirect2("/admin");
|
|
395
|
+
}
|
|
396
|
+
return /* @__PURE__ */ jsx6(UsersListView, { currentUserId: session.userId });
|
|
397
|
+
}
|
|
398
|
+
return UsersPage;
|
|
399
|
+
}
|
|
400
|
+
|
|
235
401
|
// src/pages/login.tsx
|
|
236
402
|
function createLoginPage(_admin) {
|
|
237
403
|
return LoginPage;
|
|
@@ -246,5 +412,6 @@ export {
|
|
|
246
412
|
createPostsListPage,
|
|
247
413
|
createSiteEditPage,
|
|
248
414
|
createSiteThemePage,
|
|
249
|
-
createSitesListPage
|
|
415
|
+
createSitesListPage,
|
|
416
|
+
createUsersListPage
|
|
250
417
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ampless/admin",
|
|
3
|
-
"version": "0.2.0-alpha.
|
|
3
|
+
"version": "0.2.0-alpha.7",
|
|
4
4
|
"description": "Admin UI for ampless: post editor, media manager, site/theme settings",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -50,8 +50,8 @@
|
|
|
50
50
|
"lucide-react": "^1.16.0",
|
|
51
51
|
"react-image-crop": "^11.0.7",
|
|
52
52
|
"tailwind-merge": "^3.6.0",
|
|
53
|
-
"ampless": "0.2.0-alpha.
|
|
54
|
-
"@ampless/runtime": "0.2.0-alpha.
|
|
53
|
+
"ampless": "0.2.0-alpha.2",
|
|
54
|
+
"@ampless/runtime": "0.2.0-alpha.4"
|
|
55
55
|
},
|
|
56
56
|
"peerDependencies": {
|
|
57
57
|
"next": "^15 || ^16",
|