@edifice.io/react 2.5.23-fix-query-params.20260623180310 → 2.5.24-develop.20260623184311
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/components/AppIcon/AppIcon.js +4 -1
- package/dist/components/Avatar/Avatar.d.ts +1 -1
- package/dist/components/Avatar/Avatar.js +2 -1
- package/dist/components/BetaSwitch/BetaSwitch.d.ts +13 -0
- package/dist/components/BetaSwitch/BetaSwitch.js +27 -0
- package/dist/components/BetaSwitch/index.d.ts +1 -0
- package/dist/components/ButtonBeta/ButtonBeta.d.ts +47 -0
- package/dist/components/ButtonBeta/ButtonBeta.js +34 -0
- package/dist/components/ButtonBeta/index.d.ts +2 -0
- package/dist/components/Flex/Flex.js +5 -1
- package/dist/components/Logo/index.d.ts +1 -1
- package/dist/components/LogoBeta/LogoBeta.d.ts +7 -0
- package/dist/components/LogoBeta/LogoBeta.js +14 -0
- package/dist/components/LogoBeta/index.d.ts +2 -0
- package/dist/components/PageLayout/PageLayout.d.ts +45 -0
- package/dist/components/PageLayout/PageLayout.js +94 -0
- package/dist/components/PageLayout/PageLayoutContext.d.ts +14 -0
- package/dist/components/PageLayout/PageLayoutContext.js +8 -0
- package/dist/components/PageLayout/components/PageLayoutBreadcrumb.d.ts +9 -0
- package/dist/components/PageLayout/components/PageLayoutBreadcrumb.js +10 -0
- package/dist/components/PageLayout/components/PageLayoutContent.d.ts +9 -0
- package/dist/components/PageLayout/components/PageLayoutContent.js +18 -0
- package/dist/components/PageLayout/components/PageLayoutHeader.d.ts +10 -0
- package/dist/components/PageLayout/components/PageLayoutHeader.js +18 -0
- package/dist/components/PageLayout/components/PageLayoutOverlay.d.ts +15 -0
- package/dist/components/PageLayout/components/PageLayoutOverlay.js +51 -0
- package/dist/components/PageLayout/components/PageLayoutSidebarLeft.d.ts +9 -0
- package/dist/components/PageLayout/components/PageLayoutSidebarLeft.js +18 -0
- package/dist/components/PageLayout/components/PageLayoutSidebarRight.d.ts +9 -0
- package/dist/components/PageLayout/components/PageLayoutSidebarRight.js +18 -0
- package/dist/components/PageLayout/hook/useOverlay.d.ts +5 -0
- package/dist/components/PageLayout/hook/useOverlay.js +15 -0
- package/dist/components/PageLayout/index.d.ts +4 -0
- package/dist/components/PageLayout/store/overlayStore.d.ts +15 -0
- package/dist/components/PageLayout/store/overlayStore.js +12 -0
- package/dist/components/index.d.ts +4 -0
- package/dist/homepage.js +34 -0
- package/dist/hooks/index.d.ts +1 -1
- package/dist/hooks/useEdificeIcons/useEdificeIcons.js +10 -9
- package/dist/icons-nav.js +38 -28
- package/dist/index.js +215 -202
- package/dist/modules/homepage/components/Favorites/Favorites.d.ts +6 -0
- package/dist/modules/homepage/components/Favorites/Favorites.js +28 -0
- package/dist/modules/homepage/components/Favorites/FavoritesContainer.d.ts +4 -0
- package/dist/modules/homepage/components/Favorites/FavoritesContainer.js +10 -0
- package/dist/modules/homepage/components/Favorites/index.d.ts +2 -0
- package/dist/modules/homepage/components/Header/Header.d.ts +9 -0
- package/dist/modules/homepage/components/Header/Header.js +80 -0
- package/dist/modules/homepage/components/Header/index.d.ts +2 -0
- package/dist/modules/homepage/components/HomeCard/HomeCard.d.ts +37 -0
- package/dist/modules/homepage/components/HomeCard/HomeCard.js +17 -0
- package/dist/modules/homepage/components/HomeCard/HomeCardContent.d.ts +7 -0
- package/dist/modules/homepage/components/HomeCard/HomeCardContent.js +10 -0
- package/dist/modules/homepage/components/HomeCard/HomeCardHeader.d.ts +18 -0
- package/dist/modules/homepage/components/HomeCard/HomeCardHeader.js +22 -0
- package/dist/modules/homepage/components/HomeCard/index.d.ts +4 -0
- package/dist/modules/homepage/components/LastInfos/LastInfos.d.ts +49 -0
- package/dist/modules/homepage/components/LastInfos/LastInfos.js +58 -0
- package/dist/modules/homepage/components/LastInfos/LastInfosContainer.d.ts +4 -0
- package/dist/modules/homepage/components/LastInfos/LastInfosContainer.js +37 -0
- package/dist/modules/homepage/components/LastInfos/LastInfosList.d.ts +13 -0
- package/dist/modules/homepage/components/LastInfos/LastInfosList.js +31 -0
- package/dist/modules/homepage/components/LastInfos/index.d.ts +4 -0
- package/dist/modules/homepage/components/LastInfos/useLastInfos.d.ts +18 -0
- package/dist/modules/homepage/components/LastInfos/useLastInfos.js +25 -0
- package/dist/modules/homepage/components/MessageFlashList/MessageFlash.d.ts +12 -0
- package/dist/modules/homepage/components/MessageFlashList/MessageFlash.js +65 -0
- package/dist/modules/homepage/components/MessageFlashList/MessageFlashList.d.ts +12 -0
- package/dist/modules/homepage/components/MessageFlashList/MessageFlashList.js +10 -0
- package/dist/modules/homepage/components/MessageFlashList/MessageFlashListContainer.d.ts +5 -0
- package/dist/modules/homepage/components/MessageFlashList/MessageFlashListContainer.js +14 -0
- package/dist/modules/homepage/components/MessageFlashList/hooks/useMessageFlashList.d.ts +16 -0
- package/dist/modules/homepage/components/MessageFlashList/hooks/useMessageFlashList.js +19 -0
- package/dist/modules/homepage/components/MessageFlashList/index.d.ts +4 -0
- package/dist/modules/homepage/components/MessageFlashList/services/api/index.d.ts +4 -0
- package/dist/modules/homepage/components/MessageFlashList/services/api/index.js +5 -0
- package/dist/modules/homepage/components/MessageFlashList/services/api/messagesFlashService.d.ts +20 -0
- package/dist/modules/homepage/components/MessageFlashList/services/api/messagesFlashService.js +21 -0
- package/dist/modules/homepage/components/MessageFlashList/services/queries/messagesFlash.d.ts +13 -0
- package/dist/modules/homepage/components/MessageFlashList/services/queries/messagesFlash.js +31 -0
- package/dist/modules/homepage/components/Notifications/Notification.d.ts +20 -0
- package/dist/modules/homepage/components/Notifications/Notification.js +16 -0
- package/dist/modules/homepage/components/Notifications/NotificationList.d.ts +18 -0
- package/dist/modules/homepage/components/Notifications/NotificationList.js +44 -0
- package/dist/modules/homepage/components/Notifications/NotificationListContainer.d.ts +9 -0
- package/dist/modules/homepage/components/Notifications/NotificationListContainer.js +20 -0
- package/dist/modules/homepage/components/Notifications/NotificationListSkeleton.d.ts +5 -0
- package/dist/modules/homepage/components/Notifications/NotificationListSkeleton.js +17 -0
- package/dist/modules/homepage/components/Notifications/NotificationSkeleton.d.ts +3 -0
- package/dist/modules/homepage/components/Notifications/NotificationSkeleton.js +19 -0
- package/dist/modules/homepage/components/Notifications/components/NotificationItem.d.ts +24 -0
- package/dist/modules/homepage/components/Notifications/components/NotificationItem.js +28 -0
- package/dist/modules/homepage/components/Notifications/components/NotificationResource.d.ts +15 -0
- package/dist/modules/homepage/components/Notifications/components/NotificationResource.js +19 -0
- package/dist/modules/homepage/components/Notifications/components/SystemNotification.d.ts +15 -0
- package/dist/modules/homepage/components/Notifications/components/SystemNotification.js +20 -0
- package/dist/modules/homepage/components/Notifications/components/UserNotification.d.ts +15 -0
- package/dist/modules/homepage/components/Notifications/components/UserNotification.js +25 -0
- package/dist/modules/homepage/components/Notifications/components/notificationAdapter.d.ts +27 -0
- package/dist/modules/homepage/components/Notifications/components/notificationAdapter.js +53 -0
- package/dist/modules/homepage/components/Notifications/hooks/useNotificationList.d.ts +20 -0
- package/dist/modules/homepage/components/Notifications/hooks/useNotificationList.js +26 -0
- package/dist/modules/homepage/components/Notifications/index.d.ts +6 -0
- package/dist/modules/homepage/components/Notifications/services/api/index.d.ts +4 -0
- package/dist/modules/homepage/components/Notifications/services/api/index.js +5 -0
- package/dist/modules/homepage/components/Notifications/services/api/notificationService.d.ts +15 -0
- package/dist/modules/homepage/components/Notifications/services/api/notificationService.js +22 -0
- package/dist/modules/homepage/components/Notifications/services/queries/notification.d.ts +20 -0
- package/dist/modules/homepage/components/Notifications/services/queries/notification.js +40 -0
- package/dist/modules/homepage/components/SchoolSpace/SchoolSpace.d.ts +15 -0
- package/dist/modules/homepage/components/SchoolSpace/SchoolSpace.js +29 -0
- package/dist/modules/homepage/components/SchoolSpace/SchoolSpaceContainer.d.ts +4 -0
- package/dist/modules/homepage/components/SchoolSpace/SchoolSpaceContainer.js +13 -0
- package/dist/modules/homepage/components/SchoolSpace/index.d.ts +3 -0
- package/dist/modules/homepage/components/SchoolSpace/useUserSchools.d.ts +6 -0
- package/dist/modules/homepage/components/SchoolSpace/useUserSchools.js +39 -0
- package/dist/modules/homepage/components/UserSpace/UserSpace.d.ts +13 -0
- package/dist/modules/homepage/components/UserSpace/UserSpace.js +28 -0
- package/dist/modules/homepage/components/UserSpace/UserSpaceContainer.d.ts +7 -0
- package/dist/modules/homepage/components/UserSpace/UserSpaceContainer.js +19 -0
- package/dist/modules/homepage/components/UserSpace/index.d.ts +3 -0
- package/dist/modules/homepage/components/index.d.ts +8 -0
- package/dist/modules/homepage/hooks/useWidget.d.ts +6 -0
- package/dist/modules/homepage/hooks/useWidget.js +83 -0
- package/dist/modules/homepage/hooks/useWidgetPreferences.d.ts +6 -0
- package/dist/modules/homepage/hooks/useWidgetPreferences.js +34 -0
- package/dist/modules/homepage/index.d.ts +1 -0
- package/dist/modules/icons/components/nav/IconCommunitiesBeta.d.ts +7 -0
- package/dist/modules/icons/components/nav/IconCommunitiesBeta.js +18 -0
- package/dist/modules/icons/components/nav/IconHomeBeta.d.ts +7 -0
- package/dist/modules/icons/components/nav/IconHomeBeta.js +13 -0
- package/dist/modules/icons/components/nav/IconMessagesBeta.d.ts +7 -0
- package/dist/modules/icons/components/nav/IconMessagesBeta.js +18 -0
- package/dist/modules/icons/components/nav/IconMyAppsBeta.d.ts +7 -0
- package/dist/modules/icons/components/nav/IconMyAppsBeta.js +13 -0
- package/dist/modules/icons/components/nav/IconNotificationBeta.d.ts +7 -0
- package/dist/modules/icons/components/nav/IconNotificationBeta.js +14 -0
- package/dist/modules/icons/components/nav/index.d.ts +5 -0
- package/dist/modules/modals/OnboardingModal/index.d.ts +1 -1
- package/dist/providers/EdificeClientProvider/EdificeClientProvider.d.ts +0 -7
- package/dist/utilities/create-selectors/createSelectors.d.ts +10 -0
- package/dist/utilities/create-selectors/createSelectors.js +11 -0
- package/package.json +13 -8
package/dist/modules/homepage/components/MessageFlashList/services/api/messagesFlashService.d.ts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { IFlashMessageModel } from '@edifice.io/client';
|
|
2
|
+
/**
|
|
3
|
+
* Creates a message flash service with methods to interact with flash messages.
|
|
4
|
+
*
|
|
5
|
+
* @param baseURL The base URL for the message flash service API.
|
|
6
|
+
* @returns A service exposing methods to retrieve flash messages and mark them as read.
|
|
7
|
+
*/
|
|
8
|
+
export declare const createMessagesFlashService: (baseURL: string) => {
|
|
9
|
+
/**
|
|
10
|
+
* Get message flash.
|
|
11
|
+
* @returns a message flash object
|
|
12
|
+
*/
|
|
13
|
+
getMessagesFlash(): Promise<IFlashMessageModel[]>;
|
|
14
|
+
/**
|
|
15
|
+
* Mark a flash message as read.
|
|
16
|
+
* @param message - The flash message to mark as read
|
|
17
|
+
* @returns A promise that resolves when the operation is complete
|
|
18
|
+
*/
|
|
19
|
+
markAsRead(message: IFlashMessageModel): Promise<void>;
|
|
20
|
+
};
|
package/dist/modules/homepage/components/MessageFlashList/services/api/messagesFlashService.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { odeServices } from "@edifice.io/client";
|
|
2
|
+
const createMessagesFlashService = (baseURL) => ({
|
|
3
|
+
/**
|
|
4
|
+
* Get message flash.
|
|
5
|
+
* @returns a message flash object
|
|
6
|
+
*/
|
|
7
|
+
getMessagesFlash() {
|
|
8
|
+
return odeServices.http().get(`${baseURL}/timeline/flashmsg/listuser`);
|
|
9
|
+
},
|
|
10
|
+
/**
|
|
11
|
+
* Mark a flash message as read.
|
|
12
|
+
* @param message - The flash message to mark as read
|
|
13
|
+
* @returns A promise that resolves when the operation is complete
|
|
14
|
+
*/
|
|
15
|
+
markAsRead(message) {
|
|
16
|
+
return odeServices.http().put(`${baseURL}/timeline/flashmsg/` + message.id + "/markasread");
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
export {
|
|
20
|
+
createMessagesFlashService
|
|
21
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { IFlashMessageModel } from '@edifice.io/client';
|
|
2
|
+
export declare const messagesFlashQueryKeys: {
|
|
3
|
+
all: () => readonly ["messagesFlash"];
|
|
4
|
+
};
|
|
5
|
+
export declare const messagesFlashQueryOptions: {
|
|
6
|
+
getMessagesFlash(): import('@tanstack/react-query').OmitKeyof<import('@tanstack/react-query').UseQueryOptions<IFlashMessageModel[], Error, IFlashMessageModel[], import('@tanstack/react-query').QueryKey>, "queryFn"> & {
|
|
7
|
+
queryFn?: import('@tanstack/react-query').QueryFunction<IFlashMessageModel[], import('@tanstack/react-query').QueryKey, never> | undefined;
|
|
8
|
+
} & {
|
|
9
|
+
queryKey: import('@tanstack/react-query').DataTag<import('@tanstack/react-query').QueryKey, IFlashMessageModel[]>;
|
|
10
|
+
};
|
|
11
|
+
};
|
|
12
|
+
export declare const useMessagesFlash: () => import('@tanstack/react-query').UseQueryResult<IFlashMessageModel[], Error>;
|
|
13
|
+
export declare const useMarkAsRead: () => import('@tanstack/react-query').UseMutationResult<void, Error, IFlashMessageModel, void>;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { useQuery, useQueryClient, useMutation, queryOptions } from "@tanstack/react-query";
|
|
2
|
+
import { messageFlashService } from "../api/index.js";
|
|
3
|
+
const messagesFlashQueryKeys = {
|
|
4
|
+
all: () => ["messagesFlash"]
|
|
5
|
+
}, messagesFlashQueryOptions = {
|
|
6
|
+
getMessagesFlash() {
|
|
7
|
+
return queryOptions({
|
|
8
|
+
queryKey: messagesFlashQueryKeys.all(),
|
|
9
|
+
queryFn: async () => messageFlashService.getMessagesFlash()
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
}, useMessagesFlash = () => useQuery(messagesFlashQueryOptions.getMessagesFlash()), useMarkAsRead = () => {
|
|
13
|
+
const queryClient = useQueryClient();
|
|
14
|
+
return useMutation({
|
|
15
|
+
mutationFn: (message) => messageFlashService.markAsRead(message),
|
|
16
|
+
onMutate: async (message) => {
|
|
17
|
+
queryClient.setQueryData(messagesFlashQueryKeys.all(), (oldMessages) => oldMessages.filter((msg) => msg.id !== message.id));
|
|
18
|
+
},
|
|
19
|
+
onError() {
|
|
20
|
+
queryClient.invalidateQueries({
|
|
21
|
+
queryKey: messagesFlashQueryKeys.all()
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
};
|
|
26
|
+
export {
|
|
27
|
+
messagesFlashQueryKeys,
|
|
28
|
+
messagesFlashQueryOptions,
|
|
29
|
+
useMarkAsRead,
|
|
30
|
+
useMessagesFlash
|
|
31
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { NotificationModel } from '@edifice.io/client';
|
|
2
|
+
export type { SystemWebNotification, UserWebNotification, WebNotification, } from './components/notificationAdapter';
|
|
3
|
+
export type NotificationProps = {
|
|
4
|
+
notification: NotificationModel;
|
|
5
|
+
};
|
|
6
|
+
/**
|
|
7
|
+
* Renders a single notification from a raw `NotificationModel`.
|
|
8
|
+
*
|
|
9
|
+
* Internally adapts the model into one of two display variants:
|
|
10
|
+
* - **user** — triggered by another user (e.g. shared a resource); shows their avatar.
|
|
11
|
+
* - **system** — triggered by an application event; shows the app icon.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* <Notification notification={notificationModel} />
|
|
15
|
+
*/
|
|
16
|
+
declare const Notification: {
|
|
17
|
+
({ notification }: NotificationProps): import("react/jsx-runtime").JSX.Element;
|
|
18
|
+
displayName: string;
|
|
19
|
+
};
|
|
20
|
+
export default Notification;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { jsxs, Fragment, jsx } from "react/jsx-runtime";
|
|
2
|
+
import SystemNotification from "./components/SystemNotification.js";
|
|
3
|
+
import UserNotification from "./components/UserNotification.js";
|
|
4
|
+
import { notificationAdapter } from "./components/notificationAdapter.js";
|
|
5
|
+
const Notification = ({
|
|
6
|
+
notification
|
|
7
|
+
}) => {
|
|
8
|
+
const notif = notificationAdapter(notification);
|
|
9
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
10
|
+
notif.type === "user" && /* @__PURE__ */ jsx(UserNotification, { notification: notif }),
|
|
11
|
+
notif.type === "system" && /* @__PURE__ */ jsx(SystemNotification, { notification: notif })
|
|
12
|
+
] });
|
|
13
|
+
};
|
|
14
|
+
export {
|
|
15
|
+
Notification as default
|
|
16
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { NotificationModel } from '@edifice.io/client';
|
|
2
|
+
export type NotificationListProps = {
|
|
3
|
+
/** List of notifications to display */
|
|
4
|
+
notifications?: NotificationModel[];
|
|
5
|
+
/** Callback when the notifications list is closed */
|
|
6
|
+
onCloseNotifications?: () => void;
|
|
7
|
+
/** Callback to load the next page of notifications, used for infinite scrolling */
|
|
8
|
+
onLoadNextPage?: () => void;
|
|
9
|
+
/** Indicates if there are more notifications to load, used for infinite scrolling */
|
|
10
|
+
hasNextPage?: boolean;
|
|
11
|
+
/** Loading state for fetching notifications, used to prevent multiple simultaneous fetches */
|
|
12
|
+
isLoading?: boolean;
|
|
13
|
+
};
|
|
14
|
+
declare const NotificationList: {
|
|
15
|
+
({ notifications, onCloseNotifications, onLoadNextPage, hasNextPage, isLoading, }: NotificationListProps): import("react/jsx-runtime").JSX.Element;
|
|
16
|
+
displayName: string;
|
|
17
|
+
};
|
|
18
|
+
export default NotificationList;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { jsx, jsxs, Fragment } from "react/jsx-runtime";
|
|
2
|
+
import illuEmptyNotification from "@edifice.io/bootstrap/dist/images/emptyscreen/illu-notifications.png";
|
|
3
|
+
import { useTranslation } from "react-i18next";
|
|
4
|
+
import SvgIconClose from "../../../icons/components/IconClose.js";
|
|
5
|
+
import Notification from "./Notification.js";
|
|
6
|
+
import NotificationListSkeleton from "./NotificationListSkeleton.js";
|
|
7
|
+
import NotificationSkeleton from "./NotificationSkeleton.js";
|
|
8
|
+
import useInfiniteScroll from "../../../../hooks/useInfiniteScroll/useInfiniteScroll.js";
|
|
9
|
+
import Flex from "../../../../components/Flex/Flex.js";
|
|
10
|
+
import ButtonBeta from "../../../../components/ButtonBeta/ButtonBeta.js";
|
|
11
|
+
import EmptyScreen from "../../../../components/EmptyScreen/EmptyScreen.js";
|
|
12
|
+
import Divider from "../../../../components/Divider/Divider.js";
|
|
13
|
+
const NotificationList = ({
|
|
14
|
+
notifications,
|
|
15
|
+
onCloseNotifications,
|
|
16
|
+
onLoadNextPage,
|
|
17
|
+
hasNextPage,
|
|
18
|
+
isLoading
|
|
19
|
+
}) => {
|
|
20
|
+
const {
|
|
21
|
+
t
|
|
22
|
+
} = useTranslation(), loadNextRef = useInfiniteScroll({
|
|
23
|
+
callback: () => onLoadNextPage == null ? void 0 : onLoadNextPage()
|
|
24
|
+
}), handleCloseClick = () => {
|
|
25
|
+
onCloseNotifications && onCloseNotifications();
|
|
26
|
+
};
|
|
27
|
+
return /* @__PURE__ */ jsx("section", { role: "region", className: "notification-list", children: /* @__PURE__ */ jsxs(Flex, { direction: "column", children: [
|
|
28
|
+
/* @__PURE__ */ jsxs(Flex, { justify: "between", align: "center", wrap: "nowrap", className: "py-16 ps-24 pe-8", children: [
|
|
29
|
+
/* @__PURE__ */ jsx("h4", { className: "text-truncate", children: t("homepage.notifications-list.title") }),
|
|
30
|
+
onCloseNotifications && /* @__PURE__ */ jsx(ButtonBeta, { color: "tertiary", variant: "ghost", rightIcon: /* @__PURE__ */ jsx(SvgIconClose, {}), onClick: handleCloseClick, "aria-label": t("homepage.notifications-list.close"), title: t("homepage.notifications-list.close"), "data-testid": "notification-list-close-button" })
|
|
31
|
+
] }),
|
|
32
|
+
(notifications == null ? void 0 : notifications.length) === 0 ? /* @__PURE__ */ jsx("div", { className: "mx-24", children: /* @__PURE__ */ jsx(EmptyScreen, { size: 120, imageSrc: illuEmptyNotification, imageAlt: t("homepage.notifications-list.empty.description"), text: t("homepage.notifications-list.empty.description") }) }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
33
|
+
/* @__PURE__ */ jsx("ul", { children: notifications == null ? void 0 : notifications.map((notification, index) => /* @__PURE__ */ jsxs("li", { children: [
|
|
34
|
+
/* @__PURE__ */ jsx(Notification, { notification }),
|
|
35
|
+
/* @__PURE__ */ jsx(Divider, { className: "border-grey-300 my-0" })
|
|
36
|
+
] }, "notification-list-" + notification._id + "-" + index)) }),
|
|
37
|
+
hasNextPage && /* @__PURE__ */ jsx(NotificationSkeleton, { ref: loadNextRef }),
|
|
38
|
+
isLoading && /* @__PURE__ */ jsx(NotificationListSkeleton, {})
|
|
39
|
+
] })
|
|
40
|
+
] }) });
|
|
41
|
+
};
|
|
42
|
+
export {
|
|
43
|
+
NotificationList as default
|
|
44
|
+
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export type NotificationListContainerProps = {
|
|
2
|
+
/** Callback when the notifications list is closed */
|
|
3
|
+
onCloseNotifications?: () => void;
|
|
4
|
+
};
|
|
5
|
+
export declare const NotificationListContainer: {
|
|
6
|
+
({ onCloseNotifications, }: NotificationListContainerProps): import("react/jsx-runtime").JSX.Element;
|
|
7
|
+
displayName: string;
|
|
8
|
+
};
|
|
9
|
+
export default NotificationListContainer;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
import NotificationList from "./NotificationList.js";
|
|
3
|
+
import { useNotificationListContainer } from "./hooks/useNotificationList.js";
|
|
4
|
+
const NotificationListContainer = ({
|
|
5
|
+
onCloseNotifications
|
|
6
|
+
}) => {
|
|
7
|
+
const {
|
|
8
|
+
notifications,
|
|
9
|
+
hasNextPage,
|
|
10
|
+
loadNextPage,
|
|
11
|
+
isLoading
|
|
12
|
+
} = useNotificationListContainer();
|
|
13
|
+
return /* @__PURE__ */ jsx(NotificationList, { notifications, onCloseNotifications, onLoadNextPage: () => {
|
|
14
|
+
hasNextPage && !isLoading && loadNextPage();
|
|
15
|
+
}, hasNextPage, isLoading });
|
|
16
|
+
};
|
|
17
|
+
export {
|
|
18
|
+
NotificationListContainer,
|
|
19
|
+
NotificationListContainer as default
|
|
20
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { jsxs, jsx } from "react/jsx-runtime";
|
|
2
|
+
import NotificationSkeleton from "./NotificationSkeleton.js";
|
|
3
|
+
import Divider from "../../../../components/Divider/Divider.js";
|
|
4
|
+
const NotificationListSkeleton = () => /* @__PURE__ */ jsxs("ul", { children: [
|
|
5
|
+
/* @__PURE__ */ jsxs("li", { children: [
|
|
6
|
+
/* @__PURE__ */ jsx(NotificationSkeleton, {}),
|
|
7
|
+
/* @__PURE__ */ jsx(Divider, { className: "border-grey-300 my-0" })
|
|
8
|
+
] }),
|
|
9
|
+
/* @__PURE__ */ jsxs("li", { children: [
|
|
10
|
+
/* @__PURE__ */ jsx(NotificationSkeleton, {}),
|
|
11
|
+
/* @__PURE__ */ jsx(Divider, { className: "border-grey-300 my-0" })
|
|
12
|
+
] }),
|
|
13
|
+
/* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx(NotificationSkeleton, {}) })
|
|
14
|
+
] });
|
|
15
|
+
export {
|
|
16
|
+
NotificationListSkeleton as default
|
|
17
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import React from "react";
|
|
3
|
+
import Flex from "../../../../components/Flex/Flex.js";
|
|
4
|
+
import Avatar from "../../../../components/Avatar/Avatar.js";
|
|
5
|
+
import TextSkeleton from "../../../../components/Skeleton/TextSkeleton.js";
|
|
6
|
+
const NotificationSkeleton = /* @__PURE__ */ React.forwardRef((_props, ref) => /* @__PURE__ */ jsx(Flex, { direction: "column", className: "notification", gap: "8", ref, children: /* @__PURE__ */ jsxs(Flex, { direction: "row", gap: "8", children: [
|
|
7
|
+
/* @__PURE__ */ jsx("div", { className: "notification-picture", children: /* @__PURE__ */ jsx(Avatar, { alt: "Notification Picture", variant: "circle", className: "notification-avatar" }) }),
|
|
8
|
+
/* @__PURE__ */ jsxs(Flex, { direction: "column", gap: "8", className: "notification-message", children: [
|
|
9
|
+
/* @__PURE__ */ jsx(TextSkeleton, {}),
|
|
10
|
+
/* @__PURE__ */ jsx(TextSkeleton, {}),
|
|
11
|
+
/* @__PURE__ */ jsx("div", { className: "placeholder col-4", style: {
|
|
12
|
+
height: "2rem"
|
|
13
|
+
} }),
|
|
14
|
+
/* @__PURE__ */ jsx(TextSkeleton, { className: "col-2" })
|
|
15
|
+
] })
|
|
16
|
+
] }) }));
|
|
17
|
+
export {
|
|
18
|
+
NotificationSkeleton as default
|
|
19
|
+
};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
export type NotificationItemProps = {
|
|
3
|
+
picture: ReactNode;
|
|
4
|
+
message: string;
|
|
5
|
+
date: Date;
|
|
6
|
+
uri?: string;
|
|
7
|
+
children?: ReactNode;
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* Base layout for a single notification row.
|
|
11
|
+
*
|
|
12
|
+
* Renders a picture slot (avatar or app icon), a clickable message linking to
|
|
13
|
+
* `uri`, a relative timestamp (e.g. "2 hours ago"), and an optional `children`
|
|
14
|
+
* area for extra content below the message.
|
|
15
|
+
*
|
|
16
|
+
* This is a presentational component — it does not know whether the
|
|
17
|
+
* notification comes from a user or a system event. Use `UserNotification` or
|
|
18
|
+
* `SystemNotification` instead of consuming this directly.
|
|
19
|
+
*/
|
|
20
|
+
declare const NotificationItem: {
|
|
21
|
+
({ picture, message, date, uri, children, }: NotificationItemProps): import("react/jsx-runtime").JSX.Element;
|
|
22
|
+
displayName: string;
|
|
23
|
+
};
|
|
24
|
+
export default NotificationItem;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import useDate from "../../../../../hooks/useDate/useDate.js";
|
|
3
|
+
import Flex from "../../../../../components/Flex/Flex.js";
|
|
4
|
+
const NotificationItem = ({
|
|
5
|
+
picture,
|
|
6
|
+
message,
|
|
7
|
+
date,
|
|
8
|
+
uri,
|
|
9
|
+
children
|
|
10
|
+
}) => {
|
|
11
|
+
const {
|
|
12
|
+
formatTimeAgo,
|
|
13
|
+
formatDate
|
|
14
|
+
} = useDate();
|
|
15
|
+
return /* @__PURE__ */ jsx(Flex, { direction: "column", className: "notification", gap: "8", children: /* @__PURE__ */ jsxs(Flex, { direction: "row", gap: "8", children: [
|
|
16
|
+
/* @__PURE__ */ jsx("div", { className: "notification-picture", children: picture }),
|
|
17
|
+
/* @__PURE__ */ jsx("a", { href: uri, "data-testid": "notification-content", children: /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: "8", children: [
|
|
18
|
+
/* @__PURE__ */ jsx("div", { className: "notification-message", dangerouslySetInnerHTML: {
|
|
19
|
+
__html: message
|
|
20
|
+
} }),
|
|
21
|
+
children,
|
|
22
|
+
/* @__PURE__ */ jsx("p", { className: "notification-date", title: formatDate(date, "LLL"), children: formatTimeAgo(date) })
|
|
23
|
+
] }) })
|
|
24
|
+
] }) });
|
|
25
|
+
};
|
|
26
|
+
export {
|
|
27
|
+
NotificationItem as default
|
|
28
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export type NotificationResourceProps = {
|
|
2
|
+
appCode: string;
|
|
3
|
+
};
|
|
4
|
+
/**
|
|
5
|
+
* Displays the originating application of a notification as a small icon + label.
|
|
6
|
+
*
|
|
7
|
+
* Resolves the human-readable app name via i18n key `<appCode>` present in entcore/portal/backend/src/main/resources/i18n/fr.json,
|
|
8
|
+
* falling back to the raw `appCode` if no translation exists.
|
|
9
|
+
*
|
|
10
|
+
*/
|
|
11
|
+
declare const NotificationResource: {
|
|
12
|
+
({ appCode }: NotificationResourceProps): import("react/jsx-runtime").JSX.Element;
|
|
13
|
+
displayName: string;
|
|
14
|
+
};
|
|
15
|
+
export default NotificationResource;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { jsxs, jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useTranslation } from "react-i18next";
|
|
3
|
+
import AppIcon from "../../../../../components/AppIcon/AppIcon.js";
|
|
4
|
+
const NotificationResource = ({
|
|
5
|
+
appCode
|
|
6
|
+
}) => {
|
|
7
|
+
const {
|
|
8
|
+
t
|
|
9
|
+
} = useTranslation(), appLabel = t(`${appCode}`, {
|
|
10
|
+
defaultValue: appCode
|
|
11
|
+
}), appCssClass = `app-${appCode}`;
|
|
12
|
+
return /* @__PURE__ */ jsxs("div", { className: `notification-resource ${appCssClass} bg-app-light`, children: [
|
|
13
|
+
/* @__PURE__ */ jsx("span", { className: "notification-resource-icon", children: /* @__PURE__ */ jsx(AppIcon, { app: appCode, size: "24", iconFit: "contain" }) }),
|
|
14
|
+
/* @__PURE__ */ jsx("span", { className: "notification-resource-name color-app", children: appLabel })
|
|
15
|
+
] });
|
|
16
|
+
};
|
|
17
|
+
export {
|
|
18
|
+
NotificationResource as default
|
|
19
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { SystemWebNotification } from './notificationAdapter';
|
|
2
|
+
export type SystemNotificationProps = {
|
|
3
|
+
notification: SystemWebNotification;
|
|
4
|
+
};
|
|
5
|
+
/**
|
|
6
|
+
* Renders a system notification (no sender) using an app icon as the picture.
|
|
7
|
+
*
|
|
8
|
+
* Wraps `NotificationItem` — prefer using `Notification` at the top level
|
|
9
|
+
* rather than this component directly.
|
|
10
|
+
*/
|
|
11
|
+
declare const SystemNotification: {
|
|
12
|
+
({ notification }: SystemNotificationProps): import("react/jsx-runtime").JSX.Element;
|
|
13
|
+
displayName: string;
|
|
14
|
+
};
|
|
15
|
+
export default SystemNotification;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useTranslation } from "react-i18next";
|
|
3
|
+
import NotificationItem from "./NotificationItem.js";
|
|
4
|
+
import AppIcon from "../../../../../components/AppIcon/AppIcon.js";
|
|
5
|
+
const SystemNotification = ({
|
|
6
|
+
notification
|
|
7
|
+
}) => {
|
|
8
|
+
const {
|
|
9
|
+
params,
|
|
10
|
+
message,
|
|
11
|
+
date,
|
|
12
|
+
uri
|
|
13
|
+
} = notification, {
|
|
14
|
+
t
|
|
15
|
+
} = useTranslation(), appName = t(params.appCode);
|
|
16
|
+
return /* @__PURE__ */ jsx(NotificationItem, { uri, message, date, picture: /* @__PURE__ */ jsx("a", { href: uri, title: appName, "data-testid": "notification-app-icon", "aria-label": t("homepage.notifications.app-icon.placeholder"), children: /* @__PURE__ */ jsx(AppIcon, { app: params.appCode, size: "24", variant: "square", className: "notification-app-icon" }) }) });
|
|
17
|
+
};
|
|
18
|
+
export {
|
|
19
|
+
SystemNotification as default
|
|
20
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { UserWebNotification } from './notificationAdapter';
|
|
2
|
+
export type UserNotificationProps = {
|
|
3
|
+
notification: UserWebNotification;
|
|
4
|
+
};
|
|
5
|
+
/**
|
|
6
|
+
* Renders a user-triggered notification using the sender's avatar as the picture.
|
|
7
|
+
*
|
|
8
|
+
* The avatar and its link are resolved via `useDirectory`. Wraps `NotificationItem`
|
|
9
|
+
* — prefer using `Notification` at the top level rather than this component directly.
|
|
10
|
+
*/
|
|
11
|
+
declare const UserNotification: {
|
|
12
|
+
({ notification }: UserNotificationProps): import("react/jsx-runtime").JSX.Element;
|
|
13
|
+
displayName: string;
|
|
14
|
+
};
|
|
15
|
+
export default UserNotification;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useTranslation } from "react-i18next";
|
|
3
|
+
import NotificationItem from "./NotificationItem.js";
|
|
4
|
+
import NotificationResource from "./NotificationResource.js";
|
|
5
|
+
import useDirectory from "../../../../../hooks/useDirectory/useDirectory.js";
|
|
6
|
+
import Avatar from "../../../../../components/Avatar/Avatar.js";
|
|
7
|
+
const UserNotification = ({
|
|
8
|
+
notification
|
|
9
|
+
}) => {
|
|
10
|
+
const {
|
|
11
|
+
getAvatarURL,
|
|
12
|
+
getUserbookURL
|
|
13
|
+
} = useDirectory(), {
|
|
14
|
+
params,
|
|
15
|
+
message,
|
|
16
|
+
date,
|
|
17
|
+
uri
|
|
18
|
+
} = notification, {
|
|
19
|
+
t
|
|
20
|
+
} = useTranslation(), userName = t(params.username);
|
|
21
|
+
return /* @__PURE__ */ jsx(NotificationItem, { uri, message, date, picture: /* @__PURE__ */ jsx("a", { href: getUserbookURL(params.userId, "user"), title: userName, "data-testid": "notification-avatar", children: /* @__PURE__ */ jsx(Avatar, { "aria-label": t("homepage.notifications.avatar.placeholder"), src: getAvatarURL(params.userId, "user"), alt: userName, variant: "circle", className: "notification-avatar" }) }), children: /* @__PURE__ */ jsx(NotificationResource, { appCode: params.appCode }) });
|
|
22
|
+
};
|
|
23
|
+
export {
|
|
24
|
+
UserNotification as default
|
|
25
|
+
};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { NotificationModel } from '@edifice.io/client';
|
|
2
|
+
type WebNotificationBase = {
|
|
3
|
+
id: string;
|
|
4
|
+
uri?: string;
|
|
5
|
+
message: string;
|
|
6
|
+
date: Date;
|
|
7
|
+
};
|
|
8
|
+
/** Notification triggered by another user (e.g. shared a resource). */
|
|
9
|
+
export type UserWebNotification = WebNotificationBase & {
|
|
10
|
+
type: 'user';
|
|
11
|
+
params: {
|
|
12
|
+
appCode: string;
|
|
13
|
+
username: string;
|
|
14
|
+
userId: string;
|
|
15
|
+
};
|
|
16
|
+
};
|
|
17
|
+
/** Notification triggered by an application event (no sender). */
|
|
18
|
+
export type SystemWebNotification = WebNotificationBase & {
|
|
19
|
+
type: 'system';
|
|
20
|
+
params: {
|
|
21
|
+
appCode: string;
|
|
22
|
+
};
|
|
23
|
+
};
|
|
24
|
+
/** Discriminated union — narrow on `type` to get the specific variant. */
|
|
25
|
+
export type WebNotification = UserWebNotification | SystemWebNotification;
|
|
26
|
+
export declare const notificationAdapter: (notification: NotificationModel) => WebNotification;
|
|
27
|
+
export {};
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
const resolveNotificationResourceUri = (params, type) => {
|
|
2
|
+
if (type === "user")
|
|
3
|
+
return params.resourceUri || params.uri;
|
|
4
|
+
for (const [key, value] of Object.entries(params))
|
|
5
|
+
if (typeof value == "string" && value.length > 0 && key.endsWith("Uri") && key !== "profilUri" && key !== "resourceFolderUri")
|
|
6
|
+
return value;
|
|
7
|
+
}, parseNotificationMessage = (message) => message.replace(/<\/a>/gi, "</strong>").replace(/<a\b[^>]*>/gi, "<strong>"), getAppCode = (appCode) => {
|
|
8
|
+
switch (appCode = appCode.toLowerCase(), appCode) {
|
|
9
|
+
case "collaborativewall":
|
|
10
|
+
return "collaborative-wall";
|
|
11
|
+
case "formulaire":
|
|
12
|
+
return "forms";
|
|
13
|
+
case "messagerie":
|
|
14
|
+
return "conversation";
|
|
15
|
+
case "news":
|
|
16
|
+
return "actualites";
|
|
17
|
+
case "homeworks":
|
|
18
|
+
return "cahier-de-texte";
|
|
19
|
+
case "userbook_motto":
|
|
20
|
+
case "userbook_mood":
|
|
21
|
+
case "userbook_discovervisiblegroups":
|
|
22
|
+
return "userbook";
|
|
23
|
+
default:
|
|
24
|
+
return appCode.replace(/_/g, "-");
|
|
25
|
+
}
|
|
26
|
+
}, notificationAdapter = (notification) => {
|
|
27
|
+
const type = notification.sender ? "user" : "system", uri = resolveNotificationResourceUri(notification.params, type), date = new Date(notification.date.$date), appCode = getAppCode(notification.type), message = parseNotificationMessage(notification.message), base = {
|
|
28
|
+
id: notification._id,
|
|
29
|
+
uri,
|
|
30
|
+
message,
|
|
31
|
+
date
|
|
32
|
+
};
|
|
33
|
+
return type === "user" ? {
|
|
34
|
+
...base,
|
|
35
|
+
type: "user",
|
|
36
|
+
params: {
|
|
37
|
+
username: notification.params.username,
|
|
38
|
+
// cannot be undefined if sender is present (user type)
|
|
39
|
+
userId: notification.sender,
|
|
40
|
+
// cannot be undefined if sender is present (user type)
|
|
41
|
+
appCode
|
|
42
|
+
}
|
|
43
|
+
} : {
|
|
44
|
+
...base,
|
|
45
|
+
type: "system",
|
|
46
|
+
params: {
|
|
47
|
+
appCode
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
};
|
|
51
|
+
export {
|
|
52
|
+
notificationAdapter
|
|
53
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { NotificationModel } from '@edifice.io/client';
|
|
2
|
+
export interface UseNotificationListContainerReturn {
|
|
3
|
+
/** Array of notifications */
|
|
4
|
+
notifications: NotificationModel[] | undefined;
|
|
5
|
+
/** Array of notification types */
|
|
6
|
+
notificationTypes: string[] | undefined;
|
|
7
|
+
/** Indicates if there are more notifications to load */
|
|
8
|
+
hasNextPage: boolean | undefined;
|
|
9
|
+
/** Callback to load the next page of notifications */
|
|
10
|
+
loadNextPage: () => void;
|
|
11
|
+
/** Loading state for fetching notifications */
|
|
12
|
+
isLoading: boolean;
|
|
13
|
+
/** Error state from fetching notifications */
|
|
14
|
+
error: Error | null;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Custom hook that provides notifications data and handlers with exposed loading states
|
|
18
|
+
* @returns Object containing notifications, loading state, and error state
|
|
19
|
+
*/
|
|
20
|
+
export declare const useNotificationListContainer: () => UseNotificationListContainerReturn;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { useNotificationTypes, useNotifications } from "../services/queries/notification.js";
|
|
2
|
+
const useNotificationListContainer = () => {
|
|
3
|
+
const {
|
|
4
|
+
data: notificationTypes,
|
|
5
|
+
isLoading: isLoadingTypes,
|
|
6
|
+
isFetched: isFetchedTypes,
|
|
7
|
+
error: errorTypes
|
|
8
|
+
} = useNotificationTypes(), {
|
|
9
|
+
data: notifications,
|
|
10
|
+
hasNextPage,
|
|
11
|
+
isLoading: isLoadingNotifications,
|
|
12
|
+
error: errorNotifications,
|
|
13
|
+
fetchNextPage
|
|
14
|
+
} = useNotifications(notificationTypes ?? [], isFetchedTypes && !!notificationTypes);
|
|
15
|
+
return {
|
|
16
|
+
notifications,
|
|
17
|
+
notificationTypes,
|
|
18
|
+
hasNextPage,
|
|
19
|
+
loadNextPage: () => fetchNextPage(),
|
|
20
|
+
isLoading: isLoadingTypes || isLoadingNotifications,
|
|
21
|
+
error: errorTypes || errorNotifications
|
|
22
|
+
};
|
|
23
|
+
};
|
|
24
|
+
export {
|
|
25
|
+
useNotificationListContainer
|
|
26
|
+
};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export * from './Notification';
|
|
2
|
+
export { default as Notification } from './Notification';
|
|
3
|
+
export * from './NotificationList';
|
|
4
|
+
export { default as NotificationList } from './NotificationList';
|
|
5
|
+
export * from './NotificationListContainer';
|
|
6
|
+
export { default as NotificationListContainer } from './NotificationListContainer';
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { NotificationModel } from '@edifice.io/client';
|
|
2
|
+
/**
|
|
3
|
+
* Creates a notification service with methods to interact with notifications.
|
|
4
|
+
*
|
|
5
|
+
* @param baseURL The base URL for the notification service API.
|
|
6
|
+
* @returns A service exposing methods to retrieve notifications.
|
|
7
|
+
*/
|
|
8
|
+
export declare const createNotificationService: (baseURL: string) => {
|
|
9
|
+
/**
|
|
10
|
+
* Get notifications.
|
|
11
|
+
* @returns list of notification objects
|
|
12
|
+
*/
|
|
13
|
+
getNotifications(types: string[], page: number): Promise<NotificationModel[]>;
|
|
14
|
+
getNotificationTypes(): Promise<string[]>;
|
|
15
|
+
};
|