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

Merge branch 'feat/integrate-implement-page-alert-component' into feat/98981-trash-page-alert

yuken 3 лет назад
Родитель
Сommit
ab75fcc4f4

+ 2 - 4
packages/app/src/components/PageAlert/PageAlerts.tsx

@@ -1,9 +1,8 @@
 import dynamic from 'next/dynamic'
 import { FixPageGrantAlert } from "./FixPageGrantAlert";
 import { PageGrantAlert } from "./PageGrantAlert";
-
 const TrashPageAlert = dynamic(() => import('./TrashPageAlert').then(mod => mod.TrashPageAlert), {ssr: false})
-
+import { PageStaleAlert } from "./PageStaleAlert";
 
 export const PageAlerts = (): JSX.Element => {
 
@@ -13,10 +12,9 @@ export const PageAlerts = (): JSX.Element => {
       <div className="col-sm-12">
         {/* alerts */}
         <FixPageGrantAlert/>
-
         <PageGrantAlert/>
-
         <TrashPageAlert/>
+        <PageStaleAlert/>
       </div>
     </div>
   );

+ 41 - 0
packages/app/src/components/PageAlert/PageStaleAlert.tsx

@@ -0,0 +1,41 @@
+import { useIsEnabledStaleNotification } from '../../stores/context'
+import { useSWRxCurrentPage, useSWRxPageInfo } from '../../stores/page'
+import { useTranslation } from 'react-i18next';
+
+export const PageStaleAlert = ():JSX.Element => {
+  const { t } = useTranslation()
+  const { data: isEnabledStaleNotification } = useIsEnabledStaleNotification();
+
+  // Todo: determine if it should fetch or not like useSWRxPageInfo below after https://redmine.weseek.co.jp/issues/96788
+  const { data: pageData } = useSWRxCurrentPage();
+  const { data: pageInfo } = useSWRxPageInfo(isEnabledStaleNotification ? pageData?._id : null);
+
+  const contentAge = pageInfo?.contentAge;
+
+  if (!isEnabledStaleNotification) {
+    return <></>
+  }
+
+  if( pageInfo == null || contentAge == null || contentAge === 0) {
+    return <></>
+  }
+
+  let alertClass;
+  switch (contentAge) {
+    case 1:
+      alertClass = "alert-info";
+      break;
+    case 2:
+      alertClass = "alert-warning";
+      break;
+    default:
+      alertClass = "alert-danger";
+  }
+
+  return (
+    <div className={`alert ${alertClass}`}>
+      <i className="icon-fw icon-hourglass"></i>
+      <strong>{ t('page_page.notice.stale', { count: pageInfo.contentAge }) }</strong>
+    </div>
+  )
+}

+ 1 - 0
packages/app/src/interfaces/page.ts

@@ -53,6 +53,7 @@ export type IPageInfo = {
   isDeletable: boolean,
   isAbleToDeleteCompletely: boolean,
   isRevertible: boolean,
+  contentAge?: number,
 }
 
 export type IPageInfoForEntity = IPageInfo & {

+ 3 - 3
packages/app/src/pages/[[...path]].page.tsx

@@ -83,7 +83,7 @@ type Props = CommonProps & {
   // isAllReplyShown: boolean,
   // isContainerFluid: boolean,
   // editorConfig: any,
-  // isEnabledStaleNotification: boolean,
+  isEnabledStaleNotification: boolean,
   // isEnabledLinebreaks: boolean,
   // isEnabledLinebreaksInComments: boolean,
   // adminPreferredIndentSize: number,
@@ -114,10 +114,10 @@ const GrowiPage: NextPage<Props> = (props: Props) => {
   // useShareLinkId(props.shareLinkId);
   // useIsAbleToDeleteCompletely(props.isAbleToDeleteCompletely);
   // useIsSharedUser(props.currentUser == null && isSharedPage(props.currentPagePath));
-  // useIsEnabledStaleNotification(props.isEnabledStaleNotification);
   useLastUpdateUsername(props.lastUpdateUserName);
   useDeletedAt(props.deletedAt);
   useRevisionId(props.revisionId);
+  useIsEnabledStaleNotification(props.isEnabledStaleNotification);
 
   useIsSearchServiceConfigured(props.isSearchServiceConfigured);
   useIsSearchServiceReachable(props.isSearchServiceReachable);
@@ -315,7 +315,7 @@ export const getServerSideProps: GetServerSideProps = async(context: GetServerSi
   // props.highlightJsStyle = configManager.getConfig('crowi', 'customize:highlightJsStyle');
   // props.isAllReplyShown = configManager.getConfig('crowi', 'customize:isAllReplyShown');
   // props.isContainerFluid = configManager.getConfig('crowi', 'customize:isContainerFluid');
-  // props.isEnabledStaleNotification = configManager.getConfig('crowi', 'customize:isEnabledStaleNotification');
+  props.isEnabledStaleNotification = configManager.getConfig('crowi', 'customize:isEnabledStaleNotification');
   // props.isEnabledLinebreaks = configManager.getConfig('markdown', 'markdown:isEnabledLinebreaks');
   // props.isEnabledLinebreaksInComments = configManager.getConfig('markdown', 'markdown:isEnabledLinebreaksInComments');
   // props.editorConfig = {

+ 2 - 1
packages/app/src/server/service/page.ts

@@ -2176,7 +2176,7 @@ class PageService {
     });
   }
 
-  constructBasicPageInfo(page: IPage, isGuestUser?: boolean): IPageInfo | IPageInfoForEntity {
+  constructBasicPageInfo(page: PageDocument, isGuestUser?: boolean): IPageInfo | IPageInfoForEntity {
     const isMovable = isGuestUser ? false : isMovablePage(page.path);
 
     if (page.isEmpty) {
@@ -2204,6 +2204,7 @@ class PageService {
       isDeletable: isMovable,
       isAbleToDeleteCompletely: false,
       isRevertible: isTrashPage(page.path),
+      contentAge: page.getContentAge(),
     };
 
   }

+ 5 - 0
packages/app/src/stores/context.tsx

@@ -187,6 +187,11 @@ export const useGrowiVersion = (initialData?: string): SWRResponse<string, any>
   return useStaticSWR('growiVersion', initialData);
 };
 
+export const useIsEnabledStaleNotification = (initialData?: boolean): SWRResponse<boolean, any> => {
+  return useStaticSWR('isEnabledStaleNotification', initialData);
+};
+
+
 
 /** **********************************************************
  *                     Computed contexts