strapi-plugin-magic-sessionmanager 1.0.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.
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const de = {
4
+ "plugin.name": "Session Manager",
5
+ "plugin.description": "Verfolgung von Benutzer-Login/Logout und Sitzungsaktivität",
6
+ "settings.section": "Session Manager",
7
+ "settings.sessions": "Aktive Sitzungen",
8
+ "settings.emailTemplates.title": "E-Mail Templates",
9
+ "settings.emailTemplates.description": "Passe E-Mail-Benachrichtigungen mit dynamischen Variablen an",
10
+ "settings.emailTemplates.validate": "Validieren",
11
+ "settings.emailTemplates.loadDefault": "Standard-Template laden",
12
+ "settings.emailTemplates.subject": "E-Mail Betreff",
13
+ "settings.emailTemplates.htmlTemplate": "HTML Template",
14
+ "settings.emailTemplates.textTemplate": "Text Template (Fallback)",
15
+ "settings.emailTemplates.variables": "Verfügbare Variablen (klicken zum Kopieren)",
16
+ "settings.emailTemplates.validation.success": "Template gültig! {count} Variablen gefunden.",
17
+ "settings.emailTemplates.validation.warning": "Keine Variablen im Template gefunden. Füge mindestens eine Variable hinzu.",
18
+ "settings.emailTemplates.defaultLoaded": "Standard-Template geladen!",
19
+ "settings.emailTemplates.suspiciousLogin": "Verdächtiger Login",
20
+ "settings.emailTemplates.newLocation": "Neuer Standort",
21
+ "settings.emailTemplates.vpnProxy": "VPN/Proxy"
22
+ };
23
+ exports.default = de;
@@ -0,0 +1,23 @@
1
+ const de = {
2
+ "plugin.name": "Session Manager",
3
+ "plugin.description": "Verfolgung von Benutzer-Login/Logout und Sitzungsaktivität",
4
+ "settings.section": "Session Manager",
5
+ "settings.sessions": "Aktive Sitzungen",
6
+ "settings.emailTemplates.title": "E-Mail Templates",
7
+ "settings.emailTemplates.description": "Passe E-Mail-Benachrichtigungen mit dynamischen Variablen an",
8
+ "settings.emailTemplates.validate": "Validieren",
9
+ "settings.emailTemplates.loadDefault": "Standard-Template laden",
10
+ "settings.emailTemplates.subject": "E-Mail Betreff",
11
+ "settings.emailTemplates.htmlTemplate": "HTML Template",
12
+ "settings.emailTemplates.textTemplate": "Text Template (Fallback)",
13
+ "settings.emailTemplates.variables": "Verfügbare Variablen (klicken zum Kopieren)",
14
+ "settings.emailTemplates.validation.success": "Template gültig! {count} Variablen gefunden.",
15
+ "settings.emailTemplates.validation.warning": "Keine Variablen im Template gefunden. Füge mindestens eine Variable hinzu.",
16
+ "settings.emailTemplates.defaultLoaded": "Standard-Template geladen!",
17
+ "settings.emailTemplates.suspiciousLogin": "Verdächtiger Login",
18
+ "settings.emailTemplates.newLocation": "Neuer Standort",
19
+ "settings.emailTemplates.vpnProxy": "VPN/Proxy"
20
+ };
21
+ export {
22
+ de as default
23
+ };
@@ -0,0 +1,23 @@
1
+ const en = {
2
+ "plugin.name": "Session Manager",
3
+ "plugin.description": "Track user login/logout and session activity",
4
+ "settings.section": "Session Manager",
5
+ "settings.sessions": "Active Sessions",
6
+ "settings.emailTemplates.title": "Email Templates",
7
+ "settings.emailTemplates.description": "Customize email notification templates with dynamic variables",
8
+ "settings.emailTemplates.validate": "Validate",
9
+ "settings.emailTemplates.loadDefault": "Load Default Template",
10
+ "settings.emailTemplates.subject": "Email Subject",
11
+ "settings.emailTemplates.htmlTemplate": "HTML Template",
12
+ "settings.emailTemplates.textTemplate": "Text Template (Fallback)",
13
+ "settings.emailTemplates.variables": "Available Variables (click to copy)",
14
+ "settings.emailTemplates.validation.success": "Template valid! Found {count} variables.",
15
+ "settings.emailTemplates.validation.warning": "No variables found in template. Add at least one variable.",
16
+ "settings.emailTemplates.defaultLoaded": "Default template loaded!",
17
+ "settings.emailTemplates.suspiciousLogin": "Suspicious Login",
18
+ "settings.emailTemplates.newLocation": "New Location",
19
+ "settings.emailTemplates.vpnProxy": "VPN/Proxy"
20
+ };
21
+ export {
22
+ en as default
23
+ };
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const en = {
4
+ "plugin.name": "Session Manager",
5
+ "plugin.description": "Track user login/logout and session activity",
6
+ "settings.section": "Session Manager",
7
+ "settings.sessions": "Active Sessions",
8
+ "settings.emailTemplates.title": "Email Templates",
9
+ "settings.emailTemplates.description": "Customize email notification templates with dynamic variables",
10
+ "settings.emailTemplates.validate": "Validate",
11
+ "settings.emailTemplates.loadDefault": "Load Default Template",
12
+ "settings.emailTemplates.subject": "Email Subject",
13
+ "settings.emailTemplates.htmlTemplate": "HTML Template",
14
+ "settings.emailTemplates.textTemplate": "Text Template (Fallback)",
15
+ "settings.emailTemplates.variables": "Available Variables (click to copy)",
16
+ "settings.emailTemplates.validation.success": "Template valid! Found {count} variables.",
17
+ "settings.emailTemplates.validation.warning": "No variables found in template. Add at least one variable.",
18
+ "settings.emailTemplates.defaultLoaded": "Default template loaded!",
19
+ "settings.emailTemplates.suspiciousLogin": "Suspicious Login",
20
+ "settings.emailTemplates.newLocation": "New Location",
21
+ "settings.emailTemplates.vpnProxy": "VPN/Proxy"
22
+ };
23
+ exports.default = en;
@@ -0,0 +1,508 @@
1
+ import { useEffect, useState } from "react";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import { Box, Typography, Flex, Badge, Divider, Button } from "@strapi/design-system";
4
+ import { Server, Clock, Cross, Check, Phone, Monitor } from "@strapi/icons";
5
+ import { useFetchClient, useNotification } from "@strapi/strapi/admin";
6
+ const strapi = {
7
+ name: "magic-sessionmanager",
8
+ displayName: "Magic Sessionmanager"
9
+ };
10
+ const pluginPkg = {
11
+ strapi
12
+ };
13
+ const pluginId = "magic-sessionmanager";
14
+ const Initializer = () => {
15
+ useEffect(() => {
16
+ console.log("[magic-sessionmanager] Plugin initialized");
17
+ }, []);
18
+ return null;
19
+ };
20
+ const PluginIcon = () => /* @__PURE__ */ jsx("svg", { viewBox: "0 0 32 32", fill: "currentColor", width: "24", height: "24", children: /* @__PURE__ */ jsx("path", { d: "M26 5H6a3 3 0 0 0-3 3v14a3 3 0 0 0 3 3h20a3 3 0 0 0 3-3V8a3 3 0 0 0-3-3M20 27h-8a1 1 0 0 0 0 2h8a1 1 0 0 0 0-2" }) });
21
+ const parseUserAgent = (userAgent) => {
22
+ if (!userAgent) {
23
+ return {
24
+ device: "Unknown",
25
+ deviceIcon: "❓",
26
+ browser: "Unknown",
27
+ os: "Unknown"
28
+ };
29
+ }
30
+ const ua = userAgent.toLowerCase();
31
+ let device = "Desktop";
32
+ let deviceIcon = "💻";
33
+ if (/(tablet|ipad|playbook|silk)|(android(?!.*mobi))/i.test(userAgent)) {
34
+ device = "Tablet";
35
+ deviceIcon = "📱";
36
+ } else if (/Mobile|Android|iP(hone|od)|IEMobile|BlackBerry|Kindle|Silk-Accelerated|(hpw|web)OS|Opera M(obi|ini)/.test(userAgent)) {
37
+ device = "Mobile";
38
+ deviceIcon = "📱";
39
+ }
40
+ let browser = "Unknown";
41
+ if (ua.includes("edg/")) {
42
+ browser = "Edge";
43
+ } else if (ua.includes("chrome/") && !ua.includes("edg/")) {
44
+ browser = "Chrome";
45
+ } else if (ua.includes("firefox/")) {
46
+ browser = "Firefox";
47
+ } else if (ua.includes("safari/") && !ua.includes("chrome/")) {
48
+ browser = "Safari";
49
+ } else if (ua.includes("opera/") || ua.includes("opr/")) {
50
+ browser = "Opera";
51
+ } else if (ua.includes("curl/")) {
52
+ browser = "cURL";
53
+ deviceIcon = "⚙️";
54
+ device = "API Client";
55
+ } else if (ua.includes("postman")) {
56
+ browser = "Postman";
57
+ deviceIcon = "📮";
58
+ device = "API Client";
59
+ } else if (ua.includes("insomnia")) {
60
+ browser = "Insomnia";
61
+ deviceIcon = "🌙";
62
+ device = "API Client";
63
+ }
64
+ let os = "Unknown";
65
+ if (ua.includes("windows")) {
66
+ os = "Windows";
67
+ } else if (ua.includes("mac os x") || ua.includes("macintosh")) {
68
+ os = "macOS";
69
+ } else if (ua.includes("linux")) {
70
+ os = "Linux";
71
+ } else if (ua.includes("android")) {
72
+ os = "Android";
73
+ } else if (ua.includes("iphone") || ua.includes("ipad")) {
74
+ os = "iOS";
75
+ }
76
+ return {
77
+ device,
78
+ deviceIcon,
79
+ browser,
80
+ os
81
+ };
82
+ };
83
+ const SessionInfoPanel = ({ documentId, model, document }) => {
84
+ const [sessions, setSessions] = useState([]);
85
+ const [loading, setLoading] = useState(true);
86
+ const [isBlocked, setIsBlocked] = useState(false);
87
+ const [actionLoading, setActionLoading] = useState(false);
88
+ const { get, post: postRequest } = useFetchClient();
89
+ const { toggleNotification } = useNotification();
90
+ const userId = document?.id || documentId;
91
+ useEffect(() => {
92
+ if (model !== "plugin::users-permissions.user" || !userId) {
93
+ setLoading(false);
94
+ return;
95
+ }
96
+ const fetchData = async () => {
97
+ try {
98
+ const { data } = await get(`/api/magic-sessionmanager/user/${userId}/sessions`);
99
+ const activeSessions = (data.data || []).filter((s) => s.isTrulyActive);
100
+ setSessions(activeSessions);
101
+ setIsBlocked(document?.blocked || false);
102
+ } catch (err) {
103
+ console.error("[SessionInfoPanel] Error:", err);
104
+ } finally {
105
+ setLoading(false);
106
+ }
107
+ };
108
+ fetchData();
109
+ }, [userId, model, document, get]);
110
+ const handleLogoutAll = async () => {
111
+ if (!userId) return;
112
+ setActionLoading(true);
113
+ try {
114
+ const response = await postRequest(`/magic-sessionmanager/user/${userId}/terminate-all`);
115
+ if (response.data?.success) {
116
+ toggleNotification({
117
+ type: "success",
118
+ message: "All sessions terminated successfully"
119
+ });
120
+ setSessions([]);
121
+ }
122
+ } catch (error) {
123
+ toggleNotification({
124
+ type: "warning",
125
+ message: "Failed to terminate sessions"
126
+ });
127
+ console.error("[SessionInfoPanel] Logout all error:", error);
128
+ } finally {
129
+ setActionLoading(false);
130
+ }
131
+ };
132
+ const handleToggleBlock = async () => {
133
+ if (!userId) return;
134
+ setActionLoading(true);
135
+ try {
136
+ const response = await postRequest(`/magic-sessionmanager/user/${userId}/toggle-block`);
137
+ if (response.data?.success) {
138
+ const newBlockedStatus = response.data.blocked;
139
+ setIsBlocked(newBlockedStatus);
140
+ toggleNotification({
141
+ type: "success",
142
+ message: newBlockedStatus ? "User blocked successfully" : "User unblocked successfully"
143
+ });
144
+ if (newBlockedStatus) {
145
+ setSessions([]);
146
+ }
147
+ }
148
+ } catch (error) {
149
+ toggleNotification({
150
+ type: "warning",
151
+ message: "Failed to update user status"
152
+ });
153
+ console.error("[SessionInfoPanel] Toggle block error:", error);
154
+ } finally {
155
+ setActionLoading(false);
156
+ }
157
+ };
158
+ const getDeviceIcon = (deviceType) => {
159
+ if (deviceType === "Mobile" || deviceType === "Tablet") return Phone;
160
+ if (deviceType === "Desktop" || deviceType === "Laptop") return Monitor;
161
+ return Server;
162
+ };
163
+ if (model !== "plugin::users-permissions.user") {
164
+ return null;
165
+ }
166
+ if (loading) {
167
+ return {
168
+ title: "Session Info",
169
+ content: /* @__PURE__ */ jsx(Box, { padding: 4, background: "neutral0", children: /* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "neutral600", children: "Loading..." }) })
170
+ };
171
+ }
172
+ const isOnline = sessions.length > 0;
173
+ return {
174
+ title: "Session Info",
175
+ content: /* @__PURE__ */ jsx(Box, { style: { width: "100%" }, children: /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 4, alignItems: "stretch", children: [
176
+ /* @__PURE__ */ jsx(
177
+ Box,
178
+ {
179
+ padding: 5,
180
+ background: isOnline ? "success100" : "neutral150",
181
+ hasRadius: true,
182
+ style: {
183
+ border: isOnline ? "1px solid #c6f6d5" : "1px solid #eaeaef",
184
+ transition: "all 0.2s ease"
185
+ },
186
+ children: /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 3, alignItems: "center", children: [
187
+ /* @__PURE__ */ jsx(
188
+ Badge,
189
+ {
190
+ backgroundColor: isOnline ? "success600" : "neutral600",
191
+ textColor: "neutral0",
192
+ size: "M",
193
+ style: { fontSize: "14px", padding: "6px 12px" },
194
+ children: isOnline ? "🟢 ACTIVE" : "⚫ OFFLINE"
195
+ }
196
+ ),
197
+ /* @__PURE__ */ jsxs(Typography, { variant: "omega", fontWeight: "semiBold", textColor: isOnline ? "success700" : "neutral700", children: [
198
+ sessions.length,
199
+ " active session",
200
+ sessions.length !== 1 ? "s" : ""
201
+ ] })
202
+ ] })
203
+ }
204
+ ),
205
+ isBlocked && /* @__PURE__ */ jsxs(
206
+ Box,
207
+ {
208
+ padding: 4,
209
+ background: "danger100",
210
+ hasRadius: true,
211
+ children: [
212
+ /* @__PURE__ */ jsx(Typography, { variant: "omega", fontWeight: "semiBold", textColor: "danger700", marginBottom: 1, children: "User is blocked" }),
213
+ /* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "danger600", children: "Authentication disabled" })
214
+ ]
215
+ }
216
+ ),
217
+ sessions.length > 0 ? /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 3, alignItems: "stretch", children: [
218
+ /* @__PURE__ */ jsx(Typography, { variant: "sigma", textColor: "neutral600", textTransform: "uppercase", style: {
219
+ textAlign: "left",
220
+ letterSpacing: "0.5px",
221
+ fontSize: "12px"
222
+ }, children: "Active Sessions" }),
223
+ sessions.slice(0, 5).map((session) => {
224
+ const deviceInfo = parseUserAgent(session.userAgent);
225
+ const DeviceIcon = getDeviceIcon(deviceInfo.device);
226
+ return /* @__PURE__ */ jsx(
227
+ Box,
228
+ {
229
+ padding: 4,
230
+ background: "neutral0",
231
+ hasRadius: true,
232
+ style: {
233
+ border: "1px solid #e3e8ef",
234
+ boxShadow: "0 1px 3px rgba(0, 0, 0, 0.04)",
235
+ transition: "all 0.2s ease"
236
+ },
237
+ onMouseEnter: (e) => {
238
+ e.currentTarget.style.boxShadow = "0 4px 12px rgba(0, 0, 0, 0.08)";
239
+ e.currentTarget.style.borderColor = "#4945FF";
240
+ },
241
+ onMouseLeave: (e) => {
242
+ e.currentTarget.style.boxShadow = "0 1px 3px rgba(0, 0, 0, 0.04)";
243
+ e.currentTarget.style.borderColor = "#e3e8ef";
244
+ },
245
+ children: /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 2, alignItems: "flex-start", children: [
246
+ /* @__PURE__ */ jsxs(Flex, { gap: 2, alignItems: "center", children: [
247
+ /* @__PURE__ */ jsx(DeviceIcon, { width: "20px", height: "20px" }),
248
+ /* @__PURE__ */ jsx(Typography, { variant: "omega", fontWeight: "bold", textColor: "neutral800", children: deviceInfo.device })
249
+ ] }),
250
+ /* @__PURE__ */ jsx(
251
+ Badge,
252
+ {
253
+ backgroundColor: "success600",
254
+ textColor: "neutral0",
255
+ size: "S",
256
+ children: "Active"
257
+ }
258
+ ),
259
+ /* @__PURE__ */ jsxs(Typography, { variant: "pi", textColor: "neutral600", children: [
260
+ deviceInfo.browser,
261
+ " on ",
262
+ deviceInfo.os
263
+ ] }),
264
+ /* @__PURE__ */ jsx(Divider, {}),
265
+ /* @__PURE__ */ jsxs(Flex, { gap: 2, alignItems: "center", children: [
266
+ /* @__PURE__ */ jsx(Server, { width: "14px", height: "14px" }),
267
+ /* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "neutral600", children: session.ipAddress })
268
+ ] }),
269
+ /* @__PURE__ */ jsxs(Flex, { gap: 2, alignItems: "center", children: [
270
+ /* @__PURE__ */ jsx(Clock, { width: "14px", height: "14px" }),
271
+ /* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "neutral600", children: new Date(session.loginTime).toLocaleString("en-US", {
272
+ month: "short",
273
+ day: "numeric",
274
+ hour: "2-digit",
275
+ minute: "2-digit"
276
+ }) })
277
+ ] }),
278
+ session.minutesSinceActive !== void 0 && session.minutesSinceActive < 60 && /* @__PURE__ */ jsxs(Typography, { variant: "pi", textColor: "success600", fontWeight: "semiBold", children: [
279
+ "Active ",
280
+ session.minutesSinceActive === 0 ? "now" : `${session.minutesSinceActive} min ago`
281
+ ] })
282
+ ] })
283
+ },
284
+ session.id
285
+ );
286
+ }),
287
+ sessions.length > 5 && /* @__PURE__ */ jsx(Box, { padding: 3, background: "primary100", hasRadius: true, textAlign: "center", children: /* @__PURE__ */ jsxs(Typography, { variant: "pi", textColor: "primary600", fontWeight: "semiBold", children: [
288
+ "+",
289
+ sessions.length - 5,
290
+ " more session",
291
+ sessions.length - 5 !== 1 ? "s" : ""
292
+ ] }) })
293
+ ] }) : /* @__PURE__ */ jsx(
294
+ Box,
295
+ {
296
+ padding: 6,
297
+ background: "neutral100",
298
+ hasRadius: true,
299
+ style: {
300
+ border: "1px dashed #dcdce4",
301
+ textAlign: "center"
302
+ },
303
+ children: /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "center", gap: 2, children: [
304
+ /* @__PURE__ */ jsx(
305
+ Typography,
306
+ {
307
+ variant: "pi",
308
+ textColor: "neutral600",
309
+ style: { fontSize: "32px", marginBottom: "8px" },
310
+ children: "💤"
311
+ }
312
+ ),
313
+ /* @__PURE__ */ jsx(Typography, { variant: "omega", fontWeight: "semiBold", textColor: "neutral700", children: "No active sessions" }),
314
+ /* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "neutral500", style: { fontSize: "13px" }, children: "User has not logged in yet" })
315
+ ] })
316
+ }
317
+ ),
318
+ /* @__PURE__ */ jsx(Divider, {}),
319
+ /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 3, alignItems: "stretch", children: [
320
+ /* @__PURE__ */ jsx(Typography, { variant: "sigma", textColor: "neutral600", textTransform: "uppercase", style: {
321
+ textAlign: "left",
322
+ letterSpacing: "0.5px",
323
+ fontSize: "12px"
324
+ }, children: "Actions" }),
325
+ /* @__PURE__ */ jsx(
326
+ Button,
327
+ {
328
+ variant: "secondary",
329
+ size: "M",
330
+ fullWidth: true,
331
+ onClick: handleLogoutAll,
332
+ disabled: actionLoading || sessions.length === 0,
333
+ startIcon: /* @__PURE__ */ jsx(Cross, {}),
334
+ style: {
335
+ border: "1px solid #dc2626",
336
+ color: "#dc2626",
337
+ backgroundColor: "transparent",
338
+ transition: "all 0.2s ease"
339
+ },
340
+ onMouseEnter: (e) => {
341
+ if (!actionLoading && sessions.length > 0) {
342
+ e.currentTarget.style.backgroundColor = "#dc2626";
343
+ e.currentTarget.style.color = "white";
344
+ }
345
+ },
346
+ onMouseLeave: (e) => {
347
+ if (!actionLoading && sessions.length > 0) {
348
+ e.currentTarget.style.backgroundColor = "transparent";
349
+ e.currentTarget.style.color = "#dc2626";
350
+ }
351
+ },
352
+ children: "Terminate All Sessions"
353
+ }
354
+ ),
355
+ /* @__PURE__ */ jsx(
356
+ Button,
357
+ {
358
+ variant: "secondary",
359
+ size: "M",
360
+ fullWidth: true,
361
+ onClick: handleToggleBlock,
362
+ disabled: actionLoading,
363
+ startIcon: isBlocked ? /* @__PURE__ */ jsx(Check, {}) : /* @__PURE__ */ jsx(Cross, {}),
364
+ style: {
365
+ border: isBlocked ? "1px solid #16a34a" : "1px solid #dc2626",
366
+ color: isBlocked ? "#16a34a" : "#dc2626",
367
+ backgroundColor: "transparent",
368
+ transition: "all 0.2s ease"
369
+ },
370
+ onMouseEnter: (e) => {
371
+ if (!actionLoading) {
372
+ e.currentTarget.style.backgroundColor = isBlocked ? "#16a34a" : "#dc2626";
373
+ e.currentTarget.style.color = "white";
374
+ }
375
+ },
376
+ onMouseLeave: (e) => {
377
+ if (!actionLoading) {
378
+ e.currentTarget.style.backgroundColor = "transparent";
379
+ e.currentTarget.style.color = isBlocked ? "#16a34a" : "#dc2626";
380
+ }
381
+ },
382
+ children: isBlocked ? "Unblock User" : "Block User"
383
+ }
384
+ )
385
+ ] })
386
+ ] }) })
387
+ };
388
+ };
389
+ const prefixPluginTranslations = (data, pluginId2) => {
390
+ const prefixed = {};
391
+ Object.keys(data).forEach((key) => {
392
+ prefixed[`${pluginId2}.${key}`] = data[key];
393
+ });
394
+ return prefixed;
395
+ };
396
+ const name = pluginPkg.strapi.name;
397
+ const index = {
398
+ register(app) {
399
+ app.addMenuLink({
400
+ to: `/plugins/${pluginId}`,
401
+ icon: PluginIcon,
402
+ intlLabel: {
403
+ id: `${pluginId}.plugin.name`,
404
+ defaultMessage: pluginPkg.strapi.displayName
405
+ },
406
+ Component: () => import("./App-MPqlEJVm.mjs")
407
+ });
408
+ app.createSettingSection(
409
+ {
410
+ intlLabel: { id: `${pluginId}.settings.section`, defaultMessage: "Sessions" },
411
+ id: pluginId,
412
+ to: `/settings/${pluginId}`
413
+ },
414
+ [
415
+ {
416
+ intlLabel: {
417
+ id: `${pluginId}.settings.general`,
418
+ defaultMessage: "General"
419
+ },
420
+ id: "general",
421
+ to: `/settings/${pluginId}/general`,
422
+ Component: () => import("./Settings-Ds8IhBiX.mjs")
423
+ },
424
+ {
425
+ intlLabel: {
426
+ id: `${pluginId}.settings.analytics`,
427
+ defaultMessage: "Analytics"
428
+ },
429
+ id: "analytics",
430
+ to: `/settings/${pluginId}/analytics`,
431
+ Component: () => import("./Analytics-ZQSBqi6k.mjs")
432
+ },
433
+ {
434
+ intlLabel: {
435
+ id: `${pluginId}.settings.license`,
436
+ defaultMessage: "License"
437
+ },
438
+ id: "license",
439
+ to: `/settings/${pluginId}/license`,
440
+ Component: () => import("./License-WSbNrJuz.mjs")
441
+ }
442
+ ]
443
+ );
444
+ app.registerPlugin({
445
+ id: pluginId,
446
+ initializer: Initializer,
447
+ isReady: true,
448
+ name
449
+ });
450
+ if ("widgets" in app) {
451
+ app.widgets.register({
452
+ icon: PluginIcon,
453
+ title: {
454
+ id: `${pluginId}.widget.online-users.title`,
455
+ defaultMessage: "Online Users"
456
+ },
457
+ component: async () => {
458
+ const component = await import("./OnlineUsersWidget-ArMl0nen.mjs");
459
+ return component.default;
460
+ },
461
+ id: "online-users-widget",
462
+ pluginId
463
+ });
464
+ console.log(`[${pluginId}] ✅ Online Users Widget registered`);
465
+ }
466
+ },
467
+ bootstrap(app) {
468
+ console.log(`[${pluginId}] Bootstrapping plugin...`);
469
+ try {
470
+ const contentManagerPlugin = app.getPlugin("content-manager");
471
+ if (contentManagerPlugin && contentManagerPlugin.apis) {
472
+ console.log(`[${pluginId}] Injecting SessionInfoPanel into edit view sidebar...`);
473
+ contentManagerPlugin.apis.addEditViewSidePanel([SessionInfoPanel]);
474
+ console.log(`[${pluginId}] ✅ SessionInfoPanel injected successfully`);
475
+ } else {
476
+ console.warn(`[${pluginId}] Content Manager plugin or APIs not available`);
477
+ }
478
+ } catch (error) {
479
+ console.error(`[${pluginId}] Error injecting SessionInfoPanel:`, error);
480
+ }
481
+ },
482
+ async registerTrads({ locales }) {
483
+ const importedTrads = {
484
+ en: () => import("./en-CsPpPJL3.mjs"),
485
+ de: () => import("./de-CdO3s01z.mjs")
486
+ };
487
+ const translatedLanguages = Object.keys(importedTrads).filter(
488
+ (lang) => locales.includes(lang)
489
+ );
490
+ const translations = await Promise.all(
491
+ translatedLanguages.map(
492
+ (language) => importedTrads[language]().then(({ default: data }) => ({
493
+ data: prefixPluginTranslations(data, pluginId),
494
+ locale: language
495
+ })).catch(() => ({
496
+ data: {},
497
+ locale: language
498
+ }))
499
+ )
500
+ );
501
+ return Promise.resolve(translations);
502
+ }
503
+ };
504
+ export {
505
+ pluginId as a,
506
+ index as i,
507
+ parseUserAgent as p
508
+ };