@fydemy/cms 1.0.5 → 1.0.6
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/bin.js +36 -8
- package/dist/bin.js.map +1 -1
- package/dist/bin.mjs +36 -8
- package/dist/bin.mjs.map +1 -1
- package/dist/index.js +287 -679
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +287 -679
- package/dist/index.mjs.map +1 -1
- package/package.json +13 -10
- package/LICENSE +0 -21
package/dist/index.mjs
CHANGED
|
@@ -1002,33 +1002,8 @@ function AdminDashboard() {
|
|
|
1002
1002
|
event.target.value = "";
|
|
1003
1003
|
}
|
|
1004
1004
|
};
|
|
1005
|
-
const handleFileUpload = async (event) => {
|
|
1006
|
-
const file = event.target.files?.[0];
|
|
1007
|
-
if (!file) return;
|
|
1008
|
-
setUploading(true);
|
|
1009
|
-
setMessage("");
|
|
1010
|
-
try {
|
|
1011
|
-
const formData = new FormData();
|
|
1012
|
-
formData.append("file", file);
|
|
1013
|
-
const response = await fetch("/api/cms/upload", {
|
|
1014
|
-
method: "POST",
|
|
1015
|
-
body: formData
|
|
1016
|
-
});
|
|
1017
|
-
const data = await response.json();
|
|
1018
|
-
if (response.ok) {
|
|
1019
|
-
setMessage(`\u2705 File uploaded! Path: ${data.url}`);
|
|
1020
|
-
setTimeout(() => setMessage(""), 5e3);
|
|
1021
|
-
} else {
|
|
1022
|
-
setMessage("\u274C Failed to upload file");
|
|
1023
|
-
}
|
|
1024
|
-
} catch (error) {
|
|
1025
|
-
setMessage("\u274C Error uploading file");
|
|
1026
|
-
} finally {
|
|
1027
|
-
setUploading(false);
|
|
1028
|
-
event.target.value = "";
|
|
1029
|
-
}
|
|
1030
|
-
};
|
|
1031
1005
|
const renderField = (key, field) => {
|
|
1006
|
+
const inputClasses = "flex h-9 w-full rounded-md border border-slate-200 bg-transparent px-3 py-1 text-sm shadow-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-slate-400 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-slate-950 disabled:cursor-not-allowed disabled:opacity-50";
|
|
1032
1007
|
switch (field.type) {
|
|
1033
1008
|
case "text":
|
|
1034
1009
|
return /* @__PURE__ */ jsx(
|
|
@@ -1038,12 +1013,7 @@ function AdminDashboard() {
|
|
|
1038
1013
|
type: "text",
|
|
1039
1014
|
value: field.value,
|
|
1040
1015
|
onChange: (e) => updateField(key, e.target.value),
|
|
1041
|
-
|
|
1042
|
-
width: "100%",
|
|
1043
|
-
padding: "0.5rem",
|
|
1044
|
-
border: "1px solid #ddd",
|
|
1045
|
-
borderRadius: "4px"
|
|
1046
|
-
}
|
|
1016
|
+
className: inputClasses
|
|
1047
1017
|
}
|
|
1048
1018
|
);
|
|
1049
1019
|
case "number":
|
|
@@ -1054,12 +1024,7 @@ function AdminDashboard() {
|
|
|
1054
1024
|
type: "number",
|
|
1055
1025
|
value: field.value,
|
|
1056
1026
|
onChange: (e) => updateField(key, parseFloat(e.target.value) || 0),
|
|
1057
|
-
|
|
1058
|
-
width: "100%",
|
|
1059
|
-
padding: "0.5rem",
|
|
1060
|
-
border: "1px solid #ddd",
|
|
1061
|
-
borderRadius: "4px"
|
|
1062
|
-
}
|
|
1027
|
+
className: inputClasses
|
|
1063
1028
|
}
|
|
1064
1029
|
);
|
|
1065
1030
|
case "date":
|
|
@@ -1070,12 +1035,7 @@ function AdminDashboard() {
|
|
|
1070
1035
|
type: "date",
|
|
1071
1036
|
value: field.value,
|
|
1072
1037
|
onChange: (e) => updateField(key, e.target.value),
|
|
1073
|
-
|
|
1074
|
-
width: "100%",
|
|
1075
|
-
padding: "0.5rem",
|
|
1076
|
-
border: "1px solid #ddd",
|
|
1077
|
-
borderRadius: "4px"
|
|
1078
|
-
}
|
|
1038
|
+
className: inputClasses
|
|
1079
1039
|
}
|
|
1080
1040
|
);
|
|
1081
1041
|
case "markdown":
|
|
@@ -1085,19 +1045,12 @@ function AdminDashboard() {
|
|
|
1085
1045
|
id: key,
|
|
1086
1046
|
value: field.value,
|
|
1087
1047
|
onChange: (e) => updateField(key, e.target.value),
|
|
1088
|
-
|
|
1089
|
-
width: "100%",
|
|
1090
|
-
minHeight: key === "content" ? "400px" : "150px",
|
|
1091
|
-
fontFamily: "monospace",
|
|
1092
|
-
padding: "0.5rem",
|
|
1093
|
-
border: "1px solid #ddd",
|
|
1094
|
-
borderRadius: "4px"
|
|
1095
|
-
},
|
|
1048
|
+
className: "flex min-h-[300px] w-full rounded-md border border-slate-200 bg-transparent px-3 py-2 text-sm shadow-sm placeholder:text-slate-400 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-slate-950 disabled:cursor-not-allowed disabled:opacity-50 font-mono",
|
|
1096
1049
|
placeholder: key === "content" ? "Write your markdown content here..." : "Markdown text..."
|
|
1097
1050
|
}
|
|
1098
1051
|
);
|
|
1099
1052
|
case "image":
|
|
1100
|
-
return /* @__PURE__ */ jsxs("div", { children: [
|
|
1053
|
+
return /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
1101
1054
|
/* @__PURE__ */ jsx(
|
|
1102
1055
|
"input",
|
|
1103
1056
|
{
|
|
@@ -1106,13 +1059,7 @@ function AdminDashboard() {
|
|
|
1106
1059
|
value: field.value,
|
|
1107
1060
|
onChange: (e) => updateField(key, e.target.value),
|
|
1108
1061
|
placeholder: "/uploads/image.jpg or https://...",
|
|
1109
|
-
|
|
1110
|
-
width: "100%",
|
|
1111
|
-
padding: "0.5rem",
|
|
1112
|
-
marginBottom: "0.5rem",
|
|
1113
|
-
border: "1px solid #ddd",
|
|
1114
|
-
borderRadius: "4px"
|
|
1115
|
-
}
|
|
1062
|
+
className: inputClasses
|
|
1116
1063
|
}
|
|
1117
1064
|
),
|
|
1118
1065
|
/* @__PURE__ */ jsx(
|
|
@@ -1122,7 +1069,7 @@ function AdminDashboard() {
|
|
|
1122
1069
|
accept: "image/*",
|
|
1123
1070
|
onChange: (e) => handleImageUpload(key, e),
|
|
1124
1071
|
disabled: uploading,
|
|
1125
|
-
|
|
1072
|
+
className: "block w-full text-sm text-slate-500\n file:mr-4 file:py-2 file:px-4\n file:rounded-md file:border-0\n file:text-sm file:font-semibold\n file:bg-slate-50 file:text-slate-700\n hover:file:bg-slate-100"
|
|
1126
1073
|
}
|
|
1127
1074
|
),
|
|
1128
1075
|
field.value && /* @__PURE__ */ jsx(
|
|
@@ -1130,13 +1077,7 @@ function AdminDashboard() {
|
|
|
1130
1077
|
{
|
|
1131
1078
|
src: field.value,
|
|
1132
1079
|
alt: key,
|
|
1133
|
-
|
|
1134
|
-
maxWidth: "200px",
|
|
1135
|
-
display: "block",
|
|
1136
|
-
marginTop: "0.5rem",
|
|
1137
|
-
borderRadius: "4px",
|
|
1138
|
-
border: "1px solid #ddd"
|
|
1139
|
-
}
|
|
1080
|
+
className: "max-w-[200px] rounded-md border border-slate-200"
|
|
1140
1081
|
}
|
|
1141
1082
|
)
|
|
1142
1083
|
] });
|
|
@@ -1147,497 +1088,202 @@ function AdminDashboard() {
|
|
|
1147
1088
|
id: key,
|
|
1148
1089
|
type: "text",
|
|
1149
1090
|
value: field.value,
|
|
1150
|
-
onChange: (e) => updateField(key, e.target.value)
|
|
1091
|
+
onChange: (e) => updateField(key, e.target.value),
|
|
1092
|
+
className: inputClasses
|
|
1151
1093
|
}
|
|
1152
1094
|
);
|
|
1153
1095
|
}
|
|
1154
1096
|
};
|
|
1155
|
-
return /* @__PURE__ */ jsxs(
|
|
1156
|
-
"div",
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
"
|
|
1097
|
+
return /* @__PURE__ */ jsxs("div", { className: "min-h-screen bg-slate-50/50 pb-8", children: [
|
|
1098
|
+
/* @__PURE__ */ jsx("div", { className: "border-b border-slate-200 bg-white px-4 py-4 mb-6", children: /* @__PURE__ */ jsxs("div", { className: "container mx-auto max-w-7xl flex items-center justify-between", children: [
|
|
1099
|
+
/* @__PURE__ */ jsx("div", { className: "flex items-center gap-2", children: /* @__PURE__ */ jsx("h1", { className: "text-xl font-bold tracking-tight", children: "\u{1F4DD} Admin Dashboard" }) }),
|
|
1100
|
+
/* @__PURE__ */ jsx(
|
|
1101
|
+
"button",
|
|
1102
|
+
{
|
|
1103
|
+
onClick: handleLogout2,
|
|
1104
|
+
className: "inline-flex h-9 items-center justify-center rounded-md border border-slate-200 bg-white px-4 py-2 text-sm font-medium transition-colors hover:bg-slate-100 hover:text-slate-900 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-slate-950",
|
|
1105
|
+
children: "Logout"
|
|
1106
|
+
}
|
|
1107
|
+
)
|
|
1108
|
+
] }) }),
|
|
1109
|
+
/* @__PURE__ */ jsxs("div", { className: "container mx-auto max-w-7xl px-4 grid grid-cols-1 md:grid-cols-[300px_1fr] gap-6", children: [
|
|
1110
|
+
/* @__PURE__ */ jsx("div", { className: "flex flex-col gap-4", children: /* @__PURE__ */ jsx("div", { className: "rounded-xl border border-slate-200 bg-white text-slate-950 shadow-sm", children: /* @__PURE__ */ jsxs("div", { className: "p-6", children: [
|
|
1111
|
+
/* @__PURE__ */ jsx("h2", { className: "text-lg font-semibold leading-none tracking-tight mb-4", children: "Files" }),
|
|
1112
|
+
/* @__PURE__ */ jsxs("div", { className: "mb-4 text-sm text-slate-500 flex items-center gap-1 overflow-hidden", children: [
|
|
1113
|
+
/* @__PURE__ */ jsx(
|
|
1114
|
+
"button",
|
|
1115
|
+
{
|
|
1116
|
+
onClick: () => setCurrentPath(""),
|
|
1117
|
+
className: "hover:text-slate-900 hover:underline shrink-0",
|
|
1118
|
+
children: "content"
|
|
1119
|
+
}
|
|
1120
|
+
),
|
|
1121
|
+
currentPath && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1122
|
+
/* @__PURE__ */ jsx("span", { className: "text-slate-300", children: "/" }),
|
|
1123
|
+
/* @__PURE__ */ jsx("span", { className: "font-medium truncate text-slate-900", children: currentPath })
|
|
1124
|
+
] })
|
|
1125
|
+
] }),
|
|
1126
|
+
currentPath && /* @__PURE__ */ jsx(
|
|
1127
|
+
"button",
|
|
1163
1128
|
{
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
alignItems: "center",
|
|
1168
|
-
marginBottom: "2rem"
|
|
1169
|
-
},
|
|
1170
|
-
children: [
|
|
1171
|
-
/* @__PURE__ */ jsx("h1", { children: "\u{1F4DD} Admin Dashboard" }),
|
|
1172
|
-
/* @__PURE__ */ jsx(
|
|
1173
|
-
"button",
|
|
1174
|
-
{
|
|
1175
|
-
onClick: handleLogout2,
|
|
1176
|
-
style: {
|
|
1177
|
-
padding: "0.5rem 1rem",
|
|
1178
|
-
background: "#f5f5f5",
|
|
1179
|
-
border: "1px solid #ddd",
|
|
1180
|
-
borderRadius: "4px",
|
|
1181
|
-
cursor: "pointer"
|
|
1182
|
-
},
|
|
1183
|
-
children: "Logout"
|
|
1184
|
-
}
|
|
1185
|
-
)
|
|
1186
|
-
]
|
|
1129
|
+
onClick: goUp,
|
|
1130
|
+
className: "mb-4 inline-flex h-8 w-full items-center justify-center rounded-md bg-slate-100 px-3 text-xs font-medium text-slate-900 hover:bg-slate-200/80",
|
|
1131
|
+
children: "\u2B06\uFE0F Go Up"
|
|
1187
1132
|
}
|
|
1188
1133
|
),
|
|
1189
|
-
/* @__PURE__ */ jsxs(
|
|
1134
|
+
/* @__PURE__ */ jsxs("div", { className: "mb-6 space-y-2 border-b border-slate-100 pb-6", children: [
|
|
1135
|
+
/* @__PURE__ */ jsx(
|
|
1136
|
+
"input",
|
|
1137
|
+
{
|
|
1138
|
+
type: "text",
|
|
1139
|
+
placeholder: "new-file.md",
|
|
1140
|
+
value: newFileName,
|
|
1141
|
+
onChange: (e) => setNewFileName(e.target.value),
|
|
1142
|
+
className: "flex h-9 w-full rounded-md border border-slate-200 bg-transparent px-3 py-1 text-sm shadow-sm transition-colors placeholder:text-slate-400 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-slate-950"
|
|
1143
|
+
}
|
|
1144
|
+
),
|
|
1145
|
+
/* @__PURE__ */ jsx(
|
|
1146
|
+
"button",
|
|
1147
|
+
{
|
|
1148
|
+
onClick: createFile,
|
|
1149
|
+
disabled: loading || !newFileName,
|
|
1150
|
+
className: "inline-flex h-9 w-full items-center justify-center rounded-md bg-slate-900 px-4 py-2 text-sm font-medium text-slate-50 shadow hover:bg-slate-900/90 disabled:pointer-events-none disabled:opacity-50",
|
|
1151
|
+
children: "+ New File"
|
|
1152
|
+
}
|
|
1153
|
+
)
|
|
1154
|
+
] }),
|
|
1155
|
+
/* @__PURE__ */ jsxs("ul", { className: "space-y-1", children: [
|
|
1156
|
+
entries.length === 0 && /* @__PURE__ */ jsx("li", { className: "text-sm text-slate-500 italic px-2", children: "Empty directory" }),
|
|
1157
|
+
entries.map((entry) => /* @__PURE__ */ jsx("li", { children: entry.type === "directory" ? /* @__PURE__ */ jsxs(
|
|
1158
|
+
"button",
|
|
1159
|
+
{
|
|
1160
|
+
onClick: () => navigateToDir(entry.path),
|
|
1161
|
+
className: "flex w-full items-center gap-2 rounded-md px-2 py-1.5 text-sm font-medium hover:bg-slate-100 text-slate-700 hover:text-slate-900",
|
|
1162
|
+
children: [
|
|
1163
|
+
"\u{1F4C1} ",
|
|
1164
|
+
entry.name
|
|
1165
|
+
]
|
|
1166
|
+
}
|
|
1167
|
+
) : /* @__PURE__ */ jsxs("div", { className: "group flex items-center justify-between rounded-md hover:bg-slate-100 px-2 py-1.5", children: [
|
|
1168
|
+
/* @__PURE__ */ jsxs(
|
|
1169
|
+
"button",
|
|
1170
|
+
{
|
|
1171
|
+
onClick: () => loadFile(entry.path),
|
|
1172
|
+
className: `flex-1 text-left text-sm truncate ${selectedFile === entry.path ? "font-semibold text-slate-900" : "text-slate-600 group-hover:text-slate-900"}`,
|
|
1173
|
+
children: [
|
|
1174
|
+
"\u{1F4C4} ",
|
|
1175
|
+
entry.name
|
|
1176
|
+
]
|
|
1177
|
+
}
|
|
1178
|
+
),
|
|
1179
|
+
/* @__PURE__ */ jsx(
|
|
1180
|
+
"button",
|
|
1181
|
+
{
|
|
1182
|
+
onClick: () => deleteFile(entry.path),
|
|
1183
|
+
disabled: loading,
|
|
1184
|
+
className: "opacity-0 group-hover:opacity-100 ml-2 text-slate-400 hover:text-red-500 transition-opacity",
|
|
1185
|
+
title: "Delete file",
|
|
1186
|
+
children: "\u2715"
|
|
1187
|
+
}
|
|
1188
|
+
)
|
|
1189
|
+
] }) }, entry.path))
|
|
1190
|
+
] })
|
|
1191
|
+
] }) }) }),
|
|
1192
|
+
/* @__PURE__ */ jsx("div", { className: "flex flex-col gap-4", children: /* @__PURE__ */ jsx("div", { className: "rounded-xl border border-slate-200 bg-white text-slate-950 shadow-sm min-h-[500px]", children: selectedFile ? /* @__PURE__ */ jsxs("div", { className: "p-6", children: [
|
|
1193
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col sm:flex-row sm:items-center justify-between gap-4 mb-6 pb-6 border-b border-slate-100", children: [
|
|
1194
|
+
/* @__PURE__ */ jsxs("h2", { className: "text-xl font-semibold tracking-tight break-all", children: [
|
|
1195
|
+
"Edit: ",
|
|
1196
|
+
selectedFile
|
|
1197
|
+
] }),
|
|
1198
|
+
/* @__PURE__ */ jsxs("div", { className: "flex gap-2 shrink-0", children: [
|
|
1199
|
+
/* @__PURE__ */ jsx(
|
|
1200
|
+
"button",
|
|
1201
|
+
{
|
|
1202
|
+
onClick: duplicateFile,
|
|
1203
|
+
disabled: loading,
|
|
1204
|
+
className: "inline-flex h-9 items-center justify-center rounded-md border border-slate-200 bg-white px-4 py-2 text-sm font-medium shadow-sm transition-colors hover:bg-slate-100 hover:text-slate-900 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-slate-950 disabled:pointer-events-none disabled:opacity-50",
|
|
1205
|
+
children: "\u{1F4CB} Duplicate"
|
|
1206
|
+
}
|
|
1207
|
+
),
|
|
1208
|
+
/* @__PURE__ */ jsx(
|
|
1209
|
+
"button",
|
|
1210
|
+
{
|
|
1211
|
+
onClick: saveFile,
|
|
1212
|
+
disabled: loading,
|
|
1213
|
+
className: "inline-flex h-9 items-center justify-center rounded-md bg-slate-900 px-4 py-2 text-sm font-medium text-slate-50 shadow hover:bg-slate-900/90 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-slate-950 disabled:pointer-events-none disabled:opacity-50",
|
|
1214
|
+
children: loading ? "Saving..." : "\u{1F4BE} Save Changes"
|
|
1215
|
+
}
|
|
1216
|
+
)
|
|
1217
|
+
] })
|
|
1218
|
+
] }),
|
|
1219
|
+
message && /* @__PURE__ */ jsx(
|
|
1190
1220
|
"div",
|
|
1191
1221
|
{
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
{
|
|
1240
|
-
onClick: goUp,
|
|
1241
|
-
style: {
|
|
1242
|
-
width: "100%",
|
|
1243
|
-
marginBottom: "1rem",
|
|
1244
|
-
padding: "0.5rem",
|
|
1245
|
-
background: "#f5f5f5",
|
|
1246
|
-
border: "1px solid #ddd",
|
|
1247
|
-
borderRadius: "4px",
|
|
1248
|
-
cursor: "pointer"
|
|
1249
|
-
},
|
|
1250
|
-
children: "\u2B06\uFE0F Go Up"
|
|
1251
|
-
}
|
|
1252
|
-
),
|
|
1253
|
-
/* @__PURE__ */ jsxs(
|
|
1254
|
-
"div",
|
|
1255
|
-
{
|
|
1256
|
-
style: {
|
|
1257
|
-
marginBottom: "1.5rem",
|
|
1258
|
-
paddingBottom: "1.5rem",
|
|
1259
|
-
borderBottom: "1px solid #eee"
|
|
1260
|
-
},
|
|
1261
|
-
children: [
|
|
1262
|
-
/* @__PURE__ */ jsx(
|
|
1263
|
-
"input",
|
|
1264
|
-
{
|
|
1265
|
-
type: "text",
|
|
1266
|
-
placeholder: "new-file.md",
|
|
1267
|
-
value: newFileName,
|
|
1268
|
-
onChange: (e) => setNewFileName(e.target.value),
|
|
1269
|
-
style: {
|
|
1270
|
-
width: "100%",
|
|
1271
|
-
padding: "0.5rem",
|
|
1272
|
-
marginBottom: "0.5rem",
|
|
1273
|
-
border: "1px solid #ddd",
|
|
1274
|
-
borderRadius: "4px"
|
|
1275
|
-
}
|
|
1276
|
-
}
|
|
1277
|
-
),
|
|
1278
|
-
/* @__PURE__ */ jsx(
|
|
1279
|
-
"button",
|
|
1280
|
-
{
|
|
1281
|
-
onClick: createFile,
|
|
1282
|
-
disabled: loading || !newFileName,
|
|
1283
|
-
style: {
|
|
1284
|
-
width: "100%",
|
|
1285
|
-
padding: "0.5rem",
|
|
1286
|
-
background: "#0070f3",
|
|
1287
|
-
color: "white",
|
|
1288
|
-
border: "none",
|
|
1289
|
-
borderRadius: "4px",
|
|
1290
|
-
cursor: "pointer",
|
|
1291
|
-
opacity: loading ? 0.7 : 1
|
|
1292
|
-
},
|
|
1293
|
-
children: "+ New File"
|
|
1294
|
-
}
|
|
1295
|
-
)
|
|
1296
|
-
]
|
|
1297
|
-
}
|
|
1298
|
-
),
|
|
1299
|
-
/* @__PURE__ */ jsxs("ul", { style: { listStyle: "none", padding: 0, margin: 0 }, children: [
|
|
1300
|
-
entries.length === 0 && /* @__PURE__ */ jsx("li", { style: { color: "#999", fontStyle: "italic" }, children: "Empty directory" }),
|
|
1301
|
-
entries.map((entry) => /* @__PURE__ */ jsx(
|
|
1302
|
-
"li",
|
|
1303
|
-
{
|
|
1304
|
-
style: {
|
|
1305
|
-
marginBottom: "0.5rem",
|
|
1306
|
-
display: "flex",
|
|
1307
|
-
flexDirection: "column"
|
|
1308
|
-
},
|
|
1309
|
-
children: entry.type === "directory" ? /* @__PURE__ */ jsxs(
|
|
1310
|
-
"button",
|
|
1311
|
-
{
|
|
1312
|
-
onClick: () => navigateToDir(entry.path),
|
|
1313
|
-
style: {
|
|
1314
|
-
background: "none",
|
|
1315
|
-
border: "none",
|
|
1316
|
-
color: "#0070f3",
|
|
1317
|
-
cursor: "pointer",
|
|
1318
|
-
textAlign: "left",
|
|
1319
|
-
fontSize: "1rem",
|
|
1320
|
-
padding: "0.25rem 0",
|
|
1321
|
-
fontWeight: "bold"
|
|
1322
|
-
},
|
|
1323
|
-
children: [
|
|
1324
|
-
"\u{1F4C1} ",
|
|
1325
|
-
entry.name
|
|
1326
|
-
]
|
|
1327
|
-
}
|
|
1328
|
-
) : /* @__PURE__ */ jsxs(
|
|
1329
|
-
"div",
|
|
1330
|
-
{
|
|
1331
|
-
style: {
|
|
1332
|
-
display: "flex",
|
|
1333
|
-
justifyContent: "space-between",
|
|
1334
|
-
alignItems: "center"
|
|
1335
|
-
},
|
|
1336
|
-
children: [
|
|
1337
|
-
/* @__PURE__ */ jsxs(
|
|
1338
|
-
"button",
|
|
1339
|
-
{
|
|
1340
|
-
onClick: () => loadFile(entry.path),
|
|
1341
|
-
style: {
|
|
1342
|
-
background: "none",
|
|
1343
|
-
border: "none",
|
|
1344
|
-
color: selectedFile === entry.path ? "#000" : "#444",
|
|
1345
|
-
cursor: "pointer",
|
|
1346
|
-
textAlign: "left",
|
|
1347
|
-
padding: "0.25rem 0",
|
|
1348
|
-
fontWeight: selectedFile === entry.path ? "bold" : "normal",
|
|
1349
|
-
textDecoration: selectedFile === entry.path ? "underline" : "none",
|
|
1350
|
-
flex: 1
|
|
1351
|
-
},
|
|
1352
|
-
children: [
|
|
1353
|
-
"\u{1F4C4} ",
|
|
1354
|
-
entry.name
|
|
1355
|
-
]
|
|
1356
|
-
}
|
|
1357
|
-
),
|
|
1358
|
-
/* @__PURE__ */ jsx(
|
|
1359
|
-
"button",
|
|
1360
|
-
{
|
|
1361
|
-
onClick: () => deleteFile(entry.path),
|
|
1362
|
-
disabled: loading,
|
|
1363
|
-
style: {
|
|
1364
|
-
background: "none",
|
|
1365
|
-
border: "none",
|
|
1366
|
-
color: "#d32f2f",
|
|
1367
|
-
cursor: "pointer",
|
|
1368
|
-
fontSize: "0.8rem",
|
|
1369
|
-
opacity: 0.7
|
|
1370
|
-
},
|
|
1371
|
-
children: "\u2715"
|
|
1372
|
-
}
|
|
1373
|
-
)
|
|
1374
|
-
]
|
|
1375
|
-
}
|
|
1376
|
-
)
|
|
1377
|
-
},
|
|
1378
|
-
entry.path
|
|
1379
|
-
))
|
|
1380
|
-
] })
|
|
1381
|
-
]
|
|
1382
|
-
}
|
|
1383
|
-
),
|
|
1222
|
+
className: `mb-6 rounded-md p-3 text-sm flex items-center gap-2 ${message.includes("\u2705") ? "bg-green-50 text-green-900 border border-green-200" : "bg-red-50 text-red-900 border border-red-200"}`,
|
|
1223
|
+
children: message
|
|
1224
|
+
}
|
|
1225
|
+
),
|
|
1226
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-6", children: [
|
|
1227
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
|
|
1228
|
+
/* @__PURE__ */ jsx("h3", { className: "text-sm font-medium leading-none text-slate-500 uppercase tracking-wider", children: "Frontmatter Fields" }),
|
|
1229
|
+
/* @__PURE__ */ jsx(
|
|
1230
|
+
"button",
|
|
1231
|
+
{
|
|
1232
|
+
onClick: addField,
|
|
1233
|
+
className: "inline-flex h-8 items-center justify-center rounded-md bg-slate-100 px-3 text-xs font-medium text-slate-900 hover:bg-slate-200",
|
|
1234
|
+
children: "+ Add Field"
|
|
1235
|
+
}
|
|
1236
|
+
)
|
|
1237
|
+
] }),
|
|
1238
|
+
Object.keys(fields).length === 0 ? /* @__PURE__ */ jsx("div", { className: "text-center py-12 text-slate-500 border-2 border-dashed border-slate-200 rounded-lg", children: "No fields found. Add one or load a file layout." }) : /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
|
|
1239
|
+
Object.entries(fields).filter(([key]) => key !== "content").map(([key, field]) => /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
1240
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
|
|
1241
|
+
/* @__PURE__ */ jsxs(
|
|
1242
|
+
"label",
|
|
1243
|
+
{
|
|
1244
|
+
htmlFor: key,
|
|
1245
|
+
className: "text-sm font-medium bg-slate-100 px-2 py-0.5 rounded text-slate-700",
|
|
1246
|
+
children: [
|
|
1247
|
+
key,
|
|
1248
|
+
" ",
|
|
1249
|
+
/* @__PURE__ */ jsxs("span", { className: "text-slate-400 font-normal text-xs ml-1", children: [
|
|
1250
|
+
"(",
|
|
1251
|
+
field.type,
|
|
1252
|
+
")"
|
|
1253
|
+
] })
|
|
1254
|
+
]
|
|
1255
|
+
}
|
|
1256
|
+
),
|
|
1257
|
+
/* @__PURE__ */ jsx(
|
|
1258
|
+
"button",
|
|
1259
|
+
{
|
|
1260
|
+
onClick: () => removeField(key),
|
|
1261
|
+
className: "text-xs text-red-500 hover:text-red-700 hover:underline",
|
|
1262
|
+
children: "Remove"
|
|
1263
|
+
}
|
|
1264
|
+
)
|
|
1265
|
+
] }),
|
|
1266
|
+
renderField(key, field)
|
|
1267
|
+
] }, key)),
|
|
1268
|
+
fields["content"] && /* @__PURE__ */ jsxs("div", { className: "pt-6 mt-6 border-t border-slate-100", children: [
|
|
1384
1269
|
/* @__PURE__ */ jsx(
|
|
1385
|
-
"
|
|
1270
|
+
"label",
|
|
1386
1271
|
{
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
borderRadius: "8px",
|
|
1391
|
-
boxShadow: "0 2px 4px rgba(0,0,0,0.1)"
|
|
1392
|
-
},
|
|
1393
|
-
children: selectedFile ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1394
|
-
/* @__PURE__ */ jsxs(
|
|
1395
|
-
"div",
|
|
1396
|
-
{
|
|
1397
|
-
style: {
|
|
1398
|
-
display: "flex",
|
|
1399
|
-
justifyContent: "space-between",
|
|
1400
|
-
alignItems: "center",
|
|
1401
|
-
marginBottom: "2rem",
|
|
1402
|
-
paddingBottom: "1rem",
|
|
1403
|
-
borderBottom: "1px solid #eee"
|
|
1404
|
-
},
|
|
1405
|
-
children: [
|
|
1406
|
-
/* @__PURE__ */ jsxs("h2", { style: { margin: 0 }, children: [
|
|
1407
|
-
"Edit: ",
|
|
1408
|
-
selectedFile
|
|
1409
|
-
] }),
|
|
1410
|
-
/* @__PURE__ */ jsxs("div", { style: { display: "flex", gap: "0.5rem" }, children: [
|
|
1411
|
-
/* @__PURE__ */ jsx(
|
|
1412
|
-
"button",
|
|
1413
|
-
{
|
|
1414
|
-
onClick: duplicateFile,
|
|
1415
|
-
disabled: loading,
|
|
1416
|
-
style: {
|
|
1417
|
-
padding: "0.5rem 1rem",
|
|
1418
|
-
background: "#f5f5f5",
|
|
1419
|
-
border: "1px solid #ddd",
|
|
1420
|
-
borderRadius: "4px",
|
|
1421
|
-
cursor: "pointer"
|
|
1422
|
-
},
|
|
1423
|
-
children: "\u{1F4CB} Duplicate"
|
|
1424
|
-
}
|
|
1425
|
-
),
|
|
1426
|
-
/* @__PURE__ */ jsx(
|
|
1427
|
-
"button",
|
|
1428
|
-
{
|
|
1429
|
-
onClick: saveFile,
|
|
1430
|
-
disabled: loading,
|
|
1431
|
-
style: {
|
|
1432
|
-
padding: "0.5rem 1rem",
|
|
1433
|
-
background: "#0070f3",
|
|
1434
|
-
color: "white",
|
|
1435
|
-
border: "none",
|
|
1436
|
-
borderRadius: "4px",
|
|
1437
|
-
cursor: "pointer",
|
|
1438
|
-
opacity: loading ? 0.7 : 1
|
|
1439
|
-
},
|
|
1440
|
-
children: loading ? "Saving..." : "\u{1F4BE} Save Changes"
|
|
1441
|
-
}
|
|
1442
|
-
)
|
|
1443
|
-
] })
|
|
1444
|
-
]
|
|
1445
|
-
}
|
|
1446
|
-
),
|
|
1447
|
-
message && /* @__PURE__ */ jsx(
|
|
1448
|
-
"div",
|
|
1449
|
-
{
|
|
1450
|
-
style: {
|
|
1451
|
-
marginBottom: "1.5rem",
|
|
1452
|
-
padding: "0.75rem",
|
|
1453
|
-
background: message.includes("\u2705") ? "#e6ffe6" : "#ffe6e6",
|
|
1454
|
-
borderRadius: "4px",
|
|
1455
|
-
border: message.includes("\u2705") ? "1px solid #a5d6a7" : "1px solid #ef9a9a"
|
|
1456
|
-
},
|
|
1457
|
-
children: message
|
|
1458
|
-
}
|
|
1459
|
-
),
|
|
1460
|
-
/* @__PURE__ */ jsxs("div", { style: { marginBottom: "2rem" }, children: [
|
|
1461
|
-
/* @__PURE__ */ jsxs(
|
|
1462
|
-
"div",
|
|
1463
|
-
{
|
|
1464
|
-
style: {
|
|
1465
|
-
display: "flex",
|
|
1466
|
-
justifyContent: "space-between",
|
|
1467
|
-
alignItems: "center",
|
|
1468
|
-
marginBottom: "1rem"
|
|
1469
|
-
},
|
|
1470
|
-
children: [
|
|
1471
|
-
/* @__PURE__ */ jsx("h3", { style: { fontSize: "1.1rem", margin: 0 }, children: "Fields" }),
|
|
1472
|
-
/* @__PURE__ */ jsx(
|
|
1473
|
-
"button",
|
|
1474
|
-
{
|
|
1475
|
-
onClick: addField,
|
|
1476
|
-
style: {
|
|
1477
|
-
fontSize: "0.875rem",
|
|
1478
|
-
padding: "0.4rem 0.8rem",
|
|
1479
|
-
background: "#e1f5fe",
|
|
1480
|
-
color: "#0288d1",
|
|
1481
|
-
border: "none",
|
|
1482
|
-
borderRadius: "4px",
|
|
1483
|
-
cursor: "pointer"
|
|
1484
|
-
},
|
|
1485
|
-
children: "+ Add Field"
|
|
1486
|
-
}
|
|
1487
|
-
)
|
|
1488
|
-
]
|
|
1489
|
-
}
|
|
1490
|
-
),
|
|
1491
|
-
Object.keys(fields).length === 0 ? /* @__PURE__ */ jsxs(
|
|
1492
|
-
"div",
|
|
1493
|
-
{
|
|
1494
|
-
style: {
|
|
1495
|
-
padding: "2rem",
|
|
1496
|
-
textAlign: "center",
|
|
1497
|
-
background: "#f9f9f9",
|
|
1498
|
-
borderRadius: "4px",
|
|
1499
|
-
border: "1px dashed #ccc"
|
|
1500
|
-
},
|
|
1501
|
-
children: [
|
|
1502
|
-
/* @__PURE__ */ jsx(
|
|
1503
|
-
"p",
|
|
1504
|
-
{
|
|
1505
|
-
style: { color: "#666", fontStyle: "italic", margin: 0 },
|
|
1506
|
-
children: 'No fields yet. Click "+ Add Field" to start.'
|
|
1507
|
-
}
|
|
1508
|
-
),
|
|
1509
|
-
/* @__PURE__ */ jsx(
|
|
1510
|
-
"small",
|
|
1511
|
-
{
|
|
1512
|
-
style: {
|
|
1513
|
-
color: "#999",
|
|
1514
|
-
marginTop: "0.5rem",
|
|
1515
|
-
display: "block"
|
|
1516
|
-
},
|
|
1517
|
-
children: "Add 'content' field for the main body"
|
|
1518
|
-
}
|
|
1519
|
-
)
|
|
1520
|
-
]
|
|
1521
|
-
}
|
|
1522
|
-
) : Object.entries(fields).map(([key, field]) => /* @__PURE__ */ jsxs(
|
|
1523
|
-
"div",
|
|
1524
|
-
{
|
|
1525
|
-
style: {
|
|
1526
|
-
marginBottom: "1.5rem",
|
|
1527
|
-
background: "#fff",
|
|
1528
|
-
border: "1px solid #eee",
|
|
1529
|
-
padding: "1rem",
|
|
1530
|
-
borderRadius: "6px"
|
|
1531
|
-
},
|
|
1532
|
-
children: [
|
|
1533
|
-
/* @__PURE__ */ jsxs(
|
|
1534
|
-
"div",
|
|
1535
|
-
{
|
|
1536
|
-
style: {
|
|
1537
|
-
display: "flex",
|
|
1538
|
-
justifyContent: "space-between",
|
|
1539
|
-
alignItems: "center",
|
|
1540
|
-
marginBottom: "0.5rem"
|
|
1541
|
-
},
|
|
1542
|
-
children: [
|
|
1543
|
-
/* @__PURE__ */ jsxs("label", { htmlFor: key, style: { fontWeight: 500 }, children: [
|
|
1544
|
-
key,
|
|
1545
|
-
/* @__PURE__ */ jsx(
|
|
1546
|
-
"span",
|
|
1547
|
-
{
|
|
1548
|
-
style: {
|
|
1549
|
-
marginLeft: "0.5rem",
|
|
1550
|
-
fontSize: "0.75rem",
|
|
1551
|
-
color: "#999",
|
|
1552
|
-
background: "#f0f0f0",
|
|
1553
|
-
padding: "0.1rem 0.4rem",
|
|
1554
|
-
borderRadius: "4px"
|
|
1555
|
-
},
|
|
1556
|
-
children: field.type
|
|
1557
|
-
}
|
|
1558
|
-
)
|
|
1559
|
-
] }),
|
|
1560
|
-
/* @__PURE__ */ jsx(
|
|
1561
|
-
"button",
|
|
1562
|
-
{
|
|
1563
|
-
onClick: () => removeField(key),
|
|
1564
|
-
style: {
|
|
1565
|
-
background: "none",
|
|
1566
|
-
border: "none",
|
|
1567
|
-
color: "#e57373",
|
|
1568
|
-
cursor: "pointer",
|
|
1569
|
-
fontSize: "0.875rem"
|
|
1570
|
-
},
|
|
1571
|
-
children: "\u2715 Remove"
|
|
1572
|
-
}
|
|
1573
|
-
)
|
|
1574
|
-
]
|
|
1575
|
-
}
|
|
1576
|
-
),
|
|
1577
|
-
renderField(key, field)
|
|
1578
|
-
]
|
|
1579
|
-
},
|
|
1580
|
-
key
|
|
1581
|
-
))
|
|
1582
|
-
] }),
|
|
1583
|
-
/* @__PURE__ */ jsxs(
|
|
1584
|
-
"div",
|
|
1585
|
-
{
|
|
1586
|
-
style: {
|
|
1587
|
-
marginTop: "3rem",
|
|
1588
|
-
paddingTop: "1rem",
|
|
1589
|
-
borderTop: "1px solid #eee"
|
|
1590
|
-
},
|
|
1591
|
-
children: [
|
|
1592
|
-
/* @__PURE__ */ jsx(
|
|
1593
|
-
"h3",
|
|
1594
|
-
{
|
|
1595
|
-
style: {
|
|
1596
|
-
fontSize: "1rem",
|
|
1597
|
-
marginBottom: "0.5rem",
|
|
1598
|
-
color: "#666"
|
|
1599
|
-
},
|
|
1600
|
-
children: "Quick File Upload"
|
|
1601
|
-
}
|
|
1602
|
-
),
|
|
1603
|
-
/* @__PURE__ */ jsxs("div", { style: { display: "flex", gap: "0.5rem" }, children: [
|
|
1604
|
-
/* @__PURE__ */ jsx(
|
|
1605
|
-
"input",
|
|
1606
|
-
{
|
|
1607
|
-
type: "file",
|
|
1608
|
-
onChange: handleFileUpload,
|
|
1609
|
-
disabled: uploading,
|
|
1610
|
-
style: { flex: 1 }
|
|
1611
|
-
}
|
|
1612
|
-
),
|
|
1613
|
-
uploading && /* @__PURE__ */ jsx("span", { style: { color: "#666" }, children: "Uploading..." })
|
|
1614
|
-
] })
|
|
1615
|
-
]
|
|
1616
|
-
}
|
|
1617
|
-
)
|
|
1618
|
-
] }) : /* @__PURE__ */ jsxs(
|
|
1619
|
-
"div",
|
|
1620
|
-
{
|
|
1621
|
-
style: {
|
|
1622
|
-
textAlign: "center",
|
|
1623
|
-
padding: "5rem 2rem",
|
|
1624
|
-
color: "#999"
|
|
1625
|
-
},
|
|
1626
|
-
children: [
|
|
1627
|
-
/* @__PURE__ */ jsx("div", { style: { fontSize: "3rem", marginBottom: "1rem" }, children: "\u{1F448}" }),
|
|
1628
|
-
/* @__PURE__ */ jsx("p", { style: { fontSize: "1.1rem" }, children: "Select a file from the sidebar to edit" }),
|
|
1629
|
-
/* @__PURE__ */ jsx("p", { children: "or create a new file to get started" })
|
|
1630
|
-
]
|
|
1631
|
-
}
|
|
1632
|
-
)
|
|
1272
|
+
htmlFor: "content",
|
|
1273
|
+
className: "block text-sm font-medium mb-3 text-slate-900",
|
|
1274
|
+
children: "Content (Markdown)"
|
|
1633
1275
|
}
|
|
1634
|
-
)
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1276
|
+
),
|
|
1277
|
+
renderField("content", fields["content"])
|
|
1278
|
+
] })
|
|
1279
|
+
] })
|
|
1280
|
+
] })
|
|
1281
|
+
] }) : /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center justify-center h-[500px] text-slate-500", children: [
|
|
1282
|
+
/* @__PURE__ */ jsx("div", { className: "text-4xl mb-4", children: "\u{1F4C4}" }),
|
|
1283
|
+
/* @__PURE__ */ jsx("p", { children: "Select a file to edit or create a new one." })
|
|
1284
|
+
] }) }) })
|
|
1285
|
+
] })
|
|
1286
|
+
] });
|
|
1641
1287
|
}
|
|
1642
1288
|
|
|
1643
1289
|
// src/ui/Login.tsx
|
|
@@ -1670,133 +1316,67 @@ function Login() {
|
|
|
1670
1316
|
setLoading(false);
|
|
1671
1317
|
}
|
|
1672
1318
|
};
|
|
1673
|
-
return /* @__PURE__ */ jsx2(
|
|
1674
|
-
"div",
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1319
|
+
return /* @__PURE__ */ jsx2("div", { className: "flex min-h-screen items-center justify-center bg-slate-50 p-4 font-sans text-slate-900", children: /* @__PURE__ */ jsxs2("div", { className: "w-full max-w-[350px] rounded-xl border border-slate-200 bg-white shadow-sm", children: [
|
|
1320
|
+
/* @__PURE__ */ jsxs2("div", { className: "flex flex-col space-y-1.5 p-6", children: [
|
|
1321
|
+
/* @__PURE__ */ jsx2("h1", { className: "text-2xl font-semibold leading-none tracking-tight", children: "Admin Login" }),
|
|
1322
|
+
/* @__PURE__ */ jsx2("p", { className: "text-sm text-slate-500", children: "Enter your credentials to access the CMS" })
|
|
1323
|
+
] }),
|
|
1324
|
+
/* @__PURE__ */ jsx2("div", { className: "p-6 pt-0", children: /* @__PURE__ */ jsxs2("form", { onSubmit: handleSubmit, className: "space-y-4", children: [
|
|
1325
|
+
/* @__PURE__ */ jsxs2("div", { className: "space-y-2", children: [
|
|
1326
|
+
/* @__PURE__ */ jsx2(
|
|
1327
|
+
"label",
|
|
1328
|
+
{
|
|
1329
|
+
htmlFor: "username",
|
|
1330
|
+
className: "text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70",
|
|
1331
|
+
children: "Username"
|
|
1332
|
+
}
|
|
1333
|
+
),
|
|
1334
|
+
/* @__PURE__ */ jsx2(
|
|
1335
|
+
"input",
|
|
1336
|
+
{
|
|
1337
|
+
id: "username",
|
|
1338
|
+
type: "text",
|
|
1339
|
+
value: username,
|
|
1340
|
+
onChange: (e) => setUsername(e.target.value),
|
|
1341
|
+
required: true,
|
|
1342
|
+
autoFocus: true,
|
|
1343
|
+
className: "flex h-9 w-full rounded-md border border-slate-200 bg-transparent px-3 py-1 text-sm shadow-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-slate-400 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-slate-950 disabled:cursor-not-allowed disabled:opacity-50"
|
|
1344
|
+
}
|
|
1345
|
+
)
|
|
1346
|
+
] }),
|
|
1347
|
+
/* @__PURE__ */ jsxs2("div", { className: "space-y-2", children: [
|
|
1348
|
+
/* @__PURE__ */ jsx2(
|
|
1349
|
+
"label",
|
|
1350
|
+
{
|
|
1351
|
+
htmlFor: "password",
|
|
1352
|
+
className: "text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70",
|
|
1353
|
+
children: "Password"
|
|
1354
|
+
}
|
|
1355
|
+
),
|
|
1356
|
+
/* @__PURE__ */ jsx2(
|
|
1357
|
+
"input",
|
|
1358
|
+
{
|
|
1359
|
+
id: "password",
|
|
1360
|
+
type: "password",
|
|
1361
|
+
value: password,
|
|
1362
|
+
onChange: (e) => setPassword(e.target.value),
|
|
1363
|
+
required: true,
|
|
1364
|
+
className: "flex h-9 w-full rounded-md border border-slate-200 bg-transparent px-3 py-1 text-sm shadow-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-slate-400 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-slate-950 disabled:cursor-not-allowed disabled:opacity-50"
|
|
1365
|
+
}
|
|
1366
|
+
)
|
|
1367
|
+
] }),
|
|
1368
|
+
error && /* @__PURE__ */ jsx2("div", { className: "rounded-md bg-red-50 p-3 text-sm text-red-500 border border-red-200", children: error }),
|
|
1369
|
+
/* @__PURE__ */ jsx2(
|
|
1370
|
+
"button",
|
|
1686
1371
|
{
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
background: "white",
|
|
1692
|
-
borderRadius: "8px",
|
|
1693
|
-
boxShadow: "0 4px 6px rgba(0,0,0,0.1)"
|
|
1694
|
-
},
|
|
1695
|
-
children: [
|
|
1696
|
-
/* @__PURE__ */ jsx2("h1", { style: { marginBottom: "0.5rem", textAlign: "center" }, children: "Admin Login" }),
|
|
1697
|
-
/* @__PURE__ */ jsx2("p", { style: { color: "#666", marginBottom: "2rem", textAlign: "center" }, children: "Enter your credentials to access the CMS" }),
|
|
1698
|
-
/* @__PURE__ */ jsxs2("form", { onSubmit: handleSubmit, children: [
|
|
1699
|
-
/* @__PURE__ */ jsxs2("div", { style: { marginBottom: "1rem" }, children: [
|
|
1700
|
-
/* @__PURE__ */ jsx2(
|
|
1701
|
-
"label",
|
|
1702
|
-
{
|
|
1703
|
-
htmlFor: "username",
|
|
1704
|
-
style: {
|
|
1705
|
-
display: "block",
|
|
1706
|
-
marginBottom: "0.5rem",
|
|
1707
|
-
fontWeight: 500
|
|
1708
|
-
},
|
|
1709
|
-
children: "Username"
|
|
1710
|
-
}
|
|
1711
|
-
),
|
|
1712
|
-
/* @__PURE__ */ jsx2(
|
|
1713
|
-
"input",
|
|
1714
|
-
{
|
|
1715
|
-
id: "username",
|
|
1716
|
-
type: "text",
|
|
1717
|
-
value: username,
|
|
1718
|
-
onChange: (e) => setUsername(e.target.value),
|
|
1719
|
-
required: true,
|
|
1720
|
-
autoFocus: true,
|
|
1721
|
-
style: {
|
|
1722
|
-
width: "100%",
|
|
1723
|
-
padding: "0.75rem",
|
|
1724
|
-
border: "1px solid #ddd",
|
|
1725
|
-
borderRadius: "4px"
|
|
1726
|
-
}
|
|
1727
|
-
}
|
|
1728
|
-
)
|
|
1729
|
-
] }),
|
|
1730
|
-
/* @__PURE__ */ jsxs2("div", { style: { marginBottom: "1.5rem" }, children: [
|
|
1731
|
-
/* @__PURE__ */ jsx2(
|
|
1732
|
-
"label",
|
|
1733
|
-
{
|
|
1734
|
-
htmlFor: "password",
|
|
1735
|
-
style: {
|
|
1736
|
-
display: "block",
|
|
1737
|
-
marginBottom: "0.5rem",
|
|
1738
|
-
fontWeight: 500
|
|
1739
|
-
},
|
|
1740
|
-
children: "Password"
|
|
1741
|
-
}
|
|
1742
|
-
),
|
|
1743
|
-
/* @__PURE__ */ jsx2(
|
|
1744
|
-
"input",
|
|
1745
|
-
{
|
|
1746
|
-
id: "password",
|
|
1747
|
-
type: "password",
|
|
1748
|
-
value: password,
|
|
1749
|
-
onChange: (e) => setPassword(e.target.value),
|
|
1750
|
-
required: true,
|
|
1751
|
-
style: {
|
|
1752
|
-
width: "100%",
|
|
1753
|
-
padding: "0.75rem",
|
|
1754
|
-
border: "1px solid #ddd",
|
|
1755
|
-
borderRadius: "4px"
|
|
1756
|
-
}
|
|
1757
|
-
}
|
|
1758
|
-
)
|
|
1759
|
-
] }),
|
|
1760
|
-
error && /* @__PURE__ */ jsx2(
|
|
1761
|
-
"div",
|
|
1762
|
-
{
|
|
1763
|
-
style: {
|
|
1764
|
-
marginBottom: "1rem",
|
|
1765
|
-
padding: "0.75rem",
|
|
1766
|
-
background: "#ffe6e6",
|
|
1767
|
-
color: "#d32f2f",
|
|
1768
|
-
borderRadius: "4px",
|
|
1769
|
-
fontSize: "0.875rem"
|
|
1770
|
-
},
|
|
1771
|
-
children: error
|
|
1772
|
-
}
|
|
1773
|
-
),
|
|
1774
|
-
/* @__PURE__ */ jsx2(
|
|
1775
|
-
"button",
|
|
1776
|
-
{
|
|
1777
|
-
type: "submit",
|
|
1778
|
-
disabled: loading,
|
|
1779
|
-
style: {
|
|
1780
|
-
width: "100%",
|
|
1781
|
-
padding: "0.75rem",
|
|
1782
|
-
background: "#0070f3",
|
|
1783
|
-
color: "white",
|
|
1784
|
-
border: "none",
|
|
1785
|
-
borderRadius: "4px",
|
|
1786
|
-
fontSize: "1rem",
|
|
1787
|
-
fontWeight: 500,
|
|
1788
|
-
cursor: "pointer",
|
|
1789
|
-
opacity: loading ? 0.7 : 1
|
|
1790
|
-
},
|
|
1791
|
-
children: loading ? "Logging in..." : "Login"
|
|
1792
|
-
}
|
|
1793
|
-
)
|
|
1794
|
-
] })
|
|
1795
|
-
]
|
|
1372
|
+
type: "submit",
|
|
1373
|
+
disabled: loading,
|
|
1374
|
+
className: "inline-flex h-9 w-full items-center justify-center whitespace-nowrap rounded-md bg-slate-900 px-4 py-2 text-sm font-medium text-slate-50 shadow transition-colors hover:bg-slate-900/90 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-slate-950 disabled:pointer-events-none disabled:opacity-50",
|
|
1375
|
+
children: loading ? "Logging in..." : "Login"
|
|
1796
1376
|
}
|
|
1797
1377
|
)
|
|
1798
|
-
}
|
|
1799
|
-
);
|
|
1378
|
+
] }) })
|
|
1379
|
+
] }) });
|
|
1800
1380
|
}
|
|
1801
1381
|
|
|
1802
1382
|
// src/middleware/auth.ts
|
|
@@ -2080,20 +1660,48 @@ export const config = {
|
|
|
2080
1660
|
);
|
|
2081
1661
|
console.log("\u2705 Created middleware.ts");
|
|
2082
1662
|
}
|
|
2083
|
-
|
|
2084
|
-
await
|
|
2085
|
-
|
|
2086
|
-
|
|
1663
|
+
console.log("\n\u2699\uFE0F Configuration");
|
|
1664
|
+
const rl = await import("readline");
|
|
1665
|
+
const askQuestion = (query) => {
|
|
1666
|
+
const interface_ = rl.createInterface({
|
|
1667
|
+
input: process.stdin,
|
|
1668
|
+
output: process.stdout
|
|
1669
|
+
});
|
|
1670
|
+
return new Promise((resolve) => {
|
|
1671
|
+
interface_.question(query, (ans) => {
|
|
1672
|
+
interface_.close();
|
|
1673
|
+
resolve(ans);
|
|
1674
|
+
});
|
|
1675
|
+
});
|
|
1676
|
+
};
|
|
1677
|
+
const storageChoice = await askQuestion(
|
|
1678
|
+
"Select production storage provider:\n 1. GitHub (default)\n 2. S3 / Cloudflare R2 / Vercel Blob\nEnter choice [1]: "
|
|
1679
|
+
);
|
|
1680
|
+
const isS3 = storageChoice.trim() === "2";
|
|
1681
|
+
let envContent = `CMS_ADMIN_USERNAME=admin
|
|
2087
1682
|
CMS_ADMIN_PASSWORD=password
|
|
2088
1683
|
CMS_SESSION_SECRET=ensure_this_is_at_least_32_chars_long_random_string
|
|
2089
1684
|
|
|
2090
|
-
|
|
1685
|
+
`;
|
|
1686
|
+
if (isS3) {
|
|
1687
|
+
envContent += `# S3 / Cloudflare R2 / Vercel Blob Storage
|
|
1688
|
+
STORAGE_BUCKET=my-bucket
|
|
1689
|
+
STORAGE_ENDPOINT=https://<accountid>.r2.cloudflarestorage.com
|
|
1690
|
+
STORAGE_ACCESS_KEY_ID=
|
|
1691
|
+
STORAGE_SECRET_ACCESS_KEY=
|
|
1692
|
+
STORAGE_REGION=auto
|
|
1693
|
+
STORAGE_PUBLIC_URL=https://pub-<id>.r2.dev
|
|
1694
|
+
`;
|
|
1695
|
+
} else {
|
|
1696
|
+
envContent += `# GitHub Storage (Production)
|
|
1697
|
+
# Generate at https://github.com/settings/tokens (Needs 'repo' or 'contents:write' scope)
|
|
2091
1698
|
GITHUB_TOKEN=
|
|
2092
1699
|
GITHUB_REPO=owner/repo
|
|
2093
1700
|
GITHUB_BRANCH=main
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
);
|
|
1701
|
+
`;
|
|
1702
|
+
}
|
|
1703
|
+
const envExamplePath = path3.join(process.cwd(), ".env.local.example");
|
|
1704
|
+
await fs2.writeFile(envExamplePath, envContent, "utf-8");
|
|
2097
1705
|
console.log("");
|
|
2098
1706
|
console.log("\u{1F389} CMS initialized successfully!");
|
|
2099
1707
|
console.log(
|