multiple assigned users support
This commit is contained in:
@@ -217,7 +217,7 @@ class Base implements Injectable
|
||||
}
|
||||
}
|
||||
|
||||
if ($entity->hasAttribute('assignedUsersIds') && $entity->hasRelation('assignedUsers')) {
|
||||
if ($entity->hasLinkMultipleField('assignedUsers')) {
|
||||
if ($entity->hasLinkMultipleId('assignedUsers', $user->id)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -143,6 +143,8 @@ class Entity extends \Espo\ORM\Entity
|
||||
}
|
||||
|
||||
$this->set($idsAttribute, $ids);
|
||||
$this->setFetched($idsAttribute, $ids);
|
||||
|
||||
$this->set($field . 'Names', $names);
|
||||
if ($hasType) {
|
||||
$this->set($field . 'Types', $types);
|
||||
|
||||
@@ -484,9 +484,9 @@ class Base
|
||||
{
|
||||
if ($this->hasAssignedUsersField()) {
|
||||
$this->setDistinct(true, $result);
|
||||
$this->addLeftJoin('assignedUsers', $result);
|
||||
$this->addLeftJoin(['assignedUsers', 'assignedUsersAccess'], $result);
|
||||
$result['whereClause'][] = array(
|
||||
'assignedUsers.id' => $this->getUser()->id
|
||||
'assignedUsersAccess.id' => $this->getUser()->id
|
||||
);
|
||||
return;
|
||||
}
|
||||
@@ -1558,19 +1558,25 @@ class Base
|
||||
protected function boolFilterOnlyMy(&$result)
|
||||
{
|
||||
if (!$this->checkIsPortal()) {
|
||||
if ($this->hasAssignedUserField()) {
|
||||
$result['whereClause'][] = array(
|
||||
if ($this->hasAssignedUsersField()) {
|
||||
$this->setDistinct(true, $result);
|
||||
$this->addLeftJoin(['assignedUsers', 'assignedUsersAccess'], $result);
|
||||
$result['whereClause'][] = [
|
||||
'assignedUsersAccess.id' => $this->getUser()->id
|
||||
];
|
||||
} else if ($this->hasAssignedUserField()) {
|
||||
$result['whereClause'][] = [
|
||||
'assignedUserId' => $this->getUser()->id
|
||||
);
|
||||
];
|
||||
} else {
|
||||
$result['whereClause'][] = array(
|
||||
$result['whereClause'][] = [
|
||||
'createdById' => $this->getUser()->id
|
||||
);
|
||||
];
|
||||
}
|
||||
} else {
|
||||
$result['whereClause'][] = array(
|
||||
$result['whereClause'][] = [
|
||||
'createdById' => $this->getUser()->id
|
||||
);
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -183,12 +183,23 @@ class Stream extends \Espo\Core\Hooks\Base
|
||||
$entityType = $entity->getEntityType();
|
||||
|
||||
if ($this->checkHasStream($entity)) {
|
||||
|
||||
$hasAssignedUsersField = false;
|
||||
if ($entity->hasLinkMultipleField('assignedUsers')) {
|
||||
$hasAssignedUsersField = true;
|
||||
}
|
||||
|
||||
if ($entity->isNew()) {
|
||||
$userIdList = [];
|
||||
|
||||
$assignedUserId = $entity->get('assignedUserId');
|
||||
$createdById = $entity->get('createdById');
|
||||
|
||||
$assignedUserIdList = [];
|
||||
if ($hasAssignedUsersField) {
|
||||
$assignedUserIdList = $entity->getLinkMultipleIdList('assignedUsers');
|
||||
}
|
||||
|
||||
if (
|
||||
!$this->getUser()->isSystem()
|
||||
&&
|
||||
@@ -210,6 +221,15 @@ class Stream extends \Espo\Core\Hooks\Base
|
||||
) {
|
||||
$userIdList[] = $createdById;
|
||||
}
|
||||
|
||||
if ($hasAssignedUsersField) {
|
||||
foreach ($assignedUserIdList as $userId) {
|
||||
if (!empty($userId) && !in_array($userId, $userIdList)) {
|
||||
$userIdList[] = $userId;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($assignedUserId) && !in_array($assignedUserId, $userIdList)) {
|
||||
$userIdList[] = $assignedUserId;
|
||||
}
|
||||
@@ -273,6 +293,27 @@ class Stream extends \Espo\Core\Hooks\Base
|
||||
$this->getStreamService()->noteStatus($entity, $field);
|
||||
}
|
||||
}
|
||||
|
||||
$assignedUserIdList = [];
|
||||
if ($hasAssignedUsersField) {
|
||||
$assignedUserIdList = $entity->getLinkMultipleIdList('assignedUsers');
|
||||
}
|
||||
|
||||
if ($hasAssignedUsersField) {
|
||||
$fetchedAssignedUserIdList = $entity->getFetched('assignedUsersIds');
|
||||
if (!is_array($fetchedAssignedUserIdList)) {
|
||||
$fetchedAssignedUserIdList = [];
|
||||
}
|
||||
foreach ($assignedUserIdList as $userId) {
|
||||
if (in_array($userId, $fetchedAssignedUserIdList)) {
|
||||
continue;
|
||||
}
|
||||
$this->getStreamService()->followEntity($entity, $userId);
|
||||
if ($this->getUser()->id === $userId) {
|
||||
$entity->set('isFollowed', true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$methodName = 'isChangedWithAclAffect';
|
||||
|
||||
@@ -836,7 +836,6 @@ class Activities extends \Espo\Core\Services\Base
|
||||
'createdAt'
|
||||
],
|
||||
'whereClause' => array(
|
||||
'assignedUserId' => $userId,
|
||||
array(
|
||||
'OR' => array(
|
||||
array(
|
||||
@@ -858,6 +857,14 @@ class Activities extends \Espo\Core\Services\Base
|
||||
)
|
||||
);
|
||||
|
||||
if ($this->getMetadata()->get(['entityDefs', 'Task', 'fields', 'assignedUsers', 'type']) === 'linkMultiple') {
|
||||
$selectManager->setDistinct(true, $selectParams);
|
||||
$selectManager->addLeftJoin(['assignedUsers', 'assignedUsers'], $selectParams);
|
||||
$selectParams['whereClause'][] = ['assignedUsers.id' => $userId];
|
||||
} else {
|
||||
$selectParams['whereClause'][] = ['assignedUserId' => $userId];
|
||||
}
|
||||
|
||||
return $this->getEntityManager()->getQuery()->createSelectQuery('Task', $selectParams);
|
||||
}
|
||||
|
||||
@@ -890,6 +897,8 @@ class Activities extends \Espo\Core\Services\Base
|
||||
}
|
||||
|
||||
if ($seed->hasRelation('assignedUsers')) {
|
||||
$selectManager->setDistinct(true, $selectParams);
|
||||
$selectManager->addLeftJoin(['assignedUsers', 'assignedUsers'], $selectParams);
|
||||
$wherePart['assignedUsersMiddle.userId'] = $userId;
|
||||
}
|
||||
|
||||
|
||||
@@ -76,7 +76,7 @@
|
||||
{
|
||||
"name":"tasks",
|
||||
"label":"Tasks",
|
||||
"view":"crm:views/record/panels/tasks",
|
||||
"view":"crm:views/user/record/panels/tasks",
|
||||
"aclScope": "Task"
|
||||
}
|
||||
],
|
||||
@@ -96,7 +96,7 @@
|
||||
{
|
||||
"name":"tasks",
|
||||
"label":"Tasks",
|
||||
"view":"crm:views/record/panels/tasks",
|
||||
"view":"crm:views/user/record/panels/tasks",
|
||||
"aclScope": "Task"
|
||||
}
|
||||
]
|
||||
|
||||
@@ -813,4 +813,9 @@ class Email extends Record
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function isPermittedAssignedUsers(Entity $entity)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -403,6 +403,66 @@ class Record extends \Espo\Core\Services\Base
|
||||
if (!$this->isPermittedTeams($entity)) {
|
||||
return false;
|
||||
}
|
||||
if ($entity->hasLinkMultipleField('assignedUsers')) {
|
||||
if (!$this->isPermittedAssignedUsers($entity)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public function isPermittedAssignedUsers(Entity $entity)
|
||||
{
|
||||
if (!$entity->hasLinkMultipleField('assignedUsers')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$assignmentPermission = $this->getAcl()->get('assignmentPermission');
|
||||
|
||||
if ($assignmentPermission === true || $assignmentPermission === 'yes' || !in_array($assignmentPermission, ['team', 'no'])) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$toProcess = false;
|
||||
|
||||
if (!$entity->isNew()) {
|
||||
$userIdList = $entity->getLinkMultipleIdList('assignedUsers');
|
||||
if ($entity->isAttributeChanged('assignedUsersIds')) {
|
||||
$toProcess = true;
|
||||
}
|
||||
} else {
|
||||
$toProcess = true;
|
||||
}
|
||||
|
||||
$userIdList = $entity->getLinkMultipleIdList('assignedUsers');
|
||||
|
||||
if ($toProcess) {
|
||||
if (empty($userIdList)) {
|
||||
if ($assignmentPermission == 'no') {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
$fetchedAssignedUserIdList = $entity->getFetched('assignedUsersIds');
|
||||
|
||||
if ($assignmentPermission == 'no') {
|
||||
foreach ($userIdList as $userId) {
|
||||
if (!$entity->isNew() && in_array($userId, $fetchedAssignedUserIdList)) continue;
|
||||
if ($this->getUser()->id != $userId) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else if ($assignmentPermission == 'team') {
|
||||
$teamIdList = $this->getUser()->getLinkMultipleIdList('teams');
|
||||
foreach ($userIdList as $userId) {
|
||||
if (!$entity->isNew() && in_array($userId, $fetchedAssignedUserIdList)) continue;
|
||||
if (!$this->getEntityManager()->getRepository('User')->checkBelongsToAnyOfTeams($userId, $teamIdList)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -466,8 +526,15 @@ class Record extends \Espo\Core\Services\Base
|
||||
$teamIdList = $entity->getLinkMultipleIdList('teams');
|
||||
if (empty($teamIdList)) {
|
||||
if ($assignmentPermission === 'team') {
|
||||
if (!$entity->get('assignedUserId')) {
|
||||
return false;
|
||||
if ($entity->hasLinkMultipleField('assignedUsers')) {
|
||||
$assignedUserIdList = $entity->getLinkMultipleIdList('assignedUsers');
|
||||
if (empty($assignedUserIdList)) {
|
||||
return false;
|
||||
}
|
||||
} else if ($entity->hasAttribute('assignedUserId')) {
|
||||
if (!$entity->get('assignedUserId')) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
@@ -993,6 +1060,9 @@ class Record extends \Espo\Core\Services\Base
|
||||
if (!$this->getAcl()->check($entity, 'read')) {
|
||||
throw new Forbidden();
|
||||
}
|
||||
if (empty($link)) {
|
||||
throw new Error();
|
||||
}
|
||||
|
||||
$methodName = 'findLinkedEntities' . ucfirst($link);
|
||||
if (method_exists($this, $methodName)) {
|
||||
|
||||
@@ -111,6 +111,12 @@ Espo.define('crm:views/record/panels/tasks', 'views/record/panels/relationship',
|
||||
setup: function () {
|
||||
this.scope = this.model.name;
|
||||
|
||||
this.link = 'tasks';
|
||||
|
||||
if (this.scope == 'Account') {
|
||||
this.link = 'tasksPrimary';
|
||||
}
|
||||
|
||||
this.currentTab = this.getStorage().get('state', this.getStorageKey()) || this.defaultTab;
|
||||
|
||||
this.where = [
|
||||
@@ -122,12 +128,8 @@ Espo.define('crm:views/record/panels/tasks', 'views/record/panels/relationship',
|
||||
},
|
||||
|
||||
afterRender: function () {
|
||||
var link = 'tasks';
|
||||
|
||||
if (this.scope == 'Account') {
|
||||
link = 'tasksPrimary';
|
||||
}
|
||||
var url = this.model.name + '/' + this.model.id + '/' + link;
|
||||
var url = this.model.name + '/' + this.model.id + '/' + this.link;
|
||||
|
||||
if (!this.getAcl().check('Task', 'read')) {
|
||||
this.$el.find('.list-container').html(this.translate('No Access'));
|
||||
@@ -165,7 +167,7 @@ Espo.define('crm:views/record/panels/tasks', 'views/record/panels/relationship',
|
||||
|
||||
actionCreateTask: function (data) {
|
||||
var self = this;
|
||||
var link = 'tasks';
|
||||
var link = this.link;
|
||||
var scope = 'Task';
|
||||
var foreignLink = this.model.defs['links'][link].foreign;
|
||||
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2018 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/.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
Espo.define('crm:views/user/record/panels/tasks', 'crm:views/record/panels/tasks', function (Dep) {
|
||||
|
||||
return Dep.extend({
|
||||
|
||||
listLayout: {
|
||||
rows: [
|
||||
[
|
||||
{
|
||||
name: 'name',
|
||||
link: true,
|
||||
},
|
||||
{
|
||||
name: 'isOverdue'
|
||||
}
|
||||
],
|
||||
[
|
||||
{name: 'status'},
|
||||
{name: 'dateEnd'}
|
||||
]
|
||||
]
|
||||
},
|
||||
|
||||
setup: function () {
|
||||
Dep.prototype.setup.call(this);
|
||||
|
||||
if (this.getMetadata().get(['entityDefs', 'Task', 'fields', 'assignedUsers'])) {
|
||||
var foreignLink = this.getMetadata().get(['entityDefs', 'Task', 'links', 'assignedUsers', 'foreign']);
|
||||
if (foreignLink) {
|
||||
this.link = foreignLink;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
@@ -539,10 +539,15 @@ Espo.define('views/admin/link-manager/modals/edit', ['views/modal', 'views/admin
|
||||
url: url,
|
||||
type: 'POST',
|
||||
data: JSON.stringify(attributes),
|
||||
error: function (x) {
|
||||
if (x.status == 409) {
|
||||
Espo.Ui.error(this.translate('linkConflict', 'messages', 'EntityManager'));
|
||||
x.errorIsHandled = true;
|
||||
error: function (xhr) {
|
||||
if (xhr.status == 409) {
|
||||
var msg = this.translate('linkConflict', 'messages', 'EntityManager');
|
||||
var statusReasonHeader = xhr.getResponseHeader('X-Status-Reason');
|
||||
if (statusReasonHeader) {
|
||||
console.error(statusReasonHeader);
|
||||
}
|
||||
Espo.Ui.error(msg);
|
||||
xhr.errorIsHandled = true;
|
||||
}
|
||||
this.$el.find('button[data-name="save"]').removeClass('disabled').removeAttr('disabled');
|
||||
}.bind(this)
|
||||
|
||||
@@ -48,6 +48,4 @@ Espo.define('views/email/record/detail-side', 'views/record/detail-side', functi
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
@@ -548,23 +548,33 @@ Espo.define('views/record/base', ['view', 'view-record-helper', 'dynamic-logic']
|
||||
var defaultHash = {};
|
||||
|
||||
if (!this.getUser().get('portalId')) {
|
||||
if (this.model.hasField('assignedUser')) {
|
||||
if (this.model.hasField('assignedUser') || this.model.hasField('assignedUsers')) {
|
||||
var assignedUserField = 'assignedUser';
|
||||
if (this.model.hasField('assignedUsers')) {
|
||||
assignedUserField = 'assignedUsers';
|
||||
}
|
||||
var fillAssignedUser = true;
|
||||
if (this.getPreferences().get('doNotFillAssignedUserIfNotRequired')) {
|
||||
fillAssignedUser = false;
|
||||
if (this.model.getFieldParam('assignedUser', 'required')) {
|
||||
if (this.model.getFieldParam(assignedUserField, 'required')) {
|
||||
fillAssignedUser = true;
|
||||
} else if (this.getAcl().get('assignmentPermission') === 'no') {
|
||||
fillAssignedUser = true;
|
||||
} else if (this.getAcl().get('assignmentPermission') === 'team' && !this.getUser().get('defaultTeamId')) {
|
||||
fillAssignedUser = true;
|
||||
} else if (~this.getAcl().getScopeForbiddenFieldList(this.model.name, 'edit').indexOf('assignedUser')) {
|
||||
} else if (~this.getAcl().getScopeForbiddenFieldList(this.model.name, 'edit').indexOf(assignedUserField)) {
|
||||
fillAssignedUser = true;
|
||||
}
|
||||
}
|
||||
if (fillAssignedUser) {
|
||||
defaultHash['assignedUserId'] = this.getUser().id;
|
||||
defaultHash['assignedUserName'] = this.getUser().get('name');
|
||||
if (assignedUserField === 'assignedUsers') {
|
||||
defaultHash['assignedUsersIds'] = [this.getUser().id];
|
||||
defaultHash['assignedUsersNames'] = {};
|
||||
defaultHash['assignedUsersNames'][this.getUser().id] = this.getUser().get('name');
|
||||
} else {
|
||||
defaultHash['assignedUserId'] = this.getUser().id;
|
||||
defaultHash['assignedUserName'] = this.getUser().get('name');
|
||||
}
|
||||
}
|
||||
}
|
||||
var defaultTeamId = this.getUser().get('defaultTeamId');
|
||||
@@ -572,7 +582,7 @@ Espo.define('views/record/base', ['view', 'view-record-helper', 'dynamic-logic']
|
||||
if (this.model.hasField('teams') && !this.model.getFieldParam('teams', 'default')) {
|
||||
defaultHash['teamsIds'] = [defaultTeamId];
|
||||
defaultHash['teamsNames'] = {};
|
||||
defaultHash['teamsNames'][defaultTeamId] = this.getUser().get('defaultTeamName')
|
||||
defaultHash['teamsNames'][defaultTeamId] = this.getUser().get('defaultTeamName');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,12 +50,10 @@ Espo.define('views/record/detail-side', ['view'], function (Dep) {
|
||||
options: {
|
||||
fieldList: [
|
||||
{
|
||||
name: 'assignedUser',
|
||||
view: 'views/fields/assigned-user'
|
||||
name: ':assignedUser'
|
||||
},
|
||||
{
|
||||
name: 'teams',
|
||||
view: 'views/fields/teams'
|
||||
name: 'teams'
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -210,6 +208,29 @@ Espo.define('views/record/detail-side', ['view'], function (Dep) {
|
||||
defaultPanelDefs.options.fieldList = fieldList;
|
||||
}
|
||||
|
||||
if (defaultPanelDefs.options.fieldList && defaultPanelDefs.options.fieldList.length) {
|
||||
defaultPanelDefs.options.fieldList.forEach(function (item, i) {
|
||||
if (typeof item !== 'object') {
|
||||
item = {
|
||||
name: item
|
||||
}
|
||||
defaultPanelDefs.options.fieldList[i] = item;
|
||||
}
|
||||
if (item.name === ':assignedUser') {
|
||||
if (this.model.hasField('assignedUsers')) {
|
||||
item.name = 'assignedUsers';
|
||||
if (!this.model.getFieldParam('assignedUsers', 'view')) {
|
||||
item.view = 'views/fields/assigned-users';
|
||||
}
|
||||
} else if (this.model.hasField('assignedUser')) {
|
||||
item.name = 'assignedUser';
|
||||
} else {
|
||||
defaultPanelDefs.options.fieldList[i] = {};
|
||||
}
|
||||
}
|
||||
}, this);
|
||||
}
|
||||
|
||||
this.panelList.unshift(defaultPanelDefs);
|
||||
},
|
||||
|
||||
|
||||
@@ -40,8 +40,7 @@ Espo.define('views/record/edit-side', 'views/record/detail-side', function (Dep)
|
||||
options: {
|
||||
fieldList: [
|
||||
{
|
||||
name: 'assignedUser',
|
||||
view: 'views/fields/assigned-user'
|
||||
name: ':assignedUser'
|
||||
},
|
||||
{
|
||||
name: 'teams',
|
||||
|
||||
@@ -49,7 +49,7 @@ Espo.define('views/record/panels/relationship', ['views/record/panels/bottom', '
|
||||
setup: function () {
|
||||
Dep.prototype.setup.call(this);
|
||||
|
||||
this.link = this.defs.link || this.panelName;
|
||||
this.link = this.link || this.defs.link || this.panelName;
|
||||
|
||||
if (!this.scope && !(this.link in this.model.defs.links)) {
|
||||
throw new Error('Link \'' + this.link + '\' is not defined in model \'' + this.model.name + '\'');
|
||||
|
||||
Reference in New Issue
Block a user