InAppNotificationPage.tsx 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. import React, {
  2. FC, useState, useEffect, useCallback,
  3. } from 'react';
  4. import { useTranslation } from 'react-i18next';
  5. import PropTypes from 'prop-types';
  6. import AppContainer from '~/client/services/AppContainer';
  7. import { withUnstatedContainers } from '../UnstatedUtils';
  8. import InAppNotificationList from './InAppNotificationList';
  9. import { useSWRxInAppNotifications, useSWRxInAppNotificationStatus } from '../../stores/in-app-notification';
  10. import PaginationWrapper from '../PaginationWrapper';
  11. import CustomNavAndContents from '../CustomNavigation/CustomNavAndContents';
  12. import { InAppNotificationStatuses } from '~/interfaces/in-app-notification';
  13. import { apiv3Put, apiv3Post } from '~/client/util/apiv3-client';
  14. import loggerFactory from '~/utils/logger';
  15. const logger = loggerFactory('growi:InAppNotificationPage');
  16. type Props = {
  17. appContainer: AppContainer
  18. }
  19. const InAppNotificationPageBody: FC<Props> = (props) => {
  20. const { appContainer } = props;
  21. const limit = appContainer.config.pageLimitationXL;
  22. const { t } = useTranslation();
  23. const { mutate } = useSWRxInAppNotificationStatus();
  24. const updateNotificationStatus = useCallback(async() => {
  25. try {
  26. await apiv3Post('/in-app-notification/read');
  27. mutate();
  28. }
  29. catch (err) {
  30. logger.error(err);
  31. }
  32. }, [mutate]);
  33. useEffect(() => {
  34. updateNotificationStatus();
  35. }, [updateNotificationStatus]);
  36. const InAppNotificationCategoryByStatus = (status?: InAppNotificationStatuses) => {
  37. const [activePage, setActivePage] = useState(1);
  38. const offset = (activePage - 1) * limit;
  39. let categoryStatus;
  40. switch (status) {
  41. case InAppNotificationStatuses.STATUS_UNOPENED:
  42. categoryStatus = InAppNotificationStatuses.STATUS_UNOPENED;
  43. break;
  44. default:
  45. }
  46. const { data: notificationData, mutate: mutateNotificationData } = useSWRxInAppNotifications(limit, offset, categoryStatus);
  47. const { mutate: mutateAllNotificationData } = useSWRxInAppNotifications(limit, offset, undefined);
  48. const setAllNotificationPageNumber = (selectedPageNumber): void => {
  49. setActivePage(selectedPageNumber);
  50. };
  51. if (notificationData == null) {
  52. return (
  53. <div className="wiki">
  54. <div className="text-muted text-center">
  55. <i className="fa fa-2x fa-spinner fa-pulse mr-1"></i>
  56. </div>
  57. </div>
  58. );
  59. }
  60. const updateUnopendNotificationStatusesToOpened = async() => {
  61. await apiv3Put('/in-app-notification/all-statuses-open');
  62. // mutate notification statuses in 'UNREAD' Category
  63. mutateNotificationData();
  64. // mutate notification statuses in 'ALL' Category
  65. mutateAllNotificationData();
  66. };
  67. return (
  68. <>
  69. {(status === InAppNotificationStatuses.STATUS_UNOPENED && notificationData.totalDocs > 0)
  70. && (
  71. <div className="mb-2 d-flex justify-content-end">
  72. <button
  73. type="button"
  74. className="btn btn-outline-primary"
  75. onClick={updateUnopendNotificationStatusesToOpened}
  76. >
  77. {t('in_app_notification.mark_all_as_read')}
  78. </button>
  79. </div>
  80. )}
  81. <InAppNotificationList inAppNotificationData={notificationData} />
  82. {notificationData.totalDocs > 0
  83. && (
  84. <PaginationWrapper
  85. activePage={activePage}
  86. changePage={setAllNotificationPageNumber}
  87. totalItemsCount={notificationData.totalDocs}
  88. pagingLimit={notificationData.limit}
  89. align="center"
  90. size="sm"
  91. />
  92. )
  93. }
  94. </>
  95. );
  96. };
  97. const navTabMapping = {
  98. user_infomation: {
  99. Icon: () => <></>,
  100. Content: () => InAppNotificationCategoryByStatus(),
  101. i18n: t('in_app_notification.all'),
  102. index: 0,
  103. },
  104. external_accounts: {
  105. Icon: () => <></>,
  106. Content: () => InAppNotificationCategoryByStatus(InAppNotificationStatuses.STATUS_UNOPENED),
  107. i18n: t('in_app_notification.unopend'),
  108. index: 1,
  109. },
  110. };
  111. return (
  112. <CustomNavAndContents navTabMapping={navTabMapping} />
  113. );
  114. };
  115. const InAppNotificationPage = withUnstatedContainers(InAppNotificationPageBody, [AppContainer]);
  116. export default InAppNotificationPage;
  117. InAppNotificationPageBody.propTypes = {
  118. appContainer: PropTypes.instanceOf(AppContainer).isRequired,
  119. };