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

# Feature/45 duplicate page
* Add duplicate-page modal.
* Fix tag id "newPageName" for duplicate-page to "duplicatePageName" (because it was same id with move-page's "newPageName").
* Implement page-duplicate api.

Tatsuya Ise 8 лет назад
Родитель
Сommit
d096cf1953
5 измененных файлов с 136 добавлено и 5 удалено
  1. 48 0
      lib/models/page.js
  2. 1 0
      lib/routes/index.js
  3. 46 0
      lib/routes/page.js
  4. 36 0
      lib/views/modal/duplicate.html
  5. 5 5
      resource/js/legacy/crowi.js

+ 48 - 0
lib/models/page.js

@@ -1157,6 +1157,54 @@ module.exports = function(crowi) {
     });
   };
 
+  pageSchema.statics.duplicate = function (path, originPageData, user, options) {
+    var Page = this
+      , Revision = crowi.model('Revision')
+      , format = options.format || 'markdown'
+      , grant = options.grant || GRANT_PUBLIC
+      , originRevision = originPageData.revision
+
+    // force public
+    if (isPortalPath(path)) {
+      grant = GRANT_PUBLIC;
+    }
+
+    return new Promise(function (resolve, reject) {
+      Page.findOne({ path: path }, function (err, pageData) {
+        if (pageData) {
+          return reject(new Error('Cannot create new page to existed path'));
+        }
+
+        var newPage = new Page();
+        newPage.path = path;
+        newPage.creator = user;
+        newPage.lastUpdateUser = user;
+        newPage.createdAt = Date.now();
+        newPage.updatedAt = Date.now();
+        newPage.redirectTo = null;
+        newPage.grant = grant;
+        newPage.status = STATUS_PUBLISHED;
+        newPage.grantedUsers = [];
+        newPage.grantedUsers.push(user);
+
+        newPage.save(function (err, newPage) {
+          if (err) {
+            return reject(err);
+          }
+
+          var newRevision = Revision.prepareRevision(newPage, originRevision.body, user, { format: format });
+          Page.pushRevision(newPage, newRevision, user).then(function (data) {
+            resolve(data);
+            pageEvent.emit('create', data, user);
+          }).catch(function (err) {
+            debug('Push Revision Error on duplicate page', err);
+            return reject(err);
+          });
+        });
+      });
+    });
+  };
+
   pageSchema.statics.getHistories = function() {
     // TODO
     return;

+ 1 - 0
lib/routes/index.js

@@ -138,6 +138,7 @@ module.exports = function(crowi, app) {
   app.post('/_api/pages.remove'       , loginRequired(crowi, app) , csrf, page.api.remove); // (Avoid from API Token)
   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.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);

+ 46 - 0
lib/routes/page.js

@@ -1132,6 +1132,52 @@ module.exports = function(crowi, app) {
     });
   };
 
+  /**
+   * @api {post} /pages.duplicate Duplicate page
+   * @apiName DuplicatePage
+   * @apiGroup Page
+   *
+   * @apiParam {String} page_id Page Id.
+   * @apiParam {String} path
+   * @apiParam {String} revision_id
+   * @apiParam {String} new_path
+   * @apiParam {Bool} create_redirect
+   */
+  api.duplicate = function (req, res) {
+    var pageId = req.body.page_id;
+    var newPagePath = Page.normalizePath(req.body.new_path);
+    var grant = req.body.grant || null;
+    var page = {};
+
+    if (!Page.isCreatableName(newPagePath)) {
+      return res.json(ApiResponse.error(`このページ名は作成できません (${newPagePath})`));
+    }
+
+    Page.findPageByPath(newPagePath)
+      .then(function (page) {
+        // if page found, cannot cannot duplicate to that path
+        return res.json(ApiResponse.error(`このページ名は作成できません (${newPagePath})。ページが存在します。`));
+      }).catch(function (err) {
+
+        Page.findPageById(pageId)
+          .then(function (pageData) {
+            return Page.duplicate(newPagePath, pageData, req.user, { grant: grant });
+
+          }).then(function (data) {
+            if (!data) {
+              throw new Error('Failed to create page.');
+            }
+            var result = { page: data.toObject() };
+
+            result.page.lastUpdateUser = User.filterToPublicFields(data.lastUpdateUser);
+            result.page.creator = User.filterToPublicFields(data.creator);
+            return res.json(ApiResponse.success(result));
+          }).catch(function (err) {
+            return res.json(ApiResponse.error(err));
+          });;
+      });
+  };
+
   /**
    * @api {post} /pages.unlink Remove the redirecting page
    * @apiName UnlinkPage

+ 36 - 0
lib/views/modal/duplicate.html

@@ -0,0 +1,36 @@
+  <div class="modal" id="duplicatePage">
+    <div class="modal-dialog">
+      <div class="modal-content">
+
+      <form role="form" id="duplicatePageForm" onsubmit="return false;">
+
+        <div class="modal-header">
+          <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
+          <h4 class="modal-title">{{ t('Duplicate page') }}</h4>
+        </div>
+        <div class="modal-body">
+            <div class="form-group">
+              <label for="">{{ t('Current page name') }}</label><br>
+              <code>{{ page.path }}</code>
+            </div>
+            <div class="form-group">
+              <label for="duplicatePageName">{{ t('New page name') }}</label><br>
+              <div class="input-group">
+                <span class="input-group-addon">{{ config.crowi['app:url'] }}</span>
+                <input type="text" class="form-control" name="new_path" id="duplicatePageName" value="{{ page.path }}">
+              </div>
+            </div>
+        </div>
+        <div class="modal-footer">
+          <p><small class="pull-left" id="duplicatePageNameCheck"></small></p>
+          <input type="hidden" name="_csrf" value="{{ csrf() }}">
+          <input type="hidden" name="path" value="{{ page.path }}">
+          <input type="hidden" name="page_id" value="{{ page._id.toString() }}">
+          <input type="hidden" name="revision_id" value="{{ page.revision._id.toString() }}">
+          <input type="submit" class="btn btn-primary" value="Duplicate page">
+        </div>
+
+      </form>
+      </div><!-- /.modal-content -->
+    </div><!-- /.modal-dialog -->
+  </div><!-- /.modal -->

+ 5 - 5
resource/js/legacy/crowi.js

@@ -314,7 +314,7 @@ $(function() {
 
   // duplicate
   $('#duplicatePage').on('shown.bs.modal', function (e) {
-    $('#newPageName').focus();
+    $('#duplicatePageName').focus();
   });
   $('#duplicatePageForm, #unportalize-form').submit(function (e) {
     // create name-value map
@@ -331,16 +331,16 @@ $(function() {
     }).done(function (res) {
       if (!res.ok) {
         // if already exists
-        $('#newPageNameCheck').html('<i class="fa fa-times-circle"></i> ' + res.error);
-        $('#newPageNameCheck').addClass('alert-danger');
+        $('#duplicatePageNameCheck').html('<i class="fa fa-times-circle"></i> ' + res.error);
+        $('#duplicatePageNameCheck').addClass('alert-danger');
         $('#linkToNewPage').html(`
           <i class="fa fa-fw fa-arrow-right"></i><a href="${nameValueMap.new_path}">${nameValueMap.new_path}</a>
         `);
       } else {
         var page = res.page;
 
-        $('#newPageNameCheck').removeClass('alert-danger');
-        $('#newPageNameCheck').html('<img src="/images/loading_s.gif"> Page duplicated! Redirecting to new page location.');
+        $('#duplicatePageNameCheck').removeClass('alert-danger');
+        $('#duplicatePageNameCheck').html('<img src="/images/loading_s.gif"> Page duplicated! Redirecting to new page location.');
 
         setTimeout(function () {
           top.location.href = page.path + '?duplicated=' + pagePath;