diff --git a/application/Espo/Controllers/EntityManager.php b/application/Espo/Controllers/EntityManager.php
index 76d46d2747..8c4fd69eb2 100644
--- a/application/Espo/Controllers/EntityManager.php
+++ b/application/Espo/Controllers/EntityManager.php
@@ -87,6 +87,11 @@ class EntityManager extends \Espo\Core\Controllers\Base
$params['color'] = $data['color'];
}
+ $params['kanbanViewMode'] = !empty($data['kanbanViewMode']);
+ if (!empty($data['kanbanStatusIgnoreList'])) {
+ $params['kanbanStatusIgnoreList'] = $data['kanbanStatusIgnoreList'];
+ }
+
$result = $this->getContainer()->get('entityManagerUtil')->create($name, $type, $params);
if ($result) {
diff --git a/application/Espo/Core/Utils/EntityManager.php b/application/Espo/Core/Utils/EntityManager.php
index e4d2a940e7..a85f441ba3 100644
--- a/application/Espo/Core/Utils/EntityManager.php
+++ b/application/Espo/Core/Utils/EntityManager.php
@@ -283,6 +283,10 @@ class EntityManager
$scopesData['isNotRemovable'] = true;
}
+ if (!empty($params['kanbanStatusIgnoreList'])) {
+ $scopesData['kanbanStatusIgnoreList'] = $params['kanbanStatusIgnoreList'];
+ }
+
$this->getMetadata()->set('scopes', $name, $scopesData);
$filePath = $templatePath . "/Metadata/{$type}/entityDefs.json";
@@ -306,6 +310,10 @@ class EntityManager
if (array_key_exists('color', $params)) {
$clientDefsData['color'] = $params['color'];
};
+
+ if (!empty($params['kanbanViewMode'])) {
+ $clientDefsData['kanbanViewMode'] = true;
+ }
$this->getMetadata()->set('clientDefs', $name, $clientDefsData);
$this->getBaseLanguage()->set('Global', 'scopeNames', $name, $labelSingular);
@@ -391,6 +399,18 @@ class EntityManager
$this->getMetadata()->set('entityDefs', $name, $entityDefsData);
}
+ if (array_key_exists('kanbanStatusIgnoreList', $data)) {
+ $scopeData['kanbanStatusIgnoreList'] = $data['kanbanStatusIgnoreList'];
+ $this->getMetadata()->set('scopes', $name, $scopeData);
+ }
+
+ if (array_key_exists('kanbanViewMode', $data)) {
+ $clientDefsData = [
+ 'kanbanViewMode' => $data['kanbanViewMode']
+ ];
+ $this->getMetadata()->set('clientDefs', $name, $clientDefsData);
+ }
+
if (array_key_exists('color', $data)) {
$clientDefsData = [
'color' => $data['color']
diff --git a/application/Espo/Resources/i18n/en_US/EntityManager.json b/application/Espo/Resources/i18n/en_US/EntityManager.json
index 99aea3ed5f..fd26ce1147 100644
--- a/application/Espo/Resources/i18n/en_US/EntityManager.json
+++ b/application/Espo/Resources/i18n/en_US/EntityManager.json
@@ -29,7 +29,9 @@
"auditedForeign": "Foreign Audited",
"statusField": "Status Field",
"beforeSaveCustomScript": "Before Save Custom Script",
- "color": "Color"
+ "color": "Color",
+ "kanbanViewMode": "Kanban View",
+ "kanbanStatusIgnoreList": "Ignored groups in Kanban view"
},
"options": {
"type": {
diff --git a/client/res/templates/admin/entity-manager/modals/edit-entity.tpl b/client/res/templates/admin/entity-manager/modals/edit-entity.tpl
index 415ebe4b6d..41916230c5 100644
--- a/client/res/templates/admin/entity-manager/modals/edit-entity.tpl
+++ b/client/res/templates/admin/entity-manager/modals/edit-entity.tpl
@@ -69,14 +69,27 @@
{{{textFilterFields}}}
- {{#if stream}}
- {{/if}}
+
+
+
{{/unless}}
diff --git a/client/src/views/admin/entity-manager/modals/edit-entity.js b/client/src/views/admin/entity-manager/modals/edit-entity.js
index b5ae02034b..0f39b2a9b0 100644
--- a/client/src/views/admin/entity-manager/modals/edit-entity.js
+++ b/client/src/views/admin/entity-manager/modals/edit-entity.js
@@ -91,6 +91,9 @@ Espo.define('views/admin/entity-manager/modals/edit-entity', ['views/modal', 'mo
this.model.set('statusField', this.getMetadata().get('scopes.' + scope + '.statusField') || null);
this.model.set('color', this.getMetadata().get(['clientDefs', scope, 'color']) || null);
+
+ this.model.set('kanbanViewMode', this.getMetadata().get(['clientDefs', scope, 'kanbanViewMode']) || false);
+ this.model.set('kanbanStatusIgnoreList', this.getMetadata().get(['scopes', scope, 'kanbanStatusIgnoreList']) || []);
}
this.createView('type', 'views/fields/enum', {
@@ -222,6 +225,15 @@ Espo.define('views/admin/entity-manager/modals/edit-entity', ['views/modal', 'mo
}
});
+ this.createView('kanbanViewMode', 'views/fields/bool', {
+ model: model,
+ mode: 'edit',
+ el: this.options.el + ' .field[data-name="kanbanViewMode"]',
+ defs: {
+ name: 'kanbanViewMode'
+ }
+ });
+
var optionList = Object.keys(fieldDefs).filter(function (item) {
if (!~['varchar', 'text', 'phone', 'email', 'personName', 'number'].indexOf(this.getMetadata().get(['entityDefs', scope, 'fields', item, 'type']))) {
return false;
@@ -253,39 +265,53 @@ Espo.define('views/admin/entity-manager/modals/edit-entity', ['views/modal', 'mo
});
- if (this.hasStreamField) {
- var enumFieldList = Object.keys(fieldDefs).filter(function (item) {
- if (fieldDefs[item].disabled) return;
- if (fieldDefs[item].type == 'enum') {
- return true;
+ var enumFieldList = Object.keys(fieldDefs).filter(function (item) {
+ if (fieldDefs[item].disabled) return;
+ if (fieldDefs[item].type == 'enum') {
+ return true;
+ }
+ return;
+ }, this).sort(function (v1, v2) {
+ return this.translate(v1, 'fields', scope).localeCompare(this.translate(v2, 'fields', scope));
+ }.bind(this));
+
+ var translatedStatusFields = {};
+ enumFieldList.forEach(function (item) {
+ translatedStatusFields[item] = this.translate(item, 'fields', scope);
+ }, this);
+ enumFieldList.unshift('');
+ translatedStatusFields[''] = '-' + this.translate('None') + '-';
+
+ this.createView('statusField', 'views/fields/enum', {
+ model: model,
+ mode: 'edit',
+ el: this.options.el + ' .field[data-name="statusField"]',
+ defs: {
+ name: 'statusField',
+ params: {
+ options: enumFieldList
}
- return;
- }, this).sort(function (v1, v2) {
- return this.translate(v1, 'fields', scope).localeCompare(this.translate(v2, 'fields', scope));
- }.bind(this));
+ },
+ tooltip: true,
+ tooltipText: this.translate('statusField', 'tooltips', 'EntityManager'),
+ translatedOptions: translatedStatusFields
+ });
- var translatedStatusFields = {};
- enumFieldList.forEach(function (item) {
- translatedStatusFields[item] = this.translate(item, 'fields', scope);
- }, this);
- enumFieldList.unshift('');
- translatedStatusFields[''] = '-' + this.translate('None') + '-';
+ var statusOptionList = [];
+ var translatedStatusOptions = {};
- this.createView('statusField', 'views/fields/enum', {
- model: model,
- mode: 'edit',
- el: this.options.el + ' .field[data-name="statusField"]',
- defs: {
- name: 'statusField',
- params: {
- options: enumFieldList
- }
- },
- tooltip: true,
- tooltipText: this.translate('statusField', 'tooltips', 'EntityManager'),
- translatedOptions: translatedStatusFields
- });
- }
+ this.createView('kanbanStatusIgnoreList', 'views/fields/multi-enum', {
+ model: model,
+ mode: 'edit',
+ el: this.options.el + ' .field[data-name="kanbanStatusIgnoreList"]',
+ defs: {
+ name: 'kanbanStatusIgnoreList',
+ params: {
+ options: statusOptionList
+ }
+ },
+ translatedOptions: translatedStatusOptions
+ });
}
this.model.fetchedAttributes = this.model.getClonedAttributes();
},
@@ -325,22 +351,62 @@ Espo.define('views/admin/entity-manager/modals/edit-entity', ['views/modal', 'mo
this.model.set('name', name);
}, this);
- this.manageStreamField();
- this.listenTo(this.model, 'change:stream', function () {
- this.manageStreamField();
- }, this);
+ if (!this.isNew) {
+ this.manageKanbanFields({});
+ this.listenTo(this.model, 'change:statusField', function (m, value, o) {
+ this.manageKanbanFields(o);
+ }, this);
+
+ this.manageKanbanViewModeField();
+ this.listenTo(this.model, 'change:kanbanViewMode', function () {
+ this.manageKanbanViewModeField();
+ }, this);
+ }
if (this.isNew) {
this.hideField('disabled');
}
},
- manageStreamField: function () {
- if (this.model.get('stream')) {
- this.showField('statusField');
- } else {
- this.hideField('statusField');
+ manageKanbanFields: function (o) {
+ if (o.ui) {
+ this.model.set('kanbanStatusIgnoreList', []);
}
+ if (this.model.get('statusField')) {
+ this.setKanbanStatusIgnoreListOptions();
+ this.showField('kanbanViewMode');
+ if (this.model.get('kanbanViewMode')) {
+ this.showField('kanbanStatusIgnoreList');
+ } else {
+ this.hideField('kanbanStatusIgnoreList');
+ }
+ } else {
+ this.hideField('kanbanViewMode');
+ this.hideField('kanbanStatusIgnoreList');
+ }
+ },
+
+ manageKanbanViewModeField: function () {
+ if (this.model.get('kanbanViewMode')) {
+ this.showField('kanbanStatusIgnoreList');
+ } else {
+ this.hideField('kanbanStatusIgnoreList');
+ }
+ },
+
+ setKanbanStatusIgnoreListOptions: function () {
+ var statusField = this.model.get('statusField');
+ var fieldView = this.getView('kanbanStatusIgnoreList');
+
+ var optionList = this.getMetadata().get(['entityDefs', this.scope, 'fields', statusField, 'options']) || [];
+ var translation = this.getMetadata().get(['entityDefs', this.scope, 'fields', statusField, 'translation']) || this.scope + '.options.' + statusField;
+
+ fieldView.params.options = optionList;
+ fieldView.params.translation = translation;
+
+ fieldView.setupTranslation();
+
+ fieldView.setOptionList(optionList);
},
actionSave: function () {
@@ -357,6 +423,8 @@ Espo.define('views/admin/entity-manager/modals/edit-entity', ['views/modal', 'mo
if (this.scope) {
arr.push('sortBy');
arr.push('sortDirection');
+ arr.push('kanbanViewMode');
+ arr.push('kanbanStatusIgnoreList');
}
var notValid = false;
@@ -405,6 +473,8 @@ Espo.define('views/admin/entity-manager/modals/edit-entity', ['views/modal', 'mo
if (this.scope) {
data.sortBy = this.model.get('sortBy');
data.sortDirection = this.model.get('sortDirection');
+ data.kanbanViewMode = this.model.get('kanbanViewMode');
+ data.kanbanStatusIgnoreList = this.model.get('kanbanStatusIgnoreList');
}
if (!this.isNew) {
diff --git a/client/src/views/fields/array.js b/client/src/views/fields/array.js
index f9eb91258c..882092b7c6 100644
--- a/client/src/views/fields/array.js
+++ b/client/src/views/fields/array.js
@@ -105,32 +105,7 @@ Espo.define('views/fields/array', ['views/fields/base', 'lib!Selectize'], functi
}
if (!this.translatedOptions) {
- var t = {};
- if (this.params.translation) {
- var data = this.getLanguage().data;
- var arr = this.params.translation.split('.');
- var pointer = this.getLanguage().data;
- arr.forEach(function (key) {
- if (key in pointer) {
- pointer = pointer[key];
- t = pointer;
- }
- }, this);
- } else {
- t = this.translate(this.name, 'options', this.model.name);
- }
- this.translatedOptions = null;
- var translatedOptions = {};
- if (this.params.options) {
- this.params.options.forEach(function (o) {
- if (typeof t === 'object' && o in t) {
- translatedOptions[o] = t[o];
- } else {
- translatedOptions[o] = o;
- }
- }.bind(this));
- this.translatedOptions = translatedOptions;
- }
+ this.setupTranslation();
}
if (this.options.customOptionList) {
@@ -138,6 +113,35 @@ Espo.define('views/fields/array', ['views/fields/base', 'lib!Selectize'], functi
}
},
+ setupTranslation: function () {
+ var t = {};
+ if (this.params.translation) {
+ var data = this.getLanguage().data;
+ var arr = this.params.translation.split('.');
+ var pointer = this.getLanguage().data;
+ arr.forEach(function (key) {
+ if (key in pointer) {
+ pointer = pointer[key];
+ t = pointer;
+ }
+ }, this);
+ } else {
+ t = this.translate(this.name, 'options', this.model.name);
+ }
+ this.translatedOptions = null;
+ var translatedOptions = {};
+ if (this.params.options) {
+ this.params.options.forEach(function (o) {
+ if (typeof t === 'object' && o in t) {
+ translatedOptions[o] = t[o];
+ } else {
+ translatedOptions[o] = o;
+ }
+ }.bind(this));
+ this.translatedOptions = translatedOptions;
+ }
+ },
+
setupOptions: function () {
},
diff --git a/client/src/views/fields/enum.js b/client/src/views/fields/enum.js
index 132fb6d13c..a6800911e7 100644
--- a/client/src/views/fields/enum.js
+++ b/client/src/views/fields/enum.js
@@ -80,6 +80,28 @@ Espo.define('views/fields/enum', ['views/fields/base', 'lib!Selectize'], functio
this.translatedOptions = this.params.translatedOptions;
}
+ this.setupTranslation();
+
+ if (this.translatedOptions === null) {
+ this.translatedOptions = this.getLanguage().translate(this.name, 'options', this.model.name) || {};
+ if (this.translatedOptions === this.name) {
+ this.translatedOptions = null;
+ }
+ }
+
+ if (this.params.isSorted && this.translatedOptions) {
+ this.params.options = Espo.Utils.clone(this.params.options);
+ this.params.options = this.params.options.sort(function (v1, v2) {
+ return (this.translatedOptions[v1] || v1).localeCompare(this.translatedOptions[v2] || v2);
+ }.bind(this));
+ }
+
+ if (this.options.customOptionList) {
+ this.setOptionList(this.options.customOptionList);
+ }
+ },
+
+ setupTranslation: function () {
if (this.params.translation) {
var translationObj;
var data = this.getLanguage().data;
@@ -111,24 +133,6 @@ Espo.define('views/fields/enum', ['views/fields/base', 'lib!Selectize'], functio
this.translatedOptions = translatedOptions;
}
}
-
- if (this.translatedOptions === null) {
- this.translatedOptions = this.getLanguage().translate(this.name, 'options', this.model.name) || {};
- if (this.translatedOptions === this.name) {
- this.translatedOptions = null;
- }
- }
-
- if (this.params.isSorted && this.translatedOptions) {
- this.params.options = Espo.Utils.clone(this.params.options);
- this.params.options = this.params.options.sort(function (v1, v2) {
- return (this.translatedOptions[v1] || v1).localeCompare(this.translatedOptions[v2] || v2);
- }.bind(this));
- }
-
- if (this.options.customOptionList) {
- this.setOptionList(this.options.customOptionList);
- }
},
setupOptions: function () {