link manager: parent

This commit is contained in:
Yuri Kuznetsov
2019-12-04 11:06:13 +02:00
parent dc962d868f
commit 472073ee5a
11 changed files with 482 additions and 68 deletions

View File

@@ -60,7 +60,7 @@ class EntityManager extends \Espo\Core\Controllers\Base
$name = filter_var($name, \FILTER_SANITIZE_STRING);
$type = filter_var($type, \FILTER_SANITIZE_STRING);
$params = array();
$params = [];
if (!empty($data['labelSingular'])) {
$params['labelSingular'] = $data['labelSingular'];
@@ -187,19 +187,19 @@ class EntityManager extends \Espo\Core\Controllers\Base
$paramList = [
'entity',
'entityForeign',
'link',
'linkForeign',
'label',
'labelForeign',
'linkType'
'linkType',
];
$additionalParamList = [
'entityForeign',
'relationName',
'labelForeign',
];
$params = array();
$params = [];
foreach ($paramList as $item) {
if (empty($data[$item])) {
@@ -209,9 +209,11 @@ class EntityManager extends \Espo\Core\Controllers\Base
}
foreach ($additionalParamList as $item) {
$params[$item] = filter_var($data[$item], \FILTER_SANITIZE_STRING);
$params[$item] = filter_var($data[$item] ?? null, \FILTER_SANITIZE_STRING);
}
$params['labelForeign'] = $params['labelForeign'] ?? $params['linkForeign'];
if (array_key_exists('linkMultipleField', $data)) {
$params['linkMultipleField'] = $data['linkMultipleField'];
}
@@ -225,6 +227,12 @@ class EntityManager extends \Espo\Core\Controllers\Base
if (array_key_exists('auditedForeign', $data)) {
$params['auditedForeign'] = $data['auditedForeign'];
}
if (array_key_exists('parentEntityTypeList', $data)) {
$params['parentEntityTypeList'] = $data['parentEntityTypeList'];
}
if (array_key_exists('foreignLinkEntityTypeList', $data)) {
$params['foreignLinkEntityTypeList'] = $data['foreignLinkEntityTypeList'];
}
$result = $this->getContainer()->get('entityManagerUtil')->createLink($params);
@@ -251,12 +259,12 @@ class EntityManager extends \Espo\Core\Controllers\Base
'link',
'linkForeign',
'label',
'labelForeign'
'labelForeign',
];
$additionalParamList = [];
$params = array();
$params = [];
foreach ($paramList as $item) {
if (array_key_exists($item, $data)) {
$params[$item] = filter_var($data[$item], \FILTER_SANITIZE_STRING);
@@ -280,6 +288,12 @@ class EntityManager extends \Espo\Core\Controllers\Base
if (array_key_exists('auditedForeign', $data)) {
$params['auditedForeign'] = $data['auditedForeign'];
}
if (array_key_exists('parentEntityTypeList', $data)) {
$params['parentEntityTypeList'] = $data['parentEntityTypeList'];
}
if (array_key_exists('foreignLinkEntityTypeList', $data)) {
$params['foreignLinkEntityTypeList'] = $data['foreignLinkEntityTypeList'];
}
$result = $this->getContainer()->get('entityManagerUtil')->updateLink($params);

View File

@@ -672,18 +672,23 @@ class EntityManager
if (empty($linkType)) {
throw new Error();
}
if (empty($entity) || empty($entityForeign)) {
throw new Error();
}
if (empty($entityForeign) || empty($linkForeign)) {
if (empty($entity)) {
throw new Error();
}
if ($linkType !== 'childrenToParent') {
if (empty($entityForeign)) {
throw new Error();
}
}
if ($this->getMetadata()->get('entityDefs.' . $entity . '.links.' . $link)) {
throw new Conflict('Link ['.$entity.'::'.$link.'] already exists.');
}
if ($this->getMetadata()->get('entityDefs.' . $entityForeign . '.links.' . $linkForeign)) {
throw new Conflict('Link ['.$entityForeign.'::'.$linkForeign.'] already exists.');
if ($entityForeign) {
if ($this->getMetadata()->get('entityDefs.' . $entityForeign . '.links.' . $linkForeign)) {
throw new Conflict('Link ['.$entityForeign.'::'.$linkForeign.'] already exists.');
}
}
if ($entity === $entityForeign) {
@@ -926,28 +931,60 @@ class EntityManager
$dataRight['links'][$linkForeign]['midKeys'] = ['rightId', 'leftId'];
}
break;
case 'childrenToParent':
$dataLeft = [
'fields' => [
$link => [
'type' => 'linkParent',
'entityList' => $params['parentEntityTypeList'] ?? [],
],
],
'links' => [
$link => [
'type' => 'belongsToParent',
'foreign' => $linkForeign,
'isCustom' => true,
],
],
];
break;
default:
throw new BadRequest();
}
$this->getMetadata()->set('entityDefs', $entity, $dataLeft);
$this->getMetadata()->set('entityDefs', $entityForeign, $dataRight);
if ($entityForeign) {
$this->getMetadata()->set('entityDefs', $entityForeign, $dataRight);
}
$this->getMetadata()->save();
$this->getLanguage()->set($entity, 'fields', $link, $label);
$this->getLanguage()->set($entity, 'links', $link, $label);
$this->getLanguage()->set($entityForeign, 'fields', $linkForeign, $labelForeign);
$this->getLanguage()->set($entityForeign, 'links', $linkForeign, $labelForeign);
if ($entityForeign) {
$this->getLanguage()->set($entityForeign, 'fields', $linkForeign, $labelForeign);
$this->getLanguage()->set($entityForeign, 'links', $linkForeign, $labelForeign);
}
$this->getLanguage()->save();
if ($this->getLanguage()->getLanguage() !== $this->getBaseLanguage()->getLanguage()) {
$this->getBaseLanguage()->set($entity, 'fields', $link, $label);
$this->getBaseLanguage()->set($entity, 'links', $link, $label);
$this->getBaseLanguage()->set($entityForeign, 'fields', $linkForeign, $labelForeign);
$this->getBaseLanguage()->set($entityForeign, 'links', $linkForeign, $labelForeign);
if ($entityForeign) {
$this->getBaseLanguage()->set($entityForeign, 'fields', $linkForeign, $labelForeign);
$this->getBaseLanguage()->set($entityForeign, 'links', $linkForeign, $labelForeign);
}
$this->getBaseLanguage()->save();
}
if ($linkType === 'childrenToParent') {
$foreignLinkEntityTypeList = $params['foreignLinkEntityTypeList'] ?? null;
if ($foreignLinkEntityTypeList && is_array($foreignLinkEntityTypeList)) {
$this->updateParentForeignLinks($entity, $link, $linkForeign, $foreignLinkEntityTypeList);
}
}
return true;
}
@@ -955,18 +992,22 @@ class EntityManager
{
$entity = $params['entity'];
$link = $params['link'];
$entityForeign = $params['entityForeign'];
$entityForeign = $params['entityForeign'] ?? null;
$linkForeign = $params['linkForeign'];
if (empty($entity) || empty($entityForeign)) {
throw new Error();
}
if (empty($entityForeign) || empty($linkForeign)) {
throw new Error();
}
if (empty($link)) throw new BadRequest();
if (empty($entity)) throw new BadRequest();
$linkType = $this->getMetadata()->get("entityDefs.{$entity}.links.{$link}.type");
$isCustom = $this->getMetadata()->get("entityDefs.{$entity}.links.{$link}.isCustom");
if ($linkType === 'belongsToParent') {
} else {
if (empty($entityForeign)) throw new BadRequest();
if (empty($linkForeign)) throw new BadRequest();
}
if (
$this->getMetadata()->get("entityDefs.{$entity}.links.{$link}.type") == 'hasMany'
&&
@@ -1033,6 +1074,7 @@ class EntityManager
}
if (
$linkForeign &&
in_array($this->getMetadata()->get("entityDefs.{$entityForeign}.links.{$linkForeign}.type"), ['hasMany', 'hasChildren'])
) {
if (array_key_exists('auditedForeign', $params)) {
@@ -1049,23 +1091,44 @@ class EntityManager
}
}
if ($linkType === 'belongsToParent') {
$parentEntityTypeList = $params['parentEntityTypeList'] ?? null;
if ($parentEntityTypeList && is_array($parentEntityTypeList)) {
$data = [
'fields' => [
$link => [
'entityList' => $parentEntityTypeList,
],
],
];
$this->getMetadata()->set('entityDefs', $entity, $data);
$this->getMetadata()->save();
}
$foreignLinkEntityTypeList = $params['foreignLinkEntityTypeList'] ?? null;
if ($foreignLinkEntityTypeList && is_array($foreignLinkEntityTypeList)) {
$this->updateParentForeignLinks($entity, $link, $linkForeign, $foreignLinkEntityTypeList);
}
}
$label = null;
if (isset($params['label'])) {
$label = $params['label'];
}
$labelForeign = null;
if (isset($params['labelForeign'])) {
$labelForeign = $params['labelForeign'];
}
if ($label) {
$this->getLanguage()->set($entity, 'fields', $link, $label);
$this->getLanguage()->set($entity, 'links', $link, $label);
}
if ($labelForeign) {
$this->getLanguage()->set($entityForeign, 'fields', $linkForeign, $labelForeign);
$this->getLanguage()->set($entityForeign, 'links', $linkForeign, $labelForeign);
if ($linkType !== 'belongsToParent') {
$labelForeign = null;
if (isset($params['labelForeign'])) {
$labelForeign = $params['labelForeign'];
}
if ($labelForeign) {
$this->getLanguage()->set($entityForeign, 'fields', $linkForeign, $labelForeign);
$this->getLanguage()->set($entityForeign, 'links', $linkForeign, $labelForeign);
}
}
$this->getLanguage()->save();
@@ -1076,7 +1139,7 @@ class EntityManager
$this->getBaseLanguage()->set($entity, 'fields', $link, $label);
$this->getBaseLanguage()->set($entity, 'links', $link, $label);
}
if ($labelForeign) {
if ($labelForeign && $linkType !== 'belongsToParent') {
$this->getBaseLanguage()->set($entityForeign, 'fields', $linkForeign, $labelForeign);
$this->getBaseLanguage()->set($entityForeign, 'links', $linkForeign, $labelForeign);
}
@@ -1096,14 +1159,38 @@ class EntityManager
throw new Error("Could not delete link {$entity}.{$link}. Not isCustom.");
}
if (empty($entity) || empty($link)) {
throw new BadRequest();
}
$entityForeign = $this->getMetadata()->get("entityDefs.{$entity}.links.{$link}.entity");
$linkForeign = $this->getMetadata()->get("entityDefs.{$entity}.links.{$link}.foreign");
$linkType = $this->getMetadata()->get("entityDefs.{$entity}.links.{$link}.type");
if (empty($entity) || empty($entityForeign)) {
throw new Error();
if (!$this->getMetadata()->get('entityDefs', $entity, 'links', $link, 'isCustom')) {
throw new Error("Can't remove not custom link.");
}
if ($linkType === 'hasChildren') {
$this->getMetadata()->delete('entityDefs', $entity, [
'links.' . $link,
]);
$this->getMetadata()->save();
return true;
}
if ($linkType === 'belongsToParent') {
$this->getMetadata()->delete('entityDefs', $entity, [
'fields.' . $link,
'links.' . $link,
]);
$this->getMetadata()->save();
$this->updateParentForeignLinks($entity, $link, $linkForeign, []);
return true;
}
if (empty($entityForeign) || empty($linkForeign)) {
throw new Error();
throw new BadRequest();
}
$this->getMetadata()->delete('entityDefs', $entity, array(
@@ -1148,8 +1235,6 @@ class EntityManager
$className = '\\Espo\\Modules\\'.$normalizedTemplateModuleName.'\\Core\\Utils\\EntityManager\\Hooks\\' . $type . 'Type';
}
$className = $this->getMetadata()->get(['app', 'entityTemplates', $type, 'hookClassName'], $className);
if (class_exists($className)) {
@@ -1192,4 +1277,89 @@ class EntityManager
$this->getLanguage()->delete('Global', 'scopeNamesPlural', $scope);
$this->getLanguage()->save();
}
protected function updateParentForeignLinks(
string $entityType, string $link, string $linkForeign, array $foreignLinkEntityTypeList
)
{
$toCreateList = [];
foreach ($foreignLinkEntityTypeList as $foreignEntityType) {
$linkDefs = $this->getMetadata()->get(['entityDefs', $foreignEntityType, 'links']) ?? [];
foreach ($linkDefs as $kLink => $defs) {
$kForeign = $defs['foreign'] ?? null;
$kIsCustom = $defs['isCustom'] ?? false;
$kEntity = $defs['entity'] ?? null;
if (
$kForeign === $link && !$kIsCustom && $kEntity == $entityType
) continue 2;
if ($kLink == $linkForeign) {
if ($defs['type'] !== 'hasChildren') continue 2;
}
}
$toCreateList[] = $foreignEntityType;
}
$entityTypeList = array_keys($this->getMetadata()->get('entityDefs') ?? []);
foreach ($entityTypeList as $itemEntityType) {
$linkDefs = $this->getMetadata()->get(['entityDefs', $itemEntityType, 'links']) ?? [];
foreach ($linkDefs as $kLink => $defs) {
$kForeign = $defs['foreign'] ?? null;
$kIsCustom = $defs['isCustom'] ?? false;
$kEntity = $defs['entity'] ?? null;
if (
$kForeign === $link && $kIsCustom && $kEntity == $entityType && $defs['type'] == 'hasChildren' &&
$kLink === $linkForeign
) {
if (!in_array($itemEntityType, $toCreateList)) {
$this->getMetadata()->delete('entityDefs', $itemEntityType, [
'links.' . $linkForeign,
]);
$this->getLanguage()->delete($itemEntityType, 'links', $linkForeign);
if ($this->getLanguage()->getLanguage() !== $this->getBaseLanguage()->getLanguage()) {
$this->getBaseLanguage()->delete($itemEntityType, 'links', $linkForeign);
}
}
break;
}
}
}
foreach ($toCreateList as $itemEntityType) {
$this->getMetadata()->set('entityDefs', $itemEntityType, [
'links' => [
$linkForeign => [
'type' => 'hasChildren',
'foreign' => $link,
'entity' => $entityType,
'isCustom' => true,
],
],
]);
$label = $this->getLanguage()->translate($entityType, 'scopeNamesPlural');
$this->getLanguage()->set($itemEntityType, 'links', $linkForeign, $label);
if ($this->getLanguage()->getLanguage() !== $this->getBaseLanguage()->getLanguage()) {
$this->getBaseLanguage()->set($itemEntityType, 'links', $linkForeign, $label);
}
}
$this->getMetadata()->save();
$this->getLanguage()->save();
if ($this->getLanguage()->getLanguage() !== $this->getBaseLanguage()->getLanguage()) {
$this->getBaseLanguage()->save();
}
}
}

View File

@@ -34,7 +34,9 @@
"kanbanStatusIgnoreList": "Ignored groups in Kanban view",
"iconClass": "Icon",
"countDisabled": "Disable record count",
"fullTextSearch": "Full-Text Search"
"fullTextSearch": "Full-Text Search",
"parentEntityTypeList": "Parent Entity Types",
"foreignLinkEntityTypeList": "Foreign Links"
},
"options": {
"type": {

View File

@@ -48,7 +48,7 @@
</a>
</td>
<td align="right" width="10%">
{{#if isCustom}}
{{#if isRemovable}}
<a href="javascript:" data-action="removeLink" data-link="{{link}}">
{{translate 'Remove'}}
</a>

View File

@@ -81,3 +81,27 @@
</div>
</div>
</div>
<div class="row">
<div class="cell form-group col-md-4"></div>
<div class="cell form-group col-md-4" data-name="parentEntityTypeList">
<label class="control-label" data-name="parentEntityTypeList">
{{translate 'parentEntityTypeList' category='fields' scope='EntityManager'}}
</label>
<div class="field" data-name="parentEntityTypeList">
{{{parentEntityTypeList}}}
</div>
</div>
</div>
<div class="row">
<div class="cell form-group col-md-4"></div>
<div class="cell form-group col-md-4" data-name="foreignLinkEntityTypeList">
<label class="control-label" data-name="foreignLinkEntityTypeList">
{{translate 'foreignLinkEntityTypeList' category='fields' scope='EntityManager'}}
</label>
<div class="field" data-name="foreignLinkEntityTypeList">
{{{foreignLinkEntityTypeList}}}
</div>
</div>
</div>

View File

@@ -5,3 +5,4 @@
<label for="{{id}}" class="checklist-label">{{label}}</label>
</div>
{{/each}}
{{#unless optionDataList.length}}{{translate 'None'}}{{/unless}}

View File

@@ -5,3 +5,4 @@
<label for="{{id}}" class="checklist-label">{{label}}</label>
</div>
{{/each}}
{{#unless optionDataList.length}}{{translate 'None'}}{{/unless}}

View File

@@ -0,0 +1,67 @@
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM - Open Source CRM application.
* Copyright (C) 2014-2019 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
* Website: https://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.
************************************************************************/
define('views/admin/link-manager/fields/foreign-link-entity-type-list', 'views/fields/checklist', function (Dep) {
return Dep.extend({
setup: function () {
this.params.translation = 'Global.scopeNames';
Dep.prototype.setup.call(this);
},
afterRender: function () {
Dep.prototype.afterRender.call(this);
this.controlOptionsAviability();
},
controlOptionsAviability: function () {
this.params.options.forEach(function (item) {
var link = this.model.get('link');
var linkForeign = this.model.get('linkForeign');
var entityType = this.model.get('entity');
var linkDefs = this.getMetadata().get(['entityDefs', item, 'links']) || {};
var isFound = false;
for (var i in linkDefs) {
if (linkDefs[i].foreign == link && !linkDefs[i].isCustom && linkDefs[i].entity == entityType) {
isFound = true;
} else if (i === linkForeign && linkDefs[i].type !== 'hasChildren') {
isFound = true;
}
}
if (isFound) {
this.$el.find('input[data-name="checklistItem-foreignLinkEntityTypeList-'+item+'"]').attr('disabled', 'disabled');
}
}, this);
},
});
});

View File

@@ -105,25 +105,30 @@ define('views/admin/link-manager/index', 'view', function (Dep) {
linkList.forEach(function (link) {
var d = links[link];
if (!d.foreign) return;
if (!d.entity) return;
var linkForeign = d.foreign;
var foreignType = this.getMetadata().get('entityDefs.' + d.entity + '.links.' + d.foreign + '.type');
var type = this.computeRelationshipType(d.type, foreignType);
if (d.type === 'belongsToParent') {
var type = 'childrenToParent';
} else {
if (!d.entity) return;
if (!linkForeign) return;
var foreignType = this.getMetadata().get('entityDefs.' + d.entity + '.links.' + d.foreign + '.type');
var type = this.computeRelationshipType(d.type, foreignType);
}
if (!type) return;
this.linkDataList.push({
link: link,
isCustom: d.isCustom,
isRemovable: d.isCustom,
customizable: d.customizable,
type: type,
entityForeign: d.entity,
entity: this.scope,
linkForeign: d.foreign,
linkForeign: linkForeign,
label: this.getLanguage().translate(link, 'links', this.scope),
labelForeign: this.getLanguage().translate(d.foreign, 'links', d.entity)
labelForeign: this.getLanguage().translate(d.foreign, 'links', d.entity),
});
}, this);
@@ -182,7 +187,7 @@ define('views/admin/link-manager/index', 'view', function (Dep) {
type: 'POST',
data: JSON.stringify({
entity: this.scope,
link: link
link: link,
})
}).done(function () {
this.$el.find('table tr[data-link="'+link+'"]').remove();

View File

@@ -85,7 +85,18 @@ define('views/admin/link-manager/modals/edit',
var type = this.getMetadata().get('entityDefs.' + entity + '.links.' + link + '.type');
var foreignType = this.getMetadata().get('entityDefs.' + entityForeign + '.links.' + linkForeign + '.type');
var linkType = Index.prototype.computeRelationshipType.call(this, type, foreignType);
if (type === 'belongsToParent') {
var linkType = 'childrenToParent';
labelForeign = null;
var entityTypeList = this.getMetadata().get(['entityDefs', entity, 'fields', link, 'entityList']) || [];
this.model.set('parentEntityTypeList', entityTypeList);
var foreignLinkEntityTypeList = this.getForeignLinkEntityTypeList(entity, link, entityTypeList);
this.model.set('foreignLinkEntityTypeList', foreignLinkEntityTypeList);
} else {
var linkType = Index.prototype.computeRelationshipType.call(this, type, foreignType);
}
this.model.set('linkType', linkType);
this.model.set('entityForeign', entityForeign);
@@ -166,7 +177,7 @@ define('views/admin/link-manager/modals/edit',
name: 'linkType',
params: {
required: true,
options: ['', 'oneToMany', 'manyToOne', 'manyToMany', 'oneToOneRight', 'oneToOneLeft']
options: ['', 'oneToMany', 'manyToOne', 'manyToMany', 'oneToOneRight', 'oneToOneLeft', 'childrenToParent']
}
},
readOnly: !isNew
@@ -285,8 +296,55 @@ define('views/admin/link-manager/modals/edit',
tooltipText: this.translate('linkAudited', 'tooltips', 'EntityManager')
});
this.createView('parentEntityTypeList', 'views/fields/entity-type-list', {
model: model,
mode: 'edit',
el: this.options.el + ' .field[data-name="parentEntityTypeList"]',
defs: {
name: 'parentEntityTypeList',
},
});
this.createView('foreignLinkEntityTypeList', 'views/admin/link-manager/fields/foreign-link-entity-type-list', {
model: model,
mode: 'edit',
el: this.options.el + ' .field[data-name="foreignLinkEntityTypeList"]',
defs: {
name: 'foreignLinkEntityTypeList',
params: {
options: this.model.get('parentEntityTypeList') || [],
},
},
});
this.model.fetchedAttributes = this.model.getClonedAttributes();
this.listenTo(this.model, 'change', function () {
if (
!this.model.hasChanged('parentEntityTypeList')
&&
!this.model.hasChanged('linkForeign')
&&
!this.model.hasChanged('link')
) return;
var view = this.getView('foreignLinkEntityTypeList');
if (view) {
view.setOptionList(this.model.get('parentEntityTypeList') || []);
}
var checkedList = Espo.Utils.clone(this.model.get('foreignLinkEntityTypeList') || []);
this.getForeignLinkEntityTypeList(
this.model.get('entity'), this.model.get('link'), this.model.get('parentEntityTypeList') || [], true
).forEach(function (item) {
if (!~checkedList.indexOf(item)) {
checkedList.push(item);
}
}, this);
this.model.set('foreignLinkEntityTypeList', checkedList)
}, this);
},
toPlural: function (string) {
@@ -301,13 +359,32 @@ define('views/admin/link-manager/modals/edit',
var entityForeign = this.model.get('entityForeign');
var linkType = this.model.get('linkType');
if (!entityForeign || !linkType) {
this.model.set('link', '');
this.model.set('linkForeign', '');
if (linkType === 'childrenToParent') {
this.model.set('link', 'parent');
this.model.set('label', 'Parent');
this.model.set('label', '');
this.model.set('labelForeign', '');
return;
var linkForeign = this.toPlural(Espo.Utils.lowerCaseFirst(this.scope));
if (this.getMetadata().get(['entityDefs', this.scope, 'links', 'parent'])) {
this.model.set('link', 'parentAnother');
this.model.set('label', 'Parent Another');
linkForeign += 'Another';
}
this.model.set('linkForeign', linkForeign);
this.model.set('labelForeign', '');
this.model.set('entityForeign', null);
return;
} else {
if (!entityForeign || !linkType) {
this.model.set('link', '');
this.model.set('linkForeign', '');
this.model.set('label', '');
this.model.set('labelForeign', '');
return;
}
}
var link;
@@ -423,10 +500,16 @@ define('views/admin/link-manager/modals/edit',
handleLinkTypeChange: function () {
var linkType = this.model.get('linkType');
this.showField('entityForeign');
this.showField('labelForeign');
this.hideField('parentEntityTypeList');
this.hideField('foreignLinkEntityTypeList');
if (linkType === 'manyToMany') {
var relationNameView = this.getView('relationName');
this.showField('relationName');
this.showField('relationName');
this.showField('linkMultipleField');
this.showField('linkMultipleFieldForeign');
@@ -457,6 +540,11 @@ define('views/admin/link-manager/modals/edit',
} else if (linkType == 'childrenToParent') {
this.hideField('audited');
this.showField('auditedForeign');
this.hideField('entityForeign');
this.hideField('labelForeign');
this.showField('parentEntityTypeList');
this.showField('foreignLinkEntityTypeList');
} else {
this.hideField('audited');
this.hideField('auditedForeign');
@@ -504,6 +592,8 @@ define('views/admin/link-manager/modals/edit',
'linkMultipleFieldForeign',
'audited',
'auditedForeign',
'parentEntityTypeList',
'foreignLinkEntityTypeList',
];
var notValid = false;
@@ -548,6 +638,8 @@ define('views/admin/link-manager/modals/edit',
var audited = this.model.get('audited');
var auditedForeign = this.model.get('auditedForeign');
var linkType = this.model.get('linkType');
var attributes = {
entity: entity,
entityForeign: entityForeign,
@@ -555,14 +647,15 @@ define('views/admin/link-manager/modals/edit',
linkForeign: linkForeign,
label: label,
labelForeign: labelForeign,
linkType: this.model.get('linkType'),
linkType: linkType,
relationName: relationName,
linkMultipleField: linkMultipleField,
linkMultipleFieldForeign: linkMultipleFieldForeign,
audited: audited,
auditedForeign: auditedForeign
auditedForeign: auditedForeign,
};
if (!this.isNew) {
if (attributes.label === this.model.fetchedAttributes.label) {
delete attributes.label;
@@ -572,6 +665,13 @@ define('views/admin/link-manager/modals/edit',
}
}
if (linkType === 'childrenToParent') {
delete attributes.entityForeign;
delete attributes.labelForeign;
attributes.parentEntityTypeList = this.model.get('parentEntityTypeList');
attributes.foreignLinkEntityTypeList = this.model.get('foreignLinkEntityTypeList');
}
$.ajax({
url: url,
type: 'POST',
@@ -603,9 +703,14 @@ define('views/admin/link-manager/modals/edit',
(data.fields || {})[link] = label;
(data.links || {})[link] = label;
data = ((this.getLanguage().data || {}) || {})[entityForeign];
(data.fields || {})[linkForeign] = labelForeign;
(data.links || {})[linkForeign] = labelForeign;
if (entityForeign) {
data = ((this.getLanguage().data || {}) || {})[entityForeign];
if (linkForeign) {
(data.fields || {})[linkForeign] = labelForeign;
(data.links || {})[linkForeign] = labelForeign;
}
}
this.getMetadata().load(function () {
this.trigger('after:save');
@@ -613,5 +718,32 @@ define('views/admin/link-manager/modals/edit',
}.bind(this), true);
}.bind(this));
},
getForeignLinkEntityTypeList: function (entityType, link, entityTypeList, onlyNotCustom) {
var list = [];
entityTypeList.forEach(function (item) {
var linkDefs = this.getMetadata().get(['entityDefs', item, 'links']) || {};
var isFound = false;
for (var i in linkDefs) {
if (linkDefs[i].foreign == link && linkDefs[i].entity == entityType && linkDefs[i].type === 'hasChildren') {
if (onlyNotCustom) {
if (linkDefs[i].isCustom) {
continue;
}
}
isFound = true;
break;
}
}
if (isFound) {
list.push(item);
}
}, this);
return list;
},
});
});

View File

@@ -26,7 +26,7 @@
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
Espo.define('views/fields/entity-type-list', 'views/fields/multi-enum', function (Dep) {
define('views/fields/entity-type-list', 'views/fields/multi-enum', function (Dep) {
return Dep.extend({
@@ -46,7 +46,6 @@ Espo.define('views/fields/entity-type-list', 'views/fields/multi-enum', function
}.bind(this)).sort(function (v1, v2) {
return this.translate(v1, 'scopeNames').localeCompare(this.translate(v2, 'scopeNames'));
}.bind(this));
this.params.options.unshift('');
},
setup: function () {
@@ -55,8 +54,7 @@ Espo.define('views/fields/entity-type-list', 'views/fields/multi-enum', function
}
this.setupOptions();
Dep.prototype.setup.call(this);
}
},
});
});