mirror of
https://github.com/espocrm/espocrm.git
synced 2026-06-28 06:56:05 +00:00
options ref
This commit is contained in:
@@ -128,6 +128,14 @@ class ArrayType
|
||||
|
||||
/** @var ?string $path */
|
||||
$path = $fieldDefs->getParam('optionsPath');
|
||||
/** @var ?string $path */
|
||||
$ref = $fieldDefs->getParam('optionsReference');
|
||||
|
||||
if (!$path && $ref && str_contains($ref, '.')) {
|
||||
[$refEntityType, $refField] = explode('.', $ref);
|
||||
|
||||
$path = "entityDefs.{$refEntityType}.fields.{$refField}.options";
|
||||
}
|
||||
|
||||
/** @var string[]|null|false $optionList */
|
||||
$optionList = $path ?
|
||||
|
||||
@@ -37,7 +37,6 @@ use Espo\ORM\Entity;
|
||||
class EnumType
|
||||
{
|
||||
private Metadata $metadata;
|
||||
|
||||
private Defs $defs;
|
||||
|
||||
private const DEFAULT_MAX_LENGTH = 255;
|
||||
@@ -65,6 +64,14 @@ class EnumType
|
||||
|
||||
/** @var ?string $path */
|
||||
$path = $fieldDefs->getParam('optionsPath');
|
||||
/** @var ?string $path */
|
||||
$ref = $fieldDefs->getParam('optionsReference');
|
||||
|
||||
if (!$path && $ref && str_contains($ref, '.')) {
|
||||
[$refEntityType, $refField] = explode('.', $ref);
|
||||
|
||||
$path = "entityDefs.{$refEntityType}.fields.{$refField}.options";
|
||||
}
|
||||
|
||||
/** @var string[]|null|false $optionList */
|
||||
$optionList = $path ?
|
||||
|
||||
@@ -1,13 +1,5 @@
|
||||
{
|
||||
"aclDependencies": {
|
||||
"Lead.options.source": {
|
||||
"scope": "Opportunity",
|
||||
"field": "leadSource"
|
||||
},
|
||||
"Account.options.industry": {
|
||||
"scope": "Lead",
|
||||
"field": "industry"
|
||||
},
|
||||
"Meeting": {
|
||||
"anyScopeList": ["Call"]
|
||||
}
|
||||
|
||||
@@ -1,14 +1,5 @@
|
||||
{
|
||||
"aclDependencies": {
|
||||
"entityDefs.Lead.fields.source.options": {
|
||||
"scope": "Opportunity",
|
||||
"field": "leadSource"
|
||||
},
|
||||
"entityDefs.Account.fields.industry.options": {
|
||||
"scope": "Lead",
|
||||
"field": "industry"
|
||||
}
|
||||
},
|
||||
"aclDependencies": {},
|
||||
"frontendHiddenPathList": [
|
||||
"__APPEND__",
|
||||
["app", "calendar", "additionalAttributeList"]
|
||||
|
||||
@@ -66,8 +66,7 @@
|
||||
"type": "enum",
|
||||
"view": "crm:views/lead/fields/industry",
|
||||
"customizationOptionsDisabled": true,
|
||||
"optionsPath": "entityDefs.Account.fields.industry.options",
|
||||
"translation": "Account.options.industry",
|
||||
"optionsReference": "Account.industry",
|
||||
"default": "",
|
||||
"isSorted": true
|
||||
},
|
||||
|
||||
@@ -201,8 +201,7 @@
|
||||
"type": "enum",
|
||||
"view": "crm:views/opportunity/fields/lead-source",
|
||||
"customizationOptionsDisabled": true,
|
||||
"optionsPath": "entityDefs.Lead.fields.source.options",
|
||||
"translation": "Lead.options.source"
|
||||
"optionsReference": "Lead.source"
|
||||
},
|
||||
"closeDate": {
|
||||
"type": "date",
|
||||
|
||||
@@ -162,6 +162,7 @@
|
||||
"default": "Default",
|
||||
"maxLength": "Max Length",
|
||||
"options": "Options",
|
||||
"optionsReference": "Options Reference",
|
||||
"after": "After (field)",
|
||||
"before": "Before (field)",
|
||||
"link": "Link",
|
||||
|
||||
@@ -80,6 +80,7 @@
|
||||
}
|
||||
},
|
||||
"tooltips": {
|
||||
"optionsReference": "Re-use options from another field.",
|
||||
"currencyDecimal": "Use the Decimal DB type. In the app, values will be represented as strings. Check this parameter if precision is required.",
|
||||
"cutHeight": "A text higher then a specified value will be cut with a 'show more' button displayed.",
|
||||
"urlStrip": "Strip a protocol and a trailing slash.",
|
||||
|
||||
@@ -11,6 +11,12 @@
|
||||
"view": "views/admin/field-manager/fields/options",
|
||||
"tooltip": "optionsArray"
|
||||
},
|
||||
{
|
||||
"name": "optionsReference",
|
||||
"type": "varchar",
|
||||
"view": "views/admin/field-manager/fields/options-reference",
|
||||
"tooltip": true
|
||||
},
|
||||
{
|
||||
"name": "translation",
|
||||
"type": "varchar",
|
||||
|
||||
@@ -13,6 +13,12 @@
|
||||
"required": true,
|
||||
"tooltip": true
|
||||
},
|
||||
{
|
||||
"name": "optionsReference",
|
||||
"type": "varchar",
|
||||
"view": "views/admin/field-manager/fields/options-reference",
|
||||
"tooltip": true
|
||||
},
|
||||
{
|
||||
"name": "isSorted",
|
||||
"type": "bool"
|
||||
|
||||
@@ -16,6 +16,12 @@
|
||||
"type": "enum",
|
||||
"view": "views/admin/field-manager/fields/options/default"
|
||||
},
|
||||
{
|
||||
"name": "optionsReference",
|
||||
"type": "varchar",
|
||||
"view": "views/admin/field-manager/fields/options-reference",
|
||||
"tooltip": true
|
||||
},
|
||||
{
|
||||
"name": "isSorted",
|
||||
"type": "bool"
|
||||
|
||||
@@ -11,6 +11,12 @@
|
||||
"view": "views/admin/field-manager/fields/options-with-style",
|
||||
"tooltip": true
|
||||
},
|
||||
{
|
||||
"name": "optionsReference",
|
||||
"type": "varchar",
|
||||
"view": "views/admin/field-manager/fields/options-reference",
|
||||
"tooltip": true
|
||||
},
|
||||
{
|
||||
"name": "isSorted",
|
||||
"type": "bool"
|
||||
|
||||
@@ -32,11 +32,20 @@ namespace Espo\Tools\App\Language;
|
||||
use Espo\Core\Utils\Config;
|
||||
use Espo\Core\Utils\DataCache;
|
||||
use Espo\Core\Utils\Metadata;
|
||||
use Espo\ORM\Defs;
|
||||
|
||||
class AclDependencyProvider
|
||||
{
|
||||
private const CACHE_KEY = 'languageAclDependency';
|
||||
|
||||
/** @var string[] */
|
||||
private array $enumFieldTypeList = [
|
||||
'enum',
|
||||
'multiEnum',
|
||||
'array',
|
||||
'checklist',
|
||||
];
|
||||
|
||||
/** @var ?AclDependencyItem[] */
|
||||
private ?array $data = null;
|
||||
private bool $useCache;
|
||||
@@ -44,7 +53,8 @@ class AclDependencyProvider
|
||||
public function __construct(
|
||||
private DataCache $dataCache,
|
||||
private Metadata $metadata,
|
||||
Config $config
|
||||
Config $config,
|
||||
private Defs $ormDefs
|
||||
) {
|
||||
$this->useCache = $config->get('useCache');
|
||||
}
|
||||
@@ -96,6 +106,35 @@ class AclDependencyProvider
|
||||
];
|
||||
}
|
||||
|
||||
foreach ($this->ormDefs->getEntityList() as $entityDefs) {
|
||||
if (!$this->metadata->get(['scopes', $entityDefs->getName(), 'object'])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach ($entityDefs->getFieldList() as $fieldDefs) {
|
||||
if (!in_array($fieldDefs->getType(), $this->enumFieldTypeList)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$optionsReference = $fieldDefs->getParam('optionsReference');
|
||||
|
||||
if (!$optionsReference || !str_contains($optionsReference, '.')) {
|
||||
continue;
|
||||
}
|
||||
|
||||
[$refEntityType, $refField] = explode('.', $optionsReference);
|
||||
|
||||
$target = "{$refEntityType}.options.{$refField}";
|
||||
|
||||
$data[] = [
|
||||
'target' => $target,
|
||||
'anyScopeList' => null,
|
||||
'scope' => $entityDefs->getName(),
|
||||
'field' => $fieldDefs->getName(),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->useCache) {
|
||||
$this->dataCache->store(self::CACHE_KEY, $data);
|
||||
}
|
||||
|
||||
@@ -32,11 +32,20 @@ namespace Espo\Tools\App\Metadata;
|
||||
use Espo\Core\Utils\Config;
|
||||
use Espo\Core\Utils\DataCache;
|
||||
use Espo\Core\Utils\Metadata;
|
||||
use Espo\ORM\Defs;
|
||||
|
||||
class AclDependencyProvider
|
||||
{
|
||||
private const CACHE_KEY = 'metadataAclDependency';
|
||||
|
||||
/** @var string[] */
|
||||
private array $enumFieldTypeList = [
|
||||
'enum',
|
||||
'multiEnum',
|
||||
'array',
|
||||
'checklist',
|
||||
];
|
||||
|
||||
/** @var ?AclDependencyItem[] */
|
||||
private ?array $data = null;
|
||||
private bool $useCache;
|
||||
@@ -44,7 +53,8 @@ class AclDependencyProvider
|
||||
public function __construct(
|
||||
private DataCache $dataCache,
|
||||
private Metadata $metadata,
|
||||
Config $config
|
||||
Config $config,
|
||||
private Defs $ormDefs
|
||||
) {
|
||||
$this->useCache = $config->get('useCache');
|
||||
}
|
||||
@@ -98,6 +108,41 @@ class AclDependencyProvider
|
||||
];
|
||||
}
|
||||
|
||||
foreach ($this->ormDefs->getEntityList() as $entityDefs) {
|
||||
if (!$this->metadata->get(['scopes', $entityDefs->getName(), 'object'])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach ($entityDefs->getFieldList() as $fieldDefs) {
|
||||
if (!in_array($fieldDefs->getType(), $this->enumFieldTypeList)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$optionsPath = $fieldDefs->getParam('optionsPath');
|
||||
$optionsReference = $fieldDefs->getParam('optionsReference');
|
||||
|
||||
if (
|
||||
!$optionsPath &&
|
||||
$optionsReference &&
|
||||
str_contains($optionsReference, '.')
|
||||
) {
|
||||
[$refEntityType, $refField] = explode('.', $optionsReference);
|
||||
|
||||
$optionsPath = "entityDefs.{$refEntityType}.fields.{$refField}.options";
|
||||
}
|
||||
|
||||
if (!$optionsPath) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$data[] = [
|
||||
'target' => $optionsPath,
|
||||
'scope' => $entityDefs->getName(),
|
||||
'field' => $fieldDefs->getName(),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->useCache) {
|
||||
$this->dataCache->store(self::CACHE_KEY, $data);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2023 Yurii Kuznietsov, Taras Machyshyn, Oleksii 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/field-manager/fields/options-reference', ['views/fields/enum'], function (Dep) {
|
||||
|
||||
return Dep.extend({
|
||||
|
||||
enumFieldTypeList: [
|
||||
'enum',
|
||||
'multiEnum',
|
||||
'array',
|
||||
'checklist',
|
||||
'varchar',
|
||||
],
|
||||
|
||||
setupOptions: function () {
|
||||
this.params.options = [''];
|
||||
|
||||
let entityTypeList = Object.keys(this.getMetadata().get(['entityDefs']))
|
||||
.filter(item => this.getMetadata().get(['scopes', item, 'object']))
|
||||
.sort((s1, s2) => {
|
||||
return this.getLanguage().translate(s1, 'scopesName')
|
||||
.localeCompare(this.getLanguage().translate(s2, 'scopesName'));
|
||||
});
|
||||
|
||||
this.translatedOptions = {};
|
||||
|
||||
entityTypeList.forEach(entityType => {
|
||||
let fieldList =
|
||||
Object.keys(this.getMetadata().get(['entityDefs', entityType, 'fields']) || [])
|
||||
.filter(item => entityType !== this.model.scope || item !== this.model.get('name'))
|
||||
.sort((s1, s2) => {
|
||||
return this.getLanguage().translate(s1, 'fields', entityType)
|
||||
.localeCompare(this.getLanguage().translate(s2, 'fields', entityType));
|
||||
});
|
||||
|
||||
fieldList.forEach(field => {
|
||||
let {type, options, optionsPath, optionsReference} =
|
||||
this.getMetadata().get(['entityDefs', entityType, 'fields', field]) || {};
|
||||
|
||||
if (!this.enumFieldTypeList.includes(type)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (optionsPath || optionsReference) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!options) {
|
||||
return;
|
||||
}
|
||||
|
||||
let value = entityType + '.' + field;
|
||||
|
||||
this.params.options.push(value);
|
||||
|
||||
this.translatedOptions[value] =
|
||||
this.translate(entityType, 'scopeName') + ' · ' +
|
||||
this.translate(field, 'fields', entityType);
|
||||
});
|
||||
});
|
||||
},
|
||||
});
|
||||
});
|
||||
@@ -138,10 +138,18 @@ function (Dep, RegExpPattern, /** module:ui/multi-select*/MultiSelect) {
|
||||
this.selected = [];
|
||||
}
|
||||
|
||||
if (this.params.optionsPath) {
|
||||
this.params.options = Espo.Utils.clone(
|
||||
this.getMetadata().get(this.params.optionsPath) || []
|
||||
);
|
||||
let optionsPath = this.params.optionsPath;
|
||||
/** @type {?string} */
|
||||
let optionsReference = this.params.optionsReference;
|
||||
|
||||
if (!optionsPath && optionsReference) {
|
||||
let [refEntityType, refField] = optionsReference.split('.');
|
||||
|
||||
optionsPath = `entityDefs.${refEntityType}.fields.${refField}.options`;
|
||||
}
|
||||
|
||||
if (optionsPath) {
|
||||
this.params.options = Espo.Utils.clone(this.getMetadata().get(optionsPath)) || [];
|
||||
}
|
||||
|
||||
this.styleMap = this.params.style || {};
|
||||
@@ -214,8 +222,18 @@ function (Dep, RegExpPattern, /** module:ui/multi-select*/MultiSelect) {
|
||||
setupTranslation: function () {
|
||||
let t = {};
|
||||
|
||||
if (this.params.translation) {
|
||||
let arr = this.params.translation.split('.');
|
||||
let translation = this.params.translation;
|
||||
/** @type {?string} */
|
||||
let optionsReference = this.params.optionsReference;
|
||||
|
||||
if (!translation && optionsReference) {
|
||||
let [refEntityType, refField] = optionsReference.split('.');
|
||||
|
||||
translation = `${refEntityType}.options.${refField}`;
|
||||
}
|
||||
|
||||
if (translation) {
|
||||
let arr = translation.split('.');
|
||||
|
||||
let pointer = this.getLanguage().data;
|
||||
|
||||
|
||||
@@ -109,10 +109,18 @@ function (Dep, /** module:ui/multi-select*/MultiSelect, /** module:ui/select*/Se
|
||||
}
|
||||
}
|
||||
|
||||
if (this.params.optionsPath) {
|
||||
this.params.options = Espo.Utils.clone(
|
||||
this.getMetadata().get(this.params.optionsPath) || []
|
||||
);
|
||||
let optionsPath = this.params.optionsPath;
|
||||
/** @type {?string} */
|
||||
let optionsReference = this.params.optionsReference;
|
||||
|
||||
if (!optionsPath && optionsReference) {
|
||||
let [refEntityType, refField] = optionsReference.split('.');
|
||||
|
||||
optionsPath = `entityDefs.${refEntityType}.fields.${refField}.options`;
|
||||
}
|
||||
|
||||
if (optionsPath) {
|
||||
this.params.options = Espo.Utils.clone(this.getMetadata().get(optionsPath)) || [];
|
||||
}
|
||||
|
||||
this.styleMap = this.params.style || this.model.getFieldParam(this.name, 'style') || {};
|
||||
@@ -153,13 +161,23 @@ function (Dep, /** module:ui/multi-select*/MultiSelect, /** module:ui/select*/Se
|
||||
},
|
||||
|
||||
setupTranslation: function () {
|
||||
if (!this.params.translation) {
|
||||
let translation = this.params.translation;
|
||||
/** @type {?string} */
|
||||
let optionsReference = this.params.optionsReference;
|
||||
|
||||
if (!translation && optionsReference) {
|
||||
let [refEntityType, refField] = optionsReference.split('.');
|
||||
|
||||
translation = `${refEntityType}.options.${refField}`;
|
||||
}
|
||||
|
||||
if (!translation) {
|
||||
return;
|
||||
}
|
||||
|
||||
let translationObj;
|
||||
|
||||
let arr = this.params.translation.split('.');
|
||||
let arr = translation.split('.');
|
||||
let pointer = this.getLanguage().data;
|
||||
|
||||
arr.forEach(key => {
|
||||
|
||||
Reference in New Issue
Block a user