Browse Source

UI: Added filter widget type

pull/4205/head
Vladyslav_Prykhodko 6 years ago
parent
commit
a3e2106888
  1. 22
      ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-page.component.html
  2. 78
      ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-page.component.ts
  3. 42
      ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-widget-select.component.ts
  4. 23
      ui-ngx/src/app/modules/home/components/dashboard-page/widget-types-panel.component.html
  5. 36
      ui-ngx/src/app/modules/home/components/dashboard-page/widget-types-panel.component.scss
  6. 48
      ui-ngx/src/app/modules/home/components/dashboard-page/widget-types-panel.component.ts
  7. 6
      ui-ngx/src/app/modules/home/components/details-panel.component.html
  8. 7
      ui-ngx/src/app/modules/home/components/details-panel.component.ts
  9. 7
      ui-ngx/src/app/modules/home/components/home-components.module.ts
  10. 2
      ui-ngx/src/app/shared/components/widgets-bundle-search.component.html
  11. 3
      ui-ngx/src/assets/locale/locale.constant-en_US.json
  12. 3
      ui-ngx/src/styles.scss

22
ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-page.component.html

@ -248,11 +248,14 @@
headerHeightPx="120" headerHeightPx="120"
[isReadOnly]="true" [isReadOnly]="true"
[isEdit]="false" [isEdit]="false"
[showBackStateIcon]="!!widgetsBundle?.title" (closeDetails)="onAddWidgetClosed()">
(closeDetails)="onAddWidgetClosed()" <div class="prefix-title-buttons" [fxHide]="!widgetsBundle?.title" style="height: 28px; margin-right: 12px">
(backStateDetails)="widgetBundleSelected(null)"> <button class="tb-mat-28" mat-icon-button type="button" (click)="widgetBundleSelected(null)">
<mat-icon>arrow_back</mat-icon>
</button>
</div>
<div class="header-pane" *ngIf="isAddingWidget"> <div class="header-pane" *ngIf="isAddingWidget">
<div fxLayout="row"> <div fxLayout="row" fxLayoutGap="12px">
<tb-widgets-bundle-search fxFlex <tb-widgets-bundle-search fxFlex
[(ngModel)]="searchBundle" [(ngModel)]="searchBundle"
placeholder="{{ (!widgetsBundle?.title ? 'widgets-bundle.search' : 'widget.search') | translate }}" placeholder="{{ (!widgetsBundle?.title ? 'widgets-bundle.search' : 'widget.search') | translate }}"
@ -260,10 +263,21 @@
</tb-widgets-bundle-search> </tb-widgets-bundle-search>
</div> </div>
</div> </div>
<div class="details-buttons" *ngIf="isAddingWidget">
<button mat-button mat-icon-button type="button"
*ngIf="widgetTypes.length > 1"
(click)="editWidgetsTypesToDisplay($event)"
matTooltip="{{ 'widget.filter' | translate }}"
matTooltipPosition="above">
<mat-icon>filter_list</mat-icon>
</button>
</div>
<tb-dashboard-widget-select *ngIf="isAddingWidget" <tb-dashboard-widget-select *ngIf="isAddingWidget"
[aliasController]="dashboardCtx.aliasController" [aliasController]="dashboardCtx.aliasController"
[widgetsBundle]="widgetsBundle" [widgetsBundle]="widgetsBundle"
[searchBundle]="searchBundle" [searchBundle]="searchBundle"
[filterWidgetTypes]="filterWidgetTypes"
(widgetsTypes)="updateWidgetsTypes($event)"
(widgetsBundleSelected)="widgetBundleSelected($event)" (widgetsBundleSelected)="widgetBundleSelected($event)"
(widgetSelected)="addWidgetFromType($event)"> (widgetSelected)="addWidgetFromType($event)">
</tb-dashboard-widget-select> </tb-dashboard-widget-select>

78
ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-page.component.ts

@ -18,11 +18,14 @@ import {
ChangeDetectorRef, ChangeDetectorRef,
Component, Component,
Inject, Inject,
Injector,
Input, Input,
NgZone, NgZone,
OnDestroy, OnDestroy,
OnInit, OnInit,
StaticProvider,
ViewChild, ViewChild,
ViewContainerRef,
ViewEncapsulation ViewEncapsulation
} from '@angular/core'; } from '@angular/core';
import { PageComponent } from '@shared/components/page.component'; import { PageComponent } from '@shared/components/page.component';
@ -58,7 +61,14 @@ import { BreakpointObserver, BreakpointState } from '@angular/cdk/layout';
import { MediaBreakpoints } from '@shared/models/constants'; import { MediaBreakpoints } from '@shared/models/constants';
import { AuthUser } from '@shared/models/user.model'; import { AuthUser } from '@shared/models/user.model';
import { getCurrentAuthState } from '@core/auth/auth.selectors'; import { getCurrentAuthState } from '@core/auth/auth.selectors';
import { Widget, WidgetConfig, WidgetInfo, WidgetPosition, widgetTypesData } from '@app/shared/models/widget.models'; import {
Widget,
WidgetConfig,
WidgetInfo,
WidgetPosition,
widgetType,
widgetTypesData
} from '@shared/models/widget.models';
import { environment as env } from '@env/environment'; import { environment as env } from '@env/environment';
import { Authority } from '@shared/models/authority.enum'; import { Authority } from '@shared/models/authority.enum';
import { DialogService } from '@core/services/dialog.service'; import { DialogService } from '@core/services/dialog.service';
@ -80,7 +90,10 @@ import {
import { EntityAliases } from '@app/shared/models/alias.models'; import { EntityAliases } from '@app/shared/models/alias.models';
import { EditWidgetComponent } from '@home/components/dashboard-page/edit-widget.component'; import { EditWidgetComponent } from '@home/components/dashboard-page/edit-widget.component';
import { WidgetsBundle } from '@shared/models/widgets-bundle.model'; import { WidgetsBundle } from '@shared/models/widgets-bundle.model';
import { AddWidgetDialogComponent, AddWidgetDialogData } from '@home/components/dashboard-page/add-widget-dialog.component'; import {
AddWidgetDialogComponent,
AddWidgetDialogData
} from '@home/components/dashboard-page/add-widget-dialog.component';
import { TranslateService } from '@ngx-translate/core'; import { TranslateService } from '@ngx-translate/core';
import { import {
ManageDashboardLayoutsDialogComponent, ManageDashboardLayoutsDialogComponent,
@ -99,6 +112,14 @@ import { ImportExportService } from '@home/components/import-export/import-expor
import { AuthState } from '@app/core/auth/auth.models'; import { AuthState } from '@app/core/auth/auth.models';
import { FiltersDialogComponent, FiltersDialogData } from '@home/components/filter/filters-dialog.component'; import { FiltersDialogComponent, FiltersDialogData } from '@home/components/filter/filters-dialog.component';
import { Filters } from '@shared/models/query/query.models'; import { Filters } from '@shared/models/query/query.models';
import { ConnectedPosition, Overlay, OverlayConfig, OverlayRef } from '@angular/cdk/overlay';
import { ComponentPortal } from '@angular/cdk/portal';
import {
DISPLAY_WIDGET_TYPES_PANEL_DATA,
DisplayWidgetTypesPanelComponent,
DisplayWidgetTypesPanelData,
WidgetTypes
} from '@home/components/dashboard-page/widget-types-panel.component';
// @dynamic // @dynamic
@Component({ @Component({
@ -147,6 +168,8 @@ export class DashboardPageComponent extends PageComponent implements IDashboardC
isAddingWidgetClosed = true; isAddingWidgetClosed = true;
widgetsBundle: WidgetsBundle = null; widgetsBundle: WidgetsBundle = null;
searchBundle = ''; searchBundle = '';
widgetTypes: WidgetTypes[] = [];
filterWidgetTypes: widgetType[] = null;
isToolbarOpened = false; isToolbarOpened = false;
isToolbarOpenedAnimate = false; isToolbarOpenedAnimate = false;
@ -261,6 +284,8 @@ export class DashboardPageComponent extends PageComponent implements IDashboardC
private dialog: MatDialog, private dialog: MatDialog,
private translate: TranslateService, private translate: TranslateService,
private ngZone: NgZone, private ngZone: NgZone,
private overlay: Overlay,
private viewContainerRef: ViewContainerRef,
private cd: ChangeDetectorRef) { private cd: ChangeDetectorRef) {
super(store); super(store);
@ -1121,6 +1146,55 @@ export class DashboardPageComponent extends PageComponent implements IDashboardC
widgetBundleSelected(bundle: WidgetsBundle){ widgetBundleSelected(bundle: WidgetsBundle){
this.widgetsBundle = bundle; this.widgetsBundle = bundle;
this.widgetTypes = [];
this.searchBundle = ''; this.searchBundle = '';
} }
updateWidgetsTypes(types: Set<widgetType>) {
this.widgetTypes = Array.from(types.values()).map(type => {
return {type, display: true};
});
}
editWidgetsTypesToDisplay($event: Event) {
if ($event) {
$event.stopPropagation();
}
const target = $event.target || $event.currentTarget;
const config = new OverlayConfig();
config.backdropClass = 'cdk-overlay-transparent-backdrop';
config.hasBackdrop = true;
const connectedPosition: ConnectedPosition = {
originX: 'end',
originY: 'bottom',
overlayX: 'end',
overlayY: 'top'
};
config.positionStrategy = this.overlay.position().flexibleConnectedTo(target as HTMLElement)
.withPositions([connectedPosition]);
const overlayRef = this.overlay.create(config);
overlayRef.backdropClick().subscribe(() => {
overlayRef.dispose();
});
const providers: StaticProvider[] = [
{
provide: DISPLAY_WIDGET_TYPES_PANEL_DATA,
useValue: {
types: this.widgetTypes,
typesUpdated: (newTypes) => {
this.filterWidgetTypes = newTypes.filter(type => type.display).map(type => type.type);
}
} as DisplayWidgetTypesPanelData
},
{
provide: OverlayRef,
useValue: overlayRef
}
];
const injector = Injector.create({parent: this.viewContainerRef.injector, providers});
overlayRef.attach(new ComponentPortal(DisplayWidgetTypesPanelComponent, this.viewContainerRef, injector));
this.cd.detectChanges();
}
} }

42
ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-widget-select.component.ts

@ -19,10 +19,10 @@ import { WidgetsBundle } from '@shared/models/widgets-bundle.model';
import { IAliasController } from '@core/api/widget-api.models'; import { IAliasController } from '@core/api/widget-api.models';
import { NULL_UUID } from '@shared/models/id/has-uuid'; import { NULL_UUID } from '@shared/models/id/has-uuid';
import { WidgetService } from '@core/http/widget.service'; import { WidgetService } from '@core/http/widget.service';
import { WidgetInfo } from '@shared/models/widget.models'; import { WidgetInfo, widgetType } from '@shared/models/widget.models';
import { toWidgetInfo } from '@home/models/widget-component.models'; import { toWidgetInfo } from '@home/models/widget-component.models';
import { distinctUntilChanged, map, publishReplay, refCount, switchMap } from 'rxjs/operators'; import { distinctUntilChanged, map, publishReplay, refCount, switchMap, tap } from 'rxjs/operators';
import { BehaviorSubject, Observable, of } from 'rxjs'; import { BehaviorSubject, combineLatest, Observable, of } from 'rxjs';
import { DomSanitizer, SafeUrl } from '@angular/platform-browser'; import { DomSanitizer, SafeUrl } from '@angular/platform-browser';
import { isDefinedAndNotNull } from '@core/utils'; import { isDefinedAndNotNull } from '@core/utils';
@ -34,15 +34,20 @@ import { isDefinedAndNotNull } from '@core/utils';
export class DashboardWidgetSelectComponent implements OnInit { export class DashboardWidgetSelectComponent implements OnInit {
private search$ = new BehaviorSubject<string>(''); private search$ = new BehaviorSubject<string>('');
private widgetsTypes: Observable<Array<WidgetInfo>>; private filterWidgetTypes$ = new BehaviorSubject<Array<widgetType>>(null);
private widgetsInfo: Observable<Array<WidgetInfo>>;
private widgetsBundleValue: WidgetsBundle; private widgetsBundleValue: WidgetsBundle;
private widgetsType = new Set<widgetType>();
widgets$: Observable<Array<WidgetInfo>>; widgets$: Observable<Array<WidgetInfo>>;
widgetsBundles$: Observable<Array<WidgetsBundle>>; widgetsBundles$: Observable<Array<WidgetsBundle>>;
@Input() @Input()
set widgetsBundle(widgetBundle: WidgetsBundle) { set widgetsBundle(widgetBundle: WidgetsBundle) {
this.widgetsTypes = null; this.widgetsInfo = null;
this.widgetsType.clear();
this.widgetsTypes.emit(this.widgetsType);
this.filterWidgetTypes$.next(null);
this.widgetsBundleValue = widgetBundle; this.widgetsBundleValue = widgetBundle;
} }
@ -58,12 +63,20 @@ export class DashboardWidgetSelectComponent implements OnInit {
this.search$.next(search); this.search$.next(search);
} }
@Input()
set filterWidgetTypes(widgetTypes: Array<widgetType>) {
this.filterWidgetTypes$.next(widgetTypes);
}
@Output() @Output()
widgetSelected: EventEmitter<WidgetInfo> = new EventEmitter<WidgetInfo>(); widgetSelected: EventEmitter<WidgetInfo> = new EventEmitter<WidgetInfo>();
@Output() @Output()
widgetsBundleSelected: EventEmitter<WidgetsBundle> = new EventEmitter<WidgetsBundle>(); widgetsBundleSelected: EventEmitter<WidgetsBundle> = new EventEmitter<WidgetsBundle>();
@Output()
widgetsTypes: EventEmitter<Set<widgetType>> = new EventEmitter<Set<widgetType>>();
constructor(private widgetsService: WidgetService, constructor(private widgetsService: WidgetService,
private sanitizer: DomSanitizer) { private sanitizer: DomSanitizer) {
} }
@ -73,21 +86,22 @@ export class DashboardWidgetSelectComponent implements OnInit {
distinctUntilChanged(), distinctUntilChanged(),
switchMap(search => this.fetchWidgetBundle(search)) switchMap(search => this.fetchWidgetBundle(search))
); );
this.widgets$ = this.search$.asObservable().pipe( this.widgets$ = combineLatest([this.search$.asObservable(), this.filterWidgetTypes$.asObservable()]).pipe(
distinctUntilChanged(), distinctUntilChanged((oldValue, newValue) => JSON.stringify(oldValue) === JSON.stringify(newValue)),
switchMap(search => this.fetchWidget(search)) switchMap(search => this.fetchWidget(...search))
); );
} }
private getWidgets(): Observable<Array<WidgetInfo>> { private getWidgets(): Observable<Array<WidgetInfo>> {
if (!this.widgetsTypes) { if (!this.widgetsInfo) {
if (this.widgetsBundle !== null) { if (this.widgetsBundle !== null) {
const bundleAlias = this.widgetsBundle.alias; const bundleAlias = this.widgetsBundle.alias;
const isSystem = this.widgetsBundle.tenantId.id === NULL_UUID; const isSystem = this.widgetsBundle.tenantId.id === NULL_UUID;
this.widgetsTypes = this.widgetsService.getBundleWidgetTypes(bundleAlias, isSystem).pipe( this.widgetsInfo = this.widgetsService.getBundleWidgetTypes(bundleAlias, isSystem).pipe(
map(widgets => widgets.sort((a, b) => b.createdTime - a.createdTime)), map(widgets => widgets.sort((a, b) => b.createdTime - a.createdTime)),
map(widgets => widgets.map((type) => { map(widgets => widgets.map((type) => {
const widgetTypeInfo = toWidgetInfo(type); const widgetTypeInfo = toWidgetInfo(type);
this.widgetsType.add(widgetTypeInfo.type);
const widget: WidgetInfo = { const widget: WidgetInfo = {
isSystemType: isSystem, isSystemType: isSystem,
bundleAlias, bundleAlias,
@ -99,14 +113,15 @@ export class DashboardWidgetSelectComponent implements OnInit {
}; };
return widget; return widget;
})), })),
tap(() => this.widgetsTypes.emit(this.widgetsType)),
publishReplay(1), publishReplay(1),
refCount() refCount()
); );
} else { } else {
this.widgetsTypes = of([]); this.widgetsInfo = of([]);
} }
} }
return this.widgetsTypes; return this.widgetsInfo;
} }
onWidgetClicked($event: Event, widget: WidgetInfo): void { onWidgetClicked($event: Event, widget: WidgetInfo): void {
@ -149,8 +164,9 @@ export class DashboardWidgetSelectComponent implements OnInit {
); );
} }
private fetchWidget(search: string): Observable<Array<WidgetInfo>> { private fetchWidget(search: string, filter: widgetType[]): Observable<Array<WidgetInfo>> {
return this.getWidgets().pipe( return this.getWidgets().pipe(
map(widgets => filter ? widgets.filter((widget) => filter.includes(widget.type)) : widgets),
map(widgets => search ? widgets.filter( map(widgets => search ? widgets.filter(
widget => ( widget => (
widget.title?.toLowerCase().includes(search.toLowerCase()) || widget.title?.toLowerCase().includes(search.toLowerCase()) ||

23
ui-ngx/src/app/modules/home/components/dashboard-page/widget-types-panel.component.html

@ -0,0 +1,23 @@
<!--
Copyright © 2016-2021 The Thingsboard Authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<div fxLayout="column" class="mat-content mat-padding">
<mat-checkbox style="padding-bottom: 8px;" [(ngModel)]="type.display" *ngFor="let type of types"
(ngModelChange)="update()">
{{ 'widget.' + type.type | translate }}
</mat-checkbox>
</div>

36
ui-ngx/src/app/modules/home/components/dashboard-page/widget-types-panel.component.scss

@ -0,0 +1,36 @@
/**
* Copyright © 2016-2021 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
:host {
width: 100%;
height: 100%;
min-width: 200px;
overflow: hidden;
background: #fff;
border-radius: 4px;
box-shadow:
0 7px 8px -4px rgba(0, 0, 0, .2),
0 13px 19px 2px rgba(0, 0, 0, .14),
0 5px 24px 4px rgba(0, 0, 0, .12);
.mat-content {
overflow: hidden;
background-color: #fff;
}
.mat-padding {
padding: 16px;
}
}

48
ui-ngx/src/app/modules/home/components/dashboard-page/widget-types-panel.component.ts

@ -0,0 +1,48 @@
///
/// Copyright © 2016-2021 The Thingsboard Authors
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
/// http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
import { Component, Inject, InjectionToken } from '@angular/core';
import { widgetType } from '@shared/models/widget.models';
export const DISPLAY_WIDGET_TYPES_PANEL_DATA = new InjectionToken<any>('DisplayWidgetTypesPanelData');
export interface WidgetTypes {
type: widgetType;
display: boolean;
}
export interface DisplayWidgetTypesPanelData {
types: WidgetTypes[];
typesUpdated: (columns: WidgetTypes[]) => void;
}
@Component({
selector: 'tb-widget-types-panel',
templateUrl: './widget-types-panel.component.html',
styleUrls: ['./widget-types-panel.component.scss']
})
export class DisplayWidgetTypesPanelComponent {
types: WidgetTypes[];
constructor(@Inject(DISPLAY_WIDGET_TYPES_PANEL_DATA) public data: DisplayWidgetTypesPanelData) {
this.types = this.data.types;
}
public update() {
this.data.typesUpdated(this.types);
}
}

6
ui-ngx/src/app/modules/home/components/details-panel.component.html

@ -19,10 +19,8 @@
<mat-toolbar class="details-toolbar" color="primary" [ngStyle]="{height: headerHeightPx+'px'}"> <mat-toolbar class="details-toolbar" color="primary" [ngStyle]="{height: headerHeightPx+'px'}">
<div class="mat-toolbar-tools" fxLayout="row" fxLayoutAlign="start center" style="height: 100%;"> <div class="mat-toolbar-tools" fxLayout="row" fxLayoutAlign="start center" style="height: 100%;">
<div class="mat-toolbar-tools tb-details-title-header" fxFlex fxLayout="column" fxLayoutAlign="start start"> <div class="mat-toolbar-tools tb-details-title-header" fxFlex fxLayout="column" fxLayoutAlign="start start">
<div class="tb-details-title" fxLayout="row" fxLayoutGap="8px" fxLayoutAlign="start center"> <div class="tb-details-title" fxLayout="row" fxLayoutAlign="start center">
<button class="tb-mat-28" mat-icon-button type="button" [fxHide]="!showBackStateIcon" (click)="onBackStateDetails()"> <ng-content select=".prefix-title-buttons"></ng-content>
<mat-icon>arrow_back</mat-icon>
</button>
<span>{{ headerTitle }}</span> <span>{{ headerTitle }}</span>
</div> </div>
<span class="tb-details-subtitle">{{ headerSubtitle }}</span> <span class="tb-details-subtitle">{{ headerSubtitle }}</span>

7
ui-ngx/src/app/modules/home/components/details-panel.component.ts

@ -32,7 +32,6 @@ export class DetailsPanelComponent extends PageComponent {
@Input() headerSubtitle = ''; @Input() headerSubtitle = '';
@Input() isReadOnly = false; @Input() isReadOnly = false;
@Input() isAlwaysEdit = false; @Input() isAlwaysEdit = false;
@Input() showBackStateIcon = false;
theFormValue: FormGroup; theFormValue: FormGroup;
@ -51,8 +50,6 @@ export class DetailsPanelComponent extends PageComponent {
toggleDetailsEditMode = new EventEmitter<boolean>(); toggleDetailsEditMode = new EventEmitter<boolean>();
@Output() @Output()
applyDetails = new EventEmitter<void>(); applyDetails = new EventEmitter<void>();
@Output()
backStateDetails = new EventEmitter<void>();
isEditValue = false; isEditValue = false;
@ -78,10 +75,6 @@ export class DetailsPanelComponent extends PageComponent {
this.closeDetails.emit(); this.closeDetails.emit();
} }
onBackStateDetails() {
this.backStateDetails.emit();
}
onToggleDetailsEditMode() { onToggleDetailsEditMode() {
if (!this.isAlwaysEdit) { if (!this.isAlwaysEdit) {
this.isEdit = !this.isEdit; this.isEdit = !this.isEdit;

7
ui-ngx/src/app/modules/home/components/home-components.module.ts

@ -132,6 +132,7 @@ import { ManageDashboardStatesDialogComponent } from '@home/components/dashboard
import { DashboardStateDialogComponent } from '@home/components/dashboard-page/states/dashboard-state-dialog.component'; import { DashboardStateDialogComponent } from '@home/components/dashboard-page/states/dashboard-state-dialog.component';
import { EmbedDashboardDialogComponent } from '@home/components/widget/dialog/embed-dashboard-dialog.component'; import { EmbedDashboardDialogComponent } from '@home/components/widget/dialog/embed-dashboard-dialog.component';
import { EMBED_DASHBOARD_DIALOG_TOKEN } from '@home/components/widget/dialog/embed-dashboard-dialog-token'; import { EMBED_DASHBOARD_DIALOG_TOKEN } from '@home/components/widget/dialog/embed-dashboard-dialog-token';
import { DisplayWidgetTypesPanelComponent } from '@home/components/dashboard-page/widget-types-panel.component';
@NgModule({ @NgModule({
declarations: declarations:
@ -244,7 +245,8 @@ import { EMBED_DASHBOARD_DIALOG_TOKEN } from '@home/components/widget/dialog/emb
DashboardSettingsDialogComponent, DashboardSettingsDialogComponent,
ManageDashboardStatesDialogComponent, ManageDashboardStatesDialogComponent,
DashboardStateDialogComponent, DashboardStateDialogComponent,
EmbedDashboardDialogComponent EmbedDashboardDialogComponent,
DisplayWidgetTypesPanelComponent
], ],
imports: [ imports: [
CommonModule, CommonModule,
@ -345,7 +347,8 @@ import { EMBED_DASHBOARD_DIALOG_TOKEN } from '@home/components/widget/dialog/emb
DashboardSettingsDialogComponent, DashboardSettingsDialogComponent,
ManageDashboardStatesDialogComponent, ManageDashboardStatesDialogComponent,
DashboardStateDialogComponent, DashboardStateDialogComponent,
EmbedDashboardDialogComponent EmbedDashboardDialogComponent,
DisplayWidgetTypesPanelComponent
], ],
providers: [ providers: [
WidgetComponentService, WidgetComponentService,

2
ui-ngx/src/app/shared/components/widgets-bundle-search.component.html

@ -18,7 +18,7 @@
<div class="input-wrapper" fxLayoutAlign="start center" fxLayoutGap="8px"> <div class="input-wrapper" fxLayoutAlign="start center" fxLayoutGap="8px">
<mat-icon>search</mat-icon> <mat-icon>search</mat-icon>
<input type="text" [(ngModel)]="searchText" (ngModelChange)="updateSearchText()" [placeholder]=placeholder> <input type="text" [(ngModel)]="searchText" (ngModelChange)="updateSearchText()" [placeholder]=placeholder>
<button mat-button *ngIf="searchText" mat-icon-button (click)="clear()"> <button mat-button type="button" *ngIf="searchText" mat-icon-button (click)="clear()">
<mat-icon>close</mat-icon> <mat-icon>close</mat-icon>
</button> </button>
</div> </div>

3
ui-ngx/src/assets/locale/locale.constant-en_US.json

@ -2265,7 +2265,8 @@
"no-data": "No data to display on widget", "no-data": "No data to display on widget",
"data-overflow": "Widget displays {{count}} out of {{total}} entities", "data-overflow": "Widget displays {{count}} out of {{total}} entities",
"alarm-data-overflow": "Widget displays alarms for {{allowedEntities}} (maximum allowed) entities out of {{totalEntities}} entities", "alarm-data-overflow": "Widget displays alarms for {{allowedEntities}} (maximum allowed) entities out of {{totalEntities}} entities",
"search": "Search widget" "search": "Search widget",
"filter": "Widget filter type"
}, },
"widget-action": { "widget-action": {
"header-button": "Widget header button", "header-button": "Widget header button",

3
ui-ngx/src/styles.scss

@ -753,6 +753,9 @@ mat-label {
&.tb-mat-20 { &.tb-mat-20 {
@include tb-mat-icon-size(20); @include tb-mat-icon-size(20);
} }
&.tb-mat-28 {
@include tb-mat-icon-size(28);
}
&.tb-mat-32 { &.tb-mat-32 {
@include tb-mat-icon-size(32); @include tb-mat-icon-size(32);
} }

Loading…
Cancel
Save