Преглед изворни кода

Merge pull request #4957 from weseek/imprv/83338-grant-swr

imprv: Migrate editor container grant to SWR
Yuki Takei пре 4 година
родитељ
комит
2fec012e10

+ 8 - 1
packages/app/src/client/services/ContextExtractor.tsx

@@ -7,10 +7,11 @@ import {
   usePageId, usePageIdOnHackmd, usePageUser, useCurrentPagePath, useRevisionCreatedAt, useRevisionId, useRevisionIdHackmdSynced,
   useShareLinkId, useShareLinksNumber, useTemplateTagData, useCurrentUpdatedAt, useCreator, useRevisionAuthor, useCurrentUser,
   useSlackChannels,
-} from '../../stores/context';
+} from '~/stores/context';
 import {
   useIsDeviceSmallerThanMd,
   usePreferDrawerModeByUser, usePreferDrawerModeOnEditByUser, useSidebarCollapsed, useCurrentSidebarContents, useCurrentProductNavWidth,
+  useSelectedGrant, useSelectedGrantGroupId, useSelectedGrantGroupName,
 } from '~/stores/ui';
 import { IUserUISettings } from '~/interfaces/user-ui-settings';
 
@@ -68,6 +69,9 @@ const ContextExtractorOnce: FC = () => {
   const creator = JSON.parse(mainContent?.getAttribute('data-page-creator') || jsonNull);
   const revisionAuthor = JSON.parse(mainContent?.getAttribute('data-page-revision-author') || jsonNull);
   const slackChannels = mainContent?.getAttribute('data-slack-channels') || '';
+  const grant = +(mainContent?.getAttribute('data-page-grant') || 1);
+  const grantGroupId = mainContent?.getAttribute('data-page-grant-group') || null;
+  const grantGroupName = mainContent?.getAttribute('data-page-grant-group-name') || null;
   /*
    * use static swr
    */
@@ -116,6 +120,9 @@ const ContextExtractorOnce: FC = () => {
 
   // Editor
   useSlackChannels(slackChannels);
+  useSelectedGrant(grant);
+  useSelectedGrantGroupId(grantGroupId);
+  useSelectedGrantGroupName(grantGroupName);
 
   return null;
 };

+ 4 - 29
packages/app/src/client/services/EditorContainer.js

@@ -27,10 +27,6 @@ export default class EditorContainer extends Container {
     this.state = {
       tags: null,
 
-      grant: 1, // default: public
-      grantGroupId: null,
-      grantGroupName: null,
-
       editorOptions: {},
       previewOptions: {},
 
@@ -43,7 +39,6 @@ export default class EditorContainer extends Container {
 
     this.isSetBeforeunloadEventHandler = false;
 
-    this.initStateGrant();
     this.initDrafts();
 
     this.initEditorOptions('editorOptions', 'editorOptions', defaultEditorOptions);
@@ -57,26 +52,6 @@ export default class EditorContainer extends Container {
     return 'EditorContainer';
   }
 
-  /**
-   * initialize state for page permission
-   */
-  initStateGrant() {
-    const mainContent = document.getElementById('content-main');
-
-    if (mainContent == null) {
-      logger.debug('#content-main element is not exists');
-      return;
-    }
-
-    this.state.grant = +mainContent.getAttribute('data-page-grant');
-
-    const grantGroupId = mainContent.getAttribute('data-page-grant-group');
-    if (grantGroupId != null && grantGroupId.length > 0) {
-      this.state.grantGroupId = grantGroupId;
-      this.state.grantGroupName = mainContent.getAttribute('data-page-grant-group-name');
-    }
-  }
-
   /**
    * initialize state for drafts
    */
@@ -145,13 +120,13 @@ export default class EditorContainer extends Container {
     const opt = {
       // isSlackEnabled: this.state.isSlackEnabled,
       // slackChannels: this.state.slackChannels,
-      grant: this.state.grant,
+      // grant: this.state.grant,
       pageTags: this.state.tags,
     };
 
-    if (this.state.grantGroupId != null) {
-      opt.grantUserGroupId = this.state.grantGroupId;
-    }
+    // if (this.state.grantGroupId != null) {
+    //   opt.grantUserGroupId = this.state.grantGroupId;
+    // }
 
     return opt;
   }

+ 18 - 3
packages/app/src/client/util/editor.ts

@@ -5,11 +5,26 @@ type OptionsToSave = {
   slackChannels: string;
   grant: number;
   pageTags: string[];
-  grantUserGroupId?: string;
+  grantUserGroupId: string | null;
+  grantUserGroupName: string | null;
 };
 
 // TODO: Remove editorContainer upon migration to SWR
-export const getOptionsToSave = (isSlackEnabled: boolean, slackChannels: string, editorContainer: EditorContainer): OptionsToSave => {
+export const getOptionsToSave = (
+    isSlackEnabled: boolean,
+    slackChannels: string,
+    grant: number,
+    grantUserGroupId: string | null,
+    grantUserGroupName: string | null,
+    editorContainer: EditorContainer,
+): OptionsToSave => {
   const optionsToSave = editorContainer.getCurrentOptionsToSave();
-  return { ...optionsToSave, isSlackEnabled, slackChannels };
+  return {
+    ...optionsToSave,
+    isSlackEnabled,
+    slackChannels,
+    grant,
+    grantUserGroupId,
+    grantUserGroupName,
+  };
 };

+ 17 - 5
packages/app/src/components/Page.jsx

@@ -20,7 +20,9 @@ import mdu from './PageEditor/MarkdownDrawioUtil';
 import { getOptionsToSave } from '~/client/util/editor';
 
 // TODO: remove this when omitting unstated is completed
-import { useEditorMode } from '~/stores/ui';
+import {
+  useEditorMode, useSelectedGrant, useSelectedGrantGroupId, useSelectedGrantGroupName,
+} from '~/stores/ui';
 import { useIsSlackEnabled } from '~/stores/editor';
 import { useSlackChannels } from '~/stores/context';
 
@@ -78,9 +80,9 @@ class Page extends React.Component {
 
   async saveHandlerForHandsontableModal(markdownTable) {
     const {
-      isSlackEnabled, slackChannels, pageContainer, editorContainer,
+      isSlackEnabled, slackChannels, pageContainer, editorContainer, grant, grantGroupId, grantGroupName,
     } = this.props;
-    const optionsToSave = getOptionsToSave(isSlackEnabled, slackChannels, editorContainer);
+    const optionsToSave = getOptionsToSave(isSlackEnabled, slackChannels, grant, grantGroupId, grantGroupName, editorContainer);
 
     const newMarkdown = mtu.replaceMarkdownTableInMarkdown(
       markdownTable,
@@ -110,9 +112,9 @@ class Page extends React.Component {
 
   async saveHandlerForDrawioModal(drawioData) {
     const {
-      isSlackEnabled, slackChannels, pageContainer, editorContainer,
+      isSlackEnabled, slackChannels, pageContainer, editorContainer, grant, grantGroupId, grantGroupName,
     } = this.props;
-    const optionsToSave = getOptionsToSave(isSlackEnabled, slackChannels, editorContainer);
+    const optionsToSave = getOptionsToSave(isSlackEnabled, slackChannels, grant, grantGroupId, grantGroupName, editorContainer);
 
     const newMarkdown = mdu.replaceDrawioInMarkdown(
       drawioData,
@@ -173,12 +175,19 @@ Page.propTypes = {
   editorMode: PropTypes.string.isRequired,
   isSlackEnabled: PropTypes.bool.isRequired,
   slackChannels: PropTypes.string.isRequired,
+  grant: PropTypes.number.isRequired,
+  grantGroupId: PropTypes.string,
+  grantGroupName: PropTypes.string,
 };
 
 const PageWrapper = (props) => {
   const { data: editorMode } = useEditorMode();
   const { data: isSlackEnabled } = useIsSlackEnabled();
   const { data: slackChannels } = useSlackChannels();
+  const { data: grant } = useSelectedGrant();
+  const { data: grantGroupId } = useSelectedGrantGroupId();
+  const { data: grantGroupName } = useSelectedGrantGroupName();
+
 
   if (editorMode == null) {
     return null;
@@ -190,6 +199,9 @@ const PageWrapper = (props) => {
       editorMode={editorMode}
       isSlackEnabled={isSlackEnabled}
       slackChannels={slackChannels}
+      grant={grant}
+      grantGroupId={grantGroupId}
+      grantGroupName={grantGroupName}
     />
   );
 };

+ 20 - 5
packages/app/src/components/PageEditor.jsx

@@ -18,7 +18,9 @@ import EditorContainer from '~/client/services/EditorContainer';
 import { getOptionsToSave } from '~/client/util/editor';
 
 // TODO: remove this when omitting unstated is completed
-import { useEditorMode } from '~/stores/ui';
+import {
+  useEditorMode, useSelectedGrant, useSelectedGrantGroupId, useSelectedGrantGroupName,
+} from '~/stores/ui';
 import { useIsEditable, useSlackChannels } from '~/stores/context';
 import { useIsSlackEnabled } from '~/stores/editor';
 
@@ -132,10 +134,10 @@ class PageEditor extends React.Component {
    */
   async onSaveWithShortcut() {
     const {
-      isSlackEnabled, slackChannels, editorContainer, pageContainer,
+      isSlackEnabled, slackChannels, grant, grantGroupId, grantGroupName, editorContainer, pageContainer,
     } = this.props;
 
-    const optionsToSave = getOptionsToSave(isSlackEnabled, slackChannels, editorContainer);
+    const optionsToSave = getOptionsToSave(isSlackEnabled, slackChannels, grant, grantGroupId, grantGroupName, editorContainer);
 
     try {
       // disable unsaved warning
@@ -161,7 +163,9 @@ class PageEditor extends React.Component {
    * @param {any} file
    */
   async onUpload(file) {
-    const { appContainer, pageContainer, editorContainer } = this.props;
+    const {
+      appContainer, pageContainer, mutateGrant,
+    } = this.props;
 
     try {
       let res = await appContainer.apiGet('/attachments.limit', {
@@ -197,7 +201,7 @@ class PageEditor extends React.Component {
       if (res.pageCreated) {
         logger.info('Page is created', res.page._id);
         pageContainer.updateStateAfterSave(res.page, res.tags, res.revision, this.props.editorMode);
-        editorContainer.setState({ grant: res.page.grant });
+        mutateGrant(res.page.grant);
       }
     }
     catch (e) {
@@ -368,6 +372,9 @@ const PageEditorWrapper = (props) => {
   const { data: editorMode } = useEditorMode();
   const { data: isSlackEnabled } = useIsSlackEnabled();
   const { data: slackChannels } = useSlackChannels();
+  const { data: grant, mutate: mutateGrant } = useSelectedGrant();
+  const { data: grantGroupId } = useSelectedGrantGroupId();
+  const { data: grantGroupName } = useSelectedGrantGroupName();
 
   if (isEditable == null || editorMode == null) {
     return null;
@@ -380,6 +387,10 @@ const PageEditorWrapper = (props) => {
       editorMode={editorMode}
       isSlackEnabled={isSlackEnabled}
       slackChannels={slackChannels}
+      grant={grant}
+      grantGroupId={grantGroupId}
+      grantGroupName={grantGroupName}
+      mutateGrant={mutateGrant}
     />
   );
 };
@@ -395,6 +406,10 @@ PageEditor.propTypes = {
   editorMode: PropTypes.string.isRequired,
   isSlackEnabled: PropTypes.bool.isRequired,
   slackChannels: PropTypes.string.isRequired,
+  grant: PropTypes.number.isRequired,
+  grantGroupId: PropTypes.string,
+  grantGroupName: PropTypes.string,
+  mutateGrant: PropTypes.func,
 };
 
 export default PageEditorWrapper;

+ 14 - 3
packages/app/src/components/PageEditorByHackmd.jsx

@@ -14,7 +14,9 @@ import HackmdEditor from './PageEditorByHackmd/HackmdEditor';
 import { getOptionsToSave } from '~/client/util/editor';
 
 // TODO: remove this when omitting unstated is completed
-import { useEditorMode } from '~/stores/ui';
+import {
+  useEditorMode, useSelectedGrant, useSelectedGrantGroupId, useSelectedGrantGroupName,
+} from '~/stores/ui';
 import { useSlackChannels } from '~/stores/context';
 import { useIsSlackEnabled } from '~/stores/editor';
 
@@ -171,9 +173,9 @@ class PageEditorByHackmd extends React.Component {
    */
   async onSaveWithShortcut(markdown) {
     const {
-      isSlackEnabled, slackChannels, pageContainer, editorContainer,
+      isSlackEnabled, slackChannels, pageContainer, editorContainer, grant, grantGroupId, grantGroupName,
     } = this.props;
-    const optionsToSave = getOptionsToSave(isSlackEnabled, slackChannels, editorContainer);
+    const optionsToSave = getOptionsToSave(isSlackEnabled, slackChannels, grant, grantGroupId, grantGroupName, editorContainer);
 
     try {
       // disable unsaved warning
@@ -432,6 +434,9 @@ const PageEditorByHackmdWrapper = (props) => {
   const { data: editorMode } = useEditorMode();
   const { data: isSlackEnabled } = useIsSlackEnabled();
   const { data: slackChannels } = useSlackChannels();
+  const { data: grant } = useSelectedGrant();
+  const { data: grantGroupId } = useSelectedGrantGroupId();
+  const { data: grantGroupName } = useSelectedGrantGroupName();
 
   if (editorMode == null) {
     return null;
@@ -443,6 +448,9 @@ const PageEditorByHackmdWrapper = (props) => {
       editorMode={editorMode}
       isSlackEnabled={isSlackEnabled}
       slackChannels={slackChannels}
+      grant={grant}
+      grantGroupId={grantGroupId}
+      grantGroupName={grantGroupName}
     />
   );
 };
@@ -458,6 +466,9 @@ PageEditorByHackmd.propTypes = {
   editorMode: PropTypes.string.isRequired,
   isSlackEnabled: PropTypes.bool.isRequired,
   slackChannels: PropTypes.string.isRequired,
+  grant: PropTypes.number.isRequired,
+  grantGroupId: PropTypes.string,
+  grantGroupName: PropTypes.string,
 };
 
 export default withTranslation()(PageEditorByHackmdWrapper);

+ 34 - 10
packages/app/src/components/SavePageControls.jsx

@@ -20,7 +20,9 @@ import GrantSelector from './SavePageControls/GrantSelector';
 import { getOptionsToSave } from '~/client/util/editor';
 
 // TODO: remove this when omitting unstated is completed
-import { useEditorMode } from '~/stores/ui';
+import {
+  useEditorMode, useSelectedGrant, useSelectedGrantGroupId, useSelectedGrantGroupName,
+} from '~/stores/ui';
 import { useIsEditable, useSlackChannels } from '~/stores/context';
 import { useIsSlackEnabled } from '~/stores/editor';
 
@@ -42,19 +44,23 @@ class SavePageControls extends React.Component {
   }
 
   updateGrantHandler(data) {
-    this.props.editorContainer.setState(data);
+    const { mutateGrant, mutateGrantGroupId, mutateGrantGroupName } = this.props;
+
+    mutateGrant(data.grant);
+    mutateGrantGroupId(data.grantGroupId);
+    mutateGrantGroupName(data.grantGroupName);
   }
 
   async save() {
     const {
-      isSlackEnabled, slackChannels, pageContainer, editorContainer,
+      isSlackEnabled, slackChannels, grant, grantGroupId, grantGroupName, pageContainer, editorContainer,
     } = this.props;
     // disable unsaved warning
     editorContainer.disableUnsavedWarning();
 
     try {
       // save
-      const optionsToSave = getOptionsToSave(isSlackEnabled, slackChannels, editorContainer);
+      const optionsToSave = getOptionsToSave(isSlackEnabled, slackChannels, grant, grantGroupId, grantGroupName, editorContainer);
       await pageContainer.saveAndReload(optionsToSave, this.props.editorMode);
     }
     catch (error) {
@@ -65,12 +71,12 @@ class SavePageControls extends React.Component {
 
   saveAndOverwriteScopesOfDescendants() {
     const {
-      isSlackEnabled, slackChannels, pageContainer, editorContainer,
+      isSlackEnabled, slackChannels, grant, grantGroupId, grantGroupName, pageContainer, editorContainer,
     } = this.props;
     // disable unsaved warning
     editorContainer.disableUnsavedWarning();
     // save
-    const currentOptionsToSave = getOptionsToSave(isSlackEnabled, slackChannels, editorContainer);
+    const currentOptionsToSave = getOptionsToSave(isSlackEnabled, slackChannels, grant, grantGroupId, grantGroupName, editorContainer);
     const optionsToSave = Object.assign(currentOptionsToSave, {
       overwriteScopesOfDescendants: true,
     });
@@ -79,7 +85,9 @@ class SavePageControls extends React.Component {
 
   render() {
 
-    const { t, pageContainer, editorContainer } = this.props;
+    const {
+      t, pageContainer, grant, grantGroupId, grantGroupName,
+    } = this.props;
 
     const isRootPage = pageContainer.state.path === '/';
     const labelSubmitButton = pageContainer.state.pageId == null ? t('Create') : t('Update');
@@ -93,9 +101,9 @@ class SavePageControls extends React.Component {
             <div className="mr-2">
               <GrantSelector
                 disabled={isRootPage}
-                grant={editorContainer.state.grant}
-                grantGroupId={editorContainer.state.grantGroupId}
-                grantGroupName={editorContainer.state.grantGroupName}
+                grant={grant}
+                grantGroupId={grantGroupId}
+                grantGroupName={grantGroupName}
                 onUpdateGrant={this.updateGrantHandler}
               />
             </div>
@@ -128,6 +136,10 @@ const SavePageControlsWrapper = (props) => {
   const { data: editorMode } = useEditorMode();
   const { data: isSlackEnabled } = useIsSlackEnabled();
   const { data: slackChannels } = useSlackChannels();
+  const { data: grant, mutate: mutateGrant } = useSelectedGrant();
+  const { data: grantGroupId, mutate: mutateGrantGroupId } = useSelectedGrantGroupId();
+  const { data: grantGroupName, mutate: mutateGrantGroupName } = useSelectedGrantGroupName();
+
 
   if (isEditable == null || editorMode == null) {
     return null;
@@ -143,6 +155,12 @@ const SavePageControlsWrapper = (props) => {
       editorMode={editorMode}
       isSlackEnabled={isSlackEnabled}
       slackChannels={slackChannels}
+      grant={grant}
+      grantGroupId={grantGroupId}
+      grantGroupName={grantGroupName}
+      mutateGrant={mutateGrant}
+      mutateGrantGroupId={mutateGrantGroupId}
+      mutateGrantGroupName={mutateGrantGroupName}
     />
   );
 };
@@ -158,6 +176,12 @@ SavePageControls.propTypes = {
   editorMode: PropTypes.string.isRequired,
   isSlackEnabled: PropTypes.bool.isRequired,
   slackChannels: PropTypes.string.isRequired,
+  grant: PropTypes.number.isRequired,
+  grantGroupId: PropTypes.string,
+  grantGroupName: PropTypes.string,
+  mutateGrant: PropTypes.func,
+  mutateGrantGroupId: PropTypes.func,
+  mutateGrantGroupName: PropTypes.func,
 };
 
 export default withTranslation()(SavePageControlsWrapper);

+ 16 - 4
packages/app/src/stores/ui.tsx

@@ -17,6 +17,8 @@ const logger = loggerFactory('growi:stores:ui');
 
 const isServer = typeof window === 'undefined';
 
+type Nullable<T> = T | null;
+
 
 /** **********************************************************
  *                          Unions
@@ -218,9 +220,19 @@ export const usePageCreateModalOpened = (isOpened?: boolean): SWRResponse<boolea
   return useStaticSWR('isPageCreateModalOpened', isOpened || null, { fallbackData: initialData });
 };
 
+
+export const useSelectedGrant = (initialData?: Nullable<number>): SWRResponse<Nullable<number>, Error> => {
+  return useStaticSWR<Nullable<number>, Error>('grant', initialData ?? null);
+};
+
+export const useSelectedGrantGroupId = (initialData?: Nullable<string>): SWRResponse<Nullable<string>, Error> => {
+  return useStaticSWR<Nullable<string>, Error>('grantGroupId', initialData ?? null);
+};
+
+export const useSelectedGrantGroupName = (initialData?: Nullable<string>): SWRResponse<Nullable<string>, Error> => {
+  return useStaticSWR<Nullable<string>, Error>('grantGroupName', initialData ?? null);
+};
+
 export const useGlobalSearchFormRef = (initialData?: RefObject<IFocusable>): SWRResponse<RefObject<IFocusable>, Error> => {
-  return useStaticSWR(
-    'globalSearchTypeahead',
-    initialData ?? null,
-  );
+  return useStaticSWR('globalSearchTypeahead', initialData ?? null);
 };