custom navbar items
This commit is contained in:
Generated
+19
@@ -854,6 +854,25 @@
|
||||
</SchemaInfo>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="metadata/app/clientNavbar">
|
||||
<value>
|
||||
<SchemaInfo>
|
||||
<option name="generatedName" value="New Schema" />
|
||||
<option name="name" value="metadata/app/clientNavbar" />
|
||||
<option name="relativePathToSchema" value="schema/metadata/app/clientNavbar.json" />
|
||||
<option name="schemaVersion" value="JSON Schema version 7" />
|
||||
<option name="patterns">
|
||||
<list>
|
||||
<Item>
|
||||
<option name="pattern" value="true" />
|
||||
<option name="path" value="*/Resources/metadata/app/clientNavbar.json" />
|
||||
<option name="mappingKind" value="Pattern" />
|
||||
</Item>
|
||||
</list>
|
||||
</option>
|
||||
</SchemaInfo>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="metadata/app/orm">
|
||||
<value>
|
||||
<SchemaInfo>
|
||||
|
||||
Vendored
+6
@@ -352,6 +352,12 @@
|
||||
],
|
||||
"url": "./schema/metadata/app/metadata.json"
|
||||
},
|
||||
{
|
||||
"fileMatch": [
|
||||
"*/Resources/metadata/app/clientNavbar.json"
|
||||
],
|
||||
"url": "./schema/metadata/app/clientNavbar.json"
|
||||
},
|
||||
{
|
||||
"fileMatch": [
|
||||
"*/Resources/metadata/app/orm.json"
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"itemDefs": {
|
||||
"quickCreate": {
|
||||
"view": "views/site/navbar/quick-create",
|
||||
"class": "dropdown hidden-xs quick-create-container"
|
||||
}
|
||||
},
|
||||
"itemList": [
|
||||
"quickCreate"
|
||||
]
|
||||
}
|
||||
@@ -174,28 +174,9 @@
|
||||
<li class="nav navbar-nav navbar-form global-search-container">
|
||||
{{{globalSearch}}}
|
||||
</li>
|
||||
{{#if enableQuickCreate}}
|
||||
<li class="dropdown hidden-xs quick-create-container">
|
||||
<a
|
||||
id="nav-quick-create-dropdown"
|
||||
class="dropdown-toggle"
|
||||
data-toggle="dropdown"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
title="{{translate 'Create'}}"
|
||||
><i class="fas fa-plus icon"></i></a>
|
||||
<ul class="dropdown-menu" role="menu" aria-labelledby="nav-quick-create-dropdown">
|
||||
<li class="dropdown-header">{{translate 'Create'}}</li>
|
||||
{{#each quickCreateList}}
|
||||
<li><a
|
||||
href="#{{./this}}/create"
|
||||
data-name="{{./this}}"
|
||||
data-action="quick-create"
|
||||
>{{translate this category='scopeNames'}}</a></li>
|
||||
{{#each itemDataList}}
|
||||
<li class="{{class}}" data-item="{{name}}">{{{var key ../this}}}</li>
|
||||
{{/each}}
|
||||
</ul>
|
||||
</li>
|
||||
{{/if}}
|
||||
<li class="dropdown notifications-badge-container">
|
||||
{{{notificationsBadge}}}
|
||||
</li>
|
||||
|
||||
@@ -56,14 +56,6 @@ class NavbarSiteView extends View {
|
||||
this.xsCollapse();
|
||||
},
|
||||
/** @this NavbarSiteView */
|
||||
'click a[data-action="quick-create"]': function (e) {
|
||||
e.preventDefault();
|
||||
|
||||
const scope = $(e.currentTarget).data('name');
|
||||
|
||||
this.quickCreate(scope);
|
||||
},
|
||||
/** @this NavbarSiteView */
|
||||
'click a.minimizer': function () {
|
||||
this.switchMinimizer();
|
||||
},
|
||||
@@ -100,10 +92,9 @@ class NavbarSiteView extends View {
|
||||
tabDefsList2: this.tabDefsList.filter(item => item.isInMore),
|
||||
title: this.options.title,
|
||||
menuDataList: this.getMenuDataList(),
|
||||
quickCreateList: this.quickCreateList,
|
||||
enableQuickCreate: this.quickCreateList.length > 0,
|
||||
userId: this.getUser().id,
|
||||
logoSrc: this.getLogoSrc(),
|
||||
itemDataList: this.getItemDataList(),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -360,10 +351,6 @@ class NavbarSiteView extends View {
|
||||
return tabList;
|
||||
}
|
||||
|
||||
getQuickCreateList() {
|
||||
return this.getConfig().get('quickCreateList') || [];
|
||||
}
|
||||
|
||||
setup() {
|
||||
this.getRouter().on('routed', (e) => {
|
||||
if (e.controller) {
|
||||
@@ -375,30 +362,29 @@ class NavbarSiteView extends View {
|
||||
this.selectTab(false);
|
||||
});
|
||||
|
||||
/** @type {string[]} */
|
||||
this.itemList = this.getMetadata().get(['app', 'clientNavbar', 'itemList']) || [];
|
||||
|
||||
this.createView('notificationsBadge', 'views/notification/badge', {
|
||||
selector: '.notifications-badge-container',
|
||||
});
|
||||
|
||||
const setup = () => {
|
||||
this.setupQuickCreateList();
|
||||
this.setupTabDefsList();
|
||||
|
||||
return Promise
|
||||
.all(this.itemList.map(item => this.createItemView(item)));
|
||||
};
|
||||
|
||||
const update = () => {
|
||||
setup().then(() => this.reRender());
|
||||
};
|
||||
|
||||
this.setupGlobalSearch();
|
||||
|
||||
setup();
|
||||
|
||||
this.listenTo(this.getHelper().settings, 'sync', () => {
|
||||
setup();
|
||||
|
||||
this.reRender();
|
||||
});
|
||||
|
||||
this.listenTo(this.getHelper().language, 'sync', () => {
|
||||
setup();
|
||||
|
||||
this.reRender();
|
||||
});
|
||||
this.listenTo(this.getHelper().settings, 'sync', () => update());
|
||||
this.listenTo(this.getHelper().language, 'sync', () => update());
|
||||
|
||||
this.once('remove', () => {
|
||||
$(window).off('resize.navbar');
|
||||
@@ -409,26 +395,63 @@ class NavbarSiteView extends View {
|
||||
});
|
||||
}
|
||||
|
||||
setupQuickCreateList() {
|
||||
const scopes = this.getMetadata().get('scopes') || {};
|
||||
getItemDataList() {
|
||||
const defsMap = {};
|
||||
|
||||
this.quickCreateList = this.getQuickCreateList().filter(scope =>{
|
||||
if (!scopes[scope]) {
|
||||
this.itemList.forEach(name => {
|
||||
defsMap[name] = this.getItemDefs(name);
|
||||
});
|
||||
|
||||
return this.itemList
|
||||
.filter(name => {
|
||||
const defs = defsMap[name];
|
||||
|
||||
if (!defs) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((scopes[scope] || {}).disabled) {
|
||||
return;
|
||||
}
|
||||
const view = this.getView(name + 'Item');
|
||||
|
||||
if ((scopes[scope] || {}).acl) {
|
||||
return this.getAcl().check(scope, 'create');
|
||||
if ('isAvailable' in view) {
|
||||
return view.isAvailable();
|
||||
}
|
||||
|
||||
return true;
|
||||
})
|
||||
.map(name => {
|
||||
return {
|
||||
key: name + 'Item',
|
||||
name: name,
|
||||
class: defsMap[name].class || '',
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {string} name
|
||||
* @return {{view: string, class: string}}
|
||||
*/
|
||||
getItemDefs(name) {
|
||||
return this.getMetadata().get(['app', 'clientNavbar', 'itemDefs', name]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} name
|
||||
* @return {Promise}
|
||||
*/
|
||||
createItemView(name) {
|
||||
const defs = this.getItemDefs(name)
|
||||
|
||||
if (!defs || !defs.view) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
const key = name + 'Item';
|
||||
|
||||
return this.createView(key, defs.view, {selector: `[data-item="${name}"]`});
|
||||
}
|
||||
|
||||
filterTabItem(scope) {
|
||||
if (~['Home', '_delimiter_', '_delimiter-ext_'].indexOf(scope)) {
|
||||
return true;
|
||||
@@ -1200,19 +1223,6 @@ class NavbarSiteView extends View {
|
||||
return list;
|
||||
}
|
||||
|
||||
quickCreate(scope) {
|
||||
Espo.Ui.notify(' ... ');
|
||||
|
||||
const type = this.getMetadata().get(['clientDefs', scope, 'quickCreateModalType']) || 'edit';
|
||||
const viewName = this.getMetadata().get(['clientDefs', scope, 'modalViews', type]) || 'views/modals/edit';
|
||||
|
||||
this.createView('quickCreate', viewName , {scope: scope}, (view) => {
|
||||
view.once('after:render', () => Espo.Ui.notify(false));
|
||||
|
||||
view.render();
|
||||
});
|
||||
}
|
||||
|
||||
// noinspection JSUnusedGlobalSymbols
|
||||
actionLogout() {
|
||||
this.getRouter().logout();
|
||||
|
||||
@@ -0,0 +1,105 @@
|
||||
/************************************************************************
|
||||
* 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.
|
||||
************************************************************************/
|
||||
|
||||
import View from 'view';
|
||||
|
||||
class QuickCreateNavbarView extends View {
|
||||
|
||||
templateContent = `
|
||||
<a
|
||||
id="nav-quick-create-dropdown"
|
||||
class="dropdown-toggle"
|
||||
data-toggle="dropdown"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
title="{{translate 'Create'}}"
|
||||
><i class="fas fa-plus icon"></i></a>
|
||||
<ul class="dropdown-menu" role="menu" aria-labelledby="nav-quick-create-dropdown">
|
||||
<li class="dropdown-header">{{translate 'Create'}}</li>
|
||||
{{#each list}}
|
||||
<li><a
|
||||
href="#{{./this}}/create"
|
||||
data-name="{{./this}}"
|
||||
data-action="quickCreate"
|
||||
>{{translate this category='scopeNames'}}</a></li>
|
||||
{{/each}}
|
||||
</ul>
|
||||
`
|
||||
|
||||
data() {
|
||||
return {
|
||||
list: this.list,
|
||||
};
|
||||
}
|
||||
|
||||
setup() {
|
||||
this.addActionHandler('quickCreate', (e, element) => {
|
||||
e.preventDefault();
|
||||
|
||||
this.processCreate(element.dataset.name);
|
||||
});
|
||||
|
||||
const scopes = this.getMetadata().get('scopes') || {};
|
||||
|
||||
/** @type {string[]} */
|
||||
const list = this.getConfig().get('quickCreateList') || [];
|
||||
|
||||
this.list = list.filter(scope => {
|
||||
if (!scopes[scope]) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((scopes[scope] || {}).disabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ((scopes[scope] || {}).acl) {
|
||||
return this.getAcl().check(scope, 'create');
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
isAvailable() {
|
||||
return this.list.length > 0;
|
||||
}
|
||||
|
||||
processCreate(scope) {
|
||||
Espo.Ui.notify(' ... ');
|
||||
|
||||
const type = this.getMetadata().get(['clientDefs', scope, 'quickCreateModalType']) || 'edit';
|
||||
const viewName = this.getMetadata().get(['clientDefs', scope, 'modalViews', type]) || 'views/modals/edit';
|
||||
|
||||
this.createView('dialog', viewName , {scope: scope})
|
||||
.then(view => view.render())
|
||||
.then(() => Espo.Ui.notify(false));
|
||||
}
|
||||
}
|
||||
|
||||
export default QuickCreateNavbarView;
|
||||
@@ -0,0 +1,38 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"$id": "https://www.espocrm.com/schema/metadata/app/client.json",
|
||||
"title": "app/navbar",
|
||||
"description": "Navbar definitions.",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"itemList": {
|
||||
"type": "array",
|
||||
"description": "Navbar items.",
|
||||
"items": {
|
||||
"type": "string",
|
||||
"anyOf": [
|
||||
{"type": "string"},
|
||||
{"const": "__APPEND__"}
|
||||
]
|
||||
}
|
||||
},
|
||||
"itemDefs": {
|
||||
"description": "Navbar item definitions",
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"description": "An item.",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"view": {
|
||||
"type": "string",
|
||||
"description": "A view."
|
||||
},
|
||||
"class": {
|
||||
"type": "string",
|
||||
"description": "A CSS class."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user