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

conflict resolution ExportArchiveDataPage.tsx

Taichi Masuyama 3 лет назад
Родитель
Сommit
e51f3fbe2f

+ 0 - 261
packages/app/src/components/Admin/ExportArchiveDataPage.jsx

@@ -1,261 +0,0 @@
-import React from 'react';
-
-import { useTranslation } from 'next-i18next';
-import PropTypes from 'prop-types';
-import * as toastr from 'toastr';
-
-
-// import { toastSuccess, toastError } from '~/client/util/apiNotification';
-import { apiDelete, apiGet } from '~/client/util/apiv1-client';
-import { useAdminSocket } from '~/stores/socket-io';
-
-import LabeledProgressBar from './Common/LabeledProgressBar';
-import ArchiveFilesTable from './ExportArchiveData/ArchiveFilesTable';
-import SelectCollectionsModal from './ExportArchiveData/SelectCollectionsModal';
-
-
-const IGNORED_COLLECTION_NAMES = [
-  'sessions', 'rlflx', 'activities',
-];
-
-class ExportArchiveDataPage extends React.Component {
-
-  constructor(props) {
-    super(props);
-
-    this.state = {
-      collections: [],
-      zipFileStats: [],
-      progressList: [],
-      isExportModalOpen: false,
-      isExporting: false,
-      isZipping: false,
-      isExported: false,
-    };
-
-    this.onZipFileStatAdd = this.onZipFileStatAdd.bind(this);
-    this.onZipFileStatRemove = this.onZipFileStatRemove.bind(this);
-    this.openExportModal = this.openExportModal.bind(this);
-    this.closeExportModal = this.closeExportModal.bind(this);
-    this.exportingRequestedHandler = this.exportingRequestedHandler.bind(this);
-  }
-
-  async UNSAFE_componentWillMount() {
-    // TODO:: use apiv3.get
-    // eslint-disable-next-line no-unused-vars
-    const [{ collections }, { status }] = await Promise.all([
-      apiGet('/v3/mongo/collections', {}),
-      apiGet('/v3/export/status', {}),
-    ]);
-    // TODO: toastSuccess, toastError
-
-    // filter only not ignored collection names
-    const filteredCollections = collections.filter((collectionName) => {
-      return !IGNORED_COLLECTION_NAMES.includes(collectionName);
-    });
-
-    const { zipFileStats, isExporting, progressList } = status;
-    this.setState({
-      collections: filteredCollections,
-      zipFileStats,
-      isExporting,
-      progressList,
-    });
-
-    this.setupWebsocketEventHandler();
-  }
-
-  setupWebsocketEventHandler() {
-    const { socket } = this.props;
-
-    if (socket != null) {
-      // websocket event
-      socket.on('admin:onProgressForExport', ({ currentCount, totalCount, progressList }) => {
-        this.setState({
-          isExporting: true,
-          progressList,
-        });
-      });
-
-      // websocket event
-      socket.on('admin:onStartZippingForExport', () => {
-        this.setState({
-          isZipping: true,
-        });
-      });
-
-      // websocket event
-      socket.on('admin:onTerminateForExport', ({ addedZipFileStat }) => {
-        const zipFileStats = this.state.zipFileStats.concat([addedZipFileStat]);
-
-        this.setState({
-          isExporting: false,
-          isZipping: false,
-          isExported: true,
-          zipFileStats,
-        });
-
-        // TODO: toastSuccess, toastError
-        toastr.success(undefined, `New Archive Data '${addedZipFileStat.fileName}' is added`, {
-          closeButton: true,
-          progressBar: true,
-          newestOnTop: false,
-          showDuration: '100',
-          hideDuration: '100',
-          timeOut: '1200',
-          extendedTimeOut: '150',
-        });
-      });
-    }
-  }
-
-  onZipFileStatAdd(newStat) {
-    this.setState((prevState) => {
-      return {
-        zipFileStats: [...prevState.zipFileStats, newStat],
-      };
-    });
-  }
-
-  async onZipFileStatRemove(fileName) {
-    try {
-      await apiDelete(`/v3/export/${fileName}`, {});
-
-      this.setState((prevState) => {
-        return {
-          zipFileStats: prevState.zipFileStats.filter(stat => stat.fileName !== fileName),
-        };
-      });
-
-      // TODO: toastSuccess, toastError
-      toastr.success(undefined, `Deleted ${fileName}`, {
-        closeButton: true,
-        progressBar: true,
-        newestOnTop: false,
-        showDuration: '100',
-        hideDuration: '100',
-        timeOut: '1200',
-        extendedTimeOut: '150',
-      });
-    }
-    catch (err) {
-      // TODO: toastSuccess, toastError
-      toastr.error(err, 'Error', {
-        closeButton: true,
-        progressBar: true,
-        newestOnTop: false,
-        showDuration: '100',
-        hideDuration: '100',
-        timeOut: '3000',
-      });
-    }
-  }
-
-  openExportModal() {
-    this.setState({ isExportModalOpen: true });
-  }
-
-  closeExportModal() {
-    this.setState({ isExportModalOpen: false });
-  }
-
-  /**
-   * event handler invoked when export process was requested successfully
-   */
-  exportingRequestedHandler() {
-  }
-
-  renderProgressBarsForCollections() {
-    const cols = this.state.progressList.map((progressData) => {
-      const { collectionName, currentCount, totalCount } = progressData;
-      return (
-        <div className="col-md-6" key={collectionName}>
-          <LabeledProgressBar
-            header={collectionName}
-            currentCount={currentCount}
-            totalCount={totalCount}
-          />
-        </div>
-      );
-    });
-
-    return <div className="row px-3">{cols}</div>;
-  }
-
-  renderProgressBarForZipping() {
-    const { isZipping, isExported } = this.state;
-    const showZippingBar = isZipping || isExported;
-
-    if (!showZippingBar) {
-      return <></>;
-    }
-
-    return (
-      <div className="row px-3">
-        <div className="col-md-12" key="progressBarForZipping">
-          <LabeledProgressBar
-            header="Zip Files"
-            currentCount={1}
-            totalCount={1}
-            isInProgress={isZipping}
-          />
-        </div>
-      </div>
-    );
-  }
-
-  render() {
-    const { t } = this.props;
-    const { isExporting, isExported, progressList } = this.state;
-
-    const showExportingData = (isExported || isExporting) && (progressList != null);
-
-    return (
-      <div data-testid="admin-export-archive-data">
-        <h2>{t('export_management.export_archive_data')}</h2>
-
-        <button type="button" className="btn btn-outline-secondary" disabled={isExporting} onClick={this.openExportModal}>
-          {t('export_management.create_new_archive_data')}
-        </button>
-
-        { showExportingData && (
-          <div className="mt-5">
-            <h3>{t('export_management.exporting_collection_list')}</h3>
-            { this.renderProgressBarsForCollections() }
-            { this.renderProgressBarForZipping() }
-          </div>
-        ) }
-
-        <div className="mt-5">
-          <h3>{t('export_management.exported_data_list')}</h3>
-          <ArchiveFilesTable
-            zipFileStats={this.state.zipFileStats}
-            onZipFileStatRemove={this.onZipFileStatRemove}
-          />
-        </div>
-
-        <SelectCollectionsModal
-          isOpen={this.state.isExportModalOpen}
-          onExportingRequested={this.exportingRequestedHandler}
-          onClose={this.closeExportModal}
-          collections={this.state.collections}
-        />
-      </div>
-    );
-  }
-
-}
-
-ExportArchiveDataPage.propTypes = {
-  t: PropTypes.func.isRequired, // i18next
-  socket: PropTypes.object,
-};
-
-const ExportArchiveDataPageWrapperFC = (props) => {
-  const { t } = useTranslation('admin');
-  const { data: socket } = useAdminSocket();
-
-  return <ExportArchiveDataPage t={t} socket={socket} {...props} />;
-};
-
-export default ExportArchiveDataPageWrapperFC;

+ 200 - 0
packages/app/src/components/Admin/ExportArchiveDataPage.tsx

@@ -0,0 +1,200 @@
+import React, { useCallback, useEffect, useState } from 'react';
+
+import { useTranslation } from 'react-i18next';
+import * as toastr from 'toastr';
+
+
+import { apiDelete } from '~/client/util/apiv1-client';
+import { apiv3Get } from '~/client/util/apiv3-client';
+import { useAdminSocket } from '~/stores/socket-io';
+
+import LabeledProgressBar from './Common/LabeledProgressBar';
+import ArchiveFilesTable from './ExportArchiveData/ArchiveFilesTable';
+import SelectCollectionsModal from './ExportArchiveData/SelectCollectionsModal';
+
+
+const IGNORED_COLLECTION_NAMES = [
+  'sessions', 'rlflx', 'activities',
+];
+
+const ExportArchiveDataPage = (): JSX.Element => {
+  const { data: socket } = useAdminSocket();
+  const { t } = useTranslation();
+
+  const [collections, setCollections] = useState<any[]>([]);
+  const [zipFileStats, setZipFileStats] = useState<any[]>([]);
+  const [progressList, setProgressList] = useState<any[]>([]);
+  const [isExportModalOpen, setExportModalOpen] = useState(false);
+  const [isExporting, setExporting] = useState(false);
+  const [isZipping, setZipping] = useState(false);
+  const [isExported, setExported] = useState(false);
+
+  const fetchData = useCallback(async() => {
+    // TODO:: use apiv3.get
+    // eslint-disable-next-line no-unused-vars
+    const [{ data: collectionsData }, { data: statusData }] = await Promise.all([
+      apiv3Get<{collections: any[]}>('/mongo/collections', {}),
+      apiv3Get<{status: { zipFileStats: any[], isExporting: boolean, progressList: any[] }}>('/export/status', {}),
+    ]);
+    // TODO: toastSuccess, toastError
+
+    // filter only not ignored collection names
+    const filteredCollections = collectionsData.collections.filter((collectionName) => {
+      return !IGNORED_COLLECTION_NAMES.includes(collectionName);
+    });
+
+    const { zipFileStats, isExporting, progressList } = statusData.status;
+    setCollections(filteredCollections);
+    setZipFileStats(zipFileStats);
+    setExporting(isExporting);
+    setProgressList(progressList);
+  }, []);
+
+  const setupWebsocketEventHandler = useCallback(() => {
+    if (socket != null) {
+      // websocket event
+      socket.on('admin:onProgressForExport', ({ currentCount, totalCount, progressList }) => {
+        setExporting(true);
+        setProgressList(progressList);
+      });
+
+      // websocket event
+      socket.on('admin:onStartZippingForExport', () => {
+        setZipping(true);
+      });
+
+      // websocket event
+      socket.on('admin:onTerminateForExport', ({ addedZipFileStat }) => {
+
+        setExporting(false);
+        setZipping(false);
+        setExported(true);
+        setZipFileStats(prev => prev.concat([addedZipFileStat]));
+
+        // TODO: toastSuccess, toastError
+        toastr.success(undefined, `New Archive Data '${addedZipFileStat.fileName}' is added`, {
+          closeButton: true,
+          progressBar: true,
+          newestOnTop: false,
+          showDuration: '100',
+          hideDuration: '100',
+          timeOut: '1200',
+          extendedTimeOut: '150',
+        });
+      });
+    }
+  }, [socket]);
+
+  const onZipFileStatRemove = useCallback(async(fileName) => {
+    try {
+      await apiDelete(`/v3/export/${fileName}`, {});
+
+      setZipFileStats(prev => prev.filter(stat => stat.fileName !== fileName));
+
+      // TODO: toastSuccess, toastError
+      toastr.success(undefined, `Deleted ${fileName}`, {
+        closeButton: true,
+        progressBar: true,
+        newestOnTop: false,
+        showDuration: '100',
+        hideDuration: '100',
+        timeOut: '1200',
+        extendedTimeOut: '150',
+      });
+    }
+    catch (err) {
+      // TODO: toastSuccess, toastError
+      toastr.error(err, 'Error', {
+        closeButton: true,
+        progressBar: true,
+        newestOnTop: false,
+        showDuration: '100',
+        hideDuration: '100',
+        timeOut: '3000',
+      });
+    }
+  }, []);
+
+  const exportingRequestedHandler = useCallback(() => {}, []);
+
+  const renderProgressBarsForCollections = useCallback(() => {
+    const cols = progressList.map((progressData) => {
+      const { collectionName, currentCount, totalCount } = progressData;
+      return (
+        <div className="col-md-6" key={collectionName}>
+          <LabeledProgressBar
+            header={collectionName}
+            currentCount={currentCount}
+            totalCount={totalCount}
+          />
+        </div>
+      );
+    });
+
+    return <div className="row px-3">{cols}</div>;
+  }, [progressList]);
+
+  const renderProgressBarForZipping = useCallback(() => {
+    const showZippingBar = isZipping || isExported;
+
+    if (!showZippingBar) {
+      return <></>;
+    }
+
+    return (
+      <div className="row px-3">
+        <div className="col-md-12" key="progressBarForZipping">
+          <LabeledProgressBar
+            header="Zip Files"
+            currentCount={1}
+            totalCount={1}
+            isInProgress={isZipping}
+          />
+        </div>
+      </div>
+    );
+  }, [isExported, isZipping]);
+
+  useEffect(() => {
+    fetchData();
+
+    setupWebsocketEventHandler();
+  }, [fetchData, setupWebsocketEventHandler]);
+
+  const showExportingData = (isExported || isExporting) && (progressList != null);
+
+  return (
+    <div data-testid="admin-export-archive-data">
+      <h2>{t('export_management.export_archive_data')}</h2>
+
+      <button type="button" className="btn btn-outline-secondary" disabled={isExporting} onClick={() => setExportModalOpen(true)}>
+        {t('export_management.create_new_archive_data')}
+      </button>
+
+      { showExportingData && (
+        <div className="mt-5">
+          <h3>{t('export_management.exporting_collection_list')}</h3>
+          { renderProgressBarsForCollections() }
+          { renderProgressBarForZipping() }
+        </div>
+      ) }
+
+      <div className="mt-5">
+        <h3>{t('export_management.exported_data_list')}</h3>
+        <ArchiveFilesTable
+          zipFileStats={zipFileStats}
+          onZipFileStatRemove={onZipFileStatRemove}
+        />
+      </div>
+
+      <SelectCollectionsModal
+        isOpen={isExportModalOpen}
+        onExportingRequested={exportingRequestedHandler}
+        onClose={() => setExportModalOpen(false)}
+        collections={collections}
+      />
+    </div>
+  );
+};
+
+export default ExportArchiveDataPage;