strapi-plugin-notifier 1.0.2 → 1.0.3
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/dist/_chunks/{Index-CiDBgkGf.js → Index-C5mgbISF.js} +18 -19
- package/dist/_chunks/{Index-DI2t9tlH.mjs → Index-DOQrGurB.mjs} +2 -3
- package/dist/_chunks/{SettingsPage-DIKfBfvo.mjs → SettingsPage-CRsuB4cw.mjs} +1 -4
- package/dist/_chunks/{SettingsPage-BdBxZMqP.js → SettingsPage-Cft7agRa.js} +8 -11
- package/dist/_chunks/index-7hrPEwa_.mjs +221 -0
- package/dist/_chunks/index-DrwLcZBZ.js +220 -0
- package/dist/admin/index.js +1 -2
- package/dist/admin/index.mjs +1 -2
- package/dist/server/index.js +1 -1
- package/dist/server/index.mjs +1 -1
- package/package.json +5 -2
- package/dist/_chunks/index-7WJGsVEY.js +0 -28282
- package/dist/_chunks/index-CNYabBMJ.mjs +0 -28264
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
3
|
const jsxRuntime = require("react/jsx-runtime");
|
|
4
|
-
const
|
|
4
|
+
const react = require("react");
|
|
5
5
|
const designSystem = require("@strapi/design-system");
|
|
6
|
-
require("
|
|
6
|
+
const strapiAdmin = require("@strapi/admin/strapi-admin");
|
|
7
|
+
const index = require("./index-DrwLcZBZ.js");
|
|
7
8
|
const icons = require("@strapi/icons");
|
|
8
|
-
const index = require("./index-7WJGsVEY.js");
|
|
9
|
-
require("@strapi/icons/symbols");
|
|
10
9
|
const toStoreItem = (n) => ({
|
|
11
10
|
id: String(n.id),
|
|
12
11
|
title: n.title,
|
|
@@ -17,11 +16,11 @@ const toStoreItem = (n) => ({
|
|
|
17
16
|
url: n.url
|
|
18
17
|
});
|
|
19
18
|
const useNotificationActions = () => {
|
|
20
|
-
const { get, put, del } =
|
|
21
|
-
const [isLoading, setIsLoading] =
|
|
22
|
-
const [pagination, setPagination] =
|
|
23
|
-
const currentPage =
|
|
24
|
-
const fetchPage =
|
|
19
|
+
const { get, put, del } = strapiAdmin.useFetchClient();
|
|
20
|
+
const [isLoading, setIsLoading] = react.useState(false);
|
|
21
|
+
const [pagination, setPagination] = react.useState(null);
|
|
22
|
+
const currentPage = react.useRef(1);
|
|
23
|
+
const fetchPage = react.useCallback(
|
|
25
24
|
async (page, append = false) => {
|
|
26
25
|
const { pageSize } = index.getConfig();
|
|
27
26
|
setIsLoading(true);
|
|
@@ -45,12 +44,12 @@ const useNotificationActions = () => {
|
|
|
45
44
|
},
|
|
46
45
|
[get]
|
|
47
46
|
);
|
|
48
|
-
const fetchAll =
|
|
49
|
-
const loadMore =
|
|
47
|
+
const fetchAll = react.useCallback(() => fetchPage(1, false), [fetchPage]);
|
|
48
|
+
const loadMore = react.useCallback(() => {
|
|
50
49
|
if (!pagination || currentPage.current >= pagination.pageCount) return;
|
|
51
50
|
fetchPage(currentPage.current + 1, true);
|
|
52
51
|
}, [fetchPage, pagination]);
|
|
53
|
-
const handleMarkAsRead =
|
|
52
|
+
const handleMarkAsRead = react.useCallback(
|
|
54
53
|
async (id) => {
|
|
55
54
|
index.markAsRead(id);
|
|
56
55
|
try {
|
|
@@ -60,14 +59,14 @@ const useNotificationActions = () => {
|
|
|
60
59
|
},
|
|
61
60
|
[put]
|
|
62
61
|
);
|
|
63
|
-
const handleMarkAllAsRead =
|
|
62
|
+
const handleMarkAllAsRead = react.useCallback(async () => {
|
|
64
63
|
index.markAllAsRead();
|
|
65
64
|
try {
|
|
66
65
|
await put("/notifier/notifications/read-all");
|
|
67
66
|
} catch {
|
|
68
67
|
}
|
|
69
68
|
}, [put]);
|
|
70
|
-
const handleClear =
|
|
69
|
+
const handleClear = react.useCallback(
|
|
71
70
|
async (id) => {
|
|
72
71
|
index.clearNotification(id);
|
|
73
72
|
try {
|
|
@@ -77,7 +76,7 @@ const useNotificationActions = () => {
|
|
|
77
76
|
},
|
|
78
77
|
[del]
|
|
79
78
|
);
|
|
80
|
-
const handleClearAll =
|
|
79
|
+
const handleClearAll = react.useCallback(async () => {
|
|
81
80
|
index.clearAll();
|
|
82
81
|
try {
|
|
83
82
|
await del("/notifier/notifications");
|
|
@@ -150,8 +149,8 @@ function InboxHeader({
|
|
|
150
149
|
] });
|
|
151
150
|
}
|
|
152
151
|
const useNotifications = () => {
|
|
153
|
-
const [notifications, setNotifications] =
|
|
154
|
-
|
|
152
|
+
const [notifications, setNotifications] = react.useState(index.getNotifications);
|
|
153
|
+
react.useEffect(() => index.subscribeToNotifications(setNotifications), []);
|
|
155
154
|
return notifications;
|
|
156
155
|
};
|
|
157
156
|
const UNREAD_BG = {
|
|
@@ -270,7 +269,7 @@ function NotificationList({
|
|
|
270
269
|
] });
|
|
271
270
|
}
|
|
272
271
|
function Index() {
|
|
273
|
-
const [filter, setFilter] =
|
|
272
|
+
const [filter, setFilter] = react.useState("all");
|
|
274
273
|
const {
|
|
275
274
|
fetchAll,
|
|
276
275
|
loadMore,
|
|
@@ -281,7 +280,7 @@ function Index() {
|
|
|
281
280
|
isLoading,
|
|
282
281
|
hasMore
|
|
283
282
|
} = useNotificationActions();
|
|
284
|
-
|
|
283
|
+
react.useEffect(() => {
|
|
285
284
|
fetchAll();
|
|
286
285
|
}, []);
|
|
287
286
|
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { padding: 8, style: { height: "100%" }, children: [
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { jsxs, jsx } from "react/jsx-runtime";
|
|
2
2
|
import { useState, useRef, useCallback, useEffect } from "react";
|
|
3
3
|
import { Box, Flex, Typography, Button, IconButton, Loader } from "@strapi/design-system";
|
|
4
|
-
import "
|
|
4
|
+
import { useFetchClient } from "@strapi/admin/strapi-admin";
|
|
5
|
+
import { g as getConfig, s as setNotifications, a as getNotifications, m as markAsRead, b as markAllAsRead, c as clearNotification, d as clearAll, e as subscribeToNotifications, u as usePluginConfig } from "./index-7hrPEwa_.mjs";
|
|
5
6
|
import { Cross } from "@strapi/icons";
|
|
6
|
-
import { u as useFetchClient, g as getConfig, s as setNotifications, a as getNotifications, m as markAsRead, b as markAllAsRead, c as clearNotification, d as clearAll, e as subscribeToNotifications, f as usePluginConfig } from "./index-CNYabBMJ.mjs";
|
|
7
|
-
import "@strapi/icons/symbols";
|
|
8
7
|
const toStoreItem = (n) => ({
|
|
9
8
|
id: String(n.id),
|
|
10
9
|
title: n.title,
|
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
import { jsxs, jsx } from "react/jsx-runtime";
|
|
2
2
|
import { useState, useEffect } from "react";
|
|
3
3
|
import { Box, Flex, Typography, Button, NumberInput, Divider, TextInput } from "@strapi/design-system";
|
|
4
|
-
import "
|
|
5
|
-
import "@strapi/icons";
|
|
6
|
-
import { u as useFetchClient } from "./index-CNYabBMJ.mjs";
|
|
7
|
-
import "@strapi/icons/symbols";
|
|
4
|
+
import { useFetchClient } from "@strapi/admin/strapi-admin";
|
|
8
5
|
const DEFAULT = {
|
|
9
6
|
retention: { maxDays: 90, maxPerUser: 500 },
|
|
10
7
|
delivery: { pollIntervalMs: 3e4, pageSize: 20 },
|
|
@@ -1,24 +1,21 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
3
|
const jsxRuntime = require("react/jsx-runtime");
|
|
4
|
-
const
|
|
4
|
+
const react = require("react");
|
|
5
5
|
const designSystem = require("@strapi/design-system");
|
|
6
|
-
require("
|
|
7
|
-
require("@strapi/icons");
|
|
8
|
-
const index = require("./index-7WJGsVEY.js");
|
|
9
|
-
require("@strapi/icons/symbols");
|
|
6
|
+
const strapiAdmin = require("@strapi/admin/strapi-admin");
|
|
10
7
|
const DEFAULT = {
|
|
11
8
|
retention: { maxDays: 90, maxPerUser: 500 },
|
|
12
9
|
delivery: { pollIntervalMs: 3e4, pageSize: 20 },
|
|
13
10
|
ui: { theme: { accent: { info: "#4945ff", success: "#5cb85c", warning: "#f0ad4e", error: "#ee5e52" } } }
|
|
14
11
|
};
|
|
15
12
|
function SettingsPage() {
|
|
16
|
-
const { get, put, del } =
|
|
17
|
-
const [settings, setSettings] =
|
|
18
|
-
const [isSaving, setIsSaving] =
|
|
19
|
-
const [isResetting, setIsResetting] =
|
|
20
|
-
const [saveError, setSaveError] =
|
|
21
|
-
|
|
13
|
+
const { get, put, del } = strapiAdmin.useFetchClient();
|
|
14
|
+
const [settings, setSettings] = react.useState(DEFAULT);
|
|
15
|
+
const [isSaving, setIsSaving] = react.useState(false);
|
|
16
|
+
const [isResetting, setIsResetting] = react.useState(false);
|
|
17
|
+
const [saveError, setSaveError] = react.useState(null);
|
|
18
|
+
react.useEffect(() => {
|
|
22
19
|
get("/notifier/settings").then(({ data }) => {
|
|
23
20
|
if (data) setSettings(data);
|
|
24
21
|
}).catch(() => {
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
import { jsxs, jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useState, useEffect, useRef } from "react";
|
|
3
|
+
import { useFetchClient } from "@strapi/admin/strapi-admin";
|
|
4
|
+
let items = [];
|
|
5
|
+
let countSubscribers = [];
|
|
6
|
+
let itemSubscribers = [];
|
|
7
|
+
const getUnreadCount = () => items.filter((n) => !n.read).length;
|
|
8
|
+
const broadcastCount = () => {
|
|
9
|
+
const n = getUnreadCount();
|
|
10
|
+
countSubscribers.forEach((fn) => fn(n));
|
|
11
|
+
};
|
|
12
|
+
const broadcastItems = () => {
|
|
13
|
+
const snapshot = [...items];
|
|
14
|
+
itemSubscribers.forEach((fn) => fn(snapshot));
|
|
15
|
+
broadcastCount();
|
|
16
|
+
};
|
|
17
|
+
const getNotificationCount = () => getUnreadCount();
|
|
18
|
+
const getNotifications = () => [...items];
|
|
19
|
+
const subscribeToCount = (fn) => {
|
|
20
|
+
countSubscribers.push(fn);
|
|
21
|
+
return () => {
|
|
22
|
+
countSubscribers = countSubscribers.filter((s) => s !== fn);
|
|
23
|
+
};
|
|
24
|
+
};
|
|
25
|
+
const subscribeToNotifications = (fn) => {
|
|
26
|
+
itemSubscribers.push(fn);
|
|
27
|
+
return () => {
|
|
28
|
+
itemSubscribers = itemSubscribers.filter((s) => s !== fn);
|
|
29
|
+
};
|
|
30
|
+
};
|
|
31
|
+
const setNotifications = (next) => {
|
|
32
|
+
items = next;
|
|
33
|
+
broadcastItems();
|
|
34
|
+
};
|
|
35
|
+
const markAsRead = (id) => {
|
|
36
|
+
items = items.map((n) => n.id === id ? { ...n, read: true } : n);
|
|
37
|
+
broadcastItems();
|
|
38
|
+
};
|
|
39
|
+
const markAllAsRead = () => {
|
|
40
|
+
items = items.map((n) => ({ ...n, read: true }));
|
|
41
|
+
broadcastItems();
|
|
42
|
+
};
|
|
43
|
+
const clearNotification = (id) => {
|
|
44
|
+
items = items.filter((n) => n.id !== id);
|
|
45
|
+
broadcastItems();
|
|
46
|
+
};
|
|
47
|
+
const clearAll = () => {
|
|
48
|
+
items = [];
|
|
49
|
+
broadcastItems();
|
|
50
|
+
};
|
|
51
|
+
const useNotificationCount = () => {
|
|
52
|
+
const [count, setCount] = useState(getNotificationCount);
|
|
53
|
+
useEffect(() => subscribeToCount(setCount), []);
|
|
54
|
+
return count;
|
|
55
|
+
};
|
|
56
|
+
const DEFAULT_CONFIG = {
|
|
57
|
+
pollIntervalMs: 3e4,
|
|
58
|
+
pageSize: 20,
|
|
59
|
+
theme: {
|
|
60
|
+
accent: {
|
|
61
|
+
info: "#4945ff",
|
|
62
|
+
success: "#5cb85c",
|
|
63
|
+
warning: "#f0ad4e",
|
|
64
|
+
error: "#ee5e52"
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
let config = DEFAULT_CONFIG;
|
|
69
|
+
let subscribers = [];
|
|
70
|
+
const getConfig = () => config;
|
|
71
|
+
const setConfig = (next) => {
|
|
72
|
+
config = { ...DEFAULT_CONFIG, ...next, theme: { accent: { ...DEFAULT_CONFIG.theme.accent, ...next?.theme?.accent } } };
|
|
73
|
+
subscribers.forEach((fn) => fn(config));
|
|
74
|
+
};
|
|
75
|
+
const subscribeToConfig = (fn) => {
|
|
76
|
+
subscribers.push(fn);
|
|
77
|
+
return () => {
|
|
78
|
+
subscribers = subscribers.filter((s) => s !== fn);
|
|
79
|
+
};
|
|
80
|
+
};
|
|
81
|
+
const usePluginConfig = () => {
|
|
82
|
+
const [config2, setConfig2] = useState(getConfig);
|
|
83
|
+
useEffect(() => subscribeToConfig(setConfig2), []);
|
|
84
|
+
return config2;
|
|
85
|
+
};
|
|
86
|
+
const toStoreNotification = (n) => ({
|
|
87
|
+
id: String(n.id),
|
|
88
|
+
title: n.title,
|
|
89
|
+
message: n.message ?? "",
|
|
90
|
+
type: n.type ?? "info",
|
|
91
|
+
read: n.read,
|
|
92
|
+
createdAt: n.createdAt,
|
|
93
|
+
url: n.url
|
|
94
|
+
});
|
|
95
|
+
function Bell() {
|
|
96
|
+
const count = useNotificationCount();
|
|
97
|
+
const config2 = usePluginConfig();
|
|
98
|
+
const { get } = useFetchClient();
|
|
99
|
+
const configLoaded = useRef(false);
|
|
100
|
+
useEffect(() => {
|
|
101
|
+
if (configLoaded.current) return;
|
|
102
|
+
configLoaded.current = true;
|
|
103
|
+
get("/notifier/config").then(({ data }) => {
|
|
104
|
+
if (data) setConfig(data);
|
|
105
|
+
}).catch(() => {
|
|
106
|
+
});
|
|
107
|
+
}, [get]);
|
|
108
|
+
useEffect(() => {
|
|
109
|
+
const poll = async () => {
|
|
110
|
+
try {
|
|
111
|
+
const { data } = await get(`/notifier/notifications?page=1&pageSize=${config2.pageSize}`);
|
|
112
|
+
if (Array.isArray(data?.data)) {
|
|
113
|
+
setNotifications(data.data.map(toStoreNotification));
|
|
114
|
+
}
|
|
115
|
+
} catch {
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
poll();
|
|
119
|
+
const id = setInterval(poll, config2.pollIntervalMs);
|
|
120
|
+
return () => clearInterval(id);
|
|
121
|
+
}, [get, config2.pollIntervalMs, config2.pageSize]);
|
|
122
|
+
return /* @__PURE__ */ jsxs("span", { style: { position: "relative", display: "inline-flex" }, children: [
|
|
123
|
+
/* @__PURE__ */ jsxs(
|
|
124
|
+
"svg",
|
|
125
|
+
{
|
|
126
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
127
|
+
viewBox: "0 0 24 24",
|
|
128
|
+
fill: "none",
|
|
129
|
+
stroke: "currentColor",
|
|
130
|
+
strokeWidth: "2",
|
|
131
|
+
strokeLinecap: "round",
|
|
132
|
+
strokeLinejoin: "round",
|
|
133
|
+
width: "1.5em",
|
|
134
|
+
height: "1.5em",
|
|
135
|
+
children: [
|
|
136
|
+
/* @__PURE__ */ jsx("path", { d: "M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9" }),
|
|
137
|
+
/* @__PURE__ */ jsx("path", { d: "M13.73 21a2 2 0 0 1-3.46 0" })
|
|
138
|
+
]
|
|
139
|
+
}
|
|
140
|
+
),
|
|
141
|
+
count > 0 && /* @__PURE__ */ jsx(
|
|
142
|
+
"span",
|
|
143
|
+
{
|
|
144
|
+
"aria-label": `${count} unread notification${count === 1 ? "" : "s"}`,
|
|
145
|
+
style: {
|
|
146
|
+
position: "absolute",
|
|
147
|
+
top: "-5px",
|
|
148
|
+
right: "-6px",
|
|
149
|
+
backgroundColor: "#ee5e52",
|
|
150
|
+
color: "#fff",
|
|
151
|
+
borderRadius: "9px",
|
|
152
|
+
fontSize: "9px",
|
|
153
|
+
fontWeight: 700,
|
|
154
|
+
height: "13px",
|
|
155
|
+
minWidth: "13px",
|
|
156
|
+
display: "flex",
|
|
157
|
+
alignItems: "center",
|
|
158
|
+
justifyContent: "center",
|
|
159
|
+
padding: "0 2px",
|
|
160
|
+
lineHeight: 1,
|
|
161
|
+
pointerEvents: "none"
|
|
162
|
+
},
|
|
163
|
+
children: count > 99 ? "99+" : count
|
|
164
|
+
}
|
|
165
|
+
)
|
|
166
|
+
] });
|
|
167
|
+
}
|
|
168
|
+
const pluginId = "notifier";
|
|
169
|
+
const index = {
|
|
170
|
+
register(app) {
|
|
171
|
+
app.addMenuLink({
|
|
172
|
+
to: `/plugins/${pluginId}`,
|
|
173
|
+
icon: Bell,
|
|
174
|
+
intlLabel: {
|
|
175
|
+
id: `${pluginId}.plugin.name`,
|
|
176
|
+
defaultMessage: "Notifications"
|
|
177
|
+
},
|
|
178
|
+
permissions: [],
|
|
179
|
+
Component: () => import("./Index-DOQrGurB.mjs")
|
|
180
|
+
});
|
|
181
|
+
app.createSettingSection(
|
|
182
|
+
{
|
|
183
|
+
id: pluginId,
|
|
184
|
+
intlLabel: {
|
|
185
|
+
id: `${pluginId}.settings.section`,
|
|
186
|
+
defaultMessage: "Notifier"
|
|
187
|
+
}
|
|
188
|
+
},
|
|
189
|
+
[
|
|
190
|
+
{
|
|
191
|
+
intlLabel: {
|
|
192
|
+
id: `${pluginId}.settings.page`,
|
|
193
|
+
defaultMessage: "Configuration"
|
|
194
|
+
},
|
|
195
|
+
id: `${pluginId}.settings`,
|
|
196
|
+
to: `/settings/${pluginId}`,
|
|
197
|
+
Component: () => import("./SettingsPage-CRsuB4cw.mjs"),
|
|
198
|
+
permissions: [
|
|
199
|
+
{ action: `plugin::${pluginId}.settings.read`, subject: null }
|
|
200
|
+
]
|
|
201
|
+
}
|
|
202
|
+
]
|
|
203
|
+
);
|
|
204
|
+
app.registerPlugin({
|
|
205
|
+
id: pluginId,
|
|
206
|
+
name: "Notifier"
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
};
|
|
210
|
+
export {
|
|
211
|
+
getNotifications as a,
|
|
212
|
+
markAllAsRead as b,
|
|
213
|
+
clearNotification as c,
|
|
214
|
+
clearAll as d,
|
|
215
|
+
subscribeToNotifications as e,
|
|
216
|
+
getConfig as g,
|
|
217
|
+
index as i,
|
|
218
|
+
markAsRead as m,
|
|
219
|
+
setNotifications as s,
|
|
220
|
+
usePluginConfig as u
|
|
221
|
+
};
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
const jsxRuntime = require("react/jsx-runtime");
|
|
3
|
+
const react = require("react");
|
|
4
|
+
const strapiAdmin = require("@strapi/admin/strapi-admin");
|
|
5
|
+
let items = [];
|
|
6
|
+
let countSubscribers = [];
|
|
7
|
+
let itemSubscribers = [];
|
|
8
|
+
const getUnreadCount = () => items.filter((n) => !n.read).length;
|
|
9
|
+
const broadcastCount = () => {
|
|
10
|
+
const n = getUnreadCount();
|
|
11
|
+
countSubscribers.forEach((fn) => fn(n));
|
|
12
|
+
};
|
|
13
|
+
const broadcastItems = () => {
|
|
14
|
+
const snapshot = [...items];
|
|
15
|
+
itemSubscribers.forEach((fn) => fn(snapshot));
|
|
16
|
+
broadcastCount();
|
|
17
|
+
};
|
|
18
|
+
const getNotificationCount = () => getUnreadCount();
|
|
19
|
+
const getNotifications = () => [...items];
|
|
20
|
+
const subscribeToCount = (fn) => {
|
|
21
|
+
countSubscribers.push(fn);
|
|
22
|
+
return () => {
|
|
23
|
+
countSubscribers = countSubscribers.filter((s) => s !== fn);
|
|
24
|
+
};
|
|
25
|
+
};
|
|
26
|
+
const subscribeToNotifications = (fn) => {
|
|
27
|
+
itemSubscribers.push(fn);
|
|
28
|
+
return () => {
|
|
29
|
+
itemSubscribers = itemSubscribers.filter((s) => s !== fn);
|
|
30
|
+
};
|
|
31
|
+
};
|
|
32
|
+
const setNotifications = (next) => {
|
|
33
|
+
items = next;
|
|
34
|
+
broadcastItems();
|
|
35
|
+
};
|
|
36
|
+
const markAsRead = (id) => {
|
|
37
|
+
items = items.map((n) => n.id === id ? { ...n, read: true } : n);
|
|
38
|
+
broadcastItems();
|
|
39
|
+
};
|
|
40
|
+
const markAllAsRead = () => {
|
|
41
|
+
items = items.map((n) => ({ ...n, read: true }));
|
|
42
|
+
broadcastItems();
|
|
43
|
+
};
|
|
44
|
+
const clearNotification = (id) => {
|
|
45
|
+
items = items.filter((n) => n.id !== id);
|
|
46
|
+
broadcastItems();
|
|
47
|
+
};
|
|
48
|
+
const clearAll = () => {
|
|
49
|
+
items = [];
|
|
50
|
+
broadcastItems();
|
|
51
|
+
};
|
|
52
|
+
const useNotificationCount = () => {
|
|
53
|
+
const [count, setCount] = react.useState(getNotificationCount);
|
|
54
|
+
react.useEffect(() => subscribeToCount(setCount), []);
|
|
55
|
+
return count;
|
|
56
|
+
};
|
|
57
|
+
const DEFAULT_CONFIG = {
|
|
58
|
+
pollIntervalMs: 3e4,
|
|
59
|
+
pageSize: 20,
|
|
60
|
+
theme: {
|
|
61
|
+
accent: {
|
|
62
|
+
info: "#4945ff",
|
|
63
|
+
success: "#5cb85c",
|
|
64
|
+
warning: "#f0ad4e",
|
|
65
|
+
error: "#ee5e52"
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
let config = DEFAULT_CONFIG;
|
|
70
|
+
let subscribers = [];
|
|
71
|
+
const getConfig = () => config;
|
|
72
|
+
const setConfig = (next) => {
|
|
73
|
+
config = { ...DEFAULT_CONFIG, ...next, theme: { accent: { ...DEFAULT_CONFIG.theme.accent, ...next?.theme?.accent } } };
|
|
74
|
+
subscribers.forEach((fn) => fn(config));
|
|
75
|
+
};
|
|
76
|
+
const subscribeToConfig = (fn) => {
|
|
77
|
+
subscribers.push(fn);
|
|
78
|
+
return () => {
|
|
79
|
+
subscribers = subscribers.filter((s) => s !== fn);
|
|
80
|
+
};
|
|
81
|
+
};
|
|
82
|
+
const usePluginConfig = () => {
|
|
83
|
+
const [config2, setConfig2] = react.useState(getConfig);
|
|
84
|
+
react.useEffect(() => subscribeToConfig(setConfig2), []);
|
|
85
|
+
return config2;
|
|
86
|
+
};
|
|
87
|
+
const toStoreNotification = (n) => ({
|
|
88
|
+
id: String(n.id),
|
|
89
|
+
title: n.title,
|
|
90
|
+
message: n.message ?? "",
|
|
91
|
+
type: n.type ?? "info",
|
|
92
|
+
read: n.read,
|
|
93
|
+
createdAt: n.createdAt,
|
|
94
|
+
url: n.url
|
|
95
|
+
});
|
|
96
|
+
function Bell() {
|
|
97
|
+
const count = useNotificationCount();
|
|
98
|
+
const config2 = usePluginConfig();
|
|
99
|
+
const { get } = strapiAdmin.useFetchClient();
|
|
100
|
+
const configLoaded = react.useRef(false);
|
|
101
|
+
react.useEffect(() => {
|
|
102
|
+
if (configLoaded.current) return;
|
|
103
|
+
configLoaded.current = true;
|
|
104
|
+
get("/notifier/config").then(({ data }) => {
|
|
105
|
+
if (data) setConfig(data);
|
|
106
|
+
}).catch(() => {
|
|
107
|
+
});
|
|
108
|
+
}, [get]);
|
|
109
|
+
react.useEffect(() => {
|
|
110
|
+
const poll = async () => {
|
|
111
|
+
try {
|
|
112
|
+
const { data } = await get(`/notifier/notifications?page=1&pageSize=${config2.pageSize}`);
|
|
113
|
+
if (Array.isArray(data?.data)) {
|
|
114
|
+
setNotifications(data.data.map(toStoreNotification));
|
|
115
|
+
}
|
|
116
|
+
} catch {
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
poll();
|
|
120
|
+
const id = setInterval(poll, config2.pollIntervalMs);
|
|
121
|
+
return () => clearInterval(id);
|
|
122
|
+
}, [get, config2.pollIntervalMs, config2.pageSize]);
|
|
123
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { position: "relative", display: "inline-flex" }, children: [
|
|
124
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
125
|
+
"svg",
|
|
126
|
+
{
|
|
127
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
128
|
+
viewBox: "0 0 24 24",
|
|
129
|
+
fill: "none",
|
|
130
|
+
stroke: "currentColor",
|
|
131
|
+
strokeWidth: "2",
|
|
132
|
+
strokeLinecap: "round",
|
|
133
|
+
strokeLinejoin: "round",
|
|
134
|
+
width: "1.5em",
|
|
135
|
+
height: "1.5em",
|
|
136
|
+
children: [
|
|
137
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9" }),
|
|
138
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M13.73 21a2 2 0 0 1-3.46 0" })
|
|
139
|
+
]
|
|
140
|
+
}
|
|
141
|
+
),
|
|
142
|
+
count > 0 && /* @__PURE__ */ jsxRuntime.jsx(
|
|
143
|
+
"span",
|
|
144
|
+
{
|
|
145
|
+
"aria-label": `${count} unread notification${count === 1 ? "" : "s"}`,
|
|
146
|
+
style: {
|
|
147
|
+
position: "absolute",
|
|
148
|
+
top: "-5px",
|
|
149
|
+
right: "-6px",
|
|
150
|
+
backgroundColor: "#ee5e52",
|
|
151
|
+
color: "#fff",
|
|
152
|
+
borderRadius: "9px",
|
|
153
|
+
fontSize: "9px",
|
|
154
|
+
fontWeight: 700,
|
|
155
|
+
height: "13px",
|
|
156
|
+
minWidth: "13px",
|
|
157
|
+
display: "flex",
|
|
158
|
+
alignItems: "center",
|
|
159
|
+
justifyContent: "center",
|
|
160
|
+
padding: "0 2px",
|
|
161
|
+
lineHeight: 1,
|
|
162
|
+
pointerEvents: "none"
|
|
163
|
+
},
|
|
164
|
+
children: count > 99 ? "99+" : count
|
|
165
|
+
}
|
|
166
|
+
)
|
|
167
|
+
] });
|
|
168
|
+
}
|
|
169
|
+
const pluginId = "notifier";
|
|
170
|
+
const index = {
|
|
171
|
+
register(app) {
|
|
172
|
+
app.addMenuLink({
|
|
173
|
+
to: `/plugins/${pluginId}`,
|
|
174
|
+
icon: Bell,
|
|
175
|
+
intlLabel: {
|
|
176
|
+
id: `${pluginId}.plugin.name`,
|
|
177
|
+
defaultMessage: "Notifications"
|
|
178
|
+
},
|
|
179
|
+
permissions: [],
|
|
180
|
+
Component: () => Promise.resolve().then(() => require("./Index-C5mgbISF.js"))
|
|
181
|
+
});
|
|
182
|
+
app.createSettingSection(
|
|
183
|
+
{
|
|
184
|
+
id: pluginId,
|
|
185
|
+
intlLabel: {
|
|
186
|
+
id: `${pluginId}.settings.section`,
|
|
187
|
+
defaultMessage: "Notifier"
|
|
188
|
+
}
|
|
189
|
+
},
|
|
190
|
+
[
|
|
191
|
+
{
|
|
192
|
+
intlLabel: {
|
|
193
|
+
id: `${pluginId}.settings.page`,
|
|
194
|
+
defaultMessage: "Configuration"
|
|
195
|
+
},
|
|
196
|
+
id: `${pluginId}.settings`,
|
|
197
|
+
to: `/settings/${pluginId}`,
|
|
198
|
+
Component: () => Promise.resolve().then(() => require("./SettingsPage-Cft7agRa.js")),
|
|
199
|
+
permissions: [
|
|
200
|
+
{ action: `plugin::${pluginId}.settings.read`, subject: null }
|
|
201
|
+
]
|
|
202
|
+
}
|
|
203
|
+
]
|
|
204
|
+
);
|
|
205
|
+
app.registerPlugin({
|
|
206
|
+
id: pluginId,
|
|
207
|
+
name: "Notifier"
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
};
|
|
211
|
+
exports.clearAll = clearAll;
|
|
212
|
+
exports.clearNotification = clearNotification;
|
|
213
|
+
exports.getConfig = getConfig;
|
|
214
|
+
exports.getNotifications = getNotifications;
|
|
215
|
+
exports.index = index;
|
|
216
|
+
exports.markAllAsRead = markAllAsRead;
|
|
217
|
+
exports.markAsRead = markAsRead;
|
|
218
|
+
exports.setNotifications = setNotifications;
|
|
219
|
+
exports.subscribeToNotifications = subscribeToNotifications;
|
|
220
|
+
exports.usePluginConfig = usePluginConfig;
|
package/dist/admin/index.js
CHANGED
package/dist/admin/index.mjs
CHANGED
package/dist/server/index.js
CHANGED
package/dist/server/index.mjs
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "strapi-plugin-notifier",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.3",
|
|
4
4
|
"description": "A highly configurable notification inbox plugin for the Strapi v5 admin panel",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"strapi",
|
|
@@ -61,12 +61,15 @@
|
|
|
61
61
|
"typescript": "^5.0.0"
|
|
62
62
|
},
|
|
63
63
|
"peerDependencies": {
|
|
64
|
+
"@strapi/admin": "^5.0.0",
|
|
64
65
|
"@strapi/design-system": "^2.0.0",
|
|
65
66
|
"@strapi/icons": "^2.0.0",
|
|
66
67
|
"@strapi/strapi": "^5.0.0",
|
|
67
68
|
"framer-motion": "*",
|
|
68
69
|
"react": "^18.0.0",
|
|
69
|
-
"react-dom": "^18.0.0"
|
|
70
|
+
"react-dom": "^18.0.0",
|
|
71
|
+
"react-router-dom": "^6.0.0",
|
|
72
|
+
"styled-components": "^6.0.0"
|
|
70
73
|
},
|
|
71
74
|
"engines": {
|
|
72
75
|
"node": ">=18.0.0 <=22.x.x",
|