strapi-plugin-magic-mark 1.1.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.
Files changed (68) hide show
  1. package/COPYRIGHT_NOTICE.txt +20 -0
  2. package/LICENSE +28 -0
  3. package/README.md +372 -0
  4. package/dist/_chunks/App-7ZH1Reka.mjs +1390 -0
  5. package/dist/_chunks/App-CMSut1pt.js +1392 -0
  6. package/dist/_chunks/de-Bag-366k.mjs +49 -0
  7. package/dist/_chunks/de-Dic_hhjg.js +49 -0
  8. package/dist/_chunks/en-C5BvHqNo.js +54 -0
  9. package/dist/_chunks/en-zokEerzt.mjs +54 -0
  10. package/dist/_chunks/es-BlSQpU1z.js +54 -0
  11. package/dist/_chunks/es-Br1ucP3h.mjs +54 -0
  12. package/dist/_chunks/fr-BHciYPYG.js +54 -0
  13. package/dist/_chunks/fr-Dzo3kt_q.mjs +54 -0
  14. package/dist/_chunks/index-B-Cc7QNW.mjs +322 -0
  15. package/dist/_chunks/index-B11QBtag.js +324 -0
  16. package/dist/_chunks/index-DYHEyGJr.mjs +2020 -0
  17. package/dist/_chunks/index-DkkmdRgb.js +2024 -0
  18. package/dist/_chunks/pt-DQoGyzyD.mjs +54 -0
  19. package/dist/_chunks/pt-Dawo5aUA.js +54 -0
  20. package/dist/admin/index.js +3 -0
  21. package/dist/admin/index.mjs +4 -0
  22. package/dist/admin/src/components/AdvancedFilterButton.d.ts +3 -0
  23. package/dist/admin/src/components/AdvancedFilterModal.d.ts +21 -0
  24. package/dist/admin/src/components/CreateEditModal.d.ts +11 -0
  25. package/dist/admin/src/components/CreateViewModal.d.ts +9 -0
  26. package/dist/admin/src/components/CustomSelect.d.ts +13 -0
  27. package/dist/admin/src/components/FilterPreview.d.ts +6 -0
  28. package/dist/admin/src/components/HomePage.d.ts +0 -0
  29. package/dist/admin/src/components/Initializer.d.ts +6 -0
  30. package/dist/admin/src/components/LicenseGuard.d.ts +6 -0
  31. package/dist/admin/src/components/PluginIcon.d.ts +3 -0
  32. package/dist/admin/src/components/QueryBuilder.d.ts +23 -0
  33. package/dist/admin/src/components/SimpleAdvancedFilterModal.d.ts +15 -0
  34. package/dist/admin/src/components/ViewsListPopover.d.ts +2 -0
  35. package/dist/admin/src/components/ViewsWidget.d.ts +8 -0
  36. package/dist/admin/src/index.d.ts +15 -0
  37. package/dist/admin/src/pages/App.d.ts +3 -0
  38. package/dist/admin/src/pages/HomePage.d.ts +3 -0
  39. package/dist/admin/src/pages/HomePageModern.d.ts +3 -0
  40. package/dist/admin/src/pages/License/index.d.ts +3 -0
  41. package/dist/admin/src/permissions.d.ts +15 -0
  42. package/dist/admin/src/pluginId.d.ts +2 -0
  43. package/dist/admin/src/utils/queryGenerator.d.ts +28 -0
  44. package/dist/admin/src/utils/queryParser.d.ts +25 -0
  45. package/dist/admin/src/utils/queryToStructure.d.ts +20 -0
  46. package/dist/server/index.js +1309 -0
  47. package/dist/server/index.mjs +1307 -0
  48. package/dist/server/src/bootstrap.d.ts +5 -0
  49. package/dist/server/src/config/index.d.ts +5 -0
  50. package/dist/server/src/content-types/index.d.ts +82 -0
  51. package/dist/server/src/controllers/controller.d.ts +11 -0
  52. package/dist/server/src/controllers/index.d.ts +20 -0
  53. package/dist/server/src/controllers/license.d.ts +27 -0
  54. package/dist/server/src/destroy.d.ts +5 -0
  55. package/dist/server/src/index.d.ts +195 -0
  56. package/dist/server/src/middlewares/index.d.ts +4 -0
  57. package/dist/server/src/middlewares/license-check.d.ts +6 -0
  58. package/dist/server/src/policies/index.d.ts +4 -0
  59. package/dist/server/src/policies/license-check.d.ts +6 -0
  60. package/dist/server/src/register.d.ts +5 -0
  61. package/dist/server/src/routes/admin.d.ts +12 -0
  62. package/dist/server/src/routes/content-api.d.ts +5 -0
  63. package/dist/server/src/routes/index.d.ts +18 -0
  64. package/dist/server/src/services/index.d.ts +57 -0
  65. package/dist/server/src/services/license-guard.d.ts +103 -0
  66. package/dist/server/src/services/service.d.ts +33 -0
  67. package/package.json +108 -0
  68. package/strapi-server.js +4 -0
@@ -0,0 +1,322 @@
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
+ import { useState, useEffect } from "react";
3
+ import { Loader, Box, Alert, Flex, Typography, Button, Badge, Accordion } from "@strapi/design-system";
4
+ import { useFetchClient, useNotification } from "@strapi/strapi/admin";
5
+ import { ArrowClockwise, Duplicate, Download, User, Shield, Sparkle, ChartBubble } from "@strapi/icons";
6
+ import styled, { keyframes } from "styled-components";
7
+ const theme = {
8
+ colors: {
9
+ neutral: { 200: "#E5E7EB" }
10
+ },
11
+ shadows: { sm: "0 1px 3px rgba(0,0,0,0.1)" },
12
+ borderRadius: { lg: "12px" }
13
+ };
14
+ const fadeIn = keyframes`
15
+ from { opacity: 0; transform: translateY(10px); }
16
+ to { opacity: 1; transform: translateY(0); }
17
+ `;
18
+ const shimmer = keyframes`
19
+ 0% { background-position: -200% 0; }
20
+ 100% { background-position: 200% 0; }
21
+ `;
22
+ const Container = styled(Box)`
23
+ animation: ${fadeIn} 0.5s;
24
+ max-width: 1400px;
25
+ margin: 0 auto;
26
+ `;
27
+ const StickySaveBar = styled(Box)`
28
+ position: sticky;
29
+ top: 0;
30
+ z-index: 10;
31
+ background: white;
32
+ border-bottom: 1px solid ${theme.colors.neutral[200]};
33
+ box-shadow: ${theme.shadows.sm};
34
+ `;
35
+ const LicenseKeyBanner = styled(Box)`
36
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
37
+ border-radius: ${theme.borderRadius.lg};
38
+ padding: 28px 32px;
39
+ color: white;
40
+ position: relative;
41
+ overflow: hidden;
42
+ box-shadow: 0 4px 20px rgba(102, 126, 234, 0.25);
43
+ margin-bottom: 24px;
44
+
45
+ &::after {
46
+ content: '';
47
+ position: absolute;
48
+ top: -50%;
49
+ right: -50%;
50
+ width: 200%;
51
+ height: 200%;
52
+ background: linear-gradient(
53
+ 45deg,
54
+ transparent,
55
+ rgba(255, 255, 255, 0.08),
56
+ transparent
57
+ );
58
+ animation: ${shimmer} 3s infinite;
59
+ pointer-events: none;
60
+ z-index: 0;
61
+ }
62
+
63
+ & > * {
64
+ position: relative;
65
+ z-index: 1;
66
+ }
67
+ `;
68
+ const LoaderContainer = styled(Flex)`
69
+ min-height: 400px;
70
+ align-items: center;
71
+ justify-content: center;
72
+ flex-direction: column;
73
+ gap: 16px;
74
+ `;
75
+ const LicensePage = () => {
76
+ const { get } = useFetchClient();
77
+ const { toggleNotification } = useNotification();
78
+ const [loading, setLoading] = useState(true);
79
+ const [licenseData, setLicenseData] = useState(null);
80
+ const [error, setError] = useState(null);
81
+ const fetchLicenseStatus = async () => {
82
+ setLoading(true);
83
+ setError(null);
84
+ try {
85
+ const response = await get("/magic-mark/license/status");
86
+ setLicenseData(response.data);
87
+ } catch (err) {
88
+ console.error("Error fetching license:", err);
89
+ setError("Failed to load license information");
90
+ } finally {
91
+ setLoading(false);
92
+ }
93
+ };
94
+ const handleCopyLicenseKey = async () => {
95
+ try {
96
+ await navigator.clipboard.writeText(licenseData?.data?.licenseKey || "");
97
+ toggleNotification({
98
+ type: "success",
99
+ message: "License key copied to clipboard!"
100
+ });
101
+ } catch (err) {
102
+ toggleNotification({
103
+ type: "danger",
104
+ message: "Failed to copy license key"
105
+ });
106
+ }
107
+ };
108
+ const handleDownloadLicenseKey = () => {
109
+ try {
110
+ const data2 = licenseData?.data || {};
111
+ const licenseKey = data2.licenseKey || "";
112
+ const email = data2.email || "N/A";
113
+ const firstName = data2.firstName || "";
114
+ const lastName = data2.lastName || "";
115
+ const fullName = `${firstName} ${lastName}`.trim() || "N/A";
116
+ const content = `MagicMark Plugin License Key
117
+ ═══════════════════════════════════════
118
+
119
+ License Key: ${licenseKey}
120
+
121
+ License Holder Information:
122
+ ──────────────────────────────────────
123
+ Name: ${fullName}
124
+ Email: ${email}
125
+
126
+ License Status:
127
+ ──────────────────────────────────────
128
+ Status: ${data2.isActive ? "ACTIVE" : "INACTIVE"}
129
+ Expires: ${data2.expiresAt ? new Date(data2.expiresAt).toLocaleDateString() : "Never"}
130
+
131
+ ═══════════════════════════════════════
132
+ Generated: ${(/* @__PURE__ */ new Date()).toLocaleString()}
133
+ `;
134
+ const blob = new Blob([content], { type: "text/plain" });
135
+ const url = window.URL.createObjectURL(blob);
136
+ const link = document.createElement("a");
137
+ link.href = url;
138
+ link.download = `magicmark-license-${licenseKey.substring(0, 8)}.txt`;
139
+ document.body.appendChild(link);
140
+ link.click();
141
+ document.body.removeChild(link);
142
+ window.URL.revokeObjectURL(url);
143
+ toggleNotification({
144
+ type: "success",
145
+ message: "License key downloaded successfully!"
146
+ });
147
+ } catch (err) {
148
+ toggleNotification({
149
+ type: "danger",
150
+ message: "Failed to download license key"
151
+ });
152
+ }
153
+ };
154
+ useEffect(() => {
155
+ fetchLicenseStatus();
156
+ }, []);
157
+ if (loading) {
158
+ return /* @__PURE__ */ jsx(Container, { children: /* @__PURE__ */ jsx(LoaderContainer, { children: /* @__PURE__ */ jsx(Loader, { children: "Loading license information..." }) }) });
159
+ }
160
+ if (error) {
161
+ return /* @__PURE__ */ jsx(Container, { children: /* @__PURE__ */ jsx(Box, { padding: 8, children: /* @__PURE__ */ jsx(Alert, { variant: "danger", title: "Error", closeLabel: "Close", children: error }) }) });
162
+ }
163
+ const isValid = licenseData?.valid;
164
+ const isDemo = licenseData?.demo;
165
+ const data = licenseData?.data || {};
166
+ return /* @__PURE__ */ jsxs(Container, { children: [
167
+ /* @__PURE__ */ jsx(StickySaveBar, { paddingTop: 5, paddingBottom: 5, paddingLeft: 6, paddingRight: 6, children: /* @__PURE__ */ jsxs(Flex, { justifyContent: "space-between", alignItems: "center", children: [
168
+ /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 1, children: [
169
+ /* @__PURE__ */ jsx(Typography, { variant: "alpha", fontWeight: "bold", children: "License Management" }),
170
+ /* @__PURE__ */ jsx(Typography, { variant: "epsilon", textColor: "neutral600", children: "View your MagicMark plugin license" })
171
+ ] }),
172
+ /* @__PURE__ */ jsx(
173
+ Button,
174
+ {
175
+ startIcon: /* @__PURE__ */ jsx(ArrowClockwise, {}),
176
+ onClick: fetchLicenseStatus,
177
+ size: "L",
178
+ style: {
179
+ background: "linear-gradient(135deg, #667eea 0%, #764ba2 100%)",
180
+ color: "white",
181
+ fontWeight: "600",
182
+ border: "none"
183
+ },
184
+ children: "Refresh Status"
185
+ }
186
+ )
187
+ ] }) }),
188
+ /* @__PURE__ */ jsxs(Box, { paddingTop: 6, paddingLeft: 6, paddingRight: 6, paddingBottom: 10, children: [
189
+ isDemo ? /* @__PURE__ */ jsx(Alert, { variant: "warning", title: "Demo Mode", closeLabel: "Close", children: "You're using the demo version. Create a license to unlock all features." }) : isValid ? /* @__PURE__ */ jsx(Alert, { variant: "success", title: "License Active", closeLabel: "Close", children: "Your license is active and all features are unlocked." }) : /* @__PURE__ */ jsx(Alert, { variant: "danger", title: "License Issue", closeLabel: "Close", children: "There's an issue with your license. Please check your license status." }),
190
+ data.licenseKey && /* @__PURE__ */ jsx(Box, { marginTop: 6, children: /* @__PURE__ */ jsx(LicenseKeyBanner, { children: /* @__PURE__ */ jsxs(Flex, { justifyContent: "space-between", alignItems: "flex-start", children: [
191
+ /* @__PURE__ */ jsxs(Box, { style: { flex: 1 }, children: [
192
+ /* @__PURE__ */ jsx(Typography, { variant: "pi", style: { color: "rgba(255,255,255,0.8)", marginBottom: "12px", textTransform: "uppercase", fontSize: "11px", letterSpacing: "0.5px", display: "block" }, children: "License Key" }),
193
+ /* @__PURE__ */ jsx(Typography, { style: { color: "white", fontFamily: "monospace", fontSize: "28px", fontWeight: "bold", wordBreak: "break-all", marginBottom: "16px" }, children: data.licenseKey }),
194
+ /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
195
+ /* @__PURE__ */ jsx(
196
+ Button,
197
+ {
198
+ onClick: handleCopyLicenseKey,
199
+ startIcon: /* @__PURE__ */ jsx(Duplicate, {}),
200
+ size: "S",
201
+ variant: "secondary",
202
+ style: {
203
+ backgroundColor: "rgba(255,255,255,0.2)",
204
+ color: "white",
205
+ border: "1px solid rgba(255,255,255,0.3)",
206
+ fontWeight: "600"
207
+ },
208
+ children: "Copy Key"
209
+ }
210
+ ),
211
+ /* @__PURE__ */ jsx(
212
+ Button,
213
+ {
214
+ onClick: handleDownloadLicenseKey,
215
+ startIcon: /* @__PURE__ */ jsx(Download, {}),
216
+ size: "S",
217
+ variant: "secondary",
218
+ style: {
219
+ backgroundColor: "rgba(255,255,255,0.2)",
220
+ color: "white",
221
+ border: "1px solid rgba(255,255,255,0.3)",
222
+ fontWeight: "600"
223
+ },
224
+ children: "Download as TXT"
225
+ }
226
+ )
227
+ ] })
228
+ ] }),
229
+ /* @__PURE__ */ jsx(
230
+ Badge,
231
+ {
232
+ backgroundColor: data.isActive ? "success100" : "danger100",
233
+ textColor: data.isActive ? "success700" : "danger700",
234
+ style: { fontSize: "11px", fontWeight: "700", padding: "6px 12px", marginLeft: "16px", flexShrink: 0 },
235
+ children: data.isActive ? "ACTIVE" : "INACTIVE"
236
+ }
237
+ )
238
+ ] }) }) }),
239
+ /* @__PURE__ */ jsx(Box, { marginTop: 6, children: /* @__PURE__ */ jsxs(Accordion.Root, { defaultValue: "account", collapsible: true, children: [
240
+ /* @__PURE__ */ jsxs(Accordion.Item, { value: "account", children: [
241
+ /* @__PURE__ */ jsx(Accordion.Header, { children: /* @__PURE__ */ jsx(Accordion.Trigger, { icon: User, children: "Account Information" }) }),
242
+ /* @__PURE__ */ jsx(Accordion.Content, { children: /* @__PURE__ */ jsx(Box, { padding: 6, children: /* @__PURE__ */ jsxs(Flex, { gap: 8, wrap: "wrap", children: [
243
+ /* @__PURE__ */ jsxs(Box, { style: { flex: "1", minWidth: "200px" }, children: [
244
+ /* @__PURE__ */ jsx(Typography, { variant: "sigma", textColor: "neutral600", textTransform: "uppercase", style: { marginBottom: "8px", display: "block" }, children: "Email Address" }),
245
+ /* @__PURE__ */ jsx(Typography, { variant: "omega", fontWeight: "semiBold", children: data.email || "Not provided" })
246
+ ] }),
247
+ /* @__PURE__ */ jsxs(Box, { style: { flex: "1", minWidth: "200px" }, children: [
248
+ /* @__PURE__ */ jsx(Typography, { variant: "sigma", textColor: "neutral600", textTransform: "uppercase", style: { marginBottom: "8px", display: "block" }, children: "License Holder" }),
249
+ /* @__PURE__ */ jsx(Typography, { variant: "omega", fontWeight: "semiBold", children: data.firstName && data.lastName ? `${data.firstName} ${data.lastName}` : "Not specified" })
250
+ ] })
251
+ ] }) }) })
252
+ ] }),
253
+ /* @__PURE__ */ jsxs(Accordion.Item, { value: "details", children: [
254
+ /* @__PURE__ */ jsx(Accordion.Header, { children: /* @__PURE__ */ jsx(Accordion.Trigger, { icon: Shield, children: "License Details" }) }),
255
+ /* @__PURE__ */ jsx(Accordion.Content, { children: /* @__PURE__ */ jsx(Box, { padding: 6, children: /* @__PURE__ */ jsxs(Flex, { gap: 8, wrap: "wrap", children: [
256
+ /* @__PURE__ */ jsxs(Box, { style: { flex: "1", minWidth: "180px" }, children: [
257
+ /* @__PURE__ */ jsx(Typography, { variant: "sigma", textColor: "neutral600", textTransform: "uppercase", style: { marginBottom: "8px", display: "block" }, children: data.isExpired ? "Expired On" : "Expires On" }),
258
+ /* @__PURE__ */ jsx(Typography, { variant: "omega", fontWeight: "semiBold", children: data.expiresAt ? new Date(data.expiresAt).toLocaleDateString("en-US", {
259
+ year: "numeric",
260
+ month: "long",
261
+ day: "numeric"
262
+ }) : "Never" })
263
+ ] }),
264
+ /* @__PURE__ */ jsxs(Box, { style: { flex: "1", minWidth: "180px" }, children: [
265
+ /* @__PURE__ */ jsx(Typography, { variant: "sigma", textColor: "neutral600", textTransform: "uppercase", style: { marginBottom: "8px", display: "block" }, children: "Device Name" }),
266
+ /* @__PURE__ */ jsx(Typography, { variant: "omega", fontWeight: "semiBold", children: data.deviceName || "Unknown" })
267
+ ] }),
268
+ /* @__PURE__ */ jsxs(Box, { style: { flex: "1", minWidth: "180px" }, children: [
269
+ /* @__PURE__ */ jsx(Typography, { variant: "sigma", textColor: "neutral600", textTransform: "uppercase", style: { marginBottom: "8px", display: "block" }, children: "IP Address" }),
270
+ /* @__PURE__ */ jsx(Typography, { variant: "omega", fontWeight: "semiBold", children: data.ipAddress || "Not detected" })
271
+ ] })
272
+ ] }) }) })
273
+ ] }),
274
+ /* @__PURE__ */ jsxs(Accordion.Item, { value: "features", children: [
275
+ /* @__PURE__ */ jsx(Accordion.Header, { children: /* @__PURE__ */ jsx(Accordion.Trigger, { icon: Sparkle, children: "Features & Capabilities" }) }),
276
+ /* @__PURE__ */ jsx(Accordion.Content, { children: /* @__PURE__ */ jsx(Box, { padding: 6, children: /* @__PURE__ */ jsxs(Flex, { gap: 8, wrap: "wrap", children: [
277
+ /* @__PURE__ */ jsxs(Box, { style: { flex: "1", minWidth: "180px" }, children: [
278
+ /* @__PURE__ */ jsx(Typography, { variant: "sigma", textColor: "neutral600", textTransform: "uppercase", style: { marginBottom: "8px", display: "block" }, children: "Premium Features" }),
279
+ /* @__PURE__ */ jsx(Typography, { variant: "omega", fontWeight: "semiBold", children: data.features?.premium ? "✓ Enabled" : "✗ Disabled" })
280
+ ] }),
281
+ /* @__PURE__ */ jsxs(Box, { style: { flex: "1", minWidth: "180px" }, children: [
282
+ /* @__PURE__ */ jsx(Typography, { variant: "sigma", textColor: "neutral600", textTransform: "uppercase", style: { marginBottom: "8px", display: "block" }, children: "Advanced Features" }),
283
+ /* @__PURE__ */ jsx(Typography, { variant: "omega", fontWeight: "semiBold", children: data.features?.advanced ? "✓ Enabled" : "✗ Disabled" })
284
+ ] }),
285
+ /* @__PURE__ */ jsxs(Box, { style: { flex: "1", minWidth: "180px" }, children: [
286
+ /* @__PURE__ */ jsx(Typography, { variant: "sigma", textColor: "neutral600", textTransform: "uppercase", style: { marginBottom: "8px", display: "block" }, children: "Enterprise Features" }),
287
+ /* @__PURE__ */ jsx(Typography, { variant: "omega", fontWeight: "semiBold", children: data.features?.enterprise ? "✓ Enabled" : "✗ Disabled" })
288
+ ] })
289
+ ] }) }) })
290
+ ] }),
291
+ /* @__PURE__ */ jsxs(Accordion.Item, { value: "status", children: [
292
+ /* @__PURE__ */ jsx(Accordion.Header, { children: /* @__PURE__ */ jsx(Accordion.Trigger, { icon: ChartBubble, children: "System Status" }) }),
293
+ /* @__PURE__ */ jsx(Accordion.Content, { children: /* @__PURE__ */ jsx(Box, { padding: 6, children: /* @__PURE__ */ jsxs(Flex, { gap: 8, wrap: "wrap", children: [
294
+ /* @__PURE__ */ jsxs(Box, { style: { flex: "1", minWidth: "150px" }, children: [
295
+ /* @__PURE__ */ jsx(Typography, { variant: "sigma", textColor: "neutral600", textTransform: "uppercase", style: { marginBottom: "8px", display: "block" }, children: "License Status" }),
296
+ /* @__PURE__ */ jsx(Typography, { variant: "omega", fontWeight: "semiBold", children: data.isActive ? "Active" : "Inactive" })
297
+ ] }),
298
+ /* @__PURE__ */ jsxs(Box, { style: { flex: "1", minWidth: "150px" }, children: [
299
+ /* @__PURE__ */ jsx(Typography, { variant: "sigma", textColor: "neutral600", textTransform: "uppercase", style: { marginBottom: "8px", display: "block" }, children: "Connection" }),
300
+ /* @__PURE__ */ jsx(Typography, { variant: "omega", fontWeight: "semiBold", children: data.isOnline ? "Online" : "Offline" })
301
+ ] }),
302
+ /* @__PURE__ */ jsxs(Box, { style: { flex: "1", minWidth: "150px" }, children: [
303
+ /* @__PURE__ */ jsx(Typography, { variant: "sigma", textColor: "neutral600", textTransform: "uppercase", style: { marginBottom: "8px", display: "block" }, children: "Last Sync" }),
304
+ /* @__PURE__ */ jsx(Typography, { variant: "omega", fontWeight: "semiBold", children: data.lastPingAt ? new Date(data.lastPingAt).toLocaleTimeString() : "Never" })
305
+ ] }),
306
+ /* @__PURE__ */ jsxs(Box, { style: { flex: "1", minWidth: "150px" }, children: [
307
+ /* @__PURE__ */ jsx(Typography, { variant: "sigma", textColor: "neutral600", textTransform: "uppercase", style: { marginBottom: "8px", display: "block" }, children: "Device Limit" }),
308
+ /* @__PURE__ */ jsxs(Typography, { variant: "omega", fontWeight: "semiBold", children: [
309
+ data.currentDevices || 0,
310
+ " / ",
311
+ data.maxDevices || 1
312
+ ] })
313
+ ] })
314
+ ] }) }) })
315
+ ] })
316
+ ] }) })
317
+ ] })
318
+ ] });
319
+ };
320
+ export {
321
+ LicensePage as default
322
+ };
@@ -0,0 +1,324 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const jsxRuntime = require("react/jsx-runtime");
4
+ const React = require("react");
5
+ const designSystem = require("@strapi/design-system");
6
+ const admin = require("@strapi/strapi/admin");
7
+ const icons = require("@strapi/icons");
8
+ const styled = require("styled-components");
9
+ const _interopDefault = (e) => e && e.__esModule ? e : { default: e };
10
+ const styled__default = /* @__PURE__ */ _interopDefault(styled);
11
+ const theme = {
12
+ colors: {
13
+ neutral: { 200: "#E5E7EB" }
14
+ },
15
+ shadows: { sm: "0 1px 3px rgba(0,0,0,0.1)" },
16
+ borderRadius: { lg: "12px" }
17
+ };
18
+ const fadeIn = styled.keyframes`
19
+ from { opacity: 0; transform: translateY(10px); }
20
+ to { opacity: 1; transform: translateY(0); }
21
+ `;
22
+ const shimmer = styled.keyframes`
23
+ 0% { background-position: -200% 0; }
24
+ 100% { background-position: 200% 0; }
25
+ `;
26
+ const Container = styled__default.default(designSystem.Box)`
27
+ animation: ${fadeIn} 0.5s;
28
+ max-width: 1400px;
29
+ margin: 0 auto;
30
+ `;
31
+ const StickySaveBar = styled__default.default(designSystem.Box)`
32
+ position: sticky;
33
+ top: 0;
34
+ z-index: 10;
35
+ background: white;
36
+ border-bottom: 1px solid ${theme.colors.neutral[200]};
37
+ box-shadow: ${theme.shadows.sm};
38
+ `;
39
+ const LicenseKeyBanner = styled__default.default(designSystem.Box)`
40
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
41
+ border-radius: ${theme.borderRadius.lg};
42
+ padding: 28px 32px;
43
+ color: white;
44
+ position: relative;
45
+ overflow: hidden;
46
+ box-shadow: 0 4px 20px rgba(102, 126, 234, 0.25);
47
+ margin-bottom: 24px;
48
+
49
+ &::after {
50
+ content: '';
51
+ position: absolute;
52
+ top: -50%;
53
+ right: -50%;
54
+ width: 200%;
55
+ height: 200%;
56
+ background: linear-gradient(
57
+ 45deg,
58
+ transparent,
59
+ rgba(255, 255, 255, 0.08),
60
+ transparent
61
+ );
62
+ animation: ${shimmer} 3s infinite;
63
+ pointer-events: none;
64
+ z-index: 0;
65
+ }
66
+
67
+ & > * {
68
+ position: relative;
69
+ z-index: 1;
70
+ }
71
+ `;
72
+ const LoaderContainer = styled__default.default(designSystem.Flex)`
73
+ min-height: 400px;
74
+ align-items: center;
75
+ justify-content: center;
76
+ flex-direction: column;
77
+ gap: 16px;
78
+ `;
79
+ const LicensePage = () => {
80
+ const { get } = admin.useFetchClient();
81
+ const { toggleNotification } = admin.useNotification();
82
+ const [loading, setLoading] = React.useState(true);
83
+ const [licenseData, setLicenseData] = React.useState(null);
84
+ const [error, setError] = React.useState(null);
85
+ const fetchLicenseStatus = async () => {
86
+ setLoading(true);
87
+ setError(null);
88
+ try {
89
+ const response = await get("/magic-mark/license/status");
90
+ setLicenseData(response.data);
91
+ } catch (err) {
92
+ console.error("Error fetching license:", err);
93
+ setError("Failed to load license information");
94
+ } finally {
95
+ setLoading(false);
96
+ }
97
+ };
98
+ const handleCopyLicenseKey = async () => {
99
+ try {
100
+ await navigator.clipboard.writeText(licenseData?.data?.licenseKey || "");
101
+ toggleNotification({
102
+ type: "success",
103
+ message: "License key copied to clipboard!"
104
+ });
105
+ } catch (err) {
106
+ toggleNotification({
107
+ type: "danger",
108
+ message: "Failed to copy license key"
109
+ });
110
+ }
111
+ };
112
+ const handleDownloadLicenseKey = () => {
113
+ try {
114
+ const data2 = licenseData?.data || {};
115
+ const licenseKey = data2.licenseKey || "";
116
+ const email = data2.email || "N/A";
117
+ const firstName = data2.firstName || "";
118
+ const lastName = data2.lastName || "";
119
+ const fullName = `${firstName} ${lastName}`.trim() || "N/A";
120
+ const content = `MagicMark Plugin License Key
121
+ ═══════════════════════════════════════
122
+
123
+ License Key: ${licenseKey}
124
+
125
+ License Holder Information:
126
+ ──────────────────────────────────────
127
+ Name: ${fullName}
128
+ Email: ${email}
129
+
130
+ License Status:
131
+ ──────────────────────────────────────
132
+ Status: ${data2.isActive ? "ACTIVE" : "INACTIVE"}
133
+ Expires: ${data2.expiresAt ? new Date(data2.expiresAt).toLocaleDateString() : "Never"}
134
+
135
+ ═══════════════════════════════════════
136
+ Generated: ${(/* @__PURE__ */ new Date()).toLocaleString()}
137
+ `;
138
+ const blob = new Blob([content], { type: "text/plain" });
139
+ const url = window.URL.createObjectURL(blob);
140
+ const link = document.createElement("a");
141
+ link.href = url;
142
+ link.download = `magicmark-license-${licenseKey.substring(0, 8)}.txt`;
143
+ document.body.appendChild(link);
144
+ link.click();
145
+ document.body.removeChild(link);
146
+ window.URL.revokeObjectURL(url);
147
+ toggleNotification({
148
+ type: "success",
149
+ message: "License key downloaded successfully!"
150
+ });
151
+ } catch (err) {
152
+ toggleNotification({
153
+ type: "danger",
154
+ message: "Failed to download license key"
155
+ });
156
+ }
157
+ };
158
+ React.useEffect(() => {
159
+ fetchLicenseStatus();
160
+ }, []);
161
+ if (loading) {
162
+ return /* @__PURE__ */ jsxRuntime.jsx(Container, { children: /* @__PURE__ */ jsxRuntime.jsx(LoaderContainer, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Loader, { children: "Loading license information..." }) }) });
163
+ }
164
+ if (error) {
165
+ return /* @__PURE__ */ jsxRuntime.jsx(Container, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { padding: 8, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Alert, { variant: "danger", title: "Error", closeLabel: "Close", children: error }) }) });
166
+ }
167
+ const isValid = licenseData?.valid;
168
+ const isDemo = licenseData?.demo;
169
+ const data = licenseData?.data || {};
170
+ return /* @__PURE__ */ jsxRuntime.jsxs(Container, { children: [
171
+ /* @__PURE__ */ jsxRuntime.jsx(StickySaveBar, { paddingTop: 5, paddingBottom: 5, paddingLeft: 6, paddingRight: 6, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { justifyContent: "space-between", alignItems: "center", children: [
172
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", gap: 1, children: [
173
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "alpha", fontWeight: "bold", children: "License Management" }),
174
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "epsilon", textColor: "neutral600", children: "View your MagicMark plugin license" })
175
+ ] }),
176
+ /* @__PURE__ */ jsxRuntime.jsx(
177
+ designSystem.Button,
178
+ {
179
+ startIcon: /* @__PURE__ */ jsxRuntime.jsx(icons.ArrowClockwise, {}),
180
+ onClick: fetchLicenseStatus,
181
+ size: "L",
182
+ style: {
183
+ background: "linear-gradient(135deg, #667eea 0%, #764ba2 100%)",
184
+ color: "white",
185
+ fontWeight: "600",
186
+ border: "none"
187
+ },
188
+ children: "Refresh Status"
189
+ }
190
+ )
191
+ ] }) }),
192
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { paddingTop: 6, paddingLeft: 6, paddingRight: 6, paddingBottom: 10, children: [
193
+ isDemo ? /* @__PURE__ */ jsxRuntime.jsx(designSystem.Alert, { variant: "warning", title: "Demo Mode", closeLabel: "Close", children: "You're using the demo version. Create a license to unlock all features." }) : isValid ? /* @__PURE__ */ jsxRuntime.jsx(designSystem.Alert, { variant: "success", title: "License Active", closeLabel: "Close", children: "Your license is active and all features are unlocked." }) : /* @__PURE__ */ jsxRuntime.jsx(designSystem.Alert, { variant: "danger", title: "License Issue", closeLabel: "Close", children: "There's an issue with your license. Please check your license status." }),
194
+ data.licenseKey && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { marginTop: 6, children: /* @__PURE__ */ jsxRuntime.jsx(LicenseKeyBanner, { children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { justifyContent: "space-between", alignItems: "flex-start", children: [
195
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { style: { flex: 1 }, children: [
196
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", style: { color: "rgba(255,255,255,0.8)", marginBottom: "12px", textTransform: "uppercase", fontSize: "11px", letterSpacing: "0.5px", display: "block" }, children: "License Key" }),
197
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { style: { color: "white", fontFamily: "monospace", fontSize: "28px", fontWeight: "bold", wordBreak: "break-all", marginBottom: "16px" }, children: data.licenseKey }),
198
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
199
+ /* @__PURE__ */ jsxRuntime.jsx(
200
+ designSystem.Button,
201
+ {
202
+ onClick: handleCopyLicenseKey,
203
+ startIcon: /* @__PURE__ */ jsxRuntime.jsx(icons.Duplicate, {}),
204
+ size: "S",
205
+ variant: "secondary",
206
+ style: {
207
+ backgroundColor: "rgba(255,255,255,0.2)",
208
+ color: "white",
209
+ border: "1px solid rgba(255,255,255,0.3)",
210
+ fontWeight: "600"
211
+ },
212
+ children: "Copy Key"
213
+ }
214
+ ),
215
+ /* @__PURE__ */ jsxRuntime.jsx(
216
+ designSystem.Button,
217
+ {
218
+ onClick: handleDownloadLicenseKey,
219
+ startIcon: /* @__PURE__ */ jsxRuntime.jsx(icons.Download, {}),
220
+ size: "S",
221
+ variant: "secondary",
222
+ style: {
223
+ backgroundColor: "rgba(255,255,255,0.2)",
224
+ color: "white",
225
+ border: "1px solid rgba(255,255,255,0.3)",
226
+ fontWeight: "600"
227
+ },
228
+ children: "Download as TXT"
229
+ }
230
+ )
231
+ ] })
232
+ ] }),
233
+ /* @__PURE__ */ jsxRuntime.jsx(
234
+ designSystem.Badge,
235
+ {
236
+ backgroundColor: data.isActive ? "success100" : "danger100",
237
+ textColor: data.isActive ? "success700" : "danger700",
238
+ style: { fontSize: "11px", fontWeight: "700", padding: "6px 12px", marginLeft: "16px", flexShrink: 0 },
239
+ children: data.isActive ? "ACTIVE" : "INACTIVE"
240
+ }
241
+ )
242
+ ] }) }) }),
243
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { marginTop: 6, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Accordion.Root, { defaultValue: "account", collapsible: true, children: [
244
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Accordion.Item, { value: "account", children: [
245
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Accordion.Header, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Accordion.Trigger, { icon: icons.User, children: "Account Information" }) }),
246
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Accordion.Content, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { padding: 6, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 8, wrap: "wrap", children: [
247
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { style: { flex: "1", minWidth: "200px" }, children: [
248
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "sigma", textColor: "neutral600", textTransform: "uppercase", style: { marginBottom: "8px", display: "block" }, children: "Email Address" }),
249
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "omega", fontWeight: "semiBold", children: data.email || "Not provided" })
250
+ ] }),
251
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { style: { flex: "1", minWidth: "200px" }, children: [
252
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "sigma", textColor: "neutral600", textTransform: "uppercase", style: { marginBottom: "8px", display: "block" }, children: "License Holder" }),
253
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "omega", fontWeight: "semiBold", children: data.firstName && data.lastName ? `${data.firstName} ${data.lastName}` : "Not specified" })
254
+ ] })
255
+ ] }) }) })
256
+ ] }),
257
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Accordion.Item, { value: "details", children: [
258
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Accordion.Header, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Accordion.Trigger, { icon: icons.Shield, children: "License Details" }) }),
259
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Accordion.Content, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { padding: 6, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 8, wrap: "wrap", children: [
260
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { style: { flex: "1", minWidth: "180px" }, children: [
261
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "sigma", textColor: "neutral600", textTransform: "uppercase", style: { marginBottom: "8px", display: "block" }, children: data.isExpired ? "Expired On" : "Expires On" }),
262
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "omega", fontWeight: "semiBold", children: data.expiresAt ? new Date(data.expiresAt).toLocaleDateString("en-US", {
263
+ year: "numeric",
264
+ month: "long",
265
+ day: "numeric"
266
+ }) : "Never" })
267
+ ] }),
268
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { style: { flex: "1", minWidth: "180px" }, children: [
269
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "sigma", textColor: "neutral600", textTransform: "uppercase", style: { marginBottom: "8px", display: "block" }, children: "Device Name" }),
270
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "omega", fontWeight: "semiBold", children: data.deviceName || "Unknown" })
271
+ ] }),
272
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { style: { flex: "1", minWidth: "180px" }, children: [
273
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "sigma", textColor: "neutral600", textTransform: "uppercase", style: { marginBottom: "8px", display: "block" }, children: "IP Address" }),
274
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "omega", fontWeight: "semiBold", children: data.ipAddress || "Not detected" })
275
+ ] })
276
+ ] }) }) })
277
+ ] }),
278
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Accordion.Item, { value: "features", children: [
279
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Accordion.Header, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Accordion.Trigger, { icon: icons.Sparkle, children: "Features & Capabilities" }) }),
280
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Accordion.Content, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { padding: 6, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 8, wrap: "wrap", children: [
281
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { style: { flex: "1", minWidth: "180px" }, children: [
282
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "sigma", textColor: "neutral600", textTransform: "uppercase", style: { marginBottom: "8px", display: "block" }, children: "Premium Features" }),
283
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "omega", fontWeight: "semiBold", children: data.features?.premium ? "✓ Enabled" : "✗ Disabled" })
284
+ ] }),
285
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { style: { flex: "1", minWidth: "180px" }, children: [
286
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "sigma", textColor: "neutral600", textTransform: "uppercase", style: { marginBottom: "8px", display: "block" }, children: "Advanced Features" }),
287
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "omega", fontWeight: "semiBold", children: data.features?.advanced ? "✓ Enabled" : "✗ Disabled" })
288
+ ] }),
289
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { style: { flex: "1", minWidth: "180px" }, children: [
290
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "sigma", textColor: "neutral600", textTransform: "uppercase", style: { marginBottom: "8px", display: "block" }, children: "Enterprise Features" }),
291
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "omega", fontWeight: "semiBold", children: data.features?.enterprise ? "✓ Enabled" : "✗ Disabled" })
292
+ ] })
293
+ ] }) }) })
294
+ ] }),
295
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Accordion.Item, { value: "status", children: [
296
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Accordion.Header, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Accordion.Trigger, { icon: icons.ChartBubble, children: "System Status" }) }),
297
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Accordion.Content, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { padding: 6, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 8, wrap: "wrap", children: [
298
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { style: { flex: "1", minWidth: "150px" }, children: [
299
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "sigma", textColor: "neutral600", textTransform: "uppercase", style: { marginBottom: "8px", display: "block" }, children: "License Status" }),
300
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "omega", fontWeight: "semiBold", children: data.isActive ? "Active" : "Inactive" })
301
+ ] }),
302
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { style: { flex: "1", minWidth: "150px" }, children: [
303
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "sigma", textColor: "neutral600", textTransform: "uppercase", style: { marginBottom: "8px", display: "block" }, children: "Connection" }),
304
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "omega", fontWeight: "semiBold", children: data.isOnline ? "Online" : "Offline" })
305
+ ] }),
306
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { style: { flex: "1", minWidth: "150px" }, children: [
307
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "sigma", textColor: "neutral600", textTransform: "uppercase", style: { marginBottom: "8px", display: "block" }, children: "Last Sync" }),
308
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "omega", fontWeight: "semiBold", children: data.lastPingAt ? new Date(data.lastPingAt).toLocaleTimeString() : "Never" })
309
+ ] }),
310
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { style: { flex: "1", minWidth: "150px" }, children: [
311
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "sigma", textColor: "neutral600", textTransform: "uppercase", style: { marginBottom: "8px", display: "block" }, children: "Device Limit" }),
312
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { variant: "omega", fontWeight: "semiBold", children: [
313
+ data.currentDevices || 0,
314
+ " / ",
315
+ data.maxDevices || 1
316
+ ] })
317
+ ] })
318
+ ] }) }) })
319
+ ] })
320
+ ] }) })
321
+ ] })
322
+ ] });
323
+ };
324
+ exports.default = LicensePage;