@edifice.io/react 2.5.23 → 2.5.24-develop-b2school.20260626115410
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/NotificationItem.d.ts +20 -0
- package/dist/modules/homepage/components/Notifications/NotificationItem.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/CommonNotificationItem.d.ts +24 -0
- package/dist/modules/homepage/components/Notifications/components/CommonNotificationItem.js +28 -0
- package/dist/modules/homepage/components/Notifications/components/NotificationItemResource.d.ts +15 -0
- package/dist/modules/homepage/components/Notifications/components/NotificationItemResource.js +19 -0
- package/dist/modules/homepage/components/Notifications/components/SystemNotificationItem.d.ts +15 -0
- package/dist/modules/homepage/components/Notifications/components/SystemNotificationItem.js +20 -0
- package/dist/modules/homepage/components/Notifications/components/UserNotificationItem.d.ts +15 -0
- package/dist/modules/homepage/components/Notifications/components/UserNotificationItem.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
|
+
* <NotificationItem notification={notificationModel} />
|
|
15
|
+
*/
|
|
16
|
+
declare const NotificationItem: {
|
|
17
|
+
({ notification }: NotificationProps): import("react/jsx-runtime").JSX.Element;
|
|
18
|
+
displayName: string;
|
|
19
|
+
};
|
|
20
|
+
export default NotificationItem;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { jsxs, Fragment, jsx } from "react/jsx-runtime";
|
|
2
|
+
import SystemNotificationItem from "./components/SystemNotificationItem.js";
|
|
3
|
+
import UserNotificationItem from "./components/UserNotificationItem.js";
|
|
4
|
+
import { notificationAdapter } from "./components/notificationAdapter.js";
|
|
5
|
+
const NotificationItem = ({
|
|
6
|
+
notification
|
|
7
|
+
}) => {
|
|
8
|
+
const notif = notificationAdapter(notification);
|
|
9
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
10
|
+
notif.type === "user" && /* @__PURE__ */ jsx(UserNotificationItem, { notification: notif }),
|
|
11
|
+
notif.type === "system" && /* @__PURE__ */ jsx(SystemNotificationItem, { notification: notif })
|
|
12
|
+
] });
|
|
13
|
+
};
|
|
14
|
+
export {
|
|
15
|
+
NotificationItem 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 NotificationItem from "./NotificationItem.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(NotificationItem, { 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-item-picture", children: /* @__PURE__ */ jsx(Avatar, { alt: "Notification Picture", variant: "circle", className: "notification-item-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 CommonNotificationItem: {
|
|
21
|
+
({ picture, message, date, uri, children, }: NotificationItemProps): import("react/jsx-runtime").JSX.Element;
|
|
22
|
+
displayName: string;
|
|
23
|
+
};
|
|
24
|
+
export default CommonNotificationItem;
|
|
@@ -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 CommonNotificationItem = ({
|
|
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-item", gap: "8", children: /* @__PURE__ */ jsxs(Flex, { direction: "row", gap: "8", children: [
|
|
16
|
+
/* @__PURE__ */ jsx("div", { className: "notification-item-picture", children: picture }),
|
|
17
|
+
/* @__PURE__ */ jsx("a", { href: uri, "data-testid": "notification-item-content", children: /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: "8", children: [
|
|
18
|
+
/* @__PURE__ */ jsx("div", { className: "notification-item-message", dangerouslySetInnerHTML: {
|
|
19
|
+
__html: message
|
|
20
|
+
} }),
|
|
21
|
+
children,
|
|
22
|
+
/* @__PURE__ */ jsx("p", { className: "notification-item-date", title: formatDate(date, "LLL"), children: formatTimeAgo(date) })
|
|
23
|
+
] }) })
|
|
24
|
+
] }) });
|
|
25
|
+
};
|
|
26
|
+
export {
|
|
27
|
+
CommonNotificationItem as default
|
|
28
|
+
};
|
package/dist/modules/homepage/components/Notifications/components/NotificationItemResource.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export type NotificationItemResourceProps = {
|
|
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 NotificationItemResource: {
|
|
12
|
+
({ appCode, }: NotificationItemResourceProps): import("react/jsx-runtime").JSX.Element;
|
|
13
|
+
displayName: string;
|
|
14
|
+
};
|
|
15
|
+
export default NotificationItemResource;
|
|
@@ -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 NotificationItemResource = ({
|
|
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-item-resource ${appCssClass} bg-app-light`, children: [
|
|
13
|
+
/* @__PURE__ */ jsx("span", { className: "notification-item-resource-icon", children: /* @__PURE__ */ jsx(AppIcon, { app: appCode, size: "24", iconFit: "contain" }) }),
|
|
14
|
+
/* @__PURE__ */ jsx("span", { className: "notification-item-resource-name color-app", children: appLabel })
|
|
15
|
+
] });
|
|
16
|
+
};
|
|
17
|
+
export {
|
|
18
|
+
NotificationItemResource as default
|
|
19
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { SystemWebNotification } from './notificationAdapter';
|
|
2
|
+
export type SystemNotificationItemProps = {
|
|
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 SystemNotificationItem: {
|
|
12
|
+
({ notification, }: SystemNotificationItemProps): import("react/jsx-runtime").JSX.Element;
|
|
13
|
+
displayName: string;
|
|
14
|
+
};
|
|
15
|
+
export default SystemNotificationItem;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useTranslation } from "react-i18next";
|
|
3
|
+
import CommonNotificationItem from "./CommonNotificationItem.js";
|
|
4
|
+
import AppIcon from "../../../../../components/AppIcon/AppIcon.js";
|
|
5
|
+
const SystemNotificationItem = ({
|
|
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(CommonNotificationItem, { uri, message, date, picture: /* @__PURE__ */ jsx("a", { href: uri, title: appName, "data-testid": "notification-item-app-icon", "aria-label": t("homepage.notifications.app-icon.placeholder"), children: /* @__PURE__ */ jsx(AppIcon, { app: params.appCode, size: "24", variant: "square", className: "notification-item-app-icon" }) }) });
|
|
17
|
+
};
|
|
18
|
+
export {
|
|
19
|
+
SystemNotificationItem as default
|
|
20
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { UserWebNotification } from './notificationAdapter';
|
|
2
|
+
export type UserNotificationItemProps = {
|
|
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 UserNotificationItem: {
|
|
12
|
+
({ notification }: UserNotificationItemProps): import("react/jsx-runtime").JSX.Element;
|
|
13
|
+
displayName: string;
|
|
14
|
+
};
|
|
15
|
+
export default UserNotificationItem;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useTranslation } from "react-i18next";
|
|
3
|
+
import CommonNotificationItem from "./CommonNotificationItem.js";
|
|
4
|
+
import NotificationItemResource from "./NotificationItemResource.js";
|
|
5
|
+
import useDirectory from "../../../../../hooks/useDirectory/useDirectory.js";
|
|
6
|
+
import Avatar from "../../../../../components/Avatar/Avatar.js";
|
|
7
|
+
const UserNotificationItem = ({
|
|
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(CommonNotificationItem, { uri, message, date, picture: /* @__PURE__ */ jsx("a", { href: getUserbookURL(params.userId, "user"), title: userName, "data-testid": "notification-item-avatar", children: /* @__PURE__ */ jsx(Avatar, { "aria-label": t("homepage.notifications.avatar.placeholder"), src: getAvatarURL(params.userId, "user"), alt: userName, variant: "circle", className: "notification-item-avatar" }) }), children: /* @__PURE__ */ jsx(NotificationItemResource, { appCode: params.appCode }) });
|
|
22
|
+
};
|
|
23
|
+
export {
|
|
24
|
+
UserNotificationItem 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 './NotificationItem';
|
|
2
|
+
export { default as NotificationItem } from './NotificationItem';
|
|
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
|
+
};
|