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

Merge pull request #2456 from weseek/feat/security-settings-share-link-for-sub-merge

Feat/security settings share link for sub merge
Ryuichi Paul E. Egoshi 5 лет назад
Родитель
Сommit
02b2ba70c7

+ 89 - 20
src/client/js/components/Admin/Security/ShareLinkSetting.jsx

@@ -1,13 +1,15 @@
-import React from 'react';
+import React, { Fragment } from 'react';
 import PropTypes from 'prop-types';
 import { withTranslation } from 'react-i18next';
 
 import { withUnstatedContainers } from '../../UnstatedUtils';
 import { toastSuccess, toastError } from '../../../util/apiNotification';
 
+import PaginationWrapper from '../../PaginationWrapper';
+
 import AppContainer from '../../../services/AppContainer';
+import AdminGeneralSecurityContainer from '../../../services/AdminGeneralSecurityContainer';
 
-import ShareLinkList from '../../ShareLinkList';
 import DeleteAllShareLinksModal from './DeleteAllShareLinksModal';
 
 class ShareLinkSetting extends React.Component {
@@ -16,15 +18,28 @@ class ShareLinkSetting extends React.Component {
     super();
 
     this.state = {
-      shareLinks: [],
       isDeleteConfirmModalShown: false,
     };
-
+    this.getShareLinkList = this.getShareLinkList.bind(this);
     this.showDeleteConfirmModal = this.showDeleteConfirmModal.bind(this);
     this.closeDeleteConfirmModal = this.closeDeleteConfirmModal.bind(this);
     this.deleteAllLinksButtonHandler = this.deleteAllLinksButtonHandler.bind(this);
   }
 
+  componentWillMount() {
+    this.getShareLinkList(1);
+  }
+
+  async getShareLinkList(page) {
+    try {
+      await this.props.adminGeneralSecurityContainer.retrieveShareLinksByPagingNum(page);
+    }
+    catch (err) {
+      toastError(err);
+    }
+
+  }
+
   showDeleteConfirmModal() {
     this.setState({ isDeleteConfirmModalShown: true });
   }
@@ -49,44 +64,98 @@ class ShareLinkSetting extends React.Component {
 
 
   render() {
-    return (
-      <>
-        <h2 className="border-bottom mb-3">
-          Shared Link List
+    const { adminGeneralSecurityContainer } = this.props;
+
+    const pager = (
+      <div className="pull-right my-3">
+        <PaginationWrapper
+          activePage={adminGeneralSecurityContainer.state.shareLinksActivePage}
+          changePage={this.getShareLinkList}
+          totalItemsCount={adminGeneralSecurityContainer.state.totalshareLinks}
+          pagingLimit={adminGeneralSecurityContainer.state.shareLinksPagingLimit}
+        />
+      </div>
+    );
+
+    const deleteAllButton = (
+      adminGeneralSecurityContainer.state.shareLinks.length > 0
+        ? (
           <button
+            className="pull-right btn btn-danger"
             type="button"
-            className="btn btn-danger pull-right"
-            disabled={this.state.shareLinks.length === 0}
             onClick={this.showDeleteConfirmModal}
           >
             Delete all links
           </button>
-        </h2>
+        )
+        : (
+          <p className="pull-right mr-2">No share links</p>
+        )
+    );
 
-        <ShareLinkList
-          shareLinks={this.state.shareLinks}
-          onClickDeleteButton={this.deleteLinkById}
-        />
+    return (
+      <Fragment>
+        <div className="mb-3">
+          {deleteAllButton}
+          <h2 className="alert-anchor border-bottom">Shared Link List</h2>
+        </div>
+
+        {pager}
+        <div className="table-responsive">
+          <table className="table table-bordered">
+            <thead>
+              <tr>
+                <th>Link</th>
+                <th>PagePath</th>
+                <th>Expiration</th>
+                <th>Description</th>
+                <th>Order</th>
+              </tr>
+            </thead>
+            <tbody>
+              {adminGeneralSecurityContainer.state.shareLinks.map((sharelink) => {
+                return (
+                  <tr key={sharelink._id}>
+                    <td>{sharelink._id}</td>
+                    <td><a href={sharelink.relatedPage.path}>{sharelink.relatedPage.path}</a></td>
+                    <td>{sharelink.expiredAt}</td>
+                    <td>{sharelink.description}</td>
+                    <td>
+                      <button
+                        className="btn btn-outline-warning"
+                        type="button"
+                        shareLinks={sharelink._id}
+                        onClickDeleteButton={this.deleteLinkById}
+                      >
+                        <i className="icon-trash mr-2"></i>Delete
+                      </button>
+                    </td>
+                  </tr>
+                );
+              })}
+            </tbody>
+          </table>
+        </div>
 
         <DeleteAllShareLinksModal
           isOpen={this.state.isDeleteConfirmModalShown}
           onClose={this.closeDeleteConfirmModal}
-          count={this.state.shareLinks.length}
+          count={adminGeneralSecurityContainer.state.shareLinks.length}
           onClickDeleteButton={this.deleteAllLinksButtonHandler}
         />
 
-      </>
+      </Fragment>
     );
   }
 
 }
 
-const ShareLinkSettingWrapper = withUnstatedContainers(ShareLinkSetting, [AppContainer]);
+const ShareLinkSettingWrapper = withUnstatedContainers(ShareLinkSetting, [AppContainer, AdminGeneralSecurityContainer]);
 
 ShareLinkSetting.propTypes = {
-  t: PropTypes.func.isRequired, // i18next
-
+  t: PropTypes.func.isRequired, //  i18next
   appContainer: PropTypes.instanceOf(AppContainer).isRequired,
+  adminGeneralSecurityContainer: PropTypes.instanceOf(AdminGeneralSecurityContainer).isRequired,
 };
 
 export default withTranslation()(ShareLinkSettingWrapper);

+ 29 - 0
src/client/js/services/AdminGeneralSecurityContainer.js

@@ -30,6 +30,10 @@ export default class AdminGeneralSecurityContainer extends Container {
       isGitHubEnabled: false,
       isTwitterEnabled: false,
       setupStrategies: [],
+      shareLinks: [],
+      totalshareLinks: 0,
+      shareLinksPagingLimit: Infinity,
+      shareLinksActivePage: 1,
     };
 
   }
@@ -151,6 +155,31 @@ export default class AdminGeneralSecurityContainer extends Container {
     }
   }
 
+  /**
+   * Retrieve All Sharelinks
+   */
+  async retrieveShareLinksByPagingNum(page) {
+
+    const params = {
+      page,
+    };
+
+    const { data } = await this.appContainer.apiv3.get('/security-setting/all-share-links', params);
+
+    if (data.paginateResult == null) {
+      throw new Error('data must conclude \'paginateResult\' property.');
+    }
+
+    const { docs: shareLinks, totalDocs: totalshareLinks, limit: shareLinksPagingLimit } = data.paginateResult;
+
+    this.setState({
+      shareLinks,
+      totalshareLinks,
+      shareLinksPagingLimit,
+      shareLinksActivePage: page,
+    });
+  }
+
   /**
    * Switch local enabled
    */

+ 8 - 4
src/server/routes/apiv3/security-setting.js

@@ -565,20 +565,24 @@ module.exports = (crowi) => {
    *                      type: object
    *                      description: suceed to get all share links
    */
-  router.get('/all-share-links/', /* loginRequiredStrictly, adminRequired, csrf, ApiV3FormValidator, */ async(req, res) => {
+  router.get('/all-share-links/', loginRequiredStrictly, adminRequired, async(req, res) => {
     const ShareLink = crowi.model('ShareLink');
     const page = parseInt(req.query.page) || 1;
     const limit = 10;
     const linkQuery = {};
     try {
-      const shareLinksResult = await ShareLink.paginate(
+      const paginateResult = await ShareLink.paginate(
         linkQuery,
         {
           page,
           limit,
+          populate: {
+            path: 'relatedPage',
+            select: 'path',
+          },
         },
       );
-      return res.apiv3({ shareLinksResult });
+      return res.apiv3({ paginateResult });
     }
     catch (err) {
       const msg = 'Error occured in get share link';
@@ -599,7 +603,7 @@ module.exports = (crowi) => {
    *            description: succeed to delete all share links
    */
 
-  router.delete('/all-share-links/', loginRequiredStrictly, adminRequired, csrf, async(req, res) => {
+  router.delete('/all-share-links/', loginRequiredStrictly, adminRequired, async(req, res) => {
     const ShareLink = crowi.model('ShareLink');
     try {
       const removedAct = await ShareLink.remove({});