UI: Widget header button action
This commit is contained in:
parent
06b5706d87
commit
bbedb8797b
@ -88,12 +88,74 @@
|
||||
</mat-icon>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
@if (widgetActionFormGroup.get('actionSourceId').value === 'headerButton') {
|
||||
<div class="tb-form-panel stroked">
|
||||
<div class="tb-form-panel-title" translate>widget-config.header-button.button-settings</div>
|
||||
<div class="tb-form-row">
|
||||
<div class="fixed-title-width" translate>widget-config.header-button.button-type</div>
|
||||
<mat-form-field class="flex-1" appearance="outline" subscriptSizing="dynamic">
|
||||
<mat-select required formControlName="buttonType" placeholder="{{ 'widget-config.set' | translate }}">
|
||||
<mat-option *ngFor="let button of widgetHeaderActionButtonTypes" [value]="button">
|
||||
{{ widgetHeaderActionButtonTypeTranslationMap.get(widgetHeaderActionButtonType[button]) | translate }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
<div class="tb-form-row space-between">
|
||||
<div class="flex flex-row items-center justify-start gap-2">
|
||||
<mat-slide-toggle class="mat-slide" formControlName="showIcon">
|
||||
</mat-slide-toggle>
|
||||
<div translate>widget-config.icon</div>
|
||||
</div>
|
||||
<tb-material-icon-select asBoxInput
|
||||
formControlName="icon">
|
||||
</tb-material-icon-select>
|
||||
</div>
|
||||
<div class="tb-form-row space-between column-xs">
|
||||
<div class="fixed-title-width">{{ 'widget-config.header-button.colors' | translate }}</div>
|
||||
<div class="flex flex-row items-center justify-start gap-2">
|
||||
<div class="tb-small-label" translate>widget-config.header-button.color</div>
|
||||
<tb-color-input asBoxInput
|
||||
formControlName="buttonColor">
|
||||
</tb-color-input>
|
||||
<mat-divider vertical></mat-divider>
|
||||
<div class="tb-small-label" translate>widget-config.header-button.background</div>
|
||||
<tb-color-input asBoxInput
|
||||
formControlName="buttonFillColor">
|
||||
</tb-color-input>
|
||||
<mat-divider vertical></mat-divider>
|
||||
<div class="tb-small-label" translate>widget-config.header-button.border</div>
|
||||
<tb-color-input asBoxInput
|
||||
formControlName="buttonBorderColor">
|
||||
</tb-color-input>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tb-form-panel stroked">
|
||||
<mat-expansion-panel class="tb-settings">
|
||||
<mat-expansion-panel-header>
|
||||
<mat-panel-description class="flex items-stretch justify-start" translate>
|
||||
widget-config.header-button.advanced-button-style
|
||||
</mat-panel-description>
|
||||
</mat-expansion-panel-header>
|
||||
<ng-template matExpansionPanelContent>
|
||||
<tb-json-object-edit
|
||||
[editorStyle]="{minHeight: '100px'}"
|
||||
label="{{ 'widget-config.header-button.button-style' | translate }}"
|
||||
formControlName="customButtonStyle"
|
||||
></tb-json-object-edit>
|
||||
</ng-template>
|
||||
</mat-expansion-panel>
|
||||
</div>
|
||||
</div>
|
||||
} @else {
|
||||
<div class="tb-form-row space-between">
|
||||
<div>{{'widget-config.icon' | translate}}</div>
|
||||
<tb-material-icon-select asBoxInput
|
||||
formControlName="icon">
|
||||
</tb-material-icon-select>
|
||||
</div>
|
||||
}
|
||||
|
||||
<div class="tb-form-panel stroked tb-slide-toggle" *ngIf="displayShowWidgetActionForm()">
|
||||
<mat-expansion-panel class="tb-settings" [expanded]="widgetActionFormGroup.get('useShowWidgetActionFunction').value"
|
||||
[disabled]="!widgetActionFormGroup.get('useShowWidgetActionFunction').value">
|
||||
|
||||
@ -43,6 +43,10 @@ import {
|
||||
CellClickColumnInfo,
|
||||
defaultWidgetAction,
|
||||
WidgetActionSource,
|
||||
WidgetHeaderActionButtonType,
|
||||
widgetHeaderActionButtonTypeMap,
|
||||
WidgetHeaderActionButtonTypes,
|
||||
widgetHeaderActionButtonTypeTranslationMap,
|
||||
widgetType
|
||||
} from '@shared/models/widget.models';
|
||||
import { takeUntil } from 'rxjs/operators';
|
||||
@ -85,6 +89,11 @@ export class WidgetActionDialogComponent extends DialogComponent<WidgetActionDia
|
||||
configuredColumns: Array<CellClickColumnInfo> = [];
|
||||
usedCellClickColumns: Array<number> = [];
|
||||
|
||||
widgetHeaderActionButtonType = WidgetHeaderActionButtonType
|
||||
widgetHeaderActionButtonTypes = WidgetHeaderActionButtonTypes;
|
||||
widgetHeaderActionButtonTypeTranslationMap = widgetHeaderActionButtonTypeTranslationMap;
|
||||
widgetHeaderActionButtonTypeMap = widgetHeaderActionButtonTypeMap;
|
||||
|
||||
@ViewChild('columnIndexSelect') columnIndexSelect: MatSelect;
|
||||
columnIndexPlaceholderText = this.translate.instant('widget-config.select-column-index');
|
||||
|
||||
@ -120,12 +129,19 @@ export class WidgetActionDialogComponent extends DialogComponent<WidgetActionDia
|
||||
actionSourceId: [this.action.actionSourceId, Validators.required],
|
||||
columnIndex: [{value: this.checkColumnIndex(this.action.columnIndex), disabled: true}, Validators.required],
|
||||
name: [this.action.name, [this.validateActionName(), Validators.required]],
|
||||
buttonType: [isDefinedAndNotNull(this.action.buttonType) ? this.action.buttonType : WidgetHeaderActionButtonType.icon, []],
|
||||
showIcon: [isDefinedAndNotNull(this.action.showIcon) ? this.action.showIcon : true, []],
|
||||
icon: [this.action.icon, Validators.required],
|
||||
buttonColor: [isDefinedAndNotNull(this.action.buttonColor) ? this.action.buttonColor : 'rgba(0, 0, 0, 0.87)', []],
|
||||
buttonFillColor: [isDefinedAndNotNull(this.action.buttonFillColor) ? this.action.buttonFillColor : '#3F52DD', []],
|
||||
buttonBorderColor: [isDefinedAndNotNull(this.action.buttonBorderColor) ? this.action.buttonBorderColor : '#3F52DD', []],
|
||||
customButtonStyle: [isDefinedAndNotNull(this.action.customButtonStyle) ? this.action.customButtonStyle : '', []],
|
||||
useShowWidgetActionFunction: [this.action.useShowWidgetActionFunction],
|
||||
showWidgetActionFunction: [this.action.showWidgetActionFunction || 'return true;'],
|
||||
widgetAction: [actionDescriptorToAction(toWidgetActionDescriptor(this.action)), Validators.required]
|
||||
});
|
||||
this.updateShowWidgetActionForm();
|
||||
this.widgetHeaderButtonValidators();
|
||||
this.widgetActionFormGroup.get('actionSourceId').valueChanges.pipe(
|
||||
takeUntil(this.destroy$)
|
||||
).subscribe((value) => {
|
||||
@ -143,6 +159,9 @@ export class WidgetActionDialogComponent extends DialogComponent<WidgetActionDia
|
||||
).subscribe(() => {
|
||||
this.updateShowWidgetActionForm();
|
||||
});
|
||||
this.widgetActionFormGroup.get('buttonType').valueChanges.pipe(
|
||||
takeUntil(this.destroy$)
|
||||
).subscribe(() => this.widgetHeaderButtonValidators());
|
||||
setTimeout(() => {
|
||||
if (this.action?.actionSourceId === 'cellClick') {
|
||||
this.widgetActionFormGroup.get('columnIndex').enable();
|
||||
@ -160,6 +179,31 @@ export class WidgetActionDialogComponent extends DialogComponent<WidgetActionDia
|
||||
super.ngOnDestroy();
|
||||
}
|
||||
|
||||
widgetHeaderButtonValidators() {
|
||||
const buttonType = this.widgetActionFormGroup.get('buttonType').value;
|
||||
this.widgetActionFormGroup.get('showIcon').disable({emitEvent: false});
|
||||
this.widgetActionFormGroup.get('buttonFillColor').disable({emitEvent: false});
|
||||
this.widgetActionFormGroup.get('buttonBorderColor').disable({emitEvent: false});
|
||||
switch (buttonType) {
|
||||
case WidgetHeaderActionButtonType.basic:
|
||||
this.widgetActionFormGroup.get('showIcon').enable({emitEvent: false});
|
||||
break;
|
||||
case WidgetHeaderActionButtonType.raised:
|
||||
this.widgetActionFormGroup.get('showIcon').enable({emitEvent: false});
|
||||
this.widgetActionFormGroup.get('buttonFillColor').enable({emitEvent: false});
|
||||
break;
|
||||
case WidgetHeaderActionButtonType.stroked:
|
||||
case WidgetHeaderActionButtonType.flat:
|
||||
this.widgetActionFormGroup.get('showIcon').enable({emitEvent: false});
|
||||
this.widgetActionFormGroup.get('buttonFillColor').enable({emitEvent: false});
|
||||
this.widgetActionFormGroup.get('buttonBorderColor').enable({emitEvent: false});
|
||||
break;
|
||||
case WidgetHeaderActionButtonType.miniFab:
|
||||
this.widgetActionFormGroup.get('buttonFillColor').enable({emitEvent: false});
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
displayShowWidgetActionForm(): boolean {
|
||||
return !!this.data.actionsData.actionSources[this.widgetActionFormGroup.get('actionSourceId').value]?.hasShowCondition;
|
||||
}
|
||||
|
||||
@ -37,14 +37,79 @@
|
||||
class="tb-widget-actions"
|
||||
[class]="{'tb-widget-actions-absolute': !(widget.showWidgetTitlePanel && !widgetComponent.widgetContext?.embedTitlePanel && (widget.showTitle||widget.hasAggregation))}"
|
||||
(mousedown)="$event.stopPropagation()">
|
||||
<button mat-icon-button *ngFor="let action of widget.customHeaderActions"
|
||||
type="button"
|
||||
<div class="flex items-center gap-2">
|
||||
<ng-container *ngFor="let action of widget.customHeaderActions">
|
||||
@switch (action.buttonType) {
|
||||
@case (widgetHeaderActionButtonType.icon) {
|
||||
<button mat-icon-button
|
||||
[style]="action.customButtonStyle"
|
||||
[class.!hidden]="isEdit"
|
||||
(click)="action.onAction($event)"
|
||||
matTooltip="{{ action.displayName }}"
|
||||
matTooltipPosition="above">
|
||||
<tb-icon>{{ action.icon }}</tb-icon>
|
||||
<tb-icon [style.color]="action.buttonColor">{{ action.icon }}</tb-icon>
|
||||
</button>
|
||||
}
|
||||
@case (widgetHeaderActionButtonType.miniFab) {
|
||||
<button mat-mini-fab
|
||||
[style]="action.customButtonStyle"
|
||||
[class.!hidden]="isEdit"
|
||||
[style.background-color]="action.buttonFillColor"
|
||||
(click)="action.onAction($event)"
|
||||
matTooltip="{{ action.displayName }}"
|
||||
matTooltipPosition="above">
|
||||
<tb-icon [style.color]="action.buttonColor">{{ action.icon }}</tb-icon>
|
||||
</button>
|
||||
}
|
||||
@case (widgetHeaderActionButtonType.basic) {
|
||||
<button [class.!hidden]="isEdit" mat-button
|
||||
[style]="action.customButtonStyle"
|
||||
(click)="action.onAction($event)"
|
||||
matTooltip="{{ action.displayName }}"
|
||||
matTooltipPosition="above">
|
||||
<tb-icon matButtonIcon *ngIf="action.showIcon" [style.color]="action.buttonColor">{{ action.icon }}</tb-icon>
|
||||
<span [style.color]="action.buttonColor">{{ action.displayName }}</span>
|
||||
</button>
|
||||
}
|
||||
@case (widgetHeaderActionButtonType.raised) {
|
||||
<button [class.!hidden]="isEdit" mat-raised-button
|
||||
[style]="action.customButtonStyle"
|
||||
[style.background-color]="action.buttonFillColor"
|
||||
(click)="action.onAction($event)"
|
||||
matTooltip="{{ action.displayName }}"
|
||||
matTooltipPosition="above">
|
||||
<tb-icon matButtonIcon *ngIf="action.showIcon" [style.color]="action.buttonColor">{{ action.icon }}</tb-icon>
|
||||
<span [style.color]="action.buttonColor">{{ action.displayName }}</span>
|
||||
</button>
|
||||
}
|
||||
@case (widgetHeaderActionButtonType.stroked) {
|
||||
<button [class.!hidden]="isEdit" mat-stroked-button
|
||||
[style]="action.customButtonStyle"
|
||||
[style.border-color]="action.buttonBorderColor"
|
||||
[style.background-color]="action.buttonFillColor"
|
||||
(click)="action.onAction($event)"
|
||||
matTooltip="{{ action.displayName }}"
|
||||
matTooltipPosition="above">
|
||||
<tb-icon matButtonIcon *ngIf="action.showIcon" [style.color]="action.buttonColor">{{ action.icon }}</tb-icon>
|
||||
<span [style.color]="action.buttonColor">{{ action.displayName }}</span>
|
||||
</button>
|
||||
}
|
||||
@case (widgetHeaderActionButtonType.flat) {
|
||||
<button [class.!hidden]="isEdit" mat-flat-button
|
||||
[style]="action.customButtonStyle"
|
||||
[style.background-color]="action.buttonFillColor"
|
||||
[style.border-color]="action.buttonBorderColor"
|
||||
(click)="action.onAction($event)"
|
||||
matTooltip="{{ action.displayName }}"
|
||||
matTooltipPosition="above">
|
||||
<tb-icon matButtonIcon *ngIf="action.showIcon" [style.color]="action.buttonColor">{{ action.icon }}</tb-icon>
|
||||
<span [style.color]="action.buttonColor">{{ action.displayName }}</span>
|
||||
</button>
|
||||
}
|
||||
}
|
||||
</ng-container>
|
||||
</div>
|
||||
|
||||
<button mat-icon-button *ngFor="let action of widget.widgetActions"
|
||||
type="button"
|
||||
[class.!hidden]="isEdit || !action.show"
|
||||
|
||||
@ -87,7 +87,7 @@ div.tb-widget {
|
||||
place-content: center flex-start;
|
||||
align-items: center;
|
||||
z-index: 19;
|
||||
margin: 5px 0 0;
|
||||
margin: 5px 0 5px;
|
||||
|
||||
&-absolute {
|
||||
position: absolute;
|
||||
|
||||
@ -44,8 +44,9 @@ import { GridsterItemComponent } from 'angular-gridster2';
|
||||
import { UtilsService } from '@core/services/utils.service';
|
||||
import { from } from 'rxjs';
|
||||
import { DashboardUtilsService } from '@core/services/dashboard-utils.service';
|
||||
import ITooltipsterInstance = JQueryTooltipster.ITooltipsterInstance;
|
||||
import { TbContextMenuEvent } from '@shared/models/jquery-event.models';
|
||||
import { WidgetHeaderActionButtonType } from '@shared/models/widget.models';
|
||||
import ITooltipsterInstance = JQueryTooltipster.ITooltipsterInstance;
|
||||
|
||||
export enum WidgetComponentActionType {
|
||||
MOUSE_DOWN,
|
||||
@ -130,6 +131,8 @@ export class WidgetContainerComponent extends PageComponent implements OnInit, O
|
||||
return (this.isEditActionEnabled || this.isRemoveActionEnabled || this.isExportActionEnabled) && !this.widget?.isFullscreen;
|
||||
}
|
||||
|
||||
widgetHeaderActionButtonType = WidgetHeaderActionButtonType;
|
||||
|
||||
private cssClass: string;
|
||||
|
||||
private editWidgetActionsTooltip: ITooltipsterInstance;
|
||||
|
||||
@ -295,7 +295,13 @@ export class WidgetComponent extends PageComponent implements OnInit, OnChanges,
|
||||
const headerAction: WidgetHeaderAction = {
|
||||
name: descriptor.name,
|
||||
displayName: descriptor.displayName,
|
||||
buttonType: descriptor.buttonType,
|
||||
showIcon: descriptor.showIcon,
|
||||
icon: descriptor.icon,
|
||||
buttonColor: descriptor.buttonColor,
|
||||
buttonFillColor: descriptor.buttonFillColor,
|
||||
buttonBorderColor: descriptor.buttonBorderColor,
|
||||
customButtonStyle: descriptor.customButtonStyle,
|
||||
descriptor,
|
||||
useShowWidgetHeaderActionFunction,
|
||||
showWidgetHeaderActionFunction,
|
||||
|
||||
@ -26,6 +26,7 @@ import {
|
||||
WidgetActionSource,
|
||||
WidgetConfig,
|
||||
WidgetControllerDescriptor,
|
||||
WidgetHeaderActionButtonType,
|
||||
WidgetType,
|
||||
widgetType,
|
||||
WidgetTypeDescriptor,
|
||||
@ -118,6 +119,12 @@ export type ShowWidgetHeaderActionFunction = (ctx: WidgetContext, data: Formatte
|
||||
export interface WidgetHeaderAction extends IWidgetAction {
|
||||
displayName: string;
|
||||
descriptor: WidgetActionDescriptor;
|
||||
buttonType?: WidgetHeaderActionButtonType;
|
||||
showIcon?:boolean;
|
||||
buttonColor?: string;
|
||||
buttonFillColor?: string;
|
||||
buttonBorderColor?: string;
|
||||
customButtonStyle?: string;
|
||||
useShowWidgetHeaderActionFunction: boolean;
|
||||
showWidgetHeaderActionFunction: CompiledTbFunction<ShowWidgetHeaderActionFunction>;
|
||||
}
|
||||
|
||||
@ -567,6 +567,35 @@ export interface LegendData {
|
||||
data: Array<LegendKeyData>;
|
||||
}
|
||||
|
||||
export enum WidgetHeaderActionButtonType {
|
||||
basic = 'basic',
|
||||
raised = 'raised',
|
||||
stroked = 'stroked',
|
||||
flat = 'flat',
|
||||
icon = 'icon',
|
||||
miniFab = 'miniFab'
|
||||
}
|
||||
|
||||
export const WidgetHeaderActionButtonTypes = Object.keys(WidgetHeaderActionButtonType) as WidgetHeaderActionButtonType[];
|
||||
|
||||
export const widgetHeaderActionButtonTypeTranslationMap = new Map<WidgetHeaderActionButtonType, string>([
|
||||
[WidgetHeaderActionButtonType.basic, 'widget-config.header-button.button-type-basic'],
|
||||
[WidgetHeaderActionButtonType.raised, 'widget-config.header-button.button-type-raised'],
|
||||
[WidgetHeaderActionButtonType.stroked, 'widget-config.header-button.button-type-stroked'],
|
||||
[WidgetHeaderActionButtonType.flat, 'widget-config.header-button.button-type-flat'],
|
||||
[WidgetHeaderActionButtonType.icon, 'widget-config.header-button.button-type-icon'],
|
||||
[WidgetHeaderActionButtonType.miniFab, 'widget-config.header-button.button-type-mini-fab']
|
||||
]);
|
||||
|
||||
export const widgetHeaderActionButtonTypeMap = new Map<WidgetHeaderActionButtonType, string>([
|
||||
[WidgetHeaderActionButtonType.basic, 'mat-button'],
|
||||
[WidgetHeaderActionButtonType.raised, 'mat-raised-button'],
|
||||
[WidgetHeaderActionButtonType.stroked, 'mat-stroked-button'],
|
||||
[WidgetHeaderActionButtonType.flat, 'mat-flat-button'],
|
||||
[WidgetHeaderActionButtonType.icon, 'mat-icon-button'],
|
||||
[WidgetHeaderActionButtonType.miniFab, 'mat-mini-fab']
|
||||
]);
|
||||
|
||||
export enum WidgetActionType {
|
||||
doNothing = 'doNothing',
|
||||
openDashboardState = 'openDashboardState',
|
||||
@ -718,7 +747,13 @@ export interface WidgetAction extends CustomActionDescriptor {
|
||||
export interface WidgetActionDescriptor extends WidgetAction {
|
||||
id: string;
|
||||
name: string;
|
||||
buttonType?: WidgetHeaderActionButtonType;
|
||||
showIcon?: boolean;
|
||||
icon: string;
|
||||
buttonColor?: string;
|
||||
buttonFillColor?: string;
|
||||
buttonBorderColor?: string;
|
||||
customButtonStyle?: string;
|
||||
displayName?: string;
|
||||
useShowWidgetActionFunction?: boolean;
|
||||
showWidgetActionFunction?: TbFunction;
|
||||
@ -729,7 +764,13 @@ export const actionDescriptorToAction = (descriptor: WidgetActionDescriptor): Wi
|
||||
const result: WidgetActionDescriptor = {...descriptor};
|
||||
delete result.id;
|
||||
delete result.name;
|
||||
delete result.buttonType;
|
||||
delete result.showIcon;
|
||||
delete result.icon;
|
||||
delete result.buttonColor;
|
||||
delete result.buttonFillColor;
|
||||
delete result.buttonBorderColor;
|
||||
delete result.customButtonStyle;
|
||||
delete result.displayName;
|
||||
delete result.useShowWidgetActionFunction;
|
||||
delete result.showWidgetActionFunction;
|
||||
|
||||
@ -6537,6 +6537,22 @@
|
||||
"action-name-required": "Action name is required.",
|
||||
"action-name-not-unique": "Another action with the same name already exists.\nAction name should be unique within the same action source.",
|
||||
"action-icon": "Icon",
|
||||
"header-button": {
|
||||
"button-settings": "Button settings",
|
||||
"button-type": "Button type",
|
||||
"button-type-basic": "Basic",
|
||||
"button-type-raised": "Raised",
|
||||
"button-type-stroked": "Stroked",
|
||||
"button-type-flat": "Flat",
|
||||
"button-type-icon": "Icon",
|
||||
"button-type-mini-fab": "FAB",
|
||||
"colors": "Colors",
|
||||
"color": "Color",
|
||||
"background": "Background",
|
||||
"border": "Border",
|
||||
"advanced-button-style": "Advanced button style",
|
||||
"button-style": "Button style"
|
||||
},
|
||||
"show-hide-action-using-function": "Show/hide action using function",
|
||||
"show-action-function": "Show action function",
|
||||
"action-type": "Type",
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user