mirror of
https://github.com/SuiteCRM/SuiteCRM-Core.git
synced 2025-09-01 08:00:47 +08:00
Add skeleton loading to top widget
This commit is contained in:
parent
863c6a8d16
commit
737dd75a32
3 changed files with 96 additions and 47 deletions
|
@ -30,56 +30,97 @@
|
|||
<div class="p-2 widget-bar-entry-message" *ngIf="this.messageLabelKey">
|
||||
{{vm.appStrings[this.messageLabelKey] || '' | uppercase}}
|
||||
</div>
|
||||
<ng-container *ngFor="let item of statistics | keyvalue">
|
||||
<ng-container *ngIf="!loading()">
|
||||
<ng-container *ngFor="let item of statistics | keyvalue">
|
||||
|
||||
<div class="d-flex flex-column justify-content-center align-items-baseline widget-bar-entry p-2">
|
||||
<div class="d-flex flex-column justify-content-center align-items-baseline widget-bar-entry p-2">
|
||||
|
||||
<ng-container *ngIf="!shouldHide(vm.statistics[item.key], item.value)">
|
||||
<ng-container *ngIf="!shouldHide(vm.statistics[item.key], item.value)">
|
||||
|
||||
<div *ngIf="item.value.labelKey && getLabel(item.value.labelKey)" class="pr-1 widget-bar-entry-label">
|
||||
<ng-container *ngIf="!isValueEmpty(vm.statistics[item.key])">
|
||||
{{getLabel(item.value.labelKey) | uppercase}}:
|
||||
</ng-container>
|
||||
<ng-container *ngIf="isValueEmpty(vm.statistics[item.key])">
|
||||
{{getLabel(item.value.labelKey) | uppercase}}
|
||||
</ng-container>
|
||||
</div>
|
||||
<div *ngIf="item.value.labelKey && getLabel(item.value.labelKey)" class="pr-1 widget-bar-entry-label">
|
||||
<ng-container *ngIf="!isValueEmpty(vm.statistics[item.key])">
|
||||
{{getLabel(item.value.labelKey) | uppercase}}:
|
||||
</ng-container>
|
||||
<ng-container *ngIf="isValueEmpty(vm.statistics[item.key])">
|
||||
{{getLabel(item.value.labelKey) | uppercase}}
|
||||
</ng-container>
|
||||
</div>
|
||||
|
||||
</ng-container>
|
||||
|
||||
<ng-container
|
||||
*ngIf="item.key && vm.statistics[item.key] && !shouldHide(vm.statistics[item.key], item.value)">
|
||||
|
||||
<div class="pl-1 pr-1 widget-bar-entry-value"
|
||||
*ngIf="!vm.statistics[item.key].loading && vm.statistics[item.key].field">
|
||||
<ng-container
|
||||
*ngIf="!isValueEmpty(vm.statistics[item.key]) || item.value.hideValueIfEmpty !== true">
|
||||
<scrm-field [type]="vm.statistics[item.key].field.type" [field]="vm.statistics[item.key].field"
|
||||
mode="list"></scrm-field>
|
||||
|
||||
</ng-container>
|
||||
</div>
|
||||
|
||||
</ng-container>
|
||||
|
||||
<div class="pl-1 pr-1 widget-bar-entry-loading" *ngIf="(item.value.store.loading$ | async) as loading">
|
||||
<scrm-inline-loading-spinner></scrm-inline-loading-spinner>
|
||||
|
||||
<ng-container *ngIf="!loading && (!item.key || !vm.statistics[item.key])">
|
||||
-
|
||||
</ng-container>
|
||||
|
||||
<ng-container
|
||||
*ngIf="item.key && vm.statistics[item.key] && !shouldHide(vm.statistics[item.key], item.value)">
|
||||
|
||||
<div class="pl-1 pr-1 widget-bar-entry-value"
|
||||
*ngIf="!vm.statistics[item.key].loading && vm.statistics[item.key].field">
|
||||
<ng-container
|
||||
*ngIf="!isValueEmpty(vm.statistics[item.key]) || item.value.hideValueIfEmpty !== true">
|
||||
<scrm-field [type]="vm.statistics[item.key].field.type" [field]="vm.statistics[item.key].field"
|
||||
mode="list"></scrm-field>
|
||||
|
||||
</ng-container>
|
||||
</div>
|
||||
|
||||
</ng-container>
|
||||
|
||||
<div class="pl-1 pr-1 widget-bar-entry-loading" *ngIf="(item.value.store.loading$ | async) as loading">
|
||||
<div class="pb-2">
|
||||
<div class="large-size-text-skeleton small-length-text-skeleton rounded box-loading skeleton-field-content">
|
||||
.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ng-container *ngIf="!loading && (!item.key || !vm.statistics[item.key])">
|
||||
-
|
||||
</ng-container>
|
||||
</div>
|
||||
|
||||
<ng-container *ngIf="!shouldHide(vm.statistics[item.key], item.value)">
|
||||
|
||||
<div *ngIf="item.value.endLabelKey && getLabel(item.value.endLabelKey)"
|
||||
class="pl-1 widget-bar-entry-end-label">
|
||||
{{getLabel(item.value.endLabelKey) | uppercase}}
|
||||
</div>
|
||||
|
||||
</ng-container>
|
||||
|
||||
</div>
|
||||
|
||||
<ng-container *ngIf="!shouldHide(vm.statistics[item.key], item.value)">
|
||||
</ng-container>
|
||||
</ng-container>
|
||||
|
||||
<div *ngIf="item.value.endLabelKey && getLabel(item.value.endLabelKey)"
|
||||
class="pl-1 widget-bar-entry-end-label">
|
||||
{{getLabel(item.value.endLabelKey) | uppercase}}
|
||||
<ng-container *ngIf="loading()">
|
||||
<div class="d-flex flex-column justify-content-center align-items-baseline widget-bar-entry p-2">
|
||||
|
||||
<div class="pl-1 pr-1 widget-bar-entry-value">
|
||||
<div class="pb-2">
|
||||
<div class="large-size-text-skeleton small-length-text-skeleton rounded box-loading skeleton-field-content">
|
||||
.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="pr-1 widget-bar-entry-label large-length-text-skeleton rounded box-loading skeleton-field-content">
|
||||
.
|
||||
</div>
|
||||
|
||||
</ng-container>
|
||||
|
||||
</div>
|
||||
<div class="d-flex flex-column justify-content-center align-items-baseline widget-bar-entry p-2">
|
||||
|
||||
<div class="pl-1 pr-1 widget-bar-entry-value">
|
||||
<div class="pb-2">
|
||||
<div class="large-size-text-skeleton small-length-text-skeleton rounded box-loading skeleton-field-content">
|
||||
.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="pr-1 widget-bar-entry-label large-length-text-skeleton rounded box-loading skeleton-field-content">
|
||||
.
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</ng-container>
|
||||
</div>
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
* the words "Supercharged by SuiteCRM".
|
||||
*/
|
||||
|
||||
import {Component, OnDestroy, OnInit} from '@angular/core';
|
||||
import {Component, OnDestroy, OnInit, signal, WritableSignal} from '@angular/core';
|
||||
import {BaseWidgetComponent} from '../../../widgets/base-widget.model';
|
||||
import {SingleValueStatisticsStore} from '../../../../store/single-value-statistics/single-value-statistics.store';
|
||||
import {
|
||||
|
@ -65,7 +65,7 @@ export class StatisticsTopWidgetComponent extends BaseWidgetComponent implements
|
|||
vm$: Observable<StatisticsTopWidgetState>;
|
||||
messageLabelKey: string;
|
||||
loading$: Observable<boolean>;
|
||||
protected loading = true;
|
||||
protected loading: WritableSignal<boolean> = signal(true);
|
||||
protected subs: Subscription[] = [];
|
||||
|
||||
constructor(
|
||||
|
@ -148,7 +148,7 @@ export class StatisticsTopWidgetComponent extends BaseWidgetComponent implements
|
|||
combineLatestWith(...loadings$),
|
||||
map((loadings) => {
|
||||
if (!loadings || loadings.length < 1) {
|
||||
this.loading = false;
|
||||
this.loading.set(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -158,7 +158,7 @@ export class StatisticsTopWidgetComponent extends BaseWidgetComponent implements
|
|||
loading = loading && value;
|
||||
});
|
||||
|
||||
this.loading = loading;
|
||||
this.loading.set(loading);
|
||||
|
||||
return loading;
|
||||
})
|
||||
|
@ -186,9 +186,9 @@ export class StatisticsTopWidgetComponent extends BaseWidgetComponent implements
|
|||
|
||||
if (this.config.reload$) {
|
||||
this.subs.push(this.config.reload$.subscribe(() => {
|
||||
if (this.loading === false) {
|
||||
if (this.loading() === false) {
|
||||
|
||||
this.loading = true;
|
||||
this.loading.set(true);
|
||||
this.config.options.statistics.forEach(statistic => {
|
||||
|
||||
if (!statistic.type) {
|
||||
|
@ -273,4 +273,6 @@ export class StatisticsTopWidgetComponent extends BaseWidgetComponent implements
|
|||
|
||||
return this.language.getFieldLabel(key, module);
|
||||
}
|
||||
|
||||
protected readonly signal = signal;
|
||||
}
|
||||
|
|
|
@ -27,17 +27,23 @@
|
|||
.widget-bar {
|
||||
background-color: $white;
|
||||
color: $dark-midnight-grey;
|
||||
box-shadow: 0 .125rem .25rem #00000013 ;
|
||||
box-shadow: 0 .125rem .25rem #00000013;
|
||||
border: 1px solid $extra-light-grey;
|
||||
min-height: 70px;
|
||||
}
|
||||
|
||||
.widget-bar .widget-bar-entry-value {
|
||||
font-weight: 900;
|
||||
font-size: 1.7em;
|
||||
|
||||
.skeleton-field-content {
|
||||
background-color: $dark-midnight-grey;
|
||||
opacity: 0.2;
|
||||
}
|
||||
}
|
||||
|
||||
.widget-bar .widget-bar-entry-label,
|
||||
.widget-bar .widget-bar-entry-end-label{
|
||||
.widget-bar .widget-bar-entry-end-label {
|
||||
font-weight: 400;
|
||||
font-size: 0.7em;
|
||||
}
|
||||
|
@ -45,5 +51,5 @@
|
|||
.widget-bar .inline-spinner > div {
|
||||
width: 0.45em;
|
||||
height: 0.45em;
|
||||
background-color: white;
|
||||
background-color: $dark-midnight-grey;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue