Przeglądaj źródła

usable tag form

yusuketk 7 lat temu
rodzic
commit
6fac1f193b

+ 1 - 1
src/client/js/app.js

@@ -297,7 +297,7 @@ if (pageId) {
 }
 if (pagePath) {
   componentMappings.page = <Page crowi={crowi} crowiRenderer={crowiRenderer} markdown={markdown} pagePath={pagePath} showHeadEditButton onSaveWithShortcut={saveWithShortcut} />;
-  componentMappings['revision-path'] = <RevisionPath pagePath={pagePath} crowi={crowi} />;
+  componentMappings['revision-path'] = <RevisionPath pageId={pageId} pagePath={pagePath} crowi={crowi} />;
   componentMappings['revision-url'] = <RevisionUrl pageId={pageId} pagePath={pagePath} />;
 }
 

+ 37 - 30
src/client/js/components/Page/RevisionPath.js

@@ -1,8 +1,8 @@
 import React from 'react';
 import PropTypes from 'prop-types';
 import Button from 'react-bootstrap/es/Button';
+import Modal from 'react-bootstrap/es/Modal';
 import PageTagForm from '../PageTagForm';
-import Modal from 'react-bootstrap/es/Modal'
 
 import CopyButton from '../CopyButton';
 
@@ -13,6 +13,7 @@ export default class RevisionPath extends React.Component {
 
     this.state = {
       pages: [],
+      pageTags: [],
       isListPage: false,
       isLinkToListPage: true,
       isOpenEditTagModal: false,
@@ -20,11 +21,13 @@ export default class RevisionPath extends React.Component {
 
     // retrieve xss library from window
     this.xss = window.xss;
+    this.getPageTags = this.getPageTags.bind(this);
     this.handleShowEditTagModal = this.handleShowEditTagModal.bind(this);
     this.handleCloseEditTagModal = this.handleCloseEditTagModal.bind(this);
+    this.handleSubmitEditTagModal = this.handleSubmitEditTagModal.bind(this);
   }
 
-  componentWillMount() {
+  async componentWillMount() {
     // whether list page or not
     const isListPage = this.props.pagePath.match(/\/$/);
     this.setState({ isListPage });
@@ -52,6 +55,18 @@ export default class RevisionPath extends React.Component {
     });
 
     this.setState({ pages });
+
+    // set pageTag on button
+    if (this.props.pageId) {
+      const pageId = this.props.pageId;
+      const pageTags = await this.getPageTags(pageId);
+      this.setState({ pageTags });
+    }
+  }
+
+  async getPageTags(pageId) {
+    const res = await this.props.crowi.apiGet('/tags.get', { pageId });
+    return res.tags;
   }
 
   handleCloseEditTagModal() {
@@ -62,6 +77,11 @@ export default class RevisionPath extends React.Component {
     this.setState({ isOpenEditTagModal: true });
   }
 
+  handleSubmitEditTagModal() {
+    this.props.crowi.apiPost('/pages.updateTags', { pageId: this.props.pageId, newTags: this.state.pageTags });
+    this.setState({ isOpenEditTagModal: false });
+  }
+
   showToolTip() {
     $('#btnCopy').tooltip('show');
     setTimeout(() => {
@@ -140,41 +160,27 @@ export default class RevisionPath extends React.Component {
           <i className="icon-note" />
         </a>
         <span className="btn-tag-container">
-        <Button
-          variant="primary"
-          onClick={this.handleShowEditTagModal}
-          className="btn btn-default btn-tag"
-          style={tagButtonStyle}
-          data-toggle="tooltip"
-          data-placement="bottom"
-          title="#growi #wiki">
-          <i className="fa fa-tags"></i>
-        </Button>
+          <Button
+            variant="primary"
+            onClick={this.handleShowEditTagModal}
+            className="btn btn-default btn-tag"
+            style={tagButtonStyle}
+            data-toggle="tooltip"
+            data-placement="bottom"
+            title={this.state.pageTags}
+          >
+            <i className="fa fa-tags"></i>
+          </Button>
         </span>
-          {/* <div className="modal-content" >
-            <div className="modal-header bg-primary">
-              <div className="modal-title">ページタグを追加</div>
-              <button type="button" className="close" data-dismiss="modal" aria-hidden="true" onClick={this.closeEditTagModal}>&times;</button>
-            </div>
-            <div className="modal-body">
-            </div>
-            <div className="modal-footer">
-              <div className="d-flex justify-content-between">
-                <div className="float-right">
-                  <button type="button" className="btn btn-primary">追加</button>
-                </div>
-              </div>
-            </div>
-          </div> */}
         <Modal show={this.state.isOpenEditTagModal} onHide={this.handleCloseEditTagModal} id="editTagModal">
           <Modal.Header closeButton className="bg-primary">
-            <Modal.Title className="white" >ページタグを追加</Modal.Title>
+            <Modal.Title className="text-white">ページタグ</Modal.Title>
           </Modal.Header>
           <Modal.Body>
-            <PageTagForm crowi={this.props.crowi} defaultPageTags="[currentPageTags]" handleSubmit={console.log('###')} />
+            <PageTagForm crowi={this.props.crowi} defaultPageTags={this.state.pageTags} />
           </Modal.Body>
           <Modal.Footer>
-            <Button variant="primary" onClick={this.handleCloseEditTagModal}>
+            <Button variant="primary" onClick={this.handleSubmitEditTagModal}>
               更新
             </Button>
           </Modal.Footer>
@@ -186,6 +192,7 @@ export default class RevisionPath extends React.Component {
 }
 
 RevisionPath.propTypes = {
+  pageId: PropTypes.string,
   pagePath: PropTypes.string.isRequired,
   crowi: PropTypes.object.isRequired,
 };

+ 2 - 3
src/client/js/components/PageTagForm.jsx

@@ -36,8 +36,7 @@ export default class PageTagForm extends React.Component {
         <AsyncTypeahead
           allowNew
           caseSensitive={false}
-          defaultSelected={['growi', 'wiki']}
-          // defaultSelected={this.props.handleSubmit}
+          defaultSelected={this.props.defaultPageTags}
           emptyLabel=""
           isLoading={this.state.isLoading}
           minLength={1}
@@ -68,7 +67,7 @@ export default class PageTagForm extends React.Component {
 
 PageTagForm.propTypes = {
   crowi: PropTypes.object.isRequired,
-  defaultpageTags: PropTypes.array,
+  defaultPageTags: PropTypes.array,
   handleSubmit: PropTypes.func,
 };
 

+ 2 - 0
src/server/routes/index.js

@@ -201,7 +201,9 @@ module.exports = function(crowi, app) {
   app.post('/_api/pages.revertRemove' , loginRequired(crowi, app) , csrf, page.api.revertRemove); // (Avoid from API Token)
   app.post('/_api/pages.unlink'       , loginRequired(crowi, app) , csrf, page.api.unlink); // (Avoid from API Token)
   app.post('/_api/pages.duplicate'    , accessTokenParser, loginRequired(crowi, app), csrf, page.api.duplicate);
+  app.post('/_api/pages.updateTags'   , accessTokenParser, loginRequired(crowi, app), csrf, page.api.updateTags);
   app.get('/_api/tags.search'         , accessTokenParser, loginRequired(crowi, app, false), tag.api.search);
+  app.get('/_api/tags.get'            , accessTokenParser, loginRequired(crowi, app, false), tag.api.get);
   app.get('/_api/comments.get'        , accessTokenParser , loginRequired(crowi, app, false) , comment.api.get);
   app.post('/_api/comments.add'       , form.comment, accessTokenParser , loginRequired(crowi, app) , csrf, comment.api.add);
   app.post('/_api/comments.remove'    , accessTokenParser , loginRequired(crowi, app) , csrf, comment.api.remove);

+ 15 - 3
src/server/routes/page.js

@@ -611,7 +611,6 @@ module.exports = function(crowi, app) {
     const overwriteScopesOfDescendants = req.body.overwriteScopesOfDescendants || null;
     const isSlackEnabled = !!req.body.isSlackEnabled; // cast to boolean
     const slackChannels = req.body.slackChannels || null;
-    // const pageTags = req.body.pageTags || null;
     const isSyncRevisionToHackmd = !!req.body.isSyncRevisionToHackmd; // cast to boolean
     const socketClientId = req.body.socketClientId || undefined;
 
@@ -670,9 +669,22 @@ module.exports = function(crowi, app) {
     if (isSlackEnabled && slackChannels != null) {
       await notifyToSlackByUser(page, req.user, slackChannels, 'update', previousRevision);
     }
+  };
 
-    // // update page tag
-    // await page.updateTags(pageTags); [pagetag]
+  /**
+   * @api {post} /pages.updateTags update page tags
+   * @apiName UpdateTags
+   * @apiGroup Page
+   *
+   * @apiParam {ObjectId} pageId
+   * @apiParam {Array} pageTags
+   */
+  api.updateTags = async function(req, res) {
+    const pageId = req.body.pageId;
+    const newTags = req.body.newTags;
+    const page = await Page.findOne({ _id: pageId });
+    // update page tag
+    await page.updateTags(newTags);
   };
 
   /**