@lodashventure/medusa-banner 1.3.12 → 1.4.0
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/.medusa/server/src/admin/index.js +281 -57
- package/.medusa/server/src/admin/index.mjs +284 -60
- package/.medusa/server/src/api/admin/banners/reorder/route.js +2 -1
- package/.medusa/server/src/api/admin/banners/route.js +8 -3
- package/.medusa/server/src/api/admin/banners/update-link/route.js +19 -0
- package/.medusa/server/src/api/store/banners/route.js +2 -1
- package/.medusa/server/src/modules/banner/migrations/Migration20251024160000.js +14 -0
- package/.medusa/server/src/modules/banner/models/banner.js +2 -1
- package/package.json +1 -1
|
@@ -2,12 +2,12 @@
|
|
|
2
2
|
const jsxRuntime = require("react/jsx-runtime");
|
|
3
3
|
const adminSdk = require("@medusajs/admin-sdk");
|
|
4
4
|
const icons = require("@medusajs/icons");
|
|
5
|
-
const Medusa = require("@medusajs/js-sdk");
|
|
6
5
|
const core = require("@dnd-kit/core");
|
|
7
6
|
const sortable = require("@dnd-kit/sortable");
|
|
8
7
|
const ui = require("@medusajs/ui");
|
|
9
8
|
const lucideReact = require("lucide-react");
|
|
10
9
|
const react = require("react");
|
|
10
|
+
const Medusa = require("@medusajs/js-sdk");
|
|
11
11
|
const reactQuery = require("@tanstack/react-query");
|
|
12
12
|
const utilities = require("@dnd-kit/utilities");
|
|
13
13
|
const reactDropzone = require("react-dropzone");
|
|
@@ -36,7 +36,7 @@ const useBanners = () => {
|
|
|
36
36
|
});
|
|
37
37
|
};
|
|
38
38
|
const DraggableItem = ({ banner }) => {
|
|
39
|
-
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-lg shadow-md border border-gray-200 opacity-80 scale-105", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
39
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-lg shadow-md border border-gray-200 dark:border-gray-700 opacity-80 scale-105 bg-white dark:bg-gray-800", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
40
40
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
41
41
|
"img",
|
|
42
42
|
{
|
|
@@ -45,22 +45,129 @@ const DraggableItem = ({ banner }) => {
|
|
|
45
45
|
className: "object-cover w-full h-48 rounded-t-lg"
|
|
46
46
|
}
|
|
47
47
|
),
|
|
48
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-2 text-sm truncate", children: banner.id })
|
|
48
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-2 text-sm truncate text-gray-900 dark:text-gray-100 bg-white dark:bg-gray-800", children: banner.id })
|
|
49
49
|
] }) });
|
|
50
50
|
};
|
|
51
|
+
const EditBannerLinkDrawerContent = ({
|
|
52
|
+
banner,
|
|
53
|
+
onSuccess,
|
|
54
|
+
onCancel
|
|
55
|
+
}) => {
|
|
56
|
+
const [link, setLink] = react.useState(banner.link || "");
|
|
57
|
+
const [isLoading, setIsLoading] = react.useState(false);
|
|
58
|
+
const handleSave = async () => {
|
|
59
|
+
setIsLoading(true);
|
|
60
|
+
try {
|
|
61
|
+
const response = await fetch("/admin/banners/update-link", {
|
|
62
|
+
method: "POST",
|
|
63
|
+
headers: {
|
|
64
|
+
"Content-Type": "application/json"
|
|
65
|
+
},
|
|
66
|
+
credentials: "include",
|
|
67
|
+
body: JSON.stringify({
|
|
68
|
+
id: banner.id,
|
|
69
|
+
link: link.trim() || null
|
|
70
|
+
})
|
|
71
|
+
});
|
|
72
|
+
if (!response.ok) {
|
|
73
|
+
const errorData = await response.json();
|
|
74
|
+
throw new Error(errorData.message || "Failed to update link");
|
|
75
|
+
}
|
|
76
|
+
onSuccess();
|
|
77
|
+
} catch (error) {
|
|
78
|
+
console.error(error);
|
|
79
|
+
alert(
|
|
80
|
+
`Error updating link: ${error instanceof Error ? error.message : "Unknown error"}`
|
|
81
|
+
);
|
|
82
|
+
} finally {
|
|
83
|
+
setIsLoading(false);
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-6", children: [
|
|
87
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-lg border overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
88
|
+
"img",
|
|
89
|
+
{
|
|
90
|
+
src: banner.url,
|
|
91
|
+
alt: `Banner ${banner.id}`,
|
|
92
|
+
className: "w-full h-48 object-cover"
|
|
93
|
+
}
|
|
94
|
+
) }),
|
|
95
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-3", children: [
|
|
96
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
97
|
+
ui.Label,
|
|
98
|
+
{
|
|
99
|
+
htmlFor: "banner-link",
|
|
100
|
+
className: "text-sm font-medium flex items-center gap-2",
|
|
101
|
+
children: [
|
|
102
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Link, { className: "h-4 w-4" }),
|
|
103
|
+
"Click URL"
|
|
104
|
+
]
|
|
105
|
+
}
|
|
106
|
+
),
|
|
107
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
108
|
+
ui.Input,
|
|
109
|
+
{
|
|
110
|
+
id: "banner-link",
|
|
111
|
+
type: "url",
|
|
112
|
+
placeholder: "https://example.com",
|
|
113
|
+
value: link,
|
|
114
|
+
onChange: (e) => setLink(e.target.value),
|
|
115
|
+
disabled: isLoading,
|
|
116
|
+
className: "w-full"
|
|
117
|
+
}
|
|
118
|
+
),
|
|
119
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground", children: "Add a URL where users will be redirected when clicking this banner. Leave empty to remove the link." })
|
|
120
|
+
] }),
|
|
121
|
+
banner.link && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-3 bg-muted/50 rounded-lg", children: [
|
|
122
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground mb-1", children: "Current link:" }),
|
|
123
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
124
|
+
"a",
|
|
125
|
+
{
|
|
126
|
+
href: banner.link,
|
|
127
|
+
target: "_blank",
|
|
128
|
+
rel: "noopener noreferrer",
|
|
129
|
+
className: "text-sm text-primary hover:underline break-all",
|
|
130
|
+
children: banner.link
|
|
131
|
+
}
|
|
132
|
+
)
|
|
133
|
+
] }),
|
|
134
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-3 justify-end", children: [
|
|
135
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
136
|
+
ui.Button,
|
|
137
|
+
{
|
|
138
|
+
variant: "secondary",
|
|
139
|
+
onClick: onCancel,
|
|
140
|
+
disabled: isLoading,
|
|
141
|
+
children: "Cancel"
|
|
142
|
+
}
|
|
143
|
+
),
|
|
144
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
145
|
+
ui.Button,
|
|
146
|
+
{
|
|
147
|
+
variant: "primary",
|
|
148
|
+
onClick: handleSave,
|
|
149
|
+
isLoading,
|
|
150
|
+
children: "Save Link"
|
|
151
|
+
}
|
|
152
|
+
)
|
|
153
|
+
] })
|
|
154
|
+
] });
|
|
155
|
+
};
|
|
51
156
|
const GridItem = ({
|
|
52
157
|
banner,
|
|
53
158
|
isSelected,
|
|
54
159
|
onClick,
|
|
55
|
-
onSelect
|
|
160
|
+
onSelect,
|
|
161
|
+
onEditLink
|
|
56
162
|
}) => {
|
|
57
163
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
58
164
|
"div",
|
|
59
165
|
{
|
|
60
166
|
className: `
|
|
61
|
-
relative overflow-hidden rounded-lg shadow-md cursor-pointer hover:shadow-lg
|
|
167
|
+
relative overflow-hidden rounded-lg shadow-md cursor-pointer hover:shadow-lg
|
|
62
168
|
transition-all duration-200 ease-in-out
|
|
63
|
-
|
|
169
|
+
bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700
|
|
170
|
+
${isSelected ? "ring-2 ring-offset-2 ring-blue-500 dark:ring-offset-gray-900" : ""}
|
|
64
171
|
`,
|
|
65
172
|
onClick,
|
|
66
173
|
children: [
|
|
@@ -73,21 +180,33 @@ const GridItem = ({
|
|
|
73
180
|
className: "object-cover w-full h-48"
|
|
74
181
|
}
|
|
75
182
|
),
|
|
76
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "truncate
|
|
183
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-2 flex items-center justify-between gap-2 bg-white dark:bg-gray-800", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "truncate text-sm flex items-center gap-2 text-gray-900 dark:text-gray-100", children: [
|
|
184
|
+
banner.link && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Link, { className: "h-3 w-3 text-blue-500 dark:text-blue-400 flex-shrink-0" }),
|
|
185
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children: banner.id })
|
|
186
|
+
] }) })
|
|
77
187
|
] }),
|
|
78
188
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
79
189
|
"div",
|
|
80
190
|
{
|
|
81
191
|
className: `
|
|
82
192
|
absolute top-2 left-2 w-6 h-6 rounded-md flex items-center justify-center
|
|
83
|
-
${isSelected ? "bg-blue-500 text-white" : "bg-white/
|
|
193
|
+
${isSelected ? "bg-blue-500 text-white" : "bg-white/90 dark:bg-gray-800/90 border border-gray-300 dark:border-gray-600"}
|
|
84
194
|
${isSelected ? "visible" : "invisible group-hover:visible"}
|
|
85
195
|
transition-opacity duration-200
|
|
86
196
|
`,
|
|
87
197
|
onClick: onSelect,
|
|
88
198
|
children: isSelected && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { className: "h-4 w-4" })
|
|
89
199
|
}
|
|
90
|
-
)
|
|
200
|
+
),
|
|
201
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute top-2 right-2 invisible group-hover:visible", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
202
|
+
ui.Button,
|
|
203
|
+
{
|
|
204
|
+
variant: "secondary",
|
|
205
|
+
className: "size-8 rounded-md p-0 bg-white/90 dark:bg-gray-800/90 hover:bg-white dark:hover:bg-gray-700 border border-gray-200 dark:border-gray-600",
|
|
206
|
+
onClick: onEditLink,
|
|
207
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Edit, { className: "h-4 w-4 text-gray-700 dark:text-gray-300" })
|
|
208
|
+
}
|
|
209
|
+
) })
|
|
91
210
|
]
|
|
92
211
|
}
|
|
93
212
|
);
|
|
@@ -112,7 +231,7 @@ const SortableItem = ({ banner }) => {
|
|
|
112
231
|
{
|
|
113
232
|
ref: setNodeRef,
|
|
114
233
|
style,
|
|
115
|
-
className: "rounded-lg shadow-md border border-gray-200 hover:border-gray-300 transition-all relative",
|
|
234
|
+
className: "rounded-lg shadow-md border border-gray-200 dark:border-gray-700 hover:border-gray-300 dark:hover:border-gray-600 transition-all relative bg-white dark:bg-gray-800",
|
|
116
235
|
...attributes,
|
|
117
236
|
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { ...listeners, children: [
|
|
118
237
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -123,11 +242,24 @@ const SortableItem = ({ banner }) => {
|
|
|
123
242
|
className: "object-cover w-full h-48 rounded-t-lg"
|
|
124
243
|
}
|
|
125
244
|
),
|
|
126
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-2 text-sm truncate", children: banner.id })
|
|
245
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-2 text-sm truncate text-gray-900 dark:text-gray-100 bg-white dark:bg-gray-800", children: banner.id })
|
|
127
246
|
] })
|
|
128
247
|
}
|
|
129
248
|
);
|
|
130
249
|
};
|
|
250
|
+
function r(e) {
|
|
251
|
+
var t, f, n = "";
|
|
252
|
+
if ("string" == typeof e || "number" == typeof e) n += e;
|
|
253
|
+
else if ("object" == typeof e) if (Array.isArray(e)) {
|
|
254
|
+
var o = e.length;
|
|
255
|
+
for (t = 0; t < o; t++) e[t] && (f = r(e[t])) && (n && (n += " "), n += f);
|
|
256
|
+
} else for (f in e) e[f] && (n && (n += " "), n += f);
|
|
257
|
+
return n;
|
|
258
|
+
}
|
|
259
|
+
function clsx() {
|
|
260
|
+
for (var e, t, f = 0, n = "", o = arguments.length; f < o; f++) (e = arguments[f]) && (t = r(e)) && (n && (n += " "), n += t);
|
|
261
|
+
return n;
|
|
262
|
+
}
|
|
131
263
|
const UploadBannerDrawerContent = ({
|
|
132
264
|
maxFileSizeMb = 10,
|
|
133
265
|
onSuccess
|
|
@@ -144,7 +276,8 @@ const UploadBannerDrawerContent = ({
|
|
|
144
276
|
return {
|
|
145
277
|
file,
|
|
146
278
|
id,
|
|
147
|
-
preview
|
|
279
|
+
preview,
|
|
280
|
+
link: ""
|
|
148
281
|
};
|
|
149
282
|
});
|
|
150
283
|
setFiles((prev) => [...prev, ...newFiles]);
|
|
@@ -158,6 +291,9 @@ const UploadBannerDrawerContent = ({
|
|
|
158
291
|
return files2.filter((f) => f.id !== id);
|
|
159
292
|
});
|
|
160
293
|
};
|
|
294
|
+
const updateFileLink = (id, link) => {
|
|
295
|
+
setFiles((files2) => files2.map((f) => f.id === id ? { ...f, link } : f));
|
|
296
|
+
};
|
|
161
297
|
const handleResetFiles = () => {
|
|
162
298
|
setFiles([]);
|
|
163
299
|
};
|
|
@@ -171,14 +307,39 @@ const UploadBannerDrawerContent = ({
|
|
|
171
307
|
}
|
|
172
308
|
formData.append("files", file.file);
|
|
173
309
|
});
|
|
174
|
-
const response = await
|
|
175
|
-
"
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
310
|
+
const response = await fetch("/admin/banners", {
|
|
311
|
+
method: "POST",
|
|
312
|
+
body: formData,
|
|
313
|
+
credentials: "include"
|
|
314
|
+
});
|
|
315
|
+
if (!response.ok) {
|
|
316
|
+
const errorData = await response.json();
|
|
317
|
+
throw new Error(errorData.message || "Upload failed");
|
|
318
|
+
}
|
|
319
|
+
const data = await response.json();
|
|
320
|
+
const uploadedFiles = data.files;
|
|
321
|
+
const updatePromises = uploadedFiles.map(
|
|
322
|
+
async (uploadedFile, index) => {
|
|
323
|
+
var _a;
|
|
324
|
+
const fileLink = (_a = files[index]) == null ? void 0 : _a.link;
|
|
325
|
+
if (fileLink && fileLink.trim()) {
|
|
326
|
+
await fetch("/admin/banners/update-link", {
|
|
327
|
+
method: "POST",
|
|
328
|
+
headers: {
|
|
329
|
+
"Content-Type": "application/json"
|
|
330
|
+
},
|
|
331
|
+
credentials: "include",
|
|
332
|
+
body: JSON.stringify({
|
|
333
|
+
id: uploadedFile.id,
|
|
334
|
+
link: fileLink.trim()
|
|
335
|
+
})
|
|
336
|
+
});
|
|
337
|
+
}
|
|
338
|
+
return uploadedFile;
|
|
179
339
|
}
|
|
180
340
|
);
|
|
181
|
-
|
|
341
|
+
await Promise.all(updatePromises);
|
|
342
|
+
setFiles([]);
|
|
182
343
|
onSuccess(uploadedFiles);
|
|
183
344
|
return {
|
|
184
345
|
files,
|
|
@@ -186,7 +347,9 @@ const UploadBannerDrawerContent = ({
|
|
|
186
347
|
};
|
|
187
348
|
} catch (error) {
|
|
188
349
|
console.error(error);
|
|
189
|
-
alert(
|
|
350
|
+
alert(
|
|
351
|
+
`Error uploading files: ${error instanceof Error ? error.message : "Unknown error"}`
|
|
352
|
+
);
|
|
190
353
|
} finally {
|
|
191
354
|
setIsLoading(false);
|
|
192
355
|
}
|
|
@@ -204,14 +367,13 @@ const UploadBannerDrawerContent = ({
|
|
|
204
367
|
"image/*": []
|
|
205
368
|
},
|
|
206
369
|
maxSize: maxFileSizeMb * 1024 * 1024
|
|
207
|
-
// maxFileSizeMb
|
|
208
370
|
});
|
|
209
371
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-6", children: [
|
|
210
372
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
211
373
|
"div",
|
|
212
374
|
{
|
|
213
375
|
...getRootProps(),
|
|
214
|
-
className:
|
|
376
|
+
className: clsx(
|
|
215
377
|
"border-2 border-dashed rounded-xl p-10 transition-all duration-150 ease-in-out cursor-pointer",
|
|
216
378
|
"flex flex-col items-center justify-center gap-4",
|
|
217
379
|
isDragActive ? "bg-primary/5 border-primary/50" : "bg-background hover:bg-muted/50",
|
|
@@ -242,7 +404,7 @@ const UploadBannerDrawerContent = ({
|
|
|
242
404
|
),
|
|
243
405
|
files.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-4", children: [
|
|
244
406
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
|
|
245
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "
|
|
407
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-4", children: [
|
|
246
408
|
/* @__PURE__ */ jsxRuntime.jsxs("h3", { className: "text-lg font-medium", children: [
|
|
247
409
|
"Selected Files (",
|
|
248
410
|
files.length,
|
|
@@ -268,48 +430,73 @@ const UploadBannerDrawerContent = ({
|
|
|
268
430
|
}
|
|
269
431
|
)
|
|
270
432
|
] }),
|
|
271
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid gap-
|
|
433
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid gap-6 grid-cols-1", children: files.map((fileItem) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
272
434
|
"div",
|
|
273
435
|
{
|
|
274
|
-
className: "
|
|
275
|
-
children: [
|
|
276
|
-
fileItem.preview ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "
|
|
436
|
+
className: "rounded-lg border bg-card text-card-foreground shadow-sm overflow-hidden",
|
|
437
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-4 p-4", children: [
|
|
438
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-shrink-0", children: fileItem.preview ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-32 h-32 overflow-hidden rounded-lg", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
277
439
|
"img",
|
|
278
440
|
{
|
|
279
441
|
src: fileItem.preview || "/placeholder.svg",
|
|
280
442
|
alt: fileItem.file.name,
|
|
281
|
-
className: "
|
|
443
|
+
className: "w-full h-full object-cover"
|
|
282
444
|
}
|
|
283
|
-
) }) : /* @__PURE__ */ jsxRuntime.
|
|
284
|
-
|
|
285
|
-
"
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
445
|
+
) }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-32 h-32 flex items-center justify-center bg-muted/50 rounded-lg", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ImageIcon, { className: "h-8 w-8 text-primary" }) }) }),
|
|
446
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 space-y-3", children: [
|
|
447
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start justify-between", children: [
|
|
448
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1", children: [
|
|
449
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-medium", children: fileItem.file.name }),
|
|
450
|
+
/* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-xs text-muted-foreground", children: [
|
|
451
|
+
(fileItem.file.size / 1024).toFixed(1),
|
|
452
|
+
" KB"
|
|
453
|
+
] })
|
|
454
|
+
] }),
|
|
455
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
456
|
+
ui.Button,
|
|
457
|
+
{
|
|
458
|
+
isLoading,
|
|
459
|
+
variant: "secondary",
|
|
460
|
+
className: "size-8 rounded-full p-0.5 text-red-400",
|
|
461
|
+
onClick: (e) => {
|
|
462
|
+
e.stopPropagation();
|
|
463
|
+
removeFile(fileItem.id);
|
|
464
|
+
},
|
|
465
|
+
children: [
|
|
466
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Trash, { className: "h-4 w-4" }),
|
|
467
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: "Remove file" })
|
|
468
|
+
]
|
|
469
|
+
}
|
|
470
|
+
)
|
|
294
471
|
] }),
|
|
295
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
472
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
|
|
473
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
474
|
+
ui.Label,
|
|
475
|
+
{
|
|
476
|
+
htmlFor: `link-${fileItem.id}`,
|
|
477
|
+
className: "text-sm font-medium flex items-center gap-2",
|
|
478
|
+
children: [
|
|
479
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Link, { className: "h-4 w-4" }),
|
|
480
|
+
"Click URL (optional)"
|
|
481
|
+
]
|
|
482
|
+
}
|
|
483
|
+
),
|
|
484
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
485
|
+
ui.Input,
|
|
486
|
+
{
|
|
487
|
+
id: `link-${fileItem.id}`,
|
|
488
|
+
type: "url",
|
|
489
|
+
placeholder: "https://example.com",
|
|
490
|
+
value: fileItem.link || "",
|
|
491
|
+
onChange: (e) => updateFileLink(fileItem.id, e.target.value),
|
|
492
|
+
disabled: isLoading,
|
|
493
|
+
className: "w-full"
|
|
494
|
+
}
|
|
495
|
+
),
|
|
496
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground", children: "Add a URL where users will be redirected when clicking this banner" })
|
|
497
|
+
] })
|
|
498
|
+
] })
|
|
499
|
+
] })
|
|
313
500
|
},
|
|
314
501
|
fileItem.id
|
|
315
502
|
)) })
|
|
@@ -318,6 +505,8 @@ const UploadBannerDrawerContent = ({
|
|
|
318
505
|
};
|
|
319
506
|
const BannerPage = () => {
|
|
320
507
|
const [open, setOpen] = react.useState(false);
|
|
508
|
+
const [editLinkOpen, setEditLinkOpen] = react.useState(false);
|
|
509
|
+
const [selectedBannerForEdit, setSelectedBannerForEdit] = react.useState(null);
|
|
321
510
|
const [selectedImage, setSelectedImage] = react.useState(null);
|
|
322
511
|
const [selectedIds, setSelectedIds] = react.useState(/* @__PURE__ */ new Set());
|
|
323
512
|
const [reorderMode, setReorderMode] = react.useState(false);
|
|
@@ -361,6 +550,15 @@ const BannerPage = () => {
|
|
|
361
550
|
const closeLightbox = () => {
|
|
362
551
|
setSelectedImage(null);
|
|
363
552
|
};
|
|
553
|
+
const openEditLinkDrawer = (e, banner) => {
|
|
554
|
+
e.stopPropagation();
|
|
555
|
+
setSelectedBannerForEdit(banner);
|
|
556
|
+
setEditLinkOpen(true);
|
|
557
|
+
};
|
|
558
|
+
const closeEditLinkDrawer = () => {
|
|
559
|
+
setEditLinkOpen(false);
|
|
560
|
+
setSelectedBannerForEdit(null);
|
|
561
|
+
};
|
|
364
562
|
const toggleReorderMode = async () => {
|
|
365
563
|
if (reorderMode) {
|
|
366
564
|
const confirmed = await dialog({
|
|
@@ -484,6 +682,31 @@ const BannerPage = () => {
|
|
|
484
682
|
}
|
|
485
683
|
)
|
|
486
684
|
] }),
|
|
685
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
686
|
+
ui.Drawer,
|
|
687
|
+
{
|
|
688
|
+
open: editLinkOpen,
|
|
689
|
+
onOpenChange: (openChanged) => {
|
|
690
|
+
if (!openChanged) {
|
|
691
|
+
closeEditLinkDrawer();
|
|
692
|
+
}
|
|
693
|
+
},
|
|
694
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Drawer.Content, { children: [
|
|
695
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Drawer.Header, { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Drawer.Title, { children: "Edit Banner Link" }) }),
|
|
696
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Drawer.Body, { children: selectedBannerForEdit && /* @__PURE__ */ jsxRuntime.jsx(
|
|
697
|
+
EditBannerLinkDrawerContent,
|
|
698
|
+
{
|
|
699
|
+
banner: selectedBannerForEdit,
|
|
700
|
+
onSuccess: () => {
|
|
701
|
+
closeEditLinkDrawer();
|
|
702
|
+
refetch();
|
|
703
|
+
},
|
|
704
|
+
onCancel: closeEditLinkDrawer
|
|
705
|
+
}
|
|
706
|
+
) })
|
|
707
|
+
] })
|
|
708
|
+
}
|
|
709
|
+
),
|
|
487
710
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "container mx-auto px-4 py-8", children: [
|
|
488
711
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-between items-center mb-6", children: [
|
|
489
712
|
selectedIds.size > 0 && !reorderMode && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex gap-2", children: /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
@@ -574,7 +797,8 @@ const BannerPage = () => {
|
|
|
574
797
|
banner,
|
|
575
798
|
isSelected: selectedIds.has(banner.id),
|
|
576
799
|
onClick: () => openLightbox(banner),
|
|
577
|
-
onSelect: (e) => toggleImageSelection(e, banner.id)
|
|
800
|
+
onSelect: (e) => toggleImageSelection(e, banner.id),
|
|
801
|
+
onEditLink: (e) => openEditLinkDrawer(e, banner)
|
|
578
802
|
},
|
|
579
803
|
banner.id
|
|
580
804
|
)) }),
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { jsx, jsxs, Fragment } from "react/jsx-runtime";
|
|
2
2
|
import { defineRouteConfig } from "@medusajs/admin-sdk";
|
|
3
|
-
import {
|
|
4
|
-
import Medusa from "@medusajs/js-sdk";
|
|
3
|
+
import { StackPerspective } from "@medusajs/icons";
|
|
5
4
|
import { useSensors, useSensor, PointerSensor, KeyboardSensor, DndContext, closestCenter, DragOverlay } from "@dnd-kit/core";
|
|
6
5
|
import { useSortable, sortableKeyboardCoordinates, SortableContext, rectSortingStrategy, arrayMove } from "@dnd-kit/sortable";
|
|
7
|
-
import {
|
|
8
|
-
import { Check, Upload, ImageIcon, Trash2, MoveHorizontal, X } from "lucide-react";
|
|
6
|
+
import { Label, Input, Button, usePrompt, Drawer } from "@medusajs/ui";
|
|
7
|
+
import { Link, Check, Edit, Upload, ImageIcon, Trash, Trash2, MoveHorizontal, X } from "lucide-react";
|
|
9
8
|
import { useState, useCallback } from "react";
|
|
9
|
+
import Medusa from "@medusajs/js-sdk";
|
|
10
10
|
import { useQuery } from "@tanstack/react-query";
|
|
11
11
|
import { CSS } from "@dnd-kit/utilities";
|
|
12
12
|
import { useDropzone } from "react-dropzone";
|
|
@@ -33,7 +33,7 @@ const useBanners = () => {
|
|
|
33
33
|
});
|
|
34
34
|
};
|
|
35
35
|
const DraggableItem = ({ banner }) => {
|
|
36
|
-
return /* @__PURE__ */ jsx("div", { className: "rounded-lg shadow-md border border-gray-200 opacity-80 scale-105", children: /* @__PURE__ */ jsxs("div", { children: [
|
|
36
|
+
return /* @__PURE__ */ jsx("div", { className: "rounded-lg shadow-md border border-gray-200 dark:border-gray-700 opacity-80 scale-105 bg-white dark:bg-gray-800", children: /* @__PURE__ */ jsxs("div", { children: [
|
|
37
37
|
/* @__PURE__ */ jsx(
|
|
38
38
|
"img",
|
|
39
39
|
{
|
|
@@ -42,22 +42,129 @@ const DraggableItem = ({ banner }) => {
|
|
|
42
42
|
className: "object-cover w-full h-48 rounded-t-lg"
|
|
43
43
|
}
|
|
44
44
|
),
|
|
45
|
-
/* @__PURE__ */ jsx("div", { className: "p-2 text-sm truncate", children: banner.id })
|
|
45
|
+
/* @__PURE__ */ jsx("div", { className: "p-2 text-sm truncate text-gray-900 dark:text-gray-100 bg-white dark:bg-gray-800", children: banner.id })
|
|
46
46
|
] }) });
|
|
47
47
|
};
|
|
48
|
+
const EditBannerLinkDrawerContent = ({
|
|
49
|
+
banner,
|
|
50
|
+
onSuccess,
|
|
51
|
+
onCancel
|
|
52
|
+
}) => {
|
|
53
|
+
const [link, setLink] = useState(banner.link || "");
|
|
54
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
55
|
+
const handleSave = async () => {
|
|
56
|
+
setIsLoading(true);
|
|
57
|
+
try {
|
|
58
|
+
const response = await fetch("/admin/banners/update-link", {
|
|
59
|
+
method: "POST",
|
|
60
|
+
headers: {
|
|
61
|
+
"Content-Type": "application/json"
|
|
62
|
+
},
|
|
63
|
+
credentials: "include",
|
|
64
|
+
body: JSON.stringify({
|
|
65
|
+
id: banner.id,
|
|
66
|
+
link: link.trim() || null
|
|
67
|
+
})
|
|
68
|
+
});
|
|
69
|
+
if (!response.ok) {
|
|
70
|
+
const errorData = await response.json();
|
|
71
|
+
throw new Error(errorData.message || "Failed to update link");
|
|
72
|
+
}
|
|
73
|
+
onSuccess();
|
|
74
|
+
} catch (error) {
|
|
75
|
+
console.error(error);
|
|
76
|
+
alert(
|
|
77
|
+
`Error updating link: ${error instanceof Error ? error.message : "Unknown error"}`
|
|
78
|
+
);
|
|
79
|
+
} finally {
|
|
80
|
+
setIsLoading(false);
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
return /* @__PURE__ */ jsxs("div", { className: "space-y-6", children: [
|
|
84
|
+
/* @__PURE__ */ jsx("div", { className: "rounded-lg border overflow-hidden", children: /* @__PURE__ */ jsx(
|
|
85
|
+
"img",
|
|
86
|
+
{
|
|
87
|
+
src: banner.url,
|
|
88
|
+
alt: `Banner ${banner.id}`,
|
|
89
|
+
className: "w-full h-48 object-cover"
|
|
90
|
+
}
|
|
91
|
+
) }),
|
|
92
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
|
|
93
|
+
/* @__PURE__ */ jsxs(
|
|
94
|
+
Label,
|
|
95
|
+
{
|
|
96
|
+
htmlFor: "banner-link",
|
|
97
|
+
className: "text-sm font-medium flex items-center gap-2",
|
|
98
|
+
children: [
|
|
99
|
+
/* @__PURE__ */ jsx(Link, { className: "h-4 w-4" }),
|
|
100
|
+
"Click URL"
|
|
101
|
+
]
|
|
102
|
+
}
|
|
103
|
+
),
|
|
104
|
+
/* @__PURE__ */ jsx(
|
|
105
|
+
Input,
|
|
106
|
+
{
|
|
107
|
+
id: "banner-link",
|
|
108
|
+
type: "url",
|
|
109
|
+
placeholder: "https://example.com",
|
|
110
|
+
value: link,
|
|
111
|
+
onChange: (e) => setLink(e.target.value),
|
|
112
|
+
disabled: isLoading,
|
|
113
|
+
className: "w-full"
|
|
114
|
+
}
|
|
115
|
+
),
|
|
116
|
+
/* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: "Add a URL where users will be redirected when clicking this banner. Leave empty to remove the link." })
|
|
117
|
+
] }),
|
|
118
|
+
banner.link && /* @__PURE__ */ jsxs("div", { className: "p-3 bg-muted/50 rounded-lg", children: [
|
|
119
|
+
/* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground mb-1", children: "Current link:" }),
|
|
120
|
+
/* @__PURE__ */ jsx(
|
|
121
|
+
"a",
|
|
122
|
+
{
|
|
123
|
+
href: banner.link,
|
|
124
|
+
target: "_blank",
|
|
125
|
+
rel: "noopener noreferrer",
|
|
126
|
+
className: "text-sm text-primary hover:underline break-all",
|
|
127
|
+
children: banner.link
|
|
128
|
+
}
|
|
129
|
+
)
|
|
130
|
+
] }),
|
|
131
|
+
/* @__PURE__ */ jsxs("div", { className: "flex gap-3 justify-end", children: [
|
|
132
|
+
/* @__PURE__ */ jsx(
|
|
133
|
+
Button,
|
|
134
|
+
{
|
|
135
|
+
variant: "secondary",
|
|
136
|
+
onClick: onCancel,
|
|
137
|
+
disabled: isLoading,
|
|
138
|
+
children: "Cancel"
|
|
139
|
+
}
|
|
140
|
+
),
|
|
141
|
+
/* @__PURE__ */ jsx(
|
|
142
|
+
Button,
|
|
143
|
+
{
|
|
144
|
+
variant: "primary",
|
|
145
|
+
onClick: handleSave,
|
|
146
|
+
isLoading,
|
|
147
|
+
children: "Save Link"
|
|
148
|
+
}
|
|
149
|
+
)
|
|
150
|
+
] })
|
|
151
|
+
] });
|
|
152
|
+
};
|
|
48
153
|
const GridItem = ({
|
|
49
154
|
banner,
|
|
50
155
|
isSelected,
|
|
51
156
|
onClick,
|
|
52
|
-
onSelect
|
|
157
|
+
onSelect,
|
|
158
|
+
onEditLink
|
|
53
159
|
}) => {
|
|
54
160
|
return /* @__PURE__ */ jsxs(
|
|
55
161
|
"div",
|
|
56
162
|
{
|
|
57
163
|
className: `
|
|
58
|
-
relative overflow-hidden rounded-lg shadow-md cursor-pointer hover:shadow-lg
|
|
164
|
+
relative overflow-hidden rounded-lg shadow-md cursor-pointer hover:shadow-lg
|
|
59
165
|
transition-all duration-200 ease-in-out
|
|
60
|
-
|
|
166
|
+
bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700
|
|
167
|
+
${isSelected ? "ring-2 ring-offset-2 ring-blue-500 dark:ring-offset-gray-900" : ""}
|
|
61
168
|
`,
|
|
62
169
|
onClick,
|
|
63
170
|
children: [
|
|
@@ -70,21 +177,33 @@ const GridItem = ({
|
|
|
70
177
|
className: "object-cover w-full h-48"
|
|
71
178
|
}
|
|
72
179
|
),
|
|
73
|
-
/* @__PURE__ */ jsx("div", { className: "truncate
|
|
180
|
+
/* @__PURE__ */ jsx("div", { className: "p-2 flex items-center justify-between gap-2 bg-white dark:bg-gray-800", children: /* @__PURE__ */ jsxs("div", { className: "truncate text-sm flex items-center gap-2 text-gray-900 dark:text-gray-100", children: [
|
|
181
|
+
banner.link && /* @__PURE__ */ jsx(Link, { className: "h-3 w-3 text-blue-500 dark:text-blue-400 flex-shrink-0" }),
|
|
182
|
+
/* @__PURE__ */ jsx("span", { className: "truncate", children: banner.id })
|
|
183
|
+
] }) })
|
|
74
184
|
] }),
|
|
75
185
|
/* @__PURE__ */ jsx(
|
|
76
186
|
"div",
|
|
77
187
|
{
|
|
78
188
|
className: `
|
|
79
189
|
absolute top-2 left-2 w-6 h-6 rounded-md flex items-center justify-center
|
|
80
|
-
${isSelected ? "bg-blue-500 text-white" : "bg-white/
|
|
190
|
+
${isSelected ? "bg-blue-500 text-white" : "bg-white/90 dark:bg-gray-800/90 border border-gray-300 dark:border-gray-600"}
|
|
81
191
|
${isSelected ? "visible" : "invisible group-hover:visible"}
|
|
82
192
|
transition-opacity duration-200
|
|
83
193
|
`,
|
|
84
194
|
onClick: onSelect,
|
|
85
195
|
children: isSelected && /* @__PURE__ */ jsx(Check, { className: "h-4 w-4" })
|
|
86
196
|
}
|
|
87
|
-
)
|
|
197
|
+
),
|
|
198
|
+
/* @__PURE__ */ jsx("div", { className: "absolute top-2 right-2 invisible group-hover:visible", children: /* @__PURE__ */ jsx(
|
|
199
|
+
Button,
|
|
200
|
+
{
|
|
201
|
+
variant: "secondary",
|
|
202
|
+
className: "size-8 rounded-md p-0 bg-white/90 dark:bg-gray-800/90 hover:bg-white dark:hover:bg-gray-700 border border-gray-200 dark:border-gray-600",
|
|
203
|
+
onClick: onEditLink,
|
|
204
|
+
children: /* @__PURE__ */ jsx(Edit, { className: "h-4 w-4 text-gray-700 dark:text-gray-300" })
|
|
205
|
+
}
|
|
206
|
+
) })
|
|
88
207
|
]
|
|
89
208
|
}
|
|
90
209
|
);
|
|
@@ -109,7 +228,7 @@ const SortableItem = ({ banner }) => {
|
|
|
109
228
|
{
|
|
110
229
|
ref: setNodeRef,
|
|
111
230
|
style,
|
|
112
|
-
className: "rounded-lg shadow-md border border-gray-200 hover:border-gray-300 transition-all relative",
|
|
231
|
+
className: "rounded-lg shadow-md border border-gray-200 dark:border-gray-700 hover:border-gray-300 dark:hover:border-gray-600 transition-all relative bg-white dark:bg-gray-800",
|
|
113
232
|
...attributes,
|
|
114
233
|
children: /* @__PURE__ */ jsxs("div", { ...listeners, children: [
|
|
115
234
|
/* @__PURE__ */ jsx(
|
|
@@ -120,11 +239,24 @@ const SortableItem = ({ banner }) => {
|
|
|
120
239
|
className: "object-cover w-full h-48 rounded-t-lg"
|
|
121
240
|
}
|
|
122
241
|
),
|
|
123
|
-
/* @__PURE__ */ jsx("div", { className: "p-2 text-sm truncate", children: banner.id })
|
|
242
|
+
/* @__PURE__ */ jsx("div", { className: "p-2 text-sm truncate text-gray-900 dark:text-gray-100 bg-white dark:bg-gray-800", children: banner.id })
|
|
124
243
|
] })
|
|
125
244
|
}
|
|
126
245
|
);
|
|
127
246
|
};
|
|
247
|
+
function r(e) {
|
|
248
|
+
var t, f, n = "";
|
|
249
|
+
if ("string" == typeof e || "number" == typeof e) n += e;
|
|
250
|
+
else if ("object" == typeof e) if (Array.isArray(e)) {
|
|
251
|
+
var o = e.length;
|
|
252
|
+
for (t = 0; t < o; t++) e[t] && (f = r(e[t])) && (n && (n += " "), n += f);
|
|
253
|
+
} else for (f in e) e[f] && (n && (n += " "), n += f);
|
|
254
|
+
return n;
|
|
255
|
+
}
|
|
256
|
+
function clsx() {
|
|
257
|
+
for (var e, t, f = 0, n = "", o = arguments.length; f < o; f++) (e = arguments[f]) && (t = r(e)) && (n && (n += " "), n += t);
|
|
258
|
+
return n;
|
|
259
|
+
}
|
|
128
260
|
const UploadBannerDrawerContent = ({
|
|
129
261
|
maxFileSizeMb = 10,
|
|
130
262
|
onSuccess
|
|
@@ -141,7 +273,8 @@ const UploadBannerDrawerContent = ({
|
|
|
141
273
|
return {
|
|
142
274
|
file,
|
|
143
275
|
id,
|
|
144
|
-
preview
|
|
276
|
+
preview,
|
|
277
|
+
link: ""
|
|
145
278
|
};
|
|
146
279
|
});
|
|
147
280
|
setFiles((prev) => [...prev, ...newFiles]);
|
|
@@ -155,6 +288,9 @@ const UploadBannerDrawerContent = ({
|
|
|
155
288
|
return files2.filter((f) => f.id !== id);
|
|
156
289
|
});
|
|
157
290
|
};
|
|
291
|
+
const updateFileLink = (id, link) => {
|
|
292
|
+
setFiles((files2) => files2.map((f) => f.id === id ? { ...f, link } : f));
|
|
293
|
+
};
|
|
158
294
|
const handleResetFiles = () => {
|
|
159
295
|
setFiles([]);
|
|
160
296
|
};
|
|
@@ -168,14 +304,39 @@ const UploadBannerDrawerContent = ({
|
|
|
168
304
|
}
|
|
169
305
|
formData.append("files", file.file);
|
|
170
306
|
});
|
|
171
|
-
const response = await
|
|
172
|
-
"
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
307
|
+
const response = await fetch("/admin/banners", {
|
|
308
|
+
method: "POST",
|
|
309
|
+
body: formData,
|
|
310
|
+
credentials: "include"
|
|
311
|
+
});
|
|
312
|
+
if (!response.ok) {
|
|
313
|
+
const errorData = await response.json();
|
|
314
|
+
throw new Error(errorData.message || "Upload failed");
|
|
315
|
+
}
|
|
316
|
+
const data = await response.json();
|
|
317
|
+
const uploadedFiles = data.files;
|
|
318
|
+
const updatePromises = uploadedFiles.map(
|
|
319
|
+
async (uploadedFile, index) => {
|
|
320
|
+
var _a;
|
|
321
|
+
const fileLink = (_a = files[index]) == null ? void 0 : _a.link;
|
|
322
|
+
if (fileLink && fileLink.trim()) {
|
|
323
|
+
await fetch("/admin/banners/update-link", {
|
|
324
|
+
method: "POST",
|
|
325
|
+
headers: {
|
|
326
|
+
"Content-Type": "application/json"
|
|
327
|
+
},
|
|
328
|
+
credentials: "include",
|
|
329
|
+
body: JSON.stringify({
|
|
330
|
+
id: uploadedFile.id,
|
|
331
|
+
link: fileLink.trim()
|
|
332
|
+
})
|
|
333
|
+
});
|
|
334
|
+
}
|
|
335
|
+
return uploadedFile;
|
|
176
336
|
}
|
|
177
337
|
);
|
|
178
|
-
|
|
338
|
+
await Promise.all(updatePromises);
|
|
339
|
+
setFiles([]);
|
|
179
340
|
onSuccess(uploadedFiles);
|
|
180
341
|
return {
|
|
181
342
|
files,
|
|
@@ -183,7 +344,9 @@ const UploadBannerDrawerContent = ({
|
|
|
183
344
|
};
|
|
184
345
|
} catch (error) {
|
|
185
346
|
console.error(error);
|
|
186
|
-
alert(
|
|
347
|
+
alert(
|
|
348
|
+
`Error uploading files: ${error instanceof Error ? error.message : "Unknown error"}`
|
|
349
|
+
);
|
|
187
350
|
} finally {
|
|
188
351
|
setIsLoading(false);
|
|
189
352
|
}
|
|
@@ -201,14 +364,13 @@ const UploadBannerDrawerContent = ({
|
|
|
201
364
|
"image/*": []
|
|
202
365
|
},
|
|
203
366
|
maxSize: maxFileSizeMb * 1024 * 1024
|
|
204
|
-
// maxFileSizeMb
|
|
205
367
|
});
|
|
206
368
|
return /* @__PURE__ */ jsxs("div", { className: "space-y-6", children: [
|
|
207
369
|
/* @__PURE__ */ jsxs(
|
|
208
370
|
"div",
|
|
209
371
|
{
|
|
210
372
|
...getRootProps(),
|
|
211
|
-
className:
|
|
373
|
+
className: clsx(
|
|
212
374
|
"border-2 border-dashed rounded-xl p-10 transition-all duration-150 ease-in-out cursor-pointer",
|
|
213
375
|
"flex flex-col items-center justify-center gap-4",
|
|
214
376
|
isDragActive ? "bg-primary/5 border-primary/50" : "bg-background hover:bg-muted/50",
|
|
@@ -239,7 +401,7 @@ const UploadBannerDrawerContent = ({
|
|
|
239
401
|
),
|
|
240
402
|
files.length > 0 && /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
|
|
241
403
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
|
|
242
|
-
/* @__PURE__ */ jsxs("div", { className: "
|
|
404
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-4", children: [
|
|
243
405
|
/* @__PURE__ */ jsxs("h3", { className: "text-lg font-medium", children: [
|
|
244
406
|
"Selected Files (",
|
|
245
407
|
files.length,
|
|
@@ -265,48 +427,73 @@ const UploadBannerDrawerContent = ({
|
|
|
265
427
|
}
|
|
266
428
|
)
|
|
267
429
|
] }),
|
|
268
|
-
/* @__PURE__ */ jsx("div", { className: "grid gap-
|
|
430
|
+
/* @__PURE__ */ jsx("div", { className: "grid gap-6 grid-cols-1", children: files.map((fileItem) => /* @__PURE__ */ jsx(
|
|
269
431
|
"div",
|
|
270
432
|
{
|
|
271
|
-
className: "
|
|
272
|
-
children: [
|
|
273
|
-
fileItem.preview ? /* @__PURE__ */ jsx("div", { className: "
|
|
433
|
+
className: "rounded-lg border bg-card text-card-foreground shadow-sm overflow-hidden",
|
|
434
|
+
children: /* @__PURE__ */ jsxs("div", { className: "flex gap-4 p-4", children: [
|
|
435
|
+
/* @__PURE__ */ jsx("div", { className: "flex-shrink-0", children: fileItem.preview ? /* @__PURE__ */ jsx("div", { className: "w-32 h-32 overflow-hidden rounded-lg", children: /* @__PURE__ */ jsx(
|
|
274
436
|
"img",
|
|
275
437
|
{
|
|
276
438
|
src: fileItem.preview || "/placeholder.svg",
|
|
277
439
|
alt: fileItem.file.name,
|
|
278
|
-
className: "
|
|
440
|
+
className: "w-full h-full object-cover"
|
|
279
441
|
}
|
|
280
|
-
) }) : /* @__PURE__ */
|
|
281
|
-
|
|
282
|
-
"
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
442
|
+
) }) : /* @__PURE__ */ jsx("div", { className: "w-32 h-32 flex items-center justify-center bg-muted/50 rounded-lg", children: /* @__PURE__ */ jsx(ImageIcon, { className: "h-8 w-8 text-primary" }) }) }),
|
|
443
|
+
/* @__PURE__ */ jsxs("div", { className: "flex-1 space-y-3", children: [
|
|
444
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between", children: [
|
|
445
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
|
|
446
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm font-medium", children: fileItem.file.name }),
|
|
447
|
+
/* @__PURE__ */ jsxs("p", { className: "text-xs text-muted-foreground", children: [
|
|
448
|
+
(fileItem.file.size / 1024).toFixed(1),
|
|
449
|
+
" KB"
|
|
450
|
+
] })
|
|
451
|
+
] }),
|
|
452
|
+
/* @__PURE__ */ jsxs(
|
|
453
|
+
Button,
|
|
454
|
+
{
|
|
455
|
+
isLoading,
|
|
456
|
+
variant: "secondary",
|
|
457
|
+
className: "size-8 rounded-full p-0.5 text-red-400",
|
|
458
|
+
onClick: (e) => {
|
|
459
|
+
e.stopPropagation();
|
|
460
|
+
removeFile(fileItem.id);
|
|
461
|
+
},
|
|
462
|
+
children: [
|
|
463
|
+
/* @__PURE__ */ jsx(Trash, { className: "h-4 w-4" }),
|
|
464
|
+
/* @__PURE__ */ jsx("span", { className: "sr-only", children: "Remove file" })
|
|
465
|
+
]
|
|
466
|
+
}
|
|
467
|
+
)
|
|
291
468
|
] }),
|
|
292
|
-
/* @__PURE__ */ jsxs(
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
469
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
470
|
+
/* @__PURE__ */ jsxs(
|
|
471
|
+
Label,
|
|
472
|
+
{
|
|
473
|
+
htmlFor: `link-${fileItem.id}`,
|
|
474
|
+
className: "text-sm font-medium flex items-center gap-2",
|
|
475
|
+
children: [
|
|
476
|
+
/* @__PURE__ */ jsx(Link, { className: "h-4 w-4" }),
|
|
477
|
+
"Click URL (optional)"
|
|
478
|
+
]
|
|
479
|
+
}
|
|
480
|
+
),
|
|
481
|
+
/* @__PURE__ */ jsx(
|
|
482
|
+
Input,
|
|
483
|
+
{
|
|
484
|
+
id: `link-${fileItem.id}`,
|
|
485
|
+
type: "url",
|
|
486
|
+
placeholder: "https://example.com",
|
|
487
|
+
value: fileItem.link || "",
|
|
488
|
+
onChange: (e) => updateFileLink(fileItem.id, e.target.value),
|
|
489
|
+
disabled: isLoading,
|
|
490
|
+
className: "w-full"
|
|
491
|
+
}
|
|
492
|
+
),
|
|
493
|
+
/* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: "Add a URL where users will be redirected when clicking this banner" })
|
|
494
|
+
] })
|
|
495
|
+
] })
|
|
496
|
+
] })
|
|
310
497
|
},
|
|
311
498
|
fileItem.id
|
|
312
499
|
)) })
|
|
@@ -315,6 +502,8 @@ const UploadBannerDrawerContent = ({
|
|
|
315
502
|
};
|
|
316
503
|
const BannerPage = () => {
|
|
317
504
|
const [open, setOpen] = useState(false);
|
|
505
|
+
const [editLinkOpen, setEditLinkOpen] = useState(false);
|
|
506
|
+
const [selectedBannerForEdit, setSelectedBannerForEdit] = useState(null);
|
|
318
507
|
const [selectedImage, setSelectedImage] = useState(null);
|
|
319
508
|
const [selectedIds, setSelectedIds] = useState(/* @__PURE__ */ new Set());
|
|
320
509
|
const [reorderMode, setReorderMode] = useState(false);
|
|
@@ -358,6 +547,15 @@ const BannerPage = () => {
|
|
|
358
547
|
const closeLightbox = () => {
|
|
359
548
|
setSelectedImage(null);
|
|
360
549
|
};
|
|
550
|
+
const openEditLinkDrawer = (e, banner) => {
|
|
551
|
+
e.stopPropagation();
|
|
552
|
+
setSelectedBannerForEdit(banner);
|
|
553
|
+
setEditLinkOpen(true);
|
|
554
|
+
};
|
|
555
|
+
const closeEditLinkDrawer = () => {
|
|
556
|
+
setEditLinkOpen(false);
|
|
557
|
+
setSelectedBannerForEdit(null);
|
|
558
|
+
};
|
|
361
559
|
const toggleReorderMode = async () => {
|
|
362
560
|
if (reorderMode) {
|
|
363
561
|
const confirmed = await dialog({
|
|
@@ -481,6 +679,31 @@ const BannerPage = () => {
|
|
|
481
679
|
}
|
|
482
680
|
)
|
|
483
681
|
] }),
|
|
682
|
+
/* @__PURE__ */ jsx(
|
|
683
|
+
Drawer,
|
|
684
|
+
{
|
|
685
|
+
open: editLinkOpen,
|
|
686
|
+
onOpenChange: (openChanged) => {
|
|
687
|
+
if (!openChanged) {
|
|
688
|
+
closeEditLinkDrawer();
|
|
689
|
+
}
|
|
690
|
+
},
|
|
691
|
+
children: /* @__PURE__ */ jsxs(Drawer.Content, { children: [
|
|
692
|
+
/* @__PURE__ */ jsx(Drawer.Header, { children: /* @__PURE__ */ jsx(Drawer.Title, { children: "Edit Banner Link" }) }),
|
|
693
|
+
/* @__PURE__ */ jsx(Drawer.Body, { children: selectedBannerForEdit && /* @__PURE__ */ jsx(
|
|
694
|
+
EditBannerLinkDrawerContent,
|
|
695
|
+
{
|
|
696
|
+
banner: selectedBannerForEdit,
|
|
697
|
+
onSuccess: () => {
|
|
698
|
+
closeEditLinkDrawer();
|
|
699
|
+
refetch();
|
|
700
|
+
},
|
|
701
|
+
onCancel: closeEditLinkDrawer
|
|
702
|
+
}
|
|
703
|
+
) })
|
|
704
|
+
] })
|
|
705
|
+
}
|
|
706
|
+
),
|
|
484
707
|
/* @__PURE__ */ jsxs("div", { className: "container mx-auto px-4 py-8", children: [
|
|
485
708
|
/* @__PURE__ */ jsxs("div", { className: "flex justify-between items-center mb-6", children: [
|
|
486
709
|
selectedIds.size > 0 && !reorderMode && /* @__PURE__ */ jsx("div", { className: "flex gap-2", children: /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
@@ -571,7 +794,8 @@ const BannerPage = () => {
|
|
|
571
794
|
banner,
|
|
572
795
|
isSelected: selectedIds.has(banner.id),
|
|
573
796
|
onClick: () => openLightbox(banner),
|
|
574
|
-
onSelect: (e) => toggleImageSelection(e, banner.id)
|
|
797
|
+
onSelect: (e) => toggleImageSelection(e, banner.id),
|
|
798
|
+
onEditLink: (e) => openEditLinkDrawer(e, banner)
|
|
575
799
|
},
|
|
576
800
|
banner.id
|
|
577
801
|
)) }),
|
|
@@ -9,9 +9,10 @@ const POST = async (req, res) => {
|
|
|
9
9
|
ids,
|
|
10
10
|
},
|
|
11
11
|
});
|
|
12
|
+
res.setHeader("Content-Type", "application/json; charset=utf-8");
|
|
12
13
|
res.json({
|
|
13
14
|
reorderedBanners,
|
|
14
15
|
});
|
|
15
16
|
};
|
|
16
17
|
exports.POST = POST;
|
|
17
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
18
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBpL2FkbWluL2Jhbm5lcnMvcmVvcmRlci9yb3V0ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFJQSwyRUFBK0U7QUFFeEUsTUFBTSxJQUFJLEdBQUcsS0FBSyxFQUN2QixHQUFrRCxFQUNsRCxHQUFtQixFQUNuQixFQUFFO0lBQ0YsTUFBTSxFQUFFLEdBQUcsRUFBRSxHQUFHLEdBQUcsQ0FBQyxJQUFJLENBQUM7SUFFekIsTUFBTSxFQUFFLE1BQU0sRUFBRSxnQkFBZ0IsRUFBRSxHQUFHLE1BQU0sSUFBQSx3Q0FBc0IsRUFDL0QsR0FBRyxDQUFDLEtBQUssQ0FDVixDQUFDLEdBQUcsQ0FBQztRQUNKLEtBQUssRUFBRTtZQUNMLEdBQUc7U0FDSjtLQUNGLENBQUMsQ0FBQztJQUVILEdBQUcsQ0FBQyxTQUFTLENBQUMsY0FBYyxFQUFFLGlDQUFpQyxDQUFDLENBQUM7SUFDakUsR0FBRyxDQUFDLElBQUksQ0FBQztRQUNQLGdCQUFnQjtLQUNqQixDQUFDLENBQUM7QUFDTCxDQUFDLENBQUM7QUFsQlcsUUFBQSxJQUFJLFFBa0JmIn0=
|
|
@@ -18,25 +18,29 @@ const POST = async (req, res) => {
|
|
|
18
18
|
/**
|
|
19
19
|
* docs: https://github.com/expressjs/multer/issues/1104#issuecomment-1152987772
|
|
20
20
|
*/
|
|
21
|
-
filename: Buffer
|
|
21
|
+
filename: Buffer
|
|
22
|
+
.from(f.originalname, "latin1")
|
|
23
|
+
.toString("utf-8"),
|
|
22
24
|
mimeType: f.mimetype,
|
|
23
25
|
content: f.buffer.toString("binary"),
|
|
24
26
|
access: "public",
|
|
25
27
|
})),
|
|
26
28
|
},
|
|
27
29
|
});
|
|
30
|
+
res.setHeader("Content-Type", "application/json; charset=utf-8");
|
|
28
31
|
res.json({
|
|
29
32
|
files,
|
|
30
33
|
});
|
|
31
34
|
};
|
|
32
35
|
exports.POST = POST;
|
|
33
36
|
async function GET(req, res) {
|
|
34
|
-
const bannerService =
|
|
37
|
+
const bannerService = framework_1.container.resolve(banner_1.BANNER_MODULE);
|
|
35
38
|
const [banners, count] = await bannerService.listAndCountBanners({}, {
|
|
36
39
|
order: {
|
|
37
40
|
order: "DESC",
|
|
38
41
|
},
|
|
39
42
|
});
|
|
43
|
+
res.setHeader("Content-Type", "application/json; charset=utf-8");
|
|
40
44
|
res.json({
|
|
41
45
|
banners,
|
|
42
46
|
count,
|
|
@@ -49,9 +53,10 @@ const DELETE = async (req, res) => {
|
|
|
49
53
|
ids,
|
|
50
54
|
},
|
|
51
55
|
});
|
|
56
|
+
res.setHeader("Content-Type", "application/json; charset=utf-8");
|
|
52
57
|
res.json({
|
|
53
58
|
deletedBanners,
|
|
54
59
|
});
|
|
55
60
|
};
|
|
56
61
|
exports.DELETE = DELETE;
|
|
57
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
62
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBpL2FkbWluL2Jhbm5lcnMvcm91dGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBK0NBLGtCQW1CQztBQTlERCxzRUFBMEU7QUFDMUUscURBQXdEO0FBQ3hELG1EQUFnRDtBQUNoRCxvREFBd0Q7QUFDeEQsc0VBQTBFO0FBT25FLE1BQU0sSUFBSSxHQUFHLEtBQUssRUFBRSxHQUFrQixFQUFFLEdBQW1CLEVBQUUsRUFBRTtJQUNwRSxNQUFNLFVBQVUsR0FBRyxHQUFHLENBQUMsS0FBSyxDQUFDO0lBRTdCLElBQUksQ0FBQyxVQUFVLEVBQUUsTUFBTSxFQUFFLENBQUM7UUFDeEIsTUFBTSxJQUFJLG1CQUFXLENBQ25CLG1CQUFXLENBQUMsS0FBSyxDQUFDLFlBQVksRUFDOUIsd0JBQXdCLENBQ3pCLENBQUM7SUFDSixDQUFDO0lBRUQsTUFBTSxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQUUsR0FBRyxNQUFNLElBQUEsc0NBQXFCLEVBQUMsR0FBRyxDQUFDLEtBQVksQ0FBQyxDQUFDLEdBQUcsQ0FBQztRQUMxRSxLQUFLLEVBQUU7WUFDTCxLQUFLLEVBQUUsVUFBVSxFQUFFLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQztnQkFDN0I7O21CQUVHO2dCQUNILFFBQVEsRUFBRyxNQUFjO3FCQUN0QixJQUFJLENBQUMsQ0FBQyxDQUFDLFlBQVksRUFBRSxRQUFRLENBQUM7cUJBQzlCLFFBQVEsQ0FBQyxPQUFPLENBQUM7Z0JBQ3BCLFFBQVEsRUFBRSxDQUFDLENBQUMsUUFBUTtnQkFDcEIsT0FBTyxFQUFFLENBQUMsQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQztnQkFDcEMsTUFBTSxFQUFFLFFBQVE7YUFDakIsQ0FBQyxDQUFDO1NBQ0o7S0FDRixDQUFDLENBQUM7SUFFSCxHQUFHLENBQUMsU0FBUyxDQUFDLGNBQWMsRUFBRSxpQ0FBaUMsQ0FBQyxDQUFDO0lBQ2pFLEdBQUcsQ0FBQyxJQUFJLENBQUM7UUFDUCxLQUFLO0tBQ04sQ0FBQyxDQUFDO0FBQ0wsQ0FBQyxDQUFDO0FBOUJXLFFBQUEsSUFBSSxRQThCZjtBQUVLLEtBQUssVUFBVSxHQUFHLENBQ3ZCLEdBQStCLEVBQy9CLEdBQW1CO0lBRW5CLE1BQU0sYUFBYSxHQUFHLHFCQUFTLENBQUMsT0FBTyxDQUFzQixzQkFBYSxDQUFDLENBQUM7SUFDNUUsTUFBTSxDQUFDLE9BQU8sRUFBRSxLQUFLLENBQUMsR0FBRyxNQUFNLGFBQWEsQ0FBQyxtQkFBbUIsQ0FDOUQsRUFBRSxFQUNGO1FBQ0UsS0FBSyxFQUFFO1lBQ0wsS0FBSyxFQUFFLE1BQU07U0FDZDtLQUNGLENBQ0YsQ0FBQztJQUVGLEdBQUcsQ0FBQyxTQUFTLENBQUMsY0FBYyxFQUFFLGlDQUFpQyxDQUFDLENBQUM7SUFDakUsR0FBRyxDQUFDLElBQUksQ0FBQztRQUNQLE9BQU87UUFDUCxLQUFLO0tBQ04sQ0FBQyxDQUFDO0FBQ0wsQ0FBQztBQUVNLE1BQU0sTUFBTSxHQUFHLEtBQUssRUFDekIsR0FBa0QsRUFDbEQsR0FBbUIsRUFDbkIsRUFBRTtJQUNGLE1BQU0sRUFBRSxHQUFHLEVBQUUsR0FBRyxHQUFHLENBQUMsSUFBSSxDQUFDO0lBRXpCLE1BQU0sRUFBRSxNQUFNLEVBQUUsY0FBYyxFQUFFLEdBQUcsTUFBTSxJQUFBLHNDQUFxQixFQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsQ0FBQyxHQUFHLENBQzNFO1FBQ0UsS0FBSyxFQUFFO1lBQ0wsR0FBRztTQUNKO0tBQ0YsQ0FDRixDQUFDO0lBRUYsR0FBRyxDQUFDLFNBQVMsQ0FBQyxjQUFjLEVBQUUsaUNBQWlDLENBQUMsQ0FBQztJQUNqRSxHQUFHLENBQUMsSUFBSSxDQUFDO1FBQ1AsY0FBYztLQUNmLENBQUMsQ0FBQztBQUNMLENBQUMsQ0FBQztBQWxCVyxRQUFBLE1BQU0sVUFrQmpCIn0=
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.POST = void 0;
|
|
4
|
+
const framework_1 = require("@medusajs/framework");
|
|
5
|
+
const banner_1 = require("../../../../modules/banner");
|
|
6
|
+
const POST = async (req, res) => {
|
|
7
|
+
const { id, link } = req.body;
|
|
8
|
+
const bannerService = framework_1.container.resolve(banner_1.BANNER_MODULE);
|
|
9
|
+
const updatedBanner = await bannerService.updateBanners({
|
|
10
|
+
id,
|
|
11
|
+
link,
|
|
12
|
+
});
|
|
13
|
+
res.setHeader("Content-Type", "application/json; charset=utf-8");
|
|
14
|
+
res.json({
|
|
15
|
+
banner: updatedBanner,
|
|
16
|
+
});
|
|
17
|
+
};
|
|
18
|
+
exports.POST = POST;
|
|
19
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBpL2FkbWluL2Jhbm5lcnMvdXBkYXRlLWxpbmsvcm91dGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBSUEsbURBQWdEO0FBQ2hELHVEQUEyRDtBQUdwRCxNQUFNLElBQUksR0FBRyxLQUFLLEVBQ3ZCLEdBQW9FLEVBQ3BFLEdBQW1CLEVBQ25CLEVBQUU7SUFDRixNQUFNLEVBQUUsRUFBRSxFQUFFLElBQUksRUFBRSxHQUFHLEdBQUcsQ0FBQyxJQUFJLENBQUM7SUFFOUIsTUFBTSxhQUFhLEdBQUcscUJBQVMsQ0FBQyxPQUFPLENBQXNCLHNCQUFhLENBQUMsQ0FBQztJQUU1RSxNQUFNLGFBQWEsR0FBRyxNQUFNLGFBQWEsQ0FBQyxhQUFhLENBQUM7UUFDdEQsRUFBRTtRQUNGLElBQUk7S0FDTCxDQUFDLENBQUM7SUFFSCxHQUFHLENBQUMsU0FBUyxDQUFDLGNBQWMsRUFBRSxpQ0FBaUMsQ0FBQyxDQUFDO0lBQ2pFLEdBQUcsQ0FBQyxJQUFJLENBQUM7UUFDUCxNQUFNLEVBQUUsYUFBYTtLQUN0QixDQUFDLENBQUM7QUFDTCxDQUFDLENBQUM7QUFqQlcsUUFBQSxJQUFJLFFBaUJmIn0=
|
|
@@ -10,9 +10,10 @@ async function GET(req, res) {
|
|
|
10
10
|
order: "DESC",
|
|
11
11
|
},
|
|
12
12
|
});
|
|
13
|
+
res.setHeader("Content-Type", "application/json; charset=utf-8");
|
|
13
14
|
res.json({
|
|
14
15
|
banners,
|
|
15
16
|
count,
|
|
16
17
|
});
|
|
17
18
|
}
|
|
18
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
19
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBpL3N0b3JlL2Jhbm5lcnMvcm91dGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFPQSxrQkFvQkM7QUF0QkQsbURBQWdEO0FBQ2hELG9EQUF3RDtBQUNqRCxLQUFLLFVBQVUsR0FBRyxDQUN2QixHQUErQixFQUMvQixHQUFtQjtJQUVuQixNQUFNLGFBQWEsR0FDakIsTUFBTSxxQkFBUyxDQUFDLE9BQU8sQ0FBc0Isc0JBQWEsQ0FBQyxDQUFDO0lBQzlELE1BQU0sQ0FBQyxPQUFPLEVBQUUsS0FBSyxDQUFDLEdBQUcsTUFBTSxhQUFhLENBQUMsbUJBQW1CLENBQzlELEVBQUUsRUFDRjtRQUNFLEtBQUssRUFBRTtZQUNMLEtBQUssRUFBRSxNQUFNO1NBQ2Q7S0FDRixDQUNGLENBQUM7SUFFRixHQUFHLENBQUMsU0FBUyxDQUFDLGNBQWMsRUFBRSxpQ0FBaUMsQ0FBQyxDQUFDO0lBQ2pFLEdBQUcsQ0FBQyxJQUFJLENBQUM7UUFDUCxPQUFPO1FBQ1AsS0FBSztLQUNOLENBQUMsQ0FBQztBQUNMLENBQUMifQ==
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Migration20251024160000 = void 0;
|
|
4
|
+
const migrations_1 = require("@medusajs/framework/mikro-orm/migrations");
|
|
5
|
+
class Migration20251024160000 extends migrations_1.Migration {
|
|
6
|
+
async up() {
|
|
7
|
+
this.addSql(`alter table if exists "banner" add column if not exists "link" text null;`);
|
|
8
|
+
}
|
|
9
|
+
async down() {
|
|
10
|
+
this.addSql(`alter table if exists "banner" drop column if exists "link";`);
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
exports.Migration20251024160000 = Migration20251024160000;
|
|
14
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiTWlncmF0aW9uMjAyNTEwMjQxNjAwMDAuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvbW9kdWxlcy9iYW5uZXIvbWlncmF0aW9ucy9NaWdyYXRpb24yMDI1MTAyNDE2MDAwMC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSx5RUFBcUU7QUFFckUsTUFBYSx1QkFBd0IsU0FBUSxzQkFBUztJQUMzQyxLQUFLLENBQUMsRUFBRTtRQUNmLElBQUksQ0FBQyxNQUFNLENBQ1QsMkVBQTJFLENBQzVFLENBQUM7SUFDSixDQUFDO0lBRVEsS0FBSyxDQUFDLElBQUk7UUFDakIsSUFBSSxDQUFDLE1BQU0sQ0FBQyw4REFBOEQsQ0FBQyxDQUFDO0lBQzlFLENBQUM7Q0FDRjtBQVZELDBEQVVDIn0=
|
|
@@ -4,7 +4,8 @@ const utils_1 = require("@medusajs/framework/utils");
|
|
|
4
4
|
const Banner = utils_1.model.define("banner", {
|
|
5
5
|
id: utils_1.model.id().primaryKey(),
|
|
6
6
|
url: utils_1.model.text(),
|
|
7
|
+
link: utils_1.model.text().nullable(),
|
|
7
8
|
order: utils_1.model.number(),
|
|
8
9
|
});
|
|
9
10
|
exports.default = Banner;
|
|
10
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
11
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmFubmVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vc3JjL21vZHVsZXMvYmFubmVyL21vZGVscy9iYW5uZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFBQSxxREFBa0Q7QUFFbEQsTUFBTSxNQUFNLEdBQUcsYUFBSyxDQUFDLE1BQU0sQ0FBQyxRQUFRLEVBQUU7SUFDcEMsRUFBRSxFQUFFLGFBQUssQ0FBQyxFQUFFLEVBQUUsQ0FBQyxVQUFVLEVBQUU7SUFDM0IsR0FBRyxFQUFFLGFBQUssQ0FBQyxJQUFJLEVBQUU7SUFDakIsSUFBSSxFQUFFLGFBQUssQ0FBQyxJQUFJLEVBQUUsQ0FBQyxRQUFRLEVBQUU7SUFDN0IsS0FBSyxFQUFFLGFBQUssQ0FBQyxNQUFNLEVBQUU7Q0FDdEIsQ0FBQyxDQUFDO0FBRUgsa0JBQWUsTUFBTSxDQUFDIn0=
|