@ampless/admin 1.0.0-alpha.40 → 1.0.0-alpha.42
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-YNQR3AFO.js → chunk-3EOEDH5Q.js} +2 -2
- package/dist/{chunk-BF6XV6TP.js → chunk-462KM4PP.js} +1 -1
- package/dist/{chunk-MDBBDBE5.js → chunk-4J2WT5DT.js} +2 -2
- package/dist/{chunk-3QXCPMPD.js → chunk-4VX6Z3OI.js} +1 -1
- package/dist/{chunk-GJSMMQVO.js → chunk-AZR2PYIA.js} +2 -2
- package/dist/{chunk-TGEPARLA.js → chunk-EX3XWPBC.js} +1 -1
- package/dist/{chunk-MHTKDXSP.js → chunk-HLORQWBX.js} +4 -2
- package/dist/{chunk-Q3FMKPAQ.js → chunk-IYUEDZTX.js} +2 -2
- package/dist/{chunk-OMWVBK2C.js → chunk-QUFDISLW.js} +1 -1
- package/dist/chunk-T6IB6W3N.js +380 -0
- package/dist/{chunk-5DWBQ73J.js → chunk-U2VSCLWY.js} +26 -0
- package/dist/{chunk-ZR35TWHV.js → chunk-VJ3FOXAK.js} +1 -1
- package/dist/{chunk-VZJU74K3.js → chunk-X47FJZR2.js} +1 -1
- package/dist/{chunk-UTQRFC6V.js → chunk-X4SCR6A4.js} +2 -2
- package/dist/{chunk-DNMENH6C.js → chunk-YI727DVE.js} +1 -1
- package/dist/components/admin-dashboard.js +3 -3
- package/dist/components/edit-post-view.js +5 -5
- package/dist/components/index.d.ts +1 -1
- package/dist/components/index.js +6 -6
- package/dist/components/login-view.js +3 -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 +17 -0
- package/dist/components/plugin-settings-form.js +10 -0
- package/dist/components/posts-list-view.js +3 -3
- package/dist/components/users-list-view.js +3 -3
- package/dist/{i18n-sYi0kbnC.d.ts → i18n-C2ev0Y0f.d.ts} +40 -0
- package/dist/index.d.ts +13 -2
- package/dist/index.js +9 -1
- package/dist/metafile-esm.json +1 -1
- package/dist/pages/index.d.ts +17 -2
- package/dist/pages/index.js +70 -14
- package/package.json +4 -4
package/dist/api/index.d.ts
CHANGED
|
@@ -3,13 +3,13 @@ import {
|
|
|
3
3
|
ImageUploadDialog,
|
|
4
4
|
createMediaRow,
|
|
5
5
|
getMediaProcessingDefaults
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-QUFDISLW.js";
|
|
7
7
|
import {
|
|
8
8
|
publicMediaUrl
|
|
9
9
|
} from "./chunk-2ITWLRYF.js";
|
|
10
10
|
import {
|
|
11
11
|
useT
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-EX3XWPBC.js";
|
|
13
13
|
|
|
14
14
|
// src/components/media-uploader.tsx
|
|
15
15
|
import { useState, useEffect, useCallback, useRef } from "react";
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import {
|
|
3
3
|
PostForm
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-X4SCR6A4.js";
|
|
5
5
|
import {
|
|
6
6
|
useT
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-EX3XWPBC.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
|
PostForm
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-X4SCR6A4.js";
|
|
5
5
|
import {
|
|
6
6
|
useT
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-EX3XWPBC.js";
|
|
8
8
|
|
|
9
9
|
// src/components/edit-post-view.tsx
|
|
10
10
|
import { useEffect, useState, use } from "react";
|
|
@@ -7,14 +7,14 @@ import {
|
|
|
7
7
|
} from "./chunk-C7G5AQ3L.js";
|
|
8
8
|
import {
|
|
9
9
|
setAdminCmsConfigClient
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-QUFDISLW.js";
|
|
11
11
|
import {
|
|
12
12
|
setAdminMediaContext
|
|
13
13
|
} from "./chunk-2ITWLRYF.js";
|
|
14
14
|
import {
|
|
15
15
|
useLocale,
|
|
16
16
|
useT
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-EX3XWPBC.js";
|
|
18
18
|
|
|
19
19
|
// src/lib/amplify-client.ts
|
|
20
20
|
import { Amplify } from "aws-amplify";
|
|
@@ -258,6 +258,7 @@ import {
|
|
|
258
258
|
Globe,
|
|
259
259
|
Users,
|
|
260
260
|
Key,
|
|
261
|
+
Puzzle,
|
|
261
262
|
LogOut,
|
|
262
263
|
ExternalLink,
|
|
263
264
|
Menu,
|
|
@@ -272,6 +273,7 @@ var navItems = [
|
|
|
272
273
|
// ampless runs one site per deployment, so this links directly to
|
|
273
274
|
// the single site's settings page instead of a list landing.
|
|
274
275
|
{ href: "/admin/sites/default", key: "sidebar.sites", icon: Globe },
|
|
276
|
+
{ href: "/admin/plugins", key: "sidebar.plugins", icon: Puzzle },
|
|
275
277
|
{ href: "/admin/users", key: "sidebar.users", icon: Users, adminOnly: true },
|
|
276
278
|
{ href: "/admin/mcp-tokens", key: "sidebar.mcpTokens", icon: Key, adminOnly: true }
|
|
277
279
|
];
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import {
|
|
3
3
|
MediaUploader
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-3EOEDH5Q.js";
|
|
5
5
|
import {
|
|
6
6
|
useT
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-EX3XWPBC.js";
|
|
8
8
|
|
|
9
9
|
// src/components/media-view.tsx
|
|
10
10
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
@@ -0,0 +1,380 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import {
|
|
3
|
+
invalidateSiteSettingsCache
|
|
4
|
+
} from "./chunk-D72XF3Q3.js";
|
|
5
|
+
import {
|
|
6
|
+
useLocale,
|
|
7
|
+
useT
|
|
8
|
+
} from "./chunk-EX3XWPBC.js";
|
|
9
|
+
|
|
10
|
+
// src/components/plugin-settings-form.tsx
|
|
11
|
+
import { useState } from "react";
|
|
12
|
+
import {
|
|
13
|
+
resolveLocalized
|
|
14
|
+
} from "ampless";
|
|
15
|
+
import { Button, Input, Label, Textarea } from "@ampless/runtime/ui";
|
|
16
|
+
|
|
17
|
+
// src/lib/plugin-settings.ts
|
|
18
|
+
import {
|
|
19
|
+
getKvStore,
|
|
20
|
+
SITE_CONFIG_PK,
|
|
21
|
+
isValidPluginKey,
|
|
22
|
+
validatePluginSettingValue
|
|
23
|
+
} from "ampless";
|
|
24
|
+
function pluginSettingKey(instanceId, fieldKey) {
|
|
25
|
+
return `plugins.${instanceId}.${fieldKey}`;
|
|
26
|
+
}
|
|
27
|
+
async function setPluginPublicSetting(instanceId, field, rawValue) {
|
|
28
|
+
if (!isValidPluginKey(instanceId)) {
|
|
29
|
+
throw new Error(`Invalid plugin instanceId: "${instanceId}"`);
|
|
30
|
+
}
|
|
31
|
+
if (!isValidPluginKey(field.key)) {
|
|
32
|
+
throw new Error(`Invalid plugin field key: "${field.key}"`);
|
|
33
|
+
}
|
|
34
|
+
const validated = validatePluginSettingValue(field, rawValue);
|
|
35
|
+
if (validated === null) {
|
|
36
|
+
throw new Error(`Invalid value for plugin field "${field.key}"`);
|
|
37
|
+
}
|
|
38
|
+
const store = getKvStore();
|
|
39
|
+
await store.put(SITE_CONFIG_PK, pluginSettingKey(instanceId, field.key), validated);
|
|
40
|
+
}
|
|
41
|
+
async function deletePluginPublicSetting(instanceId, field) {
|
|
42
|
+
if (!isValidPluginKey(instanceId)) {
|
|
43
|
+
throw new Error(`Invalid plugin instanceId: "${instanceId}"`);
|
|
44
|
+
}
|
|
45
|
+
if (!isValidPluginKey(field.key)) {
|
|
46
|
+
throw new Error(`Invalid plugin field key: "${field.key}"`);
|
|
47
|
+
}
|
|
48
|
+
const store = getKvStore();
|
|
49
|
+
await store.remove(SITE_CONFIG_PK, pluginSettingKey(instanceId, field.key));
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// src/components/plugin-settings-form.tsx
|
|
53
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
54
|
+
var CACHE_REBUILD_DELAY_MS = 8e3;
|
|
55
|
+
function stringify(field, raw) {
|
|
56
|
+
if (raw === void 0 || raw === null) return "";
|
|
57
|
+
switch (field.type) {
|
|
58
|
+
case "boolean":
|
|
59
|
+
return raw === true ? "true" : raw === false ? "false" : String(raw);
|
|
60
|
+
case "json":
|
|
61
|
+
if (typeof raw === "string") return raw;
|
|
62
|
+
try {
|
|
63
|
+
return JSON.stringify(raw, null, 2);
|
|
64
|
+
} catch {
|
|
65
|
+
return "";
|
|
66
|
+
}
|
|
67
|
+
default:
|
|
68
|
+
return typeof raw === "string" ? raw : String(raw);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
function parse(field, raw) {
|
|
72
|
+
switch (field.type) {
|
|
73
|
+
case "boolean":
|
|
74
|
+
if (raw === "true") return true;
|
|
75
|
+
if (raw === "false") return false;
|
|
76
|
+
return null;
|
|
77
|
+
case "number": {
|
|
78
|
+
const trimmed = raw.trim();
|
|
79
|
+
if (trimmed === "") return null;
|
|
80
|
+
const n = Number(trimmed);
|
|
81
|
+
return Number.isNaN(n) ? null : n;
|
|
82
|
+
}
|
|
83
|
+
case "json": {
|
|
84
|
+
const trimmed = raw.trim();
|
|
85
|
+
if (trimmed === "") return null;
|
|
86
|
+
try {
|
|
87
|
+
return JSON.parse(trimmed);
|
|
88
|
+
} catch {
|
|
89
|
+
return null;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
default:
|
|
93
|
+
return raw;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
function PluginSettingsForm({
|
|
97
|
+
instanceId,
|
|
98
|
+
displayName,
|
|
99
|
+
fields,
|
|
100
|
+
initialValues
|
|
101
|
+
}) {
|
|
102
|
+
const t = useT();
|
|
103
|
+
const locale = useLocale();
|
|
104
|
+
function defaultDisplay(field) {
|
|
105
|
+
return field.default !== void 0 ? stringify(field, field.default) : "";
|
|
106
|
+
}
|
|
107
|
+
const [state, setState] = useState(() => {
|
|
108
|
+
const values = {};
|
|
109
|
+
for (const field of fields) {
|
|
110
|
+
const has = Object.prototype.hasOwnProperty.call(initialValues, field.key);
|
|
111
|
+
values[field.key] = has ? stringify(field, initialValues[field.key]) : defaultDisplay(field);
|
|
112
|
+
}
|
|
113
|
+
return { values, touched: {}, invalid: {} };
|
|
114
|
+
});
|
|
115
|
+
const [storedKeys, setStoredKeys] = useState(
|
|
116
|
+
() => new Set(Object.keys(initialValues))
|
|
117
|
+
);
|
|
118
|
+
const [saving, setSaving] = useState(false);
|
|
119
|
+
const [error, setError] = useState(null);
|
|
120
|
+
const [info, setInfo] = useState(null);
|
|
121
|
+
function update(key, value) {
|
|
122
|
+
setState((prev) => ({
|
|
123
|
+
values: { ...prev.values, [key]: value },
|
|
124
|
+
touched: { ...prev.touched, [key]: true },
|
|
125
|
+
invalid: { ...prev.invalid, [key]: false }
|
|
126
|
+
}));
|
|
127
|
+
setInfo(null);
|
|
128
|
+
}
|
|
129
|
+
function scheduleCacheInvalidation() {
|
|
130
|
+
setTimeout(async () => {
|
|
131
|
+
try {
|
|
132
|
+
await invalidateSiteSettingsCache();
|
|
133
|
+
} catch (err) {
|
|
134
|
+
console.warn("[plugin] cache invalidation failed", err);
|
|
135
|
+
}
|
|
136
|
+
}, CACHE_REBUILD_DELAY_MS);
|
|
137
|
+
}
|
|
138
|
+
async function reset(field) {
|
|
139
|
+
setError(null);
|
|
140
|
+
setInfo(null);
|
|
141
|
+
try {
|
|
142
|
+
await deletePluginPublicSetting(instanceId, field);
|
|
143
|
+
setState((prev) => ({
|
|
144
|
+
values: { ...prev.values, [field.key]: defaultDisplay(field) },
|
|
145
|
+
touched: { ...prev.touched, [field.key]: false },
|
|
146
|
+
invalid: { ...prev.invalid, [field.key]: false }
|
|
147
|
+
}));
|
|
148
|
+
setStoredKeys((prev) => {
|
|
149
|
+
if (!prev.has(field.key)) return prev;
|
|
150
|
+
const next = new Set(prev);
|
|
151
|
+
next.delete(field.key);
|
|
152
|
+
return next;
|
|
153
|
+
});
|
|
154
|
+
setInfo(t("plugins.resetDone"));
|
|
155
|
+
scheduleCacheInvalidation();
|
|
156
|
+
} catch (err) {
|
|
157
|
+
console.error("[plugin] reset failed", err);
|
|
158
|
+
setError(err instanceof Error ? err.message : String(err));
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
async function save(e) {
|
|
162
|
+
e.preventDefault();
|
|
163
|
+
setSaving(true);
|
|
164
|
+
setError(null);
|
|
165
|
+
setInfo(null);
|
|
166
|
+
const newInvalid = {};
|
|
167
|
+
const writes = [];
|
|
168
|
+
const writtenKeys = [];
|
|
169
|
+
for (const field of fields) {
|
|
170
|
+
if (!state.touched[field.key]) continue;
|
|
171
|
+
const raw = state.values[field.key] ?? "";
|
|
172
|
+
const parsed = parse(field, raw);
|
|
173
|
+
if (parsed === null && raw !== "") {
|
|
174
|
+
newInvalid[field.key] = true;
|
|
175
|
+
continue;
|
|
176
|
+
}
|
|
177
|
+
if (parsed === null) continue;
|
|
178
|
+
writes.push(setPluginPublicSetting(instanceId, field, parsed));
|
|
179
|
+
writtenKeys.push(field.key);
|
|
180
|
+
}
|
|
181
|
+
if (Object.keys(newInvalid).length > 0) {
|
|
182
|
+
setState((prev) => ({ ...prev, invalid: newInvalid }));
|
|
183
|
+
setSaving(false);
|
|
184
|
+
setError(t("plugins.invalidValue"));
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
try {
|
|
188
|
+
await Promise.all(writes);
|
|
189
|
+
setInfo(t("plugins.saved"));
|
|
190
|
+
setState((prev) => ({ ...prev, touched: {}, invalid: {} }));
|
|
191
|
+
if (writtenKeys.length > 0) {
|
|
192
|
+
setStoredKeys((prev) => {
|
|
193
|
+
const next = new Set(prev);
|
|
194
|
+
for (const k of writtenKeys) next.add(k);
|
|
195
|
+
return next;
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
scheduleCacheInvalidation();
|
|
199
|
+
} catch (err) {
|
|
200
|
+
console.error("[plugin] save failed", err);
|
|
201
|
+
setError(err instanceof Error ? err.message : String(err));
|
|
202
|
+
} finally {
|
|
203
|
+
setSaving(false);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
return /* @__PURE__ */ jsxs("form", { onSubmit: save, className: "max-w-2xl space-y-5 rounded-md border p-4", children: [
|
|
207
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
208
|
+
/* @__PURE__ */ jsx("h2", { className: "text-base font-semibold", children: displayName ? resolveLocalized(displayName, locale) : instanceId }),
|
|
209
|
+
/* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: instanceId })
|
|
210
|
+
] }),
|
|
211
|
+
fields.map((field) => /* @__PURE__ */ jsx(
|
|
212
|
+
FieldRow,
|
|
213
|
+
{
|
|
214
|
+
field,
|
|
215
|
+
value: state.values[field.key] ?? "",
|
|
216
|
+
invalid: !!state.invalid[field.key],
|
|
217
|
+
onChange: (v) => update(field.key, v),
|
|
218
|
+
onReset: () => void reset(field),
|
|
219
|
+
hasStoredValue: storedKeys.has(field.key)
|
|
220
|
+
},
|
|
221
|
+
field.key
|
|
222
|
+
)),
|
|
223
|
+
info && /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: info }),
|
|
224
|
+
error && /* @__PURE__ */ jsx("p", { className: "text-sm text-destructive", children: error }),
|
|
225
|
+
/* @__PURE__ */ jsx(Button, { type: "submit", disabled: saving, children: saving ? t("plugins.saving") : t("plugins.save") })
|
|
226
|
+
] });
|
|
227
|
+
}
|
|
228
|
+
function FieldRow({ field, value, invalid, onChange, onReset, hasStoredValue }) {
|
|
229
|
+
const t = useT();
|
|
230
|
+
const locale = useLocale();
|
|
231
|
+
const id = `plugin-${field.key}`;
|
|
232
|
+
const labelEl = /* @__PURE__ */ jsxs(Label, { htmlFor: id, className: invalid ? "text-destructive" : void 0, children: [
|
|
233
|
+
resolveLocalized(field.label, locale),
|
|
234
|
+
field.required && /* @__PURE__ */ jsx("span", { className: "ml-1 text-destructive", children: "*" })
|
|
235
|
+
] });
|
|
236
|
+
const description = field.description ? /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: resolveLocalized(field.description, locale) }) : null;
|
|
237
|
+
const input = renderInput(field, id, value, invalid, onChange);
|
|
238
|
+
const placeholder = renderDefaultHint(field, locale);
|
|
239
|
+
return /* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
|
|
240
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
|
|
241
|
+
labelEl,
|
|
242
|
+
hasStoredValue && /* @__PURE__ */ jsx(
|
|
243
|
+
"button",
|
|
244
|
+
{
|
|
245
|
+
type: "button",
|
|
246
|
+
className: "text-xs text-muted-foreground underline-offset-2 hover:underline",
|
|
247
|
+
onClick: onReset,
|
|
248
|
+
children: t("plugins.resetToDefault")
|
|
249
|
+
}
|
|
250
|
+
)
|
|
251
|
+
] }),
|
|
252
|
+
description,
|
|
253
|
+
input,
|
|
254
|
+
placeholder
|
|
255
|
+
] });
|
|
256
|
+
}
|
|
257
|
+
function renderDefaultHint(field, _locale) {
|
|
258
|
+
if (field.default === void 0) return null;
|
|
259
|
+
let preview;
|
|
260
|
+
if (typeof field.default === "string") preview = field.default;
|
|
261
|
+
else if (typeof field.default === "boolean" || typeof field.default === "number") {
|
|
262
|
+
preview = String(field.default);
|
|
263
|
+
} else {
|
|
264
|
+
try {
|
|
265
|
+
preview = JSON.stringify(field.default);
|
|
266
|
+
} catch {
|
|
267
|
+
return null;
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
if (!preview) return null;
|
|
271
|
+
return /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: /* @__PURE__ */ jsx("code", { children: preview }) });
|
|
272
|
+
}
|
|
273
|
+
function renderInput(field, id, value, invalid, onChange) {
|
|
274
|
+
switch (field.type) {
|
|
275
|
+
case "text":
|
|
276
|
+
case "url":
|
|
277
|
+
return /* @__PURE__ */ jsx(
|
|
278
|
+
Input,
|
|
279
|
+
{
|
|
280
|
+
id,
|
|
281
|
+
value,
|
|
282
|
+
maxLength: field.type === "text" ? field.maxLength : void 0,
|
|
283
|
+
placeholder: "placeholder" in field ? field.placeholder : void 0,
|
|
284
|
+
onChange: (e) => onChange(e.target.value),
|
|
285
|
+
"aria-invalid": invalid,
|
|
286
|
+
type: field.type === "url" ? "url" : "text"
|
|
287
|
+
}
|
|
288
|
+
);
|
|
289
|
+
case "textarea":
|
|
290
|
+
return /* @__PURE__ */ jsx(
|
|
291
|
+
Textarea,
|
|
292
|
+
{
|
|
293
|
+
id,
|
|
294
|
+
value,
|
|
295
|
+
rows: field.rows ?? 4,
|
|
296
|
+
maxLength: field.maxLength,
|
|
297
|
+
placeholder: field.placeholder,
|
|
298
|
+
onChange: (e) => onChange(e.target.value),
|
|
299
|
+
"aria-invalid": invalid
|
|
300
|
+
}
|
|
301
|
+
);
|
|
302
|
+
case "code":
|
|
303
|
+
return /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
|
|
304
|
+
field.language && /* @__PURE__ */ jsx("p", { className: "text-[10px] uppercase tracking-wide text-muted-foreground", children: field.language }),
|
|
305
|
+
/* @__PURE__ */ jsx(
|
|
306
|
+
Textarea,
|
|
307
|
+
{
|
|
308
|
+
id,
|
|
309
|
+
value,
|
|
310
|
+
rows: field.rows ?? 8,
|
|
311
|
+
maxLength: field.maxLength,
|
|
312
|
+
placeholder: field.placeholder,
|
|
313
|
+
onChange: (e) => onChange(e.target.value),
|
|
314
|
+
"aria-invalid": invalid,
|
|
315
|
+
className: "font-mono text-xs"
|
|
316
|
+
}
|
|
317
|
+
)
|
|
318
|
+
] });
|
|
319
|
+
case "boolean":
|
|
320
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
321
|
+
/* @__PURE__ */ jsx(
|
|
322
|
+
"input",
|
|
323
|
+
{
|
|
324
|
+
id,
|
|
325
|
+
type: "checkbox",
|
|
326
|
+
checked: value === "true",
|
|
327
|
+
onChange: (e) => onChange(e.target.checked ? "true" : "false"),
|
|
328
|
+
className: "h-4 w-4"
|
|
329
|
+
}
|
|
330
|
+
),
|
|
331
|
+
/* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground", children: value === "true" ? "on" : "off" })
|
|
332
|
+
] });
|
|
333
|
+
case "number":
|
|
334
|
+
return /* @__PURE__ */ jsx(
|
|
335
|
+
Input,
|
|
336
|
+
{
|
|
337
|
+
id,
|
|
338
|
+
type: "number",
|
|
339
|
+
value,
|
|
340
|
+
min: field.min,
|
|
341
|
+
max: field.max,
|
|
342
|
+
step: field.step,
|
|
343
|
+
onChange: (e) => onChange(e.target.value),
|
|
344
|
+
"aria-invalid": invalid
|
|
345
|
+
}
|
|
346
|
+
);
|
|
347
|
+
case "select":
|
|
348
|
+
return /* @__PURE__ */ jsxs(
|
|
349
|
+
"select",
|
|
350
|
+
{
|
|
351
|
+
id,
|
|
352
|
+
className: "w-full rounded-md border bg-background px-2 py-1.5 text-sm",
|
|
353
|
+
value,
|
|
354
|
+
onChange: (e) => onChange(e.target.value),
|
|
355
|
+
"aria-invalid": invalid,
|
|
356
|
+
children: [
|
|
357
|
+
/* @__PURE__ */ jsx("option", { value: "", children: "\u2014" }),
|
|
358
|
+
field.options.map((opt) => /* @__PURE__ */ jsx("option", { value: opt.value, children: typeof opt.label === "string" ? opt.label : opt.value }, opt.value))
|
|
359
|
+
]
|
|
360
|
+
}
|
|
361
|
+
);
|
|
362
|
+
case "json":
|
|
363
|
+
return /* @__PURE__ */ jsx(
|
|
364
|
+
Textarea,
|
|
365
|
+
{
|
|
366
|
+
id,
|
|
367
|
+
value,
|
|
368
|
+
rows: field.rows ?? 8,
|
|
369
|
+
placeholder: field.placeholder ?? "{}",
|
|
370
|
+
onChange: (e) => onChange(e.target.value),
|
|
371
|
+
"aria-invalid": invalid,
|
|
372
|
+
className: "font-mono text-xs"
|
|
373
|
+
}
|
|
374
|
+
);
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
export {
|
|
379
|
+
PluginSettingsForm
|
|
380
|
+
};
|
|
@@ -34,6 +34,7 @@ var en_default = {
|
|
|
34
34
|
posts: "Posts",
|
|
35
35
|
media: "Media",
|
|
36
36
|
sites: "Sites",
|
|
37
|
+
plugins: "Plugins",
|
|
37
38
|
users: "Users",
|
|
38
39
|
mcpTokens: "MCP tokens",
|
|
39
40
|
viewSite: "View site",
|
|
@@ -281,6 +282,18 @@ var en_default = {
|
|
|
281
282
|
userExists: "An account with this email already exists."
|
|
282
283
|
}
|
|
283
284
|
},
|
|
285
|
+
plugins: {
|
|
286
|
+
title: "Plugin Settings",
|
|
287
|
+
description: "Edit admin-managed values for installed plugins. Changes propagate to the public site within ~10 seconds (S3 cache rebuild).",
|
|
288
|
+
noConfigurablePlugins: "No installed plugins expose configurable settings.",
|
|
289
|
+
save: "Save",
|
|
290
|
+
saving: "Saving\u2026",
|
|
291
|
+
saved: "Saved. Public site refreshes within ~10 seconds.",
|
|
292
|
+
saveError: "Save failed",
|
|
293
|
+
invalidValue: "One or more values are invalid \u2014 fix highlighted fields and try again.",
|
|
294
|
+
resetToDefault: "Reset to default",
|
|
295
|
+
resetDone: "Stored value cleared. Falling back to the manifest default."
|
|
296
|
+
},
|
|
284
297
|
mcpTokens: {
|
|
285
298
|
title: "MCP tokens",
|
|
286
299
|
description: "Access tokens for the HTTP MCP endpoint. Use them in Claude Desktop / Cursor / any MCP-aware client to read and write this CMS over the wire.",
|
|
@@ -363,6 +376,7 @@ var ja_default = {
|
|
|
363
376
|
posts: "\u8A18\u4E8B",
|
|
364
377
|
media: "\u30E1\u30C7\u30A3\u30A2",
|
|
365
378
|
sites: "\u30B5\u30A4\u30C8",
|
|
379
|
+
plugins: "\u30D7\u30E9\u30B0\u30A4\u30F3",
|
|
366
380
|
users: "\u30E6\u30FC\u30B6\u30FC",
|
|
367
381
|
mcpTokens: "MCP \u30C8\u30FC\u30AF\u30F3",
|
|
368
382
|
viewSite: "\u30B5\u30A4\u30C8\u3092\u8868\u793A",
|
|
@@ -610,6 +624,18 @@ var ja_default = {
|
|
|
610
624
|
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"
|
|
611
625
|
}
|
|
612
626
|
},
|
|
627
|
+
plugins: {
|
|
628
|
+
title: "\u30D7\u30E9\u30B0\u30A4\u30F3\u8A2D\u5B9A",
|
|
629
|
+
description: "\u30A4\u30F3\u30B9\u30C8\u30FC\u30EB\u6E08\u307F\u30D7\u30E9\u30B0\u30A4\u30F3\u306E\u7BA1\u7406\u5024\u3092\u7DE8\u96C6\u3057\u307E\u3059\u3002\u7D0410\u79D2\u4EE5\u5185\u306B\u516C\u958B\u30B5\u30A4\u30C8\u306B\u53CD\u6620\u3055\u308C\u307E\u3059(S3\u30AD\u30E3\u30C3\u30B7\u30E5\u518D\u751F\u6210)\u3002",
|
|
630
|
+
noConfigurablePlugins: "\u8A2D\u5B9A\u53EF\u80FD\u306A\u30D7\u30E9\u30B0\u30A4\u30F3\u306F\u3042\u308A\u307E\u305B\u3093\u3002",
|
|
631
|
+
save: "\u4FDD\u5B58",
|
|
632
|
+
saving: "\u4FDD\u5B58\u4E2D\u2026",
|
|
633
|
+
saved: "\u4FDD\u5B58\u3057\u307E\u3057\u305F\u3002\u7D0410\u79D2\u4EE5\u5185\u306B\u516C\u958B\u30B5\u30A4\u30C8\u306B\u53CD\u6620\u3055\u308C\u307E\u3059\u3002",
|
|
634
|
+
saveError: "\u4FDD\u5B58\u306B\u5931\u6557\u3057\u307E\u3057\u305F",
|
|
635
|
+
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",
|
|
636
|
+
resetToDefault: "\u30C7\u30D5\u30A9\u30EB\u30C8\u306B\u623B\u3059",
|
|
637
|
+
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"
|
|
638
|
+
},
|
|
613
639
|
mcpTokens: {
|
|
614
640
|
title: "MCP \u30C8\u30FC\u30AF\u30F3",
|
|
615
641
|
description: "HTTP MCP \u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8\u7528\u306E\u30A2\u30AF\u30BB\u30B9\u30C8\u30FC\u30AF\u30F3\u3002Claude Desktop / Cursor \u306A\u3069\u306E MCP \u5BFE\u5FDC\u30AF\u30E9\u30A4\u30A2\u30F3\u30C8\u304B\u3089\u3001\u3053\u306E CMS \u306E\u8AAD\u307F\u66F8\u304D\u306B\u4F7F\u3048\u307E\u3059\u3002",
|
|
@@ -3,13 +3,13 @@ import {
|
|
|
3
3
|
ImageUploadDialog,
|
|
4
4
|
getMediaProcessingDefaults,
|
|
5
5
|
uploadProcessedImage
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-QUFDISLW.js";
|
|
7
7
|
import {
|
|
8
8
|
publicMediaUrl
|
|
9
9
|
} from "./chunk-2ITWLRYF.js";
|
|
10
10
|
import {
|
|
11
11
|
useT
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-EX3XWPBC.js";
|
|
13
13
|
|
|
14
14
|
// src/components/media-picker.tsx
|
|
15
15
|
import { useEffect, useRef, useState } from "react";
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import {
|
|
3
3
|
AdminDashboard
|
|
4
|
-
} from "../chunk-
|
|
5
|
-
import "../chunk-
|
|
6
|
-
import "../chunk-
|
|
4
|
+
} from "../chunk-4VX6Z3OI.js";
|
|
5
|
+
import "../chunk-EX3XWPBC.js";
|
|
6
|
+
import "../chunk-U2VSCLWY.js";
|
|
7
7
|
export {
|
|
8
8
|
AdminDashboard
|
|
9
9
|
};
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import {
|
|
3
3
|
EditPostPage
|
|
4
|
-
} from "../chunk-
|
|
5
|
-
import "../chunk-
|
|
6
|
-
import "../chunk-
|
|
4
|
+
} from "../chunk-AZR2PYIA.js";
|
|
5
|
+
import "../chunk-X4SCR6A4.js";
|
|
6
|
+
import "../chunk-QUFDISLW.js";
|
|
7
7
|
import "../chunk-2ITWLRYF.js";
|
|
8
|
-
import "../chunk-
|
|
9
|
-
import "../chunk-
|
|
8
|
+
import "../chunk-EX3XWPBC.js";
|
|
9
|
+
import "../chunk-U2VSCLWY.js";
|
|
10
10
|
export {
|
|
11
11
|
EditPostPage
|
|
12
12
|
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
-
import { L as Locale, D as Dictionary } from '../i18n-
|
|
2
|
+
import { L as Locale, D as Dictionary } from '../i18n-C2ev0Y0f.js';
|
|
3
3
|
import { Config, Post, ThemeManifest, LocalizedString, MediaProcessingDefaults } from 'ampless';
|
|
4
4
|
import { AmplessOutputs, ColorScheme } from '@ampless/runtime';
|
|
5
5
|
import { ProcessOptions } from 'ampless/media';
|