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

Merge pull request #8227 from weseek/support/134087-refactor-conditional-branch-about-doc.parsedSnapshot

support: 134087 refactor conditional branch about doc.parsed snapshot
Shun Miyazawa 2 лет назад
Родитель
Сommit
5b43f9b039

+ 11 - 32
apps/app/src/components/InAppNotification/InAppNotificationElm.tsx

@@ -2,7 +2,7 @@ import React, {
   FC, useRef,
 } from 'react';
 
-import type { HasObjectId } from '@growi/core';
+import type { IUser, IPage, HasObjectId } from '@growi/core';
 import { UserPicture } from '@growi/ui/dist/components';
 import { DropdownItem } from 'reactstrap';
 
@@ -40,31 +40,6 @@ const InAppNotificationElm: FC<Props> = (props: Props) => {
     }
   };
 
-  const getActionUsers = () => {
-    if (notification.targetModel === SupportedTargetModel.MODEL_USER) {
-      return notification.target.username;
-    }
-
-    const latestActionUsers = notification.actionUsers.slice(0, 3);
-    const latestUsers = latestActionUsers.map((user) => {
-      return `@${user.name}`;
-    });
-
-    let actionedUsers = '';
-    const latestUsersCount = latestUsers.length;
-    if (latestUsersCount === 1) {
-      actionedUsers = latestUsers[0];
-    }
-    else if (notification.actionUsers.length >= 4) {
-      actionedUsers = `${latestUsers.slice(0, 2).join(', ')} and ${notification.actionUsers.length - 2} others`;
-    }
-    else {
-      actionedUsers = latestUsers.join(', ');
-    }
-
-    return actionedUsers;
-  };
-
   const renderActionUserPictures = (): JSX.Element => {
     const actionUsers = notification.actionUsers;
 
@@ -84,10 +59,16 @@ const InAppNotificationElm: FC<Props> = (props: Props) => {
     );
   };
 
-  const actionUsers = getActionUsers();
-
   const isDropdownItem = props.type === 'dropdown-item';
 
+  const isPageNotification = (notification: IInAppNotification): notification is IInAppNotification<IPage> => {
+    return notification.targetModel === SupportedTargetModel.MODEL_PAGE;
+  };
+
+  const isUserNotification = (notification: IInAppNotification): notification is IInAppNotification<IUser> => {
+    return notification.targetModel === SupportedTargetModel.MODEL_USER;
+  };
+
   // determine tag
   const TagElem = isDropdownItem
     ? DropdownItem
@@ -105,18 +86,16 @@ const InAppNotificationElm: FC<Props> = (props: Props) => {
         >
         </span>
         {renderActionUserPictures()}
-        {notification.targetModel === SupportedTargetModel.MODEL_PAGE && (
+        {isPageNotification(notification) && (
           <PageModelNotification
             ref={notificationRef}
             notification={notification}
-            actionUsers={actionUsers}
           />
         )}
-        {notification.targetModel === SupportedTargetModel.MODEL_USER && (
+        {isUserNotification(notification) && (
           <UserModelNotification
             ref={notificationRef}
             notification={notification}
-            actionUsers={actionUsers}
           />
         )}
       </div>

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

@@ -26,7 +26,7 @@ const InAppNotificationList: FC<Props> = (props: Props) => {
     );
   }
 
-  const notifications = inAppNotificationData.docs.filter((notification) => { return notification.parsedSnapshot != null });
+  const notifications = inAppNotificationData.docs;
 
   return (
     <>

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

@@ -31,7 +31,9 @@ export const ModelNotification: FC<Props> = (props) => {
   return (
     <div className="p-2 overflow-hidden">
       <div className="text-truncate">
-        <b>{actionUsers}</b> {actionMsg} <PagePathLabel path={notification.parsedSnapshot?.path ?? ''} />
+        <b>{actionUsers}</b>
+        {actionMsg}
+        <PagePathLabel path={notification.parsedSnapshot?.path ?? ''} />
       </div>
       <i className={`${actionIcon} me-2`} />
       <FormattedDistanceDate

+ 30 - 7
apps/app/src/components/InAppNotification/PageNotification/PageModelNotification.tsx

@@ -1,32 +1,53 @@
 import React, {
-  forwardRef, ForwardRefRenderFunction,
+  forwardRef, ForwardRefRenderFunction, useCallback,
 } from 'react';
 
-import type { HasObjectId } from '@growi/core';
+import type { IPage, HasObjectId } from '@growi/core';
 import { useRouter } from 'next/router';
 
 import type { IInAppNotificationOpenable } from '~/client/interfaces/in-app-notification-openable';
 import type { IInAppNotification } from '~/interfaces/in-app-notification';
+import * as pageSerializers from '~/models/serializers/in-app-notification-snapshot/page';
 
 import { ModelNotification } from './ModelNotification';
 import { useActionMsgAndIconForPageModelNotification } from './useActionAndMsg';
 
 
 interface Props {
-  notification: IInAppNotification & HasObjectId
-  actionUsers: string
+  notification: IInAppNotification<IPage> & HasObjectId
 }
 
 const PageModelNotification: ForwardRefRenderFunction<IInAppNotificationOpenable, Props> = (props: Props, ref) => {
 
-  const {
-    notification, actionUsers,
-  } = props;
+  const { notification } = props;
 
   const { actionMsg, actionIcon } = useActionMsgAndIconForPageModelNotification(notification);
 
   const router = useRouter();
 
+  const getActionUsers = useCallback(() => {
+    const latestActionUsers = notification.actionUsers.slice(0, 3);
+    const latestUsers = latestActionUsers.map((user) => {
+      return `@${user.name}`;
+    });
+
+    let actionedUsers = '';
+    const latestUsersCount = latestUsers.length;
+    if (latestUsersCount === 1) {
+      actionedUsers = latestUsers[0];
+    }
+    else if (notification.actionUsers.length >= 4) {
+      actionedUsers = `${latestUsers.slice(0, 2).join(', ')} and ${notification.actionUsers.length - 2} others`;
+    }
+    else {
+      actionedUsers = latestUsers.join(', ');
+    }
+
+    return actionedUsers;
+  }, [notification.actionUsers]);
+
+  const actionUsers = getActionUsers();
+
   // publish open()
   const publishOpen = () => {
     if (notification.target != null) {
@@ -38,6 +59,8 @@ const PageModelNotification: ForwardRefRenderFunction<IInAppNotificationOpenable
     }
   };
 
+  notification.parsedSnapshot = pageSerializers.parseSnapshot(notification.snapshot);
+
   return (
     <ModelNotification
       notification={notification}

+ 11 - 8
apps/app/src/components/InAppNotification/PageNotification/UserModelNotification.tsx

@@ -2,7 +2,7 @@ import React, {
   forwardRef, ForwardRefRenderFunction,
 } from 'react';
 
-import type { HasObjectId } from '@growi/core';
+import type { IUser, HasObjectId } from '@growi/core';
 import { useRouter } from 'next/router';
 
 import type { IInAppNotificationOpenable } from '~/client/interfaces/in-app-notification-openable';
@@ -11,22 +11,25 @@ import type { IInAppNotification } from '~/interfaces/in-app-notification';
 import { ModelNotification } from './ModelNotification';
 import { useActionMsgAndIconForUserModelNotification } from './useActionAndMsg';
 
+interface Props {
+  notification: IInAppNotification<IUser> & HasObjectId
+}
 
-const UserModelNotification: ForwardRefRenderFunction<IInAppNotificationOpenable, {
-  notification: IInAppNotification & HasObjectId
-  actionUsers: string
-}> = ({
-  notification, actionUsers,
-}, ref) => {
-  const router = useRouter();
+const UserModelNotification: ForwardRefRenderFunction<IInAppNotificationOpenable, Props> = (props: Props, ref) => {
+
+  const { notification } = props;
 
   const { actionMsg, actionIcon } = useActionMsgAndIconForUserModelNotification(notification);
 
+  const router = useRouter();
+
   // publish open()
   const publishOpen = () => {
     router.push('/admin/users');
   };
 
+  const actionUsers = notification.target.username;
+
   return (
     <ModelNotification
       notification={notification}

+ 3 - 3
apps/app/src/components/InAppNotification/PageNotification/useActionAndMsg.ts

@@ -1,4 +1,4 @@
-import type { HasObjectId } from '@growi/core';
+import type { IUser, IPage, HasObjectId } from '@growi/core';
 
 import { SupportedAction } from '~/interfaces/activity';
 import type { IInAppNotification } from '~/interfaces/in-app-notification';
@@ -8,7 +8,7 @@ export type ActionMsgAndIconType = {
   actionIcon: string
 }
 
-export const useActionMsgAndIconForPageModelNotification = (notification: IInAppNotification & HasObjectId): ActionMsgAndIconType => {
+export const useActionMsgAndIconForPageModelNotification = (notification: IInAppNotification<IPage> & HasObjectId): ActionMsgAndIconType => {
   const actionType: string = notification.action;
   let actionMsg: string;
   let actionIcon: string;
@@ -77,7 +77,7 @@ export const useActionMsgAndIconForPageModelNotification = (notification: IInApp
   };
 };
 
-export const useActionMsgAndIconForUserModelNotification = (notification: IInAppNotification & HasObjectId): ActionMsgAndIconType => {
+export const useActionMsgAndIconForUserModelNotification = (notification: IInAppNotification<IUser> & HasObjectId): ActionMsgAndIconType => {
   const actionType: string = notification.action;
   let actionMsg: string;
   let actionIcon: string;

+ 2 - 2
apps/app/src/interfaces/in-app-notification.ts

@@ -10,10 +10,10 @@ export enum InAppNotificationStatuses {
 
 // TODO: do not use any type
 // https://redmine.weseek.co.jp/issues/120632
-export interface IInAppNotification {
+export interface IInAppNotification<T = unknown> {
   user: IUser
   targetModel: SupportedTargetModelType
-  target: any
+  target: T
   action: SupportedActionType
   status: InAppNotificationStatuses
   actionUsers: IUser[]

+ 1 - 0
apps/app/src/server/routes/apiv3/in-app-notification.ts

@@ -1,6 +1,7 @@
 import { SupportedAction } from '~/interfaces/activity';
 import { generateAddActivityMiddleware } from '~/server/middlewares/add-activity';
 
+
 import { IInAppNotification } from '../../../interfaces/in-app-notification';
 
 const express = require('express');

+ 3 - 10
apps/app/src/stores/in-app-notification.ts

@@ -1,8 +1,8 @@
 import useSWR, { SWRConfiguration, SWRResponse } from 'swr';
 
+
 import { SupportedTargetModel } from '~/interfaces/activity';
 import type { InAppNotificationStatuses, IInAppNotification, PaginateResult } from '~/interfaces/in-app-notification';
-import * as pageSerializers from '~/models/serializers/in-app-notification-snapshot/page';
 import * as userSerializers from '~/models/serializers/in-app-notification-snapshot/user';
 import loggerFactory from '~/utils/logger';
 
@@ -24,15 +24,8 @@ export const useSWRxInAppNotifications = (
       const inAppNotificationPaginateResult = response.data as inAppNotificationPaginateResult;
       inAppNotificationPaginateResult.docs.forEach((doc) => {
         try {
-          switch (doc.targetModel) {
-            case SupportedTargetModel.MODEL_PAGE:
-              doc.parsedSnapshot = pageSerializers.parseSnapshot(doc.snapshot);
-              break;
-            case SupportedTargetModel.MODEL_USER:
-              doc.parsedSnapshot = userSerializers.parseSnapshot(doc.snapshot);
-              break;
-            default:
-              throw new Error(`No serializer found for targetModel: ${doc.targetModel}`);
+          if (doc.targetModel === SupportedTargetModel.MODEL_USER) {
+            doc.parsedSnapshot = userSerializers.parseSnapshot(doc.snapshot);
           }
         }
         catch (err) {