Pārlūkot izejas kodu

PageBulkExportSelectModal

Futa Arai 2 gadi atpakaļ
vecāks
revīzija
95ba63ee8d

+ 4 - 1
apps/app/public/static/locales/en_US/translation.json

@@ -601,7 +601,10 @@
     "failed_to_count_pages": "Failed to count pages",
     "export_page_markdown": "Export page as Markdown",
     "export_page_pdf": "Export page as PDF",
-    "bulk_export": "Export page and all child pages"
+    "bulk_export": "Export page and all child pages",
+    "bulk_export_notice": "Once a download link is ready, a notification will be sent. If the number of pages is large, it may take a while for preparation.",
+    "markdown": "Markdown",
+    "choose_export_format": "Select export format"
   },
   "message": {
     "successfully_connected": "Successfully Connected!",

+ 4 - 1
apps/app/public/static/locales/ja_JP/translation.json

@@ -634,7 +634,10 @@
     "failed_to_count_pages": "ページ数の取得に失敗しました",
     "export_page_markdown": "マークダウン形式でページをエクスポート",
     "export_page_pdf": "PDF形式でページをエクスポート",
-    "bulk_export": "ページとその配下のページを全てエクスポート"
+    "bulk_export": "ページとその配下のページを全てエクスポート",
+    "bulk_export_notice": "ダウンロードの準備が完了すると、通知が届きます。ページ数が多いと、準備に時間がかかる場合があります。",
+    "markdown": "マークダウン",
+    "choose_export_format": "エクスポート形式を選択してください"
   },
   "message": {
     "successfully_connected": "接続に成功しました!",

+ 4 - 1
apps/app/public/static/locales/zh_CN/translation.json

@@ -604,7 +604,10 @@
     "failed_to_count_pages": "页面计数失败",
     "export_page_markdown": "以Markdown格式导出页面",
     "export_page_pdf": "以PDF格式导出页面",
-    "bulk_export": "导出页面及其下的所有页面"
+    "bulk_export": "导出页面及其下的所有页面",
+    "bulk_export_notice": "下载链接准备好后,将发送通知。如果页数较多,则可能需要一段时间准备。",
+    "markdown": "Markdown",
+    "choose_export_format": "选择导出格式"
   },
 	"message": {
 		"successfully_connected": "连接成功!",

+ 2 - 0
apps/app/src/components/Layout/BasicLayout.tsx

@@ -25,6 +25,7 @@ const PageRenameModal = dynamic(() => import('../PageRenameModal'), { ssr: false
 const PagePresentationModal = dynamic(() => import('../PagePresentationModal'), { ssr: false });
 const PageAccessoriesModal = dynamic(() => import('../PageAccessoriesModal').then(mod => mod.PageAccessoriesModal), { ssr: false });
 const DeleteBookmarkFolderModal = dynamic(() => import('../DeleteBookmarkFolderModal').then(mod => mod.DeleteBookmarkFolderModal), { ssr: false });
+const PageBulkExportSelectModal = dynamic(() => import('../PageBulkExportSelectModal'), { ssr: false });
 // Fab
 const Fab = dynamic(() => import('../Fab').then(mod => mod.Fab), { ssr: false });
 
@@ -69,6 +70,7 @@ export const BasicLayout = ({ children, className }: Props): JSX.Element => {
       <Fab />
 
       <ShortcutsModal />
+      <PageBulkExportSelectModal />
       <SystemVersion showShortcutsButton />
     </RawLayout>
   );

+ 3 - 2
apps/app/src/components/Navbar/GrowiContextualSubNavigation.tsx

@@ -22,7 +22,7 @@ import {
 import { usePageTagsForEditors } from '~/stores/editor';
 import {
   usePageAccessoriesModal, PageAccessoriesModalContents, IPageForPageDuplicateModal,
-  usePageDuplicateModal, usePageRenameModal, usePageDeleteModal, usePagePresentationModal,
+  usePageDuplicateModal, usePageRenameModal, usePageDeleteModal, usePagePresentationModal, usePageBulkExportSelectModal,
 } from '~/stores/modal';
 import {
   useSWRMUTxCurrentPage, useSWRxTagsInfo, useCurrentPageId, useIsNotFound, useTemplateTagData, useSWRxPageInfo,
@@ -85,6 +85,7 @@ const PageOperationMenuItems = (props: PageOperationMenuItemsProps): JSX.Element
 
   const { open: openPresentationModal } = usePagePresentationModal();
   const { open: openAccessoriesModal } = usePageAccessoriesModal();
+  const { open: openPageBulkExportSelectModal } = usePageBulkExportSelectModal();
 
   return (
     <>
@@ -111,7 +112,7 @@ const PageOperationMenuItems = (props: PageOperationMenuItemsProps): JSX.Element
 
       {/* Bulk export */}
       <DropdownItem
-        onClick={() => {}}
+        onClick={openPageBulkExportSelectModal}
         className="grw-page-control-dropdown-item"
       >
         <i className="icon-fw icon-cloud-download grw-page-control-dropdown-icon"></i>

+ 35 - 0
apps/app/src/components/PageBulkExportSelectModal.tsx

@@ -0,0 +1,35 @@
+import { useTranslation } from 'next-i18next';
+import { Modal, ModalHeader, ModalBody } from 'reactstrap';
+
+import { usePageBulkExportSelectModal } from '~/stores/modal';
+
+const PageBulkExportSelectModal = (): JSX.Element => {
+  const { t } = useTranslation();
+  const { data: status, close } = usePageBulkExportSelectModal();
+
+  return (
+    <>
+      {status != null && (
+        <Modal isOpen={status.isOpened} toggle={close}>
+          <ModalHeader tag="h4" toggle={close} className="bg-primary text-light">
+            {t('page_export.bulk_export')}
+          </ModalHeader>
+          <ModalBody>
+            <div className="mb-2">
+              <small className="text-muted">
+                {t('page_export.bulk_export_notice')}
+              </small>
+            </div>
+            {t('page_export.choose_export_format')}:
+            <div className="d-flex justify-content-center mt-2">
+              <button className="btn btn-primary" type="button">{t('page_export.markdown')}</button>
+              <button className="btn btn-primary ml-2" type="button">PDF</button>
+            </div>
+          </ModalBody>
+        </Modal>
+      )}
+    </>
+  );
+};
+
+export default PageBulkExportSelectModal;

+ 27 - 0
apps/app/src/stores/modal.tsx

@@ -393,6 +393,33 @@ export const usePageAccessoriesModal = (): SWRResponse<PageAccessoriesModalStatu
   });
 };
 
+/*
+ * PageBulkExportSelectModal
+ */
+type PageBulkExportSelectModalStatus = {
+  isOpened: boolean,
+}
+
+type PageBulkExportSelectModalUtils = {
+  open(): Promise<void>,
+  close(): Promise<void>,
+}
+
+export const usePageBulkExportSelectModal = (): SWRResponse<PageBulkExportSelectModalStatus, Error> & PageBulkExportSelectModalUtils => {
+  const initialStatus: PageBulkExportSelectModalStatus = { isOpened: false };
+  const swrResponse = useStaticSWR<PageBulkExportSelectModalStatus, Error>('pageBulkExportSelectModal', undefined, { fallbackData: initialStatus });
+
+  return {
+    ...swrResponse,
+    async open() {
+      await swrResponse.mutate({ isOpened: true });
+    },
+    async close() {
+      await swrResponse.mutate({ isOpened: false });
+    },
+  };
+};
+
 /*
  * UpdateUserGroupConfirmModal
  */