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

Merge pull request #8579 from weseek/feat/142713-prevent-opening-edit-modal-if-revision-is-outdated

feat: Prevent opening edit modal if revision is outdated
Yuki Takei 2 лет назад
Родитель
Сommit
4f8988fbdc

+ 4 - 1
apps/app/src/components/ReactMarkdownComponents/DrawioViewerWithEditButton.tsx

@@ -14,6 +14,8 @@ import {
 } from '~/stores/context';
 } from '~/stores/context';
 
 
 import '@growi/remark-drawio/dist/style.css';
 import '@growi/remark-drawio/dist/style.css';
+import { useIsRevisionOutdated } from '~/stores/page';
+
 import styles from './DrawioViewerWithEditButton.module.scss';
 import styles from './DrawioViewerWithEditButton.module.scss';
 
 
 
 
@@ -32,6 +34,7 @@ export const DrawioViewerWithEditButton = React.memo((props: DrawioViewerProps):
   const { data: isReadOnlyUser } = useIsReadOnlyUser();
   const { data: isReadOnlyUser } = useIsReadOnlyUser();
   const { data: isSharedUser } = useIsSharedUser();
   const { data: isSharedUser } = useIsSharedUser();
   const { data: shareLinkId } = useShareLinkId();
   const { data: shareLinkId } = useShareLinkId();
+  const { data: isRevisionOutdated } = useIsRevisionOutdated();
 
 
   const [isRendered, setRendered] = useState(false);
   const [isRendered, setRendered] = useState(false);
   const [mxfile, setMxfile] = useState('');
   const [mxfile, setMxfile] = useState('');
@@ -55,7 +58,7 @@ export const DrawioViewerWithEditButton = React.memo((props: DrawioViewerProps):
     }
     }
   }, []);
   }, []);
 
 
-  const showEditButton = isRendered && !isGuestUser && !isReadOnlyUser && !isSharedUser && shareLinkId == null;
+  const showEditButton = !isRevisionOutdated && isRendered && !isGuestUser && !isReadOnlyUser && !isSharedUser && shareLinkId == null;
 
 
   return (
   return (
     <div className={`drawio-viewer-with-edit-button ${styles['drawio-viewer-with-edit-button']}`}>
     <div className={`drawio-viewer-with-edit-button ${styles['drawio-viewer-with-edit-button']}`}>

+ 3 - 1
apps/app/src/components/ReactMarkdownComponents/TableWithEditButton.tsx

@@ -7,6 +7,7 @@ import type { Element } from 'react-markdown/lib/rehype-filter';
 import {
 import {
   useIsGuestUser, useIsReadOnlyUser, useIsSharedUser, useShareLinkId,
   useIsGuestUser, useIsReadOnlyUser, useIsSharedUser, useShareLinkId,
 } from '~/stores/context';
 } from '~/stores/context';
+import { useIsRevisionOutdated } from '~/stores/page';
 
 
 import styles from './TableWithEditButton.module.scss';
 import styles from './TableWithEditButton.module.scss';
 
 
@@ -29,6 +30,7 @@ export const TableWithEditButton = React.memo((props: TableWithEditButtonProps):
   const { data: isReadOnlyUser } = useIsReadOnlyUser();
   const { data: isReadOnlyUser } = useIsReadOnlyUser();
   const { data: isSharedUser } = useIsSharedUser();
   const { data: isSharedUser } = useIsSharedUser();
   const { data: shareLinkId } = useShareLinkId();
   const { data: shareLinkId } = useShareLinkId();
+  const { data: isRevisionOutdated } = useIsRevisionOutdated();
 
 
   const bol = node.position?.start.line;
   const bol = node.position?.start.line;
   const eol = node.position?.end.line;
   const eol = node.position?.end.line;
@@ -37,7 +39,7 @@ export const TableWithEditButton = React.memo((props: TableWithEditButtonProps):
     globalEmitter.emit('launchHandsonTableModal', bol, eol);
     globalEmitter.emit('launchHandsonTableModal', bol, eol);
   }, [bol, eol]);
   }, [bol, eol]);
 
 
-  const showEditButton = !isGuestUser && !isReadOnlyUser && !isSharedUser && shareLinkId == null;
+  const showEditButton = !isRevisionOutdated && !isGuestUser && !isReadOnlyUser && !isSharedUser && shareLinkId == null;
 
 
   return (
   return (
     <div className={`editable-with-handsontable ${styles['editable-with-handsontable']}`}>
     <div className={`editable-with-handsontable ${styles['editable-with-handsontable']}`}>

+ 13 - 0
apps/app/src/stores/page.tsx

@@ -26,6 +26,7 @@ import type { IPageTagsInfo } from '../interfaces/tag';
 import {
 import {
   useCurrentPathname, useShareLinkId, useIsGuestUser, useIsReadOnlyUser,
   useCurrentPathname, useShareLinkId, useIsGuestUser, useIsReadOnlyUser,
 } from './context';
 } from './context';
+import { useRemoteRevisionId } from './remote-latest-page';
 
 
 
 
 const { isPermalink: _isPermalink } = pagePathUtils;
 const { isPermalink: _isPermalink } = pagePathUtils;
@@ -326,3 +327,15 @@ export const useIsTrashPage = (): SWRResponse<boolean, Error> => {
     // { fallbackData:  }
     // { fallbackData:  }
   );
   );
 };
 };
+
+export const useIsRevisionOutdated = (): SWRResponse<boolean, Error> => {
+  const { data: currentPage } = useSWRxCurrentPage();
+  const { data: remoteRevisionId } = useRemoteRevisionId();
+
+  const currentRevisionId = currentPage?.revision?._id;
+
+  return useSWRImmutable(
+    currentRevisionId != null && remoteRevisionId != null ? ['useIsRevisionOutdated', currentRevisionId, remoteRevisionId] : null,
+    ([, remoteRevisionId, currentRevisionId]) => { return remoteRevisionId !== currentRevisionId },
+  );
+};