strapi-plugin-magic-sessionmanager 4.2.4 → 4.2.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +0 -2
- package/dist/server/index.js +1 -1
- package/dist/server/index.mjs +1 -1
- package/package.json +1 -3
- package/admin/jsconfig.json +0 -10
- package/admin/src/components/Initializer.jsx +0 -11
- package/admin/src/components/LicenseGuard.jsx +0 -591
- package/admin/src/components/OnlineUsersWidget.jsx +0 -212
- package/admin/src/components/PluginIcon.jsx +0 -8
- package/admin/src/components/SessionDetailModal.jsx +0 -449
- package/admin/src/components/SessionInfoCard.jsx +0 -151
- package/admin/src/components/SessionInfoPanel.jsx +0 -385
- package/admin/src/components/index.jsx +0 -5
- package/admin/src/hooks/useLicense.js +0 -103
- package/admin/src/index.js +0 -149
- package/admin/src/pages/ActiveSessions.jsx +0 -12
- package/admin/src/pages/Analytics.jsx +0 -735
- package/admin/src/pages/App.jsx +0 -12
- package/admin/src/pages/HomePage.jsx +0 -1212
- package/admin/src/pages/License.jsx +0 -603
- package/admin/src/pages/Settings.jsx +0 -1646
- package/admin/src/pages/SettingsNew.jsx +0 -1204
- package/admin/src/pages/UpgradePage.jsx +0 -448
- package/admin/src/pages/index.jsx +0 -3
- package/admin/src/pluginId.js +0 -4
- package/admin/src/translations/de.json +0 -299
- package/admin/src/translations/en.json +0 -299
- package/admin/src/translations/es.json +0 -287
- package/admin/src/translations/fr.json +0 -287
- package/admin/src/translations/pt.json +0 -287
- package/admin/src/utils/getTranslation.js +0 -5
- package/admin/src/utils/index.js +0 -2
- package/admin/src/utils/parseUserAgent.js +0 -79
- package/admin/src/utils/theme.js +0 -85
- package/server/jsconfig.json +0 -10
- package/server/src/bootstrap.js +0 -492
- package/server/src/config/index.js +0 -23
- package/server/src/content-types/index.js +0 -9
- package/server/src/content-types/session/schema.json +0 -84
- package/server/src/controllers/controller.js +0 -11
- package/server/src/controllers/index.js +0 -11
- package/server/src/controllers/license.js +0 -266
- package/server/src/controllers/session.js +0 -433
- package/server/src/controllers/settings.js +0 -122
- package/server/src/destroy.js +0 -22
- package/server/src/index.js +0 -23
- package/server/src/middlewares/index.js +0 -5
- package/server/src/middlewares/last-seen.js +0 -62
- package/server/src/policies/index.js +0 -3
- package/server/src/register.js +0 -36
- package/server/src/routes/admin.js +0 -149
- package/server/src/routes/content-api.js +0 -60
- package/server/src/routes/index.js +0 -9
- package/server/src/services/geolocation.js +0 -182
- package/server/src/services/index.js +0 -13
- package/server/src/services/license-guard.js +0 -316
- package/server/src/services/notifications.js +0 -319
- package/server/src/services/service.js +0 -7
- package/server/src/services/session.js +0 -393
- package/server/src/utils/encryption.js +0 -121
- package/server/src/utils/getClientIp.js +0 -118
- package/server/src/utils/logger.js +0 -84
|
@@ -1,448 +0,0 @@
|
|
|
1
|
-
import { useState, useEffect } from 'react';
|
|
2
|
-
import { useFetchClient, useNotification } from '@strapi/strapi/admin';
|
|
3
|
-
import styled from 'styled-components';
|
|
4
|
-
import {
|
|
5
|
-
Box,
|
|
6
|
-
Button,
|
|
7
|
-
Flex,
|
|
8
|
-
Typography,
|
|
9
|
-
Badge,
|
|
10
|
-
} from '@strapi/design-system';
|
|
11
|
-
import {
|
|
12
|
-
Check as CheckIcon,
|
|
13
|
-
Cross as XMarkIcon,
|
|
14
|
-
Sparkle as SparklesIcon,
|
|
15
|
-
Lightning as BoltIcon,
|
|
16
|
-
Rocket as RocketLaunchIcon,
|
|
17
|
-
} from '@strapi/icons';
|
|
18
|
-
import pluginId from '../pluginId';
|
|
19
|
-
|
|
20
|
-
const Container = styled(Box)`
|
|
21
|
-
padding: 32px;
|
|
22
|
-
max-width: 1400px;
|
|
23
|
-
margin: 0 auto;
|
|
24
|
-
`;
|
|
25
|
-
|
|
26
|
-
const Header = styled(Box)`
|
|
27
|
-
text-align: center;
|
|
28
|
-
margin-bottom: 48px;
|
|
29
|
-
display: flex;
|
|
30
|
-
flex-direction: column;
|
|
31
|
-
align-items: center;
|
|
32
|
-
gap: 8px;
|
|
33
|
-
`;
|
|
34
|
-
|
|
35
|
-
const Title = styled(Typography)`
|
|
36
|
-
font-size: 2.5rem;
|
|
37
|
-
font-weight: 700;
|
|
38
|
-
margin-bottom: 8px;
|
|
39
|
-
background: linear-gradient(135deg, #0EA5E9, #A855F7);
|
|
40
|
-
-webkit-background-clip: text;
|
|
41
|
-
-webkit-text-fill-color: transparent;
|
|
42
|
-
display: block;
|
|
43
|
-
`;
|
|
44
|
-
|
|
45
|
-
const Subtitle = styled(Typography)`
|
|
46
|
-
font-size: 1.125rem;
|
|
47
|
-
color: ${props => props.theme.colors.neutral600};
|
|
48
|
-
line-height: 1.6;
|
|
49
|
-
display: block;
|
|
50
|
-
`;
|
|
51
|
-
|
|
52
|
-
const TierGrid = styled(Flex)`
|
|
53
|
-
gap: 32px;
|
|
54
|
-
margin: 0 auto 48px;
|
|
55
|
-
max-width: 1080px;
|
|
56
|
-
justify-content: center;
|
|
57
|
-
flex-wrap: wrap;
|
|
58
|
-
align-items: stretch;
|
|
59
|
-
`;
|
|
60
|
-
|
|
61
|
-
const TierWrapper = styled(Box)`
|
|
62
|
-
flex: 1;
|
|
63
|
-
min-width: 280px;
|
|
64
|
-
max-width: 340px;
|
|
65
|
-
display: flex;
|
|
66
|
-
`;
|
|
67
|
-
|
|
68
|
-
const TierCard = styled(Box)`
|
|
69
|
-
background: ${props => props.theme.colors.neutral0};
|
|
70
|
-
border-radius: 16px;
|
|
71
|
-
padding: 32px;
|
|
72
|
-
border: 2px solid ${props => props.$featured ? '#0EA5E9' : props.theme.colors.neutral200};
|
|
73
|
-
position: relative;
|
|
74
|
-
transition: all 0.3s ease;
|
|
75
|
-
box-shadow: ${props => props.$featured
|
|
76
|
-
? '0 20px 25px -5px rgba(14, 165, 233, 0.25), 0 8px 10px -6px rgba(14, 165, 233, 0.2)'
|
|
77
|
-
: '0 10px 15px -3px rgba(15, 23, 42, 0.08), 0 4px 6px -4px rgba(15, 23, 42, 0.05)'};
|
|
78
|
-
display: flex;
|
|
79
|
-
flex-direction: column;
|
|
80
|
-
width: 100%;
|
|
81
|
-
|
|
82
|
-
&:hover {
|
|
83
|
-
transform: translateY(-4px);
|
|
84
|
-
box-shadow: 0 20px 25px -5px rgba(15, 23, 42, 0.15), 0 8px 10px -6px rgba(15, 23, 42, 0.1);
|
|
85
|
-
}
|
|
86
|
-
`;
|
|
87
|
-
|
|
88
|
-
const PopularBadge = styled(Badge)`
|
|
89
|
-
position: absolute;
|
|
90
|
-
top: -12px;
|
|
91
|
-
right: 24px;
|
|
92
|
-
background: linear-gradient(135deg, #0EA5E9, #0284C7);
|
|
93
|
-
color: white;
|
|
94
|
-
padding: 4px 16px;
|
|
95
|
-
font-size: 12px;
|
|
96
|
-
font-weight: 600;
|
|
97
|
-
`;
|
|
98
|
-
|
|
99
|
-
const TierIcon = styled(Box)`
|
|
100
|
-
width: 48px;
|
|
101
|
-
height: 48px;
|
|
102
|
-
border-radius: 12px;
|
|
103
|
-
display: flex;
|
|
104
|
-
align-items: center;
|
|
105
|
-
justify-content: center;
|
|
106
|
-
margin-bottom: 16px;
|
|
107
|
-
background: ${props => props.$color};
|
|
108
|
-
|
|
109
|
-
svg {
|
|
110
|
-
width: 28px;
|
|
111
|
-
height: 28px;
|
|
112
|
-
color: white;
|
|
113
|
-
}
|
|
114
|
-
`;
|
|
115
|
-
|
|
116
|
-
const TierName = styled(Typography)`
|
|
117
|
-
font-size: 1.5rem;
|
|
118
|
-
font-weight: 700;
|
|
119
|
-
margin-bottom: 8px;
|
|
120
|
-
`;
|
|
121
|
-
|
|
122
|
-
const TierPrice = styled(Typography)`
|
|
123
|
-
font-size: 2rem;
|
|
124
|
-
font-weight: 800;
|
|
125
|
-
margin-bottom: 4px;
|
|
126
|
-
`;
|
|
127
|
-
|
|
128
|
-
const TierDescription = styled(Typography)`
|
|
129
|
-
color: ${props => props.theme.colors.neutral600};
|
|
130
|
-
margin-bottom: 24px;
|
|
131
|
-
`;
|
|
132
|
-
|
|
133
|
-
const FeatureList = styled(Box)`
|
|
134
|
-
margin-bottom: 24px;
|
|
135
|
-
flex: 1;
|
|
136
|
-
`;
|
|
137
|
-
|
|
138
|
-
const Feature = styled(Flex)`
|
|
139
|
-
gap: 12px;
|
|
140
|
-
margin-bottom: 12px;
|
|
141
|
-
align-items: flex-start;
|
|
142
|
-
`;
|
|
143
|
-
|
|
144
|
-
const FeatureIcon = styled(Box)`
|
|
145
|
-
width: 20px;
|
|
146
|
-
height: 20px;
|
|
147
|
-
border-radius: 50%;
|
|
148
|
-
display: flex;
|
|
149
|
-
align-items: center;
|
|
150
|
-
justify-content: center;
|
|
151
|
-
flex-shrink: 0;
|
|
152
|
-
margin-top: 2px;
|
|
153
|
-
|
|
154
|
-
${props => props.$included ? `
|
|
155
|
-
background: #DCFCE7;
|
|
156
|
-
svg { color: #16A34A; }
|
|
157
|
-
` : `
|
|
158
|
-
background: #FEE2E2;
|
|
159
|
-
svg { color: #DC2626; }
|
|
160
|
-
`}
|
|
161
|
-
`;
|
|
162
|
-
|
|
163
|
-
const UpgradeButton = styled(Button)`
|
|
164
|
-
width: 100%;
|
|
165
|
-
height: 48px;
|
|
166
|
-
font-weight: 600;
|
|
167
|
-
font-size: 15px;
|
|
168
|
-
background: ${props => props.$gradient};
|
|
169
|
-
border: none;
|
|
170
|
-
color: white;
|
|
171
|
-
|
|
172
|
-
&:hover {
|
|
173
|
-
transform: translateY(-2px);
|
|
174
|
-
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
|
175
|
-
}
|
|
176
|
-
`;
|
|
177
|
-
|
|
178
|
-
const CurrentPlanBadge = styled(Badge)`
|
|
179
|
-
width: 100%;
|
|
180
|
-
height: 48px;
|
|
181
|
-
display: flex;
|
|
182
|
-
align-items: center;
|
|
183
|
-
justify-content: center;
|
|
184
|
-
background: ${props => props.theme.colors.neutral100};
|
|
185
|
-
color: ${props => props.theme.colors.neutral600};
|
|
186
|
-
font-weight: 600;
|
|
187
|
-
font-size: 15px;
|
|
188
|
-
`;
|
|
189
|
-
|
|
190
|
-
const LimitsBox = styled(Box)`
|
|
191
|
-
background: ${props => props.theme.colors.neutral100};
|
|
192
|
-
border-radius: 8px;
|
|
193
|
-
padding: 12px;
|
|
194
|
-
margin-bottom: 20px;
|
|
195
|
-
`;
|
|
196
|
-
|
|
197
|
-
/**
|
|
198
|
-
* Upgrade page for Magic Sessionmanager with pricing tiers
|
|
199
|
-
*/
|
|
200
|
-
const UpgradePage = () => {
|
|
201
|
-
const { get } = useFetchClient();
|
|
202
|
-
const { toggleNotification } = useNotification();
|
|
203
|
-
const [currentTier, setCurrentTier] = useState('free');
|
|
204
|
-
const [limits, setLimits] = useState(null);
|
|
205
|
-
const [loading, setLoading] = useState(true);
|
|
206
|
-
|
|
207
|
-
useEffect(() => {
|
|
208
|
-
fetchLicenseInfo();
|
|
209
|
-
}, []);
|
|
210
|
-
|
|
211
|
-
/**
|
|
212
|
-
* Fetches current license information
|
|
213
|
-
*/
|
|
214
|
-
const fetchLicenseInfo = async () => {
|
|
215
|
-
try {
|
|
216
|
-
const response = await get(`/${pluginId}/license/status`);
|
|
217
|
-
const licenseData = response.data || {};
|
|
218
|
-
|
|
219
|
-
let tier = 'free';
|
|
220
|
-
if (licenseData.data?.features?.advanced) {
|
|
221
|
-
tier = 'advanced';
|
|
222
|
-
} else if (licenseData.data?.features?.premium) {
|
|
223
|
-
tier = 'premium';
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
setCurrentTier(tier);
|
|
227
|
-
setLimits(licenseData.limits);
|
|
228
|
-
setLoading(false);
|
|
229
|
-
} catch (error) {
|
|
230
|
-
console.error('[magic-sessionmanager] Failed to fetch license info:', error);
|
|
231
|
-
setLoading(false);
|
|
232
|
-
}
|
|
233
|
-
};
|
|
234
|
-
|
|
235
|
-
/**
|
|
236
|
-
* Returns rank of tier for comparison
|
|
237
|
-
*/
|
|
238
|
-
const getTierRank = (tierId) => {
|
|
239
|
-
const ranks = {
|
|
240
|
-
'free': 0,
|
|
241
|
-
'premium': 1,
|
|
242
|
-
'advanced': 2,
|
|
243
|
-
};
|
|
244
|
-
return ranks[tierId] || 0;
|
|
245
|
-
};
|
|
246
|
-
|
|
247
|
-
/**
|
|
248
|
-
* Returns button text based on tier comparison
|
|
249
|
-
*/
|
|
250
|
-
const getButtonText = (tierId) => {
|
|
251
|
-
const currentRank = getTierRank(currentTier);
|
|
252
|
-
const targetRank = getTierRank(tierId);
|
|
253
|
-
|
|
254
|
-
if (currentRank === targetRank) {
|
|
255
|
-
return 'Current Plan';
|
|
256
|
-
} else if (targetRank > currentRank) {
|
|
257
|
-
return 'Upgrade Now';
|
|
258
|
-
} else {
|
|
259
|
-
return 'Downgrade';
|
|
260
|
-
}
|
|
261
|
-
};
|
|
262
|
-
|
|
263
|
-
const tiers = [
|
|
264
|
-
{
|
|
265
|
-
id: 'free',
|
|
266
|
-
name: 'FREE',
|
|
267
|
-
price: '$0',
|
|
268
|
-
period: 'forever',
|
|
269
|
-
description: 'Perfect for small projects and testing',
|
|
270
|
-
icon: <SparklesIcon />,
|
|
271
|
-
color: 'linear-gradient(135deg, #6B7280, #4B5563)',
|
|
272
|
-
features: [
|
|
273
|
-
{ name: 'Session Tracking', included: true },
|
|
274
|
-
{ name: 'Force Logout', included: true },
|
|
275
|
-
{ name: 'Dashboard Widget', included: true },
|
|
276
|
-
{ name: 'Device Detection', included: true },
|
|
277
|
-
{ name: 'Basic Monitoring', included: true },
|
|
278
|
-
{ name: 'IP Geolocation', included: false },
|
|
279
|
-
{ name: 'VPN/Proxy Detection', included: false },
|
|
280
|
-
{ name: 'Threat Analysis', included: false },
|
|
281
|
-
{ name: 'Auto-blocking', included: false },
|
|
282
|
-
],
|
|
283
|
-
limits: {
|
|
284
|
-
sessions: 'Unlimited',
|
|
285
|
-
support: 'Community',
|
|
286
|
-
}
|
|
287
|
-
},
|
|
288
|
-
{
|
|
289
|
-
id: 'premium',
|
|
290
|
-
name: 'PREMIUM',
|
|
291
|
-
price: '$14.50',
|
|
292
|
-
period: '/month',
|
|
293
|
-
description: 'Enhanced security for growing teams',
|
|
294
|
-
icon: <BoltIcon />,
|
|
295
|
-
color: 'linear-gradient(135deg, #8B5CF6, #7C3AED)',
|
|
296
|
-
featured: true,
|
|
297
|
-
features: [
|
|
298
|
-
{ name: 'Session Tracking', included: true },
|
|
299
|
-
{ name: 'Force Logout', included: true },
|
|
300
|
-
{ name: 'Dashboard Widget', included: true },
|
|
301
|
-
{ name: 'Device Detection', included: true },
|
|
302
|
-
{ name: 'Basic Monitoring', included: true },
|
|
303
|
-
{ name: 'IP Geolocation', included: true },
|
|
304
|
-
{ name: 'VPN/Proxy Detection', included: true },
|
|
305
|
-
{ name: 'Security Risk Scoring', included: true },
|
|
306
|
-
{ name: 'Extended Logging', included: true },
|
|
307
|
-
{ name: 'Priority Support', included: true },
|
|
308
|
-
],
|
|
309
|
-
limits: {
|
|
310
|
-
sessions: 'Unlimited',
|
|
311
|
-
support: 'Priority',
|
|
312
|
-
}
|
|
313
|
-
},
|
|
314
|
-
{
|
|
315
|
-
id: 'advanced',
|
|
316
|
-
name: 'ADVANCED',
|
|
317
|
-
price: '$39.50',
|
|
318
|
-
period: '/month',
|
|
319
|
-
description: 'Maximum security for enterprises',
|
|
320
|
-
icon: <RocketLaunchIcon />,
|
|
321
|
-
color: 'linear-gradient(135deg, #0EA5E9, #0284C7)',
|
|
322
|
-
features: [
|
|
323
|
-
{ name: 'Session Tracking', included: true },
|
|
324
|
-
{ name: 'Force Logout', included: true },
|
|
325
|
-
{ name: 'Dashboard Widget', included: true },
|
|
326
|
-
{ name: 'Device Detection', included: true },
|
|
327
|
-
{ name: 'Basic Monitoring', included: true },
|
|
328
|
-
{ name: 'IP Geolocation', included: true },
|
|
329
|
-
{ name: 'VPN/Proxy Detection', included: true },
|
|
330
|
-
{ name: 'Security Risk Scoring', included: true },
|
|
331
|
-
{ name: 'Extended Logging', included: true },
|
|
332
|
-
{ name: 'Threat Analysis', included: true },
|
|
333
|
-
{ name: 'Auto-blocking', included: true },
|
|
334
|
-
{ name: 'Email/Webhook Alerts', included: true },
|
|
335
|
-
{ name: 'Geo-fencing', included: true },
|
|
336
|
-
{ name: 'Priority + Phone Support', included: true },
|
|
337
|
-
],
|
|
338
|
-
limits: {
|
|
339
|
-
sessions: 'Unlimited',
|
|
340
|
-
support: 'Priority + Phone',
|
|
341
|
-
}
|
|
342
|
-
}
|
|
343
|
-
];
|
|
344
|
-
|
|
345
|
-
/**
|
|
346
|
-
* Handle upgrade button click
|
|
347
|
-
*/
|
|
348
|
-
const handleUpgrade = (tierId) => {
|
|
349
|
-
window.open('https://store.magicdx.dev/', '_blank');
|
|
350
|
-
};
|
|
351
|
-
|
|
352
|
-
if (loading) {
|
|
353
|
-
return (
|
|
354
|
-
<Container>
|
|
355
|
-
<Flex justifyContent="center" alignItems="center" style={{ minHeight: '400px' }}>
|
|
356
|
-
<Typography>Loading license information...</Typography>
|
|
357
|
-
</Flex>
|
|
358
|
-
</Container>
|
|
359
|
-
);
|
|
360
|
-
}
|
|
361
|
-
|
|
362
|
-
return (
|
|
363
|
-
<Container>
|
|
364
|
-
<Header>
|
|
365
|
-
<Title variant="alpha">Choose Your Plan</Title>
|
|
366
|
-
<Subtitle variant="omega">
|
|
367
|
-
Unlock powerful session management features for your Strapi application
|
|
368
|
-
</Subtitle>
|
|
369
|
-
</Header>
|
|
370
|
-
|
|
371
|
-
<TierGrid>
|
|
372
|
-
{tiers.map((tier) => (
|
|
373
|
-
<TierWrapper key={tier.id}>
|
|
374
|
-
<TierCard $featured={tier.featured}>
|
|
375
|
-
{tier.featured && <PopularBadge>MOST POPULAR</PopularBadge>}
|
|
376
|
-
|
|
377
|
-
<TierIcon $color={tier.color}>
|
|
378
|
-
{tier.icon}
|
|
379
|
-
</TierIcon>
|
|
380
|
-
|
|
381
|
-
<TierName variant="beta">{tier.name}</TierName>
|
|
382
|
-
|
|
383
|
-
<Flex alignItems="baseline" gap={1}>
|
|
384
|
-
<TierPrice variant="alpha">{tier.price}</TierPrice>
|
|
385
|
-
<Typography variant="omega" style={{ color: '#6B7280' }}>
|
|
386
|
-
{tier.period}
|
|
387
|
-
</Typography>
|
|
388
|
-
</Flex>
|
|
389
|
-
|
|
390
|
-
<TierDescription variant="omega">
|
|
391
|
-
{tier.description}
|
|
392
|
-
</TierDescription>
|
|
393
|
-
|
|
394
|
-
<LimitsBox>
|
|
395
|
-
<Flex direction="column" gap={2}>
|
|
396
|
-
<Typography variant="pi" style={{ fontSize: '13px' }}>
|
|
397
|
-
<strong>Sessions:</strong> {tier.limits.sessions}
|
|
398
|
-
</Typography>
|
|
399
|
-
<Typography variant="pi" style={{ fontSize: '13px' }}>
|
|
400
|
-
<strong>Support:</strong> {tier.limits.support}
|
|
401
|
-
</Typography>
|
|
402
|
-
</Flex>
|
|
403
|
-
</LimitsBox>
|
|
404
|
-
|
|
405
|
-
<FeatureList>
|
|
406
|
-
{tier.features.map((feature, index) => (
|
|
407
|
-
<Feature key={index}>
|
|
408
|
-
<FeatureIcon $included={feature.included}>
|
|
409
|
-
{feature.included ? (
|
|
410
|
-
<CheckIcon style={{ width: 14, height: 14 }} />
|
|
411
|
-
) : (
|
|
412
|
-
<XMarkIcon style={{ width: 14, height: 14 }} />
|
|
413
|
-
)}
|
|
414
|
-
</FeatureIcon>
|
|
415
|
-
<Typography
|
|
416
|
-
variant="omega"
|
|
417
|
-
style={{
|
|
418
|
-
fontSize: '14px',
|
|
419
|
-
color: feature.included ? '#374151' : '#9CA3AF',
|
|
420
|
-
textDecoration: feature.included ? 'none' : 'line-through'
|
|
421
|
-
}}
|
|
422
|
-
>
|
|
423
|
-
{feature.name}
|
|
424
|
-
</Typography>
|
|
425
|
-
</Feature>
|
|
426
|
-
))}
|
|
427
|
-
</FeatureList>
|
|
428
|
-
|
|
429
|
-
{currentTier === tier.id ? (
|
|
430
|
-
<CurrentPlanBadge>CURRENT PLAN</CurrentPlanBadge>
|
|
431
|
-
) : (
|
|
432
|
-
<UpgradeButton
|
|
433
|
-
onClick={() => handleUpgrade(tier.id)}
|
|
434
|
-
$gradient={tier.color}
|
|
435
|
-
>
|
|
436
|
-
{getButtonText(tier.id)}
|
|
437
|
-
</UpgradeButton>
|
|
438
|
-
)}
|
|
439
|
-
</TierCard>
|
|
440
|
-
</TierWrapper>
|
|
441
|
-
))}
|
|
442
|
-
</TierGrid>
|
|
443
|
-
</Container>
|
|
444
|
-
);
|
|
445
|
-
};
|
|
446
|
-
|
|
447
|
-
export default UpgradePage;
|
|
448
|
-
|
package/admin/src/pluginId.js
DELETED