@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.
Files changed (143) hide show
  1. package/dist/components/AppIcon/AppIcon.js +4 -1
  2. package/dist/components/Avatar/Avatar.d.ts +1 -1
  3. package/dist/components/Avatar/Avatar.js +2 -1
  4. package/dist/components/BetaSwitch/BetaSwitch.d.ts +13 -0
  5. package/dist/components/BetaSwitch/BetaSwitch.js +27 -0
  6. package/dist/components/BetaSwitch/index.d.ts +1 -0
  7. package/dist/components/ButtonBeta/ButtonBeta.d.ts +47 -0
  8. package/dist/components/ButtonBeta/ButtonBeta.js +34 -0
  9. package/dist/components/ButtonBeta/index.d.ts +2 -0
  10. package/dist/components/Flex/Flex.js +5 -1
  11. package/dist/components/Logo/index.d.ts +1 -1
  12. package/dist/components/LogoBeta/LogoBeta.d.ts +7 -0
  13. package/dist/components/LogoBeta/LogoBeta.js +14 -0
  14. package/dist/components/LogoBeta/index.d.ts +2 -0
  15. package/dist/components/PageLayout/PageLayout.d.ts +45 -0
  16. package/dist/components/PageLayout/PageLayout.js +94 -0
  17. package/dist/components/PageLayout/PageLayoutContext.d.ts +14 -0
  18. package/dist/components/PageLayout/PageLayoutContext.js +8 -0
  19. package/dist/components/PageLayout/components/PageLayoutBreadcrumb.d.ts +9 -0
  20. package/dist/components/PageLayout/components/PageLayoutBreadcrumb.js +10 -0
  21. package/dist/components/PageLayout/components/PageLayoutContent.d.ts +9 -0
  22. package/dist/components/PageLayout/components/PageLayoutContent.js +18 -0
  23. package/dist/components/PageLayout/components/PageLayoutHeader.d.ts +10 -0
  24. package/dist/components/PageLayout/components/PageLayoutHeader.js +18 -0
  25. package/dist/components/PageLayout/components/PageLayoutOverlay.d.ts +15 -0
  26. package/dist/components/PageLayout/components/PageLayoutOverlay.js +51 -0
  27. package/dist/components/PageLayout/components/PageLayoutSidebarLeft.d.ts +9 -0
  28. package/dist/components/PageLayout/components/PageLayoutSidebarLeft.js +18 -0
  29. package/dist/components/PageLayout/components/PageLayoutSidebarRight.d.ts +9 -0
  30. package/dist/components/PageLayout/components/PageLayoutSidebarRight.js +18 -0
  31. package/dist/components/PageLayout/hook/useOverlay.d.ts +5 -0
  32. package/dist/components/PageLayout/hook/useOverlay.js +15 -0
  33. package/dist/components/PageLayout/index.d.ts +4 -0
  34. package/dist/components/PageLayout/store/overlayStore.d.ts +15 -0
  35. package/dist/components/PageLayout/store/overlayStore.js +12 -0
  36. package/dist/components/index.d.ts +4 -0
  37. package/dist/homepage.js +34 -0
  38. package/dist/hooks/index.d.ts +1 -1
  39. package/dist/hooks/useEdificeIcons/useEdificeIcons.js +10 -9
  40. package/dist/icons-nav.js +38 -28
  41. package/dist/index.js +215 -202
  42. package/dist/modules/homepage/components/Favorites/Favorites.d.ts +6 -0
  43. package/dist/modules/homepage/components/Favorites/Favorites.js +28 -0
  44. package/dist/modules/homepage/components/Favorites/FavoritesContainer.d.ts +4 -0
  45. package/dist/modules/homepage/components/Favorites/FavoritesContainer.js +10 -0
  46. package/dist/modules/homepage/components/Favorites/index.d.ts +2 -0
  47. package/dist/modules/homepage/components/Header/Header.d.ts +9 -0
  48. package/dist/modules/homepage/components/Header/Header.js +80 -0
  49. package/dist/modules/homepage/components/Header/index.d.ts +2 -0
  50. package/dist/modules/homepage/components/HomeCard/HomeCard.d.ts +37 -0
  51. package/dist/modules/homepage/components/HomeCard/HomeCard.js +17 -0
  52. package/dist/modules/homepage/components/HomeCard/HomeCardContent.d.ts +7 -0
  53. package/dist/modules/homepage/components/HomeCard/HomeCardContent.js +10 -0
  54. package/dist/modules/homepage/components/HomeCard/HomeCardHeader.d.ts +18 -0
  55. package/dist/modules/homepage/components/HomeCard/HomeCardHeader.js +22 -0
  56. package/dist/modules/homepage/components/HomeCard/index.d.ts +4 -0
  57. package/dist/modules/homepage/components/LastInfos/LastInfos.d.ts +49 -0
  58. package/dist/modules/homepage/components/LastInfos/LastInfos.js +58 -0
  59. package/dist/modules/homepage/components/LastInfos/LastInfosContainer.d.ts +4 -0
  60. package/dist/modules/homepage/components/LastInfos/LastInfosContainer.js +37 -0
  61. package/dist/modules/homepage/components/LastInfos/LastInfosList.d.ts +13 -0
  62. package/dist/modules/homepage/components/LastInfos/LastInfosList.js +31 -0
  63. package/dist/modules/homepage/components/LastInfos/index.d.ts +4 -0
  64. package/dist/modules/homepage/components/LastInfos/useLastInfos.d.ts +18 -0
  65. package/dist/modules/homepage/components/LastInfos/useLastInfos.js +25 -0
  66. package/dist/modules/homepage/components/MessageFlashList/MessageFlash.d.ts +12 -0
  67. package/dist/modules/homepage/components/MessageFlashList/MessageFlash.js +65 -0
  68. package/dist/modules/homepage/components/MessageFlashList/MessageFlashList.d.ts +12 -0
  69. package/dist/modules/homepage/components/MessageFlashList/MessageFlashList.js +10 -0
  70. package/dist/modules/homepage/components/MessageFlashList/MessageFlashListContainer.d.ts +5 -0
  71. package/dist/modules/homepage/components/MessageFlashList/MessageFlashListContainer.js +14 -0
  72. package/dist/modules/homepage/components/MessageFlashList/hooks/useMessageFlashList.d.ts +16 -0
  73. package/dist/modules/homepage/components/MessageFlashList/hooks/useMessageFlashList.js +19 -0
  74. package/dist/modules/homepage/components/MessageFlashList/index.d.ts +4 -0
  75. package/dist/modules/homepage/components/MessageFlashList/services/api/index.d.ts +4 -0
  76. package/dist/modules/homepage/components/MessageFlashList/services/api/index.js +5 -0
  77. package/dist/modules/homepage/components/MessageFlashList/services/api/messagesFlashService.d.ts +20 -0
  78. package/dist/modules/homepage/components/MessageFlashList/services/api/messagesFlashService.js +21 -0
  79. package/dist/modules/homepage/components/MessageFlashList/services/queries/messagesFlash.d.ts +13 -0
  80. package/dist/modules/homepage/components/MessageFlashList/services/queries/messagesFlash.js +31 -0
  81. package/dist/modules/homepage/components/Notifications/NotificationItem.d.ts +20 -0
  82. package/dist/modules/homepage/components/Notifications/NotificationItem.js +16 -0
  83. package/dist/modules/homepage/components/Notifications/NotificationList.d.ts +18 -0
  84. package/dist/modules/homepage/components/Notifications/NotificationList.js +44 -0
  85. package/dist/modules/homepage/components/Notifications/NotificationListContainer.d.ts +9 -0
  86. package/dist/modules/homepage/components/Notifications/NotificationListContainer.js +20 -0
  87. package/dist/modules/homepage/components/Notifications/NotificationListSkeleton.d.ts +5 -0
  88. package/dist/modules/homepage/components/Notifications/NotificationListSkeleton.js +17 -0
  89. package/dist/modules/homepage/components/Notifications/NotificationSkeleton.d.ts +3 -0
  90. package/dist/modules/homepage/components/Notifications/NotificationSkeleton.js +19 -0
  91. package/dist/modules/homepage/components/Notifications/components/CommonNotificationItem.d.ts +24 -0
  92. package/dist/modules/homepage/components/Notifications/components/CommonNotificationItem.js +28 -0
  93. package/dist/modules/homepage/components/Notifications/components/NotificationItemResource.d.ts +15 -0
  94. package/dist/modules/homepage/components/Notifications/components/NotificationItemResource.js +19 -0
  95. package/dist/modules/homepage/components/Notifications/components/SystemNotificationItem.d.ts +15 -0
  96. package/dist/modules/homepage/components/Notifications/components/SystemNotificationItem.js +20 -0
  97. package/dist/modules/homepage/components/Notifications/components/UserNotificationItem.d.ts +15 -0
  98. package/dist/modules/homepage/components/Notifications/components/UserNotificationItem.js +25 -0
  99. package/dist/modules/homepage/components/Notifications/components/notificationAdapter.d.ts +27 -0
  100. package/dist/modules/homepage/components/Notifications/components/notificationAdapter.js +53 -0
  101. package/dist/modules/homepage/components/Notifications/hooks/useNotificationList.d.ts +20 -0
  102. package/dist/modules/homepage/components/Notifications/hooks/useNotificationList.js +26 -0
  103. package/dist/modules/homepage/components/Notifications/index.d.ts +6 -0
  104. package/dist/modules/homepage/components/Notifications/services/api/index.d.ts +4 -0
  105. package/dist/modules/homepage/components/Notifications/services/api/index.js +5 -0
  106. package/dist/modules/homepage/components/Notifications/services/api/notificationService.d.ts +15 -0
  107. package/dist/modules/homepage/components/Notifications/services/api/notificationService.js +22 -0
  108. package/dist/modules/homepage/components/Notifications/services/queries/notification.d.ts +20 -0
  109. package/dist/modules/homepage/components/Notifications/services/queries/notification.js +40 -0
  110. package/dist/modules/homepage/components/SchoolSpace/SchoolSpace.d.ts +15 -0
  111. package/dist/modules/homepage/components/SchoolSpace/SchoolSpace.js +29 -0
  112. package/dist/modules/homepage/components/SchoolSpace/SchoolSpaceContainer.d.ts +4 -0
  113. package/dist/modules/homepage/components/SchoolSpace/SchoolSpaceContainer.js +13 -0
  114. package/dist/modules/homepage/components/SchoolSpace/index.d.ts +3 -0
  115. package/dist/modules/homepage/components/SchoolSpace/useUserSchools.d.ts +6 -0
  116. package/dist/modules/homepage/components/SchoolSpace/useUserSchools.js +39 -0
  117. package/dist/modules/homepage/components/UserSpace/UserSpace.d.ts +13 -0
  118. package/dist/modules/homepage/components/UserSpace/UserSpace.js +28 -0
  119. package/dist/modules/homepage/components/UserSpace/UserSpaceContainer.d.ts +7 -0
  120. package/dist/modules/homepage/components/UserSpace/UserSpaceContainer.js +19 -0
  121. package/dist/modules/homepage/components/UserSpace/index.d.ts +3 -0
  122. package/dist/modules/homepage/components/index.d.ts +8 -0
  123. package/dist/modules/homepage/hooks/useWidget.d.ts +6 -0
  124. package/dist/modules/homepage/hooks/useWidget.js +83 -0
  125. package/dist/modules/homepage/hooks/useWidgetPreferences.d.ts +6 -0
  126. package/dist/modules/homepage/hooks/useWidgetPreferences.js +34 -0
  127. package/dist/modules/homepage/index.d.ts +1 -0
  128. package/dist/modules/icons/components/nav/IconCommunitiesBeta.d.ts +7 -0
  129. package/dist/modules/icons/components/nav/IconCommunitiesBeta.js +18 -0
  130. package/dist/modules/icons/components/nav/IconHomeBeta.d.ts +7 -0
  131. package/dist/modules/icons/components/nav/IconHomeBeta.js +13 -0
  132. package/dist/modules/icons/components/nav/IconMessagesBeta.d.ts +7 -0
  133. package/dist/modules/icons/components/nav/IconMessagesBeta.js +18 -0
  134. package/dist/modules/icons/components/nav/IconMyAppsBeta.d.ts +7 -0
  135. package/dist/modules/icons/components/nav/IconMyAppsBeta.js +13 -0
  136. package/dist/modules/icons/components/nav/IconNotificationBeta.d.ts +7 -0
  137. package/dist/modules/icons/components/nav/IconNotificationBeta.js +14 -0
  138. package/dist/modules/icons/components/nav/index.d.ts +5 -0
  139. package/dist/modules/modals/OnboardingModal/index.d.ts +1 -1
  140. package/dist/providers/EdificeClientProvider/EdificeClientProvider.d.ts +0 -7
  141. package/dist/utilities/create-selectors/createSelectors.d.ts +10 -0
  142. package/dist/utilities/create-selectors/createSelectors.js +11 -0
  143. package/package.json +13 -8
@@ -0,0 +1,4 @@
1
+ export declare const messageFlashService: {
2
+ getMessagesFlash(): Promise<import('@edifice.io/client').IFlashMessageModel[]>;
3
+ markAsRead(message: import('@edifice.io/client').IFlashMessageModel): Promise<void>;
4
+ };
@@ -0,0 +1,5 @@
1
+ import { createMessagesFlashService } from "./messagesFlashService.js";
2
+ const messageFlashService = createMessagesFlashService("");
3
+ export {
4
+ messageFlashService
5
+ };
@@ -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
+ };
@@ -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,5 @@
1
+ declare const NotificationListSkeleton: {
2
+ (): import("react/jsx-runtime").JSX.Element;
3
+ displayName: string;
4
+ };
5
+ export default NotificationListSkeleton;
@@ -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,3 @@
1
+ import { default as React } from 'react';
2
+ declare const NotificationSkeleton: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLDivElement> & React.RefAttributes<HTMLDivElement>>;
3
+ export default NotificationSkeleton;
@@ -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
+ };
@@ -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,4 @@
1
+ export declare const notificationService: {
2
+ getNotifications(types: string[], page: number): Promise<import('@edifice.io/client').NotificationModel[]>;
3
+ getNotificationTypes(): Promise<string[]>;
4
+ };
@@ -0,0 +1,5 @@
1
+ import { createNotificationService } from "./notificationService.js";
2
+ const notificationService = createNotificationService("");
3
+ export {
4
+ notificationService
5
+ };
@@ -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
+ };