InAppNotificationElm.tsx 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. import React, { useCallback } from 'react';
  2. import { UserPicture, PagePathLabel } from '@growi/ui';
  3. import { IInAppNotification } from '~/interfaces/in-app-notification';
  4. import { apiv3Post } from '~/client/util/apiv3-client';
  5. import FormattedDistanceDate from '../FormattedDistanceDate';
  6. import loggerFactory from '~/utils/logger';
  7. const logger = loggerFactory('growi:InAppNotificationElm');
  8. interface Props {
  9. notification: IInAppNotification
  10. }
  11. const InAppNotificationElm = (props: Props): JSX.Element => {
  12. const { notification } = props;
  13. const getActionUsers = () => {
  14. const latestActionUsers = notification.actionUsers.slice(0, 3);
  15. const latestUsers = latestActionUsers.map((user) => {
  16. return `@${user.name}`;
  17. });
  18. let actionedUsers = '';
  19. const latestUsersCount = latestUsers.length;
  20. if (latestUsersCount === 1) {
  21. actionedUsers = latestUsers[0];
  22. }
  23. else if (notification.actionUsers.length >= 4) {
  24. actionedUsers = `${latestUsers.slice(0, 2).join(', ')} and ${notification.actionUsers.length - 2} others`;
  25. }
  26. else {
  27. actionedUsers = latestUsers.join(', ');
  28. }
  29. return actionedUsers;
  30. };
  31. const renderActionUserPictures = (): JSX.Element => {
  32. const actionUsers = notification.actionUsers;
  33. if (actionUsers.length < 1) {
  34. return <></>;
  35. }
  36. if (actionUsers.length === 1) {
  37. return <UserPicture user={actionUsers[0]} size="md" noTooltip />;
  38. }
  39. return (
  40. <div className="position-relative">
  41. <UserPicture user={actionUsers[0]} size="md" noTooltip />
  42. <div className="position-absolute" style={{ top: 10, left: 10 }}>
  43. <UserPicture user={actionUsers[1]} size="md" noTooltip />
  44. </div>
  45. </div>
  46. );
  47. };
  48. const notificationClickHandler = useCallback(() => {
  49. // set notification status "OPEND"
  50. apiv3Post('/in-app-notification/open', { id: notification._id });
  51. // jump to target page
  52. window.location.href = notification.target.path;
  53. }, []);
  54. const actionUsers = getActionUsers();
  55. const pagePath = { path: props.notification.target.path };
  56. const actionType: string = notification.action;
  57. let actionMsg: string;
  58. let actionIcon: string;
  59. switch (actionType) {
  60. case 'PAGE_UPDATE':
  61. actionMsg = 'updated on';
  62. actionIcon = 'ti-agenda';
  63. break;
  64. case 'COMMENT_CREATE':
  65. actionMsg = 'commented on';
  66. actionIcon = 'icon-bubble';
  67. break;
  68. default:
  69. actionMsg = '';
  70. actionIcon = '';
  71. }
  72. return (
  73. <div className="dropdown-item d-flex flex-row mb-3">
  74. <div className="p-2 mr-2 d-flex align-items-center">
  75. {renderActionUserPictures()}
  76. </div>
  77. <div className="p-2">
  78. <div onClick={notificationClickHandler}>
  79. <div>
  80. <b>{actionUsers}</b> {actionMsg} <PagePathLabel page={pagePath} />
  81. </div>
  82. <i className={`${actionIcon} mr-2`} />
  83. <FormattedDistanceDate
  84. id={notification._id}
  85. date={notification.createdAt}
  86. isShowTooltip={false}
  87. differenceForAvoidingFormat={Number.POSITIVE_INFINITY}
  88. />
  89. </div>
  90. </div>
  91. </div>
  92. );
  93. };
  94. export default InAppNotificationElm;