Selaa lähdekoodia

Merge pull request #5767 from weseek/feat/plpages-convert-by-path-input

feat: Private legacy pages convert by path
Yuki Takei 4 vuotta sitten
vanhempi
sitoutus
18379126ba

+ 1 - 1
packages/app/src/client/app.jsx

@@ -16,7 +16,7 @@ import PersonalContainer from '~/client/services/PersonalContainer';
 import RevisionComparerContainer from '~/client/services/RevisionComparerContainer';
 import TagContainer from '~/client/services/TagContainer';
 import IdenticalPathPage from '~/components/IdenticalPathPage';
-import { PrivateLegacyPages } from '~/components/PrivateLegacyPages';
+import PrivateLegacyPages from '~/components/PrivateLegacyPages';
 import loggerFactory from '~/utils/logger';
 import { swrGlobalConfiguration } from '~/utils/swr-utils';
 

+ 66 - 7
packages/app/src/components/PrivateLegacyPages.tsx

@@ -4,18 +4,18 @@ import React, {
 import { useTranslation } from 'react-i18next';
 
 import {
-  UncontrolledButtonDropdown, DropdownToggle, DropdownMenu, DropdownItem,
+  UncontrolledButtonDropdown, DropdownToggle, DropdownMenu, DropdownItem, Modal, ModalHeader, ModalBody, ModalFooter,
 } from 'reactstrap';
 
 import { IFormattedSearchResult } from '~/interfaces/search';
 import AppContainer from '~/client/services/AppContainer';
 import { ISelectableAll, ISelectableAndIndeterminatable } from '~/client/interfaces/selectable-all';
-import { toastSuccess } from '~/client/util/apiNotification';
+import { toastSuccess, toastError } from '~/client/util/apiNotification';
 import {
   useSWRxSearch,
 } from '~/stores/search';
 import {
-  ILegacyPrivatePage, useLegacyPrivatePagesMigrationModal,
+  ILegacyPrivatePage, usePrivateLegacyPagesMigrationModal,
 } from '~/stores/modal';
 
 import PaginationWrapper from './PaginationWrapper';
@@ -23,10 +23,11 @@ import { OperateAllControl } from './SearchPage/OperateAllControl';
 
 import { IReturnSelectedPageIds, SearchPageBase, usePageDeleteModalForBulkDeletion } from './SearchPage2/SearchPageBase';
 import { MenuItemType } from './Common/Dropdown/PageItemControl';
-import { LegacyPrivatePagesMigrationModal } from './LegacyPrivatePagesMigrationModal';
+import { PrivateLegacyPagesMigrationModal } from './PrivateLegacyPagesMigrationModal';
 import SearchControl from './SearchPage/SearchControl';
 import { useSWRxV5MigrationStatus } from '~/stores/page-listing';
 import { V5MigrationStatus } from '~/interfaces/page-listing-results';
+import { apiv3Post } from '~/client/util/apiv3-client';
 
 
 // TODO: replace with "customize:showPageLimitationS"
@@ -124,6 +125,39 @@ const SearchResultListHead = React.memo((props: SearchResultListHeadProps): JSX.
   );
 });
 
+/*
+ * ConvertByPathModal
+ */
+type ConvertByPathModalProps = {
+  isOpen: boolean,
+  close?: () => void,
+  onSubmit?: (convertPath: string) => Promise<void> | void,
+}
+const ConvertByPathModal = React.memo((props: ConvertByPathModalProps): JSX.Element => {
+  const { t } = useTranslation();
+
+  const [currentInput, setInput] = useState<string>('');
+
+  return (
+    <Modal size="lg" isOpen={props.isOpen} toggle={props.close} className="grw-create-page">
+      <ModalHeader tag="h4" toggle={props.close} className="bg-primary text-light">
+        { t('private_legacy_pages.modal.title') }
+      </ModalHeader>
+      <ModalBody>
+        {/* TODO: i18n */}
+        <p>{t('modal_description')}</p>
+        <input type="text" className="form-control" placeholder="/" value={currentInput} onChange={e => setInput(e.target.value)} />
+      </ModalBody>
+      <ModalFooter>
+        <button type="button" className="btn btn-primary" onSubmit={(e) => { e.preventDefault(); props.onSubmit?.(currentInput) }}>
+          <i className="icon-fw icon-refresh" aria-hidden="true"></i>
+          { t('private_legacy_pages.modal.button_label') }
+        </button>
+      </ModalFooter>
+    </Modal>
+  );
+});
+
 
 /**
  * LegacyPage
@@ -133,7 +167,7 @@ type Props = {
   appContainer: AppContainer,
 }
 
-export const PrivateLegacyPages = (props: Props): JSX.Element => {
+const PrivateLegacyPages = (props: Props): JSX.Element => {
   const { t } = useTranslation();
 
   const {
@@ -144,6 +178,7 @@ export const PrivateLegacyPages = (props: Props): JSX.Element => {
   const [keyword, setKeyword] = useState<string>(initQ);
   const [offset, setOffset] = useState<number>(0);
   const [limit, setLimit] = useState<number>(INITIAL_PAGING_SIZE);
+  const [isOpenConvertModal, setOpenConvertModal] = useState<boolean>(false);
 
   const [isControlEnabled, setControlEnabled] = useState(false);
 
@@ -165,7 +200,7 @@ export const PrivateLegacyPages = (props: Props): JSX.Element => {
     setOffset(0);
   }, []);
 
-  const { open: openModal, close: closeModal } = useLegacyPrivatePagesMigrationModal();
+  const { open: openModal, close: closeModal } = usePrivateLegacyPagesMigrationModal();
 
   const selectAllCheckboxChangedHandler = useCallback((isChecked: boolean) => {
     const instance = searchPageBaseRef.current;
@@ -282,6 +317,11 @@ export const PrivateLegacyPages = (props: Props): JSX.Element => {
             </UncontrolledButtonDropdown>
           </OperateAllControl>
         </div>
+        <div className="d-flex pl-md-2">
+          <button type="button" className="btn btn-light" onClick={() => setOpenConvertModal(true)}>
+            Input the path to convert
+          </button>
+        </div>
       </div>
     );
   }, [convertMenuItemClickedHandler, deleteAllButtonClickedHandler, hitsCount, isControlEnabled, selectAllCheckboxChangedHandler, t]);
@@ -347,7 +387,26 @@ export const PrivateLegacyPages = (props: Props): JSX.Element => {
         searchPager={searchPager}
       />
 
-      <LegacyPrivatePagesMigrationModal />
+      <PrivateLegacyPagesMigrationModal />
+      <ConvertByPathModal
+        isOpen={isOpenConvertModal}
+        close={() => setOpenConvertModal(false)}
+        onSubmit={async(convertPath: string) => {
+          try {
+            await apiv3Post<void>('/pages/legacy-pages-migration', {
+              convertPath,
+            });
+            // TODO: i18n
+            toastSuccess(t('success_message'));
+          }
+          catch {
+            // TODO: i18n
+            toastError(t('error_message'));
+          }
+        }}
+      />
     </>
   );
 };
+
+export default PrivateLegacyPages;

+ 3 - 3
packages/app/src/components/LegacyPrivatePagesMigrationModal.tsx → packages/app/src/components/PrivateLegacyPagesMigrationModal.tsx

@@ -5,7 +5,7 @@ import {
 import { useTranslation } from 'react-i18next';
 
 import { apiv3Post } from '~/client/util/apiv3-client';
-import { useLegacyPrivatePagesMigrationModal } from '~/stores/modal';
+import { usePrivateLegacyPagesMigrationModal } from '~/stores/modal';
 
 import ApiErrorMessageList from './PageManagement/ApiErrorMessageList';
 
@@ -14,10 +14,10 @@ type Props = {
 
 }
 
-export const LegacyPrivatePagesMigrationModal = (props: Props): JSX.Element => {
+export const PrivateLegacyPagesMigrationModal = (props: Props): JSX.Element => {
   const { t } = useTranslation();
 
-  const { data: status, close } = useLegacyPrivatePagesMigrationModal();
+  const { data: status, close } = usePrivateLegacyPagesMigrationModal();
 
   const isOpened = status?.isOpened ?? false;
 

+ 12 - 12
packages/app/src/stores/modal.tsx

@@ -222,32 +222,32 @@ export const usePagePresentationModal = (
 
 
 /*
- * LegacyPrivatePagesMigrationModal
+ * PrivateLegacyPagesMigrationModal
  */
 
 export type ILegacyPrivatePage = { pageId: string, path: string };
 
-export type LegacyPrivatePagesMigrationModalSubmitedHandler = (pages: ILegacyPrivatePage[], isRecursively?: boolean) => void;
+export type PrivateLegacyPagesMigrationModalSubmitedHandler = (pages: ILegacyPrivatePage[], isRecursively?: boolean) => void;
 
-type LegacyPrivatePagesMigrationModalStatus = {
+type PrivateLegacyPagesMigrationModalStatus = {
   isOpened: boolean,
   pages?: ILegacyPrivatePage[],
-  onSubmited?: LegacyPrivatePagesMigrationModalSubmitedHandler,
+  onSubmited?: PrivateLegacyPagesMigrationModalSubmitedHandler,
 }
 
-type LegacyPrivatePagesMigrationModalStatusUtils = {
-  open(pages: ILegacyPrivatePage[], onSubmited?: LegacyPrivatePagesMigrationModalSubmitedHandler): Promise<LegacyPrivatePagesMigrationModalStatus | undefined>,
-  close(): Promise<LegacyPrivatePagesMigrationModalStatus | undefined>,
+type PrivateLegacyPagesMigrationModalStatusUtils = {
+  open(pages: ILegacyPrivatePage[], onSubmited?: PrivateLegacyPagesMigrationModalSubmitedHandler): Promise<PrivateLegacyPagesMigrationModalStatus | undefined>,
+  close(): Promise<PrivateLegacyPagesMigrationModalStatus | undefined>,
 }
 
-export const useLegacyPrivatePagesMigrationModal = (
-    status?: LegacyPrivatePagesMigrationModalStatus,
-): SWRResponse<LegacyPrivatePagesMigrationModalStatus, Error> & LegacyPrivatePagesMigrationModalStatusUtils => {
-  const initialData: LegacyPrivatePagesMigrationModalStatus = {
+export const usePrivateLegacyPagesMigrationModal = (
+    status?: PrivateLegacyPagesMigrationModalStatus,
+): SWRResponse<PrivateLegacyPagesMigrationModalStatus, Error> & PrivateLegacyPagesMigrationModalStatusUtils => {
+  const initialData: PrivateLegacyPagesMigrationModalStatus = {
     isOpened: false,
     pages: [],
   };
-  const swrResponse = useStaticSWR<LegacyPrivatePagesMigrationModalStatus, Error>('legacyPrivatePagesMigrationModal', status, { fallbackData: initialData });
+  const swrResponse = useStaticSWR<PrivateLegacyPagesMigrationModalStatus, Error>('privateLegacyPagesMigrationModal', status, { fallbackData: initialData });
 
   return {
     ...swrResponse,