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

Merge pull request #8277 from weseek/feat/78027-135782-bulk-export-ui-mock

feat: 78027 135782 bulk export UI mock
Futa Arai 2 лет назад
Родитель
Сommit
9e5c14bfe4

+ 7 - 2
apps/app/public/static/locales/en_US/translation.json

@@ -596,11 +596,16 @@
     "discription_heading": "Create Account",
     "discription": "Create an your account with the invited email address"
   },
-  "export_bulk": {
+  "page_export": {
     "failed_to_export": "Failed to export",
     "failed_to_count_pages": "Failed to count pages",
     "export_page_markdown": "Export page as Markdown",
-    "export_page_pdf": "Export page as PDF"
+    "export_page_pdf": "Export page as PDF",
+    "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",
+    "bulk_export_started": "Please wait a moment..."
   },
   "message": {
     "successfully_connected": "Successfully Connected!",

+ 7 - 2
apps/app/public/static/locales/ja_JP/translation.json

@@ -629,11 +629,16 @@
     "discription_heading": "アカウント作成",
     "discription": "招待を受け取ったメールアドレスでアカウントを作成します"
   },
-  "export_bulk": {
+  "page_export": {
     "failed_to_export": "ページのエクスポートに失敗しました",
     "failed_to_count_pages": "ページ数の取得に失敗しました",
     "export_page_markdown": "マークダウン形式でページをエクスポート",
-    "export_page_pdf": "PDF形式でページをエクスポート"
+    "export_page_pdf": "PDF形式でページをエクスポート",
+    "bulk_export": "ページとその配下のページを全てエクスポート",
+    "bulk_export_notice": "ダウンロードの準備が完了すると、通知が届きます。ページ数が多いと、準備に時間がかかる場合があります。",
+    "markdown": "マークダウン",
+    "choose_export_format": "エクスポート形式を選択してください",
+    "bulk_export_started": "ただいま準備中です..."
   },
   "message": {
     "successfully_connected": "接続に成功しました!",

+ 7 - 2
apps/app/public/static/locales/zh_CN/translation.json

@@ -599,11 +599,16 @@
     "discription_heading": "创建账户",
     "discription": "用被邀请的电子邮件地址创建一个你的账户"
   },
-  "export_bulk": {
+  "page_export": {
     "failed_to_export": "导出失败",
     "failed_to_count_pages": "页面计数失败",
     "export_page_markdown": "以Markdown格式导出页面",
-    "export_page_pdf": "以PDF格式导出页面"
+    "export_page_pdf": "以PDF格式导出页面",
+    "bulk_export": "导出页面及其下的所有页面",
+    "bulk_export_notice": "下载链接准备好后,将发送通知。如果页数较多,则可能需要一段时间准备。",
+    "markdown": "Markdown",
+    "choose_export_format": "选择导出格式",
+    "bulk_export_started": "目前我们正在准备..."
   },
 	"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('../../features/page-bulk-export/client/components/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>
   );

+ 13 - 1
apps/app/src/components/Navbar/GrowiContextualSubNavigation.tsx

@@ -14,6 +14,7 @@ import { DropdownItem } from 'reactstrap';
 import { exportAsMarkdown, updateContentWidth, useUpdateStateAfterSave } from '~/client/services/page-operation';
 import { apiPost } from '~/client/util/apiv1-client';
 import { toastSuccess, toastError } from '~/client/util/toastr';
+import { usePageBulkExportSelectModal } from '~/features/page-bulk-export/client/stores/modal';
 import { OnDuplicatedFunction, OnRenamedFunction, OnDeletedFunction } from '~/interfaces/ui';
 import {
   useCurrentPathname,
@@ -33,6 +34,7 @@ import {
   useIsAbleToChangeEditorMode, useIsAbleToShowPageAuthors,
 } from '~/stores/ui';
 
+
 import CreateTemplateModal from '../CreateTemplateModal';
 import AttachmentIcon from '../Icons/AttachmentIcon';
 import HistoryIcon from '../Icons/HistoryIcon';
@@ -85,6 +87,7 @@ const PageOperationMenuItems = (props: PageOperationMenuItemsProps): JSX.Element
 
   const { open: openPresentationModal } = usePagePresentationModal();
   const { open: openAccessoriesModal } = usePageAccessoriesModal();
+  const { open: openPageBulkExportSelectModal } = usePageBulkExportSelectModal();
 
   return (
     <>
@@ -106,7 +109,16 @@ const PageOperationMenuItems = (props: PageOperationMenuItemsProps): JSX.Element
         className="grw-page-control-dropdown-item"
       >
         <i className="icon-fw icon-cloud-download grw-page-control-dropdown-icon"></i>
-        {t('export_bulk.export_page_markdown')}
+        {t('page_export.export_page_markdown')}
+      </DropdownItem>
+
+      {/* Bulk export */}
+      <DropdownItem
+        onClick={openPageBulkExportSelectModal}
+        className="grw-page-control-dropdown-item"
+      >
+        <i className="icon-fw icon-cloud-download grw-page-control-dropdown-icon"></i>
+        {t('page_export.bulk_export')}
       </DropdownItem>
 
       <DropdownItem divider />

+ 1 - 1
apps/app/src/components/SearchPage/SearchResultContent.tsx

@@ -55,7 +55,7 @@ const AdditionalMenuItems = (props: AdditionalMenuItemsProps): JSX.Element => {
       className="grw-page-control-dropdown-item"
     >
       <i className="icon-fw icon-cloud-download grw-page-control-dropdown-icon"></i>
-      {t('export_bulk.export_page_markdown')}
+      {t('page_export.export_page_markdown')}
     </DropdownItem>
   );
 };

+ 41 - 0
apps/app/src/features/page-bulk-export/client/components/PageBulkExportSelectModal.tsx

@@ -0,0 +1,41 @@
+import { useTranslation } from 'next-i18next';
+import { Modal, ModalHeader, ModalBody } from 'reactstrap';
+
+import { toastSuccess } from '~/client/util/toastr';
+import { usePageBulkExportSelectModal } from '~/features/page-bulk-export/client/stores/modal';
+
+const PageBulkExportSelectModal = (): JSX.Element => {
+  const { t } = useTranslation();
+  const { data: status, close } = usePageBulkExportSelectModal();
+
+  const startBulkExport = () => {
+    close();
+    toastSuccess(t('page_export.bulk_export_started'));
+  };
+
+  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>
+            {t('page_export.choose_export_format')}
+            <div className="my-2">
+              <small className="text-muted">
+                {t('page_export.bulk_export_notice')}
+              </small>
+            </div>
+            <div className="d-flex justify-content-center mt-2">
+              <button className="btn btn-primary" type="button" onClick={startBulkExport}>{t('page_export.markdown')}</button>
+              <button className="btn btn-primary ml-2" type="button" onClick={startBulkExport}>PDF</button>
+            </div>
+          </ModalBody>
+        </Modal>
+      )}
+    </>
+  );
+};
+
+export default PageBulkExportSelectModal;

+ 27 - 0
apps/app/src/features/page-bulk-export/client/stores/modal.tsx

@@ -0,0 +1,27 @@
+import { SWRResponse } from 'swr';
+
+import { useStaticSWR } from '../../../../stores/use-static-swr';
+
+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 });
+    },
+  };
+};