Browse Source

[3.0] minor fix (#2645)

* Improvement layout-setting setting from mobile/tablet view

* Fix EntityView not show type in translate

* Clear code and update tablet/mobile view

* Update tablet/mobile view

* Fix hide title and text-overflow

* Add support Safari

* Minor fix
pull/2663/head
Vladyslav 7 years ago
committed by GitHub
parent
commit
3103d0a726
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      ui-ngx/src/app/modules/home/components/alias/aliases-entity-select-panel.component.html
  2. 4
      ui-ngx/src/app/modules/home/components/alias/aliases-entity-select.component.html
  3. 10
      ui-ngx/src/app/modules/home/components/alias/entity-alias-dialog.component.html
  4. 14
      ui-ngx/src/app/modules/home/components/alias/entity-alias-dialog.component.ts
  5. 2
      ui-ngx/src/app/modules/home/components/alias/entity-alias-select.component.html
  6. 23
      ui-ngx/src/app/modules/home/components/alias/entity-alias-select.component.ts
  7. 38
      ui-ngx/src/app/modules/home/components/alias/entity-aliases-dialog.component.html
  8. 6
      ui-ngx/src/app/modules/home/components/alias/entity-aliases-dialog.component.scss
  9. 7
      ui-ngx/src/app/modules/home/components/alias/entity-aliases-dialog.component.ts
  10. 8
      ui-ngx/src/app/modules/home/components/attribute/add-attribute-dialog.component.html
  11. 8
      ui-ngx/src/app/modules/home/components/attribute/add-widget-to-dashboard-dialog.component.html
  12. 16
      ui-ngx/src/app/modules/home/components/attribute/add-widget-to-dashboard-dialog.component.ts
  13. 1
      ui-ngx/src/app/modules/home/components/dashboard/dashboard.component.html
  14. 8
      ui-ngx/src/app/modules/home/components/dashboard/dashboard.component.scss
  15. 8
      ui-ngx/src/app/modules/home/components/dashboard/layout-button.scss
  16. 18
      ui-ngx/src/app/modules/home/components/dashboard/select-target-layout-dialog.component.html
  17. 15
      ui-ngx/src/app/modules/home/components/dashboard/select-target-state-dialog.component.html
  18. 3
      ui-ngx/src/app/modules/home/components/dashboard/select-target-state-dialog.component.ts
  19. 2
      ui-ngx/src/app/modules/home/components/details-panel.component.html
  20. 2
      ui-ngx/src/app/modules/home/components/details-panel.component.scss
  21. 6
      ui-ngx/src/app/modules/home/components/entity/entity-filter-view.component.ts
  22. 12
      ui-ngx/src/app/modules/home/components/entity/entity-filter.component.html
  23. 60
      ui-ngx/src/app/modules/home/components/relation/relation-filters.component.html
  24. 24
      ui-ngx/src/app/modules/home/components/relation/relation-filters.component.scss
  25. 16
      ui-ngx/src/app/modules/home/components/relation/relation-filters.component.ts
  26. 4
      ui-ngx/src/app/modules/home/components/relation/relation-table.component.html
  27. 2
      ui-ngx/src/app/modules/home/components/widget/action/custom-action-pretty-editor.component.html
  28. 34
      ui-ngx/src/app/modules/home/components/widget/action/custom-action-pretty-editor.component.ts
  29. 4
      ui-ngx/src/app/modules/home/components/widget/action/custom-action-pretty-resources-tabs.component.html
  30. 7
      ui-ngx/src/app/modules/home/components/widget/action/custom-action-pretty-resources-tabs.component.ts
  31. 16
      ui-ngx/src/app/modules/home/components/widget/action/manage-widget-actions.component.html
  32. 15
      ui-ngx/src/app/modules/home/components/widget/action/manage-widget-actions.component.models.ts
  33. 19
      ui-ngx/src/app/modules/home/components/widget/action/manage-widget-actions.component.ts
  34. 20
      ui-ngx/src/app/modules/home/components/widget/action/widget-action-dialog.component.html
  35. 20
      ui-ngx/src/app/modules/home/components/widget/action/widget-action-dialog.component.scss
  36. 2
      ui-ngx/src/app/modules/home/components/widget/action/widget-action-dialog.component.ts
  37. 10
      ui-ngx/src/app/modules/home/components/widget/data-key-config-dialog.component.html
  38. 1
      ui-ngx/src/app/modules/home/components/widget/data-key-config-dialog.component.scss
  39. 21
      ui-ngx/src/app/modules/home/components/widget/data-key-config.component.html
  40. 22
      ui-ngx/src/app/modules/home/components/widget/data-key-config.component.scss
  41. 5
      ui-ngx/src/app/modules/home/components/widget/data-keys.component.scss
  42. 14
      ui-ngx/src/app/modules/home/components/widget/dialog/custom-dialog-container.component.ts
  43. 3
      ui-ngx/src/app/modules/home/components/widget/dialog/custom-dialog.component.ts
  44. 1
      ui-ngx/src/app/modules/home/components/widget/dynamic-widget.component.ts
  45. 4
      ui-ngx/src/app/modules/home/components/widget/lib/alarms-table-widget.component.html
  46. 4
      ui-ngx/src/app/modules/home/components/widget/lib/entities-table-widget.component.html
  47. 4
      ui-ngx/src/app/modules/home/components/widget/lib/timeseries-table-widget.component.html
  48. 162
      ui-ngx/src/app/modules/home/components/widget/widget-config.component.html
  49. 24
      ui-ngx/src/app/modules/home/components/widget/widget-config.component.scss
  50. 13
      ui-ngx/src/app/modules/home/pages/dashboard/add-widget-dialog.component.html
  51. 8
      ui-ngx/src/app/modules/home/pages/dashboard/add-widget-dialog.component.ts
  52. 24
      ui-ngx/src/app/modules/home/pages/dashboard/dashboard-page.component.html
  53. 20
      ui-ngx/src/app/modules/home/pages/dashboard/dashboard-settings-dialog.component.html
  54. 26
      ui-ngx/src/app/modules/home/pages/dashboard/dashboard-settings-dialog.component.scss
  55. 2
      ui-ngx/src/app/modules/home/pages/dashboard/dashboard-settings-dialog.component.ts
  56. 6
      ui-ngx/src/app/modules/home/pages/dashboard/dashboard-toolbar.component.html
  57. 2
      ui-ngx/src/app/modules/home/pages/dashboard/layout/dashboard-layout.component.ts
  58. 3
      ui-ngx/src/app/modules/home/pages/dashboard/layout/layout.models.ts
  59. 27
      ui-ngx/src/app/modules/home/pages/dashboard/layout/manage-dashboard-layouts-dialog.component.html
  60. 11
      ui-ngx/src/app/modules/home/pages/dashboard/layout/manage-dashboard-layouts-dialog.component.ts
  61. 10
      ui-ngx/src/app/modules/home/pages/dashboard/states/dashboard-state-dialog.component.html
  62. 4
      ui-ngx/src/app/modules/home/pages/dashboard/states/dashboard-state-dialog.component.ts
  63. 30
      ui-ngx/src/app/modules/home/pages/dashboard/states/manage-dashboard-states-dialog.component.html
  64. 8
      ui-ngx/src/app/modules/home/pages/dashboard/states/states-component.directive.ts
  65. 32
      ui-ngx/src/app/modules/home/pages/widget/widget-editor.component.html
  66. 7
      ui-ngx/src/app/modules/home/pages/widget/widget-editor.component.ts
  67. 6
      ui-ngx/src/app/shared/components/color-input.component.scss
  68. 22
      ui-ngx/src/app/shared/components/color-input.component.ts
  69. 31
      ui-ngx/src/app/shared/components/dashboard-autocomplete.component.ts
  70. 2
      ui-ngx/src/app/shared/components/dashboard-select.component.html
  71. 39
      ui-ngx/src/app/shared/components/entity/entity-type-list.component.ts
  72. 11
      ui-ngx/src/app/shared/components/fab-toolbar.component.ts
  73. 1
      ui-ngx/src/app/shared/components/json-form/react/json-form-checkbox.tsx
  74. 2
      ui-ngx/src/app/shared/components/material-icon-select.component.html
  75. 6
      ui-ngx/src/app/shared/components/material-icon-select.component.scss
  76. 24
      ui-ngx/src/app/shared/components/material-icon-select.component.ts
  77. 2
      ui-ngx/src/app/shared/components/relation/relation-type-autocomplete.component.html
  78. 28
      ui-ngx/src/app/shared/components/relation/relation-type-autocomplete.component.ts
  79. 1
      ui-ngx/src/styles.scss

2
ui-ngx/src/app/modules/home/components/alias/aliases-entity-select-panel.component.html

@ -19,7 +19,7 @@
<div fxLayout="row" *ngFor="let alias of entityAliasesInfo | keyvalue"> <div fxLayout="row" *ngFor="let alias of entityAliasesInfo | keyvalue">
<mat-form-field> <mat-form-field>
<mat-label>{{alias.value.alias}}</mat-label> <mat-label>{{alias.value.alias}}</mat-label>
<mat-select matInput [(ngModel)]="alias.value.selectedId" <mat-select [(ngModel)]="alias.value.selectedId"
(ngModelChange)="currentAliasEntityChanged(alias.key, alias.value.selectedId)"> (ngModelChange)="currentAliasEntityChanged(alias.key, alias.value.selectedId)">
<mat-option *ngFor="let resolvedEntity of alias.value.resolvedEntities" [value]="resolvedEntity.id"> <mat-option *ngFor="let resolvedEntity of alias.value.resolvedEntities" [value]="resolvedEntity.id">
{{resolvedEntity.name}} {{resolvedEntity.name}}

4
ui-ngx/src/app/modules/home/components/alias/aliases-entity-select.component.html

@ -16,14 +16,14 @@
--> -->
<section class="tb-aliases-entity-select" fxLayout="row" fxLayoutAlign="start center"> <section class="tb-aliases-entity-select" fxLayout="row" fxLayoutAlign="start center">
<button mat-button mat-icon-button <button mat-icon-button
cdkOverlayOrigin #aliasEntitySelectPanelOrigin="cdkOverlayOrigin" cdkOverlayOrigin #aliasEntitySelectPanelOrigin="cdkOverlayOrigin"
(click)="openEditMode()" (click)="openEditMode()"
matTooltip="{{ 'entity.select-entities' | translate }}" matTooltip="{{ 'entity.select-entities' | translate }}"
[matTooltipPosition]="tooltipPosition"> [matTooltipPosition]="tooltipPosition">
<mat-icon class="material-icons">devices_other</mat-icon> <mat-icon class="material-icons">devices_other</mat-icon>
</button> </button>
<span fxHide.xs fxHide.sm fxHide.md <span fxHide.lt-lg
(click)="openEditMode()" (click)="openEditMode()"
matTooltip="{{ 'entity.select-entities' | translate }}" matTooltip="{{ 'entity.select-entities' | translate }}"
[matTooltipPosition]="tooltipPosition"> [matTooltipPosition]="tooltipPosition">

10
ui-ngx/src/app/modules/home/components/alias/entity-alias-dialog.component.html

@ -15,11 +15,11 @@
limitations under the License. limitations under the License.
--> -->
<form #entityAliasForm="ngForm" [formGroup]="entityAliasFormGroup" (ngSubmit)="save()" style="min-width: 550px;"> <form #entityAliasForm="ngForm" [formGroup]="entityAliasFormGroup" (ngSubmit)="save()" style="min-width: 480px;">
<mat-toolbar color="primary"> <mat-toolbar color="primary">
<h2>{{ (isAdd ? 'alias.add' : 'alias.edit') | translate }}</h2> <h2>{{ (isAdd ? 'alias.add' : 'alias.edit') | translate }}</h2>
<span fxFlex></span> <span fxFlex></span>
<button mat-button mat-icon-button <button mat-icon-button
(click)="cancel()" (click)="cancel()"
type="button"> type="button">
<mat-icon class="material-icons">close</mat-icon> <mat-icon class="material-icons">close</mat-icon>
@ -58,15 +58,13 @@
</div> </div>
</fieldset> </fieldset>
</div> </div>
<div mat-dialog-actions fxLayout="row"> <div mat-dialog-actions fxLayoutAlign="end center">
<span fxFlex></span> <button mat-raised-button color="primary"
<button mat-button mat-raised-button color="primary"
type="submit" type="submit"
[disabled]="(isLoading$ | async) || entityAliasFormGroup.invalid || !entityAliasFormGroup.dirty"> [disabled]="(isLoading$ | async) || entityAliasFormGroup.invalid || !entityAliasFormGroup.dirty">
{{ (isAdd ? 'action.add' : 'action.save') | translate }} {{ (isAdd ? 'action.add' : 'action.save') | translate }}
</button> </button>
<button mat-button color="primary" <button mat-button color="primary"
style="margin-right: 20px;"
type="button" type="button"
[disabled]="(isLoading$ | async)" [disabled]="(isLoading$ | async)"
(click)="cancel()" cdkFocusInitial> (click)="cancel()" cdkFocusInitial>

14
ui-ngx/src/app/modules/home/components/alias/entity-alias-dialog.component.ts

@ -20,26 +20,22 @@ import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { Store } from '@ngrx/store'; import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state'; import { AppState } from '@core/core.state';
import { import {
AbstractControl,
FormArray,
FormBuilder, FormBuilder,
FormControl, FormControl,
FormGroup, FormGroup,
FormGroupDirective, FormGroupDirective,
NgForm, Validators, ValidatorFn NgForm,
ValidatorFn,
Validators
} from '@angular/forms'; } from '@angular/forms';
import { Router } from '@angular/router'; import { Router } from '@angular/router';
import { DialogComponent } from '@app/shared/components/dialog.component'; import { DialogComponent } from '@app/shared/components/dialog.component';
import { AttributeData } from '@shared/models/telemetry/telemetry.models'; import { EntityAlias, EntityAliases } from '@shared/models/alias.models';
import { EntityAlias, EntityAliases, EntityAliasFilter } from '@shared/models/alias.models';
import { DatasourceType, Widget, widgetType } from '@shared/models/widget.models';
import { AliasEntityType, EntityType } from '@shared/models/entity-type.models'; import { AliasEntityType, EntityType } from '@shared/models/entity-type.models';
import { UtilsService } from '@core/services/utils.service'; import { UtilsService } from '@core/services/utils.service';
import { TranslateService } from '@ngx-translate/core'; import { TranslateService } from '@ngx-translate/core';
import { ActionNotificationShow } from '@core/notification/notification.actions';
import { DialogService } from '@core/services/dialog.service';
import { EntityService } from '@core/http/entity.service'; import { EntityService } from '@core/http/entity.service';
import { Observable, of } from 'rxjs'; import { Observable } from 'rxjs';
export interface EntityAliasDialogData { export interface EntityAliasDialogData {
isAdd: boolean; isAdd: boolean;

2
ui-ngx/src/app/modules/home/components/alias/entity-alias-select.component.html

@ -27,7 +27,7 @@
[matAutocomplete]="entityAliasAutocomplete"> [matAutocomplete]="entityAliasAutocomplete">
<button *ngIf="selectEntityAliasFormGroup.get('entityAlias').value && !disabled" <button *ngIf="selectEntityAliasFormGroup.get('entityAlias').value && !disabled"
type="button" type="button"
matSuffix mat-button mat-icon-button aria-label="Clear" matSuffix mat-icon-button aria-label="Clear"
(click)="clear()"> (click)="clear()">
<mat-icon class="material-icons">close</mat-icon> <mat-icon class="material-icons">close</mat-icon>
</button> </button>

23
ui-ngx/src/app/modules/home/components/alias/entity-alias-select.component.ts

@ -21,24 +21,23 @@ import {
FormControl, FormControl,
FormGroup, FormGroup,
FormGroupDirective, FormGroupDirective,
NG_VALUE_ACCESSOR, NgForm NG_VALUE_ACCESSOR,
NgForm
} from '@angular/forms'; } from '@angular/forms';
import { Observable, of } from 'rxjs'; import { Observable, of } from 'rxjs';
import { map, mergeMap, startWith, tap, share, filter } from 'rxjs/operators'; import { map, mergeMap, share, tap } from 'rxjs/operators';
import {Store} from '@ngrx/store'; import { Store } from '@ngrx/store';
import {AppState} from '@app/core/core.state'; import { AppState } from '@app/core/core.state';
import {TranslateService} from '@ngx-translate/core'; import { TranslateService } from '@ngx-translate/core';
import {AliasEntityType, EntityType} from '@shared/models/entity-type.models'; import { EntityType } from '@shared/models/entity-type.models';
import {BaseData} from '@shared/models/base-data'; import { EntityService } from '@core/http/entity.service';
import {EntityId} from '@shared/models/id/entity-id'; import { coerceBooleanProperty } from '@angular/cdk/coercion';
import {EntityService} from '@core/http/entity.service';
import {coerceBooleanProperty} from '@angular/cdk/coercion';
import { EntityAlias } from '@shared/models/alias.models'; import { EntityAlias } from '@shared/models/alias.models';
import { IAliasController } from '@core/api/widget-api.models'; import { IAliasController } from '@core/api/widget-api.models';
import { TruncatePipe } from '@shared/pipe/truncate.pipe'; import { TruncatePipe } from '@shared/pipe/truncate.pipe';
import { MatAutocomplete, MatAutocompleteSelectedEvent, MatAutocompleteTrigger } from '@angular/material/autocomplete'; import { MatAutocomplete, MatAutocompleteTrigger } from '@angular/material/autocomplete';
import { EntityAliasSelectCallbacks } from './entity-alias-select.component.models'; import { EntityAliasSelectCallbacks } from './entity-alias-select.component.models';
import {ENTER} from '@angular/cdk/keycodes'; import { ENTER } from '@angular/cdk/keycodes';
import { ErrorStateMatcher } from '@angular/material/core'; import { ErrorStateMatcher } from '@angular/material/core';
@Component({ @Component({

38
ui-ngx/src/app/modules/home/components/alias/entity-aliases-dialog.component.html

@ -16,10 +16,10 @@
--> -->
<form #entityAliasesForm="ngForm" [formGroup]="entityAliasesFormGroup" (ngSubmit)="save()" style="width: 700px;"> <form #entityAliasesForm="ngForm" [formGroup]="entityAliasesFormGroup" (ngSubmit)="save()" style="width: 700px;">
<mat-toolbar fxLayout="row" color="primary"> <mat-toolbar color="primary">
<h2>{{ title | translate }}</h2> <h2>{{ title | translate }}</h2>
<span fxFlex></span> <span fxFlex></span>
<button mat-button mat-icon-button <button mat-icon-button
(click)="cancel()" (click)="cancel()"
type="button"> type="button">
<mat-icon class="material-icons">close</mat-icon> <mat-icon class="material-icons">close</mat-icon>
@ -28,18 +28,18 @@
<mat-progress-bar color="warn" mode="indeterminate" *ngIf="isLoading$ | async"> <mat-progress-bar color="warn" mode="indeterminate" *ngIf="isLoading$ | async">
</mat-progress-bar> </mat-progress-bar>
<div style="height: 4px;" *ngIf="!(isLoading$ | async)"></div> <div style="height: 4px;" *ngIf="!(isLoading$ | async)"></div>
<div class="tb-aliases-header" fxFlex fxLayout="row" fxLayoutAlign="start center">
<span fxFlex="5"></span>
<div fxFlex="95" fxLayout="row" fxLayoutAlign="start center">
<span class="tb-header-label" translate fxFlex="150px">alias.name</span>
<span class="tb-header-label" translate fxFlex style="padding-left: 10px;">alias.entity-filter</span>
<span class="tb-header-label" translate fxFlex="120px" style="padding-left: 10px;">alias.resolve-multiple</span>
<span style="min-width: 80px;"></span>
</div>
</div>
<mat-divider></mat-divider>
<div mat-dialog-content> <div mat-dialog-content>
<div class="tb-aliases-header" fxLayout="row" fxLayoutAlign="start center">
<span fxFlex="5"></span>
<div fxFlex="95" fxLayout="row" fxLayoutAlign="start center">
<span class="tb-header-label" translate fxFlex="150px">alias.name</span>
<span class="tb-header-label" translate fxFlex style="padding-left: 10px;">alias.entity-filter</span>
<span class="tb-header-label" translate fxFlex="120px" style="padding-left: 10px;">alias.resolve-multiple</span>
<span style="min-width: 80px;"></span>
</div>
</div>
<fieldset [disabled]="isLoading$ | async"> <fieldset [disabled]="isLoading$ | async">
<mat-divider></mat-divider>
<div fxFlex fxLayout="row" fxLayoutAlign="start center" <div fxFlex fxLayout="row" fxLayoutAlign="start center"
formArrayName="entityAliases" formArrayName="entityAliases"
*ngFor="let entityAliasControl of entityAliasesFormArray().controls; let $index = index"> *ngFor="let entityAliasControl of entityAliasesFormArray().controls; let $index = index">
@ -63,7 +63,7 @@
</mat-slide-toggle> </mat-slide-toggle>
</section> </section>
<button [disabled]="isLoading$ | async" <button [disabled]="isLoading$ | async"
mat-button mat-icon-button color="primary" mat-icon-button color="primary"
style="min-width: 40px;" style="min-width: 40px;"
type="button" type="button"
(click)="editAlias($index)" (click)="editAlias($index)"
@ -72,7 +72,7 @@
<mat-icon>edit</mat-icon> <mat-icon>edit</mat-icon>
</button> </button>
<button [disabled]="isLoading$ | async" <button [disabled]="isLoading$ | async"
mat-button mat-icon-button color="primary" mat-icon-button color="primary"
style="min-width: 40px;" style="min-width: 40px;"
type="button" type="button"
(click)="removeAlias($index)" (click)="removeAlias($index)"
@ -84,8 +84,8 @@
</div> </div>
</fieldset> </fieldset>
</div> </div>
<div mat-dialog-actions fxLayout="row"> <div mat-dialog-actions>
<button mat-button mat-raised-button color="primary" <button mat-raised-button color="primary"
type="button" type="button"
(click)="addAlias()" (click)="addAlias()"
[fxShow]="!disableAdd" [fxShow]="!disableAdd"
@ -95,16 +95,16 @@
{{ 'alias.add' | translate }} {{ 'alias.add' | translate }}
</button> </button>
<span fxFlex></span> <span fxFlex></span>
<button mat-button mat-raised-button color="primary" <button mat-raised-button color="primary"
type="submit" type="submit"
[disabled]="(isLoading$ | async) || entityAliasesFormGroup.invalid || !entityAliasesFormGroup.dirty"> [disabled]="(isLoading$ | async) || entityAliasesFormGroup.invalid || !entityAliasesFormGroup.dirty">
{{ 'action.save' | translate }} {{ 'action.save' | translate }}
</button> </button>
<button mat-button color="primary" <button mat-button color="primary"
style="margin-right: 20px;"
type="button" type="button"
[disabled]="(isLoading$ | async)" [disabled]="(isLoading$ | async)"
(click)="cancel()" cdkFocusInitial> (click)="cancel()"
cdkFocusInitial>
{{ 'action.cancel' | translate }} {{ 'action.cancel' | translate }}
</button> </button>
</div> </div>

6
ui-ngx/src/app/modules/home/components/alias/entity-aliases-dialog.component.scss

@ -17,7 +17,7 @@
.tb-aliases-header { .tb-aliases-header {
min-height: 40px; min-height: 40px;
padding: 0 34px 0 34px; padding: 0 11px;
margin: 5px; margin: 5px;
.tb-header-label { .tb-header-label {
@ -26,6 +26,10 @@
} }
} }
mat-divider{
margin: -1px -24px;
}
.tb-alias { .tb-alias {
padding: 0 0 0 10px; padding: 0 0 0 10px;
margin: 5px; margin: 5px;

7
ui-ngx/src/app/modules/home/components/alias/entity-aliases-dialog.component.ts

@ -16,7 +16,7 @@
import { Component, Inject, OnInit, SkipSelf } from '@angular/core'; import { Component, Inject, OnInit, SkipSelf } from '@angular/core';
import { ErrorStateMatcher } from '@angular/material/core'; import { ErrorStateMatcher } from '@angular/material/core';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; import { MAT_DIALOG_DATA, MatDialog, MatDialogRef } from '@angular/material/dialog';
import { Store } from '@ngrx/store'; import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state'; import { AppState } from '@core/core.state';
import { import {
@ -26,11 +26,11 @@ import {
FormControl, FormControl,
FormGroup, FormGroup,
FormGroupDirective, FormGroupDirective,
NgForm, Validators NgForm,
Validators
} from '@angular/forms'; } from '@angular/forms';
import { Router } from '@angular/router'; import { Router } from '@angular/router';
import { DialogComponent } from '@app/shared/components/dialog.component'; import { DialogComponent } from '@app/shared/components/dialog.component';
import { AttributeData } from '@shared/models/telemetry/telemetry.models';
import { EntityAlias, EntityAliases, EntityAliasFilter } from '@shared/models/alias.models'; import { EntityAlias, EntityAliases, EntityAliasFilter } from '@shared/models/alias.models';
import { DatasourceType, Widget, widgetType } from '@shared/models/widget.models'; import { DatasourceType, Widget, widgetType } from '@shared/models/widget.models';
import { AliasEntityType, EntityType } from '@shared/models/entity-type.models'; import { AliasEntityType, EntityType } from '@shared/models/entity-type.models';
@ -39,7 +39,6 @@ import { TranslateService } from '@ngx-translate/core';
import { ActionNotificationShow } from '@core/notification/notification.actions'; import { ActionNotificationShow } from '@core/notification/notification.actions';
import { DialogService } from '@core/services/dialog.service'; import { DialogService } from '@core/services/dialog.service';
import { deepClone, isUndefined } from '@core/utils'; import { deepClone, isUndefined } from '@core/utils';
import { MatDialog } from '@angular/material/dialog';
import { EntityAliasDialogComponent, EntityAliasDialogData } from './entity-alias-dialog.component'; import { EntityAliasDialogComponent, EntityAliasDialogData } from './entity-alias-dialog.component';
export interface EntityAliasesDialogData { export interface EntityAliasesDialogData {

8
ui-ngx/src/app/modules/home/components/attribute/add-attribute-dialog.component.html

@ -16,7 +16,7 @@
--> -->
<form [formGroup]="attributeFormGroup" (ngSubmit)="add()" style="min-width: 400px;"> <form [formGroup]="attributeFormGroup" (ngSubmit)="add()" style="min-width: 400px;">
<mat-toolbar fxLayout="row" color="primary"> <mat-toolbar color="primary">
<h2>{{ 'attribute.add' | translate }}</h2> <h2>{{ 'attribute.add' | translate }}</h2>
<span fxFlex></span> <span fxFlex></span>
<button mat-button mat-icon-button <button mat-button mat-icon-button
@ -43,15 +43,13 @@
</tb-value-input> </tb-value-input>
</fieldset> </fieldset>
</div> </div>
<div mat-dialog-actions fxLayout="row"> <div mat-dialog-actions fxLayoutAlign="end center">
<span fxFlex></span> <button mat-raised-button color="primary"
<button mat-button mat-raised-button color="primary"
type="submit" type="submit"
[disabled]="(isLoading$ | async) || attributeFormGroup.invalid || !attributeFormGroup.dirty"> [disabled]="(isLoading$ | async) || attributeFormGroup.invalid || !attributeFormGroup.dirty">
{{ 'action.add' | translate }} {{ 'action.add' | translate }}
</button> </button>
<button mat-button color="primary" <button mat-button color="primary"
style="margin-right: 20px;"
type="button" type="button"
[disabled]="(isLoading$ | async)" [disabled]="(isLoading$ | async)"
(click)="cancel()" cdkFocusInitial> (click)="cancel()" cdkFocusInitial>

8
ui-ngx/src/app/modules/home/components/attribute/add-widget-to-dashboard-dialog.component.html

@ -16,7 +16,7 @@
--> -->
<form #addWidgetForm="ngForm" [formGroup]="addWidgetFormGroup" (ngSubmit)="add()" style="min-width: 400px;"> <form #addWidgetForm="ngForm" [formGroup]="addWidgetFormGroup" (ngSubmit)="add()" style="min-width: 400px;">
<mat-toolbar fxLayout="row" color="primary"> <mat-toolbar color="primary">
<h2 translate>attribute.add-widget-to-dashboard</h2> <h2 translate>attribute.add-widget-to-dashboard</h2>
<span fxFlex></span> <span fxFlex></span>
<button mat-button mat-icon-button <button mat-button mat-icon-button
@ -55,19 +55,17 @@
</mat-radio-group> </mat-radio-group>
</fieldset> </fieldset>
</div> </div>
<div mat-dialog-actions fxLayout="row"> <div mat-dialog-actions fxLayoutAlign="end center">
<span fxFlex></span>
<mat-checkbox formControlName="openDashboard" <mat-checkbox formControlName="openDashboard"
style="margin-bottom: 0px; padding-right: 20px;"> style="margin-bottom: 0px; padding-right: 20px;">
{{ 'dashboard.open-dashboard' | translate }} {{ 'dashboard.open-dashboard' | translate }}
</mat-checkbox> </mat-checkbox>
<button mat-button mat-raised-button color="primary" <button mat-raised-button color="primary"
type="submit" type="submit"
[disabled]="(isLoading$ | async) || addWidgetFormGroup.invalid || !addWidgetFormGroup.dirty"> [disabled]="(isLoading$ | async) || addWidgetFormGroup.invalid || !addWidgetFormGroup.dirty">
{{ 'action.add' | translate }} {{ 'action.add' | translate }}
</button> </button>
<button mat-button color="primary" <button mat-button color="primary"
style="margin-right: 20px;"
type="button" type="button"
[disabled]="(isLoading$ | async)" [disabled]="(isLoading$ | async)"
(click)="cancel()" cdkFocusInitial> (click)="cancel()" cdkFocusInitial>

16
ui-ngx/src/app/modules/home/components/attribute/add-widget-to-dashboard-dialog.component.ts

@ -16,34 +16,26 @@
import { Component, Inject, OnInit, SkipSelf } from '@angular/core'; import { Component, Inject, OnInit, SkipSelf } from '@angular/core';
import { ErrorStateMatcher } from '@angular/material/core'; import { ErrorStateMatcher } from '@angular/material/core';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; import { MAT_DIALOG_DATA, MatDialog, MatDialogRef } from '@angular/material/dialog';
import { Store } from '@ngrx/store'; import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state'; import { AppState } from '@core/core.state';
import { FormBuilder, FormControl, FormGroup, FormGroupDirective, NgForm, Validators } from '@angular/forms'; import { FormBuilder, FormControl, FormGroup, FormGroupDirective, NgForm, Validators } from '@angular/forms';
import { Router } from '@angular/router'; import { Router } from '@angular/router';
import { DialogComponent } from '@app/shared/components/dialog.component'; import { DialogComponent } from '@app/shared/components/dialog.component';
import { UtilsService } from '@core/services/utils.service'; import { UtilsService } from '@core/services/utils.service';
import { TranslateService } from '@ngx-translate/core'; import { Dashboard, DashboardLayoutId } from '@app/shared/models/dashboard.models';
import { import { objToBase64 } from '@core/utils';
DashboardLayoutId,
DashboardSettings,
GridSettings,
StateControllerId,
Dashboard
} from '@app/shared/models/dashboard.models';
import { isUndefined, objToBase64 } from '@core/utils';
import { DashboardUtilsService } from '@core/services/dashboard-utils.service'; import { DashboardUtilsService } from '@core/services/dashboard-utils.service';
import { EntityId } from '@app/shared/models/id/entity-id'; import { EntityId } from '@app/shared/models/id/entity-id';
import { Widget } from '@app/shared/models/widget.models'; import { Widget } from '@app/shared/models/widget.models';
import { DashboardService } from '@core/http/dashboard.service'; import { DashboardService } from '@core/http/dashboard.service';
import { forkJoin, Observable, of } from 'rxjs'; import { forkJoin, Observable, of } from 'rxjs';
import { SelectTargetLayoutDialogComponent } from '@home/components/dashboard/select-target-layout-dialog.component'; import { SelectTargetLayoutDialogComponent } from '@home/components/dashboard/select-target-layout-dialog.component';
import { MatDialog } from '@angular/material/dialog';
import { import {
SelectTargetStateDialogComponent, SelectTargetStateDialogComponent,
SelectTargetStateDialogData SelectTargetStateDialogData
} from '@home/components/dashboard/select-target-state-dialog.component'; } from '@home/components/dashboard/select-target-state-dialog.component';
import { mergeMap, map } from 'rxjs/operators'; import { mergeMap } from 'rxjs/operators';
import { AliasesInfo } from '@shared/models/alias.models'; import { AliasesInfo } from '@shared/models/alias.models';
import { ItemBufferService } from '@core/services/item-buffer.service'; import { ItemBufferService } from '@core/services/item-buffer.service';
import { StateObject } from '@core/api/widget-api.models'; import { StateObject } from '@core/api/widget-api.models';

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

@ -83,6 +83,7 @@
<div fxLayout="row" fxLayoutAlign="space-between start"> <div fxLayout="row" fxLayoutAlign="space-between start">
<div class="tb-widget-title" fxLayout="column" fxLayoutAlign="center start" [fxShow]="widget.showWidgetTitlePanel"> <div class="tb-widget-title" fxLayout="column" fxLayoutAlign="center start" [fxShow]="widget.showWidgetTitlePanel">
<span [fxShow]="widget.showTitle" <span [fxShow]="widget.showTitle"
[ngClass]="{'single-row': widget.hasTimewindow}"
[ngStyle]="widget.titleStyle" [ngStyle]="widget.titleStyle"
[matTooltip]="widget.titleTooltip" [matTooltip]="widget.titleTooltip"
matTooltipClass="tb-tooltip-multiline" matTooltipClass="tb-tooltip-multiline"

8
ui-ngx/src/app/modules/home/components/dashboard/dashboard.component.scss

@ -76,6 +76,7 @@ div.tb-widget {
tb-timewindow { tb-timewindow {
font-size: 14px; font-size: 14px;
opacity: .85; opacity: .85;
margin: 0;
} }
.title { .title {
@ -85,6 +86,13 @@ div.tb-widget {
line-height: 24px; line-height: 24px;
letter-spacing: .01em; letter-spacing: .01em;
margin: 0; margin: 0;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
&.single-row{
-webkit-line-clamp: 1;
}
} }
} }

8
ui-ngx/src/app/modules/home/components/dashboard/layout-button.scss

@ -13,13 +13,15 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
:host ::ng-deep { :host {
button.tb-layout-button { button.tb-layout-button {
width: 100%; width: 100%;
max-width: 240px;
height: 100%; height: 100%;
padding: 40px 20px;
}
&::ng-deep {
.mat-button-wrapper { .mat-button-wrapper {
padding: 40px;
line-height: 18px; line-height: 18px;
span { span {
font-size: 18px; font-size: 18px;

18
ui-ngx/src/app/modules/home/components/dashboard/select-target-layout-dialog.component.html

@ -16,10 +16,10 @@
--> -->
<form #widgetForm="ngForm"> <form #widgetForm="ngForm">
<mat-toolbar fxLayout="row" color="primary"> <mat-toolbar color="primary">
<h2 translate>layout.select</h2> <h2 translate>layout.select</h2>
<span fxFlex></span> <span fxFlex></span>
<button mat-button mat-icon-button <button mat-icon-button
(click)="cancel()" (click)="cancel()"
type="button"> type="button">
<mat-icon class="material-icons">close</mat-icon> <mat-icon class="material-icons">close</mat-icon>
@ -30,16 +30,18 @@
<div mat-dialog-content> <div mat-dialog-content>
<fieldset [disabled]="isLoading$ | async" fxLayout="column" fxLayoutGap="8px"> <fieldset [disabled]="isLoading$ | async" fxLayout="column" fxLayoutGap="8px">
<div fxLayout="row" fxLayoutAlign="start center" fxLayoutGap="8px"> <div fxLayout="row" fxLayoutAlign="start center" fxLayoutGap="8px">
<button fxFlex fxLayout="column" <button fxFlex
type="button" mat-button mat-raised-button color="primary" mat-raised-button color="primary"
type="button"
class="tb-layout-button" class="tb-layout-button"
(click)="selectLayout('main')"> (click)="selectLayout('main')">
<span translate>layout.main</span> <span translate>layout.main</span>
</button> </button>
<button fxFlex fxLayout="column" <button fxFlex
type="button" mat-button mat-raised-button color="primary" mat-raised-button color="primary"
type="button"
class="tb-layout-button" class="tb-layout-button"
(click)="selectLayout('right')"> (click)="selectLayout('right')">
<span translate>layout.right</span> <span translate>layout.right</span>
</button> </button>
</div> </div>

15
ui-ngx/src/app/modules/home/components/dashboard/select-target-state-dialog.component.html

@ -16,10 +16,10 @@
--> -->
<form #stateForm="ngForm" [formGroup]="stateFormGroup" (ngSubmit)="save()"> <form #stateForm="ngForm" [formGroup]="stateFormGroup" (ngSubmit)="save()">
<mat-toolbar fxLayout="row" color="primary"> <mat-toolbar color="primary">
<h2 translate>dashboard.select-state</h2> <h2 translate>dashboard.select-state</h2>
<span fxFlex></span> <span fxFlex></span>
<button mat-button mat-icon-button <button mat-icon-button
(click)="cancel()" (click)="cancel()"
type="button"> type="button">
<mat-icon class="material-icons">close</mat-icon> <mat-icon class="material-icons">close</mat-icon>
@ -31,7 +31,7 @@
<fieldset [disabled]="isLoading$ | async" fxLayout="column"> <fieldset [disabled]="isLoading$ | async" fxLayout="column">
<mat-form-field class="mat-block"> <mat-form-field class="mat-block">
<mat-label translate>dashboard.state</mat-label> <mat-label translate>dashboard.state</mat-label>
<mat-select required matInput formControlName="stateId"> <mat-select required formControlName="stateId">
<mat-option *ngFor="let stateItem of states | keyvalue" [value]="stateItem.key"> <mat-option *ngFor="let stateItem of states | keyvalue" [value]="stateItem.key">
{{ stateItem.value.name }} {{ stateItem.value.name }}
</mat-option> </mat-option>
@ -39,18 +39,17 @@
</mat-form-field> </mat-form-field>
</fieldset> </fieldset>
</div> </div>
<div mat-dialog-actions fxLayout="row"> <div mat-dialog-actions fxLayoutAlign="end center">
<span fxFlex></span> <button mat-raised-button color="primary"
<button mat-button mat-raised-button color="primary"
type="submit" type="submit"
[disabled]="(isLoading$ | async) || stateFormGroup.invalid"> [disabled]="(isLoading$ | async) || stateFormGroup.invalid">
{{ 'action.select' | translate }} {{ 'action.select' | translate }}
</button> </button>
<button mat-button color="primary" <button mat-button color="primary"
style="margin-right: 20px;"
type="button" type="button"
[disabled]="(isLoading$ | async)" [disabled]="(isLoading$ | async)"
(click)="cancel()" cdkFocusInitial> (click)="cancel()"
cdkFocusInitial>
{{ 'action.cancel' | translate }} {{ 'action.cancel' | translate }}
</button> </button>
</div> </div>

3
ui-ngx/src/app/modules/home/components/dashboard/select-target-state-dialog.component.ts

@ -22,11 +22,8 @@ import { AppState } from '@core/core.state';
import { FormBuilder, FormControl, FormGroup, FormGroupDirective, NgForm, Validators } from '@angular/forms'; import { FormBuilder, FormControl, FormGroup, FormGroupDirective, NgForm, Validators } from '@angular/forms';
import { Router } from '@angular/router'; import { Router } from '@angular/router';
import { DialogComponent } from '@app/shared/components/dialog.component'; import { DialogComponent } from '@app/shared/components/dialog.component';
import { UtilsService } from '@core/services/utils.service';
import { TranslateService } from '@ngx-translate/core';
import { DashboardState } from '@app/shared/models/dashboard.models'; import { DashboardState } from '@app/shared/models/dashboard.models';
import { DashboardUtilsService } from '@core/services/dashboard-utils.service'; import { DashboardUtilsService } from '@core/services/dashboard-utils.service';
import { DashboardService } from '@core/http/dashboard.service';
export interface SelectTargetStateDialogData { export interface SelectTargetStateDialogData {
states: {[id: string]: DashboardState }; states: {[id: string]: DashboardState };

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

@ -17,7 +17,7 @@
--> -->
<header> <header>
<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" fxFlex 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">
<span class="tb-details-title">{{ headerTitle }}</span> <span class="tb-details-title">{{ headerTitle }}</span>
<span class="tb-details-subtitle">{{ headerSubtitle }}</span> <span class="tb-details-subtitle">{{ headerSubtitle }}</span>

2
ui-ngx/src/app/modules/home/components/details-panel.component.scss

@ -45,7 +45,7 @@
white-space: nowrap; white-space: nowrap;
@media #{$mat-gt-sm} { @media #{$mat-gt-sm} {
font-size: 1.6rem; font-size: 1.5rem;
} }
} }

6
ui-ngx/src/app/modules/home/components/entity/entity-filter-view.component.ts

@ -102,14 +102,14 @@ export class EntityFilterViewComponent implements ControlValueAccessor {
} }
break; break;
case AliasFilterType.entityViewType: case AliasFilterType.entityViewType:
const entityViewType = this.filter.entityViewType; const entityView = this.filter.entityViewType;
prefix = this.filter.entityViewNameFilter; prefix = this.filter.entityViewNameFilter;
if (prefix && prefix.length) { if (prefix && prefix.length) {
this.filterDisplayValue = this.translate.instant('alias.filter-type-entity-view-type-and-name-description', this.filterDisplayValue = this.translate.instant('alias.filter-type-entity-view-type-and-name-description',
{entityViewType, prefix}); {entityView, prefix});
} else { } else {
this.filterDisplayValue = this.translate.instant('alias.filter-type-entity-view-type-description', this.filterDisplayValue = this.translate.instant('alias.filter-type-entity-view-type-description',
{entityViewType}); {entityView});
} }
break; break;
case AliasFilterType.relationsQuery: case AliasFilterType.relationsQuery:

12
ui-ngx/src/app/modules/home/components/entity/entity-filter.component.html

@ -141,10 +141,10 @@
<label class="tb-small root-state-entity-label" translate>alias.last-level-relation</label> <label class="tb-small root-state-entity-label" translate>alias.last-level-relation</label>
</section> </section>
</div> </div>
<div fxFlex fxLayoutGap="8px" fxLayout="row"> <div fxFlex fxLayoutGap="8px" fxLayout="row" fxLayout.xs="column">
<mat-form-field class="mat-block" style="min-width: 100px;"> <mat-form-field class="mat-block" style="min-width: 100px;">
<mat-label translate>relation.direction</mat-label> <mat-label translate>relation.direction</mat-label>
<mat-select required matInput formControlName="direction"> <mat-select required formControlName="direction">
<mat-option *ngFor="let type of directionTypes" [value]="type"> <mat-option *ngFor="let type of directionTypes" [value]="type">
{{ directionTypeTranslations.get(directionTypeEnum[type]) | translate }} {{ directionTypeTranslations.get(directionTypeEnum[type]) | translate }}
</mat-option> </mat-option>
@ -172,7 +172,7 @@
entityFilterFormGroup.get('type').value === aliasFilterType.entityViewSearchQuery ? entityFilterFormGroup.get('type').value === aliasFilterType.entityViewSearchQuery ?
entityFilterFormGroup.get('type').value : ''"> entityFilterFormGroup.get('type').value : ''">
<label class="tb-small">{{ 'alias.root-entity' | translate }}</label> <label class="tb-small">{{ 'alias.root-entity' | translate }}</label>
<section class="tb-root-state-entity-switch" fxLayout="row" fxLayoutAlign="start center" style="padding-left: 0px;"> <section class="tb-root-state-entity-switch" fxLayout="row" fxLayoutAlign="start center" style="padding-left: 0;">
<mat-slide-toggle class="root-state-entity-switch" <mat-slide-toggle class="root-state-entity-switch"
formControlName="rootStateEntity"> formControlName="rootStateEntity">
</mat-slide-toggle> </mat-slide-toggle>
@ -200,17 +200,17 @@
</div> </div>
</div> </div>
<div fxFlex fxLayout="row"> <div fxFlex fxLayout="row">
<section class="tb-root-state-entity-switch" fxLayout="row" fxLayoutAlign="start center" style="padding-left: 0px;"> <section class="tb-root-state-entity-switch" fxLayout="row" fxLayoutAlign="start center" style="padding-left: 0;">
<mat-slide-toggle class="root-state-entity-switch" <mat-slide-toggle class="root-state-entity-switch"
formControlName="fetchLastLevelOnly"> formControlName="fetchLastLevelOnly">
</mat-slide-toggle> </mat-slide-toggle>
<label class="tb-small root-state-entity-label" translate>alias.last-level-relation</label> <label class="tb-small root-state-entity-label" translate>alias.last-level-relation</label>
</section> </section>
</div> </div>
<div fxFlex fxLayoutGap="8px" fxLayout="row"> <div fxFlex fxLayoutGap="8px" fxLayout="row" fxLayout.xs="column">
<mat-form-field class="mat-block" style="min-width: 100px;"> <mat-form-field class="mat-block" style="min-width: 100px;">
<mat-label translate>relation.direction</mat-label> <mat-label translate>relation.direction</mat-label>
<mat-select required matInput formControlName="direction"> <mat-select required formControlName="direction">
<mat-option *ngFor="let type of directionTypes" [value]="type"> <mat-option *ngFor="let type of directionTypes" [value]="type">
{{ directionTypeTranslations.get(directionTypeEnum[type]) | translate }} {{ directionTypeTranslations.get(directionTypeEnum[type]) | translate }}
</mat-option> </mat-option>

60
ui-ngx/src/app/modules/home/components/relation/relation-filters.component.html

@ -16,35 +16,37 @@
--> -->
<div class="tb-relation-filters" [formGroup]="relationFiltersFormGroup"> <div class="tb-relation-filters" [formGroup]="relationFiltersFormGroup">
<div class="header" [fxShow]="relationFiltersFormArray().length"> <div class="container">
<div fxLayout="row" fxLayoutAlign="start center"> <div class="header" [fxShow]="relationFiltersFormArray().length">
<span class="cell" style="width: 200px; min-width: 200px;" translate>relation.type</span> <div fxLayout="row" fxLayoutAlign="start center">
<span class="cell" fxFlex translate>entity.entity-types</span> <span class="cell" style="width: 200px; min-width: 200px;" translate>relation.type</span>
<span class="cell" style="width: 40px; min-width: 40px;">&nbsp;</span> <span class="cell" fxFlex translate>entity.entity-types</span>
<span class="cell" style="width: 40px; min-width: 40px;">&nbsp;</span>
</div>
</div> </div>
</div> <div class="body" [fxShow]="relationFiltersFormArray().length">
<div class="body" [fxShow]="relationFiltersFormArray().length"> <div class="row" fxFlex fxLayout="row"
<div class="row" fxFlex fxLayout="row" fxLayoutAlign="start center" formArrayName="relationFilters"
fxLayoutAlign="start center" formArrayName="relationFilters" *ngFor="let relationFilterControl of relationFiltersFormArray().controls; let $index = index">
*ngFor="let relationFilterControl of relationFiltersFormArray().controls; let $index = index"> <div class="mat-elevation-z1" fxFlex fxLayout="row" fxLayoutAlign="start center">
<div class="mat-elevation-z1" fxFlex fxLayout="row" fxLayoutAlign="start center"> <tb-relation-type-autocomplete
<tb-relation-type-autocomplete class="cell" style="width: 200px; min-width: 200px;"
class="cell" style="width: 200px; min-width: 200px;" [formControl]="relationFilterControl.get('relationType')">
[formControl]="relationFilterControl.get('relationType')"> </tb-relation-type-autocomplete>
</tb-relation-type-autocomplete> <tb-entity-type-list class="cell" fxFlex
<tb-entity-type-list class="cell" fxFlex [allowedEntityTypes]="allowedEntityTypes"
[allowedEntityTypes]="allowedEntityTypes" [formControl]="relationFilterControl.get('entityTypes')">
[formControl]="relationFilterControl.get('entityTypes')"> </tb-entity-type-list>
</tb-entity-type-list> <button mat-icon-button color="primary"
<button mat-button mat-icon-button color="primary" type="button"
type="button" style="width: 40px; min-width: 40px;"
style="width: 40px; min-width: 40px;" (click)="removeFilter($index)"
(click)="removeFilter($index)" [disabled]="isLoading$ | async"
[disabled]="isLoading$ | async" matTooltip="{{ 'relation.remove-relation-filter' | translate }}"
matTooltip="{{ 'relation.remove-relation-filter' | translate }}" matTooltipPosition="above">
matTooltipPosition="above"> <mat-icon>close</mat-icon>
<mat-icon>close</mat-icon> </button>
</button> </div>
</div> </div>
</div> </div>
</div> </div>
@ -53,7 +55,7 @@
class="tb-prompt" translate>relation.any-relation</span> class="tb-prompt" translate>relation.any-relation</span>
</div> </div>
<div> <div>
<button mat-button mat-raised-button color="primary" <button mat-raised-button color="primary"
[disabled]="isLoading$ | async" [disabled]="isLoading$ | async"
(click)="addFilter()" (click)="addFilter()"
type="button" type="button"

24
ui-ngx/src/app/modules/home/components/relation/relation-filters.component.scss

@ -15,10 +15,17 @@
*/ */
:host { :host {
.tb-relation-filters { .tb-relation-filters {
max-width: calc(100vw - 48px);
overflow: hidden;
.container{
width: 100%;
overflow: auto;
}
.header { .header {
padding-right: 5px; width: max-content;
padding-bottom: 5px; padding: 0 5px 5px;
padding-left: 5px;
.cell { .cell {
padding-right: 5px; padding-right: 5px;
@ -31,11 +38,8 @@
} }
.body { .body {
max-height: 300px; width: max-content;
padding-right: 5px; padding: 0 5px 20px;
padding-bottom: 20px;
padding-left: 5px;
overflow: auto;
.row { .row {
padding-top: 5px; padding-top: 5px;
@ -46,6 +50,10 @@
padding-left: 5px; padding-left: 5px;
} }
} }
.any-filter{
margin: 10px 0 20px;
}
} }
} }

16
ui-ngx/src/app/modules/home/components/relation/relation-filters.component.ts

@ -14,21 +14,17 @@
/// limitations under the License. /// limitations under the License.
/// ///
import { Component, EventEmitter, forwardRef, Input, OnInit, Output } from '@angular/core'; import { Component, forwardRef, Input, OnInit } from '@angular/core';
import { import {
AbstractControl, AbstractControl,
ControlValueAccessor, FormArray, ControlValueAccessor,
FormBuilder, FormControl, FormArray,
FormBuilder,
FormGroup, FormGroup,
NG_VALUE_ACCESSOR, NG_VALUE_ACCESSOR
ValidatorFn,
Validators
} from '@angular/forms'; } from '@angular/forms';
import { AliasFilterType, aliasFilterTypeTranslationMap, EntityAliasFilter } from '@shared/models/alias.models';
import { AliasEntityType, EntityType } from '@shared/models/entity-type.models'; import { AliasEntityType, EntityType } from '@shared/models/entity-type.models';
import { TranslateService } from '@ngx-translate/core'; import { EntityTypeFilter } from '@shared/models/relation.models';
import { EntityService } from '@core/http/entity.service';
import { EntitySearchDirection, entitySearchDirectionTranslations, EntityTypeFilter } from '@shared/models/relation.models';
import { PageComponent } from '@shared/components/page.component'; import { PageComponent } from '@shared/components/page.component';
import { Store } from '@ngrx/store'; import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state'; import { AppState } from '@core/core.state';

4
ui-ngx/src/app/modules/home/components/relation/relation-table.component.html

@ -86,7 +86,7 @@
</div> </div>
</mat-toolbar> </mat-toolbar>
<div fxFlex class="table-container"> <div fxFlex class="table-container">
<mat-table [dataSource]="dataSource" <table mat-table [dataSource]="dataSource"
matSort [matSortActive]="pageLink.sortOrder.property" [matSortDirection]="pageLink.sortDirection()" matSortDisableClear> matSort [matSortActive]="pageLink.sortOrder.property" [matSortDirection]="pageLink.sortDirection()" matSortDisableClear>
<ng-container matColumnDef="select" sticky> <ng-container matColumnDef="select" sticky>
<mat-header-cell *matHeaderCellDef style="width: 30px;"> <mat-header-cell *matHeaderCellDef style="width: 30px;">
@ -156,7 +156,7 @@
<mat-row [ngClass]="{'mat-row-select': true, <mat-row [ngClass]="{'mat-row-select': true,
'mat-selected': dataSource.selection.isSelected(relation)}" 'mat-selected': dataSource.selection.isSelected(relation)}"
*matRowDef="let relation; columns: displayedColumns;" (click)="dataSource.selection.toggle(relation)"></mat-row> *matRowDef="let relation; columns: displayedColumns;" (click)="dataSource.selection.toggle(relation)"></mat-row>
</mat-table> </table>
<span [fxShow]="dataSource.isEmpty() | async" <span [fxShow]="dataSource.isEmpty() | async"
fxLayoutAlign="center center" fxLayoutAlign="center center"
class="no-data-found" translate>{{ 'relation.no-relations-text' }}</span> class="no-data-found" translate>{{ 'relation.no-relations-text' }}</span>

2
ui-ngx/src/app/modules/home/components/widget/action/custom-action-pretty-editor.component.html

@ -17,7 +17,7 @@
--> -->
<div class="tb-custom-action-pretty mat-elevation-z1" tb-fullscreen [fullscreen]="fullscreen"> <div class="tb-custom-action-pretty mat-elevation-z1" tb-fullscreen [fullscreen]="fullscreen">
<div fxLayout="row" fxLayoutAlign="end center" class="tb-action-expand-button" [ngClass]="{'tb-fullscreen-editor': fullscreen}"> <div fxLayout="row" fxLayoutAlign="end center" class="tb-action-expand-button" [ngClass]="{'tb-fullscreen-editor': fullscreen}">
<button mat-button fxHide.xs fxHide.sm <button mat-button fxHide.lt-md
matTooltip="{{ 'widget.toggle-fullscreen' | translate }}" matTooltip="{{ 'widget.toggle-fullscreen' | translate }}"
matTooltipPosition="above" matTooltipPosition="above"
(click)="fullscreen = !fullscreen"> (click)="fullscreen = !fullscreen">

34
ui-ngx/src/app/modules/home/components/widget/action/custom-action-pretty-editor.component.ts

@ -19,46 +19,22 @@
import { import {
AfterViewInit, AfterViewInit,
ChangeDetectionStrategy,
Component, Component,
ElementRef, ElementRef,
forwardRef, forwardRef,
Input, Input,
OnDestroy, OnDestroy,
OnInit, OnInit,
ViewChild, ViewEncapsulation, ViewChildren, QueryList, ComponentFactoryResolver QueryList,
ViewChildren,
ViewEncapsulation
} from '@angular/core'; } from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms'; import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
import { TranslateService } from '@ngx-translate/core';
import { PageComponent } from '@shared/components/page.component'; import { PageComponent } from '@shared/components/page.component';
import { Store } from '@ngrx/store'; import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state'; import { AppState } from '@core/core.state';
import { MatDialog } from '@angular/material/dialog'; import { combineLatest } from 'rxjs';
import { DialogService } from '@core/services/dialog.service'; import { CustomActionDescriptor } from '@shared/models/widget.models';
import { PageLink } from '@shared/models/page/page-link';
import { Direction, SortOrder } from '@shared/models/page/sort-order';
import { MatPaginator } from '@angular/material/paginator';
import { MatSort } from '@angular/material/sort';
import { combineLatest, fromEvent, merge } from 'rxjs';
import { debounceTime, distinctUntilChanged, tap } from 'rxjs/operators';
import {
WidgetActionDescriptorInfo,
WidgetActionsData,
WidgetActionsDatasource,
WidgetActionCallbacks, toWidgetActionDescriptor
} from '@home/components/widget/action/manage-widget-actions.component.models';
import { UtilsService } from '@core/services/utils.service';
import { EntityRelation, EntitySearchDirection, RelationTypeGroup } from '@shared/models/relation.models';
import { RelationDialogComponent, RelationDialogData } from '@home/components/relation/relation-dialog.component';
import { CustomActionDescriptor, WidgetActionDescriptor, WidgetActionSource } from '@shared/models/widget.models';
import {
WidgetActionDialogComponent,
WidgetActionDialogData
} from '@home/components/widget/action/widget-action-dialog.component';
import { deepClone } from '@core/utils';
import { TbAnchorComponent } from '@shared/components/tb-anchor.component';
import { CustomActionPrettyResourcesTabsComponent } from '@home/components/widget/action/custom-action-pretty-resources-tabs.component';
import { MatTab, MatTabGroup } from '@angular/material/tabs';
@Component({ @Component({
selector: 'tb-custom-action-pretty-editor', selector: 'tb-custom-action-pretty-editor',

4
ui-ngx/src/app/modules/home/components/widget/action/custom-action-pretty-resources-tabs.component.html

@ -23,12 +23,12 @@
fxLayoutAlign="start center" fxLayoutAlign="start center"
*ngFor="let resource of action.customResources; let i = index" > *ngFor="let resource of action.customResources; let i = index" >
<mat-form-field fxFlex class="mat-block resource-field" floatLabel="never" <mat-form-field fxFlex class="mat-block resource-field" floatLabel="never"
style="margin: 10px 0px 0px 0px; max-height: 40px;"> style="margin: 10px 0 0; max-height: 40px;">
<input required matInput [(ngModel)]="resource.url" <input required matInput [(ngModel)]="resource.url"
(ngModelChange)="notifyActionUpdated()" (ngModelChange)="notifyActionUpdated()"
placeholder="{{ 'widget.resource-url' | translate }}"/> placeholder="{{ 'widget.resource-url' | translate }}"/>
</mat-form-field> </mat-form-field>
<button mat-button mat-icon-button color="primary" <button mat-icon-button color="primary"
[disabled]="isLoading$ | async" [disabled]="isLoading$ | async"
type="button" type="button"
(click)="removeResource(i)" (click)="removeResource(i)"

7
ui-ngx/src/app/modules/home/components/widget/action/custom-action-pretty-resources-tabs.component.ts

@ -22,9 +22,10 @@ import {
OnChanges, OnChanges,
OnDestroy, OnDestroy,
OnInit, OnInit,
Output, QueryList, Output,
SimpleChanges, SimpleChanges,
ViewChild, ViewChildren, ViewEncapsulation ViewChild,
ViewEncapsulation
} from '@angular/core'; } from '@angular/core';
import { TranslateService } from '@ngx-translate/core'; import { TranslateService } from '@ngx-translate/core';
import { PageComponent } from '@shared/components/page.component'; import { PageComponent } from '@shared/components/page.component';
@ -34,8 +35,6 @@ import { CustomActionDescriptor } from '@shared/models/widget.models';
import * as ace from 'ace-builds'; import * as ace from 'ace-builds';
import { CancelAnimationFrame, RafService } from '@core/services/raf.service'; import { CancelAnimationFrame, RafService } from '@core/services/raf.service';
import { css_beautify, html_beautify } from 'js-beautify'; import { css_beautify, html_beautify } from 'js-beautify';
import { MatTab } from '@angular/material/tabs';
import { BehaviorSubject } from 'rxjs';
@Component({ @Component({
selector: 'tb-custom-action-pretty-resources-tabs', selector: 'tb-custom-action-pretty-resources-tabs',

16
ui-ngx/src/app/modules/home/components/widget/action/manage-widget-actions.component.html

@ -21,14 +21,14 @@
<div class="mat-toolbar-tools"> <div class="mat-toolbar-tools">
<span class="tb-entity-table-title" translate>widget-config.actions</span> <span class="tb-entity-table-title" translate>widget-config.actions</span>
<span fxFlex></span> <span fxFlex></span>
<button mat-button mat-icon-button [disabled]="isLoading$ | async" <button mat-icon-button [disabled]="isLoading$ | async"
type="button" type="button"
(click)="addAction($event)" (click)="addAction($event)"
matTooltip="{{ 'widget-config.add-action' | translate }}" matTooltip="{{ 'widget-config.add-action' | translate }}"
matTooltipPosition="above"> matTooltipPosition="above">
<mat-icon>add</mat-icon> <mat-icon>add</mat-icon>
</button> </button>
<button mat-button mat-icon-button [disabled]="isLoading$ | async" (click)="enterFilterMode()" <button mat-icon-button [disabled]="isLoading$ | async" (click)="enterFilterMode()"
type="button" type="button"
matTooltip="{{ 'action.search' | translate }}" matTooltip="{{ 'action.search' | translate }}"
matTooltipPosition="above"> matTooltipPosition="above">
@ -38,7 +38,7 @@
</mat-toolbar> </mat-toolbar>
<mat-toolbar class="mat-table-toolbar" [fxShow]="textSearchMode"> <mat-toolbar class="mat-table-toolbar" [fxShow]="textSearchMode">
<div class="mat-toolbar-tools"> <div class="mat-toolbar-tools">
<button mat-button mat-icon-button <button mat-icon-button
type="button" type="button"
matTooltip="{{ 'widget-config.search-actions' | translate }}" matTooltip="{{ 'widget-config.search-actions' | translate }}"
matTooltipPosition="above"> matTooltipPosition="above">
@ -50,7 +50,7 @@
[(ngModel)]="pageLink.textSearch" [(ngModel)]="pageLink.textSearch"
placeholder="{{ 'widget-config.search-actions' | translate }}"/> placeholder="{{ 'widget-config.search-actions' | translate }}"/>
</mat-form-field> </mat-form-field>
<button mat-button mat-icon-button (click)="exitFilterMode()" <button mat-icon-button (click)="exitFilterMode()"
type="button" type="button"
matTooltip="{{ 'action.close' | translate }}" matTooltip="{{ 'action.close' | translate }}"
matTooltipPosition="above"> matTooltipPosition="above">
@ -59,7 +59,7 @@
</div> </div>
</mat-toolbar> </mat-toolbar>
<div fxFlex class="table-container"> <div fxFlex class="table-container">
<mat-table [dataSource]="dataSource" <table mat-table [dataSource]="dataSource"
matSort [matSortActive]="pageLink.sortOrder.property" [matSortDirection]="pageLink.sortDirection()" matSortDisableClear> matSort [matSortActive]="pageLink.sortOrder.property" [matSortDirection]="pageLink.sortDirection()" matSortDisableClear>
<ng-container matColumnDef="actionSourceName"> <ng-container matColumnDef="actionSourceName">
<mat-header-cell *matHeaderCellDef mat-sort-header style="width: 20%"> {{ 'widget-config.action-source' | translate }} </mat-header-cell> <mat-header-cell *matHeaderCellDef mat-sort-header style="width: 20%"> {{ 'widget-config.action-source' | translate }} </mat-header-cell>
@ -90,14 +90,14 @@
</mat-header-cell> </mat-header-cell>
<mat-cell *matCellDef="let action"> <mat-cell *matCellDef="let action">
<div fxFlex fxLayout="row" fxLayoutAlign="end"> <div fxFlex fxLayout="row" fxLayoutAlign="end">
<button mat-button mat-icon-button [disabled]="isLoading$ | async" <button mat-icon-button [disabled]="isLoading$ | async"
type="button" type="button"
matTooltip="{{ 'widget-config.edit-action' | translate }}" matTooltip="{{ 'widget-config.edit-action' | translate }}"
matTooltipPosition="above" matTooltipPosition="above"
(click)="editAction($event, action)"> (click)="editAction($event, action)">
<mat-icon>edit</mat-icon> <mat-icon>edit</mat-icon>
</button> </button>
<button mat-button mat-icon-button [disabled]="isLoading$ | async" <button mat-icon-button [disabled]="isLoading$ | async"
type="button" type="button"
matTooltip="{{ 'widget-config.delete-action' | translate }}" matTooltip="{{ 'widget-config.delete-action' | translate }}"
matTooltipPosition="above" matTooltipPosition="above"
@ -110,7 +110,7 @@
<mat-header-row [ngClass]="{'mat-row-select': true}" *matHeaderRowDef="displayedColumns; sticky: true"></mat-header-row> <mat-header-row [ngClass]="{'mat-row-select': true}" *matHeaderRowDef="displayedColumns; sticky: true"></mat-header-row>
<mat-row [ngClass]="{'mat-row-select': true}" <mat-row [ngClass]="{'mat-row-select': true}"
*matRowDef="let action; columns: displayedColumns;"></mat-row> *matRowDef="let action; columns: displayedColumns;"></mat-row>
</mat-table> </table>
<span [fxShow]="dataSource.isEmpty() | async" <span [fxShow]="dataSource.isEmpty() | async"
fxLayoutAlign="center center" fxLayoutAlign="center center"
class="no-data-found" translate>{{ 'widget-config.no-actions-text' }}</span> class="no-data-found" translate>{{ 'widget-config.no-actions-text' }}</span>

15
ui-ngx/src/app/modules/home/components/widget/action/manage-widget-actions.component.models.ts

@ -14,19 +14,18 @@
/// limitations under the License. /// limitations under the License.
/// ///
import { WidgetActionDescriptor, WidgetActionSource, import {
widgetActionTypeTranslationMap, CustomActionDescriptor } from '@app/shared/models/widget.models'; CustomActionDescriptor,
WidgetActionDescriptor,
WidgetActionSource,
widgetActionTypeTranslationMap
} from '@app/shared/models/widget.models';
import { CollectionViewer, DataSource } from '@angular/cdk/collections'; import { CollectionViewer, DataSource } from '@angular/cdk/collections';
import { EntityRelationInfo, EntitySearchDirection } from '@shared/models/relation.models';
import { BehaviorSubject, Observable, of, ReplaySubject } from 'rxjs'; import { BehaviorSubject, Observable, of, ReplaySubject } from 'rxjs';
import { emptyPageData, PageData } from '@shared/models/page/page-data'; import { emptyPageData, PageData } from '@shared/models/page/page-data';
import { SelectionModel } from '@angular/cdk/collections';
import { EntityRelationService } from '@core/http/entity-relation.service';
import { TranslateService } from '@ngx-translate/core'; import { TranslateService } from '@ngx-translate/core';
import { EntityId } from '@shared/models/id/entity-id';
import { PageLink } from '@shared/models/page/page-link'; import { PageLink } from '@shared/models/page/page-link';
import { catchError, map, publishReplay, refCount, share, take, tap } from 'rxjs/operators'; import { catchError, map, publishReplay, refCount } from 'rxjs/operators';
import { entityTypeTranslations } from '@shared/models/entity-type.models';
import { UtilsService } from '@core/services/utils.service'; import { UtilsService } from '@core/services/utils.service';
import { deepClone, isDefined, isUndefined } from '@core/utils'; import { deepClone, isDefined, isUndefined } from '@core/utils';

19
ui-ngx/src/app/modules/home/components/widget/action/manage-widget-actions.component.ts

@ -14,17 +14,7 @@
/// limitations under the License. /// limitations under the License.
/// ///
import { import { AfterViewInit, Component, ElementRef, forwardRef, Input, OnDestroy, OnInit, ViewChild } from '@angular/core';
AfterViewInit,
ChangeDetectionStrategy,
Component,
ElementRef,
forwardRef,
Input,
OnDestroy,
OnInit,
ViewChild
} from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms'; import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
import { TranslateService } from '@ngx-translate/core'; import { TranslateService } from '@ngx-translate/core';
import { PageComponent } from '@shared/components/page.component'; import { PageComponent } from '@shared/components/page.component';
@ -39,14 +29,13 @@ import { MatSort } from '@angular/material/sort';
import { fromEvent, merge } from 'rxjs'; import { fromEvent, merge } from 'rxjs';
import { debounceTime, distinctUntilChanged, tap } from 'rxjs/operators'; import { debounceTime, distinctUntilChanged, tap } from 'rxjs/operators';
import { import {
toWidgetActionDescriptor,
WidgetActionCallbacks,
WidgetActionDescriptorInfo, WidgetActionDescriptorInfo,
WidgetActionsData, WidgetActionsData,
WidgetActionsDatasource, WidgetActionsDatasource
WidgetActionCallbacks, toWidgetActionDescriptor
} from '@home/components/widget/action/manage-widget-actions.component.models'; } from '@home/components/widget/action/manage-widget-actions.component.models';
import { UtilsService } from '@core/services/utils.service'; import { UtilsService } from '@core/services/utils.service';
import { EntityRelation, EntitySearchDirection, RelationTypeGroup } from '@shared/models/relation.models';
import { RelationDialogComponent, RelationDialogData } from '@home/components/relation/relation-dialog.component';
import { WidgetActionDescriptor, WidgetActionSource } from '@shared/models/widget.models'; import { WidgetActionDescriptor, WidgetActionSource } from '@shared/models/widget.models';
import { import {
WidgetActionDialogComponent, WidgetActionDialogComponent,

20
ui-ngx/src/app/modules/home/components/widget/action/widget-action-dialog.component.html

@ -15,8 +15,8 @@
limitations under the License. limitations under the License.
--> -->
<form #widgetActionForm="ngForm" [formGroup]="widgetActionFormGroup" (ngSubmit)="save()" style="min-width: 600px;"> <form #widgetActionForm="ngForm" [formGroup]="widgetActionFormGroup" (ngSubmit)="save()" style="min-width: 480px;">
<mat-toolbar fxLayout="row" color="primary"> <mat-toolbar color="primary">
<h2>{{ (isAdd ? 'widget-config.add-action' : 'widget-config.edit-action' ) | translate }}</h2> <h2>{{ (isAdd ? 'widget-config.add-action' : 'widget-config.edit-action' ) | translate }}</h2>
<span fxFlex></span> <span fxFlex></span>
<button mat-button mat-icon-button <button mat-button mat-icon-button
@ -32,7 +32,7 @@
<fieldset [disabled]="isLoading$ | async"> <fieldset [disabled]="isLoading$ | async">
<mat-form-field class="mat-block"> <mat-form-field class="mat-block">
<mat-label translate>widget-config.action-source</mat-label> <mat-label translate>widget-config.action-source</mat-label>
<mat-select required matInput formControlName="actionSourceId"> <mat-select required formControlName="actionSourceId">
<mat-option *ngFor="let actionSourceItem of data.actionsData.actionSources | keyvalue" [value]="actionSourceItem.key"> <mat-option *ngFor="let actionSourceItem of data.actionsData.actionSources | keyvalue" [value]="actionSourceItem.key">
{{ actionSourceName(actionSourceItem.value) }} {{ actionSourceName(actionSourceItem.value) }}
</mat-option> </mat-option>
@ -41,7 +41,7 @@
{{ 'widget-config.action-source-required' | translate }} {{ 'widget-config.action-source-required' | translate }}
</mat-error> </mat-error>
</mat-form-field> </mat-form-field>
<mat-form-field class="mat-block" style="padding-bottom: 20px;"> <mat-form-field class="mat-block">
<mat-label translate>widget-config.action-name</mat-label> <mat-label translate>widget-config.action-name</mat-label>
<input required matInput formControlName="name"> <input required matInput formControlName="name">
<mat-error *ngIf="widgetActionFormGroup.get('name').hasError('required')"> <mat-error *ngIf="widgetActionFormGroup.get('name').hasError('required')">
@ -56,7 +56,7 @@
</tb-material-icon-select> </tb-material-icon-select>
<mat-form-field class="mat-block"> <mat-form-field class="mat-block">
<mat-label translate>widget-config.action-type</mat-label> <mat-label translate>widget-config.action-type</mat-label>
<mat-select required matInput formControlName="type"> <mat-select required formControlName="type">
<mat-option *ngFor="let actionType of widgetActionTypes" [value]="actionType"> <mat-option *ngFor="let actionType of widgetActionTypes" [value]="actionType">
{{ widgetActionTypeTranslations.get(widgetActionType[actionType]) | translate }} {{ widgetActionTypeTranslations.get(widgetActionType[actionType]) | translate }}
</mat-option> </mat-option>
@ -67,7 +67,7 @@
</mat-form-field> </mat-form-field>
<section fxLayout="column" [formGroup]="actionTypeFormGroup" [ngSwitch]="widgetActionFormGroup.get('type').value"> <section fxLayout="column" [formGroup]="actionTypeFormGroup" [ngSwitch]="widgetActionFormGroup.get('type').value">
<ng-template [ngSwitchCase]="widgetActionType.openDashboard"> <ng-template [ngSwitchCase]="widgetActionType.openDashboard">
<div fxLayout="column" style="padding-bottom: 20px;"> <div fxLayout="column">
<div class="mat-caption tb-required" <div class="mat-caption tb-required"
style="padding-left: 3px; padding-bottom: 10px; color: rgba(0,0,0,0.57);" translate>widget-action.target-dashboard</div> style="padding-left: 3px; padding-bottom: 10px; color: rgba(0,0,0,0.57);" translate>widget-action.target-dashboard</div>
<tb-dashboard-autocomplete <tb-dashboard-autocomplete
@ -89,7 +89,7 @@
[matAutocomplete]="targetDashboardStateAutocomplete"> [matAutocomplete]="targetDashboardStateAutocomplete">
<button *ngIf="actionTypeFormGroup.get('targetDashboardStateId').value" <button *ngIf="actionTypeFormGroup.get('targetDashboardStateId').value"
type="button" type="button"
matSuffix mat-button mat-icon-button aria-label="Clear" matSuffix mat-icon-button aria-label="Clear"
(click)="clearTargetDashboardState()"> (click)="clearTargetDashboardState()">
<mat-icon class="material-icons">close</mat-icon> <mat-icon class="material-icons">close</mat-icon>
</button> </button>
@ -145,15 +145,13 @@
</section> </section>
</fieldset> </fieldset>
</div> </div>
<div mat-dialog-actions fxLayout="row"> <div mat-dialog-actions fxLayoutAlign="end center">
<span fxFlex></span> <button mat-raised-button color="primary"
<button mat-button mat-raised-button color="primary"
type="submit" type="submit"
[disabled]="(isLoading$ | async) || widgetActionFormGroup.invalid || actionTypeFormGroup.invalid || (!widgetActionFormGroup.dirty && !actionTypeFormGroup.dirty)"> [disabled]="(isLoading$ | async) || widgetActionFormGroup.invalid || actionTypeFormGroup.invalid || (!widgetActionFormGroup.dirty && !actionTypeFormGroup.dirty)">
{{ (isAdd ? 'action.add' : 'action.save') | translate }} {{ (isAdd ? 'action.add' : 'action.save') | translate }}
</button> </button>
<button mat-button color="primary" <button mat-button color="primary"
style="margin-right: 20px;"
type="button" type="button"
[disabled]="(isLoading$ | async)" [disabled]="(isLoading$ | async)"
(click)="cancel()" cdkFocusInitial> (click)="cancel()" cdkFocusInitial>

20
ui-ngx/src/app/modules/home/components/widget/action/widget-action-dialog.component.scss

@ -0,0 +1,20 @@
/**
* Copyright © 2016-2020 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 ::ng-deep {
.mat-checkbox-label {
white-space: normal;
}
}

2
ui-ngx/src/app/modules/home/components/widget/action/widget-action-dialog.component.ts

@ -55,7 +55,7 @@ export interface WidgetActionDialogData {
selector: 'tb-widget-action-dialog', selector: 'tb-widget-action-dialog',
templateUrl: './widget-action-dialog.component.html', templateUrl: './widget-action-dialog.component.html',
providers: [{provide: ErrorStateMatcher, useExisting: WidgetActionDialogComponent}], providers: [{provide: ErrorStateMatcher, useExisting: WidgetActionDialogComponent}],
styleUrls: [] styleUrls: ['./widget-action-dialog.component.scss']
}) })
export class WidgetActionDialogComponent extends DialogComponent<WidgetActionDialogComponent, export class WidgetActionDialogComponent extends DialogComponent<WidgetActionDialogComponent,
WidgetActionDescriptorInfo> implements OnInit, ErrorStateMatcher { WidgetActionDescriptorInfo> implements OnInit, ErrorStateMatcher {

10
ui-ngx/src/app/modules/home/components/widget/data-key-config-dialog.component.html

@ -15,8 +15,8 @@
limitations under the License. limitations under the License.
--> -->
<form #dataKeyForm="ngForm" [formGroup]="dataKeyFormGroup" (ngSubmit)="save()" style="width: 600px;"> <form #dataKeyForm="ngForm" [formGroup]="dataKeyFormGroup" (ngSubmit)="save()" style="min-width: 480px;">
<mat-toolbar fxLayout="row" color="primary"> <mat-toolbar color="primary">
<h2>{{ 'datakey.configuration' | translate }}</h2> <h2>{{ 'datakey.configuration' | translate }}</h2>
<span fxFlex></span> <span fxFlex></span>
<button mat-button mat-icon-button <button mat-button mat-icon-button
@ -36,15 +36,13 @@
formControlName="dataKey"> formControlName="dataKey">
</tb-data-key-config> </tb-data-key-config>
</div> </div>
<div mat-dialog-actions fxLayout="row"> <div mat-dialog-actions fxLayoutAlign="end center">
<span fxFlex></span> <button mat-raised-button color="primary"
<button mat-button mat-raised-button color="primary"
type="submit" type="submit"
[disabled]="(isLoading$ | async) || dataKeyForm.invalid || !dataKeyForm.dirty"> [disabled]="(isLoading$ | async) || dataKeyForm.invalid || !dataKeyForm.dirty">
{{ 'action.save' | translate }} {{ 'action.save' | translate }}
</button> </button>
<button mat-button color="primary" <button mat-button color="primary"
style="margin-right: 20px;"
type="button" type="button"
[disabled]="(isLoading$ | async)" [disabled]="(isLoading$ | async)"
(click)="cancel()" cdkFocusInitial> (click)="cancel()" cdkFocusInitial>

1
ui-ngx/src/app/modules/home/components/widget/data-key-config-dialog.component.scss

@ -17,5 +17,6 @@
.mat-dialog-content { .mat-dialog-content {
padding: 0 !important; padding: 0 !important;
margin: 0 !important; margin: 0 !important;
overflow: hidden;
} }
} }

21
ui-ngx/src/app/modules/home/components/widget/data-key-config.component.html

@ -15,10 +15,9 @@
limitations under the License. limitations under the License.
--> -->
<mat-tab-group class="tb-datakey-config" [ngClass]="{'tb-headless': !displayAdvanced}" <mat-tab-group class="tb-datakey-config" [ngClass]="{'tb-headless': !displayAdvanced}">
class="tb-datakey-config">
<mat-tab [formGroup]="dataKeyFormGroup" label="{{ 'datakey.settings' | translate }}"> <mat-tab [formGroup]="dataKeyFormGroup" label="{{ 'datakey.settings' | translate }}">
<div class="mat-content mat-padding" fxLayout="column"> <div class="mat-padding settings" fxLayout="column">
<mat-form-field class="mat-block" *ngIf="modelValue.type !== dataKeyTypes.function"> <mat-form-field class="mat-block" *ngIf="modelValue.type !== dataKeyTypes.function">
<mat-label>{{ 'entity.key' | translate }}</mat-label> <mat-label>{{ 'entity.key' | translate }}</mat-label>
<input matInput type="text" placeholder="{{ 'entity.key-name' | translate }}" <input matInput type="text" placeholder="{{ 'entity.key-name' | translate }}"
@ -28,7 +27,7 @@
[matAutocomplete]="keyAutocomplete"> [matAutocomplete]="keyAutocomplete">
<button *ngIf="dataKeyFormGroup.get('name').value" <button *ngIf="dataKeyFormGroup.get('name').value"
type="button" type="button"
matSuffix mat-button mat-icon-button aria-label="Clear" matSuffix mat-icon-button aria-label="Clear"
(click)="clearKey()"> (click)="clearKey()">
<mat-icon class="material-icons">close</mat-icon> <mat-icon class="material-icons">close</mat-icon>
</button> </button>
@ -40,7 +39,7 @@
</mat-option> </mat-option>
</mat-autocomplete> </mat-autocomplete>
</mat-form-field> </mat-form-field>
<div fxLayout="row" fxLayoutAlign="start center" fxLayoutGap="8px"> <div fxLayout="row" fxLayout.xs="column" fxLayoutAlign="start center" fxLayoutAlign.xs fxLayoutGap="8px">
<mat-form-field fxFlex class="mat-block"> <mat-form-field fxFlex class="mat-block">
<mat-label translate>datakey.label</mat-label> <mat-label translate>datakey.label</mat-label>
<input matInput formControlName="label" required> <input matInput formControlName="label" required>
@ -53,7 +52,7 @@
formControlName="color"> formControlName="color">
</tb-color-input> </tb-color-input>
</div> </div>
<div fxLayout="row" fxLayoutAlign="start center" fxLayoutGap="8px" *ngIf="modelValue.type !== dataKeyTypes.alarm"> <div fxLayout="row" fxLayout.xs="column" fxLayoutAlign="start center" fxLayoutAlign.xs fxLayoutGap="8px" *ngIf="modelValue.type !== dataKeyTypes.alarm">
<mat-form-field fxFlex> <mat-form-field fxFlex>
<mat-label translate>datakey.units</mat-label> <mat-label translate>datakey.units</mat-label>
<input matInput formControlName="units"> <input matInput formControlName="units">
@ -94,12 +93,10 @@
</div> </div>
</mat-tab> </mat-tab>
<mat-tab [formGroup]="dataKeySettingsFormGroup" label="{{ 'datakey.advanced' | translate }}" *ngIf="displayAdvanced"> <mat-tab [formGroup]="dataKeySettingsFormGroup" label="{{ 'datakey.advanced' | translate }}" *ngIf="displayAdvanced">
<div class="mat-content mat-padding" fxLayout="column"> <div class="mat-padding" fxLayout="column">
<div style="overflow: auto;"> <tb-json-form
<tb-json-form formControlName="settings">
formControlName="settings"> </tb-json-form>
</tb-json-form>
</div>
</div> </div>
</mat-tab> </mat-tab>
</mat-tab-group> </mat-tab-group>

22
ui-ngx/src/app/modules/home/components/widget/data-key-config.component.scss

@ -13,11 +13,21 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
@import '../../../../../scss/constants';
:host { :host {
.tb-datakey-config { .tb-datakey-config {
min-width: 500px !important; height: 100%;
min-height: 500px !important;
height: 500px !important; .settings{
&> :first-child{
padding-top: 12px;
}
&> :nth-child(n){
padding-right: 12px;
padding-left: 12px;
}
}
} }
} }
@ -25,7 +35,11 @@
.tb-datakey-config { .tb-datakey-config {
.mat-tab-body.mat-tab-body-active { .mat-tab-body.mat-tab-body-active {
.mat-tab-body-content > div { .mat-tab-body-content > div {
height: 100%; height: calc(65vh - 50px);
overflow: initial;
@media #{$mat-xs} {
height: 500px;
}
} }
} }
} }

5
ui-ngx/src/app/modules/home/components/widget/data-keys.component.scss

@ -15,6 +15,8 @@
*/ */
:host { :host {
.mat-chip.mat-standard-chip { .mat-chip.mat-standard-chip {
overflow: hidden;
.tb-attribute-chip { .tb-attribute-chip {
max-width: 100%; max-width: 100%;
color: rgb(66, 66, 66); color: rgb(66, 66, 66);
@ -32,7 +34,8 @@
.tb-chip-labels { .tb-chip-labels {
display: flex; display: flex;
flex-direction: row; flex-direction: row;
min-width: 0px; align-items: flex-end;
min-width: 0;
.tb-chip-label { .tb-chip-label {
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;

14
ui-ngx/src/app/modules/home/components/widget/dialog/custom-dialog-container.component.ts

@ -16,23 +16,21 @@
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { import {
Inject, Component,
ComponentRef,
ElementRef,
ViewContainerRef,
ComponentFactory, ComponentFactory,
ComponentRef,
Inject,
Injector, Injector,
ReflectiveInjector, OnDestroy,
Component, ViewContainerRef
OnDestroy
} from '@angular/core'; } from '@angular/core';
import { DialogComponent } from '@shared/components/dialog.component'; import { DialogComponent } from '@shared/components/dialog.component';
import { Store } from '@ngrx/store'; import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state'; import { AppState } from '@core/core.state';
import { Router } from '@angular/router'; import { Router } from '@angular/router';
import { import {
CustomDialogComponent,
CUSTOM_DIALOG_DATA, CUSTOM_DIALOG_DATA,
CustomDialogComponent,
CustomDialogData CustomDialogData
} from '@home/components/widget/dialog/custom-dialog.component'; } from '@home/components/widget/dialog/custom-dialog.component';

3
ui-ngx/src/app/modules/home/components/widget/dialog/custom-dialog.component.ts

@ -14,9 +14,8 @@
/// limitations under the License. /// limitations under the License.
/// ///
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; import { MatDialogRef } from '@angular/material/dialog';
import { Inject, InjectionToken } from '@angular/core'; import { Inject, InjectionToken } from '@angular/core';
import { DialogComponent } from '@shared/components/dialog.component';
import { Store } from '@ngrx/store'; import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state'; import { AppState } from '@core/core.state';
import { Router } from '@angular/router'; import { Router } from '@angular/router';

1
ui-ngx/src/app/modules/home/components/widget/dynamic-widget.component.ts

@ -21,7 +21,6 @@ import { AppState } from '@core/core.state';
import { IDynamicWidgetComponent, WidgetContext } from '@home/models/widget-component.models'; import { IDynamicWidgetComponent, WidgetContext } from '@home/models/widget-component.models';
import { HttpErrorResponse } from '@angular/common/http'; import { HttpErrorResponse } from '@angular/common/http';
import { RafService } from '@core/services/raf.service'; import { RafService } from '@core/services/raf.service';
import { ActionNotificationShow } from '@core/notification/notification.actions';
import { import {
NotificationHorizontalPosition, NotificationHorizontalPosition,
NotificationType, NotificationType,

4
ui-ngx/src/app/modules/home/components/widget/lib/alarms-table-widget.component.html

@ -61,7 +61,7 @@
</div> </div>
</mat-toolbar> </mat-toolbar>
<div fxFlex class="table-container"> <div fxFlex class="table-container">
<mat-table [dataSource]="alarmsDatasource" <table mat-table [dataSource]="alarmsDatasource"
matSort [matSortActive]="sortOrderProperty" [matSortDirection]="pageLink.sortDirection()" matSortDisableClear> matSort [matSortActive]="sortOrderProperty" [matSortDirection]="pageLink.sortDirection()" matSortDisableClear>
<ng-container matColumnDef="select" sticky> <ng-container matColumnDef="select" sticky>
<mat-header-cell *matHeaderCellDef style="width: 30px;"> <mat-header-cell *matHeaderCellDef style="width: 30px;">
@ -124,7 +124,7 @@
'tb-current-entity': alarmsDatasource.isCurrentAlarm(alarm)}" 'tb-current-entity': alarmsDatasource.isCurrentAlarm(alarm)}"
*matRowDef="let alarm; columns: displayedColumns;" *matRowDef="let alarm; columns: displayedColumns;"
(click)="onRowClick($event, alarm)"></mat-row> (click)="onRowClick($event, alarm)"></mat-row>
</mat-table> </table>
<span [fxShow]="alarmsDatasource.isEmpty() | async" <span [fxShow]="alarmsDatasource.isEmpty() | async"
fxLayoutAlign="center center" fxLayoutAlign="center center"
class="no-data-found" translate>alarm.no-alarms-prompt</span> class="no-data-found" translate>alarm.no-alarms-prompt</span>

4
ui-ngx/src/app/modules/home/components/widget/lib/entities-table-widget.component.html

@ -38,7 +38,7 @@
</div> </div>
</mat-toolbar> </mat-toolbar>
<div fxFlex class="table-container"> <div fxFlex class="table-container">
<mat-table [dataSource]="entityDatasource" <table mat-table [dataSource]="entityDatasource"
matSort [matSortActive]="sortOrderProperty" [matSortDirection]="pageLink.sortDirection()" matSortDisableClear> matSort [matSortActive]="sortOrderProperty" [matSortDirection]="pageLink.sortDirection()" matSortDisableClear>
<ng-container [matColumnDef]="column.def" *ngFor="let column of columns; trackBy: trackByColumnDef;"> <ng-container [matColumnDef]="column.def" *ngFor="let column of columns; trackBy: trackByColumnDef;">
<mat-header-cell [ngStyle]="headerStyle(column)" *matHeaderCellDef mat-sort-header> {{ column.title }} </mat-header-cell> <mat-header-cell [ngStyle]="headerStyle(column)" *matHeaderCellDef mat-sort-header> {{ column.title }} </mat-header-cell>
@ -85,7 +85,7 @@
<mat-row [ngClass]="{'tb-current-entity': entityDatasource.isCurrentEntity(entity)}" <mat-row [ngClass]="{'tb-current-entity': entityDatasource.isCurrentEntity(entity)}"
*matRowDef="let entity; columns: displayedColumns;" *matRowDef="let entity; columns: displayedColumns;"
(click)="onRowClick($event, entity)" (dblclick)="onRowClick($event, entity, true)"></mat-row> (click)="onRowClick($event, entity)" (dblclick)="onRowClick($event, entity, true)"></mat-row>
</mat-table> </table>
<span [fxShow]="entityDatasource.isEmpty() | async" <span [fxShow]="entityDatasource.isEmpty() | async"
fxLayoutAlign="center center" fxLayoutAlign="center center"
class="no-data-found" translate>entity.no-entities-prompt</span> class="no-data-found" translate>entity.no-entities-prompt</span>

4
ui-ngx/src/app/modules/home/components/widget/lib/timeseries-table-widget.component.html

@ -41,7 +41,7 @@
[(selectedIndex)]="sourceIndex" (selectedIndexChange)="onSourceIndexChanged()"> [(selectedIndex)]="sourceIndex" (selectedIndexChange)="onSourceIndexChanged()">
<mat-tab *ngFor="let source of sources" label="{{ source.datasource.name }}"> <mat-tab *ngFor="let source of sources" label="{{ source.datasource.name }}">
<div fxFlex class="table-container"> <div fxFlex class="table-container">
<mat-table [dataSource]="source.timeseriesDatasource" [trackBy]="trackByRowIndex" <table mat-table [dataSource]="source.timeseriesDatasource" [trackBy]="trackByRowIndex"
matSort [matSortActive]="source.pageLink.sortOrder.property" [matSortDirection]="source.pageLink.sortDirection()" matSortDisableClear> matSort [matSortActive]="source.pageLink.sortOrder.property" [matSortDirection]="source.pageLink.sortDirection()" matSortDisableClear>
<ng-container *ngIf="showTimestamp" [matColumnDef]="'0'"> <ng-container *ngIf="showTimestamp" [matColumnDef]="'0'">
<mat-header-cell *matHeaderCellDef mat-sort-header>Timestamp</mat-header-cell> <mat-header-cell *matHeaderCellDef mat-sort-header>Timestamp</mat-header-cell>
@ -94,7 +94,7 @@
<mat-header-row *matHeaderRowDef="source.displayedColumns; sticky: true"></mat-header-row> <mat-header-row *matHeaderRowDef="source.displayedColumns; sticky: true"></mat-header-row>
<mat-row *matRowDef="let row; columns: source.displayedColumns;" <mat-row *matRowDef="let row; columns: source.displayedColumns;"
(click)="onRowClick($event, row)"></mat-row> (click)="onRowClick($event, row)"></mat-row>
</mat-table> </table>
<span [fxShow]="source.timeseriesDatasource.isEmpty() | async" <span [fxShow]="source.timeseriesDatasource.isEmpty() | async"
fxLayoutAlign="center center" fxLayoutAlign="center center"
class="no-data-found" translate>widget.no-data-found</span> class="no-data-found" translate>widget.no-data-found</span>

162
ui-ngx/src/app/modules/home/components/widget/widget-config.component.html

@ -16,12 +16,12 @@
--> -->
<mat-tab-group [ngClass]="{'tb-headless': (widgetType === widgetTypes.static && !displayAdvanced())}" <mat-tab-group [ngClass]="{'tb-headless': (widgetType === widgetTypes.static && !displayAdvanced())}"
fxFlex class="tb-widget-config tb-absolute-fill" [(selectedIndex)]="selectedTab"> class="tb-widget-config tb-absolute-fill" [(selectedIndex)]="selectedTab">
<mat-tab label="{{ 'widget-config.data' | translate }}" [fxShow]="widgetType !== widgetTypes.static"> <mat-tab label="{{ 'widget-config.data' | translate }}" [fxShow]="widgetType !== widgetTypes.static">
<div [formGroup]="dataSettings" class="mat-content mat-padding" fxLayout="column" fxLayoutGap="8px"> <div [formGroup]="dataSettings" class="mat-content mat-padding" fxLayout="column" fxLayoutGap="8px">
<div *ngIf="widgetType === widgetTypes.timeseries || widgetType === widgetTypes.alarm" <div *ngIf="widgetType === widgetTypes.timeseries || widgetType === widgetTypes.alarm" fxFlex="100"
fxLayout="column" fxLayoutGap="8px" fxLayoutAlign="center" fxLayout.gt-sm="row" fxLayoutAlign.gt-sm="start center"> fxLayout.xs="column" fxLayoutGap="8px" fxLayoutAlign.xs="center" fxLayout="row" fxLayoutAlign="start center">
<div fxLayout="column" fxLayoutGap="8px" fxFlex> <div fxLayout="column" fxLayoutGap="8px" fxFlex.gt-xs>
<mat-checkbox formControlName="useDashboardTimewindow"> <mat-checkbox formControlName="useDashboardTimewindow">
{{ 'widget-config.use-dashboard-timewindow' | translate }} {{ 'widget-config.use-dashboard-timewindow' | translate }}
</mat-checkbox> </mat-checkbox>
@ -29,8 +29,10 @@
{{ 'widget-config.display-timewindow' | translate }} {{ 'widget-config.display-timewindow' | translate }}
</mat-checkbox> </mat-checkbox>
</div> </div>
<section fxFlex fxLayout="row" fxLayoutAlign="start center" style="margin-bottom: 16px;"> <section fxLayout="row" fxLayoutAlign="start center" fxLayout.lt-lg="column" fxLayoutAlign.lt-lg="center start"
<span [ngClass]="{'tb-disabled-label': dataSettings.get('useDashboardTimewindow').value}" translate style="padding-right: 8px;">widget-config.timewindow</span> fxFlex.gt-xs style="margin-bottom: 16px;">
<span [ngClass]="{'tb-disabled-label': dataSettings.get('useDashboardTimewindow').value}" translate
style="padding-right: 8px;">widget-config.timewindow</span>
<tb-timewindow asButton="true" <tb-timewindow asButton="true"
isEdit="true" isEdit="true"
aggregation="{{ widgetType === widgetTypes.timeseries }}" aggregation="{{ widgetType === widgetTypes.timeseries }}"
@ -38,10 +40,11 @@
</section> </section>
</div> </div>
<div *ngIf="widgetType === widgetTypes.alarm" fxLayout="column" fxLayoutAlign="center"> <div *ngIf="widgetType === widgetTypes.alarm" fxLayout="column" fxLayoutAlign="center">
<div fxLayout.gt-sm="row" fxLayoutAlign.gt-sm="start center" fxLayoutGap="8px"> <div fxLayout="column" fxLayoutAlign="center" fxLayout.gt-xs="row" fxLayoutAlign.gt-xs="start center"
fxLayoutGap="8px">
<mat-form-field fxFlex class="mat-block"> <mat-form-field fxFlex class="mat-block">
<mat-label translate>alarm.alarm-status</mat-label> <mat-label translate>alarm.alarm-status</mat-label>
<mat-select matInput formControlName="alarmSearchStatus"> <mat-select formControlName="alarmSearchStatus">
<mat-option *ngFor="let searchStatus of alarmSearchStatuses" [value]="searchStatus"> <mat-option *ngFor="let searchStatus of alarmSearchStatuses" [value]="searchStatus">
{{ ('alarm.search-status.' + searchStatus) | translate }} {{ ('alarm.search-status.' + searchStatus) | translate }}
</mat-option> </mat-option>
@ -61,7 +64,8 @@
</mat-error> </mat-error>
</mat-form-field> </mat-form-field>
</div> </div>
<div fxLayout.gt-sm="row" fxLayoutAlign.gt-sm="start center" fxLayoutGap="8px"> <div fxLayout="column" fxLayoutAlign="center" fxLayout.gt-xs="row" fxLayoutAlign.gt-xs="start center"
fxLayoutGap="8px">
<mat-form-field fxFlex class="mat-block"> <mat-form-field fxFlex class="mat-block">
<mat-label translate>alarm.max-count-load</mat-label> <mat-label translate>alarm.max-count-load</mat-label>
<input matInput required <input matInput required
@ -100,7 +104,7 @@
<mat-panel-title fxLayout="column"> <mat-panel-title fxLayout="column">
<div class="tb-panel-title" translate>widget-config.datasources</div> <div class="tb-panel-title" translate>widget-config.datasources</div>
<div *ngIf="modelValue?.typeParameters && modelValue?.typeParameters.maxDatasources > -1" <div *ngIf="modelValue?.typeParameters && modelValue?.typeParameters.maxDatasources > -1"
class="tb-hint">{{ 'widget-config.maximum-datasources' | translate:{count: modelValue?.typeParameters.maxDatasources} }}</div> class="tb-panel-hint">{{ 'widget-config.maximum-datasources' | translate:{count: modelValue?.typeParameters.maxDatasources} }}</div>
</mat-panel-title> </mat-panel-title>
</mat-expansion-panel-header> </mat-expansion-panel-header>
<div *ngIf="datasourcesFormArray().length === 0; else datasourcesTemplate"> <div *ngIf="datasourcesFormArray().length === 0; else datasourcesTemplate">
@ -133,7 +137,7 @@
fxLayout.gt-sm="row" fxLayout.gt-sm="row"
fxLayoutAlign.gt-sm="start center"> fxLayoutAlign.gt-sm="start center">
<mat-form-field class="tb-datasource-type"> <mat-form-field class="tb-datasource-type">
<mat-select matInput formControlName="type"> <mat-select formControlName="type">
<mat-option *ngFor="let datasourceType of datasourceTypes" [value]="datasourceType"> <mat-option *ngFor="let datasourceType of datasourceTypes" [value]="datasourceType">
{{ datasourceTypesTranslations.get(datasourceType) | translate }} {{ datasourceTypesTranslations.get(datasourceType) | translate }}
</mat-option> </mat-option>
@ -172,7 +176,7 @@
</section> </section>
<button [disabled]="isLoading$ | async" <button [disabled]="isLoading$ | async"
type="button" type="button"
mat-button mat-icon-button color="primary" mat-icon-button color="primary"
style="min-width: 40px;" style="min-width: 40px;"
(click)="removeDatasource($index)" (click)="removeDatasource($index)"
matTooltip="{{ 'widget-config.remove-datasource' | translate }}" matTooltip="{{ 'widget-config.remove-datasource' | translate }}"
@ -186,7 +190,7 @@
<div fxFlex fxLayout="row" fxLayoutAlign="start center"> <div fxFlex fxLayout="row" fxLayoutAlign="start center">
<button [disabled]="isLoading$ | async" <button [disabled]="isLoading$ | async"
type="button" type="button"
mat-button mat-raised-button color="primary" mat-raised-button color="primary"
[fxShow]="modelValue?.typeParameters && [fxShow]="modelValue?.typeParameters &&
(modelValue?.typeParameters.maxDatasources == -1 || datasourcesFormArray().controls.length < modelValue?.typeParameters.maxDatasources)" (modelValue?.typeParameters.maxDatasources == -1 || datasourcesFormArray().controls.length < modelValue?.typeParameters.maxDatasources)"
(click)="addDatasource()" (click)="addDatasource()"
@ -228,7 +232,7 @@
fxLayout.gt-sm="row" fxLayout.gt-sm="row"
fxLayoutAlign.gt-sm="start center"> fxLayoutAlign.gt-sm="start center">
<mat-form-field class="tb-datasource-type"> <mat-form-field class="tb-datasource-type">
<mat-select matInput formControlName="type"> <mat-select formControlName="type">
<mat-option *ngFor="let datasourceType of datasourceTypes" [value]="datasourceType"> <mat-option *ngFor="let datasourceType of datasourceTypes" [value]="datasourceType">
{{ datasourceTypesTranslations.get(datasourceType) | translate }} {{ datasourceTypesTranslations.get(datasourceType) | translate }}
</mat-option> </mat-option>
@ -268,15 +272,20 @@
</div> </div>
</mat-tab> </mat-tab>
<mat-tab label="{{ 'widget-config.settings' | translate }}"> <mat-tab label="{{ 'widget-config.settings' | translate }}">
<div class="mat-content mat-padding" <div class="mat-content mat-padding" fxLayout="column" fxLayoutGap="8px">
fxLayout="column" fxLayoutGap="8px">
<div [formGroup]="widgetSettings" fxLayout="column" fxLayoutGap="8px"> <div [formGroup]="widgetSettings" fxLayout="column" fxLayoutGap="8px">
<span translate>widget-config.general-settings</span> <span translate>widget-config.general-settings</span>
<div fxLayout="column" fxLayoutAlign="center" fxLayout.gt-sm="row" fxLayoutAlign.gt-sm="start center"> <div fxLayout.xs="column" fxLayoutAlign.xs="center" fxLayout="row" fxLayoutAlign="start center">
<mat-form-field fxFlex class="mat-block"> <div fxLayout="column" fxLayoutAlign="center" fxFlex.sm="40%" fxFlex.gt-sm="30%">
<mat-label translate>widget-config.title</mat-label> <mat-form-field fxFlex class="mat-block">
<input matInput formControlName="title"> <mat-label translate>widget-config.title</mat-label>
</mat-form-field> <input matInput formControlName="title">
</mat-form-field>
<mat-form-field fxFlex>
<mat-label translate>widget-config.title-tooltip</mat-label>
<input matInput formControlName="titleTooltip">
</mat-form-field>
</div>
<div fxFlex [fxShow]="widgetSettings.get('showTitle').value"> <div fxFlex [fxShow]="widgetSettings.get('showTitle').value">
<tb-json-object-edit <tb-json-object-edit
[editorStyle]="{minHeight: '100px'}" [editorStyle]="{minHeight: '100px'}"
@ -286,46 +295,40 @@
></tb-json-object-edit> ></tb-json-object-edit>
</div> </div>
</div> </div>
<div fxLayout="column" fxLayoutAlign="center" fxLayout.gt-sm="row" fxLayoutAlign.gt-sm="start center" <div fxLayout="column" fxLayoutAlign="center" fxLayout.gt-md="row" fxLayoutAlign.gt-md="start center" fxFlex="100%"
fxLayoutGap="8px"> fxLayoutGap="8px">
<div fxLayout="row" fxFlex> <div fxLayout.xs="column" fxLayoutAlign.xs="center" fxLayout="row" fxLayoutAlign="start center"
<mat-checkbox formControlName="showTitleIcon"> fxLayoutGap="8px" fxFlex.gt-md>
<mat-checkbox fxFlex formControlName="showTitleIcon">
{{ 'widget-config.display-icon' | translate }} {{ 'widget-config.display-icon' | translate }}
</mat-checkbox> </mat-checkbox>
</div> <tb-material-icon-select fxFlex
<div fxFlex>
<tb-material-icon-select
formControlName="titleIcon"> formControlName="titleIcon">
</tb-material-icon-select> </tb-material-icon-select>
</div> </div>
<tb-color-input fxFlex <div fxLayout.xs="column" fxLayoutAlign.xs="center" fxLayout="row" fxLayoutAlign="start center"
label="{{'widget-config.icon-color' | translate}}" fxLayoutGap="8px" fxFlex.gt-md>
icon="format_color_fill" <tb-color-input fxFlex
openOnInput label="{{'widget-config.icon-color' | translate}}"
formControlName="iconColor"> icon="format_color_fill"
</tb-color-input> openOnInput
<mat-form-field fxFlex> formControlName="iconColor">
<mat-label translate>widget-config.icon-size</mat-label> </tb-color-input>
<input matInput formControlName="iconSize"> <mat-form-field fxFlex>
</mat-form-field> <mat-label translate>widget-config.icon-size</mat-label>
<mat-form-field fxFlex> <input matInput formControlName="iconSize">
<mat-label translate>widget-config.title-tooltip</mat-label> </mat-form-field>
<input matInput formControlName="titleTooltip"> </div>
</mat-form-field>
</div> </div>
<div fxLayout="column" fxLayoutAlign="center" fxLayout.gt-sm="row" fxLayoutAlign.gt-sm="start center" <div fxLayout.xs="column" fxLayoutAlign.xs="center" fxLayout="row" fxLayoutAlign="start center"
fxLayoutGap="8px"> fxLayoutGap="8px">
<div fxLayout="row"> <div fxLayout="column" fxLayoutAlign="center" fxLayoutGap="8px" fxFlex.sm="40%" fxFlex.gt-sm="30%">
<mat-checkbox formControlName="showTitle"> <mat-checkbox formControlName="showTitle">
{{ 'widget-config.display-title' | translate }} {{ 'widget-config.display-title' | translate }}
</mat-checkbox> </mat-checkbox>
</div>
<div fxLayout="row">
<mat-checkbox formControlName="dropShadow"> <mat-checkbox formControlName="dropShadow">
{{ 'widget-config.drop-shadow' | translate }} {{ 'widget-config.drop-shadow' | translate }}
</mat-checkbox> </mat-checkbox>
</div>
<div fxLayout="row">
<mat-checkbox formControlName="enableFullscreen"> <mat-checkbox formControlName="enableFullscreen">
{{ 'widget-config.enable-fullscreen' | translate }} {{ 'widget-config.enable-fullscreen' | translate }}
</mat-checkbox> </mat-checkbox>
@ -339,30 +342,36 @@
></tb-json-object-edit> ></tb-json-object-edit>
</div> </div>
</div> </div>
<div fxLayout="column" fxLayoutAlign="center" fxLayout.gt-sm="row" fxLayoutAlign.gt-sm="start center" <div fxLayout="column" fxLayoutAlign="center" fxLayout.gt-md="row" fxLayoutAlign.gt-md="start center"
fxLayoutGap="8px"> fxFlex="100%" fxLayoutGap="8px">
<tb-color-input fxFlex <div fxLayout.xs="column" fxLayoutAlign.xs="center" fxLayout="row" fxLayoutAlign="start center"
label="{{'widget-config.background-color' | translate}}" fxLayoutGap="8px" fxFlex.gt-md>
icon="format_color_fill" <tb-color-input fxFlex
openOnInput label="{{'widget-config.background-color' | translate}}"
formControlName="backgroundColor"> icon="format_color_fill"
</tb-color-input> openOnInput
<tb-color-input fxFlex formControlName="backgroundColor">
label="{{'widget-config.text-color' | translate}}" </tb-color-input>
icon="format_color_fill" <tb-color-input fxFlex
openOnInput label="{{'widget-config.text-color' | translate}}"
formControlName="color"> icon="format_color_fill"
</tb-color-input> openOnInput
<mat-form-field fxFlex> formControlName="color">
<mat-label translate>widget-config.padding</mat-label> </tb-color-input>
<input matInput formControlName="padding"> </div>
</mat-form-field> <div fxLayout.xs="column" fxLayoutAlign.xs="center" fxLayout="row" fxLayoutAlign="start center"
<mat-form-field fxFlex> fxLayoutGap="8px" fxFlex.gt-md>
<mat-label translate>widget-config.margin</mat-label> <mat-form-field fxFlex>
<input matInput formControlName="margin"> <mat-label translate>widget-config.padding</mat-label>
</mat-form-field> <input matInput formControlName="padding">
</mat-form-field>
<mat-form-field fxFlex>
<mat-label translate>widget-config.margin</mat-label>
<input matInput formControlName="margin">
</mat-form-field>
</div>
</div> </div>
<div fxLayout="column" fxLayoutAlign="center" fxLayout.gt-sm="row" fxLayoutAlign.gt-sm="start center" <div fxLayout.xs="column" fxLayoutAlign.xs="center" fxLayout="row" fxLayoutAlign="start center"
fxLayoutGap="8px"> fxLayoutGap="8px">
<mat-form-field fxFlex> <mat-form-field fxFlex>
<mat-label translate>widget-config.units</mat-label> <mat-label translate>widget-config.units</mat-label>
@ -373,14 +382,13 @@
<input matInput formControlName="decimals" type="number" min="0" max="15" step="1"> <input matInput formControlName="decimals" type="number" min="0" max="15" step="1">
</mat-form-field> </mat-form-field>
</div> </div>
<div [fxShow]="widgetType === widgetTypes.timeseries || <div [fxShow]="widgetType === widgetTypes.timeseries || widgetType === widgetTypes.latest"
widgetType === widgetTypes.latest" fxLayout.xs="column" fxLayoutAlign.xs="center" fxLayout="row" fxLayoutAlign="start center"
fxLayout="column" fxLayoutAlign="center" fxLayout.gt-sm="row" fxLayoutAlign.gt-sm="start center" fxLayoutGap="8px" fxFlex="100%">
fxLayoutGap="8px"> <mat-checkbox fxFlex.gt-xs formControlName="showLegend">
<mat-checkbox fxFlex formControlName="showLegend">
{{ 'widget-config.display-legend' | translate }} {{ 'widget-config.display-legend' | translate }}
</mat-checkbox> </mat-checkbox>
<section fxFlex fxLayout="row" fxLayoutAlign="start center" style="margin-bottom: 16px;"> <section fxFlex.gt-xs fxLayout="row" fxLayoutAlign="start center" style="margin-bottom: 16px;">
<tb-legend-config formControlName="legendConfig"> <tb-legend-config formControlName="legendConfig">
</tb-legend-config> </tb-legend-config>
</section> </section>
@ -388,7 +396,7 @@
</div> </div>
<div [formGroup]="layoutSettings" fxLayout="column" fxLayoutGap="8px"> <div [formGroup]="layoutSettings" fxLayout="column" fxLayoutGap="8px">
<span translate>widget-config.mobile-mode-settings</span> <span translate>widget-config.mobile-mode-settings</span>
<div fxLayout="column" fxLayoutAlign="center" fxLayout.gt-sm="row" fxLayoutAlign.gt-sm="start center" <div fxLayout.xs="column" fxLayoutAlign.xs="center" fxLayout="row" fxLayoutAlign="start center"
fxLayoutGap="8px"> fxLayoutGap="8px">
<mat-form-field fxFlex> <mat-form-field fxFlex>
<mat-label translate>widget-config.order</mat-label> <mat-label translate>widget-config.order</mat-label>

24
ui-ngx/src/app/modules/home/components/widget/widget-config.component.scss

@ -57,14 +57,26 @@
right: 0; right: 0;
bottom: 0; bottom: 0;
} }
.mat-tab-body.mat-tab-body-active { .tb-panel-hint {
.mat-tab-body-content > div { font-size: 12px;
height: 100%; color: #808080;
} }
//.mat-tab-body.mat-tab-body-active {
// .mat-tab-body-content > div {
// height: 100%;
// }
//}
.mat-checkbox-label {
white-space: normal;
} }
.mat-expansion-panel { .mat-expansion-panel {
&.tb-datasources.mat-expanded { &.tb-datasources{
overflow: visible; &.mat-expanded {
overflow: visible;
}
.mat-expansion-panel-body{
padding: 0 12px 16px;
}
} }
.mat-expansion-panel-content { .mat-expansion-panel-content {
font: inherit; font: inherit;

13
ui-ngx/src/app/modules/home/pages/dashboard/add-widget-dialog.component.html

@ -16,11 +16,11 @@
--> -->
<form #widgetForm="ngForm" [formGroup]="widgetFormGroup" (ngSubmit)="add()" style="width: 900px;"> <form #widgetForm="ngForm" [formGroup]="widgetFormGroup" (ngSubmit)="add()" style="width: 900px;">
<mat-toolbar fxLayout="row" color="primary"> <mat-toolbar color="primary">
<h2 translate>widget.add</h2> <h2 translate>widget.add</h2>
<span fxFlex></span> <span fxFlex></span>
<div [tb-help]="helpLinkIdForWidgetType()"></div> <div [tb-help]="helpLinkIdForWidgetType()"></div>
<button mat-button mat-icon-button <button mat-icon-button
(click)="cancel()" (click)="cancel()"
type="button"> type="button">
<mat-icon class="material-icons">close</mat-icon> <mat-icon class="material-icons">close</mat-icon>
@ -39,18 +39,17 @@
</tb-widget-config> </tb-widget-config>
</fieldset> </fieldset>
</div> </div>
<div mat-dialog-actions fxLayout="row"> <div mat-dialog-actions fxLayoutAlign="end center">
<span fxFlex></span> <button mat-raised-button color="primary"
<button mat-button mat-raised-button color="primary"
type="submit" type="submit"
[disabled]="(isLoading$ | async) || widgetFormGroup.invalid"> [disabled]="(isLoading$ | async) || widgetFormGroup.invalid">
{{ 'action.add' | translate }} {{ 'action.add' | translate }}
</button> </button>
<button mat-button color="primary" <button mat-button color="primary"
style="margin-right: 20px;"
type="button" type="button"
[disabled]="(isLoading$ | async)" [disabled]="(isLoading$ | async)"
(click)="cancel()" cdkFocusInitial> (click)="cancel()"
cdkFocusInitial>
{{ 'action.cancel' | translate }} {{ 'action.cancel' | translate }}
</button> </button>
</div> </div>

8
ui-ngx/src/app/modules/home/pages/dashboard/add-widget-dialog.component.ts

@ -23,9 +23,6 @@ import { FormBuilder, FormControl, FormGroup, FormGroupDirective, NgForm } from
import { Router } from '@angular/router'; import { Router } from '@angular/router';
import { DialogComponent } from '@app/shared/components/dialog.component'; import { DialogComponent } from '@app/shared/components/dialog.component';
import { Widget, widgetTypesData } from '@shared/models/widget.models'; import { Widget, widgetTypesData } from '@shared/models/widget.models';
import { UtilsService } from '@core/services/utils.service';
import { TranslateService } from '@ngx-translate/core';
import { EntityService } from '@core/http/entity.service';
import { Dashboard } from '@app/shared/models/dashboard.models'; import { Dashboard } from '@app/shared/models/dashboard.models';
import { IAliasController } from '@core/api/widget-api.models'; import { IAliasController } from '@core/api/widget-api.models';
import { WidgetConfigComponentData, WidgetInfo } from '@home/models/widget-component.models'; import { WidgetConfigComponentData, WidgetInfo } from '@home/models/widget-component.models';
@ -60,10 +57,7 @@ export class AddWidgetDialogComponent extends DialogComponent<AddWidgetDialogCom
@Inject(MAT_DIALOG_DATA) public data: AddWidgetDialogData, @Inject(MAT_DIALOG_DATA) public data: AddWidgetDialogData,
@SkipSelf() private errorStateMatcher: ErrorStateMatcher, @SkipSelf() private errorStateMatcher: ErrorStateMatcher,
public dialogRef: MatDialogRef<AddWidgetDialogComponent, Widget>, public dialogRef: MatDialogRef<AddWidgetDialogComponent, Widget>,
private fb: FormBuilder, private fb: FormBuilder) {
private utils: UtilsService,
private translate: TranslateService,
private entityService: EntityService) {
super(store, router, dialogRef); super(store, router, dialogRef);
this.dashboard = this.data.dashboard; this.dashboard = this.data.dashboard;

24
ui-ngx/src/app/modules/home/pages/dashboard/dashboard-page.component.html

@ -27,27 +27,27 @@
fxLayoutAlign="center stretch" fxLayoutAlign.gt-sm="space-between center"> fxLayoutAlign="center stretch" fxLayoutAlign.gt-sm="space-between center">
<div class="tb-dashboard-action-panel" fxFlex.md="30" fxLayout="row-reverse" <div class="tb-dashboard-action-panel" fxFlex.md="30" fxLayout="row-reverse"
fxLayoutAlign.gt-sm="start center" fxLayoutAlign="space-between center" fxLayoutGap="12px"> fxLayoutAlign.gt-sm="start center" fxLayoutAlign="space-between center" fxLayoutGap="12px">
<button [fxShow]="showCloseToolbar()" mat-button mat-icon-button class="close-action" <button [fxShow]="showCloseToolbar()" mat-icon-button class="close-action"
matTooltip="{{ 'dashboard.close-toolbar' | translate }}" matTooltip="{{ 'dashboard.close-toolbar' | translate }}"
matTooltipPosition="below" matTooltipPosition="below"
(click)="closeToolbar()"> (click)="closeToolbar()">
<mat-icon>arrow_forward</mat-icon> <mat-icon>arrow_forward</mat-icon>
</button> </button>
<tb-user-menu *ngIf="!isPublicUser() && forceFullscreen" fxHide.xs fxHide.sm displayUserInfo="true"> <tb-user-menu *ngIf="!isPublicUser() && forceFullscreen" fxHide.lt-md displayUserInfo="true">
</tb-user-menu> </tb-user-menu>
<button [fxShow]="showRightLayoutSwitch()" mat-button mat-icon-button <button [fxShow]="showRightLayoutSwitch()" mat-icon-button
matTooltip="{{ (isRightLayoutOpened ? 'dashboard.hide-details' : 'dashboard.show-details') | translate }}" matTooltip="{{ (isRightLayoutOpened ? 'dashboard.hide-details' : 'dashboard.show-details') | translate }}"
matTooltipPosition="below" matTooltipPosition="below"
(click)="toggleLayouts()"> (click)="toggleLayouts()">
<mat-icon>{{isRightLayoutOpened ? 'arrow_back' : 'menu'}}</mat-icon> <mat-icon>{{isRightLayoutOpened ? 'arrow_back' : 'menu'}}</mat-icon>
</button> </button>
<button [fxShow]="!hideFullscreenButton()" mat-button mat-icon-button <button [fxShow]="!hideFullscreenButton()" mat-icon-button
matTooltip="{{(isFullscreen ? 'fullscreen.exit' : 'fullscreen.expand') | translate}}" matTooltip="{{(isFullscreen ? 'fullscreen.exit' : 'fullscreen.expand') | translate}}"
matTooltipPosition="below" matTooltipPosition="below"
(click)="isFullscreen = !isFullscreen"> (click)="isFullscreen = !isFullscreen">
<mat-icon>{{ isFullscreen ? 'fullscreen_exit' : 'fullscreen' }}</mat-icon> <mat-icon>{{ isFullscreen ? 'fullscreen_exit' : 'fullscreen' }}</mat-icon>
</button> </button>
<button [fxShow]="isEdit || displayExport()" mat-button mat-icon-button <button [fxShow]="isEdit || displayExport()" mat-icon-button
matTooltip="{{'dashboard.export' | translate}}" matTooltip="{{'dashboard.export' | translate}}"
matTooltipPosition="below" matTooltipPosition="below"
(click)="exportDashboard($event)"> (click)="exportDashboard($event)">
@ -65,13 +65,13 @@
tooltipPosition="below" tooltipPosition="below"
[aliasController]="dashboardCtx.aliasController"> [aliasController]="dashboardCtx.aliasController">
</tb-aliases-entity-select> </tb-aliases-entity-select>
<button [fxShow]="isEdit" mat-button mat-icon-button <button [fxShow]="isEdit" mat-icon-button
matTooltip="{{ 'entity.aliases' | translate }}" matTooltip="{{ 'entity.aliases' | translate }}"
matTooltipPosition="below" matTooltipPosition="below"
(click)="openEntityAliases($event)"> (click)="openEntityAliases($event)">
<mat-icon>devices_other</mat-icon> <mat-icon>devices_other</mat-icon>
</button> </button>
<button [fxShow]="isEdit" mat-button mat-icon-button <button [fxShow]="isEdit" mat-icon-button
matTooltip="{{ 'dashboard.settings' | translate }}" matTooltip="{{ 'dashboard.settings' | translate }}"
matTooltipPosition="below" matTooltipPosition="below"
(click)="openDashboardSettings($event)"> (click)="openDashboardSettings($event)">
@ -89,23 +89,23 @@
<tb-user-menu *ngIf="!isPublicUser() && forceFullscreen" fxHide.gt-sm displayUserInfo="true"> <tb-user-menu *ngIf="!isPublicUser() && forceFullscreen" fxHide.gt-sm displayUserInfo="true">
</tb-user-menu> </tb-user-menu>
<div [fxShow]="isEdit" <div [fxShow]="isEdit"
fxFlex.xs fxFlex.sm fxLayout="row" fxFlex.lt-md fxLayout="row"
fxLayoutAlign.gt-sm="start center" fxLayoutAlign.gt-sm="start center"
fxLayoutAlign="space-between center" fxLayoutGap="12px"> fxLayoutAlign="end center" fxLayoutGap="12px">
<button mat-button mat-icon-button <button mat-icon-button
matTooltip="{{'dashboard.manage-states' | translate}}" matTooltip="{{'dashboard.manage-states' | translate}}"
matTooltipPosition="below" matTooltipPosition="below"
(click)="manageDashboardStates($event)"> (click)="manageDashboardStates($event)">
<mat-icon>layers</mat-icon> <mat-icon>layers</mat-icon>
</button> </button>
<button mat-button mat-icon-button <button mat-icon-button
matTooltip="{{'layout.manage' | translate}}" matTooltip="{{'layout.manage' | translate}}"
matTooltipPosition="below" matTooltipPosition="below"
(click)="manageDashboardLayouts($event)"> (click)="manageDashboardLayouts($event)">
<mat-icon>view_compact</mat-icon> <mat-icon>view_compact</mat-icon>
</button> </button>
</div> </div>
<tb-states-component fxFlex.xs fxFlex.sm <tb-states-component fxFlex.lt-md
[statesControllerId]="isEdit ? 'default' : dashboardConfiguration.settings.stateControllerId" [statesControllerId]="isEdit ? 'default' : dashboardConfiguration.settings.stateControllerId"
[dashboardCtrl]="this" [dashboardCtrl]="this"
[dashboardId]="dashboard.id ? dashboard.id.id : ''" [dashboardId]="dashboard.id ? dashboard.id.id : ''"

20
ui-ngx/src/app/modules/home/pages/dashboard/dashboard-settings-dialog.component.html

@ -16,7 +16,7 @@
--> -->
<form #settingsForm="ngForm" (ngSubmit)="save()"> <form #settingsForm="ngForm" (ngSubmit)="save()">
<mat-toolbar fxLayout="row" color="primary"> <mat-toolbar color="primary">
<h2 translate>{{settings ? 'dashboard.settings' : 'layout.settings'}}</h2> <h2 translate>{{settings ? 'dashboard.settings' : 'layout.settings'}}</h2>
<span fxFlex></span> <span fxFlex></span>
<button mat-button mat-icon-button <button mat-button mat-icon-button
@ -28,17 +28,17 @@
<mat-progress-bar color="warn" mode="indeterminate" *ngIf="isLoading$ | async"> <mat-progress-bar color="warn" mode="indeterminate" *ngIf="isLoading$ | async">
</mat-progress-bar> </mat-progress-bar>
<div mat-dialog-content> <div mat-dialog-content>
<fieldset [disabled]="isLoading$ | async"> <fieldset [disabled]="isLoading$ | async" fxLayout="column" fxLayoutGap="16px">
<div *ngIf="settings" [formGroup]="settingsFormGroup"> <div *ngIf="settings" [formGroup]="settingsFormGroup">
<mat-form-field class="mat-block"> <mat-form-field class="mat-block">
<mat-label translate>dashboard.state-controller</mat-label> <mat-label translate>dashboard.state-controller</mat-label>
<mat-select required matInput formControlName="stateControllerId"> <mat-select required formControlName="stateControllerId">
<mat-option *ngFor="let stateControllerId of stateControllerIds" [value]="stateControllerId"> <mat-option *ngFor="let stateControllerId of stateControllerIds" [value]="stateControllerId">
{{stateControllerId}} {{stateControllerId}}
</mat-option> </mat-option>
</mat-select> </mat-select>
</mat-form-field> </mat-form-field>
<div fxLayout="row" fxLayoutAlign="start center" fxLayoutGap="8px"> <div fxLayout="row" fxLayoutAlign="start center" fxLayout.lt-md="column" fxLayoutAlign.lt-md fxLayoutGap="8px">
<mat-checkbox fxFlex formControlName="toolbarAlwaysOpen"> <mat-checkbox fxFlex formControlName="toolbarAlwaysOpen">
{{ 'dashboard.toolbar-always-open' | translate }} {{ 'dashboard.toolbar-always-open' | translate }}
</mat-checkbox> </mat-checkbox>
@ -52,7 +52,7 @@
formControlName="titleColor"> formControlName="titleColor">
</tb-color-input> </tb-color-input>
</div> </div>
<div fxLayout="row" fxLayoutAlign="start center" fxLayoutGap="8px"> <div fxLayout="row" fxLayoutAlign="start center" fxLayout.lt-md="column" fxLayoutAlign.lt-md fxLayoutGap="8px">
<mat-checkbox fxFlex formControlName="showDashboardsSelect"> <mat-checkbox fxFlex formControlName="showDashboardsSelect">
{{ 'dashboard.display-dashboards-selection' | translate }} {{ 'dashboard.display-dashboards-selection' | translate }}
</mat-checkbox> </mat-checkbox>
@ -117,7 +117,7 @@
</tb-image-input> </tb-image-input>
<mat-form-field class="mat-block"> <mat-form-field class="mat-block">
<mat-label translate>dashboard.background-size-mode</mat-label> <mat-label translate>dashboard.background-size-mode</mat-label>
<mat-select matInput formControlName="backgroundSizeMode"> <mat-select formControlName="backgroundSizeMode">
<mat-option value="100%">Fit width</mat-option> <mat-option value="100%">Fit width</mat-option>
<mat-option value="auto 100%">Fit height</mat-option> <mat-option value="auto 100%">Fit height</mat-option>
<mat-option value="cover">Cover</mat-option> <mat-option value="cover">Cover</mat-option>
@ -126,7 +126,7 @@
</mat-select> </mat-select>
</mat-form-field> </mat-form-field>
<small translate>dashboard.mobile-layout</small> <small translate>dashboard.mobile-layout</small>
<div fxFlex fxLayout="row" fxLayoutAlign="start center" fxLayoutGap="8px"> <div fxLayout="row" fxLayoutAlign="start center" fxLayout.xs="column" fxLayoutAlign.xs fxLayoutGap="8px" style="margin-top: 8px">
<mat-checkbox fxFlex formControlName="mobileAutoFillHeight"> <mat-checkbox fxFlex formControlName="mobileAutoFillHeight">
{{ 'dashboard.autofill-height' | translate }} {{ 'dashboard.autofill-height' | translate }}
</mat-checkbox> </mat-checkbox>
@ -148,16 +148,14 @@
</div> </div>
</fieldset> </fieldset>
</div> </div>
<div mat-dialog-actions fxLayout="row"> <div mat-dialog-actions fxLayoutAlign="end center">
<span fxFlex></span> <button mat-raised-button color="primary"
<button mat-button mat-raised-button color="primary"
type="submit" type="submit"
[disabled]="(isLoading$ | async) || settingsFormGroup.invalid || gridSettingsFormGroup.invalid [disabled]="(isLoading$ | async) || settingsFormGroup.invalid || gridSettingsFormGroup.invalid
|| (!settingsFormGroup.dirty && !gridSettingsFormGroup.dirty)"> || (!settingsFormGroup.dirty && !gridSettingsFormGroup.dirty)">
{{ 'action.save' | translate }} {{ 'action.save' | translate }}
</button> </button>
<button mat-button color="primary" <button mat-button color="primary"
style="margin-right: 20px;"
type="button" type="button"
[disabled]="(isLoading$ | async)" [disabled]="(isLoading$ | async)"
(click)="cancel()" cdkFocusInitial> (click)="cancel()" cdkFocusInitial>

26
ui-ngx/src/app/modules/home/pages/dashboard/dashboard-settings-dialog.component.scss

@ -0,0 +1,26 @@
/**
* Copyright © 2016-2020 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 {
small {
white-space: normal;
}
}
:host ::ng-deep {
.mat-checkbox-label {
white-space: normal;
}
}

2
ui-ngx/src/app/modules/home/pages/dashboard/dashboard-settings-dialog.component.ts

@ -38,7 +38,7 @@ export interface DashboardSettingsDialogData {
selector: 'tb-dashboard-settings-dialog', selector: 'tb-dashboard-settings-dialog',
templateUrl: './dashboard-settings-dialog.component.html', templateUrl: './dashboard-settings-dialog.component.html',
providers: [{provide: ErrorStateMatcher, useExisting: DashboardSettingsDialogComponent}], providers: [{provide: ErrorStateMatcher, useExisting: DashboardSettingsDialogComponent}],
styleUrls: [] styleUrls: ['./dashboard-settings-dialog.component.scss']
}) })
export class DashboardSettingsDialogComponent extends DialogComponent<DashboardSettingsDialogComponent, DashboardSettingsDialogData> export class DashboardSettingsDialogComponent extends DialogComponent<DashboardSettingsDialogComponent, DashboardSettingsDialogData>
implements OnInit, ErrorStateMatcher { implements OnInit, ErrorStateMatcher {

6
ui-ngx/src/app/modules/home/pages/dashboard/dashboard-toolbar.component.html

@ -15,12 +15,10 @@
limitations under the License. limitations under the License.
--> -->
<mat-fab-toolbar [isOpen]="toolbarOpened" <mat-fab-toolbar [isOpen]="toolbarOpened" color="primary" direction="left"
color="primary"
direction="left"
[ngClass]="{'is-fullscreen': forceFullscreen, 'mat-elevation-z1': forceFullscreen && toolbarOpened }"> [ngClass]="{'is-fullscreen': forceFullscreen, 'mat-elevation-z1': forceFullscreen && toolbarOpened }">
<mat-fab-trigger> <mat-fab-trigger>
<button mat-button mat-icon-button mat-fab color="primary" <button mat-fab color="primary"
[matTooltip]="!toolbarOpened ? ('dashboard.open-toolbar' | translate) : ''" [matTooltip]="!toolbarOpened ? ('dashboard.open-toolbar' | translate) : ''"
matTooltipPosition="below" matTooltipPosition="below"
(click)="onTriggerClick()"> (click)="onTriggerClick()">

2
ui-ngx/src/app/modules/home/pages/dashboard/layout/dashboard-layout.component.ts

@ -28,7 +28,7 @@ import {
WidgetContextMenuItem WidgetContextMenuItem
} from '@home/models/dashboard-component.models'; } from '@home/models/dashboard-component.models';
import { Subscription } from 'rxjs'; import { Subscription } from 'rxjs';
import { Hotkey, HotkeysService } from 'angular2-hotkeys'; import { Hotkey } from 'angular2-hotkeys';
import { TranslateService } from '@ngx-translate/core'; import { TranslateService } from '@ngx-translate/core';
import { ItemBufferService } from '@app/core/services/item-buffer.service'; import { ItemBufferService } from '@app/core/services/item-buffer.service';
import { DomSanitizer, SafeStyle } from '@angular/platform-browser'; import { DomSanitizer, SafeStyle } from '@angular/platform-browser';

3
ui-ngx/src/app/modules/home/pages/dashboard/layout/layout.models.ts

@ -14,9 +14,6 @@
/// limitations under the License. /// limitations under the License.
/// ///
import { Widget } from '@shared/models/widget.models';
import { WidgetLayout } from '@shared/models/dashboard.models';
export interface ILayoutController { export interface ILayoutController {
reload(); reload();
resetHighlight(); resetHighlight();

27
ui-ngx/src/app/modules/home/pages/dashboard/layout/manage-dashboard-layouts-dialog.component.html

@ -16,7 +16,7 @@
--> -->
<form #widgetForm="ngForm" [formGroup]="layoutsFormGroup" (ngSubmit)="save()"> <form #widgetForm="ngForm" [formGroup]="layoutsFormGroup" (ngSubmit)="save()">
<mat-toolbar fxLayout="row" color="primary"> <mat-toolbar color="primary">
<h2 translate>layout.manage</h2> <h2 translate>layout.manage</h2>
<span fxFlex></span> <span fxFlex></span>
<button mat-button mat-icon-button <button mat-button mat-icon-button
@ -38,33 +38,32 @@
</mat-checkbox> </mat-checkbox>
</div> </div>
<div fxLayout="row" fxLayoutAlign="start center" fxLayoutGap="8px"> <div fxLayout="row" fxLayoutAlign="start center" fxLayoutGap="8px">
<button fxFlex fxLayout="column" <button fxFlex
type="button" mat-button mat-raised-button color="primary" type="button" mat-raised-button color="primary"
class="tb-layout-button" class="tb-layout-button"
(click)="openLayoutSettings('main')"> (click)="openLayoutSettings('main')">
<span translate>layout.main</span> <span translate>layout.main</span>
</button> </button>
<button fxFlex fxLayout="column" [fxShow]="layoutsFormGroup.get('right').value" <button fxFlex [fxShow]="layoutsFormGroup.get('right').value"
type="button" mat-button mat-raised-button color="primary" type="button" mat-raised-button color="primary"
class="tb-layout-button" class="tb-layout-button"
(click)="openLayoutSettings('right')"> (click)="openLayoutSettings('right')">
<span translate>layout.right</span> <span translate>layout.right</span>
</button> </button>
</div> </div>
</fieldset> </fieldset>
</div> </div>
<div mat-dialog-actions fxLayout="row"> <div mat-dialog-actions fxLayoutAlign="end center">
<span fxFlex></span> <button mat-raised-button color="primary"
<button mat-button mat-raised-button color="primary"
type="submit" type="submit"
[disabled]="(isLoading$ | async) || layoutsFormGroup.invalid || !layoutsFormGroup.dirty"> [disabled]="(isLoading$ | async) || layoutsFormGroup.invalid || !layoutsFormGroup.dirty">
{{ 'action.save' | translate }} {{ 'action.save' | translate }}
</button> </button>
<button mat-button color="primary" <button mat-button
style="margin-right: 20px;" color="primary"
type="button" type="button"
[disabled]="(isLoading$ | async)" [disabled]="(isLoading$ | async)"
(click)="cancel()" cdkFocusInitial> (click)="cancel()" cdkFocusInitial>
{{ 'action.cancel' | translate }} {{ 'action.cancel' | translate }}
</button> </button>
</div> </div>

11
ui-ngx/src/app/modules/home/pages/dashboard/layout/manage-dashboard-layouts-dialog.component.ts

@ -16,22 +16,17 @@
import { Component, Inject, OnInit, SkipSelf } from '@angular/core'; import { Component, Inject, OnInit, SkipSelf } from '@angular/core';
import { ErrorStateMatcher } from '@angular/material/core'; import { ErrorStateMatcher } from '@angular/material/core';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; import { MAT_DIALOG_DATA, MatDialog, MatDialogRef } from '@angular/material/dialog';
import { Store } from '@ngrx/store'; import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state'; import { AppState } from '@core/core.state';
import { FormBuilder, FormControl, FormGroup, FormGroupDirective, NgForm } from '@angular/forms'; import { FormBuilder, FormControl, FormGroup, FormGroupDirective, NgForm } from '@angular/forms';
import { Router } from '@angular/router'; import { Router } from '@angular/router';
import { DialogComponent } from '@app/shared/components/dialog.component'; import { DialogComponent } from '@app/shared/components/dialog.component';
import { Widget, widgetTypesData } from '@shared/models/widget.models';
import { UtilsService } from '@core/services/utils.service'; import { UtilsService } from '@core/services/utils.service';
import { TranslateService } from '@ngx-translate/core'; import { TranslateService } from '@ngx-translate/core';
import { EntityService } from '@core/http/entity.service'; import { DashboardLayoutId, DashboardStateLayouts } from '@app/shared/models/dashboard.models';
import { Dashboard, DashboardLayoutId, DashboardStateLayouts } from '@app/shared/models/dashboard.models'; import { deepClone, isDefined } from '@core/utils';
import { IAliasController } from '@core/api/widget-api.models';
import { WidgetConfigComponentData, WidgetInfo } from '@home/models/widget-component.models';
import { deepClone, isDefined, isString } from '@core/utils';
import { DashboardUtilsService } from '@core/services/dashboard-utils.service'; import { DashboardUtilsService } from '@core/services/dashboard-utils.service';
import { MatDialog } from '@angular/material/dialog';
import { import {
DashboardSettingsDialogComponent, DashboardSettingsDialogComponent,
DashboardSettingsDialogData DashboardSettingsDialogData

10
ui-ngx/src/app/modules/home/pages/dashboard/states/dashboard-state-dialog.component.html

@ -15,8 +15,8 @@
limitations under the License. limitations under the License.
--> -->
<form #stateForm="ngForm" [formGroup]="stateFormGroup" (ngSubmit)="save()" style="min-width: 600px;"> <form #stateForm="ngForm" [formGroup]="stateFormGroup" (ngSubmit)="save()" style="min-width: 480px;">
<mat-toolbar fxLayout="row" color="primary"> <mat-toolbar color="primary">
<h2 translate>{{ isAdd ? 'dashboard.add-state' : 'dashboard.edit-state' }}</h2> <h2 translate>{{ isAdd ? 'dashboard.add-state' : 'dashboard.edit-state' }}</h2>
<span fxFlex></span> <span fxFlex></span>
<button mat-button mat-icon-button <button mat-button mat-icon-button
@ -51,15 +51,13 @@
</mat-checkbox> </mat-checkbox>
</fieldset> </fieldset>
</div> </div>
<div mat-dialog-actions fxLayout="row"> <div mat-dialog-actions fxLayoutAlign="end center">
<span fxFlex></span> <button mat-raised-button color="primary"
<button mat-button mat-raised-button color="primary"
type="submit" type="submit"
[disabled]="(isLoading$ | async) || stateFormGroup.invalid || !stateFormGroup.dirty"> [disabled]="(isLoading$ | async) || stateFormGroup.invalid || !stateFormGroup.dirty">
{{ (isAdd ? 'action.add' : 'action.save') | translate }} {{ (isAdd ? 'action.add' : 'action.save') | translate }}
</button> </button>
<button mat-button color="primary" <button mat-button color="primary"
style="margin-right: 20px;"
type="button" type="button"
[disabled]="(isLoading$ | async)" [disabled]="(isLoading$ | async)"
(click)="cancel()" cdkFocusInitial> (click)="cancel()" cdkFocusInitial>

4
ui-ngx/src/app/modules/home/pages/dashboard/states/dashboard-state-dialog.component.ts

@ -31,7 +31,6 @@ import {
import { Router } from '@angular/router'; import { Router } from '@angular/router';
import { DialogComponent } from '@app/shared/components/dialog.component'; import { DialogComponent } from '@app/shared/components/dialog.component';
import { DashboardState } from '@app/shared/models/dashboard.models'; import { DashboardState } from '@app/shared/models/dashboard.models';
import { MatDialog } from '@angular/material/dialog';
import { DashboardStateInfo } from '@home/pages/dashboard/states/manage-dashboard-states-dialog.component.models'; import { DashboardStateInfo } from '@home/pages/dashboard/states/manage-dashboard-states-dialog.component.models';
import { TranslateService } from '@ngx-translate/core'; import { TranslateService } from '@ngx-translate/core';
import { DashboardUtilsService } from '@core/services/dashboard-utils.service'; import { DashboardUtilsService } from '@core/services/dashboard-utils.service';
@ -71,8 +70,7 @@ export class DashboardStateDialogComponent extends
public dialogRef: MatDialogRef<DashboardStateDialogComponent, DashboardStateInfo>, public dialogRef: MatDialogRef<DashboardStateDialogComponent, DashboardStateInfo>,
private fb: FormBuilder, private fb: FormBuilder,
private translate: TranslateService, private translate: TranslateService,
private dashboardUtils: DashboardUtilsService, private dashboardUtils: DashboardUtilsService) {
private dialog: MatDialog) {
super(store, router, dialogRef); super(store, router, dialogRef);
this.states = this.data.states; this.states = this.data.states;

30
ui-ngx/src/app/modules/home/pages/dashboard/states/manage-dashboard-states-dialog.component.html

@ -15,8 +15,8 @@
limitations under the License. limitations under the License.
--> -->
<form #statesForm="ngForm" [formGroup]="statesFormGroup" (ngSubmit)="save()" style="min-width: 620px;"> <form #statesForm="ngForm" [formGroup]="statesFormGroup" (ngSubmit)="save()" style="min-width: 480px;">
<mat-toolbar fxLayout="row" color="primary"> <mat-toolbar color="primary">
<h2 translate>dashboard.manage-states</h2> <h2 translate>dashboard.manage-states</h2>
<span fxFlex></span> <span fxFlex></span>
<button mat-button mat-icon-button <button mat-button mat-icon-button
@ -36,14 +36,14 @@
<div class="mat-toolbar-tools"> <div class="mat-toolbar-tools">
<span class="tb-entity-table-title" translate>dashboard.states</span> <span class="tb-entity-table-title" translate>dashboard.states</span>
<span fxFlex></span> <span fxFlex></span>
<button mat-button mat-icon-button [disabled]="isLoading$ | async" <button mat-icon-button [disabled]="isLoading$ | async"
type="button" type="button"
(click)="addState($event)" (click)="addState($event)"
matTooltip="{{ 'dashboard.add-state' | translate }}" matTooltip="{{ 'dashboard.add-state' | translate }}"
matTooltipPosition="above"> matTooltipPosition="above">
<mat-icon>add</mat-icon> <mat-icon>add</mat-icon>
</button> </button>
<button mat-button mat-icon-button [disabled]="isLoading$ | async" (click)="enterFilterMode()" <button mat-icon-button [disabled]="isLoading$ | async" (click)="enterFilterMode()"
type="button" type="button"
matTooltip="{{ 'action.search' | translate }}" matTooltip="{{ 'action.search' | translate }}"
matTooltipPosition="above"> matTooltipPosition="above">
@ -53,7 +53,7 @@
</mat-toolbar> </mat-toolbar>
<mat-toolbar class="mat-table-toolbar" [fxShow]="textSearchMode"> <mat-toolbar class="mat-table-toolbar" [fxShow]="textSearchMode">
<div class="mat-toolbar-tools"> <div class="mat-toolbar-tools">
<button mat-button mat-icon-button <button mat-icon-button
type="button" type="button"
matTooltip="{{ 'dashboard.search-states' | translate }}" matTooltip="{{ 'dashboard.search-states' | translate }}"
matTooltipPosition="above"> matTooltipPosition="above">
@ -66,7 +66,7 @@
[ngModelOptions]="{standalone: true}" [ngModelOptions]="{standalone: true}"
placeholder="{{ 'dashboard.search-states' | translate }}"/> placeholder="{{ 'dashboard.search-states' | translate }}"/>
</mat-form-field> </mat-form-field>
<button mat-button mat-icon-button (click)="exitFilterMode()" <button mat-icon-button (click)="exitFilterMode()"
type="button" type="button"
matTooltip="{{ 'action.close' | translate }}" matTooltip="{{ 'action.close' | translate }}"
matTooltipPosition="above"> matTooltipPosition="above">
@ -75,16 +75,16 @@
</div> </div>
</mat-toolbar> </mat-toolbar>
<div class="table-container"> <div class="table-container">
<mat-table [dataSource]="dataSource" <table mat-table [dataSource]="dataSource"
matSort [matSortActive]="pageLink.sortOrder.property" [matSortDirection]="pageLink.sortDirection()" matSortDisableClear> matSort [matSortActive]="pageLink.sortOrder.property" [matSortDirection]="pageLink.sortDirection()" matSortDisableClear>
<ng-container matColumnDef="name"> <ng-container matColumnDef="name">
<mat-header-cell *matHeaderCellDef mat-sort-header style="width: 60%"> {{ 'dashboard.state-name' | translate }} </mat-header-cell> <mat-header-cell *matHeaderCellDef mat-sort-header style="flex: 0 0 60%"> {{ 'dashboard.state-name' | translate }} </mat-header-cell>
<mat-cell *matCellDef="let state"> <mat-cell *matCellDef="let state">
{{ state.name }} {{ state.name }}
</mat-cell> </mat-cell>
</ng-container> </ng-container>
<ng-container matColumnDef="id"> <ng-container matColumnDef="id">
<mat-header-cell *matHeaderCellDef mat-sort-header style="width: 40%"> {{ 'dashboard.state-id' | translate }} </mat-header-cell> <mat-header-cell *matHeaderCellDef mat-sort-header style="flex: 0 0 40%"> {{ 'dashboard.state-id' | translate }} </mat-header-cell>
<mat-cell *matCellDef="let state"> <mat-cell *matCellDef="let state">
{{ state.id }} {{ state.id }}
</mat-cell> </mat-cell>
@ -100,14 +100,14 @@
</mat-header-cell> </mat-header-cell>
<mat-cell *matCellDef="let state"> <mat-cell *matCellDef="let state">
<div fxFlex fxLayout="row"> <div fxFlex fxLayout="row">
<button mat-button mat-icon-button [disabled]="isLoading$ | async" <button mat-icon-button [disabled]="isLoading$ | async"
type="button" type="button"
matTooltip="{{ 'dashboard.edit-state' | translate }}" matTooltip="{{ 'dashboard.edit-state' | translate }}"
matTooltipPosition="above" matTooltipPosition="above"
(click)="editState($event, state)"> (click)="editState($event, state)">
<mat-icon>edit</mat-icon> <mat-icon>edit</mat-icon>
</button> </button>
<button [fxShow]="!state.root" mat-button mat-icon-button [disabled]="isLoading$ | async" <button [fxShow]="!state.root" mat-icon-button [disabled]="isLoading$ | async"
type="button" type="button"
matTooltip="{{ 'dashboard.delete-state' | translate }}" matTooltip="{{ 'dashboard.delete-state' | translate }}"
matTooltipPosition="above" matTooltipPosition="above"
@ -120,7 +120,7 @@
<mat-header-row class="mat-row-select" *matHeaderRowDef="displayedColumns; sticky: true"></mat-header-row> <mat-header-row class="mat-row-select" *matHeaderRowDef="displayedColumns; sticky: true"></mat-header-row>
<mat-row class="mat-row-select" <mat-row class="mat-row-select"
*matRowDef="let state; columns: displayedColumns;"></mat-row> *matRowDef="let state; columns: displayedColumns;"></mat-row>
</mat-table> </table>
<span [fxShow]="dataSource.isEmpty() | async" <span [fxShow]="dataSource.isEmpty() | async"
fxLayoutAlign="center center" fxLayoutAlign="center center"
class="no-data-found" translate>{{ 'dashboard.no-states-text' }}</span> class="no-data-found" translate>{{ 'dashboard.no-states-text' }}</span>
@ -135,15 +135,13 @@
</div> </div>
</fieldset> </fieldset>
</div> </div>
<div mat-dialog-actions fxLayout="row"> <div mat-dialog-actions fxLayoutAlign="end center">
<span fxFlex></span> <button mat-raised-button color="primary"
<button mat-button mat-raised-button color="primary"
type="submit" type="submit"
[disabled]="(isLoading$ | async) || statesFormGroup.invalid || !statesFormGroup.dirty"> [disabled]="(isLoading$ | async) || statesFormGroup.invalid || !statesFormGroup.dirty">
{{ 'action.save' | translate }} {{ 'action.save' | translate }}
</button> </button>
<button mat-button color="primary" <button mat-button color="primary"
style="margin-right: 20px;"
type="button" type="button"
[disabled]="(isLoading$ | async)" [disabled]="(isLoading$ | async)"
(click)="cancel()" cdkFocusInitial> (click)="cancel()" cdkFocusInitial>

8
ui-ngx/src/app/modules/home/pages/dashboard/states/states-component.directive.ts

@ -17,20 +17,16 @@
import { import {
ComponentRef, ComponentRef,
Directive, Directive,
ElementRef,
Input, Input,
OnChanges, OnChanges,
OnInit,
OnDestroy, OnDestroy,
OnInit,
SimpleChanges, SimpleChanges,
ViewContainerRef, ViewContainerRef
ChangeDetectorRef
} from '@angular/core'; } from '@angular/core';
import { DashboardPageComponent } from '@home/pages/dashboard/dashboard-page.component';
import { DashboardState } from '@shared/models/dashboard.models'; import { DashboardState } from '@shared/models/dashboard.models';
import { IDashboardController } from '@home/pages/dashboard/dashboard-page.models'; import { IDashboardController } from '@home/pages/dashboard/dashboard-page.models';
import { StatesControllerService } from '@home/pages/dashboard/states/states-controller.service'; import { StatesControllerService } from '@home/pages/dashboard/states/states-controller.service';
import { IStateController } from '@core/api/widget-api.models';
import { IStateControllerComponent } from '@home/pages/dashboard/states/state-controller.models'; import { IStateControllerComponent } from '@home/pages/dashboard/states/state-controller.models';
@Directive({ @Directive({

32
ui-ngx/src/app/modules/home/pages/widget/widget-editor.component.html

@ -34,23 +34,23 @@
</mat-select> </mat-select>
</mat-form-field> </mat-form-field>
<span fxFlex></span> <span fxFlex></span>
<button mat-button fxHide.xs fxHide.sm [disabled]="!iframeWidgetEditModeInited" <button mat-button fxHide.lt-md [disabled]="!iframeWidgetEditModeInited"
(click)="applyWidgetScript()" (click)="applyWidgetScript()"
matTooltip="{{ 'widget.run' | translate }} (CTRL + Return)" matTooltip="{{ 'widget.run' | translate }} (CTRL + Return)"
matTooltipPosition="below"> matTooltipPosition="below">
<mat-icon>play_arrow</mat-icon> <mat-icon>play_arrow</mat-icon>
<span translate>action.run</span> <span translate>action.run</span>
</button> </button>
<button mat-button mat-raised-button <button mat-raised-button
fxHide.xs fxHide.sm [disabled]="(isLoading$ | async) || undoDisabled()" fxHide.lt-md [disabled]="(isLoading$ | async) || undoDisabled()"
(click)="undoWidget()" (click)="undoWidget()"
matTooltip="{{ 'widget.undo' | translate }} (CTRL + Q)" matTooltip="{{ 'widget.undo' | translate }} (CTRL + Q)"
matTooltipPosition="below"> matTooltipPosition="below">
<mat-icon>undo</mat-icon> <mat-icon>undo</mat-icon>
<span translate>action.undo</span> <span translate>action.undo</span>
</button> </button>
<button *ngIf="!isReadOnly" mat-button mat-raised-button <button *ngIf="!isReadOnly" mat-raised-button
fxHide.xs fxHide.sm [disabled]="(isLoading$ | async) || saveDisabled()" fxHide.lt-md [disabled]="(isLoading$ | async) || saveDisabled()"
(click)="saveWidget()" (click)="saveWidget()"
[tb-circular-progress]="saveWidgetPending" [tb-circular-progress]="saveWidgetPending"
matTooltip="{{ 'widget.save' | translate }} (CTRL + S)" matTooltip="{{ 'widget.save' | translate }} (CTRL + S)"
@ -58,8 +58,8 @@
<mat-icon>save</mat-icon> <mat-icon>save</mat-icon>
<span translate>action.save</span> <span translate>action.save</span>
</button> </button>
<button mat-button mat-raised-button <button mat-raised-button
fxHide.xs fxHide.sm [disabled]="(isLoading$ | async) || saveAsDisabled()" fxHide.lt-md [disabled]="(isLoading$ | async) || saveAsDisabled()"
(click)="saveWidgetAs()" (click)="saveWidgetAs()"
[tb-circular-progress]="saveWidgetAsPending" [tb-circular-progress]="saveWidgetAsPending"
matTooltip="{{ 'widget.saveAs' | translate }} (Shift + CTRL + S)" matTooltip="{{ 'widget.saveAs' | translate }} (Shift + CTRL + S)"
@ -68,14 +68,14 @@
<span translate>action.saveAs</span> <span translate>action.saveAs</span>
</button> </button>
<button mat-button <button mat-button
fxHide.xs fxHide.sm fxHide.lt-md
(click)="fullscreen = !fullscreen" (click)="fullscreen = !fullscreen"
matTooltip="{{ 'widget.toggle-fullscreen' | translate }} (Shift + CTRL + F)" matTooltip="{{ 'widget.toggle-fullscreen' | translate }} (Shift + CTRL + F)"
matTooltipPosition="below"> matTooltipPosition="below">
<mat-icon>{{ fullscreen ? 'fullscreen_exit' : 'fullscreen' }}</mat-icon> <mat-icon>{{ fullscreen ? 'fullscreen_exit' : 'fullscreen' }}</mat-icon>
<span translate>widget.toggle-fullscreen</span> <span translate>widget.toggle-fullscreen</span>
</button> </button>
<button mat-button mat-icon-button fxHide.gt-sm <button mat-icon-button fxHide.gt-sm
[matMenuTriggerFor]="widgetEditMenu"> [matMenuTriggerFor]="widgetEditMenu">
<mat-icon>more_vert</mat-icon> <mat-icon>more_vert</mat-icon>
</button> </button>
@ -123,7 +123,7 @@
(ngModelChange)="isDirty = true" (ngModelChange)="isDirty = true"
placeholder="{{ 'widget.resource-url' | translate }}"/> placeholder="{{ 'widget.resource-url' | translate }}"/>
</mat-form-field> </mat-form-field>
<button mat-button mat-icon-button color="primary" <button mat-icon-button color="primary"
[disabled]="isLoading$ | async" [disabled]="isLoading$ | async"
(click)="removeResource(i)" (click)="removeResource(i)"
matTooltip="{{'widget.remove-resource' | translate}}" matTooltip="{{'widget.remove-resource' | translate}}"
@ -132,7 +132,7 @@
</button> </button>
</div> </div>
<div style="margin-top: 6px;"> <div style="margin-top: 6px;">
<button mat-button mat-raised-button color="primary" <button mat-raised-button color="primary"
[disabled]="isLoading$ | async" [disabled]="isLoading$ | async"
(click)="addResource()" (click)="addResource()"
matTooltip="{{'widget.add-resource' | translate}}" matTooltip="{{'widget.add-resource' | translate}}"
@ -165,7 +165,7 @@
<button mat-button (click)="beautifyCss()"> <button mat-button (click)="beautifyCss()">
{{ 'widget.tidy' | translate }} {{ 'widget.tidy' | translate }}
</button> </button>
<button mat-button mat-icon-button class="tb-mat-32" <button mat-icon-button class="tb-mat-32"
(click)="cssFullscreen = !cssFullscreen" (click)="cssFullscreen = !cssFullscreen"
matTooltip="{{(cssFullscreen ? 'fullscreen.exit' : 'fullscreen.expand') | translate}}" matTooltip="{{(cssFullscreen ? 'fullscreen.exit' : 'fullscreen.expand') | translate}}"
matTooltipPosition="above"> matTooltipPosition="above">
@ -185,7 +185,7 @@
<button mat-button (click)="beautifyJson()"> <button mat-button (click)="beautifyJson()">
{{ 'widget.tidy' | translate }} {{ 'widget.tidy' | translate }}
</button> </button>
<button mat-button mat-icon-button class="tb-mat-32" <button mat-icon-button class="tb-mat-32"
(click)="jsonSettingsFullscreen = !jsonSettingsFullscreen" (click)="jsonSettingsFullscreen = !jsonSettingsFullscreen"
matTooltip="{{(jsonSettingsFullscreen ? 'fullscreen.exit' : 'fullscreen.expand') | translate}}" matTooltip="{{(jsonSettingsFullscreen ? 'fullscreen.exit' : 'fullscreen.expand') | translate}}"
matTooltipPosition="above"> matTooltipPosition="above">
@ -201,7 +201,7 @@
<button mat-button (click)="beautifyDataKeyJson()"> <button mat-button (click)="beautifyDataKeyJson()">
{{ 'widget.tidy' | translate }} {{ 'widget.tidy' | translate }}
</button> </button>
<button mat-button mat-icon-button class="tb-mat-32" <button mat-icon-button class="tb-mat-32"
(click)="jsonDataKeySettingsFullscreen = !jsonDataKeySettingsFullscreen" (click)="jsonDataKeySettingsFullscreen = !jsonDataKeySettingsFullscreen"
matTooltip="{{(jsonDataKeySettingsFullscreen ? 'fullscreen.exit' : 'fullscreen.expand') | translate}}" matTooltip="{{(jsonDataKeySettingsFullscreen ? 'fullscreen.exit' : 'fullscreen.expand') | translate}}"
matTooltipPosition="above"> matTooltipPosition="above">
@ -222,7 +222,7 @@
<button mat-button (click)="beautifyJs()"> <button mat-button (click)="beautifyJs()">
{{ 'widget.tidy' | translate }} {{ 'widget.tidy' | translate }}
</button> </button>
<button mat-button mat-icon-button class="tb-mat-32" <button mat-icon-button class="tb-mat-32"
(click)="javascriptFullscreen = !javascriptFullscreen" (click)="javascriptFullscreen = !javascriptFullscreen"
matTooltip="{{(javascriptFullscreen ? 'fullscreen.exit' : 'fullscreen.expand') | translate}}" matTooltip="{{(javascriptFullscreen ? 'fullscreen.exit' : 'fullscreen.expand') | translate}}"
matTooltipPosition="above"> matTooltipPosition="above">
@ -240,7 +240,7 @@
<div tb-fullscreen [fullscreen]="iFrameFullscreen" style="width: 100%; height: 100%;"> <div tb-fullscreen [fullscreen]="iFrameFullscreen" style="width: 100%; height: 100%;">
<iframe #widgetIFrame frameborder="0" height="100%" width="100%"></iframe> <iframe #widgetIFrame frameborder="0" height="100%" width="100%"></iframe>
<div style="position: absolute; top: 10px; left: 10px; bottom: initial;"> <div style="position: absolute; top: 10px; left: 10px; bottom: initial;">
<button mat-button mat-icon-button <button mat-icon-button
class="tb-fullscreen-button-style" class="tb-fullscreen-button-style"
(click)="iFrameFullscreen = !iFrameFullscreen" (click)="iFrameFullscreen = !iFrameFullscreen"
matTooltip="{{(iFrameFullscreen ? 'fullscreen.exit' : 'fullscreen.expand') | translate}}" matTooltip="{{(iFrameFullscreen ? 'fullscreen.exit' : 'fullscreen.expand') | translate}}"

7
ui-ngx/src/app/modules/home/pages/widget/widget-editor.component.ts

@ -21,7 +21,7 @@ import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state'; import { AppState } from '@core/core.state';
import { WidgetService } from '@core/http/widget.service'; import { WidgetService } from '@core/http/widget.service';
import { toWidgetInfo, WidgetInfo } from '@home/models/widget-component.models'; import { toWidgetInfo, WidgetInfo } from '@home/models/widget-component.models';
import { WidgetConfig, widgetType, WidgetType, widgetTypesData, Widget } from '@shared/models/widget.models'; import { Widget, WidgetConfig, WidgetType, widgetType, widgetTypesData } from '@shared/models/widget.models';
import { ActivatedRoute, Router } from '@angular/router'; import { ActivatedRoute, Router } from '@angular/router';
import { deepClone } from '@core/utils'; import { deepClone } from '@core/utils';
import { HasDirtyFlag } from '@core/guards/confirm-on-exit.guard'; import { HasDirtyFlag } from '@core/guards/confirm-on-exit.guard';
@ -29,7 +29,7 @@ import { AuthUser } from '@shared/models/user.model';
import { getCurrentAuthUser } from '@core/auth/auth.selectors'; import { getCurrentAuthUser } from '@core/auth/auth.selectors';
import { Authority } from '@shared/models/authority.enum'; import { Authority } from '@shared/models/authority.enum';
import { NULL_UUID } from '@shared/models/id/has-uuid'; import { NULL_UUID } from '@shared/models/id/has-uuid';
import { Hotkey, HotkeysService } from 'angular2-hotkeys'; import { Hotkey } from 'angular2-hotkeys';
import { TranslateService } from '@ngx-translate/core'; import { TranslateService } from '@ngx-translate/core';
import { getCurrentIsLoading } from '@app/core/interceptors/load.selectors'; import { getCurrentIsLoading } from '@app/core/interceptors/load.selectors';
import * as ace from 'ace-builds'; import * as ace from 'ace-builds';
@ -38,15 +38,14 @@ import { CancelAnimationFrame, RafService } from '@core/services/raf.service';
import { WINDOW } from '@core/services/window.service'; import { WINDOW } from '@core/services/window.service';
import { WindowMessage } from '@shared/models/window-message.model'; import { WindowMessage } from '@shared/models/window-message.model';
import { ExceptionData } from '@shared/models/error.models'; import { ExceptionData } from '@shared/models/error.models';
import Timeout = NodeJS.Timeout;
import { ActionNotificationHide, ActionNotificationShow } from '@core/notification/notification.actions'; import { ActionNotificationHide, ActionNotificationShow } from '@core/notification/notification.actions';
import { MatDialog } from '@angular/material/dialog'; import { MatDialog } from '@angular/material/dialog';
import { SelectWidgetTypeDialogComponent } from '@home/pages/widget/select-widget-type-dialog.component';
import { import {
SaveWidgetTypeAsDialogComponent, SaveWidgetTypeAsDialogComponent,
SaveWidgetTypeAsDialogResult SaveWidgetTypeAsDialogResult
} from '@home/pages/widget/save-widget-type-as-dialog.component'; } from '@home/pages/widget/save-widget-type-as-dialog.component';
import { Subscription } from 'rxjs'; import { Subscription } from 'rxjs';
import Timeout = NodeJS.Timeout;
// @dynamic // @dynamic
@Component({ @Component({

6
ui-ngx/src/app/shared/components/color-input.component.scss

@ -18,3 +18,9 @@
width: 100%; width: 100%;
} }
} }
:host ::ng-deep {
.mat-form-field-infix{
width: 150px;
}
}

22
ui-ngx/src/app/shared/components/color-input.component.ts

@ -14,30 +14,12 @@
/// limitations under the License. /// limitations under the License.
/// ///
import { Component, ElementRef, forwardRef, Input, OnInit, ViewChild } from '@angular/core'; import { Component, forwardRef, Input, OnInit } from '@angular/core';
import { PageComponent } from '@shared/components/page.component'; import { PageComponent } from '@shared/components/page.component';
import { Store } from '@ngrx/store'; import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state'; import { AppState } from '@core/core.state';
import { DataKey, DatasourceType } from '@shared/models/widget.models'; import { ControlValueAccessor, FormBuilder, FormGroup, NG_VALUE_ACCESSOR, Validators } from '@angular/forms';
import {
ControlValueAccessor,
FormBuilder,
FormControl,
FormGroup,
NG_VALIDATORS,
NG_VALUE_ACCESSOR,
Validator,
Validators
} from '@angular/forms';
import { UtilsService } from '@core/services/utils.service';
import { TranslateService } from '@ngx-translate/core'; import { TranslateService } from '@ngx-translate/core';
import { MatDialog } from '@angular/material/dialog';
import { EntityService } from '@core/http/entity.service';
import { DataKeysCallbacks } from '@home/components/widget/data-keys.component.models';
import { DataKeyType } from '@shared/models/telemetry/telemetry.models';
import { Observable, of } from 'rxjs';
import { map, mergeMap, tap } from 'rxjs/operators';
import { alarmFields } from '@shared/models/alarm.models';
import { coerceBooleanProperty } from '@angular/cdk/coercion'; import { coerceBooleanProperty } from '@angular/cdk/coercion';
import { DialogService } from '@core/services/dialog.service'; import { DialogService } from '@core/services/dialog.service';

31
ui-ngx/src/app/shared/components/dashboard-autocomplete.component.ts

@ -14,22 +14,21 @@
/// limitations under the License. /// limitations under the License.
/// ///
import {AfterViewInit, Component, ElementRef, forwardRef, Input, OnInit, ViewChild} from '@angular/core'; import { AfterViewInit, Component, ElementRef, forwardRef, Input, OnInit, ViewChild } from '@angular/core';
import {ControlValueAccessor, FormBuilder, FormGroup, NG_VALUE_ACCESSOR} from '@angular/forms'; import { ControlValueAccessor, FormBuilder, FormGroup, NG_VALUE_ACCESSOR } from '@angular/forms';
import {Observable, of} from 'rxjs'; import { Observable, of } from 'rxjs';
import {PageLink} from '@shared/models/page/page-link'; import { PageLink } from '@shared/models/page/page-link';
import {Direction} from '@shared/models/page/sort-order'; import { Direction } from '@shared/models/page/sort-order';
import {map, mergeMap, startWith, tap} from 'rxjs/operators'; import { map, mergeMap, startWith, tap } from 'rxjs/operators';
import {PageData, emptyPageData} from '@shared/models/page/page-data'; import { emptyPageData, PageData } from '@shared/models/page/page-data';
import {DashboardInfo} from '@app/shared/models/dashboard.models'; import { DashboardInfo } from '@app/shared/models/dashboard.models';
import {DashboardId} from '@app/shared/models/id/dashboard-id'; import { DashboardService } from '@core/http/dashboard.service';
import {DashboardService} from '@core/http/dashboard.service'; import { Store } from '@ngrx/store';
import {Store} from '@ngrx/store'; import { AppState } from '@app/core/core.state';
import {AppState} from '@app/core/core.state'; import { getCurrentAuthUser } from '@app/core/auth/auth.selectors';
import {getCurrentAuthUser} from '@app/core/auth/auth.selectors'; import { Authority } from '@shared/models/authority.enum';
import {Authority} from '@shared/models/authority.enum'; import { TranslateService } from '@ngx-translate/core';
import {TranslateService} from '@ngx-translate/core'; import { coerceBooleanProperty } from '@angular/cdk/coercion';
import {coerceBooleanProperty} from '@angular/cdk/coercion';
@Component({ @Component({
selector: 'tb-dashboard-autocomplete', selector: 'tb-dashboard-autocomplete',

2
ui-ngx/src/app/shared/components/dashboard-select.component.html

@ -15,7 +15,7 @@
limitations under the License. limitations under the License.
--> -->
<mat-select fxHide.xs fxHide.sm fxHide.md <mat-select fxHide.lt-lg
[required]="required" [required]="required"
[disabled]="disabled" [disabled]="disabled"
[(ngModel)]="dashboardId" [(ngModel)]="dashboardId"

39
ui-ngx/src/app/shared/components/entity/entity-type-list.component.ts

@ -14,39 +14,18 @@
/// limitations under the License. /// limitations under the License.
/// ///
import { import { AfterViewInit, Component, ElementRef, forwardRef, Input, OnInit, ViewChild } from '@angular/core';
AfterContentInit, import { ControlValueAccessor, FormBuilder, FormGroup, NG_VALUE_ACCESSOR, Validators } from '@angular/forms';
AfterViewInit, import { Observable, of } from 'rxjs';
Component, import { filter, map, mergeMap, share, tap } from 'rxjs/operators';
ElementRef, import { Store } from '@ngrx/store';
forwardRef, import { AppState } from '@app/core/core.state';
Input, import { TranslateService } from '@ngx-translate/core';
OnInit,
SkipSelf,
ViewChild
} from '@angular/core';
import {
ControlValueAccessor,
FormBuilder,
FormControl,
FormGroup,
FormGroupDirective,
NG_VALUE_ACCESSOR, NgForm, Validators
} from '@angular/forms';
import {Observable, of} from 'rxjs';
import {map, mergeMap, startWith, tap, share, pairwise, filter} from 'rxjs/operators';
import {Store} from '@ngrx/store';
import {AppState} from '@app/core/core.state';
import {TranslateService} from '@ngx-translate/core';
import { AliasEntityType, EntityType, entityTypeTranslations } from '@shared/models/entity-type.models'; import { AliasEntityType, EntityType, entityTypeTranslations } from '@shared/models/entity-type.models';
import {BaseData} from '@shared/models/base-data'; import { EntityService } from '@core/http/entity.service';
import {EntityId} from '@shared/models/id/entity-id'; import { MatAutocomplete } from '@angular/material/autocomplete';
import {EntityService} from '@core/http/entity.service';
import { MatAutocomplete, MatAutocompleteSelectedEvent } from '@angular/material/autocomplete';
import { MatChipList } from '@angular/material/chips'; import { MatChipList } from '@angular/material/chips';
import { ErrorStateMatcher } from '@angular/material/core';
import { coerceBooleanProperty } from '@angular/cdk/coercion'; import { coerceBooleanProperty } from '@angular/cdk/coercion';
import { emptyPageData } from '@shared/models/page/page-data';
interface EntityTypeInfo { interface EntityTypeInfo {
name: string; name: string;

11
ui-ngx/src/app/shared/components/fab-toolbar.component.ts

@ -15,19 +15,20 @@
/// ///
import { import {
AfterViewInit,
Component, Component,
Directive,
ElementRef, ElementRef,
Inject,
Input, Input,
OnChanges, OnChanges,
OnDestroy,
OnInit, OnInit,
Renderer2,
ViewEncapsulation,
SimpleChanges, SimpleChanges,
Inject, AfterViewInit, AfterViewChecked, Directive, OnDestroy ViewEncapsulation
} from '@angular/core'; } from '@angular/core';
import { PageComponent } from '@shared/components/page.component';
import { WINDOW } from '@core/services/window.service'; import { WINDOW } from '@core/services/window.service';
import { mixinColor, CanColorCtor } from '@angular/material/core'; import { CanColorCtor, mixinColor } from '@angular/material/core';
export declare type FabToolbarDirection = 'left' | 'right'; export declare type FabToolbarDirection = 'left' | 'right';

1
ui-ngx/src/app/shared/components/json-form/react/json-form-checkbox.tsx

@ -33,7 +33,6 @@ class ThingsboardCheckbox extends React.Component<JsonFormFieldProps, JsonFormFi
onChange={(e, checked) => { onChange={(e, checked) => {
this.props.onChangeValidate(e); this.props.onChangeValidate(e);
}} }}
style={{paddingTop: '14px'}}
/> />
} }
label={this.props.form.title} label={this.props.form.title}

2
ui-ngx/src/app/shared/components/material-icon-select.component.html

@ -17,7 +17,7 @@
--> -->
<div fxLayout="row" [formGroup]="materialIconFormGroup"> <div fxLayout="row" [formGroup]="materialIconFormGroup">
<mat-icon (click)="openIconDialog()">{{materialIconFormGroup.get('icon').value}}</mat-icon> <mat-icon (click)="openIconDialog()">{{materialIconFormGroup.get('icon').value}}</mat-icon>
<mat-form-field> <mat-form-field fxFlex>
<mat-label translate>icon.icon</mat-label> <mat-label translate>icon.icon</mat-label>
<input matInput formControlName="icon" (mousedown)="openIconDialog()"> <input matInput formControlName="icon" (mousedown)="openIconDialog()">
</mat-form-field> </mat-form-field>

6
ui-ngx/src/app/shared/components/material-icon-select.component.scss

@ -21,3 +21,9 @@
border: solid 1px rgba(0, 0, 0, .27); border: solid 1px rgba(0, 0, 0, .27);
} }
} }
:host ::ng-deep {
.mat-form-field-infix{
width: 146px;
}
}

24
ui-ngx/src/app/shared/components/material-icon-select.component.ts

@ -14,31 +14,11 @@
/// limitations under the License. /// limitations under the License.
/// ///
import { Component, ElementRef, forwardRef, Input, OnInit, ViewChild } from '@angular/core'; import { Component, forwardRef, Input, OnInit } from '@angular/core';
import { PageComponent } from '@shared/components/page.component'; import { PageComponent } from '@shared/components/page.component';
import { Store } from '@ngrx/store'; import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state'; import { AppState } from '@core/core.state';
import { DataKey, DatasourceType } from '@shared/models/widget.models'; import { ControlValueAccessor, FormBuilder, FormGroup, NG_VALUE_ACCESSOR } from '@angular/forms';
import {
ControlValueAccessor,
FormBuilder,
FormControl,
FormGroup,
NG_VALIDATORS,
NG_VALUE_ACCESSOR,
Validator,
Validators
} from '@angular/forms';
import { UtilsService } from '@core/services/utils.service';
import { TranslateService } from '@ngx-translate/core';
import { MatDialog } from '@angular/material/dialog';
import { EntityService } from '@core/http/entity.service';
import { DataKeysCallbacks } from '@home/components/widget/data-keys.component.models';
import { DataKeyType } from '@shared/models/telemetry/telemetry.models';
import { Observable, of } from 'rxjs';
import { map, mergeMap, tap } from 'rxjs/operators';
import { alarmFields } from '@shared/models/alarm.models';
import { coerceBooleanProperty } from '@angular/cdk/coercion';
import { DialogService } from '@core/services/dialog.service'; import { DialogService } from '@core/services/dialog.service';
@Component({ @Component({

2
ui-ngx/src/app/shared/components/relation/relation-type-autocomplete.component.html

@ -24,7 +24,7 @@
[matAutocomplete]="relationTypeAutocomplete"> [matAutocomplete]="relationTypeAutocomplete">
<button *ngIf="relationTypeFormGroup.get('relationType').value && !disabled" <button *ngIf="relationTypeFormGroup.get('relationType').value && !disabled"
type="button" type="button"
matSuffix mat-button mat-icon-button aria-label="Clear" matSuffix mat-icon-button aria-label="Clear"
(click)="clear()"> (click)="clear()">
<mat-icon class="material-icons">close</mat-icon> <mat-icon class="material-icons">close</mat-icon>
</button> </button>

28
ui-ngx/src/app/shared/components/relation/relation-type-autocomplete.component.ts

@ -14,27 +14,15 @@
/// limitations under the License. /// limitations under the License.
/// ///
import {AfterViewInit, Component, ElementRef, forwardRef, Input, OnInit, ViewChild, OnDestroy} from '@angular/core'; import { AfterViewInit, Component, ElementRef, forwardRef, Input, OnDestroy, OnInit, ViewChild } from '@angular/core';
import { ControlValueAccessor, FormBuilder, FormGroup, NG_VALUE_ACCESSOR, Validators } from '@angular/forms'; import { ControlValueAccessor, FormBuilder, FormGroup, NG_VALUE_ACCESSOR, Validators } from '@angular/forms';
import {Observable, of, throwError, Subscription} from 'rxjs'; import { Observable, of } from 'rxjs';
import {PageLink} from '@shared/models/page/page-link'; import { map, mergeMap, tap } from 'rxjs/operators';
import {Direction} from '@shared/models/page/sort-order'; import { Store } from '@ngrx/store';
import {filter, map, mergeMap, publishReplay, refCount, startWith, tap, publish} from 'rxjs/operators'; import { AppState } from '@app/core/core.state';
import {PageData, emptyPageData} from '@shared/models/page/page-data'; import { TranslateService } from '@ngx-translate/core';
import {DashboardInfo} from '@app/shared/models/dashboard.models'; import { BroadcastService } from '@app/core/services/broadcast.service';
import {DashboardId} from '@app/shared/models/id/dashboard-id'; import { coerceBooleanProperty } from '@angular/cdk/coercion';
import {DashboardService} from '@core/http/dashboard.service';
import {Store} from '@ngrx/store';
import {AppState} from '@app/core/core.state';
import {getCurrentAuthUser} from '@app/core/auth/auth.selectors';
import {Authority} from '@shared/models/authority.enum';
import {TranslateService} from '@ngx-translate/core';
import {DeviceService} from '@core/http/device.service';
import {EntitySubtype, EntityType} from '@app/shared/models/entity-type.models';
import {BroadcastService} from '@app/core/services/broadcast.service';
import {coerceBooleanProperty} from '@angular/cdk/coercion';
import {AssetService} from '@core/http/asset.service';
import {EntityViewService} from '@core/http/entity-view.service';
import { RelationTypes } from '@app/shared/models/relation.models'; import { RelationTypes } from '@app/shared/models/relation.models';
@Component({ @Component({

1
ui-ngx/src/styles.scss

@ -863,6 +863,7 @@ mat-label {
.mat-dialog-container { .mat-dialog-container {
> *:first-child, form { > *:first-child, form {
min-width: 100% !important; min-width: 100% !important;
height: 100vh;
} }
.mat-dialog-content { .mat-dialog-content {
max-height: 100%; max-height: 100%;

Loading…
Cancel
Save