diff --git a/application/Espo/Core/Controllers/Record.php b/application/Espo/Core/Controllers/Record.php index 05d7d7b8c5..b12f0ce9c9 100644 --- a/application/Espo/Core/Controllers/Record.php +++ b/application/Espo/Core/Controllers/Record.php @@ -314,9 +314,7 @@ class Record extends Base $params['ids'] = $data['ids']; } - $idsRemoved = $this->getRecordService()->massRemove($params); - - return $idsRemoved; + return $this->getRecordService()->massRemove($params); } public function actionCreateLink($params, $data, $request) @@ -464,5 +462,31 @@ class Record extends Base return $this->getRecordService()->getDuplicateAttributes($data['id']); } + + public function postActionMassFollow($params, $data, $request) + { + if (!$this->getAcl()->check($this->name, 'stream')) { + throw new Forbidden(); + } + + if (array_key_exists('ids', $data)) { + $params['ids'] = $data['ids']; + } + + return $this->getRecordService()->massFollow($params); + } + + public function postActionMassUnfollow($params, $data, $request) + { + if (!$this->getAcl()->check($this->name, 'stream')) { + throw new Forbidden(); + } + + if (array_key_exists('ids', $data)) { + $params['ids'] = $data['ids']; + } + + return $this->getRecordService()->massUnfollow($params); + } } diff --git a/application/Espo/Resources/i18n/de_DE/Global.json b/application/Espo/Resources/i18n/de_DE/Global.json index 581175755f..4ec444ec78 100644 --- a/application/Espo/Resources/i18n/de_DE/Global.json +++ b/application/Espo/Resources/i18n/de_DE/Global.json @@ -240,7 +240,8 @@ "remove": "Löschen", "merge": "Zusammenführen", "massUpdate": "Massenänderung", - "export": "Exportieren" + "export": "Exportieren", + "follow": "Abonnieren" }, "fields": { "name": "Name", diff --git a/application/Espo/Resources/i18n/en_US/Global.json b/application/Espo/Resources/i18n/en_US/Global.json index 2966f87c9a..eded7bd2c3 100644 --- a/application/Espo/Resources/i18n/en_US/Global.json +++ b/application/Espo/Resources/i18n/en_US/Global.json @@ -232,7 +232,15 @@ "checkForNewNotifications": "Check for new notifications", "checkForNewNotes": "Check for stream updates", "internalPost": "Post will be seen only by internal users", - "done": "Done" + "done": "Done", + "confirmMassFollow": "Are you sure you want to follow selected records?", + "confirmMassUnfollow": "Are you sure you want to unfollow selected records?", + "massFollowResult": "{count} records now are followed", + "massUnfollowResult": "{count} records now are not followed", + "massFollowResultSingle": "{count} record now is followed", + "massUnfollowResultSingle": "{count} record now is not followed", + "massFollowZeroResult": "Nothing got followed", + "massUnfollowZeroResult": "Nothing got unfollowed" }, "boolFilters": { "onlyMy": "Only My", @@ -246,7 +254,9 @@ "remove": "Remove", "merge": "Merge", "massUpdate": "Mass Update", - "export": "Export" + "export": "Export", + "follow": "Follow", + "unfollow": "Unfollow" }, "fields": { "name": "Name", diff --git a/application/Espo/Services/Record.php b/application/Espo/Services/Record.php index 8923aeb58b..2777e90f2e 100644 --- a/application/Espo/Services/Record.php +++ b/application/Espo/Services/Record.php @@ -1093,6 +1093,62 @@ class Record extends \Espo\Core\Services\Base return $this->getStreamService()->unfollowEntity($entity, $userId); } + public function massFollow(array $params, $userId = null) + { + $resultIdList = []; + + if (empty($userId)) { + $userId = $this->getUser()->id; + } + + $streamService = $this->getStreamService(); + + if (array_key_exists('ids', $params)) { + $idList = $params['ids']; + foreach ($idList as $id) { + $entity = $this->getEntity($id); + if ($entity && $this->getAcl()->check($entity, 'stream')) { + if ($streamService->followEntity($entity, $userId)) { + $resultIdList[] = $entity->id; + } + } + } + } + + return array( + 'ids' => $resultIdList, + 'count' => count($resultIdList) + ); + } + + public function massUnfollow(array $params, $userId = null) + { + $resultIdList = []; + + if (empty($userId)) { + $userId = $this->getUser()->id; + } + + $streamService = $this->getStreamService(); + + if (array_key_exists('ids', $params)) { + $idList = $params['ids']; + foreach ($idList as $id) { + $entity = $this->getEntity($id); + if ($entity && $this->getAcl()->check($entity, 'stream')) { + if ($streamService->unfollowEntity($entity, $userId)) { + $resultIdList[] = $entity->id; + } + } + } + } + + return array( + 'ids' => $resultIdList, + 'count' => count($resultIdList) + ); + } + protected function getDuplicateWhereClause(Entity $entity, $data = array()) { return false; diff --git a/client/src/views/record/list.js b/client/src/views/record/list.js index 675e8f3423..e3ed436834 100644 --- a/client/src/views/record/list.js +++ b/client/src/views/record/list.js @@ -469,6 +469,62 @@ Espo.define('views/record/list', 'view', function (Dep) { } }, + massActionFollow: function () { + var count = this.checkedList.length; + + var idList = []; + for (var i in this.checkedList) { + idList.push(this.checkedList[i]); + } + + var confirmMsg = this.translate('confirmMassFollow', 'messages').replace('{count}', count.toString()); + if (confirm(confirmMsg)) { + Espo.Ui.notify(this.translate('pleaseWait', 'messages')); + this.ajaxPostRequest(this.entityType + '/action/massFollow', { + ids: idList + }).then(function (result) { + var resultCount = result.count || 0; + var msg = 'massFollowResult'; + if (resultCount) { + if (resultCount === 1) { + msg += 'Single'; + } + Espo.Ui.success(this.translate(msg, 'messages').replace('{count}', resultCount)); + } else { + Espo.Ui.warning(this.translate('massFollowZeroResult', 'messages')); + } + }.bind(this)); + } + }, + + massActionUnfollow: function () { + var count = this.checkedList.length; + + var idList = []; + for (var i in this.checkedList) { + idList.push(this.checkedList[i]); + } + + var confirmMsg = this.translate('confirmMassUnfollow', 'messages').replace('{count}', count.toString()); + if (confirm(confirmMsg)) { + Espo.Ui.notify(this.translate('pleaseWait', 'messages')); + this.ajaxPostRequest(this.entityType + '/action/massUnfollow', { + ids: idList + }).then(function (result) { + var resultCount = result.count || 0; + var msg = 'massUnfollowResult'; + if (resultCount) { + if (resultCount === 1) { + msg += 'Single'; + } + Espo.Ui.success(this.translate(msg, 'messages').replace('{count}', resultCount)); + } else { + Espo.Ui.warning(this.translate('massUnfollowZeroResult', 'messages')); + } + }.bind(this)); + } + }, + massActionMerge: function () { if (!this.getAcl().check(this.entityType, 'edit')) { this.notify('Access denied', 'error'); @@ -552,6 +608,10 @@ Espo.define('views/record/list', 'view', function (Dep) { } }, + addMassAction: function (item) { + this.massActionList.push(item); + }, + setup: function () { if (typeof this.collection === 'undefined') { throw new Error('Collection has not been injected into Record.List view.'); @@ -618,6 +678,15 @@ Espo.define('views/record/list', 'view', function (Dep) { this.removeMassAction('export'); } + if ( + !this.massFollowDisabled && + this.getMetadata().get(['scopes', this.entityType, 'stream']) && + this.getAcl().check(this.entityType, 'stream') + ) { + this.addMassAction('follow'); + this.addMassAction('unfollow'); + } + if (this.selectable) { this.events['click .list a.link'] = function (e) { e.preventDefault();