Просмотр исходного кода

Merge pull request #8371 from weseek/feat/137966-show-notifications-in-sidebar

feat: Show notifications in sidebar
Yuki Takei 2 лет назад
Родитель
Сommit
d5477d2d86

+ 1 - 1
apps/app/src/components/InAppNotification/InAppNotificationDropdown.tsx

@@ -91,7 +91,7 @@ export const InAppNotificationDropdown = (): JSX.Element => {
           // no items
           ? <DropdownItem disabled>{t('in_app_notification.mark_all_as_read')}</DropdownItem>
           // render DropdownItem
-          : <InAppNotificationList type="dropdown-item" inAppNotificationData={inAppNotificationData} />
+          : <InAppNotificationList inAppNotificationData={inAppNotificationData} />
         }
         <DropdownItem divider />
         <DropdownItem tag="a" href="/me/all-in-app-notifications">

+ 3 - 14
apps/app/src/components/InAppNotification/InAppNotificationElm.tsx

@@ -2,7 +2,6 @@ import React, { FC } from 'react';
 
 import type { HasObjectId } from '@growi/core';
 import { UserPicture } from '@growi/ui/dist/components';
-import { DropdownItem } from 'reactstrap';
 
 import { apiv3Post } from '~/client/util/apiv3-client';
 import { IInAppNotification, InAppNotificationStatuses } from '~/interfaces/in-app-notification';
@@ -11,11 +10,8 @@ import { useModelNotification } from './PageNotification';
 
 interface Props {
   notification: IInAppNotification & HasObjectId
-  elemClassName?: string,
-  type?: 'button' | 'dropdown-item',
 }
 
-
 const InAppNotificationElm: FC<Props> = (props: Props) => {
 
   const { notification } = props;
@@ -57,16 +53,8 @@ const InAppNotificationElm: FC<Props> = (props: Props) => {
     );
   };
 
-  const isDropdownItem = props.type === 'dropdown-item';
-
-  // determine tag
-  const TagElem = isDropdownItem
-    ? DropdownItem
-    // eslint-disable-next-line react/prop-types
-    : props => <button type="button" {...props}>{props.children}</button>;
-
   return (
-    <TagElem className={props.elemClassName} onClick={() => clickHandler(notification)}>
+    <div className="list-group-item list-group-item-action" onClick={() => clickHandler(notification)} style={{ cursor: 'pointer' }}>
       <div className="d-flex align-items-center">
         <span
           className={`${notification.status === InAppNotificationStatuses.STATUS_UNOPENED
@@ -75,12 +63,13 @@ const InAppNotificationElm: FC<Props> = (props: Props) => {
           } rounded-circle me-3`}
         >
         </span>
+
         {renderActionUserPictures()}
 
         <Notification />
 
       </div>
-    </TagElem>
+    </div>
   );
 };
 

+ 3 - 5
apps/app/src/components/InAppNotification/InAppNotificationList.tsx

@@ -9,8 +9,6 @@ import InAppNotificationElm from './InAppNotificationElm';
 
 type Props = {
   inAppNotificationData?: PaginateResult<IInAppNotification>,
-  elemClassName?: string,
-  type?: 'button' | 'dropdown-item',
 };
 
 const InAppNotificationList: FC<Props> = (props: Props) => {
@@ -29,13 +27,13 @@ const InAppNotificationList: FC<Props> = (props: Props) => {
   const notifications = inAppNotificationData.docs;
 
   return (
-    <>
+    <div className="list-group">
       { notifications.map((notification: IInAppNotification & HasObjectId) => {
         return (
-          <InAppNotificationElm key={notification._id} notification={notification} type={props.type} elemClassName={props.elemClassName} />
+          <InAppNotificationElm key={notification._id} notification={notification} />
         );
       }) }
-    </>
+    </div>
   );
 };
 

+ 1 - 3
apps/app/src/components/InAppNotification/InAppNotificationPage.tsx

@@ -100,9 +100,7 @@ export const InAppNotificationPage: FC = () => {
           ? t('in_app_notification.mark_all_as_read')
           // render list-group
           : (
-            <div className="list-group">
-              <InAppNotificationList inAppNotificationData={notificationData} type="button" elemClassName="list-group-item list-group-item-action" />
-            </div>
+            <InAppNotificationList inAppNotificationData={notificationData} />
           )
         }
 

+ 10 - 1
apps/app/src/components/Sidebar/InAppNotification/InAppNotification.tsx

@@ -1,7 +1,12 @@
-import React from 'react';
+import React, { Suspense } from 'react';
 
+import dynamic from 'next/dynamic';
 import { useTranslation } from 'react-i18next';
 
+import ItemsTreeContentSkeleton from '../../ItemsTree/ItemsTreeContentSkeleton';
+
+const InAppNotificationSubstance = dynamic(() => import('./InAppNotificationSubstance').then(mod => mod.InAppNotificationSubstance), { ssr: false });
+
 export const InAppNotification = (): JSX.Element => {
   const { t } = useTranslation();
   return (
@@ -11,6 +16,10 @@ export const InAppNotification = (): JSX.Element => {
           {t('In-App Notification')}
         </h3>
       </div>
+
+      <Suspense fallback={<ItemsTreeContentSkeleton />}>
+        <InAppNotificationSubstance />
+      </Suspense>
     </div>
   );
 };

+ 26 - 0
apps/app/src/components/Sidebar/InAppNotification/InAppNotificationSubstance.tsx

@@ -0,0 +1,26 @@
+import React from 'react';
+
+import { useTranslation } from 'next-i18next';
+
+import InAppNotificationList from '~/components/InAppNotification/InAppNotificationList';
+import { useSWRxInAppNotifications } from '~/stores/in-app-notification';
+
+export const InAppNotificationSubstance = (): JSX.Element => {
+  const { t } = useTranslation('commons');
+
+  // TODO: Infinite scroll implemented (https://redmine.weseek.co.jp/issues/138057)
+  const { data: inAppNotificationData } = useSWRxInAppNotifications(6, undefined, undefined, { revalidateOnFocus: true });
+
+  return (
+    <>
+      {inAppNotificationData != null && inAppNotificationData.docs.length === 0
+      // no items
+        ? t('in_app_notification.mark_all_as_read')
+      // render list-group
+        : (
+          <InAppNotificationList inAppNotificationData={inAppNotificationData} />
+        )
+      }
+    </>
+  );
+};