mirror of
https://github.com/SuiteCRM/SuiteCRM-Core.git
synced 2025-08-29 21:00:39 +08:00
Update subpanels UI
This commit is contained in:
parent
2058da049d
commit
0d1b835989
5 changed files with 380 additions and 155 deletions
|
@ -46,7 +46,7 @@ export interface SubPanelMeta {
|
|||
}
|
||||
|
||||
export interface SubPanelDefinition {
|
||||
insightWidget?: WidgetOptionMap;
|
||||
subpanelWidget?: WidgetOptionMap;
|
||||
order?: 10;
|
||||
sort_order?: string;
|
||||
sort_by?: string;
|
||||
|
|
|
@ -25,45 +25,73 @@
|
|||
* the words "Supercharged by SuiteCRM".
|
||||
*/
|
||||
-->
|
||||
<ng-container *ngIf="(vm$ | async) as vm">
|
||||
<div class="card border shadow-sm">
|
||||
<div ngbAccordion class="sub-panel-banner" #accordion="ngbAccordion" activeIds="sub-panel-buttons">
|
||||
<div ngbAccordionItem id="sub-panel-buttons" class="card" [collapsed]="isCollapsed()">
|
||||
<div ngbAccordionHeader class="card-header">
|
||||
<a (click)="toggleSubPanels()" class="clickable">
|
||||
<div class="d-flex align-items-center justify-content-between">
|
||||
<scrm-label labelKey="LBL_SELECT_SUBPANEL_BANNER"></scrm-label>
|
||||
<ng-container *ngIf="isCollapsed()">
|
||||
<scrm-image
|
||||
[attr.aria-expanded]="false"
|
||||
[image]="toggleIcon()"
|
||||
aria-controls="collapseShowSubPanels"
|
||||
class="float-right">
|
||||
</scrm-image>
|
||||
</ng-container>
|
||||
<ng-container *ngIf="!isCollapsed()">
|
||||
<scrm-image
|
||||
[attr.aria-expanded]="true"
|
||||
[image]="toggleIcon()"
|
||||
aria-controls="collapseShowSubPanels"
|
||||
class="float-right">
|
||||
</scrm-image>
|
||||
</ng-container>
|
||||
<div class="d-flex justify-content-between">
|
||||
<div class="d-flex align-items-start sub-panel-banner-header">
|
||||
<a (click)="toggleSubPanels()" class="clickable">
|
||||
<scrm-label labelKey="LBL_RELATIONSHIPS"></scrm-label>
|
||||
</a>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<div class="d-flex align-items-center justify-content-end">
|
||||
|
||||
<div class="row insight-panel" *ngIf="isCollapsed()">
|
||||
<div class="col-auto mr-3 insight-panel-card border-insight"
|
||||
*ngFor="let subpanelKey of headerSubpanels()"
|
||||
[ngClass]="{'sub-panel-banner-button-active': subpanels[subpanelKey].show === true}"
|
||||
(click)="showSubpanel(subpanels[subpanelKey].metadata.name, subpanels[subpanelKey])">
|
||||
<scrm-grid-widget
|
||||
[config]="getGridConfig(subpanels[subpanelKey])"></scrm-grid-widget>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="d-flex align-items-center sub-panel-header-toggle">
|
||||
<a (click)="toggleSubPanels()" class="clickable position-relative">
|
||||
<ng-container *ngIf="isCollapsed()">
|
||||
<scrm-image
|
||||
[attr.aria-expanded]="false"
|
||||
[image]="'chevron-down'"
|
||||
aria-controls="collapseShowSubPanels"
|
||||
class="float-right">
|
||||
</scrm-image>
|
||||
<ng-container *ngIf="activeHiddenButtonsCount() > 0">
|
||||
<span class="hidden-subpanel-buttons-count badge position-absolute">{{ activeHiddenButtonsCount() }}</span>
|
||||
</ng-container>
|
||||
</ng-container>
|
||||
<ng-container *ngIf="!isCollapsed()">
|
||||
<scrm-image
|
||||
[attr.aria-expanded]="true"
|
||||
[image]="'chevron-up'"
|
||||
aria-controls="collapseShowSubPanels"
|
||||
class="float-right">
|
||||
</scrm-image>
|
||||
</ng-container>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div ngbAccordionCollapse>
|
||||
<div ngbAccordionBody>
|
||||
<ng-template>
|
||||
<div id="collapseShowSubPanels">
|
||||
<div class="row insight-panel">
|
||||
<div class="col-xs-6 col-sm-3 col-md-2 insight-panel-card border-insight"
|
||||
*ngFor="let item of vm.subpanels | keyvalue"
|
||||
[ngClass]="{'sub-panel-banner-button-active': item.value.show === true}"
|
||||
(click)="showSubpanel(item.key, item.value)">
|
||||
<scrm-grid-widget [config]="getGridConfig(item.value)"></scrm-grid-widget>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div id="collapseShowSubPanels" class="sub-panel-banner-body d-flex align-items-center justify-content-center border-bottom border-top pt-2 pb-3 ml-2 mr-2">
|
||||
<table class="sub-panel-banner-body-table">
|
||||
<tr class="insight-panel sub-panel-banner-body-table-row" *ngFor="let subpanelRow of bodySubpanels()">
|
||||
<td *ngFor="let subpanelKey of subpanelRow" class="sub-panel-banner-body-table-col">
|
||||
<div class="insight-panel-card border-insight pl-2 pr-2"
|
||||
[ngClass]="{'sub-panel-banner-button-active': subpanels[subpanelKey].show === true}"
|
||||
(click)="showSubpanel(subpanels[subpanelKey].metadata.name, subpanels[subpanelKey])">
|
||||
<scrm-grid-widget
|
||||
[config]="getGridConfig(subpanels[subpanelKey])"></scrm-grid-widget>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</ng-template>
|
||||
</div>
|
||||
|
@ -72,19 +100,19 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div id="sub-panels">
|
||||
<ng-container *ngFor="let subpanelKey of this.openSubpanels">
|
||||
<ng-container *ngIf="(vm.subpanels[subpanelKey]) as item">
|
||||
<div class="sub-panels">
|
||||
<ng-container *ngFor="let subpanelKey of this.openSubpanels()">
|
||||
<ng-container *ngIf="(subpanels[subpanelKey]) as item">
|
||||
<scrm-subpanel *ngIf="item.show"
|
||||
[maxColumns$]="maxColumns$"
|
||||
[store]="item"
|
||||
[filterConfig]="filterConfig"
|
||||
[onClose]="getCloseCallBack(subpanelKey, item)"
|
||||
class="sub-panel">
|
||||
class="sub-panel minimal-table">
|
||||
</scrm-subpanel>
|
||||
</ng-container>
|
||||
</ng-container>
|
||||
|
||||
</div>
|
||||
|
||||
</ng-container>
|
||||
</div>
|
||||
|
|
|
@ -24,11 +24,11 @@
|
|||
* the words "Supercharged by SuiteCRM".
|
||||
*/
|
||||
|
||||
import {Component, Input, OnInit, signal} from '@angular/core';
|
||||
import {map, take, tap} from 'rxjs/operators';
|
||||
import {Observable} from 'rxjs';
|
||||
import {Component, computed, Input, OnDestroy, OnInit, Signal, signal, WritableSignal} from '@angular/core';
|
||||
import {take} from 'rxjs/operators';
|
||||
import {Observable, Subscription} from 'rxjs';
|
||||
import {SubpanelContainerConfig} from './subpanel-container.model';
|
||||
import {LanguageStore, LanguageStrings} from '../../../../store/language/language.store';
|
||||
import {LanguageStore} from '../../../../store/language/language.store';
|
||||
import {SubpanelStore, SubpanelStoreMap} from '../../store/subpanel/subpanel.store';
|
||||
import {MaxColumnsCalculator} from '../../../../services/ui/max-columns-calculator/max-columns-calculator.service';
|
||||
import {ViewContext} from '../../../../common/views/view.model';
|
||||
|
@ -38,13 +38,18 @@ import {GridWidgetConfig, StatisticsQueryArgs} from '../../../../components/grid
|
|||
import {LocalStorageService} from "../../../../services/local-storage/local-storage.service";
|
||||
import {FilterConfig} from "../../../list-filter/components/list-filter/list-filter.model";
|
||||
import {UserPreferenceStore} from '../../../../store/user-preference/user-preference.store';
|
||||
import {SystemConfigStore} from "../../../../store/system-config/system-config.store";
|
||||
import {
|
||||
ScreenSize,
|
||||
ScreenSizeObserverService
|
||||
} from "../../../../services/ui/screen-size-observer/screen-size-observer.service";
|
||||
|
||||
@Component({
|
||||
selector: 'scrm-subpanel-container',
|
||||
templateUrl: 'subpanel-container.component.html',
|
||||
providers: [MaxColumnsCalculator]
|
||||
})
|
||||
export class SubpanelContainerComponent implements OnInit {
|
||||
export class SubpanelContainerComponent implements OnInit, OnDestroy {
|
||||
|
||||
@Input() config: SubpanelContainerConfig;
|
||||
|
||||
|
@ -52,18 +57,32 @@ export class SubpanelContainerComponent implements OnInit {
|
|||
toggleIcon = signal('arrow_down_filled');
|
||||
maxColumns$: Observable<number>;
|
||||
|
||||
languages$: Observable<LanguageStrings> = this.languageStore.vm$;
|
||||
|
||||
vm$: Observable<{ subpanels: SubpanelStoreMap }>;
|
||||
openSubpanels: string[] = [];
|
||||
subpanels: SubpanelStoreMap;
|
||||
orderedSubpanels: WritableSignal<string[]> = signal([]);
|
||||
headerSubpanels: Signal<string[]> = signal([]);
|
||||
bodySubpanels: Signal<string[]> = signal([]);
|
||||
openSubpanels: WritableSignal<string[]> = signal([]);
|
||||
activeHiddenButtonsCount: Signal<number> = signal(0);
|
||||
|
||||
filterConfig: FilterConfig;
|
||||
subs: Subscription[] = [];
|
||||
protected subpanelButtonLimits: any = {
|
||||
XSmall: 2,
|
||||
Small: 3,
|
||||
Medium: 3,
|
||||
Large: 5,
|
||||
XLarge: 5
|
||||
};
|
||||
protected subpanelButtonBreakpoint: WritableSignal<number> = signal(3);
|
||||
|
||||
|
||||
constructor(
|
||||
protected languageStore: LanguageStore,
|
||||
protected maxColumnCalculator: MaxColumnsCalculator,
|
||||
protected localStorage: LocalStorageService,
|
||||
protected preferences: UserPreferenceStore
|
||||
protected preferences: UserPreferenceStore,
|
||||
protected systemConfigs: SystemConfigStore,
|
||||
protected screenSize: ScreenSizeObserverService,
|
||||
) {
|
||||
}
|
||||
|
||||
|
@ -71,38 +90,99 @@ export class SubpanelContainerComponent implements OnInit {
|
|||
const module = this?.config?.parentModule ?? 'default';
|
||||
this.setCollapsed(isTrue(this.preferences.getUi(module, 'subpanel-container-collapse') ?? false));
|
||||
|
||||
this.openSubpanels = this.preferences.getUi(module, 'subpanel-container-open-subpanels') ?? [];
|
||||
const subpanelButtonLimits = this.systemConfigs.getConfigValue('recordview_subpanel_button_limits') ?? {};
|
||||
if (subpanelButtonLimits && Object.keys(subpanelButtonLimits).length) {
|
||||
this.subpanelButtonLimits = subpanelButtonLimits;
|
||||
}
|
||||
|
||||
this.vm$ = this.config.subpanels$.pipe(
|
||||
map((subpanelsMap) => ({
|
||||
subpanels: subpanelsMap
|
||||
})),
|
||||
tap((subpanelsMap) => {
|
||||
if (!subpanelsMap || !Object.keys(subpanelsMap).length) {
|
||||
return;
|
||||
}
|
||||
this.openSubpanels.set(this.preferences.getUi(module, 'subpanel-container-open-subpanels') ?? []);
|
||||
|
||||
if (!this.openSubpanels || this.openSubpanels.length < 1) {
|
||||
return;
|
||||
}
|
||||
this.subs.push(this.config.subpanels$.subscribe({
|
||||
next: (subpanelsMap) => {
|
||||
this.subpanels = {...subpanelsMap};
|
||||
|
||||
this.openSubpanels.forEach(subpanelKey => {
|
||||
const subpanel = subpanelsMap.subpanels[subpanelKey];
|
||||
const orderedSubpanels = Object.values(this.subpanels)
|
||||
.filter(item => item?.metadata?.order !== undefined)
|
||||
.sort((a, b) => (a.metadata.order ?? 0) - (b.metadata.order ?? 0))
|
||||
.map(item => item.metadata.name);
|
||||
|
||||
if (!subpanel || subpanel.show) {
|
||||
if (orderedSubpanels) {
|
||||
this.orderedSubpanels.set(orderedSubpanels);
|
||||
}
|
||||
|
||||
if (!this.subpanels || !Object.keys(this.subpanels).length) {
|
||||
return;
|
||||
}
|
||||
|
||||
subpanel.show = true;
|
||||
subpanel.load().pipe(take(1)).subscribe();
|
||||
if (!this.openSubpanels() || this.openSubpanels().length < 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
});
|
||||
this.openSubpanels().forEach(subpanelKey => {
|
||||
const subpanel = this.subpanels[subpanelKey];
|
||||
|
||||
}));
|
||||
if (!subpanel || subpanel.show) {
|
||||
return;
|
||||
}
|
||||
|
||||
subpanel.show = true;
|
||||
subpanel.load().pipe(take(1)).subscribe();
|
||||
});
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
this.headerSubpanels = computed(() => this.orderedSubpanels().slice(0, this.subpanelButtonBreakpoint()));
|
||||
this.bodySubpanels = computed(() => {
|
||||
const sliced = [...this.orderedSubpanels()];
|
||||
|
||||
let count = 0;
|
||||
const groups = [];
|
||||
sliced.forEach(value => {
|
||||
if (count === 0) {
|
||||
groups.push([]);
|
||||
}
|
||||
|
||||
groups[groups.length - 1].push(value);
|
||||
|
||||
count++;
|
||||
if (count >= this.subpanelButtonBreakpoint()) {
|
||||
count = 0;
|
||||
}
|
||||
});
|
||||
|
||||
return groups;
|
||||
});
|
||||
|
||||
this.activeHiddenButtonsCount = computed(() => {
|
||||
const openSubpanelsSet = new Set(this.openSubpanels());
|
||||
const headerSubpanelsSet = new Set(this.headerSubpanels());
|
||||
|
||||
return this.bodySubpanels().flat().reduce(
|
||||
(count, subpanelKey) => {
|
||||
const isOpen = openSubpanelsSet.has(subpanelKey);
|
||||
const inHeader = headerSubpanelsSet.has(subpanelKey);
|
||||
return count + ((isOpen && !inHeader) ? 1 : 0);
|
||||
},
|
||||
0
|
||||
);
|
||||
});
|
||||
|
||||
this.subs.push(this.screenSize.screenSize$.subscribe({
|
||||
next: (screenSize: ScreenSize) => {
|
||||
if (screenSize && this.subpanelButtonLimits[screenSize]) {
|
||||
this.subpanelButtonBreakpoint.set(this.subpanelButtonLimits[screenSize]);
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
this.maxColumns$ = this.getMaxColumns();
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.subs.forEach(sub => sub.unsubscribe());
|
||||
}
|
||||
|
||||
getMaxColumns(): Observable<number> {
|
||||
return this.maxColumnCalculator.getMaxColumns(this.config.sidebarActive$);
|
||||
}
|
||||
|
@ -117,17 +197,21 @@ export class SubpanelContainerComponent implements OnInit {
|
|||
showSubpanel(key: string, item: SubpanelStore): void {
|
||||
item.show = !item.show;
|
||||
|
||||
let openSubpanels = [...this.openSubpanels()];
|
||||
|
||||
if (item.show) {
|
||||
if (!this.openSubpanels.includes(key)) {
|
||||
this.openSubpanels.push(key);
|
||||
if (!openSubpanels.includes(key)) {
|
||||
openSubpanels.push(key);
|
||||
}
|
||||
item.load().pipe(take(1)).subscribe();
|
||||
} else {
|
||||
this.openSubpanels = this.openSubpanels.filter(subpanelKey => subpanelKey != key);
|
||||
openSubpanels = openSubpanels.filter(subpanelKey => subpanelKey != key);
|
||||
}
|
||||
|
||||
this.openSubpanels.set(openSubpanels);
|
||||
|
||||
const module = this?.config?.parentModule ?? 'default';
|
||||
this.preferences.setUi(module, 'subpanel-container-open-subpanels', this.openSubpanels);
|
||||
this.preferences.setUi(module, 'subpanel-container-open-subpanels', this.openSubpanels());
|
||||
}
|
||||
|
||||
getCloseCallBack(key: string, item: SubpanelStore): Function {
|
||||
|
@ -136,7 +220,7 @@ export class SubpanelContainerComponent implements OnInit {
|
|||
|
||||
getGridConfig(vm: SubpanelStore): GridWidgetConfig {
|
||||
|
||||
if (!vm.metadata || !vm.metadata.insightWidget) {
|
||||
if (!vm.metadata || !vm.metadata.subpanelWidget) {
|
||||
return {
|
||||
layout: null,
|
||||
} as GridWidgetConfig;
|
||||
|
|
|
@ -319,7 +319,7 @@ export class SubpanelStore implements StateStore {
|
|||
*/
|
||||
public shouldBatchStatistic(): boolean {
|
||||
const metadata: SubPanelDefinition = this.metadata || {} as SubPanelDefinition;
|
||||
return !(metadata.insightWidget && metadata.insightWidget.batch && metadata.insightWidget.batch === false);
|
||||
return !(metadata.subpanelWidget && metadata.subpanelWidget.batch && metadata.subpanelWidget.batch === false);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -411,11 +411,11 @@ export class SubpanelStore implements StateStore {
|
|||
public getWidgetLayout(): StatisticWidgetOptions {
|
||||
|
||||
const meta = this.metadata;
|
||||
if (!meta || !meta.insightWidget || !meta.insightWidget.options || !meta.insightWidget.options.insightWidget) {
|
||||
if (!meta || !meta.subpanelWidget || !meta.subpanelWidget.options || !meta.subpanelWidget.options.subpanelWidget) {
|
||||
return {rows: []} as StatisticWidgetOptions;
|
||||
}
|
||||
|
||||
const layout = deepClone(meta.insightWidget.options.insightWidget);
|
||||
const layout = deepClone(meta.subpanelWidget.options.subpanelWidget);
|
||||
|
||||
if (!layout.rows || !layout.rows.length) {
|
||||
layout.rows = {};
|
||||
|
|
|
@ -36,15 +36,6 @@
|
|||
background-color: $midnight-blue-transparent;
|
||||
}
|
||||
|
||||
.sub-panel-banner-button-active {
|
||||
background-color: $midnight-blue-transparent;
|
||||
}
|
||||
|
||||
.widget-entry-icon svg {
|
||||
fill: $salmon-pink;
|
||||
stroke: $salmon-pink;
|
||||
font-size: 1.6em;
|
||||
}
|
||||
|
||||
.sub-panel .subpanel-icon svg {
|
||||
font-size: x-large;
|
||||
|
@ -66,6 +57,7 @@
|
|||
background-color: $midnight-blue;
|
||||
color: $white;
|
||||
border-color: $midnight-blue;
|
||||
font-weight: bold;
|
||||
|
||||
scrm-image {
|
||||
display: inline;
|
||||
|
@ -86,7 +78,7 @@
|
|||
display: inline;
|
||||
|
||||
svg {
|
||||
fill: $midnight-blue;
|
||||
fill: $midnight-blue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -99,100 +91,213 @@ div.widget-panel .panel-card .card-header {
|
|||
padding: 0.5rem 0.6rem;
|
||||
}
|
||||
|
||||
.insight-panel {
|
||||
margin-left: 0;
|
||||
margin-right: 0;
|
||||
padding: 1em;
|
||||
.sub-panel-banner {
|
||||
.insight-panel {
|
||||
margin-left: 0;
|
||||
margin-right: 0;
|
||||
|
||||
.border-insight {
|
||||
margin: 4px;
|
||||
border: 0.15em solid $very-light-grey;
|
||||
border-radius: 4px;
|
||||
border-top: 3px solid $midnight-blue;
|
||||
.insight-panel-card {
|
||||
cursor: pointer;
|
||||
padding: 0;
|
||||
border: none;
|
||||
border-bottom: 1px solid $shell-grey;
|
||||
border-radius: 0;
|
||||
margin: 0;
|
||||
margin-right: 0.5em;
|
||||
color: $shell-grey;
|
||||
|
||||
svg {
|
||||
font-size: 1.5em;
|
||||
fill: $midnight-blue;
|
||||
stroke: $midnight-blue;
|
||||
}
|
||||
}
|
||||
.grid-widget {
|
||||
min-height: 2.1em;
|
||||
padding-left: 0.5em;
|
||||
padding-right: 0.5em;
|
||||
height: 100%;
|
||||
justify-content: flex-end;
|
||||
flex-direction: row !important;
|
||||
align-items: start;
|
||||
|
||||
.insight-panel-card {
|
||||
padding-left: 0.5rem;
|
||||
padding-right: 0.5rem;
|
||||
cursor: pointer;
|
||||
}
|
||||
height: 100%;
|
||||
justify-content: flex-end;
|
||||
|
||||
.insight-panel-card:hover {
|
||||
box-shadow: 0 0.25rem 0.5rem rgb(0 0 0 / 15%);
|
||||
}
|
||||
.widget-entry-icon {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
margin-right: 0.4em;
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.col-md-2 {
|
||||
flex: 0 0 15.666667%;
|
||||
max-width: 15.666667%;
|
||||
}
|
||||
}
|
||||
svg {
|
||||
font-size: 1.5em;
|
||||
fill: $shell-grey;
|
||||
stroke: $shell-grey;
|
||||
}
|
||||
}
|
||||
|
||||
.widget-entry-icon {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
margin-top: 0.7em;
|
||||
}
|
||||
.sub-panel-banner-value {
|
||||
margin-left: 0.4em;
|
||||
|
||||
.sub-panel-banner-value {
|
||||
font-size: 1rem;
|
||||
font-weight: bold;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-top: -0.5em;
|
||||
color: $burnt-red;
|
||||
}
|
||||
.widget-entry-value {
|
||||
color: $shell-grey;
|
||||
font-size: .67rem;
|
||||
}
|
||||
}
|
||||
|
||||
.sub-panel-banner-tooltip {
|
||||
width: 100%;
|
||||
.sub-panel-banner-button-title {
|
||||
width: 100%;
|
||||
|
||||
.widget-entry-label {
|
||||
border-bottom: 2px solid $very-light-grey;
|
||||
font-size: 0.7rem;
|
||||
line-height: 1rem;
|
||||
.widget-entry-label {
|
||||
text-transform: uppercase;
|
||||
font-size: .62rem;
|
||||
width: 100%;
|
||||
padding: .5em 0;
|
||||
color: $shell-grey;
|
||||
}
|
||||
}
|
||||
|
||||
label {
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
&:hover,
|
||||
&.sub-panel-banner-button-active {
|
||||
border-bottom: 1px solid $bright-purple;
|
||||
|
||||
.grid-widget {
|
||||
background-color: inherit;
|
||||
|
||||
.widget-entry-icon {
|
||||
svg {
|
||||
fill: $bright-purple;
|
||||
stroke: $bright-purple;
|
||||
}
|
||||
}
|
||||
|
||||
.sub-panel-banner-button-title {
|
||||
.widget-entry-label {
|
||||
color: $bright-purple;
|
||||
font-weight: 900;
|
||||
}
|
||||
}
|
||||
|
||||
.sub-panel-banner-value {
|
||||
.widget-entry-value {
|
||||
color: $bright-purple;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.sub-panel-banner-button-title {
|
||||
width: 100%;
|
||||
|
||||
.widget-entry-label {
|
||||
text-transform: uppercase;
|
||||
font-size: 0.62rem;
|
||||
width: 100%;
|
||||
padding: 0.5em 0;
|
||||
color: $midnight-blue;
|
||||
@media (min-width: 768px) {
|
||||
.col-md-2 {
|
||||
flex: 0 0 15.666667%;
|
||||
max-width: 15.666667%;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.sub-panel-banner-tooltip {
|
||||
width: 100%;
|
||||
|
||||
.widget-entry-label {
|
||||
border-bottom: 2px solid $very-light-grey;
|
||||
font-size: 0.7rem;
|
||||
line-height: 1rem;
|
||||
|
||||
label {
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
.grid-widget {
|
||||
height: 100%;
|
||||
justify-content: flex-end;
|
||||
.sub-panel-banner-body {
|
||||
|
||||
|
||||
.sub-panel-banner-body-table {
|
||||
width: 95%;
|
||||
table-layout: fixed;
|
||||
|
||||
.sub-panel-banner-body-table-row:first-child {
|
||||
.sub-panel-banner-body-table-col {
|
||||
padding-bottom: 0.5em;
|
||||
}
|
||||
}
|
||||
|
||||
.sub-panel-banner-body-table-row {
|
||||
height: 100%;
|
||||
.sub-panel-banner-body-table-col {
|
||||
height: 100%;
|
||||
|
||||
.insight-panel-card {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.grid-widget {
|
||||
justify-content: flex-end;
|
||||
flex-direction: row !important;
|
||||
align-items: start;
|
||||
|
||||
.statistics-sidebar-widget-row {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
min-height: 2.7em;
|
||||
}
|
||||
|
||||
.sub-panel-banner-button-title {
|
||||
.widget-entry-label {
|
||||
text-wrap: auto;
|
||||
word-break: normal;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.accordion {
|
||||
|
||||
.sub-panels {
|
||||
padding: 0 1.25rem 1.25rem;
|
||||
}
|
||||
|
||||
.sub-panel-banner.accordion {
|
||||
.card {
|
||||
border: none;
|
||||
|
||||
.card-header {
|
||||
min-height: 2.1em;
|
||||
padding: .50rem 1.25rem;
|
||||
background: $white;
|
||||
border-top: 3px solid $midnight-blue;
|
||||
|
||||
.sub-panel-banner-header {
|
||||
min-height: 2.2em;
|
||||
}
|
||||
|
||||
.sub-panel-header-toggle {
|
||||
border-radius: 50%;
|
||||
|
||||
.hidden-subpanel-buttons-count {
|
||||
top: -7px;
|
||||
right: -10px;
|
||||
background: $sky-blue;
|
||||
color: $white;
|
||||
border-radius: 7px;
|
||||
}
|
||||
|
||||
svg {
|
||||
font-size: 1.1em;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
}
|
||||
}
|
||||
|
||||
a.clickable {
|
||||
color: $midnight-blue;
|
||||
|
@ -218,18 +323,26 @@ div.widget-panel .panel-card .card-header {
|
|||
|
||||
|
||||
.sub-panel {
|
||||
|
||||
&:first-child {
|
||||
.card.panel-card {
|
||||
margin-top: 0.5em;
|
||||
}
|
||||
}
|
||||
table {
|
||||
tr {
|
||||
td:first-child,
|
||||
th:first-child{
|
||||
th:first-child {
|
||||
padding-left: 1.3em;
|
||||
}
|
||||
|
||||
td:last-child,
|
||||
th:last-child {
|
||||
padding-right: 1.3em;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.table .show-more-column {
|
||||
float: none !important;
|
||||
width: 16px;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue