strapi-plugin-notifier 1.0.1 → 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 +4 -4
- package/dist/server/index.mjs +4 -4
- 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
|
@@ -438,23 +438,23 @@ const settings = {
|
|
|
438
438
|
method: "GET",
|
|
439
439
|
path: "/settings",
|
|
440
440
|
handler: "settings.find",
|
|
441
|
-
config: { policies: ["admin::
|
|
441
|
+
config: { policies: ["admin::isAuthenticatedAdmin"] }
|
|
442
442
|
},
|
|
443
443
|
{
|
|
444
444
|
method: "PUT",
|
|
445
445
|
path: "/settings",
|
|
446
446
|
handler: "settings.update",
|
|
447
|
-
config: { policies: ["admin::
|
|
447
|
+
config: { policies: ["admin::isAuthenticatedAdmin"] }
|
|
448
448
|
},
|
|
449
449
|
{
|
|
450
450
|
method: "DELETE",
|
|
451
451
|
path: "/settings",
|
|
452
452
|
handler: "settings.reset",
|
|
453
|
-
config: { policies: ["admin::
|
|
453
|
+
config: { policies: ["admin::isAuthenticatedAdmin"] }
|
|
454
454
|
}
|
|
455
455
|
]
|
|
456
456
|
};
|
|
457
|
-
const adminRoutes =
|
|
457
|
+
const adminRoutes = { notification, config, settings };
|
|
458
458
|
const index = {
|
|
459
459
|
register,
|
|
460
460
|
bootstrap,
|
package/dist/server/index.mjs
CHANGED
|
@@ -437,23 +437,23 @@ const settings = {
|
|
|
437
437
|
method: "GET",
|
|
438
438
|
path: "/settings",
|
|
439
439
|
handler: "settings.find",
|
|
440
|
-
config: { policies: ["admin::
|
|
440
|
+
config: { policies: ["admin::isAuthenticatedAdmin"] }
|
|
441
441
|
},
|
|
442
442
|
{
|
|
443
443
|
method: "PUT",
|
|
444
444
|
path: "/settings",
|
|
445
445
|
handler: "settings.update",
|
|
446
|
-
config: { policies: ["admin::
|
|
446
|
+
config: { policies: ["admin::isAuthenticatedAdmin"] }
|
|
447
447
|
},
|
|
448
448
|
{
|
|
449
449
|
method: "DELETE",
|
|
450
450
|
path: "/settings",
|
|
451
451
|
handler: "settings.reset",
|
|
452
|
-
config: { policies: ["admin::
|
|
452
|
+
config: { policies: ["admin::isAuthenticatedAdmin"] }
|
|
453
453
|
}
|
|
454
454
|
]
|
|
455
455
|
};
|
|
456
|
-
const adminRoutes =
|
|
456
|
+
const adminRoutes = { notification, config, settings };
|
|
457
457
|
const index = {
|
|
458
458
|
register,
|
|
459
459
|
bootstrap,
|