mirror of
https://github.com/espocrm/espocrm.git
synced 2026-06-28 06:56:05 +00:00
admin changes update current and other tabs
This commit is contained in:
@@ -58,6 +58,7 @@ define(
|
||||
'ajax',
|
||||
'number',
|
||||
'page-title',
|
||||
'broadcast-channel'
|
||||
],
|
||||
function (
|
||||
Espo,
|
||||
@@ -88,7 +89,8 @@ define(
|
||||
WebSocketManager,
|
||||
Ajax,
|
||||
NumberUtil,
|
||||
PageTitle
|
||||
PageTitle,
|
||||
BroadcastChannel
|
||||
) {
|
||||
|
||||
let App = function (options, callback) {
|
||||
@@ -149,6 +151,8 @@ define(
|
||||
|
||||
responseCache: null,
|
||||
|
||||
broadcastChannel: null,
|
||||
|
||||
initCache: function (options) {
|
||||
let cacheTimestamp = options.cacheTimestamp || null;
|
||||
let storedCacheTimestamp = null;
|
||||
@@ -290,6 +294,8 @@ define(
|
||||
this.webSocketManager.connect(this.auth, this.user.id);
|
||||
}
|
||||
|
||||
this.initBroadcastChannel();
|
||||
|
||||
let promiseList = [];
|
||||
let aclImplementationClassMap = {};
|
||||
|
||||
@@ -426,6 +432,7 @@ define(
|
||||
storage: this.storage,
|
||||
metadata: this.metadata,
|
||||
dateTime: this.dateTime,
|
||||
broadcastChannel: this.broadcastChannel,
|
||||
};
|
||||
},
|
||||
|
||||
@@ -649,14 +656,17 @@ define(
|
||||
|
||||
this.unsetCookieAuth();
|
||||
|
||||
if (this.broadcastChannel.object) {
|
||||
this.broadcastChannel.object.close();
|
||||
}
|
||||
|
||||
this.broadcastChannel = null;
|
||||
|
||||
xhr = new XMLHttpRequest;
|
||||
|
||||
xhr.open('GET', this.basePath + this.apiUrl + '/');
|
||||
|
||||
xhr.setRequestHeader('Authorization', 'Basic ' + base64.encode('**logout:logout'));
|
||||
|
||||
xhr.send('');
|
||||
|
||||
xhr.abort();
|
||||
|
||||
this.loadStylesheet();
|
||||
@@ -884,6 +894,37 @@ define(
|
||||
});
|
||||
},
|
||||
|
||||
initBroadcastChannel: function () {
|
||||
this.broadcastChannel = new BroadcastChannel();
|
||||
|
||||
this.broadcastChannel.subscribe(event => {
|
||||
if (event.data === 'update:all') {
|
||||
this.metadata.loadSkipCache();
|
||||
this.settings.loadSkipCache();
|
||||
this.language.loadSkipCache();
|
||||
this.viewHelper.layoutManager.clearLoadedData();
|
||||
}
|
||||
|
||||
if (event.data === 'update:metadata') {
|
||||
this.metadata.loadSkipCache();
|
||||
}
|
||||
|
||||
if (event.data === 'update:config') {
|
||||
this.settings.load();
|
||||
}
|
||||
|
||||
if (event.data === 'update:language') {
|
||||
this.language.loadSkipCache();
|
||||
}
|
||||
|
||||
if (event.data === 'update:layout') {
|
||||
this.viewHelper.layoutManager.clearLoadedData();
|
||||
}
|
||||
});
|
||||
|
||||
this.viewHelper.broadcastChannel = this.broadcastChannel;
|
||||
},
|
||||
|
||||
}, Backbone.Events);
|
||||
|
||||
App.extend = Backbone.Router.extend;
|
||||
|
||||
58
client/src/broadcast-channel.js
Normal file
58
client/src/broadcast-channel.js
Normal file
@@ -0,0 +1,58 @@
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2021 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('broadcast-channel', [], function () {
|
||||
|
||||
let Channel = class {
|
||||
constructor() {
|
||||
this.object = null;
|
||||
|
||||
if (BroadcastChannel) {
|
||||
this.object = new BroadcastChannel('app');
|
||||
}
|
||||
}
|
||||
|
||||
postMessage(message) {
|
||||
if (!this.object) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.object.postMessage(message);
|
||||
}
|
||||
|
||||
subscribe(callback) {
|
||||
if (!this.object) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.object.addEventListener('message', callback);
|
||||
}
|
||||
};
|
||||
|
||||
return Channel;
|
||||
});
|
||||
@@ -50,6 +50,7 @@ define('controller', [], function () {
|
||||
this._storage = injections.storage || null;
|
||||
this._metadata = injections.metadata || null;
|
||||
this._dateTime = injections.dateTime || null;
|
||||
this._broadcastChannel = injections.broadcastChannel || null;
|
||||
|
||||
this.set('masterRendered', false);
|
||||
};
|
||||
|
||||
@@ -116,6 +116,12 @@ define('controllers/admin', ['controller', 'search-manager'], function (Dep, Sea
|
||||
let model = this.getConfig().clone();
|
||||
model.defs = this.getConfig().defs;
|
||||
|
||||
this.listenTo(model, 'after:save', () => {
|
||||
this.getConfig().load();
|
||||
|
||||
this._broadcastChannel.postMessage('update:config');
|
||||
});
|
||||
|
||||
return model;
|
||||
},
|
||||
|
||||
|
||||
@@ -176,6 +176,10 @@ define('layout-manager', [], function () {
|
||||
);
|
||||
},
|
||||
|
||||
clearLoadedData: function () {
|
||||
this.data = {};
|
||||
},
|
||||
|
||||
}, Backbone.Events);
|
||||
|
||||
return LayoutManager;
|
||||
|
||||
@@ -705,6 +705,8 @@ define('views/admin/entity-manager/modals/edit-entity', ['views/modal', 'model']
|
||||
scope: name,
|
||||
};
|
||||
|
||||
this.broadcastUpdate();
|
||||
|
||||
this.trigger('after:save', o);
|
||||
});
|
||||
})
|
||||
@@ -731,6 +733,8 @@ define('views/admin/entity-manager/modals/edit-entity', ['views/modal', 'model']
|
||||
this.model.fetchedAttributes = this.model.getClonedAttributes();
|
||||
|
||||
this.notify('Done', 'success');
|
||||
|
||||
this.broadcastUpdate();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -827,5 +831,11 @@ define('views/admin/entity-manager/modals/edit-entity', ['views/modal', 'model']
|
||||
return filtersOptionList;
|
||||
},
|
||||
|
||||
broadcastUpdate: function () {
|
||||
this.getHelper().broadcastChannel.postMessage('update:metadata');
|
||||
this.getHelper().broadcastChannel.postMessage('update:language');
|
||||
this.getHelper().broadcastChannel.postMessage('update:config');
|
||||
},
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
@@ -148,6 +148,8 @@ define('views/admin/entity-manager/scope', 'view', function (Dep) {
|
||||
this.getConfig().load().then(() => {
|
||||
Espo.Ui.notify(false);
|
||||
|
||||
this.broadcastUpdate();
|
||||
|
||||
this.getRouter().navigate('#Admin/entityManager', {trigger: true});
|
||||
});
|
||||
});
|
||||
@@ -195,5 +197,10 @@ define('views/admin/entity-manager/scope', 'view', function (Dep) {
|
||||
this.$el.find('.item-dropdown-button"]').removeClass('disabled').removeAttr('disabled');
|
||||
},
|
||||
|
||||
broadcastUpdate: function () {
|
||||
this.getHelper().broadcastChannel.postMessage('update:metadata');
|
||||
this.getHelper().broadcastChannel.postMessage('update:settings');
|
||||
},
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
@@ -565,6 +565,8 @@ define('views/admin/field-manager/edit', ['view', 'model'], function (Dep, Model
|
||||
.then(() => this.trigger('after:save'));
|
||||
|
||||
this.model.fetchedAttributes = this.model.getClonedAttributes();
|
||||
|
||||
this.broadcastUpdate();
|
||||
});
|
||||
|
||||
this.notify('Saving...');
|
||||
@@ -648,6 +650,8 @@ define('views/admin/field-manager/edit', ['view', 'model'], function (Dep, Model
|
||||
this.notify('Done', 'success');
|
||||
|
||||
this.reRender();
|
||||
|
||||
this.broadcastUpdate();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -655,5 +659,11 @@ define('views/admin/field-manager/edit', ['view', 'model'], function (Dep, Model
|
||||
}, this);
|
||||
},
|
||||
|
||||
broadcastUpdate: function () {
|
||||
this.getHelper().broadcastChannel.postMessage('update:metadata');
|
||||
this.getHelper().broadcastChannel.postMessage('update:language');
|
||||
this.getHelper().broadcastChannel.postMessage('update:settings');
|
||||
},
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
@@ -36,7 +36,7 @@ define('views/admin/field-manager/list', 'view', function (Dep) {
|
||||
return {
|
||||
scope: this.scope,
|
||||
fieldDefsArray: this.fieldDefsArray,
|
||||
typeList: this.typeList
|
||||
typeList: this.typeList,
|
||||
};
|
||||
},
|
||||
|
||||
@@ -57,22 +57,26 @@ define('views/admin/field-manager/list', 'view', function (Dep) {
|
||||
},
|
||||
|
||||
buildFieldDefs: function () {
|
||||
return this.getModelFactory().create(this.scope).then(
|
||||
function (model) {
|
||||
this.fields = model.defs.fields;
|
||||
this.fieldList = Object.keys(this.fields).sort();
|
||||
this.fieldDefsArray = [];
|
||||
this.fieldList.forEach(function (field) {
|
||||
var defs = this.fields[field];
|
||||
if (defs.customizationDisabled) return;
|
||||
this.fieldDefsArray.push({
|
||||
name: field,
|
||||
isCustom: defs.isCustom || false,
|
||||
type: defs.type
|
||||
});
|
||||
}, this);
|
||||
}.bind(this)
|
||||
);
|
||||
return this.getModelFactory().create(this.scope).then(model => {
|
||||
this.fields = model.defs.fields;
|
||||
|
||||
this.fieldList = Object.keys(this.fields).sort();
|
||||
this.fieldDefsArray = [];
|
||||
|
||||
this.fieldList.forEach(field => {
|
||||
var defs = this.fields[field];
|
||||
|
||||
if (defs.customizationDisabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.fieldDefsArray.push({
|
||||
name: field,
|
||||
isCustom: defs.isCustom || false,
|
||||
type: defs.type,
|
||||
});
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
removeField: function (field) {
|
||||
@@ -87,15 +91,24 @@ define('views/admin/field-manager/list', 'view', function (Dep) {
|
||||
|
||||
delete data['entityDefs'][this.scope]['fields'][field];
|
||||
|
||||
this.getMetadata().loadSkipCache(() => {
|
||||
this.getMetadata().loadSkipCache().then(() =>
|
||||
this.buildFieldDefs()
|
||||
.then(() => {
|
||||
this.broadcastUpdate();
|
||||
|
||||
return this.reRender();
|
||||
})
|
||||
.then(() => Espo.Ui.success(this.translate('Removed')));
|
||||
});
|
||||
.then(() =>
|
||||
Espo.Ui.success(this.translate('Removed'))
|
||||
)
|
||||
);
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
broadcastUpdate: function () {
|
||||
this.getHelper().broadcastChannel.postMessage('update:metadata');
|
||||
this.getHelper().broadcastChannel.postMessage('update:language');
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
@@ -134,8 +134,9 @@ define('views/admin/label-manager/edit', 'view', function (Dep) {
|
||||
this.ajaxPostRequest('LabelManager/action/saveLabels', {
|
||||
scope: this.scope,
|
||||
language: this.language,
|
||||
labels: data
|
||||
}).then(returnData => {
|
||||
labels: data,
|
||||
})
|
||||
.then(returnData => {
|
||||
this.scopeDataInitial = Espo.Utils.cloneDeep(this.scopeData);
|
||||
this.dirtyLabelList = [];
|
||||
this.setConfirmLeaveOut(false);
|
||||
@@ -149,7 +150,12 @@ define('views/admin/label-manager/edit', 'view', function (Dep) {
|
||||
}
|
||||
|
||||
Espo.Ui.success(this.translate('Saved'));
|
||||
}).fail(() => {
|
||||
|
||||
this.getHelper().broadcastChannel.postMessage('update:language');
|
||||
|
||||
this.getLanguage().loadSkipCache();
|
||||
})
|
||||
.fail(() => {
|
||||
this.$save.removeClass('disabled').removeAttr('disabled');
|
||||
this.$cancel.removeClass('disabled').removeAttr('disabled');
|
||||
});
|
||||
|
||||
@@ -109,6 +109,8 @@ define('views/admin/layouts/base', 'view', function (Dep) {
|
||||
if (typeof callback === 'function') {
|
||||
callback();
|
||||
}
|
||||
|
||||
this.getHelper().broadcastChannel.postMessage('update:layout');
|
||||
}, this.setId);
|
||||
},
|
||||
|
||||
|
||||
@@ -746,6 +746,8 @@ define('views/admin/link-manager/modals/edit',
|
||||
}
|
||||
|
||||
this.getMetadata().loadSkipCache().then(() => {
|
||||
this.broadcastUpdate();
|
||||
|
||||
this.trigger('after:save');
|
||||
this.close();
|
||||
});
|
||||
@@ -759,8 +761,13 @@ define('views/admin/link-manager/modals/edit',
|
||||
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 (
|
||||
linkDefs[i].foreign === link &&
|
||||
linkDefs[i].entity === entityType &&
|
||||
linkDefs[i].type === 'hasChildren'
|
||||
) {
|
||||
if (onlyNotCustom) {
|
||||
if (linkDefs[i].isCustom) {
|
||||
continue;
|
||||
@@ -778,5 +785,10 @@ define('views/admin/link-manager/modals/edit',
|
||||
|
||||
return list;
|
||||
},
|
||||
|
||||
broadcastUpdate: function () {
|
||||
this.getHelper().broadcastChannel.postMessage('update:metadata');
|
||||
this.getHelper().broadcastChannel.postMessage('update:language');
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
@@ -357,38 +357,47 @@ define('views/site/navbar', 'view', function (Dep) {
|
||||
this.getRouter().on('routed', (e) => {
|
||||
if (e.controller) {
|
||||
this.selectTab(e.controller);
|
||||
|
||||
return;
|
||||
}
|
||||
else {
|
||||
this.selectTab(false);
|
||||
}
|
||||
|
||||
this.selectTab(false);
|
||||
});
|
||||
|
||||
var tabList = this.getTabList();
|
||||
this.createView('notificationsBadge', 'views/notification/badge', {
|
||||
el: this.options.el + ' .notifications-badge-container'
|
||||
});
|
||||
|
||||
let setup = () => {
|
||||
this.setupQuickCreateList();
|
||||
this.setupGlobalSearch();
|
||||
this.setupTabDefsList();
|
||||
};
|
||||
|
||||
setup();
|
||||
|
||||
this.listenTo(this.getHelper().settings, 'sync', () => {
|
||||
setup();
|
||||
|
||||
this.reRender();
|
||||
});
|
||||
|
||||
this.listenTo(this.getHelper().language, 'sync', () => {
|
||||
setup();
|
||||
|
||||
this.reRender();
|
||||
});
|
||||
|
||||
this.once('remove', () => {
|
||||
$(window).off('resize.navbar');
|
||||
$(window).off('scroll.navbar');
|
||||
$(window).off('scroll.navbar-tab-group');
|
||||
});
|
||||
},
|
||||
|
||||
setupQuickCreateList: function () {
|
||||
var scopes = this.getMetadata().get('scopes') || {};
|
||||
|
||||
this.tabList = tabList.filter(item => {
|
||||
if (!item) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (typeof item === 'object') {
|
||||
item.itemList = item.itemList || [];
|
||||
|
||||
item.itemList = item.itemList.filter(item => {
|
||||
return this.filterTabItem(item);
|
||||
});
|
||||
|
||||
if (!item.itemList.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return this.filterTabItem(item);
|
||||
});
|
||||
|
||||
this.quickCreateList = this.getQuickCreateList().filter(scope =>{
|
||||
if (!scopes[scope]) {
|
||||
return false;
|
||||
@@ -404,20 +413,6 @@ define('views/site/navbar', 'view', function (Dep) {
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
this.createView('notificationsBadge', 'views/notification/badge', {
|
||||
el: this.options.el + ' .notifications-badge-container'
|
||||
});
|
||||
|
||||
this.setupGlobalSearch();
|
||||
|
||||
this.setupTabDefsList();
|
||||
|
||||
this.once('remove', () => {
|
||||
$(window).off('resize.navbar');
|
||||
$(window).off('scroll.navbar');
|
||||
$(window).off('scroll.navbar-tab-group');
|
||||
});
|
||||
},
|
||||
|
||||
filterTabItem: function (scope) {
|
||||
@@ -890,6 +885,30 @@ define('views/site/navbar', 'view', function (Dep) {
|
||||
},
|
||||
|
||||
setupTabDefsList: function () {
|
||||
var tabList = this.getTabList();
|
||||
|
||||
this.tabList = tabList.filter(item => {
|
||||
if (!item) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (typeof item === 'object') {
|
||||
item.itemList = item.itemList || [];
|
||||
|
||||
item.itemList = item.itemList.filter(item => {
|
||||
return this.filterTabItem(item);
|
||||
});
|
||||
|
||||
if (!item.itemList.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return this.filterTabItem(item);
|
||||
});
|
||||
|
||||
var tabDefsList = [];
|
||||
|
||||
var colorsDisabled =
|
||||
|
||||
Reference in New Issue
Block a user