Yuki Takei 6 лет назад
Родитель
Сommit
94496d7f5c

+ 43 - 6
src/client/js/components/Admin/Export/ExportPage.jsx

@@ -24,6 +24,7 @@ class ExportPage extends React.Component {
       progressList: [],
       progressList: [],
       isExportModalOpen: false,
       isExportModalOpen: false,
       isExporting: false,
       isExporting: false,
+      isZipping: false,
       isExported: false,
       isExported: false,
     };
     };
 
 
@@ -59,8 +60,17 @@ class ExportPage extends React.Component {
 
 
     // websocket event
     // websocket event
     socket.on('admin:onProgressForExport', ({ currentCount, totalCount, progressList }) => {
     socket.on('admin:onProgressForExport', ({ currentCount, totalCount, progressList }) => {
-      const isExporting = currentCount !== totalCount;
-      this.setState({ isExporting, progressList });
+      this.setState({
+        isExporting: true,
+        progressList,
+      });
+    });
+
+    // websocket event
+    socket.on('admin:onStartZippingForExport', () => {
+      this.setState({
+        isZipping: true,
+      });
     });
     });
 
 
     // websocket event
     // websocket event
@@ -69,6 +79,7 @@ class ExportPage extends React.Component {
 
 
       this.setState({
       this.setState({
         isExporting: false,
         isExporting: false,
+        isZipping: false,
         isExported: true,
         isExported: true,
         zipFileStats,
         zipFileStats,
       });
       });
@@ -141,16 +152,24 @@ class ExportPage extends React.Component {
    */
    */
   exportingRequestedHandler(status) {
   exportingRequestedHandler(status) {
     const { zipFileStats, isExporting, progressList } = status;
     const { zipFileStats, isExporting, progressList } = status;
-    this.setState({ zipFileStats, isExporting, progressList });
+    this.setState({
+      zipFileStats,
+      isExporting,
+      isZipping: false,
+      progressList,
+    });
   }
   }
 
 
   renderProgressBars() {
   renderProgressBars() {
-    const cols = this.state.progressList.map((progressData) => {
+    const { isZipping, isExported } = this.state;
+    const showZippingBar = isZipping || isExported;
+
+    const collectionCols = this.state.progressList.map((progressData) => {
       const { collectionName, currentCount, totalCount } = progressData;
       const { collectionName, currentCount, totalCount } = progressData;
       return (
       return (
         <div className="col-md-6" key={collectionName}>
         <div className="col-md-6" key={collectionName}>
           <ExportingProgressBar
           <ExportingProgressBar
-            collectionName={collectionName}
+            header={collectionName}
             currentCount={currentCount}
             currentCount={currentCount}
             totalCount={totalCount}
             totalCount={totalCount}
           />
           />
@@ -158,7 +177,25 @@ class ExportPage extends React.Component {
       );
       );
     });
     });
 
 
-    return <div className="row px-3">{cols}</div>;
+    const zipCol = (
+      <div className="col-md-12" key="progressBarForZipping">
+        <ExportingProgressBar
+          header="Zip"
+          currentCount={1}
+          totalCount={1}
+          isInProgress={isZipping}
+        />
+      </div>
+    );
+
+    return (
+      <>
+        <div className="row px-3">{collectionCols}</div>
+        { showZippingBar && (
+          <div className="row px-3">{zipCol}</div>
+        ) }
+      </>
+    );
   }
   }
 
 
   render() {
   render() {

+ 10 - 5
src/client/js/components/Admin/Export/ExportingProgressBar.jsx

@@ -6,15 +6,19 @@ class ExportingProgressBar extends React.Component {
 
 
 
 
   render() {
   render() {
-    const { collectionName, currentCount, totalCount } = this.props;
+    const {
+      header, currentCount, totalCount, isInProgress,
+    } = this.props;
 
 
     const percentage = currentCount / totalCount * 100;
     const percentage = currentCount / totalCount * 100;
-    const isActive = currentCount !== totalCount;
+    const isActive = (isInProgress != null)
+      ? isInProgress
+      : (currentCount !== totalCount);
 
 
     return (
     return (
       <>
       <>
-        <h5>
-          {collectionName}
+        <h5 className="my-1">
+          {header}
           <div className="pull-right">{currentCount} / {totalCount}</div>
           <div className="pull-right">{currentCount} / {totalCount}</div>
         </h5>
         </h5>
         <div className="progress progress-sm">
         <div className="progress progress-sm">
@@ -32,9 +36,10 @@ class ExportingProgressBar extends React.Component {
 }
 }
 
 
 ExportingProgressBar.propTypes = {
 ExportingProgressBar.propTypes = {
-  collectionName: PropTypes.string.isRequired,
+  header: PropTypes.string.isRequired,
   currentCount: PropTypes.number.isRequired,
   currentCount: PropTypes.number.isRequired,
   totalCount: PropTypes.number.isRequired,
   totalCount: PropTypes.number.isRequired,
+  isInProgress: PropTypes.bool,
 };
 };
 
 
 export default withTranslation()(ExportingProgressBar);
 export default withTranslation()(ExportingProgressBar);

+ 3 - 0
src/server/routes/apiv3/export.js

@@ -50,6 +50,9 @@ module.exports = (crowi) => {
   this.adminEvent.on('onProgressForExport', (data) => {
   this.adminEvent.on('onProgressForExport', (data) => {
     crowi.getIo().sockets.emit('admin:onProgressForExport', data);
     crowi.getIo().sockets.emit('admin:onProgressForExport', data);
   });
   });
+  this.adminEvent.on('onStartZippingForExport', (data) => {
+    crowi.getIo().sockets.emit('admin:onStartZippingForExport', data);
+  });
   this.adminEvent.on('onTerminateForExport', (data) => {
   this.adminEvent.on('onTerminateForExport', (data) => {
     crowi.getIo().sockets.emit('admin:onTerminateForExport', data);
     crowi.getIo().sockets.emit('admin:onTerminateForExport', data);
   });
   });

+ 10 - 0
src/server/service/export.js

@@ -226,6 +226,9 @@ class ExportService {
     const promises = collections.map(collectionName => this.exportCollectionToJson(collectionName));
     const promises = collections.map(collectionName => this.exportCollectionToJson(collectionName));
     const jsonFiles = await Promise.all(promises);
     const jsonFiles = await Promise.all(promises);
 
 
+    // send terminate event
+    this.emitStartZippingEvent();
+
     // zip json
     // zip json
     const configs = jsonFiles.map((jsonFile) => { return { from: jsonFile, as: path.basename(jsonFile) } });
     const configs = jsonFiles.map((jsonFile) => { return { from: jsonFile, as: path.basename(jsonFile) } });
     // add meta.json in zip
     // add meta.json in zip
@@ -301,6 +304,13 @@ class ExportService {
     this.adminEvent.emit('onProgressForExport', data);
     this.adminEvent.emit('onProgressForExport', data);
   }
   }
 
 
+  /**
+   * emit start zipping event
+   */
+  emitStartZippingEvent() {
+    this.adminEvent.emit('onStartZippingForExport', {});
+  }
+
   /**
   /**
    * emit terminate event
    * emit terminate event
    * @param {object} zipFileStat added zip file status data
    * @param {object} zipFileStat added zip file status data