navbar dividers

This commit is contained in:
Yuri Kuznetsov
2023-06-28 10:44:59 +03:00
parent 910ed80ae2
commit 4be63cb75e
18 changed files with 356 additions and 33 deletions
@@ -274,6 +274,7 @@
},
"labels": {
"Group Tab": "Group Tab",
"Divider": "Divider",
"System": "System",
"Locale": "Locale",
"Search": "Search",
+16 -3
View File
@@ -7,14 +7,21 @@
><a
class="navbar-brand nav-link"
href="#"
><img src="{{logoSrc}}" class="logo"></span></a></div>
><img src="{{logoSrc}}" class="logo" alt="logo"></span></a></div>
<a role="button" class="side-menu-button"><span class="fas fa-bars"></span></a>
</div>
<div class="navbar-collapse navbar-body">
<ul class="nav navbar-nav tabs">
{{#each tabDefsList1}}
<li data-name="{{name}}" class="not-in-more tab{{#if isGroup}} tab-group dropdown{{/if}}">
<li
data-name="{{name}}"
class="not-in-more tab{{#if isGroup}} tab-group dropdown{{/if}}{{#if isDivider}} tab-divider{{/if}}"
>
{{#if isDivider}}
<div class="{{aClassName}}"><span class="label-text">{{#if label}}{{label}}{{/if}}</span></div>
{{/if}}
{{#unless isDivider}}
<a
{{#if link}}href="{{link}}"{{else}}role="button"{{/if}}
class="{{aClassName}}"
@@ -43,6 +50,7 @@
<span class="fas fa-caret-right group-caret"><span>
{{/if}}
</a>
{{/unless}}
{{#if isGroup}}
<ul class="dropdown-menu" role="menu" aria-labelledby="nav-tab-group-{{name}}">
{{#each itemList}}
@@ -88,8 +96,12 @@
{{#each tabDefsList2}}
<li
data-name="{{name}}"
class="in-more tab{{#if className}} {{className}}{{/if}}{{#if isGroup}} dropdown tab-group{{/if}}"
class="in-more tab{{#if className}} {{className}}{{/if}}{{#if isGroup}} dropdown tab-group{{/if}}{{#if isDivider}} tab-divider{{/if}}"
>
{{#if isDivider}}
<div class="{{aClassName}}{{#unless label}} no-text{{/unless}}"><span class="label-text">{{#if label}}{{label}}{{/if}}</span></div>
{{/if}}
{{#unless isDivider}}
<a
{{#if link}}href="{{link}}"{{else}}role="button"{{/if}}
tabindex="0"
@@ -119,6 +131,7 @@
<span class="fas fa-caret-right group-caret"><span>
{{/if}}
</a>
{{/unless}}
{{#if isGroup}}
<ul class="dropdown-menu" role="menu" aria-labelledby="nav-tab-group-{{name}}">
{{#each itemList}}
+31 -5
View File
@@ -135,6 +135,30 @@ class TabListFieldView extends ArrayFieldView {
getGroupItemHtml(item) {
let label = item.text || '';
let $label = $('<span>').text(label);
let $icon = null;
if (item.type === 'group') {
$icon = $('<span>')
.addClass('far fa-list-alt')
.addClass('text-muted')
}
if (item.type === 'divider') {
$label.addClass('text-soft')
.addClass('text-italic');
}
let $item = $('<span>').append($label);
if ($icon) {
$item.prepend(
$icon,
' '
)
}
return $('<div>')
.addClass('list-group-item')
.attr('data-value', item.id)
@@ -149,7 +173,7 @@ class TabListFieldView extends ArrayFieldView {
.append(
$('<span>').addClass('fas fa-pencil-alt fa-sm')
),
$('<span>').text(label),
$item,
'&nbsp;',
$('<a>')
.addClass('pull-right')
@@ -215,12 +239,14 @@ class TabListFieldView extends ArrayFieldView {
let index = this.getGroupIndexById(id);
let tabList = Espo.Utils.cloneDeep(this.selected);
this.createView('dialog', 'views/settings/modals/edit-tab-group', {
itemData: item,
}, view => {
let view = item.type === 'divider' ?
'views/settings/modals/edit-tab-divider' :
'views/settings/modals/edit-tab-group';
this.createView('dialog', view, {itemData: item}, view => {
view.render();
this.listenToOnce(view, 'apply', (itemData) => {
this.listenToOnce(view, 'apply', itemData => {
for (let a in itemData) {
tabList[index][a] = itemData[a];
}
@@ -0,0 +1,101 @@
/************************************************************************
* 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 ModalView from 'views/modal';
import Model from 'model';
class EditTabDividerSettingsModalView extends ModalView {
className = 'dialog dialog-record'
templateContent = '<div class="record no-side-margin">{{{record}}}</div>'
setup() {
super.setup();
this.headerText = this.translate('Divider', 'labels', 'Settings');
this.buttonList.push({
name: 'apply',
label: 'Apply',
style: 'danger',
});
this.buttonList.push({
name: 'cancel',
label: 'Cancel',
});
let detailLayout = [
{
rows: [
[
{
name: 'text',
labelText: this.translate('label', 'fields', 'Admin'),
},
false,
],
]
}
];
let model = this.model = new Model({}, {entityType: 'Dummy'});
model.set(this.options.itemData);
model.setDefs({
fields: {
text: {
type: 'varchar',
},
},
});
this.createView('record', 'views/record/edit-for-modal', {
detailLayout: detailLayout,
model: model,
selector: '.record',
});
}
// noinspection JSUnusedGlobalSymbols
actionApply() {
let recordView = /** @type {module:views/record/edit}*/ this.getView('record');
if (recordView.validate()) {
return;
}
let data = recordView.fetch();
this.trigger('apply', data);
}
}
// noinspection JSUnusedGlobalSymbols
export default EditTabDividerSettingsModalView;
@@ -38,6 +38,11 @@ class TabListFieldAddSettingsModalView extends ArrayFieldAddModalView {
name: 'addGroup',
text: this.translate('Group Tab', 'labels', 'Settings'),
});
this.buttonList.push({
name: 'addDivider',
text: this.translate('Divider', 'labels', 'Settings'),
});
}
}
@@ -49,6 +54,13 @@ class TabListFieldAddSettingsModalView extends ArrayFieldAddModalView {
color: null,
});
}
actionAddDivider() {
this.trigger('add', {
type: 'divider',
text: null,
});
}
}
// noinspection JSUnusedGlobalSymbols
+60 -4
View File
@@ -938,6 +938,14 @@ class NavbarSiteView extends View {
}
if (typeof item === 'object') {
if (item.type === 'divider') {
if (!this.isSide()) {
return false;
}
return true;
}
item.itemList = item.itemList || [];
item.itemList = item.itemList.filter(item => {
@@ -950,6 +958,42 @@ class NavbarSiteView extends View {
return this.filterTabItem(item);
});
function isMoreDelimiter(item) {
return item === '_delimiter_' || item === '_delimiter-ext_';
}
function isDivider(item) {
return item === 'object' && item.type === 'divider';
}
//let moreIsMet = false;
this.tabList = this.tabList.filter((item, i) => {
let nextItem = this.tabList[i + 1];
/*if (isMoreDelimiter(item)) {
moreIsMet = true;
}*/
if (!isDivider(item)) {
return true;
}
if (!nextItem) {
return true;
}
if (isDivider(nextItem)) {
return false;
}
/*if (isMoreDelimiter(nextItem) && !moreIsMet) {
return false;
}*/
return true;
});
let tabDefsList = [];
let colorsDisabled =
@@ -971,7 +1015,7 @@ class NavbarSiteView extends View {
};
this.tabList.forEach((tab, i) => {
if (tab === '_delimiter_' || tab === '_delimiter-ext_') {
if (isMoreDelimiter(tab)) {
if (!vars.moreIsMet) {
vars.moreIsMet = true;
@@ -1009,6 +1053,7 @@ class NavbarSiteView extends View {
let iconClass = null;
let color = null;
let isGroup = false;
let isDivider = false;
let name = tab;
let aClassName = 'nav-link';
@@ -1016,10 +1061,20 @@ class NavbarSiteView extends View {
label = this.getLanguage().translate(tab);
link = '#';
}
else if (typeof tab === 'object' && tab.type === 'divider') {
isDivider = true;
label = tab.text;
aClassName = 'nav-divider-text';
name = 'divider-' + i;
if (label && label.indexOf('label@') === 0) {
label = this.translate(label.substr(6), 'tabs');
}
}
else if (typeof tab === 'object') {
isGroup = true;
label = tab.text;
label = tab.text || '';
color = tab.color;
iconClass = tab.iconClass;
@@ -1042,11 +1097,11 @@ class NavbarSiteView extends View {
let shortLabel = label.substring(0, 2);
if (!params.colorsDisabled && !isGroup) {
if (!params.colorsDisabled && !isGroup && !isDivider) {
color = this.getMetadata().get(['clientDefs', tab, 'color']);
}
if (!params.tabIconsDisabled && !isGroup) {
if (!params.tabIconsDisabled && !isGroup && !isDivider) {
iconClass = this.getMetadata().get(['clientDefs', tab, 'iconClass'])
}
@@ -1061,6 +1116,7 @@ class NavbarSiteView extends View {
isAfterShowMore: vars.isHidden,
aClassName: aClassName,
isGroup: isGroup,
isDivider: isDivider,
};
if (isGroup) {
+1 -1
View File
@@ -44,7 +44,7 @@
@panel-danger-bg-value: @state-danger-bg-value;
@panel-warning-bg-value: @state-warning-bg-value;
@navbar-inverse-color-value: #d3d3d3;
@navbar-inverse-color-value: @gray-light-value;
@navbar-inverse-bg-value: #141414;
@navbar-inverse-link-color-value: @text-color-value;
@navbar-inverse-link-hover-color-value: #fff;
@@ -116,6 +116,10 @@ ul.dropdown-menu {
> li.checkbox:last-child {
margin-bottom: 3px;
}
> .dropdown-header {
user-select: none;
}
}
ul.dropdown-menu-with-icons {
+22 -8
View File
@@ -114,8 +114,8 @@
border-width: 0;
.navbar-nav > li > a {
padding-top: 9px;
padding-bottom: 9px;
padding-top: @navbar-tab-vertical-padding;
padding-bottom: @navbar-tab-vertical-padding;
height: @navbar-height-xsmall;
}
@@ -158,16 +158,16 @@
ul.tabs {
li > a {
padding-top: 9px;
padding-bottom: 9px;
padding-top: @navbar-tab-vertical-padding;
padding-bottom: @navbar-tab-vertical-padding;
}
> li.more {
&.open {
> ul {
li > a {
padding-top: 9px;
padding-bottom: 9px;
padding-top: @navbar-tab-vertical-padding;
padding-bottom: @navbar-tab-vertical-padding;
padding-left: 15px;
padding-right: 15px;
}
@@ -241,8 +241,8 @@
}
.navbar-toggle {
padding-top: 9px;
padding-bottom: 9px;
padding-top: @navbar-tab-vertical-padding;
padding-bottom: @navbar-tab-vertical-padding;
border: 0;
}
}
@@ -265,5 +265,19 @@
right: 0;
}
}
ul.tabs {
> li.tab-divider {
display: none;
}
> li.more {
ul {
> li.tab-divider {
display: none;
}
}
}
}
}
}
+4
View File
@@ -97,6 +97,10 @@ b, strong {
font-size: @font-size-smaller;
}
.text-italic {
font-style: italic;
}
.text-bold {
font-weight: 600;
}
+95 -6
View File
@@ -92,6 +92,63 @@ body[data-navbar="side"] {
> li.tab-group .group-caret {
right: 13px;
}
> li.tab-divider {
> div {
padding-top: calc(@navbar-tab-vertical-padding + 4px);
padding-bottom: @navbar-tab-vertical-padding;
padding-left: @navbar-tab-left-padding;
padding-right: @navbar-tab-right-padding;
display: block;
> .label-text {
color: var(--navbar-inverse-color);
&:empty {
&:before {
content: "\200b";
}
}
}
}
}
> li.more {
> ul {
> li.tab-divider {
&:not(:first-child):before {
height: 1px;
margin: 9.5px 0;
overflow: hidden;
background-color: var(--dropdown-divider-bg);
display: block;
content: ' ';
}
&:first-child {
> div {
padding-top: @navbar-tab-vertical-padding;
}
}
> div {
&.no-text {
display: none;
}
padding-top: calc(@navbar-tab-vertical-padding - 3px);
padding-bottom: @navbar-tab-vertical-padding;
padding-left: @navbar-tab-left-padding;
padding-right: @navbar-tab-right-padding;
> .label-text {
color: var(--gray-light);
white-space: nowrap;
}
}
}
}
}
}
a.minimizer {
@@ -112,8 +169,8 @@ body[data-navbar="side"] {
a.side-menu-button {
width: @navbar-minimized-width;
padding-top: 9px;
padding-bottom: 9px;
padding-top: @navbar-tab-vertical-padding;
padding-bottom: @navbar-tab-vertical-padding;
text-align: center;
display: none;
@@ -255,8 +312,8 @@ body[data-navbar="side"] {
}
li > a {
padding-top: 9px;
padding-bottom: 9px;
padding-top: @navbar-tab-vertical-padding;
padding-bottom: @navbar-tab-vertical-padding;
padding-left: @navbar-tab-left-padding;
padding-right: @navbar-tab-right-padding;
height: @navbar-logo-height;
@@ -269,8 +326,8 @@ body[data-navbar="side"] {
}
.navbar-form {
margin-top: 0px;
margin-bottom: 0px;
margin-top: 0;
margin-bottom: 0;
}
}
}
@@ -532,6 +589,38 @@ body[data-navbar="side"] {
}
}
&.minimized:not(.side-menu-opened) {
#navbar {
ul.tabs {
> li.tab-divider {
> div {
> .label-text {
display: none;
}
&:before {
content: "\200b";
}
}
}
}
}
}
&:not(.minimized) {
#navbar {
ul.tabs.navbar-nav {
> li {
> a {
.short-label {
//color: var(--navbar-inverse-color);
}
}
}
}
}
}
&.has-navbar > .content {
padding-left: @navbar-width + @container-padding;
max-width: @container-max-width + @navbar-width;
+2 -2
View File
@@ -145,8 +145,8 @@ body:not([data-navbar="side"]) {
> ul > li > ul > li > a,
> ul > li > a {
padding-top: 9px;
padding-bottom: 9px;
padding-top: @navbar-tab-vertical-padding;
padding-bottom: @navbar-tab-vertical-padding;
height: 38px;
> span.full-label {
+1 -1
View File
@@ -45,7 +45,7 @@
@navbar-link-hover-bg-value: @body-bg-value;
@navbar-box-shadow-value: none;
@navbar-inverse-color-value: @gray-light-value;
@navbar-inverse-color-value: #bbbbbb;
@navbar-inverse-bg-value: #4A6492;
@navbar-inverse-border-value: transparent;
@navbar-inverse-link-color-value: #DFDFDF;
+1
View File
@@ -8,6 +8,7 @@
@navbar-tab-text-left-padding: 36px;
@navbar-tab-left-padding: 15px;
@navbar-tab-right-padding: 20px;
@navbar-tab-vertical-padding: 9px;
@navbar-tabs-margin-top: 0;
@navbar-dropdown-min-width: 180px;
+1 -1
View File
@@ -44,7 +44,7 @@
@panel-danger-bg-value: @state-danger-bg-value;
@panel-warning-bg-value: @state-warning-bg-value;
@navbar-inverse-color-value: #d3d3d3;
@navbar-inverse-color-value: @gray-light-value;
@navbar-inverse-bg-value: #14141482;
@navbar-inverse-link-color-value: @text-color-value;
@navbar-inverse-link-hover-color-value: #fff;
+2
View File
@@ -1,7 +1,9 @@
@body-bg-value: #e5e9eb;
@white-color-value: #FFF;
@panel-bg-value: @white-color-value;
@navbar-inverse-bg-value: #546E7A;
@navbar-inverse-color-value: #a9b9c1;
@state-info-bg-value: #dbd0f5;
@state-info-text-value: #8e7cab;
+1 -1
View File
@@ -18,7 +18,7 @@
@brand-success-value: #76c57c;
@brand-warning-value: #e4a133;
@navbar-inverse-color-value: #FFF;
@navbar-inverse-color-value: #d7d1d4;
@navbar-inverse-bg-value: #9f6083;
@navbar-inverse-link-color-value: #F7F7F7;
+1 -1
View File
@@ -17,7 +17,7 @@
@brand-danger-value: #D06473;
@brand-warning-value: #e4a133;
@navbar-inverse-color-value: #FFF;
@navbar-inverse-color-value: #c6bcc9;
@navbar-inverse-bg-value: #8E5C9C;
@navbar-inverse-link-color-value: #F7F7F7;