strapi-plugin-magic-mail 1.0.1
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/COPYRIGHT_NOTICE.txt +13 -0
- package/LICENSE +22 -0
- package/README.md +1420 -0
- package/admin/jsconfig.json +10 -0
- package/admin/src/components/AddAccountModal.jsx +1943 -0
- package/admin/src/components/Initializer.jsx +14 -0
- package/admin/src/components/LicenseGuard.jsx +475 -0
- package/admin/src/components/PluginIcon.jsx +5 -0
- package/admin/src/hooks/useAuthRefresh.js +44 -0
- package/admin/src/hooks/useLicense.js +158 -0
- package/admin/src/index.js +86 -0
- package/admin/src/pages/Analytics.jsx +762 -0
- package/admin/src/pages/App.jsx +111 -0
- package/admin/src/pages/EmailDesigner/EditorPage.jsx +1405 -0
- package/admin/src/pages/EmailDesigner/TemplateList.jsx +1807 -0
- package/admin/src/pages/HomePage.jsx +1233 -0
- package/admin/src/pages/LicensePage.jsx +424 -0
- package/admin/src/pages/RoutingRules.jsx +1141 -0
- package/admin/src/pages/Settings.jsx +603 -0
- package/admin/src/pluginId.js +3 -0
- package/admin/src/translations/de.json +71 -0
- package/admin/src/translations/en.json +70 -0
- package/admin/src/translations/es.json +71 -0
- package/admin/src/translations/fr.json +71 -0
- package/admin/src/translations/pt.json +71 -0
- package/admin/src/utils/fetchWithRetry.js +123 -0
- package/admin/src/utils/getTranslation.js +5 -0
- package/dist/_chunks/App-B-Gp4Vbr.js +7568 -0
- package/dist/_chunks/App-BymMjoGM.mjs +7543 -0
- package/dist/_chunks/LicensePage-Bl02myMx.mjs +342 -0
- package/dist/_chunks/LicensePage-CJXwPnEe.js +344 -0
- package/dist/_chunks/Settings-C_TmKwcz.mjs +400 -0
- package/dist/_chunks/Settings-zuFQ3pnn.js +402 -0
- package/dist/_chunks/de-CN-G9j1S.js +64 -0
- package/dist/_chunks/de-DS04rP54.mjs +64 -0
- package/dist/_chunks/en-BDc7Jk8u.js +64 -0
- package/dist/_chunks/en-BEFQJXvR.mjs +64 -0
- package/dist/_chunks/es-BpV1MIdm.js +64 -0
- package/dist/_chunks/es-DQHwzPpP.mjs +64 -0
- package/dist/_chunks/fr-BG1WfEVm.mjs +64 -0
- package/dist/_chunks/fr-vpziIpRp.js +64 -0
- package/dist/_chunks/pt-CMoGrOib.mjs +64 -0
- package/dist/_chunks/pt-ODpAhDNa.js +64 -0
- package/dist/admin/index.js +89 -0
- package/dist/admin/index.mjs +90 -0
- package/dist/server/index.js +6214 -0
- package/dist/server/index.mjs +6208 -0
- package/package.json +113 -0
- package/server/jsconfig.json +10 -0
- package/server/src/bootstrap.js +153 -0
- package/server/src/config/features.js +260 -0
- package/server/src/config/index.js +6 -0
- package/server/src/content-types/email-account/schema.json +93 -0
- package/server/src/content-types/email-event/index.js +8 -0
- package/server/src/content-types/email-event/schema.json +57 -0
- package/server/src/content-types/email-link/index.js +8 -0
- package/server/src/content-types/email-link/schema.json +49 -0
- package/server/src/content-types/email-log/index.js +8 -0
- package/server/src/content-types/email-log/schema.json +106 -0
- package/server/src/content-types/email-template/schema.json +74 -0
- package/server/src/content-types/email-template-version/schema.json +60 -0
- package/server/src/content-types/index.js +33 -0
- package/server/src/content-types/routing-rule/schema.json +59 -0
- package/server/src/controllers/accounts.js +220 -0
- package/server/src/controllers/analytics.js +347 -0
- package/server/src/controllers/controller.js +26 -0
- package/server/src/controllers/email-designer.js +474 -0
- package/server/src/controllers/index.js +21 -0
- package/server/src/controllers/license.js +267 -0
- package/server/src/controllers/oauth.js +474 -0
- package/server/src/controllers/routing-rules.js +122 -0
- package/server/src/controllers/test.js +383 -0
- package/server/src/destroy.js +23 -0
- package/server/src/index.js +25 -0
- package/server/src/middlewares/index.js +3 -0
- package/server/src/policies/index.js +3 -0
- package/server/src/register.js +5 -0
- package/server/src/routes/admin.js +469 -0
- package/server/src/routes/content-api.js +37 -0
- package/server/src/routes/index.js +9 -0
- package/server/src/services/account-manager.js +277 -0
- package/server/src/services/analytics.js +496 -0
- package/server/src/services/email-designer.js +870 -0
- package/server/src/services/email-router.js +1420 -0
- package/server/src/services/index.js +17 -0
- package/server/src/services/license-guard.js +418 -0
- package/server/src/services/oauth.js +515 -0
- package/server/src/services/service.js +7 -0
- package/server/src/utils/encryption.js +81 -0
- package/strapi-admin.js +4 -0
- package/strapi-server.js +4 -0
|
@@ -0,0 +1,603 @@
|
|
|
1
|
+
import { useState, useEffect } from 'react';
|
|
2
|
+
import {
|
|
3
|
+
Box,
|
|
4
|
+
Typography,
|
|
5
|
+
Badge,
|
|
6
|
+
Flex,
|
|
7
|
+
Alert,
|
|
8
|
+
Button,
|
|
9
|
+
Loader,
|
|
10
|
+
Accordion,
|
|
11
|
+
} from '@strapi/design-system';
|
|
12
|
+
import { useFetchClient, useNotification } from '@strapi/strapi/admin';
|
|
13
|
+
import {
|
|
14
|
+
ArrowPathIcon,
|
|
15
|
+
KeyIcon,
|
|
16
|
+
UserIcon,
|
|
17
|
+
ShieldCheckIcon,
|
|
18
|
+
SparklesIcon,
|
|
19
|
+
ChartBarIcon,
|
|
20
|
+
DocumentDuplicateIcon,
|
|
21
|
+
ArrowDownTrayIcon,
|
|
22
|
+
} from '@heroicons/react/24/outline';
|
|
23
|
+
import styled, { keyframes, css } from 'styled-components';
|
|
24
|
+
|
|
25
|
+
// ================ THEME ================
|
|
26
|
+
const theme = {
|
|
27
|
+
colors: {
|
|
28
|
+
primary: { 600: '#0EA5E9', 100: '#E0F2FE', 50: '#F0F9FF' },
|
|
29
|
+
success: { 600: '#16A34A', 50: '#DCFCE7' },
|
|
30
|
+
warning: { 50: '#FEF3C7' },
|
|
31
|
+
danger: { 50: '#FEE2E2' },
|
|
32
|
+
neutral: { 0: '#FFFFFF', 100: '#F3F4F6', 200: '#E5E7EB', 600: '#4B5563', 800: '#1F2937' }
|
|
33
|
+
},
|
|
34
|
+
shadows: { sm: '0 1px 3px rgba(0,0,0,0.1)' },
|
|
35
|
+
borderRadius: { lg: '12px' }
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
// ================ ANIMATIONS ================
|
|
39
|
+
const fadeIn = keyframes`
|
|
40
|
+
from { opacity: 0; transform: translateY(10px); }
|
|
41
|
+
to { opacity: 1; transform: translateY(0); }
|
|
42
|
+
`;
|
|
43
|
+
|
|
44
|
+
const shimmer = keyframes`
|
|
45
|
+
0% { background-position: -200% 0; }
|
|
46
|
+
100% { background-position: 200% 0; }
|
|
47
|
+
`;
|
|
48
|
+
|
|
49
|
+
// ================ STYLED COMPONENTS ================
|
|
50
|
+
const Container = styled(Box)`
|
|
51
|
+
${css`animation: ${fadeIn} 0.5s;`}
|
|
52
|
+
max-width: 1400px;
|
|
53
|
+
margin: 0 auto;
|
|
54
|
+
`;
|
|
55
|
+
|
|
56
|
+
const StickySaveBar = styled(Box)`
|
|
57
|
+
position: sticky;
|
|
58
|
+
top: 0;
|
|
59
|
+
z-index: 10;
|
|
60
|
+
background: white;
|
|
61
|
+
border-bottom: 1px solid ${theme.colors.neutral[200]};
|
|
62
|
+
box-shadow: ${theme.shadows.sm};
|
|
63
|
+
`;
|
|
64
|
+
|
|
65
|
+
const LicenseKeyBanner = styled(Box)`
|
|
66
|
+
background: linear-gradient(135deg, #0EA5E9 0%, #A855F7 100%);
|
|
67
|
+
border-radius: ${theme.borderRadius.lg};
|
|
68
|
+
padding: 28px 32px;
|
|
69
|
+
color: white;
|
|
70
|
+
position: relative;
|
|
71
|
+
overflow: hidden;
|
|
72
|
+
box-shadow: 0 4px 20px rgba(14, 165, 233, 0.25);
|
|
73
|
+
margin-bottom: 24px;
|
|
74
|
+
|
|
75
|
+
&::after {
|
|
76
|
+
content: '';
|
|
77
|
+
position: absolute;
|
|
78
|
+
top: -50%;
|
|
79
|
+
right: -50%;
|
|
80
|
+
width: 200%;
|
|
81
|
+
height: 200%;
|
|
82
|
+
background: linear-gradient(
|
|
83
|
+
45deg,
|
|
84
|
+
transparent,
|
|
85
|
+
rgba(255, 255, 255, 0.08),
|
|
86
|
+
transparent
|
|
87
|
+
);
|
|
88
|
+
${css`animation: ${shimmer} 3s infinite;`}
|
|
89
|
+
pointer-events: none;
|
|
90
|
+
z-index: 0;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
& > * {
|
|
94
|
+
position: relative;
|
|
95
|
+
z-index: 1;
|
|
96
|
+
}
|
|
97
|
+
`;
|
|
98
|
+
|
|
99
|
+
const LoaderContainer = styled(Flex)`
|
|
100
|
+
min-height: 400px;
|
|
101
|
+
align-items: center;
|
|
102
|
+
justify-content: center;
|
|
103
|
+
flex-direction: column;
|
|
104
|
+
gap: 16px;
|
|
105
|
+
`;
|
|
106
|
+
|
|
107
|
+
// ================ MAIN COMPONENT ================
|
|
108
|
+
const LicensePage = () => {
|
|
109
|
+
const { get } = useFetchClient();
|
|
110
|
+
const { toggleNotification } = useNotification();
|
|
111
|
+
const [loading, setLoading] = useState(true);
|
|
112
|
+
const [licenseData, setLicenseData] = useState(null);
|
|
113
|
+
const [error, setError] = useState(null);
|
|
114
|
+
|
|
115
|
+
const fetchLicenseStatus = async () => {
|
|
116
|
+
setLoading(true);
|
|
117
|
+
setError(null);
|
|
118
|
+
|
|
119
|
+
try {
|
|
120
|
+
const response = await get('/magic-mail/license/status');
|
|
121
|
+
setLicenseData(response.data);
|
|
122
|
+
} catch (err) {
|
|
123
|
+
console.error('[MagicMail] Error fetching license:', err);
|
|
124
|
+
setError('Failed to load license information');
|
|
125
|
+
} finally {
|
|
126
|
+
setLoading(false);
|
|
127
|
+
}
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
const handleCopyLicenseKey = async () => {
|
|
131
|
+
try {
|
|
132
|
+
await navigator.clipboard.writeText(licenseData?.data?.licenseKey || '');
|
|
133
|
+
toggleNotification({
|
|
134
|
+
type: 'success',
|
|
135
|
+
message: 'License key copied to clipboard!',
|
|
136
|
+
});
|
|
137
|
+
} catch (err) {
|
|
138
|
+
toggleNotification({
|
|
139
|
+
type: 'danger',
|
|
140
|
+
message: 'Failed to copy license key',
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
const handleDownloadLicenseKey = () => {
|
|
146
|
+
try {
|
|
147
|
+
const data = licenseData?.data || {};
|
|
148
|
+
const licenseKey = data.licenseKey || '';
|
|
149
|
+
const email = data.email || 'N/A';
|
|
150
|
+
const firstName = data.firstName || '';
|
|
151
|
+
const lastName = data.lastName || '';
|
|
152
|
+
const fullName = `${firstName} ${lastName}`.trim() || 'N/A';
|
|
153
|
+
|
|
154
|
+
const content = `MagicMail - Email Business Suite - License Key
|
|
155
|
+
═══════════════════════════════════════
|
|
156
|
+
|
|
157
|
+
License Key: ${licenseKey}
|
|
158
|
+
|
|
159
|
+
License Holder Information:
|
|
160
|
+
──────────────────────────────────────
|
|
161
|
+
Name: ${fullName}
|
|
162
|
+
Email: ${email}
|
|
163
|
+
|
|
164
|
+
License Status:
|
|
165
|
+
──────────────────────────────────────
|
|
166
|
+
Status: ${data.isActive ? 'ACTIVE' : 'INACTIVE'}
|
|
167
|
+
Expires: ${data.expiresAt ? new Date(data.expiresAt).toLocaleDateString() : 'Never'}
|
|
168
|
+
|
|
169
|
+
Features:
|
|
170
|
+
──────────────────────────────────────
|
|
171
|
+
Premium: ${data.features?.premium ? 'Enabled' : 'Disabled'}
|
|
172
|
+
Advanced: ${data.features?.advanced ? 'Enabled' : 'Disabled'}
|
|
173
|
+
Enterprise: ${data.features?.enterprise ? 'Enabled' : 'Disabled'}
|
|
174
|
+
|
|
175
|
+
═══════════════════════════════════════
|
|
176
|
+
Generated: ${new Date().toLocaleString()}
|
|
177
|
+
`;
|
|
178
|
+
|
|
179
|
+
const blob = new Blob([content], { type: 'text/plain' });
|
|
180
|
+
const url = window.URL.createObjectURL(blob);
|
|
181
|
+
const link = document.createElement('a');
|
|
182
|
+
link.href = url;
|
|
183
|
+
link.download = `magicmail-license-${licenseKey.substring(0, 8)}.txt`;
|
|
184
|
+
document.body.appendChild(link);
|
|
185
|
+
link.click();
|
|
186
|
+
document.body.removeChild(link);
|
|
187
|
+
window.URL.revokeObjectURL(url);
|
|
188
|
+
|
|
189
|
+
toggleNotification({
|
|
190
|
+
type: 'success',
|
|
191
|
+
message: 'License key downloaded successfully!',
|
|
192
|
+
});
|
|
193
|
+
} catch (err) {
|
|
194
|
+
toggleNotification({
|
|
195
|
+
type: 'danger',
|
|
196
|
+
message: 'Failed to download license key',
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
};
|
|
200
|
+
|
|
201
|
+
useEffect(() => {
|
|
202
|
+
fetchLicenseStatus();
|
|
203
|
+
}, []);
|
|
204
|
+
|
|
205
|
+
if (loading) {
|
|
206
|
+
return (
|
|
207
|
+
<Container>
|
|
208
|
+
<LoaderContainer>
|
|
209
|
+
<Loader>Loading license information...</Loader>
|
|
210
|
+
</LoaderContainer>
|
|
211
|
+
</Container>
|
|
212
|
+
);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
if (error) {
|
|
216
|
+
return (
|
|
217
|
+
<Container>
|
|
218
|
+
<Box padding={8}>
|
|
219
|
+
<Alert variant="danger" title="Error" closeLabel="Close">
|
|
220
|
+
{error}
|
|
221
|
+
</Alert>
|
|
222
|
+
</Box>
|
|
223
|
+
</Container>
|
|
224
|
+
);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
const isValid = licenseData?.valid;
|
|
228
|
+
const isDemo = licenseData?.demo;
|
|
229
|
+
const data = licenseData?.data || {};
|
|
230
|
+
|
|
231
|
+
return (
|
|
232
|
+
<Container>
|
|
233
|
+
{/* Sticky Header */}
|
|
234
|
+
<StickySaveBar paddingTop={5} paddingBottom={5} paddingLeft={6} paddingRight={6}>
|
|
235
|
+
<Flex justifyContent="space-between" alignItems="flex-start">
|
|
236
|
+
<Flex direction="column" gap={1} alignItems="flex-start">
|
|
237
|
+
<Typography variant="alpha" fontWeight="bold">
|
|
238
|
+
License Management
|
|
239
|
+
</Typography>
|
|
240
|
+
<Typography variant="epsilon" textColor="neutral600">
|
|
241
|
+
View your MagicMail plugin license
|
|
242
|
+
</Typography>
|
|
243
|
+
</Flex>
|
|
244
|
+
<Button
|
|
245
|
+
startIcon={<ArrowPathIcon style={{ width: 20, height: 20 }} />}
|
|
246
|
+
onClick={fetchLicenseStatus}
|
|
247
|
+
size="L"
|
|
248
|
+
style={{
|
|
249
|
+
background: 'linear-gradient(135deg, #0EA5E9 0%, #A855F7 100%)',
|
|
250
|
+
color: 'white',
|
|
251
|
+
fontWeight: '600',
|
|
252
|
+
border: 'none',
|
|
253
|
+
}}
|
|
254
|
+
>
|
|
255
|
+
Refresh Status
|
|
256
|
+
</Button>
|
|
257
|
+
</Flex>
|
|
258
|
+
</StickySaveBar>
|
|
259
|
+
|
|
260
|
+
{/* Content */}
|
|
261
|
+
<Box paddingTop={6} paddingLeft={6} paddingRight={6} paddingBottom={10}>
|
|
262
|
+
{/* Status Alert */}
|
|
263
|
+
{isDemo ? (
|
|
264
|
+
<Alert variant="warning" title="Demo Mode" closeLabel="Close">
|
|
265
|
+
You're using the demo version. Create a license to unlock all features.
|
|
266
|
+
</Alert>
|
|
267
|
+
) : isValid ? (
|
|
268
|
+
<Alert variant="success" title="License Active" closeLabel="Close">
|
|
269
|
+
Your license is active and all features are unlocked.
|
|
270
|
+
</Alert>
|
|
271
|
+
) : (
|
|
272
|
+
<Alert variant="danger" title="License Issue" closeLabel="Close">
|
|
273
|
+
There's an issue with your license. Please check your license status.
|
|
274
|
+
</Alert>
|
|
275
|
+
)}
|
|
276
|
+
|
|
277
|
+
{/* License Key */}
|
|
278
|
+
{data.licenseKey && (
|
|
279
|
+
<Box marginTop={6}>
|
|
280
|
+
<LicenseKeyBanner>
|
|
281
|
+
<Flex justifyContent="space-between" alignItems="flex-start">
|
|
282
|
+
<Box style={{ flex: 1 }}>
|
|
283
|
+
<Typography variant="pi" style={{ color: 'rgba(255,255,255,0.8)', marginBottom: '12px', textTransform: 'uppercase', fontSize: '11px', letterSpacing: '0.5px', display: 'block' }}>
|
|
284
|
+
License Key
|
|
285
|
+
</Typography>
|
|
286
|
+
<Typography style={{ color: 'white', fontFamily: 'monospace', fontSize: '28px', fontWeight: 'bold', wordBreak: 'break-all', marginBottom: '16px' }}>
|
|
287
|
+
{data.licenseKey}
|
|
288
|
+
</Typography>
|
|
289
|
+
<Flex gap={2}>
|
|
290
|
+
<Button
|
|
291
|
+
onClick={handleCopyLicenseKey}
|
|
292
|
+
startIcon={<DocumentDuplicateIcon style={{ width: 16, height: 16 }} />}
|
|
293
|
+
size="S"
|
|
294
|
+
variant="secondary"
|
|
295
|
+
style={{
|
|
296
|
+
backgroundColor: 'rgba(255,255,255,0.2)',
|
|
297
|
+
color: 'white',
|
|
298
|
+
border: '1px solid rgba(255,255,255,0.3)',
|
|
299
|
+
fontWeight: '600',
|
|
300
|
+
}}
|
|
301
|
+
>
|
|
302
|
+
Copy Key
|
|
303
|
+
</Button>
|
|
304
|
+
<Button
|
|
305
|
+
onClick={handleDownloadLicenseKey}
|
|
306
|
+
startIcon={<ArrowDownTrayIcon style={{ width: 16, height: 16 }} />}
|
|
307
|
+
size="S"
|
|
308
|
+
variant="secondary"
|
|
309
|
+
style={{
|
|
310
|
+
backgroundColor: 'rgba(255,255,255,0.2)',
|
|
311
|
+
color: 'white',
|
|
312
|
+
border: '1px solid rgba(255,255,255,0.3)',
|
|
313
|
+
fontWeight: '600',
|
|
314
|
+
}}
|
|
315
|
+
>
|
|
316
|
+
Download as TXT
|
|
317
|
+
</Button>
|
|
318
|
+
</Flex>
|
|
319
|
+
</Box>
|
|
320
|
+
<Badge
|
|
321
|
+
backgroundColor={data.isActive ? "success100" : "danger100"}
|
|
322
|
+
textColor={data.isActive ? "success700" : "danger700"}
|
|
323
|
+
style={{ fontSize: '11px', fontWeight: '700', padding: '6px 12px', marginLeft: '16px', flexShrink: 0 }}
|
|
324
|
+
>
|
|
325
|
+
{data.isActive ? 'ACTIVE' : 'INACTIVE'}
|
|
326
|
+
</Badge>
|
|
327
|
+
</Flex>
|
|
328
|
+
</LicenseKeyBanner>
|
|
329
|
+
</Box>
|
|
330
|
+
)}
|
|
331
|
+
|
|
332
|
+
{/* Details Section */}
|
|
333
|
+
<Box marginTop={6}>
|
|
334
|
+
<Accordion.Root defaultValue="account" collapsible>
|
|
335
|
+
{/* Account Information */}
|
|
336
|
+
<Accordion.Item value="account">
|
|
337
|
+
<Accordion.Header>
|
|
338
|
+
<Accordion.Trigger icon={() => <UserIcon style={{ width: 16, height: 16 }} />}>
|
|
339
|
+
Account Information
|
|
340
|
+
</Accordion.Trigger>
|
|
341
|
+
</Accordion.Header>
|
|
342
|
+
<Accordion.Content>
|
|
343
|
+
<Box padding={6}>
|
|
344
|
+
<Flex gap={8} wrap="wrap">
|
|
345
|
+
<Box style={{ flex: '1', minWidth: '200px' }}>
|
|
346
|
+
<Typography variant="sigma" textColor="neutral600" textTransform="uppercase" style={{ marginBottom: '8px', display: 'block' }}>
|
|
347
|
+
Email Address
|
|
348
|
+
</Typography>
|
|
349
|
+
<Typography variant="omega" fontWeight="semiBold">
|
|
350
|
+
{data.email || 'Not provided'}
|
|
351
|
+
</Typography>
|
|
352
|
+
</Box>
|
|
353
|
+
<Box style={{ flex: '1', minWidth: '200px' }}>
|
|
354
|
+
<Typography variant="sigma" textColor="neutral600" textTransform="uppercase" style={{ marginBottom: '8px', display: 'block' }}>
|
|
355
|
+
License Holder
|
|
356
|
+
</Typography>
|
|
357
|
+
<Typography variant="omega" fontWeight="semiBold">
|
|
358
|
+
{data.firstName && data.lastName
|
|
359
|
+
? `${data.firstName} ${data.lastName}`
|
|
360
|
+
: 'Not specified'
|
|
361
|
+
}
|
|
362
|
+
</Typography>
|
|
363
|
+
</Box>
|
|
364
|
+
</Flex>
|
|
365
|
+
</Box>
|
|
366
|
+
</Accordion.Content>
|
|
367
|
+
</Accordion.Item>
|
|
368
|
+
|
|
369
|
+
{/* License Details */}
|
|
370
|
+
<Accordion.Item value="details">
|
|
371
|
+
<Accordion.Header>
|
|
372
|
+
<Accordion.Trigger icon={() => <ShieldCheckIcon style={{ width: 16, height: 16 }} />}>
|
|
373
|
+
License Details
|
|
374
|
+
</Accordion.Trigger>
|
|
375
|
+
</Accordion.Header>
|
|
376
|
+
<Accordion.Content>
|
|
377
|
+
<Box padding={6}>
|
|
378
|
+
<Flex gap={8} wrap="wrap">
|
|
379
|
+
<Box style={{ flex: '1', minWidth: '180px' }}>
|
|
380
|
+
<Typography variant="sigma" textColor="neutral600" textTransform="uppercase" style={{ marginBottom: '8px', display: 'block' }}>
|
|
381
|
+
{data.isExpired ? 'Expired On' : 'Expires On'}
|
|
382
|
+
</Typography>
|
|
383
|
+
<Typography variant="omega" fontWeight="semiBold">
|
|
384
|
+
{data.expiresAt
|
|
385
|
+
? new Date(data.expiresAt).toLocaleDateString('en-US', {
|
|
386
|
+
year: 'numeric',
|
|
387
|
+
month: 'long',
|
|
388
|
+
day: 'numeric',
|
|
389
|
+
})
|
|
390
|
+
: 'Never'}
|
|
391
|
+
</Typography>
|
|
392
|
+
</Box>
|
|
393
|
+
<Box style={{ flex: '1', minWidth: '180px' }}>
|
|
394
|
+
<Typography variant="sigma" textColor="neutral600" textTransform="uppercase" style={{ marginBottom: '8px', display: 'block' }}>
|
|
395
|
+
Device Name
|
|
396
|
+
</Typography>
|
|
397
|
+
<Typography variant="omega" fontWeight="semiBold">
|
|
398
|
+
{data.deviceName || 'Unknown'}
|
|
399
|
+
</Typography>
|
|
400
|
+
</Box>
|
|
401
|
+
<Box style={{ flex: '1', minWidth: '180px' }}>
|
|
402
|
+
<Typography variant="sigma" textColor="neutral600" textTransform="uppercase" style={{ marginBottom: '8px', display: 'block' }}>
|
|
403
|
+
IP Address
|
|
404
|
+
</Typography>
|
|
405
|
+
<Typography variant="omega" fontWeight="semiBold">
|
|
406
|
+
{data.ipAddress || 'Not detected'}
|
|
407
|
+
</Typography>
|
|
408
|
+
</Box>
|
|
409
|
+
</Flex>
|
|
410
|
+
</Box>
|
|
411
|
+
</Accordion.Content>
|
|
412
|
+
</Accordion.Item>
|
|
413
|
+
|
|
414
|
+
{/* Features */}
|
|
415
|
+
<Accordion.Item value="features">
|
|
416
|
+
<Accordion.Header>
|
|
417
|
+
<Accordion.Trigger icon={() => <SparklesIcon style={{ width: 16, height: 16 }} />}>
|
|
418
|
+
Features & Capabilities
|
|
419
|
+
</Accordion.Trigger>
|
|
420
|
+
</Accordion.Header>
|
|
421
|
+
<Accordion.Content>
|
|
422
|
+
<Box padding={6}>
|
|
423
|
+
{/* Feature Tier Badges */}
|
|
424
|
+
<Flex gap={3} style={{ marginBottom: '32px' }}>
|
|
425
|
+
<Badge
|
|
426
|
+
backgroundColor={data.features?.premium ? "success100" : "neutral100"}
|
|
427
|
+
textColor={data.features?.premium ? "success700" : "neutral600"}
|
|
428
|
+
style={{
|
|
429
|
+
fontSize: '13px',
|
|
430
|
+
fontWeight: '700',
|
|
431
|
+
padding: '8px 16px',
|
|
432
|
+
border: data.features?.premium ? '2px solid #dcfce7' : '2px solid #e5e7eb'
|
|
433
|
+
}}
|
|
434
|
+
>
|
|
435
|
+
{data.features?.premium ? '✓' : '✗'} PREMIUM FEATURES
|
|
436
|
+
</Badge>
|
|
437
|
+
<Badge
|
|
438
|
+
backgroundColor={data.features?.advanced ? "primary100" : "neutral100"}
|
|
439
|
+
textColor={data.features?.advanced ? "primary700" : "neutral600"}
|
|
440
|
+
style={{
|
|
441
|
+
fontSize: '13px',
|
|
442
|
+
fontWeight: '700',
|
|
443
|
+
padding: '8px 16px',
|
|
444
|
+
border: data.features?.advanced ? '2px solid #bae6fd' : '2px solid #e5e7eb'
|
|
445
|
+
}}
|
|
446
|
+
>
|
|
447
|
+
{data.features?.advanced ? '✓' : '✗'} ADVANCED FEATURES
|
|
448
|
+
</Badge>
|
|
449
|
+
<Badge
|
|
450
|
+
backgroundColor={data.features?.enterprise ? "secondary100" : "neutral100"}
|
|
451
|
+
textColor={data.features?.enterprise ? "secondary700" : "neutral600"}
|
|
452
|
+
style={{
|
|
453
|
+
fontSize: '13px',
|
|
454
|
+
fontWeight: '700',
|
|
455
|
+
padding: '8px 16px',
|
|
456
|
+
border: data.features?.enterprise ? '2px solid #ddd6fe' : '2px solid #e5e7eb'
|
|
457
|
+
}}
|
|
458
|
+
>
|
|
459
|
+
{data.features?.enterprise ? '✓' : '✗'} ENTERPRISE FEATURES
|
|
460
|
+
</Badge>
|
|
461
|
+
</Flex>
|
|
462
|
+
|
|
463
|
+
{/* Premium Features */}
|
|
464
|
+
{data.features?.premium && (
|
|
465
|
+
<Box marginBottom={5} padding={5} background="success50" hasRadius style={{ border: '2px solid #dcfce7' }}>
|
|
466
|
+
<Typography variant="delta" fontWeight="bold" textColor="success700" style={{ marginBottom: '16px', display: 'flex', alignItems: 'center', gap: '8px' }}>
|
|
467
|
+
✨ Premium Features Active
|
|
468
|
+
</Typography>
|
|
469
|
+
<Flex direction="column" gap={2}>
|
|
470
|
+
<Typography variant="omega" textColor="success700" style={{ fontSize: '14px', display: 'flex', alignItems: 'center', gap: '8px' }}>
|
|
471
|
+
✓ Gmail OAuth 2.0 (Unlimited accounts)
|
|
472
|
+
</Typography>
|
|
473
|
+
<Typography variant="omega" textColor="success700" style={{ fontSize: '14px', display: 'flex', alignItems: 'center', gap: '8px' }}>
|
|
474
|
+
✓ Microsoft 365 OAuth Integration
|
|
475
|
+
</Typography>
|
|
476
|
+
<Typography variant="omega" textColor="success700" style={{ fontSize: '14px', display: 'flex', alignItems: 'center', gap: '8px' }}>
|
|
477
|
+
✓ Yahoo Mail OAuth
|
|
478
|
+
</Typography>
|
|
479
|
+
<Typography variant="omega" textColor="success700" style={{ fontSize: '14px', display: 'flex', alignItems: 'center', gap: '8px' }}>
|
|
480
|
+
✓ SendGrid & Mailgun Integration
|
|
481
|
+
</Typography>
|
|
482
|
+
<Typography variant="omega" textColor="success700" style={{ fontSize: '14px', display: 'flex', alignItems: 'center', gap: '8px' }}>
|
|
483
|
+
✓ Smart Routing Rules (Unlimited)
|
|
484
|
+
</Typography>
|
|
485
|
+
<Typography variant="omega" textColor="success700" style={{ fontSize: '14px', display: 'flex', alignItems: 'center', gap: '8px' }}>
|
|
486
|
+
✓ Email Analytics Dashboard
|
|
487
|
+
</Typography>
|
|
488
|
+
</Flex>
|
|
489
|
+
</Box>
|
|
490
|
+
)}
|
|
491
|
+
|
|
492
|
+
{/* Advanced Features */}
|
|
493
|
+
{data.features?.advanced && (
|
|
494
|
+
<Box marginBottom={5} padding={5} background="primary50" hasRadius style={{ border: '2px solid #bae6fd' }}>
|
|
495
|
+
<Typography variant="delta" fontWeight="bold" textColor="primary700" style={{ marginBottom: '16px', display: 'flex', alignItems: 'center', gap: '8px' }}>
|
|
496
|
+
🚀 Advanced Features Active
|
|
497
|
+
</Typography>
|
|
498
|
+
<Flex direction="column" gap={2}>
|
|
499
|
+
<Typography variant="omega" textColor="primary700" style={{ fontSize: '14px', display: 'flex', alignItems: 'center', gap: '8px' }}>
|
|
500
|
+
✓ DKIM Signing for SMTP
|
|
501
|
+
</Typography>
|
|
502
|
+
<Typography variant="omega" textColor="primary700" style={{ fontSize: '14px', display: 'flex', alignItems: 'center', gap: '8px' }}>
|
|
503
|
+
✓ Email Designer Integration
|
|
504
|
+
</Typography>
|
|
505
|
+
<Typography variant="omega" textColor="primary700" style={{ fontSize: '14px', display: 'flex', alignItems: 'center', gap: '8px' }}>
|
|
506
|
+
✓ Priority Email Headers
|
|
507
|
+
</Typography>
|
|
508
|
+
<Typography variant="omega" textColor="primary700" style={{ fontSize: '14px', display: 'flex', alignItems: 'center', gap: '8px' }}>
|
|
509
|
+
✓ List-Unsubscribe Headers (GDPR)
|
|
510
|
+
</Typography>
|
|
511
|
+
<Typography variant="omega" textColor="primary700" style={{ fontSize: '14px', display: 'flex', alignItems: 'center', gap: '8px' }}>
|
|
512
|
+
✓ Enhanced Security Validation
|
|
513
|
+
</Typography>
|
|
514
|
+
</Flex>
|
|
515
|
+
</Box>
|
|
516
|
+
)}
|
|
517
|
+
|
|
518
|
+
{/* Enterprise Features */}
|
|
519
|
+
{data.features?.enterprise && (
|
|
520
|
+
<Box padding={5} background="secondary50" hasRadius style={{ border: '2px solid #ddd6fe' }}>
|
|
521
|
+
<Typography variant="delta" fontWeight="bold" textColor="secondary700" style={{ marginBottom: '16px', display: 'flex', alignItems: 'center', gap: '8px' }}>
|
|
522
|
+
🏢 Enterprise Features Active
|
|
523
|
+
</Typography>
|
|
524
|
+
<Flex direction="column" gap={2}>
|
|
525
|
+
<Typography variant="omega" textColor="secondary700" style={{ fontSize: '14px', display: 'flex', alignItems: 'center', gap: '8px' }}>
|
|
526
|
+
✓ Multi-tenant Email Management
|
|
527
|
+
</Typography>
|
|
528
|
+
<Typography variant="omega" textColor="secondary700" style={{ fontSize: '14px', display: 'flex', alignItems: 'center', gap: '8px' }}>
|
|
529
|
+
✓ Compliance Reports (GDPR, CAN-SPAM)
|
|
530
|
+
</Typography>
|
|
531
|
+
<Typography variant="omega" textColor="secondary700" style={{ fontSize: '14px', display: 'flex', alignItems: 'center', gap: '8px' }}>
|
|
532
|
+
✓ Custom Routing Rules Engine
|
|
533
|
+
</Typography>
|
|
534
|
+
<Typography variant="omega" textColor="secondary700" style={{ fontSize: '14px', display: 'flex', alignItems: 'center', gap: '8px' }}>
|
|
535
|
+
✓ Advanced Rate Limiting
|
|
536
|
+
</Typography>
|
|
537
|
+
<Typography variant="omega" textColor="secondary700" style={{ fontSize: '14px', display: 'flex', alignItems: 'center', gap: '8px' }}>
|
|
538
|
+
✓ Priority Support
|
|
539
|
+
</Typography>
|
|
540
|
+
</Flex>
|
|
541
|
+
</Box>
|
|
542
|
+
)}
|
|
543
|
+
</Box>
|
|
544
|
+
</Accordion.Content>
|
|
545
|
+
</Accordion.Item>
|
|
546
|
+
|
|
547
|
+
{/* System Status */}
|
|
548
|
+
<Accordion.Item value="status">
|
|
549
|
+
<Accordion.Header>
|
|
550
|
+
<Accordion.Trigger icon={() => <ChartBarIcon style={{ width: 16, height: 16 }} />}>
|
|
551
|
+
System Status
|
|
552
|
+
</Accordion.Trigger>
|
|
553
|
+
</Accordion.Header>
|
|
554
|
+
<Accordion.Content>
|
|
555
|
+
<Box padding={6}>
|
|
556
|
+
<Flex gap={8} wrap="wrap">
|
|
557
|
+
<Box style={{ flex: '1', minWidth: '150px' }}>
|
|
558
|
+
<Typography variant="sigma" textColor="neutral600" textTransform="uppercase" style={{ marginBottom: '8px', display: 'block' }}>
|
|
559
|
+
License Status
|
|
560
|
+
</Typography>
|
|
561
|
+
<Typography variant="omega" fontWeight="semiBold">
|
|
562
|
+
{data.isActive ? 'Active' : 'Inactive'}
|
|
563
|
+
</Typography>
|
|
564
|
+
</Box>
|
|
565
|
+
<Box style={{ flex: '1', minWidth: '150px' }}>
|
|
566
|
+
<Typography variant="sigma" textColor="neutral600" textTransform="uppercase" style={{ marginBottom: '8px', display: 'block' }}>
|
|
567
|
+
Connection
|
|
568
|
+
</Typography>
|
|
569
|
+
<Typography variant="omega" fontWeight="semiBold">
|
|
570
|
+
{data.isOnline ? 'Online' : 'Offline'}
|
|
571
|
+
</Typography>
|
|
572
|
+
</Box>
|
|
573
|
+
<Box style={{ flex: '1', minWidth: '150px' }}>
|
|
574
|
+
<Typography variant="sigma" textColor="neutral600" textTransform="uppercase" style={{ marginBottom: '8px', display: 'block' }}>
|
|
575
|
+
Last Sync
|
|
576
|
+
</Typography>
|
|
577
|
+
<Typography variant="omega" fontWeight="semiBold">
|
|
578
|
+
{data.lastPingAt
|
|
579
|
+
? new Date(data.lastPingAt).toLocaleTimeString()
|
|
580
|
+
: 'Never'}
|
|
581
|
+
</Typography>
|
|
582
|
+
</Box>
|
|
583
|
+
<Box style={{ flex: '1', minWidth: '150px' }}>
|
|
584
|
+
<Typography variant="sigma" textColor="neutral600" textTransform="uppercase" style={{ marginBottom: '8px', display: 'block' }}>
|
|
585
|
+
Device Limit
|
|
586
|
+
</Typography>
|
|
587
|
+
<Typography variant="omega" fontWeight="semiBold">
|
|
588
|
+
{data.currentDevices || 0} / {data.maxDevices || 1}
|
|
589
|
+
</Typography>
|
|
590
|
+
</Box>
|
|
591
|
+
</Flex>
|
|
592
|
+
</Box>
|
|
593
|
+
</Accordion.Content>
|
|
594
|
+
</Accordion.Item>
|
|
595
|
+
</Accordion.Root>
|
|
596
|
+
</Box>
|
|
597
|
+
</Box>
|
|
598
|
+
</Container>
|
|
599
|
+
);
|
|
600
|
+
};
|
|
601
|
+
|
|
602
|
+
export default LicensePage;
|
|
603
|
+
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
{
|
|
2
|
+
"plugin.name": "MagicMail",
|
|
3
|
+
"plugin.description": "Email Business Suite für Strapi v5",
|
|
4
|
+
|
|
5
|
+
"tabs.accounts": "Email-Konten",
|
|
6
|
+
"tabs.routing": "Routing-Regeln",
|
|
7
|
+
"tabs.license": "Lizenz",
|
|
8
|
+
|
|
9
|
+
"accounts.title": "Email-Konten",
|
|
10
|
+
"accounts.subtitle": "Verwalte mehrere Email-Konten mit Smart Routing",
|
|
11
|
+
"accounts.add": "Konto hinzufügen",
|
|
12
|
+
"accounts.edit": "Konto bearbeiten",
|
|
13
|
+
"accounts.delete": "Konto löschen",
|
|
14
|
+
"accounts.test": "Testen",
|
|
15
|
+
"accounts.empty": "Keine Email-Konten vorhanden",
|
|
16
|
+
"accounts.emptyDescription": "Füge dein erstes Email-Konto hinzu um zu starten",
|
|
17
|
+
|
|
18
|
+
"stats.emailsToday": "Heute versendet",
|
|
19
|
+
"stats.totalSent": "Gesamt versendet",
|
|
20
|
+
"stats.activeAccounts": "Aktive Konten",
|
|
21
|
+
|
|
22
|
+
"providers.smtp": "SMTP",
|
|
23
|
+
"providers.gmail": "Gmail OAuth",
|
|
24
|
+
"providers.microsoft": "Microsoft OAuth",
|
|
25
|
+
"providers.yahoo": "Yahoo Mail OAuth",
|
|
26
|
+
"providers.sendgrid": "SendGrid",
|
|
27
|
+
"providers.mailgun": "Mailgun",
|
|
28
|
+
|
|
29
|
+
"routing.title": "Routing-Regeln",
|
|
30
|
+
"routing.subtitle": "Definiere intelligente Routing-Regeln für Email-Versand",
|
|
31
|
+
"routing.add": "Regel erstellen",
|
|
32
|
+
"routing.edit": "Regel bearbeiten",
|
|
33
|
+
"routing.delete": "Regel löschen",
|
|
34
|
+
"routing.empty": "Keine Routing-Regeln vorhanden",
|
|
35
|
+
"routing.emptyDescription": "Erstelle deine erste Routing-Regel",
|
|
36
|
+
|
|
37
|
+
"license.title": "Lizenzverwaltung",
|
|
38
|
+
"license.subtitle": "Verwalte deine MagicMail Lizenz",
|
|
39
|
+
"license.active": "Lizenz aktiv",
|
|
40
|
+
"license.inactive": "Keine aktive Lizenz",
|
|
41
|
+
"license.demo": "Demo-Modus",
|
|
42
|
+
"license.generate": "Kostenlose Lizenz generieren",
|
|
43
|
+
"license.activate": "Lizenz aktivieren",
|
|
44
|
+
"license.key": "Lizenzschlüssel",
|
|
45
|
+
"license.email": "E-Mail-Adresse",
|
|
46
|
+
"license.copyKey": "Schlüssel kopieren",
|
|
47
|
+
"license.download": "Als TXT herunterladen",
|
|
48
|
+
"license.refresh": "Status aktualisieren",
|
|
49
|
+
|
|
50
|
+
"features.premium": "Premium Features",
|
|
51
|
+
"features.advanced": "Erweiterte Features",
|
|
52
|
+
"features.enterprise": "Enterprise Features",
|
|
53
|
+
|
|
54
|
+
"notifications.accountCreated": "Email-Konto erfolgreich erstellt",
|
|
55
|
+
"notifications.accountUpdated": "Email-Konto erfolgreich aktualisiert",
|
|
56
|
+
"notifications.accountDeleted": "Email-Konto erfolgreich gelöscht",
|
|
57
|
+
"notifications.testSuccess": "Test-Email erfolgreich versendet",
|
|
58
|
+
"notifications.testFailed": "Test-Email fehlgeschlagen",
|
|
59
|
+
"notifications.ruleCreated": "Routing-Regel erfolgreich erstellt",
|
|
60
|
+
"notifications.ruleUpdated": "Routing-Regel erfolgreich aktualisiert",
|
|
61
|
+
"notifications.ruleDeleted": "Routing-Regel erfolgreich gelöscht",
|
|
62
|
+
"notifications.licenseActivated": "Lizenz erfolgreich aktiviert",
|
|
63
|
+
"notifications.licenseCopied": "Lizenzschlüssel kopiert",
|
|
64
|
+
"notifications.error": "Ein Fehler ist aufgetreten",
|
|
65
|
+
|
|
66
|
+
"errors.noAccounts": "Keine Email-Konten verfügbar",
|
|
67
|
+
"errors.providerNotAllowed": "Dieser Provider erfordert eine höhere Lizenz",
|
|
68
|
+
"errors.accountLimitReached": "Konto-Limit erreicht. Upgrade erforderlich",
|
|
69
|
+
"errors.ruleLimitReached": "Regel-Limit erreicht. Upgrade erforderlich"
|
|
70
|
+
}
|
|
71
|
+
|