Przeglądaj źródła

Merge pull request #9057 from weseek/feat/150418-153064-show-duplicate-export-job-info-in-modal

Feat/150418 153064 show duplicate export job info in modal
Futa Arai 1 rok temu
rodzic
commit
0f63b28b82

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

@@ -645,8 +645,10 @@
     "bulk_export_only_available_for": "Only available for AWS or GCP",
     "export_in_progress": "Export in progress",
     "export_in_progress_explanation": "Export with the same format is already in progress. Would you like to restart to export the latest page contents?",
-    "export_cancel_warning": "The export in progress will be canceled",
-    "restart": "Restart"
+    "export_cancel_warning": "The following export in progress will be canceled",
+    "restart": "Restart",
+    "format": "Format",
+    "started_on": "Started on"
   },
   "message": {
     "successfully_connected": "Successfully Connected!",

+ 4 - 2
apps/app/public/static/locales/fr_FR/translation.json

@@ -639,8 +639,10 @@
     "bulk_export_only_available_for": "Uniquement disponible pour AWS ou GCP",
     "export_in_progress": "Exportation en cours",
     "export_in_progress_explanation": "L'exportation avec le même format est déjà en cours. Souhaitez-vous redémarrer pour exporter le dernier contenu de la page ?",
-    "export_cancel_warning": "L'export en cours sera annulé",
-    "restart": "Redémarrage"
+    "export_cancel_warning": "Les exportations suivantes en cours seront annulées",
+    "restart": "Redémarrage",
+    "format": "Format",
+    "started_on": "Commencé le"
   },
   "message": {
     "successfully_connected": "Connecté!",

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

@@ -678,8 +678,10 @@
     "bulk_export_only_available_for": "AWS と GCP のみ対応しています",
     "export_in_progress": "エクスポート進行中",
     "export_in_progress_explanation": "既に同じ形式でのエクスポートが進行中です。最新のページ内容でエクスポートを最初からやり直しますか?",
-    "export_cancel_warning": "進行中のエクスポートはキャンセルされます",
-    "restart": "やり直す"
+    "export_cancel_warning": "進行中の以下のエクスポートはキャンセルされます",
+    "restart": "やり直す",
+    "format": "形式",
+    "started_on": "開始日時"
   },
   "message": {
     "successfully_connected": "接続に成功しました!",

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

@@ -648,8 +648,10 @@
     "bulk_export_only_available_for": "仅适用于 AWS 或 GCP",
     "export_in_progress": "导出正在进行中",
     "export_in_progress_explanation": "已在进行相同格式的导出。您要重新启动以导出最新的页面内容吗?",
-    "export_cancel_warning": "正在进行的导出将被取消",
-    "restart": "重新开始"
+    "export_cancel_warning": "以下正在进行的导出将被取消",
+    "restart": "重新开始",
+    "format": "格式",
+    "started_on": "开始于"
   },
   "message": {
     "successfully_connected": "连接成功!",

+ 18 - 5
apps/app/src/features/page-bulk-export/client/components/PageBulkExportSelectModal.tsx

@@ -1,5 +1,6 @@
 import { useState } from 'react';
 
+import { format } from 'date-fns/format';
 import { useTranslation } from 'next-i18next';
 import { Modal, ModalHeader, ModalBody } from 'reactstrap';
 
@@ -15,7 +16,8 @@ const PageBulkExportSelectModal = (): JSX.Element => {
   const { data: currentPagePath } = useCurrentPagePath();
 
   const [isRestartModalOpened, setIsRestartModalOpened] = useState(false);
-  const [formatMemoForRestart, setFormatMemoForRestart] = useState<PageBulkExportFormat | null>(null);
+  const [formatMemoForRestart, setFormatMemoForRestart] = useState<PageBulkExportFormat | undefined>(undefined);
+  const [duplicateJobInfo, setDuplicateJobInfo] = useState<{createdAt: string} | undefined>(undefined);
 
   const startBulkExport = async(format: PageBulkExportFormat) => {
     try {
@@ -26,6 +28,7 @@ const PageBulkExportSelectModal = (): JSX.Element => {
     catch (e) {
       const errorCode = e?.[0].code ?? 'page_export.failed_to_export';
       if (errorCode === 'page_export.duplicate_bulk_export_job_error') {
+        setDuplicateJobInfo(e[0].args.duplicateJob);
         setIsRestartModalOpened(true);
       }
       else {
@@ -79,11 +82,21 @@ const PageBulkExportSelectModal = (): JSX.Element => {
         </ModalHeader>
         <ModalBody>
           {t('page_export.export_in_progress_explanation')}
-          <div className="my-1 text-danger">
-            <small className="text-danger">
-              {t('page_export.export_cancel_warning')}
-            </small>
+          <div className="text-danger">
+            {t('page_export.export_cancel_warning')}:
           </div>
+          { duplicateJobInfo && (
+            <div className="my-1">
+              <ul>
+                { formatMemoForRestart && (
+                  <li>
+                    {t('page_export.format')}: {formatMemoForRestart === PageBulkExportFormat.md ? t('page_export.markdown') : 'PDF'}
+                  </li>
+                )}
+                <li>{t('page_export.started_on')}: {format(new Date(duplicateJobInfo.createdAt), 'MM/dd HH:mm')}</li>
+              </ul>
+            </div>
+          )}
           <div className="d-flex justify-content-center mt-3">
             <button className="btn btn-primary" type="button" onClick={() => restartBulkExport()}>
               {t('page_export.restart')}

+ 2 - 0
apps/app/src/features/page-bulk-export/interfaces/page-bulk-export.ts

@@ -37,6 +37,8 @@ export interface IPageBulkExportJob {
   attachment?: Ref<IAttachment>,
   status: PageBulkExportJobStatus,
   revisionListHash?: string, // Hash created from the list of revision IDs. Used to detect existing duplicate uploads.
+  createdAt?: Date,
+  updatedAt?: Date
 }
 
 export interface IPageBulkExportJobHasId extends IPageBulkExportJob, HasObjectId {}

+ 5 - 1
apps/app/src/features/page-bulk-export/server/routes/apiv3/page-bulk-export.ts

@@ -48,7 +48,11 @@ module.exports = (crowi: Crowi): Router => {
     catch (err) {
       logger.error(err);
       if (err instanceof DuplicateBulkExportJobError) {
-        return res.apiv3Err(new ErrorV3('Duplicate bulk export job is in progress', 'page_export.duplicate_bulk_export_job_error'), 409);
+        return res.apiv3Err(new ErrorV3(
+          'Duplicate bulk export job is in progress',
+          'page_export.duplicate_bulk_export_job_error', undefined,
+          { duplicateJob: { createdAt: err.duplicateJob.createdAt } },
+        ), 409);
       }
       return res.apiv3Err(new ErrorV3('Failed to start bulk export', 'page_export.failed_to_export'));
     }

+ 8 - 1
apps/app/src/features/page-bulk-export/server/service/page-bulk-export/errors.ts

@@ -1,7 +1,14 @@
+import type { HydratedDocument } from 'mongoose';
+
+import type { PageBulkExportJobDocument } from '../../models/page-bulk-export-job';
+
 export class DuplicateBulkExportJobError extends Error {
 
-  constructor() {
+  duplicateJob: HydratedDocument<PageBulkExportJobDocument>;
+
+  constructor(duplicateJob: HydratedDocument<PageBulkExportJobDocument>) {
     super('Duplicate bulk export job is in progress');
+    this.duplicateJob = duplicateJob;
   }
 
 }

+ 1 - 1
apps/app/src/features/page-bulk-export/server/service/page-bulk-export/index.ts

@@ -100,7 +100,7 @@ class PageBulkExportService implements IPageBulkExportService {
         this.restartBulkExportJob(duplicatePageBulkExportJobInProgress, activityParameters);
         return;
       }
-      throw new DuplicateBulkExportJobError();
+      throw new DuplicateBulkExportJobError(duplicatePageBulkExportJobInProgress);
     }
     const pageBulkExportJob: HydratedDocument<PageBulkExportJobDocument> = await PageBulkExportJob.create({
       user: currentUser, page: basePage, format, status: PageBulkExportJobStatus.initializing,