diff --git a/application/Espo/Core/ControllerManager.php b/application/Espo/Core/ControllerManager.php index f80e7c86bd..a86e5c7f10 100644 --- a/application/Espo/Core/ControllerManager.php +++ b/application/Espo/Core/ControllerManager.php @@ -99,7 +99,7 @@ class ControllerManager } if (!method_exists($controller, $primaryActionMethodName)) { - throw new NotFound("Action '$actionName' (".$request->getMethod().") does not exist in controller '$controller'"); + throw new NotFound("Action '$actionName' (".$request->getMethod().") does not exist in controller '$controllerName'"); } if (method_exists($controller, $beforeMethodName)) { diff --git a/application/Espo/Core/Controllers/Record.php b/application/Espo/Core/Controllers/Record.php index 1c542206c7..bd432d3818 100644 --- a/application/Espo/Core/Controllers/Record.php +++ b/application/Espo/Core/Controllers/Record.php @@ -124,6 +124,9 @@ class Record extends Base $asc = $request->get('asc') === 'true'; $sortBy = $request->get('sortBy'); $q = $request->get('q'); + $primaryFilter = $request->get('primaryFilter'); + $textFilter = $request->get('textFilter'); + $boolFilterList = $request->get('boolFilterList'); if (empty($maxSize)) { $maxSize = self::MAX_SIZE_LIMIT; @@ -139,6 +142,9 @@ class Record extends Base 'asc' => $asc, 'sortBy' => $sortBy, 'q' => $q, + 'primaryFilter' => $primaryFilter, + 'textFilter' => $textFilter, + 'boolFilterList' => $boolFilterList ); if ($request->get('filter')) { $params['filter'] = $request->get('filter'); diff --git a/application/Espo/Core/SelectManagers/Base.php b/application/Espo/Core/SelectManagers/Base.php index 60012d5e27..358a219056 100644 --- a/application/Espo/Core/SelectManagers/Base.php +++ b/application/Espo/Core/SelectManagers/Base.php @@ -754,12 +754,6 @@ class Base } } - public function applyAccess(&$result) - { - $this->prepareResult($result); - $this->access($result); - } - public function applyTextFilter($textFilter, &$result) { $this->prepareResult($result); @@ -784,6 +778,12 @@ class Base ); } + public function applyAccess(&$result) + { + $this->prepareResult($result); + $this->access($result); + } + protected function boolFilters($params, &$result) { if (!empty($params['boolFilterList']) && is_array($params['boolFilterList'])) { @@ -795,8 +795,8 @@ class Base protected function primaryFilter($params, &$result) { - if (!empty($params['filter'])) { - $this->applyPrimaryFilter($params['filter'], $result); + if (!empty($params['primaryFilter'])) { + $this->applyPrimaryFilter($params['primaryFilter'], $result); } } diff --git a/application/Espo/Modules/Crm/Controllers/Activities.php b/application/Espo/Modules/Crm/Controllers/Activities.php index 9e8a92af3e..c5fdea2f23 100644 --- a/application/Espo/Modules/Crm/Controllers/Activities.php +++ b/application/Espo/Modules/Crm/Controllers/Activities.php @@ -52,6 +52,24 @@ class Activities extends \Espo\Core\Controllers\Base return $service->getEvents($userId, $from, $to); } + public function actionListUpcoming($params, $data, $request) + { + $service = $this->getService('Activities'); + + $userId = $request->get('userId'); + if (!$userId) { + $userId = $this->getUser()->id; + } + + $offset = intval($request->get('offset')); + $maxSize = intval($request->get('maxSize')); + + return $service->getUpcomingActivities($userId, array( + 'offset' => $offset, + 'maxSize' => $maxSize + )); + } + public function actionPopupNotifications() { $userId = $this->getUser()->id; diff --git a/application/Espo/Modules/Crm/Resources/i18n/en_US/Global.json b/application/Espo/Modules/Crm/Resources/i18n/en_US/Global.json index 11d3bd79ba..d16b89bcba 100644 --- a/application/Espo/Modules/Crm/Resources/i18n/en_US/Global.json +++ b/application/Espo/Modules/Crm/Resources/i18n/en_US/Global.json @@ -48,7 +48,8 @@ "OpportunitiesByStage": "Opportunities by Stage", "OpportunitiesByLeadSource": "Opportunities by Lead Source", "SalesByMonth": "Sales by Month", - "SalesPipeline": "Sales Pipeline" + "SalesPipeline": "Sales Pipeline", + "Activities": "My Activities" }, "labels": { "Create InboundEmail": "Create Inbound Email", diff --git a/application/Espo/Modules/Crm/Resources/metadata/dashlets/Activities.json b/application/Espo/Modules/Crm/Resources/metadata/dashlets/Activities.json new file mode 100644 index 0000000000..da278a93e5 --- /dev/null +++ b/application/Espo/Modules/Crm/Resources/metadata/dashlets/Activities.json @@ -0,0 +1,3 @@ +{ + "view":"crm:views/dashlets/activities" +} diff --git a/application/Espo/Modules/Crm/Services/Activities.php b/application/Espo/Modules/Crm/Services/Activities.php index 0d1deb5d32..4672ea7b66 100644 --- a/application/Espo/Modules/Crm/Services/Activities.php +++ b/application/Espo/Modules/Crm/Services/Activities.php @@ -34,7 +34,8 @@ class Activities extends \Espo\Core\Services\Base 'entityManager', 'user', 'metadata', - 'acl' + 'acl', + 'selectManagerFactory' ); protected function getPDO() @@ -62,6 +63,11 @@ class Activities extends \Espo\Core\Services\Base return $this->injections['metadata']; } + protected function getSelectManagerFactory() + { + return $this->getInjection('selectManagerFactory'); + } + protected function isPerson($scope) { return in_array($scope, ['Contact', 'Lead', 'User']); @@ -76,7 +82,7 @@ class Activities extends \Espo\Core\Services\Base meeting.parent_type AS 'parentType', meeting.parent_id AS 'parentId', meeting.status AS status, meeting.created_at AS createdAt FROM `meeting` LEFT JOIN `user` AS `assignedUser` ON assignedUser.id = meeting.assigned_user_id - JOIN `meeting_user` AS `usersMiddle` ON usersMiddle.meeting_id = meeting.id AND usersMiddle.deleted = 0 + JOIN `meeting_user` AS `usersMiddle` ON usersMiddle.meeting_id = meeting.id AND usersMiddle.deleted = 0 AND usersMiddle.status <> 'Declined' WHERE meeting.deleted = 0 AND usersMiddle.user_id = ".$pdo->quote($id)." "; if (!empty($notIn)) { @@ -96,7 +102,7 @@ class Activities extends \Espo\Core\Services\Base call.parent_type AS 'parentType', call.parent_id AS 'parentId', call.status AS status, call.created_at AS createdAt FROM `call` LEFT JOIN `user` AS `assignedUser` ON assignedUser.id = call.assigned_user_id - JOIN `call_user` AS `usersMiddle` ON usersMiddle.call_id = call.id AND usersMiddle.deleted = 0 + JOIN `call_user` AS `usersMiddle` ON usersMiddle.call_id = call.id AND usersMiddle.deleted = 0 AND usersMiddle.status <> 'Declined' WHERE call.deleted = 0 AND usersMiddle.user_id = ".$pdo->quote($id)." "; if (!empty($notIn)) { @@ -428,8 +434,6 @@ class Activities extends \Espo\Core\Services\Base "; } - - $sth = $pdo->prepare($qu); if (!empty($params['maxSize'])) { @@ -508,10 +512,13 @@ class Activities extends \Espo\Core\Services\Base $fetchAll = empty($params['scope']); - $parts = array( - 'Meeting' => ($fetchAll || $params['scope'] == 'Meeting') ? $this->getMeetingQuery($scope, $id, 'NOT IN', ['Held', 'Not Held']) : [], - 'Call' => ($fetchAll || $params['scope'] == 'Call') ? $this->getCallQuery($scope, $id, 'NOT IN', ['Held', 'Not Held']) : [], - ); + $parts = array(); + if ($this->getAcl()->checkScope('Meeting')) { + $parts['Meeting'] = ($fetchAll || $params['scope'] == 'Meeting') ? $this->getMeetingQuery($scope, $id, 'NOT IN', ['Held', 'Not Held']) : []; + } + if ($this->getAcl()->checkScope('Call')) { + $parts['Call'] = ($fetchAll || $params['scope'] == 'Call') ? $this->getCallQuery($scope, $id, 'NOT IN', ['Held', 'Not Held']) : []; + } return $this->getResult($parts, $scope, $id, $params); } @@ -523,11 +530,16 @@ class Activities extends \Espo\Core\Services\Base $fetchAll = empty($params['scope']); - $parts = array( - 'Meeting' => ($fetchAll || $params['scope'] == 'Meeting') ? $this->getMeetingQuery($scope, $id, 'IN', ['Held', 'Not Held']) : [], - 'Call' => ($fetchAll || $params['scope'] == 'Call') ? $this->getCallQuery($scope, $id, 'IN', ['Held', 'Not Held']) : [], - 'Email' => ($fetchAll || $params['scope'] == 'Email') ? $this->getEmailQuery($scope, $id, 'IN', ['Archived', 'Sent']) : [], - ); + $parts = array(); + if ($this->getAcl()->checkScope('Meeting')) { + $parts['Meeting'] = ($fetchAll || $params['scope'] == 'Meeting') ? $this->getMeetingQuery($scope, $id, 'IN', ['Held', 'Not Held']) : []; + } + if ($this->getAcl()->checkScope('Call')) { + $parts['Call'] = ($fetchAll || $params['scope'] == 'Call') ? $this->getCallQuery($scope, $id, 'IN', ['Held', 'Not Held']) : []; + } + if ($this->getAcl()->checkScope('Email')) { + $parts['Email'] = ($fetchAll || $params['scope'] == 'Email') ? $this->getEmailQuery($scope, $id, 'IN', ['Archived', 'Sent']) : []; + } $result = $this->getResult($parts, $scope, $id, $params); foreach ($result['list'] as &$item) { @@ -680,5 +692,94 @@ class Activities extends \Espo\Core\Services\Base } return $result; } + + public function getUpcomingActivities($userId, $params) + { + $user = $this->getEntityManager()->getEntity('User', $userId); + $this->accessCheck($user); + + $entityTypeList = ['Meeting', 'Call']; + + $unionPartList = []; + foreach ($entityTypeList as $entityType) { + if (!$this->getAcl()->checkScope($entityType, 'read')) { + continue; + } + + + $selectParams = array( + 'select' => ['id', 'name', 'dateStart', ['VALUE:' . $entityType, 'entityType']], + ); + + $selectManager = $this->getSelectManagerFactory()->create($entityType); + + + $selectManager->applyAccess($selectParams); + $selectManager->applyTextFilter($query, $selectParams); + $selectManager->applyPrimaryFilter('planned', $selectParams); + $selectManager->applyBoolFilter('onlyMy', $selectParams); + $selectManager->applyWhere(array( + '1' => array( + 'type' => 'or', + 'value' => array( + '1' => array( + 'type' => 'today', + 'field' => 'dateStart', + 'dateTime' => true + ), + '2' => array( + 'type' => 'future', + 'field' => 'dateEnd', + 'dateTime' => true + ) + ) + ) + ), $selectParams); + + $sql = $this->getEntityManager()->getQuery()->createSelectQuery($entityType, $selectParams); + + $unionPartList[] = '' . $sql . ''; + } + if (empty($unionPartList)) { + return array( + 'total' => 0, + 'list' => [] + ); + } + + $pdo = $this->getEntityManager()->getPDO(); + + $unionSql = implode(' UNION ', $unionPartList); + + $countSql = "SELECT COUNT(*) AS 'COUNT' FROM ({$unionSql}) AS c"; + $sth = $pdo->prepare($countSql); + $sth->execute(); + $row = $sth->fetch(\PDO::FETCH_ASSOC); + $totalCount = $row['COUNT']; + + $unionSql .= " ORDER BY dateStart ASC"; + $unionSql .= " LIMIT :offset, :maxSize"; + + $sth = $pdo->prepare($unionSql); + + $sth->bindParam(':offset', intval($params['offset']), \PDO::PARAM_INT); + $sth->bindParam(':maxSize', intval($params['maxSize']), \PDO::PARAM_INT); + $sth->execute(); + $rows = $sth->fetchAll(\PDO::FETCH_ASSOC); + + $entityDataList = []; + + foreach ($rows as $row) { + $entity = $this->getEntityManager()->getEntity($row['entityType'], $row['id']); + $entityData = $entity->toArray(); + $entityData['_scope'] = $entity->getEntityType(); + $entityDataList[] = $entityData; + } + + return array( + 'total' => $totalCount, + 'list' => $entityDataList + ); + } } diff --git a/frontend/client/modules/crm/src/views/dashlets/activities.js b/frontend/client/modules/crm/src/views/dashlets/activities.js new file mode 100644 index 0000000000..f9f2f96310 --- /dev/null +++ b/frontend/client/modules/crm/src/views/dashlets/activities.js @@ -0,0 +1,185 @@ +/************************************************************************ + * This file is part of EspoCRM. + * + * EspoCRM - Open Source CRM application. + * Copyright (C) 2014-2015 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko + * Website: http://www.espocrm.com + * + * EspoCRM is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * EspoCRM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with EspoCRM. If not, see http://www.gnu.org/licenses/. + ************************************************************************/ + +Espo.define('crm:views/dashlets/activities', ['views/dashlets/abstract/base', 'multi-collection'], function (Dep, MultiCollection) { + + return Dep.extend({ + + name: 'Activities', + + _template: '
{{{list}}}
', + + rowActionsView: 'crm:views/meeting/record/row-actions/dashlet', + + scopeList: ['Meeting', 'Call'], + + defaultOptions: { + displayRecords: 5, + autorefreshInterval: 0.5, + isDoubleHeight: false + }, + + optionsFields: _.extend(_.clone(Dep.prototype.optionsFields), { + 'displayRecords': { + type: 'enumInt', + options: [3,4,5,10,15] + }, + 'isDoubleHeight': { + type: 'bool', + }, + }), + + listLayout: { + 'Meeting': { + rows: [ + [ + { + name: 'ico', + view: 'crm:views/fields/ico', + params: { + notRelationship: true + } + }, + { + name: 'name', + link: true, + }, + ], + [ + {name: 'dateStart'} + ] + ] + }, + 'Call': { + rows: [ + [ + { + name: 'ico', + view: 'crm:views/fields/ico', + params: { + notRelationship: true + } + }, + { + name: 'name', + link: true, + }, + ], + [ + {name: 'dateStart'} + ] + ] + } + }, + + setupActionList: function () { + this.actionList.unshift({ + name: 'createCall', + html: this.translate('Create Call', 'labels', 'Call'), + iconHtml: '' + }); + this.actionList.unshift({ + name: 'createMeeting', + html: this.translate('Create Meeting', 'labels', 'Meeting'), + iconHtml: '' + }); + }, + + setup: function () { + this.seeds = {}; + + this.wait(true); + var i = 0; + this.scopeList.forEach(function (scope) { + this.getModelFactory().getSeed(scope, function (seed) { + this.seeds[scope] = seed; + i++; + if (i == this.scopeList.length) { + this.wait(false); + } + }.bind(this)); + }, this); + }, + + + afterRender: function () { + this.collection = new MultiCollection(); + this.collection.seeds = this.seeds; + this.collection.url = 'Activities/action/listUpcoming'; + this.collection.maxSize = this.getConfig().get('recordsPerPageSmall') || 5; + + this.listenToOnce(this.collection, 'sync', function () { + this.createView('list', 'crm:views/meeting/record/list-expanded', { + el: this.options.el + ' > .list-container', + pagination: false, + type: 'list', + rowActionsView: this.rowActionsView, + checkboxes: false, + collection: this.collection, + listLayout: this.listLayout, + }, function (view) { + view.render(); + }); + }, this); + + this.collection.fetch(); + }, + + actionRefresh: function () { + this.collection.fetch(); + }, + + actionCreateMeeting: function () { + var attributes = {}; + + this.notify('Loading...'); + var viewName = this.getMetadata().get('clientDefs.Meeting.modalViews.edit') || 'views/modals/edit'; + this.createView('quickCreate', viewName, { + scope: 'Meeting', + attributes: attributes, + }, function (view) { + view.render(); + view.notify(false); + this.listenToOnce(view, 'after:save', function () { + this.actionRefresh(); + }, this); + }.bind(this)); + }, + + actionCreateCall: function () { + var attributes = {}; + + this.notify('Loading...'); + var viewName = this.getMetadata().get('clientDefs.Call.modalViews.edit') || 'views/modals/edit'; + this.createView('quickCreate', viewName, { + scope: 'Call', + attributes: attributes, + }, function (view) { + view.render(); + view.notify(false); + this.listenToOnce(view, 'after:save', function () { + this.actionRefresh(); + }, this); + }.bind(this)); + } + }); +}); + diff --git a/frontend/client/modules/crm/src/views/fields/ico.js b/frontend/client/modules/crm/src/views/fields/ico.js index 657734b8a3..b3f3fde818 100644 --- a/frontend/client/modules/crm/src/views/fields/ico.js +++ b/frontend/client/modules/crm/src/views/fields/ico.js @@ -25,7 +25,12 @@ Espo.define('Crm:Views.Fields.Ico', 'Views.Fields.Base', function (Dep) { setup: function () { var tpl; - var icoTpl = ''; + var icoTpl; + if (this.params.notRelationship) { + icoTpl = ''; + } else { + icoTpl = ''; + } switch (this.model.name) { case 'Meeting': diff --git a/frontend/client/modules/crm/src/views/meeting/record/row-actions/dashlet.js b/frontend/client/modules/crm/src/views/meeting/record/row-actions/dashlet.js index fb04062a43..dff91a30b2 100644 --- a/frontend/client/modules/crm/src/views/meeting/record/row-actions/dashlet.js +++ b/frontend/client/modules/crm/src/views/meeting/record/row-actions/dashlet.js @@ -24,26 +24,33 @@ Espo.define('crm:views/meeting/record/row-actions/dashlet', ['views/record/row-a return Dep.extend({ getActionList: function () { - var actions = Dep.prototype.getActionList.call(this); + var actionList = Dep.prototype.getActionList.call(this); + + actionList.forEach(function (item) { + item.data = item.data || {}; + item.data.scope = this.model.name + }, this); if (this.options.acl.edit && !~['Held', 'Not Held'].indexOf(this.model.get('status'))) { - actions.push({ + actionList.push({ action: 'setHeld', label: 'Set Held', data: { - id: this.model.id + id: this.model.id, + scope: this.model.name } }); - actions.push({ + actionList.push({ action: 'setNotHeld', label: 'Set Not Held', data: { - id: this.model.id + id: this.model.id, + scope: this.model.name } }); } - return actions; + return actionList; } }); diff --git a/frontend/client/src/views/dashlets/abstract/record-list.js b/frontend/client/src/views/dashlets/abstract/record-list.js index 84409fc821..1b2e6b7a86 100644 --- a/frontend/client/src/views/dashlets/abstract/record-list.js +++ b/frontend/client/src/views/dashlets/abstract/record-list.js @@ -103,8 +103,8 @@ Espo.define('Views.Dashlets.Abstract.RecordList', ['Views.Dashlets.Abstract.Base var attributes = this.getCreateAttributes() || {}; this.notify('Loading...'); - var viewName = this.getMetadata().get('clientDefs.' + this.scope + '.modalViews.edit') || 'Modals.Edit'; - this.createView('quickCreate', 'Modals.Edit', { + var viewName = this.getMetadata().get('clientDefs.' + this.scope + '.modalViews.edit') || 'views/modals/edit'; + this.createView('quickCreate', viewName, { scope: this.scope, attributes: attributes, }, function (view) { diff --git a/frontend/client/src/views/fields/link-multiple.js b/frontend/client/src/views/fields/link-multiple.js index e1031a237e..3ef0afe34a 100644 --- a/frontend/client/src/views/fields/link-multiple.js +++ b/frontend/client/src/views/fields/link-multiple.js @@ -131,20 +131,11 @@ Espo.define('Views.Fields.LinkMultiple', 'Views.Fields.Base', function (Dep) { var boolList = this.getSelectBoolFilterList(); var where = []; if (boolList) { - where.push({ - type: 'bool', - value: boolList - }); + url += '&' + $.param({'boolFilterList': boolList}); } var primary = this.getSelectPrimaryFilterName(); if (primary) { - where.push({ - type: 'primary', - value: primary - }); - } - if (where.length) { - url += '&' + $.param({'where': where}); + url += '&' + $.param({'primaryFilter': primary}); } return url; }, diff --git a/frontend/client/src/views/fields/link-parent.js b/frontend/client/src/views/fields/link-parent.js index 56107937ec..422799f440 100644 --- a/frontend/client/src/views/fields/link-parent.js +++ b/frontend/client/src/views/fields/link-parent.js @@ -134,20 +134,11 @@ Espo.define('Views.Fields.LinkParent', 'Views.Fields.Base', function (Dep) { var boolList = this.getSelectBoolFilterList(); var where = []; if (boolList) { - where.push({ - type: 'bool', - value: boolList - }); + url += '&' + $.param({'boolFilterList': boolList}); } var primary = this.getSelectPrimaryFilterName(); if (primary) { - where.push({ - type: 'primary', - value: primary - }); - } - if (where.length) { - url += '&' + $.param({'where': where}); + url += '&' + $.param({'primaryFilter': primary}); } return url; }, diff --git a/frontend/client/src/views/fields/link.js b/frontend/client/src/views/fields/link.js index 8c4ec868db..188768560a 100644 --- a/frontend/client/src/views/fields/link.js +++ b/frontend/client/src/views/fields/link.js @@ -136,20 +136,11 @@ Espo.define('Views.Fields.Link', 'Views.Fields.Base', function (Dep) { var boolList = this.getSelectBoolFilterList(); var where = []; if (boolList) { - where.push({ - type: 'bool', - value: boolList - }); + url += '&' + $.param({'boolFilterList': boolList}); } var primary = this.getSelectPrimaryFilterName(); if (primary) { - where.push({ - type: 'primary', - value: primary - }); - } - if (where.length) { - url += '&' + $.param({'where': where}); + url += '&' + $.param({'primaryFilter': primary}); } return url; }, diff --git a/frontend/client/src/views/record/list.js b/frontend/client/src/views/record/list.js index 8e9d868317..f847219630 100644 --- a/frontend/client/src/views/record/list.js +++ b/frontend/client/src/views/record/list.js @@ -19,11 +19,11 @@ * along with EspoCRM. If not, see http://www.gnu.org/licenses/. ************************************************************************/ -Espo.define('Views.Record.List', 'View', function (Dep) { +Espo.define('views/record/list', 'view', function (Dep) { return Dep.extend({ - template: 'record.list', + template: 'record/list', /** * @param {String} Type of the list. Can be 'list', 'listSmall'. @@ -860,12 +860,14 @@ Espo.define('Views.Record.List', 'View', function (Dep) { var id = data.id; if (!id) return; - var viewName = this.getMetadata().get('clientDefs.' + this.scope + '.modalViews.detail') || 'Modals.Detail'; + var scope = data.scope || this.scope; + + var viewName = this.getMetadata().get('clientDefs.' + scope + '.modalViews.detail') || 'Modals.Detail'; if (!this.quickDetailDisabled) { this.notify('Loading...'); this.createView('quickDetail', viewName, { - scope: this.scope, + scope: scope, model: this.collection.get(id), id: id }, function (view) { @@ -881,27 +883,29 @@ Espo.define('Views.Record.List', 'View', function (Dep) { }, this); }.bind(this)); } else { - this.getRouter().navigate('#' + this.scope + '/view/' + id, {trigger: true}); + this.getRouter().navigate('#' + scope + '/view/' + id, {trigger: true}); } }, - actionQuickEdit: function (d) { - d = d || {} - var id = d.id; + actionQuickEdit: function (data) { + data = data || {} + var id = data.id; if (!id) return; - var viewName = this.getMetadata().get('clientDefs.' + this.scope + '.modalViews.edit') || 'Modals.Edit'; + var scope = data.scope || this.scope; + + var viewName = this.getMetadata().get('clientDefs.' + scope + '.modalViews.edit') || 'Modals.Edit'; if (!this.quickEditDisabled) { this.notify('Loading...'); this.createView('quickEdit', viewName, { - scope: this.scope, + scope: scope, id: id, model: this.collection.get(id), - fullFormDisabled: d.noFullForm, - returnUrl: '#' + this.scope, + fullFormDisabled: data.noFullForm, + returnUrl: '#' + scope, returnDispatchParams: { - controller: this.scope, + controller: scope, action: null, options: { isReturn: true @@ -923,19 +927,19 @@ Espo.define('Views.Record.List', 'View', function (Dep) { }.bind(this)); } else { - this.getRouter().dispatch(this.scope, 'edit', { + this.getRouter().dispatch(scope, 'edit', { id: id, model: this.collection.get(id), - returnUrl: '#' + this.scope, + returnUrl: '#' + scope, returnDispatchParams: { - controller: this.scope, + controller: scope, action: null, options: { isReturn: true } } }); - this.getRouter().navigate('#' + this.scope + '/edit/' + id, {trigger: false}); + this.getRouter().navigate('#' + scope + '/edit/' + id, {trigger: false}); } },