From c38b35b70750504be4e7bf860c3891fb88a63c06 Mon Sep 17 00:00:00 2001 From: OldHawk Date: Thu, 7 Dec 2017 17:47:05 +0800 Subject: [PATCH] feat(forums): admin/Moderators and topic owner can edit topic title when click on the title text #20 --- bower.json | 3 +- config/assets/default.js | 4 +- config/assets/production.js | 4 +- modules/core/client/app/trans-string-en.js | 1 + modules/core/client/app/trans-string-zh.js | 1 + .../editable-line.client.directive.js | 125 ++++++++++++++++++ modules/core/client/less/editable-line.less | 22 +++ .../forums-topic.client.controller.js | 15 +++ modules/forums/client/less/forum.less | 7 + .../client/views/topic.client.view.html | 5 +- .../controllers/forums.server.controller.js | 1 + 11 files changed, 184 insertions(+), 4 deletions(-) create mode 100644 modules/core/client/directives/editable-line.client.directive.js create mode 100644 modules/core/client/less/editable-line.less diff --git a/bower.json b/bower.json index d91de2e1..ad5b039f 100644 --- a/bower.json +++ b/bower.json @@ -34,7 +34,8 @@ "angular-side-overlay": "^1.0.3", "bootstrap-markdown": "^2.10.0", "font-awesome": "^4.7.0", - "ngprogress": "^1.1.3" + "ngprogress": "^1.1.3", + "jquery-awesome-cursor": "^0.3.1" }, "overrides": { "bootstrap": { diff --git a/config/assets/default.js b/config/assets/default.js index fe5c829e..592caa76 100644 --- a/config/assets/default.js +++ b/config/assets/default.js @@ -74,7 +74,9 @@ module.exports = { 'public/lib/bootstrap-markdown/js/bootstrap-markdown.js', 'public/lib/bootstrap-markdown/locale/bootstrap-markdown.zh.js', //ngProgress - 'public/lib/ngprogress/build/ngprogress.js' + 'public/lib/ngprogress/build/ngprogress.js', + //jquery-awesome-cursor + 'public/lib/jquery-awesome-cursor/dist/jquery.awesome-cursor.js' // endbower ], diff --git a/config/assets/production.js b/config/assets/production.js index 834ea9c4..c502d6f7 100644 --- a/config/assets/production.js +++ b/config/assets/production.js @@ -74,7 +74,9 @@ module.exports = { 'public/lib/bootstrap-markdown/js/bootstrap-markdown.js', 'public/lib/bootstrap-markdown/locale/bootstrap-markdown.zh.js', //ngProgress - 'public/lib/ngprogress/build/ngprogress.min.js' + 'public/lib/ngprogress/build/ngprogress.min.js', + //jquery-awesome-cursor + 'public/lib/jquery-awesome-cursor/dist/jquery.awesome-cursor.min.js' // endbower ] diff --git a/modules/core/client/app/trans-string-en.js b/modules/core/client/app/trans-string-en.js index 333cdaa6..ff6fb21d 100644 --- a/modules/core/client/app/trans-string-en.js +++ b/modules/core/client/app/trans-string-en.js @@ -950,6 +950,7 @@ BTN_SAVE: 'Save', BTN_CANCEL: 'Cancel', LINK_EDIT: 'Edit', + CLICK_TO_EDIT: 'Click to edit', BTN_DELETE: 'Delete', BTN_SUBMIT_TOPIC: 'Submit New Topic', BTN_SUBMIT_REPLY: 'Submit New Reply', diff --git a/modules/core/client/app/trans-string-zh.js b/modules/core/client/app/trans-string-zh.js index 3f4b42a6..301814dc 100644 --- a/modules/core/client/app/trans-string-zh.js +++ b/modules/core/client/app/trans-string-zh.js @@ -950,6 +950,7 @@ BTN_SAVE: '保存', BTN_CANCEL: '取消', LINK_EDIT: '编辑', + CLICK_TO_EDIT: '单击修改', BTN_DELETE: '删除', BTN_SUBMIT_TOPIC: '提交话题', BTN_SUBMIT_REPLY: '提交回复', diff --git a/modules/core/client/directives/editable-line.client.directive.js b/modules/core/client/directives/editable-line.client.directive.js new file mode 100644 index 00000000..22496fb8 --- /dev/null +++ b/modules/core/client/directives/editable-line.client.directive.js @@ -0,0 +1,125 @@ +(function () { + 'use strict'; + + angular.module('core') + .directive('editableLine', editableLine); + + editableLine.$inject = []; + + function editableLine() { + var highlightColor = 'transparent'; + + return { + restrict: 'A', + require: '^ngModel', + scope: { + ngModel: '=ngModel', + callback: '=', + callbackParameter: '=', + linkCallback: '=', + readonly: '=', + placeHolder: '@' + }, + template: '', + + link: function ($scope, $element, $attr) { + $scope.div = jQuery($element).find('.editable-line-display'); + $scope.input = jQuery($element).find('.editable-line-input'); + $scope.originalDivBackground = $scope.div.css('background-color'); + + $scope.div.awesomeCursor('wrench', { + color: '#ff6000', + flip: 'horizontal', + outline: '#ff3e00' + }); + + var originalValue; + $scope.div.bind('click', function () { + if ($scope.readonly) { + return; + } + originalValue = $scope.ngModel; + // get the cursor offset from display DIV + var sel = window.getSelection(); + var offset = sel.focusOffset; + // hide DIV and show INPUT + $scope.div.css('display', 'none'); + $scope.input.css('display', 'block'); + $scope.input.focus(); + // Move cursor to the same offset + var node = $scope.input.get(0); + node.setSelectionRange(offset, offset); + }); + $scope.input.bind('blur', function () { + if ($scope.callback) { + if (!$scope.ngModel) { + $scope.ngModel = originalValue; + $scope.$apply(); + } + if ($scope.callbackParameter !== undefined) { + $scope.callback($scope.ngModel !== originalValue, $scope.callbackParameter); + } else { + $scope.callback($scope.ngModel !== originalValue); + } + } + + $scope.div.css('display', 'block'); + $scope.input.css('display', 'none'); + $scope.refresh(); + }); + + $scope.div.bind('mouseover', function () { + if ($scope.readonly) { + return; + } + $scope.div.css('background-color', highlightColor); + }); + $scope.div.bind('mouseout', function () { + $scope.div.css('background-color', ''); // Removing CSS from DIV + }); + $element.bind('keydown', function (event) { + if (event.which === 13) { + event.target.blur(); + } else if (event.which === 27) { + // ESC key + $scope.ngModel = originalValue; + $scope.$apply(); + event.target.blur(); + } + }); + + $scope.refresh = function () { + var linkify = false; + var displayHtml = ' '; + + if (!$scope.readonly && ($scope.ngModel === '' || $scope.ngModel === undefined)) { + $scope.div.addClass('editable-line-placeholder'); + if ($scope.placeHolder) { + displayHtml = $scope.placeHolder; + } else { + displayHtml = ' '; + } + } else { + $scope.div.removeClass('editable-line-placeholder'); + if ($scope.linkCallback) { + displayHtml = '' + $scope.ngModel + ''; + } else { + displayHtml = $scope.ngModel; + } + } + $scope.div.html(displayHtml); + if ($scope.linkCallback) { + $scope.div.find('a.generated-link').click(function (e) { + e.stopPropagation(); + }); + } + }; + + $scope.$watch('ngModel', $scope.refresh); + // initialize + $scope.input.css('display', 'none'); + $scope.input.css('background', highlightColor); + } + }; + } +}()); diff --git a/modules/core/client/less/editable-line.less b/modules/core/client/less/editable-line.less new file mode 100644 index 00000000..40f3ef84 --- /dev/null +++ b/modules/core/client/less/editable-line.less @@ -0,0 +1,22 @@ +@import (reference) "mt-var.less"; + +.editable-line { + padding: 0; + margin: 0; + width: 100%; + word-wrap: break-word; + white-space: nowrap; + &:focus { + border: 1px dotted #ccc; + } +} + +.editable-line-display { + overflow: hidden; + text-overflow: ellipsis; +} + +.editable-line-placeholder { + color: #888888; + background-color: transparent; +} diff --git a/modules/forums/client/controllers/forums-topic.client.controller.js b/modules/forums/client/controllers/forums-topic.client.controller.js index c40bcad5..b03d70e0 100644 --- a/modules/forums/client/controllers/forums-topic.client.controller.js +++ b/modules/forums/client/controllers/forums-topic.client.controller.js @@ -189,6 +189,21 @@ } }; + /** + * onTopicTitleEdited + */ + $scope.onTopicTitleEdited = function (modifyed) { + console.log(modifyed); + if (vm.topic && modifyed) { + vm.topic.$update(function (res) { + vm.topic = res; + NotifycationService.showSuccessNotify('FORUMS.TOPIC_EDIT_SUCCESSFULLY'); + }, function (res) { + NotifycationService.showErrorNotify(res.data.message, 'FORUMS.TOPIC_EDIT_FAILED'); + }); + } + }; + /** * beginEditTopic * @param t diff --git a/modules/forums/client/less/forum.less b/modules/forums/client/less/forum.less index 5e962daa..7c1c4071 100644 --- a/modules/forums/client/less/forum.less +++ b/modules/forums/client/less/forum.less @@ -316,6 +316,13 @@ } } +.topic-view-title { + width: ~"calc(100% - 150px)"; + @media (max-width: @screen-sm-max) { + width: 100%; + } +} + /* csslint ignore:end */ .reply-item { diff --git a/modules/forums/client/views/topic.client.view.html b/modules/forums/client/views/topic.client.view.html index 2c011892..5741de96 100644 --- a/modules/forums/client/views/topic.client.view.html +++ b/modules/forums/client/views/topic.client.view.html @@ -49,7 +49,10 @@ -
{{vm.topic.title}}
+ +
+ +
{{'FORUMS.FIELDS.VIEWS' | translate}}: {{vm.topic.viewCount}}, diff --git a/modules/forums/server/controllers/forums.server.controller.js b/modules/forums/server/controllers/forums.server.controller.js index 444c0625..37b5721b 100644 --- a/modules/forums/server/controllers/forums.server.controller.js +++ b/modules/forums/server/controllers/forums.server.controller.js @@ -456,6 +456,7 @@ exports.updateTopic = function (req, res) { }); } + topic.title = req.body.title; topic.content = req.body.content; topic.updatedAt = Date.now(); topic.updatedBy = req.user;