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

Merge branch 'master' into imprv/load-template-plugins-on-server-2

Yuki Takei 2 лет назад
Родитель
Сommit
8f8b278223

+ 4 - 1
apps/app/src/components/Admin/UserGroup/UserGroupForm.tsx

@@ -45,6 +45,9 @@ export const UserGroupForm: FC<Props> = (props: Props) => {
 
   const isSelectableParentUserGroups = selectableParentUserGroups != null && selectableParentUserGroups.length > 0;
 
+  const isChildUserGroup = parentUserGroup !== undefined;
+  const messageAtReleaseParentGroup = isChildUserGroup ? t('user_group_management.release_parent_group') : t('user_group_management.select_parent_group');
+
   return (
     <form onSubmit={(e) => {
       e.preventDefault();
@@ -107,7 +110,7 @@ export const UserGroupForm: FC<Props> = (props: Props) => {
                 btn btn-outline-secondary dropdown-toggle mb-3 ${isSelectableParentUserGroups ? '' : 'disabled'}
               `}
             >
-              {selectedParent?.name ?? t('user_group_management.select_parent_group')}
+              {selectedParent?.name ?? messageAtReleaseParentGroup}
             </button>
             <div className="dropdown-menu" aria-labelledby="dropdownMenuButton">
               {

+ 1 - 1
apps/app/src/features/growi-plugin/server/services/growi-plugin/growi-plugin.ts

@@ -78,7 +78,7 @@ export class GrowiPluginService implements IGrowiPluginService {
           }
 
           // TODO: imprv Document version and repository version possibly different.
-          const ghUrl = new GitHubUrl(growiPlugin.origin.url, growiPlugin.origin.branchName);
+          const ghUrl = new GitHubUrl(growiPlugin.origin.url, growiPlugin.origin.ghBranch);
           const { reposName, branchName, archiveUrl } = ghUrl;
 
           const zipFilePath = path.join(pluginStoringPath, `${branchName}.zip`);

+ 29 - 21
apps/app/src/pages/[[...path]].page.tsx

@@ -238,15 +238,39 @@ const Page: NextPageWithLayout<Props> = (props: Props) => {
   useHasDraftOnHackmd(pageWithMeta?.data.hasDraftOnHackmd ?? false);
   useCurrentPathname(props.currentPathname);
 
-  useSWRxCurrentPage(pageWithMeta?.data ?? null); // store initial data
-
+  const { mutate: mutateInitialPage } = useSWRxCurrentPage();
   const { trigger: mutateCurrentPage } = useSWRMUTxCurrentPage();
+  const { mutate: mutateEditingMarkdown } = useEditingMarkdown();
+  const { data: currentPageId, mutate: mutateCurrentPageId } = useCurrentPageId();
 
-  const { mutate: mutateIsNotFound } = useIsNotFound();
+  // Store initial data
+  useEffect(() => {
+    if (!props.skipSSR) {
+      mutateInitialPage(pageWithMeta?.data ?? null);
+    }
+  }, [mutateInitialPage, pageWithMeta, props.skipSSR]);
 
-  const { data: currentPageId, mutate: mutateCurrentPageId } = useCurrentPageId();
+  // Store initial data (When revisionBody is not SSR)
+  useEffect(() => {
+    if (!props.skipSSR) {
+      return;
+    }
+
+    if (currentPageId != null && !props.isNotFound) {
+      const mutatePageData = async() => {
+        const pageData = await mutateCurrentPage();
+        mutateEditingMarkdown(pageData?.revision.body);
+      };
+
+      // If skipSSR is true, use the API to retrieve page data.
+      // Because pageWIthMeta does not contain revision.body
+      mutatePageData();
+    }
+  }, [currentPageId, mutateCurrentPage, mutateEditingMarkdown, props.isNotFound, props.skipSSR]);
+
+
+  const { mutate: mutateIsNotFound } = useIsNotFound();
 
-  const { mutate: mutateEditingMarkdown } = useEditingMarkdown();
   const { mutate: mutateIsLatestRevision } = useIsLatestRevision();
 
   const { data: grantData } = useSWRxIsGrantNormalized(pageId);
@@ -267,22 +291,6 @@ const Page: NextPageWithLayout<Props> = (props: Props) => {
     ? _isTrashPage(pageWithMeta.data.path)
     : false;
 
-
-  useEffect(() => {
-    if (!props.skipSSR) {
-      return;
-    }
-
-    if (currentPageId != null && !props.isNotFound) {
-      const mutatePageData = async() => {
-        const pageData = await mutateCurrentPage();
-        mutateEditingMarkdown(pageData?.revision.body);
-      };
-
-      mutatePageData();
-    }
-  }, [currentPageId, mutateCurrentPage, mutateEditingMarkdown, props.isNotFound, props.skipSSR]);
-
   // sync grant data
   useEffect(() => {
     const grantDataToApply = props.grantData ? props.grantData : grantData?.grantData.currentPageGrant;

+ 1 - 1
apps/app/src/server/routes/apiv3/bookmark-folder.ts

@@ -85,7 +85,7 @@ module.exports = (crowi) => {
               model: 'User',
             },
           },
-        }).exec();
+        }).exec() as never as BookmarkFolderItems[];
 
       const returnValue: BookmarkFolderItems[] = [];
 

+ 1 - 1
apps/app/src/server/routes/apiv3/users.js

@@ -189,7 +189,7 @@ module.exports = (crowi) => {
     await mailService.send({
       to: user.email,
       subject: `New password for ${appTitle}`,
-      template: path.join(crowi.localeDir, 'en_US/admin/userResetPassword.txt'),
+      template: path.join(crowi.localeDir, 'en_US/admin/userResetPassword.ejs'),
       vars: {
         email: user.email,
         password: user.password,

+ 1 - 1
apps/app/src/server/util/mongoose-utils.ts

@@ -26,7 +26,7 @@ export const getModelSafely = <T>(modelName: string): Model<T & Document> | null
 };
 
 // TODO: Do not use any type
-export const getOrCreateModel = <Interface, Method>(modelName: string, schema: any): any => {
+export const getOrCreateModel = <Interface, Method>(modelName: string, schema: any): Method & Model<Interface & Document> => {
   if (mongoose.modelNames().includes(modelName)) {
     return mongoose.model<Interface & Document, Method & Model<Interface & Document>>(modelName);
   }

+ 6 - 0
apps/app/test/cypress/e2e/23-editor/23-editor--with-navigation.cy.ts

@@ -65,10 +65,16 @@ context('Editor while uploading to a new page', () => {
     cy.screenshot(`${ssPrefix}-prevent-grantselector-modified-2`);
 
     // drag-drop a file
+    cy.intercept('POST', '/_api/attachments.add').as('attachmentsAdd');
     const filePath = path.relative('/', path.resolve(Cypress.spec.relative, '../assets/example.txt'));
     cy.get('.dropzone').selectFile(filePath, { action: 'drag-drop' });
+    cy.wait('@attachmentsAdd')
+
+    // Update page using shortcut keys
+    cy.get('.CodeMirror').type('{ctrl+s}');
 
     // expect
+    cy.get('.Toastify__toast').should('contain.text', 'Saved successfully');
     cy.get('.CodeMirror').should('contain.text', body);
     cy.get('.CodeMirror').should('contain.text', '[example.txt](/attachment/');
     cy.getByTestid('grw-grant-selector').find('.dropdown-toggle').should('contain.text', 'Only me');