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

Merge branch 'support/apply-nextjs-2' into support/apply-nextjs-PageComment-integrate

jam411 3 лет назад
Родитель
Сommit
c45e727c35
34 измененных файлов с 306 добавлено и 244 удалено
  1. 11 0
      packages/app/src/components/Admin/NotFoundPage.tsx
  2. 1 3
      packages/app/src/components/Admin/UserGroup/UserGroupDeleteModal.tsx
  3. 2 3
      packages/app/src/components/Admin/UserGroup/UserGroupDropdown.tsx
  4. 1 3
      packages/app/src/components/Admin/UserGroup/UserGroupForm.tsx
  5. 1 3
      packages/app/src/components/Admin/UserGroup/UserGroupModal.tsx
  6. 5 7
      packages/app/src/components/Admin/UserGroup/UserGroupPage.tsx
  7. 1 3
      packages/app/src/components/Admin/UserGroup/UserGroupTable.tsx
  8. 2 3
      packages/app/src/components/Admin/UserGroupDetail/UpdateParentConfirmModal.tsx
  9. 68 44
      packages/app/src/components/Admin/UserGroupDetail/UserGroupDetailPage.tsx
  10. 2 4
      packages/app/src/components/Admin/UserGroupDetail/UserGroupUserFormByInput.jsx
  11. 2 4
      packages/app/src/components/Admin/UserGroupDetail/UserGroupUserModal.jsx
  12. 1 3
      packages/app/src/components/Admin/UserGroupDetail/UserGroupUserTable.jsx
  13. 1 1
      packages/app/src/components/InstallerForm.jsx
  14. 3 1
      packages/app/src/components/Layout/AdminLayout.tsx
  15. 14 0
      packages/app/src/components/Layout/Invited.module.scss
  16. 27 0
      packages/app/src/components/Layout/Login.module.scss
  17. 21 62
      packages/app/src/components/Layout/NoLoginLayout.module.scss
  18. 48 0
      packages/app/src/components/Layout/NoLoginLayout.tsx
  19. 1 1
      packages/app/src/components/Layout/RawLayout.tsx
  20. 1 1
      packages/app/src/components/LoginForm.jsx
  21. 22 17
      packages/app/src/components/Me/BasicInfoSettings.tsx
  22. 2 2
      packages/app/src/components/Theme/ThemeChristmas.module.scss
  23. 4 4
      packages/app/src/components/Theme/ThemeHufflepuff.module.scss
  24. 2 2
      packages/app/src/components/Theme/ThemeSpring.module.scss
  25. 2 2
      packages/app/src/components/Theme/ThemeWood.module.scss
  26. 27 13
      packages/app/src/pages/admin/[[...path]].page.tsx
  27. 7 30
      packages/app/src/pages/installer.page.tsx
  28. 8 15
      packages/app/src/pages/login.page.tsx
  29. 4 2
      packages/app/src/pages/me.page.tsx
  30. 7 4
      packages/app/src/server/routes/admin.js
  31. 3 2
      packages/app/src/server/views/admin/not_found.html
  32. 1 1
      packages/app/src/styles/style-next.scss
  33. 2 2
      packages/app/src/styles/theme/_apply-colors-dark.scss
  34. 2 2
      packages/app/src/styles/theme/_apply-colors-light.scss

+ 11 - 0
packages/app/src/components/Admin/NotFoundPage.tsx

@@ -0,0 +1,11 @@
+import React from 'react';
+
+import { useTranslation } from 'next-i18next';
+
+export const AdminNotFoundPage = (): JSX.Element => {
+  const { t } = useTranslation();
+
+  return (
+    <h1 className="title">{t('not_found_page.page_not_exist')}</h1>
+  );
+};

+ 1 - 3
packages/app/src/components/Admin/UserGroup/UserGroupDeleteModal.tsx

@@ -40,7 +40,7 @@ const actionForPages = {
   transfer: 'transfer',
 };
 
-const UserGroupDeleteModal: FC<Props> = (props: Props) => {
+export const UserGroupDeleteModal: FC<Props> = (props: Props) => {
 
   const { t } = useTranslation();
 
@@ -209,5 +209,3 @@ const UserGroupDeleteModal: FC<Props> = (props: Props) => {
     </Modal>
   );
 };
-
-export default UserGroupDeleteModal;

+ 2 - 3
packages/app/src/components/Admin/UserGroup/UserGroupDropdown.tsx

@@ -1,4 +1,5 @@
 import React, { FC, useCallback } from 'react';
+
 import { useTranslation } from 'next-i18next';
 
 import { IUserGroupHasId } from '~/interfaces/user';
@@ -9,7 +10,7 @@ type Props = {
   onClickCreateUserGroupButton?(): void
 };
 
-const UserGroupDropdown: FC<Props> = (props: Props) => {
+export const UserGroupDropdown: FC<Props> = (props: Props) => {
   const { t } = useTranslation();
 
   const { selectableUserGroups, onClickAddExistingUserGroupButton, onClickCreateUserGroupButton } = props;
@@ -66,5 +67,3 @@ const UserGroupDropdown: FC<Props> = (props: Props) => {
     </>
   );
 };
-
-export default UserGroupDropdown;

+ 1 - 3
packages/app/src/components/Admin/UserGroup/UserGroupForm.tsx

@@ -13,7 +13,7 @@ type Props = {
   onSubmit?: (targetGroup: IUserGroupHasId, userGroupData: Partial<IUserGroupHasId>) => Promise<void> | void
 };
 
-const UserGroupForm: FC<Props> = (props: Props) => {
+export const UserGroupForm: FC<Props> = (props: Props) => {
 
   const { t } = useTranslation();
 
@@ -152,5 +152,3 @@ const UserGroupForm: FC<Props> = (props: Props) => {
     </form>
   );
 };
-
-export default UserGroupForm;

+ 1 - 3
packages/app/src/components/Admin/UserGroup/UserGroupModal.tsx

@@ -19,7 +19,7 @@ type Props = {
   onHide?: () => Promise<void> | void
 };
 
-const UserGroupModal: FC<Props> = (props: Props) => {
+export const UserGroupModal: FC<Props> = (props: Props) => {
 
   const { t } = useTranslation();
 
@@ -116,5 +116,3 @@ const UserGroupModal: FC<Props> = (props: Props) => {
     </Modal>
   );
 };
-
-export default UserGroupModal;

+ 5 - 7
packages/app/src/components/Admin/UserGroup/UserGroupPage.tsx

@@ -1,19 +1,19 @@
 import React, { FC, useState, useCallback } from 'react';
 
+import dynamic from 'next/dynamic';
 import { useTranslation } from 'react-i18next';
 
-
 import { toastSuccess, toastError } from '~/client/util/apiNotification';
 import { apiv3Delete, apiv3Post, apiv3Put } from '~/client/util/apiv3-client';
 import { IUserGroup, IUserGroupHasId } from '~/interfaces/user';
 import { useIsAclEnabled } from '~/stores/context';
 import { useSWRxUserGroupList, useSWRxChildUserGroupList, useSWRxUserGroupRelationList } from '~/stores/user-group';
 
-import UserGroupDeleteModal from './UserGroupDeleteModal';
-import UserGroupModal from './UserGroupModal';
-import UserGroupTable from './UserGroupTable';
+const UserGroupDeleteModal = dynamic(() => import('./UserGroupDeleteModal').then(mod => mod.UserGroupDeleteModal), { ssr: false });
+const UserGroupModal = dynamic(() => import('./UserGroupModal').then(mod => mod.UserGroupModal), { ssr: false });
+const UserGroupTable = dynamic(() => import('./UserGroupTable').then(mod => mod.UserGroupTable), { ssr: false });
 
-const UserGroupPage: FC = () => {
+export const UserGroupPage: FC = () => {
   const { t } = useTranslation();
 
   const { data: isAclEnabled } = useIsAclEnabled();
@@ -193,5 +193,3 @@ const UserGroupPage: FC = () => {
     </div>
   );
 };
-
-export default UserGroupPage;

+ 1 - 3
packages/app/src/components/Admin/UserGroup/UserGroupTable.tsx

@@ -53,7 +53,7 @@ const generateGroupIdToChildGroupsMap = (childUserGroups: IUserGroupHasId[]): Re
 };
 
 
-const UserGroupTable: FC<Props> = (props: Props) => {
+export const UserGroupTable: FC<Props> = (props: Props) => {
   const { t } = useTranslation();
 
   /*
@@ -219,5 +219,3 @@ const UserGroupTable: FC<Props> = (props: Props) => {
     </>
   );
 };
-
-export default UserGroupTable;

+ 2 - 3
packages/app/src/components/Admin/UserGroupDetail/UpdateParentConfirmModal.tsx

@@ -1,4 +1,5 @@
 import React, { FC, useState } from 'react';
+
 import { useTranslation } from 'next-i18next';
 import {
   Modal, ModalHeader, ModalBody, ModalFooter,
@@ -7,7 +8,7 @@ import {
 import { useUpdateUserGroupConfirmModal } from '~/stores/modal';
 
 
-const UpdateParentConfirmModal: FC = () => {
+export const UpdateParentConfirmModal: FC = () => {
   const { t } = useTranslation();
 
   const [isForceUpdate, setForceUpdate] = useState(false);
@@ -88,5 +89,3 @@ const UpdateParentConfirmModal: FC = () => {
     </Modal>
   );
 };
-
-export default UpdateParentConfirmModal;

+ 68 - 44
packages/app/src/components/Admin/UserGroupDetail/UserGroupDetailPage.tsx

@@ -1,41 +1,50 @@
 import React, {
-  FC, useState, useCallback,
+  FC, useState, useCallback, useEffect,
 } from 'react';
-import { useTranslation } from 'next-i18next';
 
-import UserGroupForm from '../UserGroup/UserGroupForm';
-import UserGroupTable from '../UserGroup/UserGroupTable';
-import UserGroupModal from '../UserGroup/UserGroupModal';
-import UserGroupDeleteModal from '../UserGroup/UserGroupDeleteModal';
-import UpdateParentConfirmModal from './UpdateParentConfirmModal';
-import UserGroupDropdown from '../UserGroup/UserGroupDropdown';
-import UserGroupUserTable from './UserGroupUserTable';
-import UserGroupUserModal from './UserGroupUserModal';
-import UserGroupPageList from './UserGroupPageList';
+import { useTranslation } from 'next-i18next';
+import dynamic from 'next/dynamic';
+import { useRouter } from 'next/router';
 
+import { toastSuccess, toastError } from '~/client/util/apiNotification';
 import {
   apiv3Get, apiv3Put, apiv3Delete, apiv3Post,
 } from '~/client/util/apiv3-client';
-import { toastSuccess, toastError } from '~/client/util/apiNotification';
 import { IPageHasId } from '~/interfaces/page';
+import { IUserGroup, IUserGroupHasId } from '~/interfaces/user';
+import { useIsAclEnabled } from '~/stores/context';
+import { useUpdateUserGroupConfirmModal } from '~/stores/modal';
 import {
-  IUserGroup, IUserGroupHasId,
-} from '~/interfaces/user';
-import {
-  useSWRxUserGroupPages, useSWRxUserGroupRelationList, useSWRxChildUserGroupList,
+  useSWRxUserGroupPages, useSWRxUserGroupRelationList, useSWRxChildUserGroupList, useSWRxUserGroup,
   useSWRxSelectableParentUserGroups, useSWRxSelectableChildUserGroups, useSWRxAncestorUserGroups,
 } from '~/stores/user-group';
-import { useIsAclEnabled } from '~/stores/context';
-import { useUpdateUserGroupConfirmModal } from '~/stores/modal';
 
-const UserGroupDetailPage: FC = () => {
+import { isValidObjectId } from '../../../../../core/src/utils/objectid-utils';
+
+const UserGroupDeleteModal = dynamic(() => import('../UserGroup/UserGroupDeleteModal').then(mod => mod.UserGroupDeleteModal), { ssr: false });
+const UserGroupDropdown = dynamic(() => import('../UserGroup/UserGroupDropdown').then(mod => mod.UserGroupDropdown), { ssr: false });
+const UserGroupForm = dynamic(() => import('../UserGroup/UserGroupForm').then(mod => mod.UserGroupForm), { ssr: false });
+const UserGroupModal = dynamic(() => import('../UserGroup/UserGroupModal').then(mod => mod.UserGroupModal), { ssr: false });
+const UserGroupTable = dynamic(() => import('../UserGroup/UserGroupTable').then(mod => mod.UserGroupTable), { ssr: false });
+const UpdateParentConfirmModal = dynamic(() => import('./UpdateParentConfirmModal').then(mod => mod.UpdateParentConfirmModal), { ssr: false });
+// import UserGroupPageList from './UserGroupPageList';
+// import UserGroupUserModal from './UserGroupUserModal';
+// import UserGroupUserTable from './UserGroupUserTable';
+
+
+type Props = {
+  userGroupId?: string,
+}
+
+const UserGroupDetailPage = (props: Props) => {
   const { t } = useTranslation();
-  const adminUserGroupDetailElem = document.getElementById('admin-user-group-detail');
+  const router = useRouter();
+  const { userGroupId: currentUserGroupId } = props;
 
   /*
    * State (from AdminUserGroupDetailContainer)
    */
-  const [currentUserGroup, setUserGroup] = useState<IUserGroupHasId>(JSON.parse(adminUserGroupDetailElem?.getAttribute('data-user-group') || 'null'));
+  const { data: currentUserGroup } = useSWRxUserGroup(currentUserGroupId);
   const [relatedPages, setRelatedPages] = useState<IPageHasId[]>([]); // For page list
   const [searchType, setSearchType] = useState<string>('partial');
   const [isAlsoMailSearched, setAlsoMailSearched] = useState<boolean>(false);
@@ -45,12 +54,23 @@ const UserGroupDetailPage: FC = () => {
   const [isUpdateModalShown, setUpdateModalShown] = useState<boolean>(false);
   const [isDeleteModalShown, setDeleteModalShown] = useState<boolean>(false);
 
+  const isLoading = currentUserGroup === undefined;
+  const notExistsUerGroup = !isLoading && currentUserGroup == null;
+
+  useEffect(() => {
+    if (!isValidObjectId(currentUserGroupId) || notExistsUerGroup) {
+      router.push('/admin/user-groups');
+    }
+  }, [currentUserGroup, currentUserGroupId, notExistsUerGroup, router]);
+
+
   /*
    * Fetch
    */
-  const { data: userGroupPages } = useSWRxUserGroupPages(currentUserGroup._id, 10, 0);
+  const { data: userGroupPages } = useSWRxUserGroupPages(currentUserGroupId, 10, 0);
+
 
-  const { data: childUserGroupsList, mutate: mutateChildUserGroups } = useSWRxChildUserGroupList([currentUserGroup._id], true);
+  const { data: childUserGroupsList, mutate: mutateChildUserGroups } = useSWRxChildUserGroupList(currentUserGroupId ? [currentUserGroupId] : [], true);
   const childUserGroups = childUserGroupsList != null ? childUserGroupsList.childUserGroups : [];
   const grandChildUserGroups = childUserGroupsList != null ? childUserGroupsList.grandChildUserGroups : [];
   const childUserGroupIds = childUserGroups.map(group => group._id);
@@ -58,15 +78,16 @@ const UserGroupDetailPage: FC = () => {
   const { data: userGroupRelationList, mutate: mutateUserGroupRelations } = useSWRxUserGroupRelationList(childUserGroupIds);
   const childUserGroupRelations = userGroupRelationList != null ? userGroupRelationList : [];
 
-  const { data: selectableParentUserGroups, mutate: mutateSelectableParentUserGroups } = useSWRxSelectableParentUserGroups(currentUserGroup._id);
-  const { data: selectableChildUserGroups, mutate: mutateSelectableChildUserGroups } = useSWRxSelectableChildUserGroups(currentUserGroup._id);
+  const { data: selectableParentUserGroups, mutate: mutateSelectableParentUserGroups } = useSWRxSelectableParentUserGroups(currentUserGroupId);
+  const { data: selectableChildUserGroups, mutate: mutateSelectableChildUserGroups } = useSWRxSelectableChildUserGroups(currentUserGroupId);
 
-  const { data: ancestorUserGroups, mutate: mutateAncestorUserGroups } = useSWRxAncestorUserGroups(currentUserGroup._id);
+  const { data: ancestorUserGroups, mutate: mutateAncestorUserGroups } = useSWRxAncestorUserGroups(currentUserGroupId);
 
   const { data: isAclEnabled } = useIsAclEnabled();
 
   const { open: openUpdateParentConfirmModal } = useUpdateUserGroupConfirmModal();
 
+
   /*
    * Function
    */
@@ -98,13 +119,11 @@ const UserGroupDetailPage: FC = () => {
     });
     const { userGroup: updatedUserGroup } = res.data;
 
-    setUserGroup(updatedUserGroup);
-
     // mutate
     mutateAncestorUserGroups();
     mutateSelectableChildUserGroups();
     mutateSelectableParentUserGroups();
-  }, [setUserGroup, mutateAncestorUserGroups, mutateSelectableChildUserGroups, mutateSelectableParentUserGroups]);
+  }, [mutateAncestorUserGroups, mutateSelectableChildUserGroups, mutateSelectableParentUserGroups]);
 
   const onSubmitUpdateGroup = useCallback(
     async(targetGroup: IUserGroupHasId, userGroupData: Partial<IUserGroupHasId>, forceUpdateParents: boolean): Promise<void> => {
@@ -143,7 +162,7 @@ const UserGroupDetailPage: FC = () => {
   }, [t, openUpdateParentConfirmModal, onSubmitUpdateGroup]);
 
   const fetchApplicableUsers = useCallback(async(searchWord) => {
-    const res = await apiv3Get(`/user-groups/${currentUserGroup._id}/unrelated-users`, {
+    const res = await apiv3Get(`/user-groups/${currentUserGroupId}/unrelated-users`, {
       searchWord,
       searchType,
       isAlsoMailSearched,
@@ -153,18 +172,18 @@ const UserGroupDetailPage: FC = () => {
     const { users } = res.data;
 
     return users;
-  }, [searchType, isAlsoMailSearched, isAlsoNameSearched]);
+  }, [currentUserGroupId, searchType, isAlsoMailSearched, isAlsoNameSearched]);
 
   // TODO 85062: will be used in UserGroupUserFormByInput
   const addUserByUsername = useCallback(async(username: string) => {
-    await apiv3Post(`/user-groups/${currentUserGroup._id}/users/${username}`);
+    await apiv3Post(`/user-groups/${currentUserGroupId}/users/${username}`);
     mutateUserGroupRelations();
-  }, [currentUserGroup, mutateUserGroupRelations]);
+  }, [currentUserGroupId, mutateUserGroupRelations]);
 
   const removeUserByUsername = useCallback(async(username: string) => {
-    await apiv3Delete(`/user-groups/${currentUserGroup._id}/users/${username}`);
+    await apiv3Delete(`/user-groups/${currentUserGroupId}/users/${username}`);
     mutateUserGroupRelations();
-  }, [currentUserGroup, mutateUserGroupRelations]);
+  }, [currentUserGroupId, mutateUserGroupRelations]);
 
   const showUpdateModal = useCallback((group: IUserGroupHasId) => {
     setUpdateModalShown(true);
@@ -201,11 +220,11 @@ const UserGroupDetailPage: FC = () => {
     await openUpdateParentConfirmModal(
       selectedChild,
       {
-        parent: currentUserGroup._id,
+        parent: currentUserGroupId,
       },
       onSubmitUpdateGroup,
     );
-  }, [openUpdateParentConfirmModal, onSubmitUpdateGroup, currentUserGroup]);
+  }, [openUpdateParentConfirmModal, currentUserGroupId, onSubmitUpdateGroup]);
 
   const showCreateModal = useCallback(() => {
     setCreateModalShown(true);
@@ -220,7 +239,7 @@ const UserGroupDetailPage: FC = () => {
       await apiv3Post('/user-groups', {
         name: userGroupData.name,
         description: userGroupData.description,
-        parentId: currentUserGroup._id,
+        parentId: currentUserGroupId,
       });
 
       toastSuccess(t('toaster.update_successed', { target: t('UserGroup') }));
@@ -235,7 +254,7 @@ const UserGroupDetailPage: FC = () => {
     catch (err) {
       toastError(err);
     }
-  }, [t, currentUserGroup, mutateChildUserGroups, mutateSelectableChildUserGroups, mutateSelectableParentUserGroups, hideCreateModal]);
+  }, [currentUserGroupId, t, mutateChildUserGroups, mutateSelectableChildUserGroups, mutateSelectableParentUserGroups, hideCreateModal]);
 
   const showDeleteModal = useCallback(async(group: IUserGroupHasId) => {
     setSelectedUserGroup(group);
@@ -303,8 +322,8 @@ const UserGroupDetailPage: FC = () => {
             ancestorUserGroups != null && ancestorUserGroups.length > 0 && (
               ancestorUserGroups.map((ancestorUserGroup: IUserGroupHasId) => (
                 // eslint-disable-next-line max-len
-                <li key={ancestorUserGroup._id} className={`breadcrumb-item ${ancestorUserGroup._id === currentUserGroup._id ? 'active' : ''}`} aria-current="page">
-                  { ancestorUserGroup._id === currentUserGroup._id ? (
+                <li key={ancestorUserGroup._id} className={`breadcrumb-item ${ancestorUserGroup._id === currentUserGroupId ? 'active' : ''}`} aria-current="page">
+                  { ancestorUserGroup._id === currentUserGroupId ? (
                     <>{ancestorUserGroup.name}</>
                   ) : (
                     <a href={`/admin/user-group-detail/${ancestorUserGroup._id}`}>{ancestorUserGroup.name}</a>
@@ -325,8 +344,11 @@ const UserGroupDetailPage: FC = () => {
         />
       </div>
       <h2 className="admin-setting-header mt-4">{t('admin:user_group_management.user_list')}</h2>
-      <UserGroupUserTable />
-      <UserGroupUserModal />
+      {/* These compoents will be successfully shown in https://redmine.weseek.co.jp/issues/102159 */}
+      {/* <UserGroupUserTable /> */}
+      UserGroupUserTable
+      {/* <UserGroupUserModal /> */}
+      UserGroupUserModal
 
       <h2 className="admin-setting-header mt-4">{t('admin:user_group_management.child_group_list')}</h2>
       <UserGroupDropdown
@@ -372,7 +394,9 @@ const UserGroupDetailPage: FC = () => {
 
       <h2 className="admin-setting-header mt-4">{t('Page')}</h2>
       <div className="page-list">
-        <UserGroupPageList />
+        {/* This compoent will be successfully shown in https://redmine.weseek.co.jp/issues/102159 */}
+        {/* <UserGroupPageList /> */}
+        UserGroupPageList
       </div>
     </div>
   );

+ 2 - 4
packages/app/src/components/Admin/UserGroupDetail/UserGroupUserFormByInput.jsx

@@ -1,13 +1,12 @@
 import React from 'react';
 
 import { UserPicture } from '@growi/ui';
+import { useTranslation } from 'next-i18next';
 import PropTypes from 'prop-types';
 import { AsyncTypeahead } from 'react-bootstrap-typeahead';
-import { useTranslation } from 'next-i18next';
 import { debounce } from 'throttle-debounce';
 
 import AdminUserGroupDetailContainer from '~/client/services/AdminUserGroupDetailContainer';
-import AppContainer from '~/client/services/AppContainer';
 import { toastSuccess, toastError } from '~/client/util/apiNotification';
 import Xss from '~/services/xss';
 
@@ -162,7 +161,6 @@ class UserGroupUserFormByInput extends React.Component {
 
 UserGroupUserFormByInput.propTypes = {
   t: PropTypes.func.isRequired, // i18next
-  appContainer: PropTypes.instanceOf(AppContainer).isRequired,
   adminUserGroupDetailContainer: PropTypes.instanceOf(AdminUserGroupDetailContainer).isRequired,
 };
 
@@ -174,6 +172,6 @@ const UserGroupUserFormByInputWrapperFC = (props) => {
 /**
  * Wrapper component for using unstated
  */
-const UserGroupUserFormByInputWrapper = withUnstatedContainers(UserGroupUserFormByInputWrapperFC, [AppContainer, AdminUserGroupDetailContainer]);
+const UserGroupUserFormByInputWrapper = withUnstatedContainers(UserGroupUserFormByInputWrapperFC, [AdminUserGroupDetailContainer]);
 
 export default UserGroupUserFormByInputWrapper;

+ 2 - 4
packages/app/src/components/Admin/UserGroupDetail/UserGroupUserModal.jsx

@@ -1,13 +1,12 @@
 import React from 'react';
 
-import PropTypes from 'prop-types';
 import { useTranslation } from 'next-i18next';
+import PropTypes from 'prop-types';
 import {
   Modal, ModalHeader, ModalBody,
 } from 'reactstrap';
 
 import AdminUserGroupDetailContainer from '~/client/services/AdminUserGroupDetailContainer';
-import AppContainer from '~/client/services/AppContainer';
 
 import { withUnstatedContainers } from '../../UnstatedUtils';
 
@@ -81,7 +80,6 @@ class UserGroupUserModal extends React.Component {
 
 UserGroupUserModal.propTypes = {
   t: PropTypes.func.isRequired, // i18next
-  appContainer: PropTypes.instanceOf(AppContainer).isRequired,
   adminUserGroupDetailContainer: PropTypes.instanceOf(AdminUserGroupDetailContainer).isRequired,
 };
 
@@ -92,6 +90,6 @@ const UserGroupUserModalWrapperFC = (props) => {
 /**
  * Wrapper component for using unstated
  */
-const UserGroupUserModalWrapper = withUnstatedContainers(UserGroupUserModalWrapperFC, [AppContainer, AdminUserGroupDetailContainer]);
+const UserGroupUserModalWrapper = withUnstatedContainers(UserGroupUserModalWrapperFC, [AdminUserGroupDetailContainer]);
 
 export default UserGroupUserModalWrapper;

+ 1 - 3
packages/app/src/components/Admin/UserGroupDetail/UserGroupUserTable.jsx

@@ -6,7 +6,6 @@ import { useTranslation } from 'next-i18next';
 import PropTypes from 'prop-types';
 
 import AdminUserGroupDetailContainer from '~/client/services/AdminUserGroupDetailContainer';
-import AppContainer from '~/client/services/AppContainer';
 import { toastSuccess, toastError } from '~/client/util/apiNotification';
 import Xss from '~/services/xss';
 
@@ -114,7 +113,6 @@ class UserGroupUserTable extends React.Component {
 
 UserGroupUserTable.propTypes = {
   t: PropTypes.func.isRequired, // i18next
-  appContainer: PropTypes.instanceOf(AppContainer).isRequired,
   adminUserGroupDetailContainer: PropTypes.instanceOf(AdminUserGroupDetailContainer).isRequired,
 };
 
@@ -126,6 +124,6 @@ const UserGroupUserTableWrapperFC = (props) => {
 /**
  * Wrapper component for using unstated
  */
-const UserGroupUserTableWrapper = withUnstatedContainers(UserGroupUserTableWrapperFC, [AppContainer, AdminUserGroupDetailContainer]);
+const UserGroupUserTableWrapper = withUnstatedContainers(UserGroupUserTableWrapperFC, [AdminUserGroupDetailContainer]);
 
 export default UserGroupUserTableWrapper;

+ 1 - 1
packages/app/src/components/InstallerForm.jsx

@@ -53,7 +53,7 @@ class InstallerForm extends React.Component {
       : <span><i className="icon-fw icon-ban" />{ this.props.t('installer.unavaliable_user_id') }</span>;
 
     return (
-      <div data-testid="installerForm" className={`login-dialog p-3 mx-auto${hasErrorClass}`}>
+      <div data-testid="installerForm" className={`noLogin-dialog p-3 mx-auto${hasErrorClass}`}>
         <div className="row">
           <div className="col-md-12">
             <p className="alert alert-success">

+ 3 - 1
packages/app/src/components/Layout/AdminLayout.tsx

@@ -8,6 +8,8 @@ import { RawLayout } from './RawLayout';
 
 import styles from './Admin.module.scss';
 
+const AdminNotFoundPage = dynamic(() => import('../Admin/NotFoundPage').then(mod => mod.AdminNotFoundPage), { ssr: false });
+
 
 type Props = {
   title: string
@@ -43,7 +45,7 @@ const AdminLayout = ({
                 <AdminNavigation selected={selectedNavOpt} />
               </div>
               <div className="col-lg-9">
-                {children}
+                {children || <AdminNotFoundPage />}
               </div>
             </div>
           </div>

+ 14 - 0
packages/app/src/components/Layout/Invited.module.scss

@@ -0,0 +1,14 @@
+.invited,
+.nologin.error {
+  .main .row {
+    @media (min-width: 510px) {
+      .offset-sm-4 {
+        margin-left: calc(50% - 240px);
+      }
+
+      .col-sm-4 {
+        width: 480px;
+      }
+    }
+  }
+}

+ 27 - 0
packages/app/src/components/Layout/Login.module.scss

@@ -0,0 +1,27 @@
+@use '~/styles/bootstrap/init' as bs;
+
+
+.login-page {
+  // layout
+  .main .row .login-header,
+  .login-dialog {
+    width: 320px;
+  }
+
+  .link-growi-org {
+    position: absolute;
+    bottom: 9px;
+    z-index: 3;
+  }
+
+  // To adjust the behavior, this problem is not solved.
+  // See https://github.com/AaronCCWong/react-card-flip/issues/56
+  .react-card-front,
+  .react-card-back {
+    height: 0% !important;
+  }
+}
+
+.collapse-external-auth {
+  overflow: hidden;
+}

+ 21 - 62
packages/app/src/styles/_login.scss → packages/app/src/components/Layout/NoLoginLayout.module.scss

@@ -1,7 +1,7 @@
-@use '~/styles/bootstrap/init' as bs;
+@use '~/styles/bootstrap/init' as *;
 
 
-.nologin {
+.nologin :global {
   #page-wrapper {
     background: none;
   }
@@ -24,7 +24,7 @@
           margin-left: 20px;
         }
 
-        .login-header {
+        .noLogin-header {
           display: flex;
           flex-direction: column;
           align-items: center;
@@ -32,7 +32,7 @@
           padding-bottom: 10px;
         }
 
-        .login-form-errors {
+        .noLogin-form-errors {
           width: 100%;
 
           .alert {
@@ -56,7 +56,7 @@
   // #wrapper
 
   // styles
-  .login-header {
+  .noLogin-header {
     h1 {
       font-size: 22px;
       line-height: 1em;
@@ -89,46 +89,42 @@
     }
   }
 
-  .collapse-external-auth {
-    overflow: hidden;
-  }
-
   $btn-fill-colors: (
     'login': (
-      rgba(bs.$danger, 0.4),
+      rgba($danger, 0.4),
       rgba(#7e4153, 0.7),
     ),
     'register': (
-      rgba(bs.$success, 0.4),
+      rgba($success, 0.4),
       rgba(#3f7263, 0.7),
     ),
     'google': (
       rgba(#24292e, 0.4),
-      bs.$gray-700,
+      $gray-700,
     ),
     'github': (
       rgba(lighten(black, 20%), 0.4),
-      bs.$gray-700,
+      $gray-700,
     ),
     'facebook': (
       rgba(#29487d, 0.4),
-      bs.$gray-700,
+      $gray-700,
     ),
     'twitter': (
       rgba(#1da1f2, 0.4),
-      bs.$gray-700,
+      $gray-700,
     ),
     'oidc': (
       rgba(#24292e, 0.4),
-      bs.$gray-700,
+      $gray-700,
     ),
     'saml': (
       rgba(#55a79a, 0.4),
-      bs.$gray-700,
+      $gray-700,
     ),
     'basic': (
       rgba(#24292e, 0.4),
-      bs.$gray-700,
+      $gray-700,
     ),
   );
 
@@ -154,57 +150,20 @@
       transition: color 0.8s;
     }
   }
-
-  .link-switch {
-    color: bs.$gray-200;
-
-    &:hover {
-      color: white;
-    }
-  }
-}
-
-.login-page {
-  // layout
-  .main .row .login-header,
-  .login-dialog {
-    width: 320px;
-  }
-
-  .link-growi-org {
-    position: absolute;
-    bottom: 9px;
-    z-index: 3;
-  }
-
-  // To adjust the behavior, this problem is not solved.
-  // See https://github.com/AaronCCWong/react-card-flip/issues/56
-  .react-card-front,
-  .react-card-back {
-    height: 0% !important;
+  .noLogin-header,
+  .noLogin-dialog {
+    max-width: 480px;
   }
 }
 
-.invited,
-.nologin.error {
-  .main .row {
-    @media (min-width: 510px) {
-      .offset-sm-4 {
-        margin-left: calc(50% - 240px);
-      }
+.link-switch {
+  color: $gray-200;
 
-      .col-sm-4 {
-        width: 480px;
-      }
-    }
+  &:hover {
+    color: white;
   }
 }
 
-.login-header,
-.login-dialog {
-  max-width: 480px;
-}
-
 .nologin.error {
   .alert h2 {
     line-height: 1em;

+ 48 - 0
packages/app/src/components/Layout/NoLoginLayout.tsx

@@ -0,0 +1,48 @@
+import React, { ReactNode } from 'react';
+
+import GrowiLogo from '../Icons/GrowiLogo';
+
+import { RawLayout } from './RawLayout';
+
+import commonStyles from './NoLoginLayout.module.scss';
+
+type Props = {
+  title: string,
+  className?: string,
+  children?: ReactNode,
+}
+
+export const NoLoginLayout = ({
+  children, title, className,
+}: Props): JSX.Element => {
+  const classNames: string[] = ['wrapper'];
+  if (className != null) {
+    classNames.push(className);
+  }
+  return (
+    <RawLayout title={title} className={`${commonStyles.nologin}`}>
+      <div className="nologin">
+        <div id="wrapper">
+          <div id="page-wrapper">
+            <div className="main container-fluid">
+
+              <div className="row">
+
+                <div className="col-md-12">
+                  <div className="noLogin-header mx-auto">
+                    <GrowiLogo />
+                    <h1 className="my-3">GROWI</h1>
+                    <div className="noLogin-form-errors px-3"></div>
+                  </div>
+                </div>
+
+                {children}
+
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+    </RawLayout>
+  );
+};

+ 1 - 1
packages/app/src/components/Layout/RawLayout.tsx

@@ -12,7 +12,7 @@ import { getBackgroundImageSrc } from '../Theme/utils/ThemeImageProvider';
 import { ThemeProvider } from '../Theme/utils/ThemeProvider';
 
 type Props = {
-  title: string,
+  title?: string,
   className?: string,
   children?: ReactNode,
 }

+ 1 - 1
packages/app/src/components/LoginForm.jsx

@@ -291,7 +291,7 @@ class LoginForm extends React.Component {
     const isSomeExternalAuthEnabled = true;
 
     return (
-      <div className="login-dialog mx-auto" id="login-dialog">
+      <div className="noLogin-dialog mx-auto" id="noLogin-dialog">
         <div className="row mx-0">
           <div className="col-12">
             <ReactCardFlip isFlipped={this.state.isRegistering} flipDirection="horizontal" cardZIndex="3">

+ 22 - 17
packages/app/src/components/Me/BasicInfoSettings.tsx

@@ -1,9 +1,10 @@
 import React from 'react';
 
-import { useTranslation } from 'next-i18next';
+import { useTranslation, i18n } from 'next-i18next';
+
+import { i18n as i18nConfig } from '^/config/next-i18next.config';
 
 import { toastSuccess, toastError } from '~/client/util/apiNotification';
-// import { localeMetadatas } from '~/client/util/i18n';
 import { useRegistrationWhiteList } from '~/stores/context';
 import { usePersonalSettings } from '~/stores/personal-settings';
 
@@ -104,23 +105,27 @@ export const BasicInfoSettings = (): JSX.Element => {
       <div className="form-group row">
         <label className="text-left text-md-right col-md-3 col-form-label">{t('Language')}</label>
         <div className="col-md-6">
-          {/*
           {
-            localeMetadatas.map(meta => (
-              <div key={meta.id} className="custom-control custom-radio custom-control-inline">
-                <input
-                  type="radio"
-                  id={`radioLang${meta.id}`}
-                  className="custom-control-input"
-                  name="userForm[lang]"
-                  checked={personalSettingsInfo?.lang === meta.id}
-                  onChange={() => changePersonalSettingsHandler({ lang: meta.id })}
-                />
-                <label className="custom-control-label" htmlFor={`radioLang${meta.id}`}>{meta.displayName}</label>
-              </div>
-            ))
+            i18nConfig.locales.map((locale) => {
+              if (i18n == null) { return }
+              const fixedT = i18n.getFixedT(locale);
+              i18n.loadLanguages(i18nConfig.locales);
+
+              return (
+                <div key={locale} className="custom-control custom-radio custom-control-inline">
+                  <input
+                    type="radio"
+                    id={`radioLang${locale}`}
+                    className="custom-control-input"
+                    name="userForm[lang]"
+                    checked={personalSettingsInfo?.lang === locale}
+                    onChange={() => changePersonalSettingsHandler({ lang: locale })}
+                  />
+                  <label className="custom-control-label" htmlFor={`radioLang${locale}`}>{fixedT('meta.display_name')}</label>
+                </div>
+              );
+            })
           }
-          */}
         </div>
       </div>
       <div className="form-group row">

+ 2 - 2
packages/app/src/components/Theme/ThemeChristmas.module.scss

@@ -146,8 +146,8 @@ $color-link-wiki-hover: lighten($color-link-wiki, 15%);
       }
     }
 
-    .login-header,
-    .login-dialog {
+    .noLogin-header,
+    .noLogin-dialog {
       background-color: rgba(#ccc, 0.5);
     }
     .link-switch {

+ 4 - 4
packages/app/src/components/Theme/ThemeHufflepuff.module.scss

@@ -138,8 +138,8 @@
       background-size: cover;
     }
 
-    .login-header,
-    .login-dialog {
+    .noLogin-header,
+    .noLogin-dialog {
       background-color: rgba(black, 0.1);
     }
 
@@ -305,8 +305,8 @@
       background-size: cover;
     }
 
-    .login-header,
-    .login-dialog {
+    .noLogin-header,
+    .noLogin-dialog {
       background-color: rgba(black, 0.1);
     }
 

+ 2 - 2
packages/app/src/components/Theme/ThemeSpring.module.scss

@@ -138,8 +138,8 @@ $accentcolor: #e08dbc;
       background-size: cover;
     }
 
-    .login-header,
-    .login-dialog {
+    .noLogin-header,
+    .noLogin-dialog {
       background-color: rgba(black, 0.1);
     }
 

+ 2 - 2
packages/app/src/components/Theme/ThemeWood.module.scss

@@ -159,8 +159,8 @@ $themelight: #f5f3ee;
   .nologin {
     background: white;
 
-    .login-header,
-    .login-dialog {
+    .noLogin-header,
+    .noLogin-dialog {
       background-color: rgba(black, 0.1);
     }
 

+ 27 - 13
packages/app/src/pages/admin/[[...path]].page.tsx

@@ -1,6 +1,6 @@
-import React from 'react';
+import React, { useCallback } from 'react';
 
-import { isClient } from '@growi/core';
+import { isClient, objectIdUtils } from '@growi/core';
 import {
   NextPage, GetServerSideProps, GetServerSidePropsContext,
 } from 'next';
@@ -55,13 +55,12 @@ const SlackIntegration = dynamic(() => import('../../components/Admin/SlackInteg
 const LegacySlackIntegration = dynamic(() => import('../../components/Admin/LegacySlackIntegration/LegacySlackIntegration'), { ssr: false });
 const UserManagement = dynamic(() => import('../../components/Admin/UserManagement'), { ssr: false });
 const ManageExternalAccount = dynamic(() => import('../../components/Admin/ManageExternalAccount'), { ssr: false });
-const UserGroupPage = dynamic(() => import('../../components/Admin/UserGroup/UserGroupPage'), { ssr: false });
 const ElasticsearchManagement = dynamic(() => import('../../components/Admin/ElasticsearchManagement/ElasticsearchManagement'), { ssr: false });
-// named export
-const AuditLogManagement = dynamic(() => import('../../components/Admin/AuditLogManagement').then(module => module.AuditLogManagement));
-
-
+const UserGroupDetailPage = dynamic(() => import('../../components/Admin/UserGroupDetail/UserGroupDetailPage'), { ssr: false });
 const AdminLayout = dynamic(() => import('../../components/Layout/AdminLayout'), { ssr: false });
+// named export
+const UserGroupPage = dynamic(() => import('../../components/Admin/UserGroup/UserGroupPage').then(mod => mod.UserGroupPage), { ssr: false });
+const AuditLogManagement = dynamic(() => import('../../components/Admin/AuditLogManagement').then(mod => mod.AuditLogManagement), { ssr: false });
 
 const pluginUtils = new PluginUtils();
 
@@ -88,6 +87,17 @@ const AdminMarkdownSettingsPage: NextPage<Props> = (props: Props) => {
   const { path } = router.query;
   const pagePathKeys: string[] = Array.isArray(path) ? path : ['home'];
 
+  /*
+  * Set userGroupId as a adminPagesMap key
+  * eg) In case that url is `/user-group-detail/62e8388a9a649bea5e703ef7`, userGroupId will be 62e8388a9a649bea5e703ef7
+  */
+  let userGroupId;
+  const [firstPath, secondPath] = pagePathKeys;
+  if (firstPath === 'user-group-detail') {
+    userGroupId = objectIdUtils.isValidObjectId(secondPath) ? secondPath : undefined;
+  }
+
+  // TODO: refactoring adminPagesMap => https://redmine.weseek.co.jp/issues/102694
   const adminPagesMap = {
     home: {
       title: useCustomTitle(props, t('Wiki Management Home Page')),
@@ -150,6 +160,12 @@ const AdminMarkdownSettingsPage: NextPage<Props> = (props: Props) => {
       title: useCustomTitle(props, t('UserGroup Management')),
       component: <UserGroupPage />,
     },
+    'user-group-detail': {
+      [userGroupId]: {
+        title: t('UserGroup Management'),
+        component: <UserGroupDetailPage userGroupId={userGroupId} />,
+      },
+    },
     search: {
       title: useCustomTitle(props, t('Full Text Search Management')),
       component: <ElasticsearchManagement />,
@@ -160,17 +176,16 @@ const AdminMarkdownSettingsPage: NextPage<Props> = (props: Props) => {
     },
   };
 
-  const getTargetPageToRender = (pagesMap, keys) => {
+  const getTargetPageToRender = (pagesMap, keys): {title: string, component: JSX.Element} => {
     return keys.reduce((pagesMap, key) => {
       return pagesMap[key];
     }, pagesMap);
   };
 
-  const targetPage: {title: string, component: JSX.Element} = getTargetPageToRender(adminPagesMap, pagePathKeys);
-  const title = targetPage.title;
+  const targetPage = getTargetPageToRender(adminPagesMap, pagePathKeys);
 
   useCurrentUser(props.currentUser != null ? JSON.parse(props.currentUser) : null);
-  useIsMailerSetup(props.isMailerSetup);
+  // useIsMailerSetup(props.isMailerSetup);
 
   // useSearchServiceConfigured(props.isSearchServiceConfigured);
   useIsSearchServiceReachable(props.isSearchServiceReachable);
@@ -239,13 +254,12 @@ const AdminMarkdownSettingsPage: NextPage<Props> = (props: Props) => {
         adminTwitterSecurityContainer,
       );
     }
-
   }
 
 
   return (
     <Provider inject={[...injectableContainers, ...adminSecurityContainers]}>
-      <AdminLayout title={title} selectedNavOpt={pagePathKeys[0]}>
+      <AdminLayout title={targetPage.title} selectedNavOpt={firstPath}>
         {targetPage.component}
       </AdminLayout>
     </Provider>

+ 7 - 30
packages/app/src/pages/installer.page.tsx

@@ -6,7 +6,7 @@ import {
 } from 'next';
 import { serverSideTranslations } from 'next-i18next/serverSideTranslations';
 
-import { RawLayout } from '~/components/Layout/RawLayout';
+import { NoLoginLayout } from '~/components/Layout/NoLoginLayout';
 
 import InstallerForm from '../components/InstallerForm';
 import {
@@ -46,36 +46,13 @@ const InstallerPage: NextPage<Props> = (props: Props) => {
   const classNames: string[] = [];
 
   return (
-    <>
-      <RawLayout title={useCustomTitle(props, 'GROWI')} className={classNames.join(' ')}>
-        <div className='nologin'>
-          <div id="wrapper">
-            <div id="page-wrapper">
-              <div className="main container-fluid">
-
-                <div className="row">
-
-                  <div className="col-md-12">
-                    <div className="login-header mx-auto">
-                      <div className="logo"></div>
-                      <h1 className="my-3">GROWI</h1>
-                      <div className="login-form-errors px-3"></div>
-                    </div>
-                  </div>
-
-                  <div className="col-md-12">
-                    <div id="installer-form-container">
-                      <InstallerForm />
-                    </div>
-                  </div>
-
-                </div>
-              </div>
-            </div>
-          </div>
+    <NoLoginLayout title={useCustomTitle(props, 'GROWI')} className={classNames.join(' ')}>
+      <div className="col-md-12">
+        <div id="installer-form-container">
+          <InstallerForm />
         </div>
-      </RawLayout>
-    </>
+      </div>
+    </NoLoginLayout>
   );
 };
 

+ 8 - 15
packages/app/src/pages/login.page.tsx

@@ -1,13 +1,12 @@
 import React from 'react';
 
 
-import { pagePathUtils } from '@growi/core';
 import {
   NextPage, GetServerSideProps, GetServerSidePropsContext,
 } from 'next';
 import dynamic from 'next/dynamic';
 
-import { RawLayout } from '~/components/Layout/RawLayout';
+import { NoLoginLayout } from '~/components/Layout/NoLoginLayout';
 import { CrowiRequest } from '~/interfaces/crowi-request';
 
 import {
@@ -36,25 +35,19 @@ const LoginPage: NextPage<Props> = (props: Props) => {
   // page
   useCurrentPathname(props.currentPathname);
 
-  const classNames: string[] = [];
+  const classNames: string[] = ['login-page'];
 
   const LoginForm = dynamic(() => import('~/components/LoginForm'), {
     ssr: false,
   });
 
   return (
-    <>
-      <RawLayout title={useCustomTitle(props, 'GROWI')} className={classNames.join(' ')}>
-        <div className='nologin'>
-          <div id='wrapper'>
-            <div id="page-wrapper">
-              <LoginForm objOfIsExternalAuthEnableds={props.enabledStrategies} isLocalStrategySetup={true} isLdapStrategySetup={true}
-                isRegistrationEnabled={true} registrationWhiteList={props.registrationWhiteList} isPasswordResetEnabled={true} />
-            </div>
-          </div>
-        </div>
-      </RawLayout>
-    </>
+    <NoLoginLayout title={useCustomTitle(props, 'GROWI')} className={classNames.join(' ')}>
+      <div className="col-md-12">
+        <LoginForm objOfIsExternalAuthEnableds={props.enabledStrategies} isLocalStrategySetup={true} isLdapStrategySetup={true}
+          isRegistrationEnabled={true} registrationWhiteList={props.registrationWhiteList} isPasswordResetEnabled={true} />
+      </div>
+    </NoLoginLayout>
   );
 };
 

+ 4 - 2
packages/app/src/pages/me.page.tsx

@@ -139,7 +139,7 @@ async function injectNextI18NextConfigurations(context: GetServerSidePropsContex
 
 export const getServerSideProps: GetServerSideProps = async(context: GetServerSidePropsContext) => {
   const req = context.req as CrowiRequest<IUserHasId & any>;
-  const { user } = req;
+  const { user, crowi } = req;
 
   const result = await getServerSideCommonProps(context);
 
@@ -153,7 +153,9 @@ export const getServerSideProps: GetServerSideProps = async(context: GetServerSi
   const props: Props = result.props as Props;
 
   if (user != null) {
-    props.currentUser = user.toObject();
+    const User = crowi.model('User');
+    const userData = await User.findById(req.user.id).populate({ path: 'imageAttachment', select: 'filePathProxied' });
+    props.currentUser = userData.toObject();
   }
 
   await injectUserUISettings(context, props);

+ 7 - 4
packages/app/src/server/routes/admin.js

@@ -524,10 +524,13 @@ module.exports = function(crowi, app) {
     return res.json(ApiResponse.success());
   };
 
-  actions.notFound = {};
-  actions.notFound.index = function(req, res) {
-    return res.render('admin/not_found');
-  };
+  /*
+  * Use AdminNotFoundPage component instead
+  */
+  // actions.notFound = {};
+  // actions.notFound.index = function(req, res) {
+  //   return res.render('admin/not_found');
+  // };
 
   return actions;
 };

+ 3 - 2
packages/app/src/server/views/admin/not_found.html

@@ -1,7 +1,8 @@
-{% extends '../layout/admin.html' %}
+<!-- Use AdminNotFoundPage component instead -->
+<!-- {% extends '../layout/admin.html' %}
 
 {% block html_title %}{{ customizeService.generateCustomTitleForFixedPageName(t('not_found_page.page_not_exist')) }}{% endblock %}
 
 {% block content_main %}
 <h1 class="title">{{ t('not_found_page.page_not_exist') }}</h1>
-{% endblock content_main %}
+{% endblock content_main %} -->

+ 1 - 1
packages/app/src/styles/style-next.scss

@@ -47,7 +47,7 @@
 // @import 'page-content-footer';
 // @import 'handsontable';
 @import 'layout';
-@import 'login';
+// @import 'login';
 // @import 'me';
 // @import 'mirror_mode';
 @import 'modal';

+ 2 - 2
packages/app/src/styles/theme/_apply-colors-dark.scss

@@ -141,7 +141,7 @@ ul.pagination {
     linear-gradient(225deg, darken(var.$growi-blue, 20%) 10%, hsla(140, 90%, 50%, 0) 80%),
     linear-gradient(315deg, darken($color-gradient, 25%) 100%, hsla(35, 95%, 55%, 0) 70%);
 
-  .login-header {
+  .noLogin-header {
     background-color: rgba(black, 0.5);
 
     .logo {
@@ -154,7 +154,7 @@ ul.pagination {
     }
   }
 
-  .login-dialog {
+  .noLogin-dialog {
     background-color: rgba(black, 0.5);
   }
 

+ 2 - 2
packages/app/src/styles/theme/_apply-colors-light.scss

@@ -84,7 +84,7 @@ $dropdown-link-active-bg: $bgcolor-dropdown-link-active;
     linear-gradient(135deg, var.$growi-green 10%, hsla(225, 95%, 50%, 0) 70%), linear-gradient(225deg, var.$growi-blue 10%, hsla(140, 90%, 50%, 0) 80%),
     linear-gradient(315deg, darken($color-gradient, 25%) 100%, hsla(35, 95%, 55%, 0) 70%);
 
-  .login-header {
+  .noLogin-header {
     background-color: rgba(white, 0.5);
 
     .logo {
@@ -97,7 +97,7 @@ $dropdown-link-active-bg: $bgcolor-dropdown-link-active;
     }
   }
 
-  .login-dialog {
+  .noLogin-dialog {
     background-color: rgba(white, 0.5);
   }