Commit 72cfe8e411313e55fd5b88935aa4d0559494c04b
Committed by
GitHub
Merge pull request #5452 from ArtemDzhereleiko/imp/new-widget-settings
[3.3.2] UI: New widget settings layout
Showing
13 changed files
with
603 additions
and
675 deletions
@@ -49,7 +49,6 @@ import { EntityAliasSelectComponent } from '@home/components/alias/entity-alias- | @@ -49,7 +49,6 @@ import { EntityAliasSelectComponent } from '@home/components/alias/entity-alias- | ||
49 | import { DataKeysComponent } from '@home/components/widget/data-keys.component'; | 49 | import { DataKeysComponent } from '@home/components/widget/data-keys.component'; |
50 | import { DataKeyConfigDialogComponent } from '@home/components/widget/data-key-config-dialog.component'; | 50 | import { DataKeyConfigDialogComponent } from '@home/components/widget/data-key-config-dialog.component'; |
51 | import { DataKeyConfigComponent } from '@home/components/widget/data-key-config.component'; | 51 | import { DataKeyConfigComponent } from '@home/components/widget/data-key-config.component'; |
52 | -import { LegendConfigPanelComponent } from '@home/components/widget/legend-config-panel.component'; | ||
53 | import { LegendConfigComponent } from '@home/components/widget/legend-config.component'; | 52 | import { LegendConfigComponent } from '@home/components/widget/legend-config.component'; |
54 | import { ManageWidgetActionsComponent } from '@home/components/widget/action/manage-widget-actions.component'; | 53 | import { ManageWidgetActionsComponent } from '@home/components/widget/action/manage-widget-actions.component'; |
55 | import { WidgetActionDialogComponent } from '@home/components/widget/action/widget-action-dialog.component'; | 54 | import { WidgetActionDialogComponent } from '@home/components/widget/action/widget-action-dialog.component'; |
@@ -182,7 +181,6 @@ import { DeviceProfileCommonModule } from '@home/components/profile/device/commo | @@ -182,7 +181,6 @@ import { DeviceProfileCommonModule } from '@home/components/profile/device/commo | ||
182 | DataKeysComponent, | 181 | DataKeysComponent, |
183 | DataKeyConfigComponent, | 182 | DataKeyConfigComponent, |
184 | DataKeyConfigDialogComponent, | 183 | DataKeyConfigDialogComponent, |
185 | - LegendConfigPanelComponent, | ||
186 | LegendConfigComponent, | 184 | LegendConfigComponent, |
187 | ManageWidgetActionsComponent, | 185 | ManageWidgetActionsComponent, |
188 | WidgetActionDialogComponent, | 186 | WidgetActionDialogComponent, |
1 | -<!-- | ||
2 | - | ||
3 | - Copyright © 2016-2021 The Thingsboard Authors | ||
4 | - | ||
5 | - Licensed under the Apache License, Version 2.0 (the "License"); | ||
6 | - you may not use this file except in compliance with the License. | ||
7 | - You may obtain a copy of the License at | ||
8 | - | ||
9 | - http://www.apache.org/licenses/LICENSE-2.0 | ||
10 | - | ||
11 | - Unless required by applicable law or agreed to in writing, software | ||
12 | - distributed under the License is distributed on an "AS IS" BASIS, | ||
13 | - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
14 | - See the License for the specific language governing permissions and | ||
15 | - limitations under the License. | ||
16 | - | ||
17 | ---> | ||
18 | -<form [formGroup]="legendConfigForm"> | ||
19 | - <fieldset [disabled]="(isLoading$ | async)"> | ||
20 | - <div class="mat-content" style="height: 100%;"> | ||
21 | - <div class="mat-padding"> | ||
22 | - <section fxLayout="column"> | ||
23 | - <mat-form-field> | ||
24 | - <mat-label translate>legend.direction</mat-label> | ||
25 | - <mat-select matInput formControlName="direction" style="min-width: 150px;"> | ||
26 | - <mat-option *ngFor="let direction of legendDirections" [value]="direction"> | ||
27 | - {{ legendDirectionTranslations.get(legendDirection[direction]) | translate }} | ||
28 | - </mat-option> | ||
29 | - </mat-select> | ||
30 | - </mat-form-field> | ||
31 | - <mat-form-field> | ||
32 | - <mat-label translate>legend.position</mat-label> | ||
33 | - <mat-select matInput formControlName="position" style="min-width: 150px;"> | ||
34 | - <mat-option *ngFor="let pos of legendPositions" [value]="pos" | ||
35 | - [disabled]="legendConfigForm.get('direction').value === legendDirection.row && | ||
36 | - (pos === legendPosition.left || pos === legendPosition.right)"> | ||
37 | - {{ legendPositionTranslations.get(legendPosition[pos]) | translate }} | ||
38 | - </mat-option> | ||
39 | - </mat-select> | ||
40 | - </mat-form-field> | ||
41 | - <mat-checkbox formControlName="sortDataKeys"> | ||
42 | - {{ 'legend.sort-legend' | translate }} | ||
43 | - </mat-checkbox> | ||
44 | - <mat-checkbox formControlName="showMin"> | ||
45 | - {{ 'legend.show-min' | translate }} | ||
46 | - </mat-checkbox> | ||
47 | - <mat-checkbox formControlName="showMax"> | ||
48 | - {{ 'legend.show-max' | translate }} | ||
49 | - </mat-checkbox> | ||
50 | - <mat-checkbox formControlName="showAvg"> | ||
51 | - {{ 'legend.show-avg' | translate }} | ||
52 | - </mat-checkbox> | ||
53 | - <mat-checkbox formControlName="showTotal"> | ||
54 | - {{ 'legend.show-total' | translate }} | ||
55 | - </mat-checkbox> | ||
56 | - </section> | ||
57 | - </div> | ||
58 | - </div> | ||
59 | - </fieldset> | ||
60 | -</form> |
1 | -/** | ||
2 | - * Copyright © 2016-2021 The Thingsboard Authors | ||
3 | - * | ||
4 | - * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | - * you may not use this file except in compliance with the License. | ||
6 | - * You may obtain a copy of the License at | ||
7 | - * | ||
8 | - * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | - * | ||
10 | - * Unless required by applicable law or agreed to in writing, software | ||
11 | - * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | - * See the License for the specific language governing permissions and | ||
14 | - * limitations under the License. | ||
15 | - */ | ||
16 | -:host { | ||
17 | - width: 100%; | ||
18 | - height: 100%; | ||
19 | - form, | ||
20 | - fieldset { | ||
21 | - height: 100%; | ||
22 | - } | ||
23 | - | ||
24 | - .mat-content { | ||
25 | - overflow: hidden; | ||
26 | - background-color: #fff; | ||
27 | - } | ||
28 | - | ||
29 | - .mat-padding { | ||
30 | - padding: 16px; | ||
31 | - } | ||
32 | -} |
1 | -/// | ||
2 | -/// Copyright © 2016-2021 The Thingsboard Authors | ||
3 | -/// | ||
4 | -/// Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | -/// you may not use this file except in compliance with the License. | ||
6 | -/// You may obtain a copy of the License at | ||
7 | -/// | ||
8 | -/// http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | -/// | ||
10 | -/// Unless required by applicable law or agreed to in writing, software | ||
11 | -/// distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | -/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | -/// See the License for the specific language governing permissions and | ||
14 | -/// limitations under the License. | ||
15 | -/// | ||
16 | - | ||
17 | -import { Component, Inject, InjectionToken, OnInit, ViewContainerRef } from '@angular/core'; | ||
18 | -import { OverlayRef } from '@angular/cdk/overlay'; | ||
19 | -import { PageComponent } from '@shared/components/page.component'; | ||
20 | -import { Store } from '@ngrx/store'; | ||
21 | -import { AppState } from '@core/core.state'; | ||
22 | -import { FormBuilder, FormGroup } from '@angular/forms'; | ||
23 | -import { | ||
24 | - LegendConfig, | ||
25 | - LegendDirection, | ||
26 | - legendDirectionTranslationMap, | ||
27 | - LegendPosition, | ||
28 | - legendPositionTranslationMap | ||
29 | -} from '@shared/models/widget.models'; | ||
30 | - | ||
31 | -export const LEGEND_CONFIG_PANEL_DATA = new InjectionToken<any>('LegendConfigPanelData'); | ||
32 | - | ||
33 | -export interface LegendConfigPanelData { | ||
34 | - legendConfig: LegendConfig; | ||
35 | - legendConfigUpdated: (legendConfig: LegendConfig) => void; | ||
36 | -} | ||
37 | - | ||
38 | -@Component({ | ||
39 | - selector: 'tb-legend-config-panel', | ||
40 | - templateUrl: './legend-config-panel.component.html', | ||
41 | - styleUrls: ['./legend-config-panel.component.scss'] | ||
42 | -}) | ||
43 | -export class LegendConfigPanelComponent extends PageComponent implements OnInit { | ||
44 | - | ||
45 | - legendConfigForm: FormGroup; | ||
46 | - | ||
47 | - legendDirection = LegendDirection; | ||
48 | - | ||
49 | - legendDirections = Object.keys(LegendDirection); | ||
50 | - | ||
51 | - legendDirectionTranslations = legendDirectionTranslationMap; | ||
52 | - | ||
53 | - legendPosition = LegendPosition; | ||
54 | - | ||
55 | - legendPositions = Object.keys(LegendPosition); | ||
56 | - | ||
57 | - legendPositionTranslations = legendPositionTranslationMap; | ||
58 | - | ||
59 | - constructor(@Inject(LEGEND_CONFIG_PANEL_DATA) public data: LegendConfigPanelData, | ||
60 | - public overlayRef: OverlayRef, | ||
61 | - protected store: Store<AppState>, | ||
62 | - public fb: FormBuilder, | ||
63 | - public viewContainerRef: ViewContainerRef) { | ||
64 | - super(store); | ||
65 | - } | ||
66 | - | ||
67 | - ngOnInit(): void { | ||
68 | - this.legendConfigForm = this.fb.group({ | ||
69 | - direction: [this.data.legendConfig.direction, []], | ||
70 | - position: [this.data.legendConfig.position, []], | ||
71 | - sortDataKeys: [this.data.legendConfig.sortDataKeys, []], | ||
72 | - showMin: [this.data.legendConfig.showMin, []], | ||
73 | - showMax: [this.data.legendConfig.showMax, []], | ||
74 | - showAvg: [this.data.legendConfig.showAvg, []], | ||
75 | - showTotal: [this.data.legendConfig.showTotal, []] | ||
76 | - }); | ||
77 | - this.legendConfigForm.get('direction').valueChanges.subscribe((direction: LegendDirection) => { | ||
78 | - this.onDirectionChanged(direction); | ||
79 | - }); | ||
80 | - this.onDirectionChanged(this.data.legendConfig.direction); | ||
81 | - this.legendConfigForm.valueChanges.subscribe(() => { | ||
82 | - this.update(); | ||
83 | - }); | ||
84 | - } | ||
85 | - | ||
86 | - private onDirectionChanged(direction: LegendDirection) { | ||
87 | - if (direction === LegendDirection.row) { | ||
88 | - let position: LegendPosition = this.legendConfigForm.get('position').value; | ||
89 | - if (position !== LegendPosition.bottom && position !== LegendPosition.top) { | ||
90 | - position = LegendPosition.bottom; | ||
91 | - } | ||
92 | - this.legendConfigForm.patchValue( | ||
93 | - { | ||
94 | - position | ||
95 | - }, {emitEvent: false} | ||
96 | - ); | ||
97 | - } | ||
98 | - } | ||
99 | - | ||
100 | - update() { | ||
101 | - const newLegendConfig: LegendConfig = this.legendConfigForm.value; | ||
102 | - this.data.legendConfigUpdated(newLegendConfig); | ||
103 | - } | ||
104 | - | ||
105 | -} |
@@ -15,9 +15,43 @@ | @@ -15,9 +15,43 @@ | ||
15 | limitations under the License. | 15 | limitations under the License. |
16 | 16 | ||
17 | --> | 17 | --> |
18 | -<button cdkOverlayOrigin #legendConfigPanelOrigin="cdkOverlayOrigin" [disabled]="disabled" | ||
19 | - type="button" | ||
20 | - mat-button mat-raised-button color="primary" (click)="openEditMode()"> | ||
21 | - <mat-icon class="material-icons">toc</mat-icon> | ||
22 | - <span translate>legend.settings</span> | ||
23 | -</button> | 18 | +<form [formGroup]="legendConfigForm"> |
19 | + <div fxLayout.xs="column" fxLayoutAlign.xs="center" fxLayout="row" fxLayoutAlign="start center" | ||
20 | + fxLayoutGap="8px"> | ||
21 | + <mat-form-field fxFlex> | ||
22 | + <mat-label translate>legend.direction</mat-label> | ||
23 | + <mat-select matInput formControlName="direction"> | ||
24 | + <mat-option *ngFor="let direction of legendDirections" [value]="direction"> | ||
25 | + {{ legendDirectionTranslations.get(legendDirection[direction]) | translate }} | ||
26 | + </mat-option> | ||
27 | + </mat-select> | ||
28 | + </mat-form-field> | ||
29 | + <mat-form-field fxFlex> | ||
30 | + <mat-label translate>legend.position</mat-label> | ||
31 | + <mat-select matInput formControlName="position"> | ||
32 | + <mat-option *ngFor="let pos of legendPositions" [value]="pos" | ||
33 | + [disabled]="legendConfigForm.get('direction').value === legendDirection.row && | ||
34 | + (pos === legendPosition.left || pos === legendPosition.right)"> | ||
35 | + {{ legendPositionTranslations.get(legendPosition[pos]) | translate }} | ||
36 | + </mat-option> | ||
37 | + </mat-select> | ||
38 | + </mat-form-field> | ||
39 | + </div> | ||
40 | + <div fxLayout.xs="column" fxLayoutAlign.xs="center" fxLayout="row wrap" fxLayoutAlign="space-between center" fxLayoutGap="8px"> | ||
41 | + <mat-checkbox formControlName="showMin" fxFlex="48"> | ||
42 | + {{ 'legend.show-min' | translate }} | ||
43 | + </mat-checkbox> | ||
44 | + <mat-checkbox formControlName="showMax" fxFlex="48"> | ||
45 | + {{ 'legend.show-max' | translate }} | ||
46 | + </mat-checkbox> | ||
47 | + <mat-checkbox formControlName="showAvg" fxFlex="48"> | ||
48 | + {{ 'legend.show-avg' | translate }} | ||
49 | + </mat-checkbox> | ||
50 | + <mat-checkbox formControlName="showTotal" fxFlex="48"> | ||
51 | + {{ 'legend.show-total' | translate }} | ||
52 | + </mat-checkbox> | ||
53 | + <mat-checkbox formControlName="sortDataKeys" fxFlex="48"> | ||
54 | + {{ 'legend.sort-legend' | translate }} | ||
55 | + </mat-checkbox> | ||
56 | + </div> | ||
57 | +</form> |
@@ -14,32 +14,17 @@ | @@ -14,32 +14,17 @@ | ||
14 | /// limitations under the License. | 14 | /// limitations under the License. |
15 | /// | 15 | /// |
16 | 16 | ||
17 | +import { Component, forwardRef, Input, OnDestroy, OnInit } from '@angular/core'; | ||
18 | +import { ControlValueAccessor, FormBuilder, FormGroup, NG_VALUE_ACCESSOR } from '@angular/forms'; | ||
19 | +import { isDefined } from '@core/utils'; | ||
17 | import { | 20 | import { |
18 | - Component, | ||
19 | - forwardRef, | ||
20 | - Inject, | ||
21 | - Injector, | ||
22 | - Input, | ||
23 | - OnDestroy, | ||
24 | - OnInit, | ||
25 | - StaticProvider, | ||
26 | - ViewChild, | ||
27 | - ViewContainerRef | ||
28 | -} from '@angular/core'; | ||
29 | -import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms'; | ||
30 | -import { DOCUMENT } from '@angular/common'; | ||
31 | -import { CdkOverlayOrigin, ConnectedPosition, Overlay, OverlayConfig, OverlayRef } from '@angular/cdk/overlay'; | ||
32 | -import { ComponentPortal } from '@angular/cdk/portal'; | ||
33 | -import { MediaBreakpoints } from '@shared/models/constants'; | ||
34 | -import { BreakpointObserver } from '@angular/cdk/layout'; | ||
35 | -import { WINDOW } from '@core/services/window.service'; | ||
36 | -import { deepClone } from '@core/utils'; | ||
37 | -import { LegendConfig } from '@shared/models/widget.models'; | ||
38 | -import { | ||
39 | - LEGEND_CONFIG_PANEL_DATA, | ||
40 | - LegendConfigPanelComponent, | ||
41 | - LegendConfigPanelData | ||
42 | -} from '@home/components/widget/legend-config-panel.component'; | 21 | + LegendConfig, |
22 | + LegendDirection, | ||
23 | + legendDirectionTranslationMap, | ||
24 | + LegendPosition, | ||
25 | + legendPositionTranslationMap | ||
26 | +} from '@shared/models/widget.models'; | ||
27 | +import { Subscription } from 'rxjs'; | ||
43 | 28 | ||
44 | // @dynamic | 29 | // @dynamic |
45 | @Component({ | 30 | @Component({ |
@@ -58,105 +43,60 @@ export class LegendConfigComponent implements OnInit, OnDestroy, ControlValueAcc | @@ -58,105 +43,60 @@ export class LegendConfigComponent implements OnInit, OnDestroy, ControlValueAcc | ||
58 | 43 | ||
59 | @Input() disabled: boolean; | 44 | @Input() disabled: boolean; |
60 | 45 | ||
61 | - @ViewChild('legendConfigPanelOrigin') legendConfigPanelOrigin: CdkOverlayOrigin; | ||
62 | - | ||
63 | - innerValue: LegendConfig; | 46 | + legendConfigForm: FormGroup; |
47 | + legendDirection = LegendDirection; | ||
48 | + legendDirections = Object.keys(LegendDirection); | ||
49 | + legendDirectionTranslations = legendDirectionTranslationMap; | ||
50 | + legendPosition = LegendPosition; | ||
51 | + legendPositions = Object.keys(LegendPosition); | ||
52 | + legendPositionTranslations = legendPositionTranslationMap; | ||
64 | 53 | ||
54 | + private legendSettingsFormChanges$: Subscription; | ||
55 | + private legendSettingsFormDirectionChanges$: Subscription; | ||
65 | private propagateChange = (_: any) => {}; | 56 | private propagateChange = (_: any) => {}; |
66 | 57 | ||
67 | - constructor(private overlay: Overlay, | ||
68 | - public viewContainerRef: ViewContainerRef, | ||
69 | - public breakpointObserver: BreakpointObserver, | ||
70 | - @Inject(DOCUMENT) private document: Document, | ||
71 | - @Inject(WINDOW) private window: Window) { | 58 | + constructor(private fb: FormBuilder) { |
72 | } | 59 | } |
73 | 60 | ||
74 | ngOnInit(): void { | 61 | ngOnInit(): void { |
62 | + this.legendConfigForm = this.fb.group({ | ||
63 | + direction: [null, []], | ||
64 | + position: [null, []], | ||
65 | + sortDataKeys: [null, []], | ||
66 | + showMin: [null, []], | ||
67 | + showMax: [null, []], | ||
68 | + showAvg: [null, []], | ||
69 | + showTotal: [null, []] | ||
70 | + }); | ||
71 | + this.legendSettingsFormDirectionChanges$ = this.legendConfigForm.get('direction').valueChanges | ||
72 | + .subscribe((direction: LegendDirection) => { | ||
73 | + this.onDirectionChanged(direction); | ||
74 | + }); | ||
75 | + this.legendSettingsFormChanges$ = this.legendConfigForm.valueChanges.subscribe( | ||
76 | + () => this.legendConfigUpdated() | ||
77 | + ); | ||
75 | } | 78 | } |
76 | 79 | ||
77 | - ngOnDestroy(): void { | ||
78 | - } | ||
79 | - | ||
80 | - openEditMode() { | ||
81 | - if (this.disabled) { | ||
82 | - return; | ||
83 | - } | ||
84 | - const isGtSm = this.breakpointObserver.isMatched(MediaBreakpoints['gt-sm']); | ||
85 | - const position = this.overlay.position(); | ||
86 | - const config = new OverlayConfig({ | ||
87 | - panelClass: 'tb-legend-config-panel', | ||
88 | - backdropClass: 'cdk-overlay-transparent-backdrop', | ||
89 | - hasBackdrop: isGtSm, | ||
90 | - }); | ||
91 | - if (isGtSm) { | ||
92 | - config.minWidth = '220px'; | ||
93 | - config.maxHeight = '300px'; | ||
94 | - const panelHeight = 220; | ||
95 | - const panelWidth = 220; | ||
96 | - const el = this.legendConfigPanelOrigin.elementRef.nativeElement; | ||
97 | - const offset = el.getBoundingClientRect(); | ||
98 | - const scrollTop = this.window.pageYOffset || this.document.documentElement.scrollTop || this.document.body.scrollTop || 0; | ||
99 | - const scrollLeft = this.window.pageXOffset || this.document.documentElement.scrollLeft || this.document.body.scrollLeft || 0; | ||
100 | - const bottomY = offset.bottom - scrollTop; | ||
101 | - const leftX = offset.left - scrollLeft; | ||
102 | - let originX; | ||
103 | - let originY; | ||
104 | - let overlayX; | ||
105 | - let overlayY; | ||
106 | - const wHeight = this.document.documentElement.clientHeight; | ||
107 | - const wWidth = this.document.documentElement.clientWidth; | ||
108 | - if (bottomY + panelHeight > wHeight) { | ||
109 | - originY = 'top'; | ||
110 | - overlayY = 'bottom'; | ||
111 | - } else { | ||
112 | - originY = 'bottom'; | ||
113 | - overlayY = 'top'; | 80 | + private onDirectionChanged(direction: LegendDirection) { |
81 | + if (direction === LegendDirection.row) { | ||
82 | + let position: LegendPosition = this.legendConfigForm.get('position').value; | ||
83 | + if (position !== LegendPosition.bottom && position !== LegendPosition.top) { | ||
84 | + position = LegendPosition.bottom; | ||
114 | } | 85 | } |
115 | - if (leftX + panelWidth > wWidth) { | ||
116 | - originX = 'end'; | ||
117 | - overlayX = 'end'; | ||
118 | - } else { | ||
119 | - originX = 'start'; | ||
120 | - overlayX = 'start'; | ||
121 | - } | ||
122 | - const connectedPosition: ConnectedPosition = { | ||
123 | - originX, | ||
124 | - originY, | ||
125 | - overlayX, | ||
126 | - overlayY | ||
127 | - }; | ||
128 | - config.positionStrategy = position.flexibleConnectedTo(this.legendConfigPanelOrigin.elementRef) | ||
129 | - .withPositions([connectedPosition]); | ||
130 | - } else { | ||
131 | - config.minWidth = '100%'; | ||
132 | - config.minHeight = '100%'; | ||
133 | - config.positionStrategy = position.global().top('0%').left('0%') | ||
134 | - .right('0%').bottom('0%'); | 86 | + this.legendConfigForm.patchValue({position}, {emitEvent: false} |
87 | + ); | ||
135 | } | 88 | } |
136 | - | ||
137 | - const overlayRef = this.overlay.create(config); | ||
138 | - | ||
139 | - overlayRef.backdropClick().subscribe(() => { | ||
140 | - overlayRef.dispose(); | ||
141 | - }); | ||
142 | - | ||
143 | - const injector = this._createLegendConfigPanelInjector( | ||
144 | - overlayRef, | ||
145 | - { | ||
146 | - legendConfig: deepClone(this.innerValue), | ||
147 | - legendConfigUpdated: this.legendConfigUpdated.bind(this) | ||
148 | - } | ||
149 | - ); | ||
150 | - | ||
151 | - overlayRef.attach(new ComponentPortal(LegendConfigPanelComponent, this.viewContainerRef, injector)); | ||
152 | } | 89 | } |
153 | 90 | ||
154 | - private _createLegendConfigPanelInjector(overlayRef: OverlayRef, data: LegendConfigPanelData): Injector { | ||
155 | - const providers: StaticProvider[] = [ | ||
156 | - {provide: LEGEND_CONFIG_PANEL_DATA, useValue: data}, | ||
157 | - {provide: OverlayRef, useValue: overlayRef} | ||
158 | - ]; | ||
159 | - return Injector.create({parent: this.viewContainerRef.injector, providers}); | 91 | + ngOnDestroy(): void { |
92 | + if (this.legendSettingsFormDirectionChanges$) { | ||
93 | + this.legendSettingsFormDirectionChanges$.unsubscribe(); | ||
94 | + this.legendSettingsFormDirectionChanges$ = null; | ||
95 | + } | ||
96 | + if (this.legendSettingsFormChanges$) { | ||
97 | + this.legendSettingsFormChanges$.unsubscribe(); | ||
98 | + this.legendSettingsFormChanges$ = null; | ||
99 | + } | ||
160 | } | 100 | } |
161 | 101 | ||
162 | registerOnChange(fn: any): void { | 102 | registerOnChange(fn: any): void { |
@@ -168,14 +108,29 @@ export class LegendConfigComponent implements OnInit, OnDestroy, ControlValueAcc | @@ -168,14 +108,29 @@ export class LegendConfigComponent implements OnInit, OnDestroy, ControlValueAcc | ||
168 | 108 | ||
169 | setDisabledState(isDisabled: boolean): void { | 109 | setDisabledState(isDisabled: boolean): void { |
170 | this.disabled = isDisabled; | 110 | this.disabled = isDisabled; |
111 | + if (this.disabled) { | ||
112 | + this.legendConfigForm.disable({emitEvent: false}); | ||
113 | + } else { | ||
114 | + this.legendConfigForm.enable({emitEvent: false}); | ||
115 | + } | ||
171 | } | 116 | } |
172 | 117 | ||
173 | - writeValue(obj: LegendConfig): void { | ||
174 | - this.innerValue = obj; | 118 | + writeValue(legendConfig: LegendConfig): void { |
119 | + if (legendConfig) { | ||
120 | + this.legendConfigForm.patchValue({ | ||
121 | + direction: legendConfig.direction, | ||
122 | + position: legendConfig.position, | ||
123 | + sortDataKeys: isDefined(legendConfig.sortDataKeys) ? legendConfig.sortDataKeys : false, | ||
124 | + showMin: isDefined(legendConfig.showMin) ? legendConfig.showMin : false, | ||
125 | + showMax: isDefined(legendConfig.showMax) ? legendConfig.showMax : false, | ||
126 | + showAvg: isDefined(legendConfig.showAvg) ? legendConfig.showAvg : false, | ||
127 | + showTotal: isDefined(legendConfig.showTotal) ? legendConfig.showTotal : false | ||
128 | + }, {emitEvent: false}); | ||
129 | + } | ||
130 | + this.onDirectionChanged(legendConfig.direction); | ||
175 | } | 131 | } |
176 | 132 | ||
177 | - private legendConfigUpdated(legendConfig: LegendConfig) { | ||
178 | - this.innerValue = legendConfig; | ||
179 | - this.propagateChange(this.innerValue); | 133 | + private legendConfigUpdated() { |
134 | + this.propagateChange(this.legendConfigForm.value); | ||
180 | } | 135 | } |
181 | } | 136 | } |
@@ -82,222 +82,246 @@ | @@ -82,222 +82,246 @@ | ||
82 | </mat-checkbox> | 82 | </mat-checkbox> |
83 | </div> | 83 | </div> |
84 | </div> | 84 | </div> |
85 | - <mat-expansion-panel class="tb-datasources" *ngIf="widgetType !== widgetTypes.rpc && | ||
86 | - widgetType !== widgetTypes.alarm && | ||
87 | - modelValue?.isDataEnabled" [expanded]="true"> | ||
88 | - <mat-expansion-panel-header> | ||
89 | - <mat-panel-title fxLayout="column"> | ||
90 | - <div class="tb-panel-title" translate>widget-config.datasources</div> | ||
91 | - <div *ngIf="modelValue?.typeParameters && modelValue?.typeParameters.maxDatasources > -1" | ||
92 | - class="tb-panel-hint">{{ 'widget-config.maximum-datasources' | translate:{count: modelValue?.typeParameters.maxDatasources} }}</div> | ||
93 | - </mat-panel-title> | ||
94 | - </mat-expansion-panel-header> | ||
95 | - <div *ngIf="datasourcesFormArray().length === 0; else datasourcesTemplate"> | ||
96 | - <span translate fxLayoutAlign="center center" | ||
97 | - class="tb-prompt">datasource.add-datasource-prompt</span> | ||
98 | - </div> | ||
99 | - <ng-template #datasourcesTemplate> | ||
100 | - <div fxFlex fxLayout="row" fxLayoutAlign="start center"> | ||
101 | - <span style="width: 60px;"></span> | ||
102 | - <div fxFlex fxLayout="row" fxLayoutAlign="start center" | ||
103 | - style="padding: 0 0 0 10px; margin: 5px;"> | ||
104 | - <span translate style="min-width: 120px;">widget-config.datasource-type</span> | ||
105 | - <span fxHide fxShow.gt-sm translate fxFlex | ||
106 | - style="padding-left: 10px;">widget-config.datasource-parameters</span> | ||
107 | - <span style="min-width: 40px;"></span> | ||
108 | - </div> | 85 | + <mat-accordion multi> |
86 | + <mat-expansion-panel class="tb-datasources" *ngIf="widgetType !== widgetTypes.rpc && | ||
87 | + widgetType !== widgetTypes.alarm && | ||
88 | + modelValue?.isDataEnabled" [expanded]="true"> | ||
89 | + <mat-expansion-panel-header> | ||
90 | + <mat-panel-title fxLayout="column"> | ||
91 | + <div class="tb-panel-title" translate>widget-config.datasources</div> | ||
92 | + <div *ngIf="modelValue?.typeParameters && modelValue?.typeParameters.maxDatasources > -1" | ||
93 | + class="tb-panel-hint">{{ 'widget-config.maximum-datasources' | translate:{count: modelValue?.typeParameters.maxDatasources} }}</div> | ||
94 | + </mat-panel-title> | ||
95 | + </mat-expansion-panel-header> | ||
96 | + <div *ngIf="datasourcesFormArray().length === 0; else datasourcesTemplate"> | ||
97 | + <span translate fxLayoutAlign="center center" | ||
98 | + class="tb-prompt">datasource.add-datasource-prompt</span> | ||
109 | </div> | 99 | </div> |
110 | - <div style="overflow: auto; padding-bottom: 15px;"> | ||
111 | - <mat-list dndDropzone dndEffectAllowed="move" | ||
112 | - (dndDrop)="onDatasourceDrop($event)" | ||
113 | - [dndDisableIf]="disabled" formArrayName="datasources"> | ||
114 | - <mat-list-item dndPlaceholderRef | ||
115 | - class="dndPlaceholder"> | ||
116 | - </mat-list-item> | ||
117 | - <mat-list-item *ngFor="let datasourceControl of datasourcesFormArray().controls; let $index = index;" | ||
118 | - [dndDraggable]="datasourceControl.value" | ||
119 | - (dndMoved)="dndDatasourceMoved($index)" | ||
120 | - [dndDisableIf]="disabled" | ||
121 | - dndEffectAllowed="move"> | ||
122 | - <div fxFlex fxLayout="row" fxLayoutAlign="start center"> | ||
123 | - <div style="width: 60px;"> | ||
124 | - <button *ngIf="!disabled" mat-icon-button color="primary" | ||
125 | - class="handle" | ||
126 | - style="min-width: 40px; margin: 0" | ||
127 | - dndHandle | ||
128 | - matTooltip="{{ 'action.drag' | translate }}" | ||
129 | - matTooltipPosition="above"> | ||
130 | - <mat-icon>drag_handle</mat-icon> | ||
131 | - </button> | ||
132 | - <span>{{$index + 1}}.</span> | ||
133 | - </div> | ||
134 | - <div class="mat-elevation-z4" fxFlex | ||
135 | - fxLayout="row" | ||
136 | - fxLayoutAlign="start center" | ||
137 | - style="padding: 0 0 0 10px; margin: 5px;"> | ||
138 | - <section fxFlex | ||
139 | - fxLayout="column" | ||
140 | - fxLayoutAlign="center" | ||
141 | - fxLayout.gt-sm="row" | ||
142 | - fxLayoutAlign.gt-sm="start center"> | ||
143 | - <mat-form-field class="tb-datasource-type"> | ||
144 | - <mat-select [formControl]="datasourceControl.get('type')"> | ||
145 | - <mat-option *ngFor="let datasourceType of datasourceTypes" [value]="datasourceType"> | ||
146 | - {{ datasourceTypesTranslations.get(datasourceType) | translate }} | ||
147 | - </mat-option> | ||
148 | - </mat-select> | ||
149 | - </mat-form-field> | ||
150 | - <section fxLayout="column" class="tb-datasource" [ngSwitch]="datasourceControl.get('type').value"> | ||
151 | - <ng-template [ngSwitchCase]="datasourceType.function"> | ||
152 | - <mat-form-field floatLabel="always" | ||
153 | - class="tb-datasource-name" style="min-width: 200px;"> | ||
154 | - <mat-label></mat-label> | ||
155 | - <input matInput | ||
156 | - placeholder="{{ 'datasource.label' | translate }}" | ||
157 | - [formControl]="datasourceControl.get('name')"> | ||
158 | - </mat-form-field> | ||
159 | - </ng-template> | ||
160 | - <ng-template [ngSwitchCase]="datasourceControl.get('type').value === datasourceType.entity || | ||
161 | - datasourceControl.get('type').value === datasourceType.entityCount ? datasourceControl.get('type').value : ''"> | ||
162 | - <tb-entity-alias-select | ||
163 | - [showLabel]="true" | ||
164 | - [tbRequired]="true" | ||
165 | - [aliasController]="aliasController" | ||
166 | - [formControl]="datasourceControl.get('entityAliasId')" | ||
167 | - [callbacks]="widgetConfigCallbacks"> | ||
168 | - </tb-entity-alias-select> | ||
169 | - <tb-filter-select | ||
170 | - [showLabel]="true" | ||
171 | - [aliasController]="aliasController" | ||
172 | - [formControl]="datasourceControl.get('filterId')" | ||
173 | - [callbacks]="widgetConfigCallbacks"> | ||
174 | - </tb-filter-select> | ||
175 | - <mat-form-field *ngIf="datasourceControl.get('type').value === datasourceType.entityCount" | ||
176 | - floatLabel="always" | ||
177 | - class="tb-datasource-name no-border-top" style="min-width: 200px;"> | ||
178 | - <mat-label></mat-label> | ||
179 | - <input matInput | ||
180 | - placeholder="{{ 'datasource.label' | translate }}" | ||
181 | - [formControl]="datasourceControl.get('name')"> | ||
182 | - </mat-form-field> | ||
183 | - </ng-template> | 100 | + <ng-template #datasourcesTemplate> |
101 | + <div fxFlex fxLayout="row" fxLayoutAlign="start center"> | ||
102 | + <span style="width: 60px;"></span> | ||
103 | + <div fxFlex fxLayout="row" fxLayoutAlign="start center" | ||
104 | + style="padding: 0 0 0 10px; margin: 5px;"> | ||
105 | + <span translate style="min-width: 120px;">widget-config.datasource-type</span> | ||
106 | + <span fxHide fxShow.gt-sm translate fxFlex | ||
107 | + style="padding-left: 10px;">widget-config.datasource-parameters</span> | ||
108 | + <span style="min-width: 40px;"></span> | ||
109 | + </div> | ||
110 | + </div> | ||
111 | + <div style="overflow: auto; padding-bottom: 15px;"> | ||
112 | + <mat-list dndDropzone dndEffectAllowed="move" | ||
113 | + (dndDrop)="onDatasourceDrop($event)" | ||
114 | + [dndDisableIf]="disabled" formArrayName="datasources"> | ||
115 | + <mat-list-item dndPlaceholderRef | ||
116 | + class="dndPlaceholder"> | ||
117 | + </mat-list-item> | ||
118 | + <mat-list-item *ngFor="let datasourceControl of datasourcesFormArray().controls; let $index = index;" | ||
119 | + [dndDraggable]="datasourceControl.value" | ||
120 | + (dndMoved)="dndDatasourceMoved($index)" | ||
121 | + [dndDisableIf]="disabled" | ||
122 | + dndEffectAllowed="move"> | ||
123 | + <div fxFlex fxLayout="row" fxLayoutAlign="start center"> | ||
124 | + <div style="width: 60px;"> | ||
125 | + <button *ngIf="!disabled" mat-icon-button color="primary" | ||
126 | + class="handle" | ||
127 | + style="min-width: 40px; margin: 0" | ||
128 | + dndHandle | ||
129 | + matTooltip="{{ 'action.drag' | translate }}" | ||
130 | + matTooltipPosition="above"> | ||
131 | + <mat-icon>drag_handle</mat-icon> | ||
132 | + </button> | ||
133 | + <span>{{$index + 1}}.</span> | ||
134 | + </div> | ||
135 | + <div class="mat-elevation-z4" fxFlex | ||
136 | + fxLayout="row" | ||
137 | + fxLayoutAlign="start center" | ||
138 | + style="padding: 0 0 0 10px; margin: 5px;"> | ||
139 | + <section fxFlex | ||
140 | + fxLayout="column" | ||
141 | + fxLayoutAlign="center" | ||
142 | + fxLayout.gt-sm="row" | ||
143 | + fxLayoutAlign.gt-sm="start center"> | ||
144 | + <mat-form-field class="tb-datasource-type"> | ||
145 | + <mat-select [formControl]="datasourceControl.get('type')"> | ||
146 | + <mat-option *ngFor="let datasourceType of datasourceTypes" [value]="datasourceType"> | ||
147 | + {{ datasourceTypesTranslations.get(datasourceType) | translate }} | ||
148 | + </mat-option> | ||
149 | + </mat-select> | ||
150 | + </mat-form-field> | ||
151 | + <section fxLayout="column" class="tb-datasource" [ngSwitch]="datasourceControl.get('type').value"> | ||
152 | + <ng-template [ngSwitchCase]="datasourceType.function"> | ||
153 | + <mat-form-field floatLabel="always" | ||
154 | + class="tb-datasource-name" style="min-width: 200px;"> | ||
155 | + <mat-label></mat-label> | ||
156 | + <input matInput | ||
157 | + placeholder="{{ 'datasource.label' | translate }}" | ||
158 | + [formControl]="datasourceControl.get('name')"> | ||
159 | + </mat-form-field> | ||
160 | + </ng-template> | ||
161 | + <ng-template [ngSwitchCase]="datasourceControl.get('type').value === datasourceType.entity || | ||
162 | + datasourceControl.get('type').value === datasourceType.entityCount ? datasourceControl.get('type').value : ''"> | ||
163 | + <tb-entity-alias-select | ||
164 | + [showLabel]="true" | ||
165 | + [tbRequired]="true" | ||
166 | + [aliasController]="aliasController" | ||
167 | + [formControl]="datasourceControl.get('entityAliasId')" | ||
168 | + [callbacks]="widgetConfigCallbacks"> | ||
169 | + </tb-entity-alias-select> | ||
170 | + <tb-filter-select | ||
171 | + [showLabel]="true" | ||
172 | + [aliasController]="aliasController" | ||
173 | + [formControl]="datasourceControl.get('filterId')" | ||
174 | + [callbacks]="widgetConfigCallbacks"> | ||
175 | + </tb-filter-select> | ||
176 | + <mat-form-field *ngIf="datasourceControl.get('type').value === datasourceType.entityCount" | ||
177 | + floatLabel="always" | ||
178 | + class="tb-datasource-name no-border-top" style="min-width: 200px;"> | ||
179 | + <mat-label></mat-label> | ||
180 | + <input matInput | ||
181 | + placeholder="{{ 'datasource.label' | translate }}" | ||
182 | + [formControl]="datasourceControl.get('name')"> | ||
183 | + </mat-form-field> | ||
184 | + </ng-template> | ||
185 | + </section> | ||
186 | + <tb-data-keys class="tb-data-keys" fxFlex | ||
187 | + [widgetType]="widgetType" | ||
188 | + [datasourceType]="datasourceControl.get('type').value" | ||
189 | + [maxDataKeys]="modelValue?.typeParameters?.maxDataKeys" | ||
190 | + [optDataKeys]="modelValue?.typeParameters?.dataKeysOptional" | ||
191 | + [aliasController]="aliasController" | ||
192 | + [datakeySettingsSchema]="modelValue?.dataKeySettingsSchema" | ||
193 | + [callbacks]="widgetConfigCallbacks" | ||
194 | + [entityAliasId]="datasourceControl.get('entityAliasId').value" | ||
195 | + [formControl]="datasourceControl.get('dataKeys')"> | ||
196 | + </tb-data-keys> | ||
184 | </section> | 197 | </section> |
185 | - <tb-data-keys class="tb-data-keys" fxFlex | ||
186 | - [widgetType]="widgetType" | ||
187 | - [datasourceType]="datasourceControl.get('type').value" | ||
188 | - [maxDataKeys]="modelValue?.typeParameters?.maxDataKeys" | ||
189 | - [optDataKeys]="modelValue?.typeParameters?.dataKeysOptional" | ||
190 | - [aliasController]="aliasController" | ||
191 | - [datakeySettingsSchema]="modelValue?.dataKeySettingsSchema" | ||
192 | - [callbacks]="widgetConfigCallbacks" | ||
193 | - [entityAliasId]="datasourceControl.get('entityAliasId').value" | ||
194 | - [formControl]="datasourceControl.get('dataKeys')"> | ||
195 | - </tb-data-keys> | ||
196 | - </section> | ||
197 | - <button [disabled]="isLoading$ | async" | ||
198 | - type="button" | ||
199 | - mat-icon-button color="primary" | ||
200 | - style="min-width: 40px;" | ||
201 | - (click)="removeDatasource($index)" | ||
202 | - matTooltip="{{ 'widget-config.remove-datasource' | translate }}" | ||
203 | - matTooltipPosition="above"> | ||
204 | - <mat-icon>close</mat-icon> | ||
205 | - </button> | 198 | + <button [disabled]="isLoading$ | async" |
199 | + type="button" | ||
200 | + mat-icon-button color="primary" | ||
201 | + style="min-width: 40px;" | ||
202 | + (click)="removeDatasource($index)" | ||
203 | + matTooltip="{{ 'widget-config.remove-datasource' | translate }}" | ||
204 | + matTooltipPosition="above"> | ||
205 | + <mat-icon>close</mat-icon> | ||
206 | + </button> | ||
207 | + </div> | ||
206 | </div> | 208 | </div> |
207 | - </div> | ||
208 | - </mat-list-item> | ||
209 | - </mat-list> | 209 | + </mat-list-item> |
210 | + </mat-list> | ||
211 | + </div> | ||
212 | + </ng-template> | ||
213 | + <div fxFlex fxLayout="row" fxLayoutAlign="start center"> | ||
214 | + <button [disabled]="isLoading$ | async" | ||
215 | + type="button" | ||
216 | + mat-raised-button color="primary" | ||
217 | + [fxShow]="modelValue?.typeParameters && | ||
218 | + (modelValue?.typeParameters.maxDatasources == -1 || datasourcesFormArray().controls.length < modelValue?.typeParameters.maxDatasources)" | ||
219 | + (click)="addDatasource()" | ||
220 | + matTooltip="{{ 'widget-config.add-datasource' | translate }}" | ||
221 | + matTooltipPosition="above"> | ||
222 | + <mat-icon>add</mat-icon> | ||
223 | + <span translate>action.add</span> | ||
224 | + </button> | ||
210 | </div> | 225 | </div> |
211 | - </ng-template> | ||
212 | - <div fxFlex fxLayout="row" fxLayoutAlign="start center"> | ||
213 | - <button [disabled]="isLoading$ | async" | ||
214 | - type="button" | ||
215 | - mat-raised-button color="primary" | ||
216 | - [fxShow]="modelValue?.typeParameters && | ||
217 | - (modelValue?.typeParameters.maxDatasources == -1 || datasourcesFormArray().controls.length < modelValue?.typeParameters.maxDatasources)" | ||
218 | - (click)="addDatasource()" | ||
219 | - matTooltip="{{ 'widget-config.add-datasource' | translate }}" | ||
220 | - matTooltipPosition="above"> | ||
221 | - <mat-icon>add</mat-icon> | ||
222 | - <span translate>action.add</span> | ||
223 | - </button> | ||
224 | - </div> | ||
225 | - </mat-expansion-panel> | ||
226 | - <mat-expansion-panel class="tb-datasources" *ngIf="widgetType === widgetTypes.rpc && | ||
227 | - modelValue?.isDataEnabled" [expanded]="true"> | ||
228 | - <mat-expansion-panel-header> | ||
229 | - <mat-panel-title> | ||
230 | - {{ 'widget-config.target-device' | translate }} | ||
231 | - </mat-panel-title> | ||
232 | - </mat-expansion-panel-header> | ||
233 | - <div [formGroup]="targetDeviceSettings" style="padding: 0 5px;"> | ||
234 | - <tb-entity-alias-select fxFlex | ||
235 | - [tbRequired]="!widgetEditMode" | ||
236 | - [aliasController]="aliasController" | ||
237 | - [allowedEntityTypes]="[entityTypes.DEVICE]" | ||
238 | - [callbacks]="widgetConfigCallbacks" | ||
239 | - formControlName="targetDeviceAliasId"> | ||
240 | - </tb-entity-alias-select> | ||
241 | - </div> | ||
242 | - </mat-expansion-panel> | ||
243 | - <mat-expansion-panel class="tb-datasources" *ngIf="widgetType === widgetTypes.alarm && | ||
244 | - modelValue?.isDataEnabled" [expanded]="true"> | ||
245 | - <mat-expansion-panel-header> | ||
246 | - <mat-panel-title> | ||
247 | - {{ 'widget-config.alarm-source' | translate }} | ||
248 | - </mat-panel-title> | ||
249 | - </mat-expansion-panel-header> | ||
250 | - <div [formGroup]="alarmSourceSettings" style="padding: 0 5px;"> | ||
251 | - <section fxFlex | ||
252 | - fxLayout="column" | ||
253 | - fxLayoutAlign="center" | ||
254 | - fxLayout.gt-sm="row" | ||
255 | - fxLayoutAlign.gt-sm="start center"> | ||
256 | - <mat-form-field class="tb-datasource-type"> | ||
257 | - <mat-select formControlName="type"> | ||
258 | - <mat-option *ngFor="let datasourceType of datasourceTypes" [value]="datasourceType"> | ||
259 | - {{ datasourceTypesTranslations.get(datasourceType) | translate }} | ||
260 | - </mat-option> | ||
261 | - </mat-select> | ||
262 | - </mat-form-field> | ||
263 | - <section class="tb-datasource" [ngSwitch]="alarmSourceSettings.get('type').value"> | ||
264 | - <ng-template [ngSwitchCase]="datasourceType.entity"> | ||
265 | - <tb-entity-alias-select | ||
266 | - [showLabel]="true" | ||
267 | - [tbRequired]="alarmSourceSettings.get('type').value === datasourceType.entity" | ||
268 | - [aliasController]="aliasController" | ||
269 | - formControlName="entityAliasId" | ||
270 | - [callbacks]="widgetConfigCallbacks"> | ||
271 | - </tb-entity-alias-select> | ||
272 | - <tb-filter-select | ||
273 | - [showLabel]="true" | ||
274 | - [aliasController]="aliasController" | ||
275 | - formControlName="filterId" | ||
276 | - [callbacks]="widgetConfigCallbacks"> | ||
277 | - </tb-filter-select> | ||
278 | - </ng-template> | 226 | + </mat-expansion-panel> |
227 | + <mat-expansion-panel class="tb-datasources" *ngIf="widgetType === widgetTypes.rpc && | ||
228 | + modelValue?.isDataEnabled" [expanded]="true"> | ||
229 | + <mat-expansion-panel-header> | ||
230 | + <mat-panel-title> | ||
231 | + {{ 'widget-config.target-device' | translate }} | ||
232 | + </mat-panel-title> | ||
233 | + </mat-expansion-panel-header> | ||
234 | + <div [formGroup]="targetDeviceSettings" style="padding: 0 5px;"> | ||
235 | + <tb-entity-alias-select fxFlex | ||
236 | + [tbRequired]="!widgetEditMode" | ||
237 | + [aliasController]="aliasController" | ||
238 | + [allowedEntityTypes]="[entityTypes.DEVICE]" | ||
239 | + [callbacks]="widgetConfigCallbacks" | ||
240 | + formControlName="targetDeviceAliasId"> | ||
241 | + </tb-entity-alias-select> | ||
242 | + </div> | ||
243 | + </mat-expansion-panel> | ||
244 | + <mat-expansion-panel class="tb-datasources" *ngIf="widgetType === widgetTypes.alarm && | ||
245 | + modelValue?.isDataEnabled" [expanded]="true"> | ||
246 | + <mat-expansion-panel-header> | ||
247 | + <mat-panel-title> | ||
248 | + {{ 'widget-config.alarm-source' | translate }} | ||
249 | + </mat-panel-title> | ||
250 | + </mat-expansion-panel-header> | ||
251 | + <div [formGroup]="alarmSourceSettings" style="padding: 0 5px;"> | ||
252 | + <section fxFlex | ||
253 | + fxLayout="column" | ||
254 | + fxLayoutAlign="center" | ||
255 | + fxLayout.gt-sm="row" | ||
256 | + fxLayoutAlign.gt-sm="start center"> | ||
257 | + <mat-form-field class="tb-datasource-type"> | ||
258 | + <mat-select formControlName="type"> | ||
259 | + <mat-option *ngFor="let datasourceType of datasourceTypes" [value]="datasourceType"> | ||
260 | + {{ datasourceTypesTranslations.get(datasourceType) | translate }} | ||
261 | + </mat-option> | ||
262 | + </mat-select> | ||
263 | + </mat-form-field> | ||
264 | + <section class="tb-datasource" [ngSwitch]="alarmSourceSettings.get('type').value"> | ||
265 | + <ng-template [ngSwitchCase]="datasourceType.entity"> | ||
266 | + <tb-entity-alias-select | ||
267 | + [showLabel]="true" | ||
268 | + [tbRequired]="alarmSourceSettings.get('type').value === datasourceType.entity" | ||
269 | + [aliasController]="aliasController" | ||
270 | + formControlName="entityAliasId" | ||
271 | + [callbacks]="widgetConfigCallbacks"> | ||
272 | + </tb-entity-alias-select> | ||
273 | + <tb-filter-select | ||
274 | + [showLabel]="true" | ||
275 | + [aliasController]="aliasController" | ||
276 | + formControlName="filterId" | ||
277 | + [callbacks]="widgetConfigCallbacks"> | ||
278 | + </tb-filter-select> | ||
279 | + </ng-template> | ||
280 | + </section> | ||
281 | + <tb-data-keys class="tb-data-keys" fxFlex | ||
282 | + [widgetType]="widgetType" | ||
283 | + [datasourceType]="alarmSourceSettings.get('type').value" | ||
284 | + [aliasController]="aliasController" | ||
285 | + [datakeySettingsSchema]="modelValue?.dataKeySettingsSchema" | ||
286 | + [callbacks]="widgetConfigCallbacks" | ||
287 | + [entityAliasId]="alarmSourceSettings.get('entityAliasId').value" | ||
288 | + formControlName="dataKeys"> | ||
289 | + </tb-data-keys> | ||
279 | </section> | 290 | </section> |
280 | - <tb-data-keys class="tb-data-keys" fxFlex | ||
281 | - [widgetType]="widgetType" | ||
282 | - [datasourceType]="alarmSourceSettings.get('type').value" | ||
283 | - [aliasController]="aliasController" | ||
284 | - [datakeySettingsSchema]="modelValue?.dataKeySettingsSchema" | ||
285 | - [callbacks]="widgetConfigCallbacks" | ||
286 | - [entityAliasId]="alarmSourceSettings.get('entityAliasId').value" | ||
287 | - formControlName="dataKeys"> | ||
288 | - </tb-data-keys> | ||
289 | - </section> | ||
290 | - </div> | ||
291 | - </mat-expansion-panel> | 291 | + </div> |
292 | + </mat-expansion-panel> | ||
293 | + <mat-expansion-panel [formGroup]="widgetSettings"> | ||
294 | + <mat-expansion-panel-header> | ||
295 | + <mat-panel-title translate>widget-config.data-settings</mat-panel-title> | ||
296 | + </mat-expansion-panel-header> | ||
297 | + <ng-template matExpansionPanelContent> | ||
298 | + <div fxLayout.xs="column" fxLayoutAlign.xs="center" fxLayout="row" fxLayoutAlign="start center" | ||
299 | + fxLayoutGap="8px"> | ||
300 | + <mat-form-field fxFlex> | ||
301 | + <mat-label translate>widget-config.units</mat-label> | ||
302 | + <input matInput formControlName="units"> | ||
303 | + </mat-form-field> | ||
304 | + <mat-form-field fxFlex> | ||
305 | + <mat-label translate>widget-config.decimals</mat-label> | ||
306 | + <input matInput formControlName="decimals" type="number" min="0" max="15" step="1"> | ||
307 | + </mat-form-field> | ||
308 | + </div> | ||
309 | + </ng-template> | ||
310 | + </mat-expansion-panel> | ||
311 | + </mat-accordion> | ||
292 | </div> | 312 | </div> |
293 | </mat-tab> | 313 | </mat-tab> |
294 | <mat-tab label="{{ 'widget-config.settings' | translate }}"> | 314 | <mat-tab label="{{ 'widget-config.settings' | translate }}"> |
295 | - <div class="mat-content mat-padding" fxLayout="column" fxLayoutGap="8px"> | ||
296 | - <div [formGroup]="widgetSettings" fxLayout="column" fxLayoutGap="8px"> | ||
297 | - <span translate>widget-config.general-settings</span> | ||
298 | - <div fxLayout.xs="column" fxLayoutAlign.xs="center" fxLayout="row" fxLayoutAlign="start center"> | ||
299 | - <div fxLayout="column" fxLayoutAlign="center" fxFlex.sm="40%" fxFlex.gt-sm="30%"> | ||
300 | - <mat-form-field fxFlex class="mat-block"> | 315 | + <div class="mat-content mat-padding" fxLayout="column"> |
316 | + <div [formGroup]="widgetSettings" fxLayout="column"> | ||
317 | + <fieldset class="fields-group" fxLayout="column"> | ||
318 | + <legend class="group-title" translate>widget-config.title</legend> | ||
319 | + <mat-slide-toggle formControlName="showTitle" style="margin: 8px 0"> | ||
320 | + {{ 'widget-config.display-title' | translate }} | ||
321 | + </mat-slide-toggle> | ||
322 | + <div fxLayout.xs="column" fxLayoutAlign.xs="center" fxLayout="row" fxLayoutAlign="start center" | ||
323 | + fxLayoutGap="8px"> | ||
324 | + <mat-form-field fxFlex> | ||
301 | <mat-label translate>widget-config.title</mat-label> | 325 | <mat-label translate>widget-config.title</mat-label> |
302 | <input matInput formControlName="title"> | 326 | <input matInput formControlName="title"> |
303 | </mat-form-field> | 327 | </mat-form-field> |
@@ -306,130 +330,143 @@ | @@ -306,130 +330,143 @@ | ||
306 | <input matInput formControlName="titleTooltip"> | 330 | <input matInput formControlName="titleTooltip"> |
307 | </mat-form-field> | 331 | </mat-form-field> |
308 | </div> | 332 | </div> |
309 | - <div fxFlex [fxShow]="widgetSettings.get('showTitle').value"> | ||
310 | - <tb-json-object-edit | ||
311 | - [editorStyle]="{minHeight: '100px'}" | ||
312 | - required | ||
313 | - label="{{ 'widget-config.title-style' | translate }}" | ||
314 | - formControlName="titleStyle" | ||
315 | - ></tb-json-object-edit> | ||
316 | - </div> | ||
317 | - </div> | ||
318 | - <div fxLayout="column" fxLayoutAlign="center" fxLayout.gt-md="row" fxLayoutAlign.gt-md="start center" fxFlex="100%" | ||
319 | - fxLayoutGap="8px"> | ||
320 | - <div fxLayout.xs="column" fxLayoutAlign.xs="center" fxLayout="row" fxLayoutAlign="start center" | ||
321 | - fxLayoutGap="8px" fxFlex.gt-md> | ||
322 | - <mat-checkbox fxFlex formControlName="showTitleIcon"> | 333 | + <fieldset class="fields-group" fxLayout="column" fxLayoutGap="8px" style="margin: 0"> |
334 | + <legend class="group-title" translate>widget-config.title-icon</legend> | ||
335 | + <mat-slide-toggle formControlName="showTitleIcon"> | ||
323 | {{ 'widget-config.display-icon' | translate }} | 336 | {{ 'widget-config.display-icon' | translate }} |
324 | - </mat-checkbox> | ||
325 | - <tb-material-icon-select fxFlex | ||
326 | - formControlName="titleIcon"> | ||
327 | - </tb-material-icon-select> | ||
328 | - </div> | ||
329 | - <div fxLayout.xs="column" fxLayoutAlign.xs="center" fxLayout="row" fxLayoutAlign="start center" | ||
330 | - fxLayoutGap="8px" fxFlex.gt-md> | ||
331 | - <tb-color-input fxFlex | ||
332 | - label="{{'widget-config.icon-color' | translate}}" | ||
333 | - icon="format_color_fill" | ||
334 | - openOnInput | ||
335 | - formControlName="iconColor"> | ||
336 | - </tb-color-input> | ||
337 | - <mat-form-field fxFlex> | ||
338 | - <mat-label translate>widget-config.icon-size</mat-label> | ||
339 | - <input matInput formControlName="iconSize"> | ||
340 | - </mat-form-field> | ||
341 | - </div> | ||
342 | - </div> | ||
343 | - <div fxLayout.xs="column" fxLayoutAlign.xs="center" fxLayout="row" fxLayoutAlign="start center" | ||
344 | - fxLayoutGap="8px"> | ||
345 | - <div fxLayout="column" fxLayoutAlign="center" fxLayoutGap="8px" fxFlex.sm="40%" fxFlex.gt-sm="30%"> | ||
346 | - <mat-checkbox formControlName="showTitle"> | ||
347 | - {{ 'widget-config.display-title' | translate }} | ||
348 | - </mat-checkbox> | ||
349 | - <mat-checkbox formControlName="dropShadow"> | ||
350 | - {{ 'widget-config.drop-shadow' | translate }} | ||
351 | - </mat-checkbox> | ||
352 | - <mat-checkbox formControlName="enableFullscreen"> | ||
353 | - {{ 'widget-config.enable-fullscreen' | translate }} | ||
354 | - </mat-checkbox> | ||
355 | - </div> | ||
356 | - <div fxFlex> | ||
357 | - <tb-json-object-edit | ||
358 | - [editorStyle]="{minHeight: '100px'}" | ||
359 | - required | ||
360 | - label="{{ 'widget-config.widget-style' | translate }}" | ||
361 | - formControlName="widgetStyle" | ||
362 | - ></tb-json-object-edit> | ||
363 | - </div> | ||
364 | - </div> | ||
365 | - <div fxLayout="column" fxLayoutAlign="center" fxLayout.gt-md="row" fxLayoutAlign.gt-md="start center" | ||
366 | - fxFlex="100%" fxLayoutGap="8px"> | ||
367 | - <div fxLayout.xs="column" fxLayoutAlign.xs="center" fxLayout="row" fxLayoutAlign="start center" | ||
368 | - fxLayoutGap="8px" fxFlex.gt-md> | ||
369 | - <tb-color-input fxFlex | ||
370 | - label="{{'widget-config.background-color' | translate}}" | ||
371 | - icon="format_color_fill" | ||
372 | - openOnInput | ||
373 | - formControlName="backgroundColor"> | ||
374 | - </tb-color-input> | ||
375 | - <tb-color-input fxFlex | ||
376 | - label="{{'widget-config.text-color' | translate}}" | ||
377 | - icon="format_color_fill" | ||
378 | - openOnInput | ||
379 | - formControlName="color"> | ||
380 | - </tb-color-input> | ||
381 | - </div> | ||
382 | - <div fxLayout.xs="column" fxLayoutAlign.xs="center" fxLayout="row" fxLayoutAlign="start center" | ||
383 | - fxLayoutGap="8px" fxFlex.gt-md> | ||
384 | - <mat-form-field fxFlex> | ||
385 | - <mat-label translate>widget-config.padding</mat-label> | ||
386 | - <input matInput formControlName="padding"> | ||
387 | - </mat-form-field> | ||
388 | - <mat-form-field fxFlex> | ||
389 | - <mat-label translate>widget-config.margin</mat-label> | ||
390 | - <input matInput formControlName="margin"> | ||
391 | - </mat-form-field> | 337 | + </mat-slide-toggle> |
338 | + <div fxLayout.xs="column" fxLayoutAlign.xs="center" fxLayout="row wrap" fxLayoutAlign="start center" | ||
339 | + fxLayoutGap="8px"> | ||
340 | + <tb-material-icon-select fxFlex | ||
341 | + formControlName="titleIcon"> | ||
342 | + </tb-material-icon-select> | ||
343 | + <tb-color-input fxFlex | ||
344 | + label="{{'widget-config.icon-color' | translate}}" | ||
345 | + icon="format_color_fill" | ||
346 | + openOnInput | ||
347 | + formControlName="iconColor"> | ||
348 | + </tb-color-input> | ||
349 | + <mat-form-field fxFlex> | ||
350 | + <mat-label translate>widget-config.icon-size</mat-label> | ||
351 | + <input matInput formControlName="iconSize"> | ||
352 | + </mat-form-field> | ||
353 | + </div> | ||
354 | + </fieldset> | ||
355 | + <mat-expansion-panel class="tb-settings"> | ||
356 | + <mat-expansion-panel-header> | ||
357 | + <mat-panel-description fxLayoutAlign="end" translate> | ||
358 | + widget-config.advanced-settings | ||
359 | + </mat-panel-description> | ||
360 | + </mat-expansion-panel-header> | ||
361 | + <ng-template matExpansionPanelContent> | ||
362 | + <tb-json-object-edit | ||
363 | + [editorStyle]="{minHeight: '100px'}" | ||
364 | + required | ||
365 | + label="{{ 'widget-config.title-style' | translate }}" | ||
366 | + formControlName="titleStyle" | ||
367 | + ></tb-json-object-edit> | ||
368 | + </ng-template> | ||
369 | + </mat-expansion-panel> | ||
370 | + </fieldset> | ||
371 | + <fieldset class="fields-group" fxLayout="column"> | ||
372 | + <legend class="group-title" translate>widget-config.widget-style</legend> | ||
373 | + <div fxLayout="column" fxLayoutAlign="center" fxLayout.gt-md="row" fxLayoutAlign.gt-md="start center" | ||
374 | + fxFlex="100%" fxLayoutGap="8px" class="tb-widget-style"> | ||
375 | + <div fxLayout.xs="column" fxLayoutAlign.xs="center" fxLayout="row" fxLayoutAlign="start center" | ||
376 | + fxLayoutGap="8px" fxFlex.gt-md> | ||
377 | + <tb-color-input fxFlex | ||
378 | + label="{{'widget-config.background-color' | translate}}" | ||
379 | + icon="format_color_fill" | ||
380 | + openOnInput | ||
381 | + formControlName="backgroundColor"> | ||
382 | + </tb-color-input> | ||
383 | + <tb-color-input fxFlex | ||
384 | + label="{{'widget-config.text-color' | translate}}" | ||
385 | + icon="format_color_fill" | ||
386 | + openOnInput | ||
387 | + formControlName="color"> | ||
388 | + </tb-color-input> | ||
389 | + </div> | ||
390 | + <div fxLayout.xs="column" fxLayoutAlign.xs="center" fxLayout="row" fxLayoutAlign="start center" | ||
391 | + fxLayoutGap="8px" fxFlex.gt-md> | ||
392 | + <mat-form-field fxFlex> | ||
393 | + <mat-label translate>widget-config.padding</mat-label> | ||
394 | + <input matInput formControlName="padding"> | ||
395 | + </mat-form-field> | ||
396 | + <mat-form-field fxFlex> | ||
397 | + <mat-label translate>widget-config.margin</mat-label> | ||
398 | + <input matInput formControlName="margin"> | ||
399 | + </mat-form-field> | ||
400 | + </div> | ||
392 | </div> | 401 | </div> |
393 | - </div> | ||
394 | - <div fxLayout.xs="column" fxLayoutAlign.xs="center" fxLayout="row" fxLayoutAlign="start center" | ||
395 | - fxLayoutGap="8px"> | ||
396 | - <mat-form-field fxFlex> | ||
397 | - <mat-label translate>widget-config.units</mat-label> | ||
398 | - <input matInput formControlName="units"> | ||
399 | - </mat-form-field> | ||
400 | - <mat-form-field fxFlex> | ||
401 | - <mat-label translate>widget-config.decimals</mat-label> | ||
402 | - <input matInput formControlName="decimals" type="number" min="0" max="15" step="1"> | ||
403 | - </mat-form-field> | ||
404 | - </div> | ||
405 | - <div [fxShow]="widgetType === widgetTypes.timeseries || widgetType === widgetTypes.latest" | ||
406 | - fxLayout.xs="column" fxLayoutAlign.xs="center" fxLayout="row" fxLayoutAlign="start center" | ||
407 | - fxLayoutGap="8px" fxFlex="100%"> | ||
408 | - <mat-checkbox fxFlex.gt-xs formControlName="showLegend"> | ||
409 | - {{ 'widget-config.display-legend' | translate }} | ||
410 | - </mat-checkbox> | ||
411 | - <section fxFlex.gt-xs fxLayout="row" fxLayoutAlign="start center" style="margin-bottom: 16px;"> | ||
412 | - <tb-legend-config formControlName="legendConfig"> | ||
413 | - </tb-legend-config> | ||
414 | - </section> | ||
415 | - </div> | ||
416 | - </div> | ||
417 | - <div [formGroup]="layoutSettings" fxLayout="column" fxLayoutGap="8px"> | ||
418 | - <span translate>widget-config.mobile-mode-settings</span> | ||
419 | - <div fxLayout.xs="column" fxLayoutAlign.xs="center" fxLayout="row" fxLayoutAlign="start center" | ||
420 | - fxLayoutGap="8px"> | ||
421 | - <mat-checkbox formControlName="mobileHide"> | ||
422 | - {{ 'widget-config.mobile-hide' | translate }} | ||
423 | - </mat-checkbox> | ||
424 | - <mat-form-field fxFlex> | ||
425 | - <mat-label translate>widget-config.order</mat-label> | ||
426 | - <input matInput formControlName="mobileOrder" type="number" step="1"> | ||
427 | - </mat-form-field> | ||
428 | - <mat-form-field fxFlex> | ||
429 | - <mat-label translate>widget-config.height</mat-label> | ||
430 | - <input matInput formControlName="mobileHeight" type="number" min="1" max="10" step="1"> | ||
431 | - </mat-form-field> | ||
432 | - </div> | 402 | + <mat-slide-toggle formControlName="dropShadow" style="margin-bottom: 8px"> |
403 | + {{ 'widget-config.drop-shadow' | translate }} | ||
404 | + </mat-slide-toggle> | ||
405 | + <mat-slide-toggle formControlName="enableFullscreen"> | ||
406 | + {{ 'widget-config.enable-fullscreen' | translate }} | ||
407 | + </mat-slide-toggle> | ||
408 | + <mat-expansion-panel class="tb-settings"> | ||
409 | + <mat-expansion-panel-header> | ||
410 | + <mat-panel-description fxLayoutAlign="end" translate> | ||
411 | + widget-config.advanced-settings | ||
412 | + </mat-panel-description> | ||
413 | + </mat-expansion-panel-header> | ||
414 | + <ng-template matExpansionPanelContent> | ||
415 | + <tb-json-object-edit | ||
416 | + [editorStyle]="{minHeight: '100px'}" | ||
417 | + required | ||
418 | + label="{{ 'widget-config.widget-style' | translate }}" | ||
419 | + formControlName="widgetStyle" | ||
420 | + ></tb-json-object-edit> | ||
421 | + </ng-template> | ||
422 | + </mat-expansion-panel> | ||
423 | + </fieldset> | ||
424 | + <fieldset class="fields-group fields-group-slider" fxLayout="column"> | ||
425 | + <legend class="group-title" translate>widget-config.legend</legend> | ||
426 | + <mat-expansion-panel class="tb-settings"> | ||
427 | + <mat-expansion-panel-header fxLayout="row wrap"> | ||
428 | + <mat-panel-title> | ||
429 | + <mat-slide-toggle formControlName="showLegend" (click)="$event.stopPropagation()" fxLayoutAlign="center"> | ||
430 | + {{ 'widget-config.display-legend' | translate }} | ||
431 | + </mat-slide-toggle> | ||
432 | + </mat-panel-title> | ||
433 | + <mat-panel-description fxLayoutAlign="end center" fxHide.xs translate> | ||
434 | + widget-config.advanced-settings | ||
435 | + </mat-panel-description> | ||
436 | + </mat-expansion-panel-header> | ||
437 | + <ng-template matExpansionPanelContent> | ||
438 | + <tb-legend-config formControlName="legendConfig"></tb-legend-config> | ||
439 | + </ng-template> | ||
440 | + </mat-expansion-panel> | ||
441 | + </fieldset> | ||
442 | + <fieldset [formGroup]="layoutSettings" class="fields-group fields-group-slider" fxLayout="column"> | ||
443 | + <legend class="group-title" translate>widget-config.mobile-mode-settings</legend> | ||
444 | + <mat-expansion-panel class="tb-settings"> | ||
445 | + <mat-expansion-panel-header> | ||
446 | + <mat-panel-title> | ||
447 | + <mat-slide-toggle formControlName="mobileHide" (click)="$event.stopPropagation()" fxLayoutAlign="center"> | ||
448 | + {{ 'widget-config.mobile-hide' | translate }} | ||
449 | + </mat-slide-toggle> | ||
450 | + </mat-panel-title> | ||
451 | + <mat-panel-description fxLayoutAlign="end center" fxHide.xs translate> | ||
452 | + widget-config.advanced-settings | ||
453 | + </mat-panel-description> | ||
454 | + </mat-expansion-panel-header> | ||
455 | + <ng-template matExpansionPanelContent> | ||
456 | + <div fxLayout.xs="column" fxLayoutAlign.xs="center" fxLayout="row" fxLayoutAlign="start center" | ||
457 | + fxLayoutGap="8px"> | ||
458 | + <mat-form-field fxFlex> | ||
459 | + <mat-label translate>widget-config.order</mat-label> | ||
460 | + <input matInput formControlName="mobileOrder" type="number" step="1"> | ||
461 | + </mat-form-field> | ||
462 | + <mat-form-field fxFlex> | ||
463 | + <mat-label translate>widget-config.height</mat-label> | ||
464 | + <input matInput formControlName="mobileHeight" type="number" min="1" max="10" step="1"> | ||
465 | + </mat-form-field> | ||
466 | + </div> | ||
467 | + </ng-template> | ||
468 | + </mat-expansion-panel> | ||
469 | + </fieldset> | ||
433 | </div> | 470 | </div> |
434 | </div> | 471 | </div> |
435 | </mat-tab> | 472 | </mat-tab> |
@@ -20,9 +20,6 @@ | @@ -20,9 +20,6 @@ | ||
20 | .tb-advanced-widget-config { | 20 | .tb-advanced-widget-config { |
21 | height: 100%; | 21 | height: 100%; |
22 | } | 22 | } |
23 | - .tb-advanced-widget-config { | ||
24 | - height: 100%; | ||
25 | - } | ||
26 | .tb-datasources { | 23 | .tb-datasources { |
27 | 24 | ||
28 | .handle { | 25 | .handle { |
@@ -69,6 +66,28 @@ | @@ -69,6 +66,28 @@ | ||
69 | padding-left: 8px; | 66 | padding-left: 8px; |
70 | } | 67 | } |
71 | } | 68 | } |
69 | + .fields-group { | ||
70 | + padding: 0 16px 8px; | ||
71 | + margin-bottom: 10px; | ||
72 | + border: 1px groove rgba(0, 0, 0, .25); | ||
73 | + border-radius: 4px; | ||
74 | + legend { | ||
75 | + color: rgba(0, 0, 0, .7); | ||
76 | + width: fit-content; | ||
77 | + } | ||
78 | + } | ||
79 | + .fields-group-slider { | ||
80 | + padding: 0; | ||
81 | + legend { | ||
82 | + margin-left: 16px; | ||
83 | + } | ||
84 | + .tb-settings { | ||
85 | + padding: 0 16px 8px; | ||
86 | + } | ||
87 | + } | ||
88 | + .tb-widget-style { | ||
89 | + margin-top: 16px; | ||
90 | + } | ||
72 | } | 91 | } |
73 | } | 92 | } |
74 | 93 | ||
@@ -94,6 +113,36 @@ | @@ -94,6 +113,36 @@ | ||
94 | white-space: normal; | 113 | white-space: normal; |
95 | } | 114 | } |
96 | .mat-expansion-panel { | 115 | .mat-expansion-panel { |
116 | + &.tb-settings { | ||
117 | + box-shadow: none; | ||
118 | + .mat-content { | ||
119 | + overflow: visible; | ||
120 | + } | ||
121 | + .mat-expansion-panel-header { | ||
122 | + padding: 0; | ||
123 | + &:hover { | ||
124 | + background: none; | ||
125 | + } | ||
126 | + .mat-expansion-indicator { | ||
127 | + padding: 2px; | ||
128 | + } | ||
129 | + } | ||
130 | + .mat-expansion-panel-header-description { | ||
131 | + align-items: center; | ||
132 | + } | ||
133 | + .mat-expansion-panel-body{ | ||
134 | + padding: 0; | ||
135 | + } | ||
136 | + .tb-json-object-panel { | ||
137 | + margin: 0 0 8px; | ||
138 | + } | ||
139 | + .mat-checkbox-layout { | ||
140 | + margin: 5px 0; | ||
141 | + } | ||
142 | + .mat-checkbox-inner-container { | ||
143 | + margin-right: 12px; | ||
144 | + } | ||
145 | + } | ||
97 | &.tb-datasources { | 146 | &.tb-datasources { |
98 | &.mat-expanded { | 147 | &.mat-expanded { |
99 | overflow: visible; | 148 | overflow: visible; |
@@ -152,5 +201,8 @@ | @@ -152,5 +201,8 @@ | ||
152 | } | 201 | } |
153 | } | 202 | } |
154 | } | 203 | } |
204 | + .mat-slide-toggle-content { | ||
205 | + white-space: normal; | ||
206 | + } | ||
155 | } | 207 | } |
156 | } | 208 | } |
@@ -212,11 +212,28 @@ export class WidgetConfigComponent extends PageComponent implements OnInit, Cont | @@ -212,11 +212,28 @@ export class WidgetConfigComponent extends PageComponent implements OnInit, Cont | ||
212 | showLegend: [null, []], | 212 | showLegend: [null, []], |
213 | legendConfig: [null, []] | 213 | legendConfig: [null, []] |
214 | }); | 214 | }); |
215 | + this.widgetSettings.get('showTitle').valueChanges.subscribe((value: boolean) => { | ||
216 | + if (value) { | ||
217 | + this.widgetSettings.get('titleStyle').enable({emitEvent: false}); | ||
218 | + this.widgetSettings.get('titleTooltip').enable({emitEvent: false}); | ||
219 | + this.widgetSettings.get('showTitleIcon').enable({emitEvent: false}); | ||
220 | + } else { | ||
221 | + this.widgetSettings.get('titleStyle').disable({emitEvent: false}); | ||
222 | + this.widgetSettings.get('titleTooltip').disable({emitEvent: false}); | ||
223 | + this.widgetSettings.get('showTitleIcon').patchValue(false); | ||
224 | + this.widgetSettings.get('showTitleIcon').disable({emitEvent: false}); | ||
225 | + } | ||
226 | + }); | ||
227 | + | ||
215 | this.widgetSettings.get('showTitleIcon').valueChanges.subscribe((value: boolean) => { | 228 | this.widgetSettings.get('showTitleIcon').valueChanges.subscribe((value: boolean) => { |
216 | if (value) { | 229 | if (value) { |
217 | this.widgetSettings.get('titleIcon').enable({emitEvent: false}); | 230 | this.widgetSettings.get('titleIcon').enable({emitEvent: false}); |
231 | + this.widgetSettings.get('iconColor').enable({emitEvent: false}); | ||
232 | + this.widgetSettings.get('iconSize').enable({emitEvent: false}); | ||
218 | } else { | 233 | } else { |
219 | this.widgetSettings.get('titleIcon').disable({emitEvent: false}); | 234 | this.widgetSettings.get('titleIcon').disable({emitEvent: false}); |
235 | + this.widgetSettings.get('iconColor').disable({emitEvent: false}); | ||
236 | + this.widgetSettings.get('iconSize').disable({emitEvent: false}); | ||
220 | } | 237 | } |
221 | }); | 238 | }); |
222 | this.widgetSettings.get('showLegend').valueChanges.subscribe((value: boolean) => { | 239 | this.widgetSettings.get('showLegend').valueChanges.subscribe((value: boolean) => { |
@@ -236,6 +253,10 @@ export class WidgetConfigComponent extends PageComponent implements OnInit, Cont | @@ -236,6 +253,10 @@ export class WidgetConfigComponent extends PageComponent implements OnInit, Cont | ||
236 | }); | 253 | }); |
237 | } | 254 | } |
238 | 255 | ||
256 | + ngOnDestroy(): void { | ||
257 | + this.removeChangeSubscriptions(); | ||
258 | + } | ||
259 | + | ||
239 | private removeChangeSubscriptions() { | 260 | private removeChangeSubscriptions() { |
240 | if (this.dataSettingsChangesSubscription) { | 261 | if (this.dataSettingsChangesSubscription) { |
241 | this.dataSettingsChangesSubscription.unsubscribe(); | 262 | this.dataSettingsChangesSubscription.unsubscribe(); |
@@ -376,7 +397,7 @@ export class WidgetConfigComponent extends PageComponent implements OnInit, Cont | @@ -376,7 +397,7 @@ export class WidgetConfigComponent extends PageComponent implements OnInit, Cont | ||
376 | iconColor: isDefined(config.iconColor) ? config.iconColor : 'rgba(0, 0, 0, 0.87)', | 397 | iconColor: isDefined(config.iconColor) ? config.iconColor : 'rgba(0, 0, 0, 0.87)', |
377 | iconSize: isDefined(config.iconSize) ? config.iconSize : '24px', | 398 | iconSize: isDefined(config.iconSize) ? config.iconSize : '24px', |
378 | titleTooltip: isDefined(config.titleTooltip) ? config.titleTooltip : '', | 399 | titleTooltip: isDefined(config.titleTooltip) ? config.titleTooltip : '', |
379 | - showTitle: config.showTitle, | 400 | + showTitle: isDefined(config.showTitle) ? config.showTitle : false, |
380 | dropShadow: isDefined(config.dropShadow) ? config.dropShadow : true, | 401 | dropShadow: isDefined(config.dropShadow) ? config.dropShadow : true, |
381 | enableFullscreen: isDefined(config.enableFullscreen) ? config.enableFullscreen : true, | 402 | enableFullscreen: isDefined(config.enableFullscreen) ? config.enableFullscreen : true, |
382 | backgroundColor: config.backgroundColor, | 403 | backgroundColor: config.backgroundColor, |
@@ -396,11 +417,25 @@ export class WidgetConfigComponent extends PageComponent implements OnInit, Cont | @@ -396,11 +417,25 @@ export class WidgetConfigComponent extends PageComponent implements OnInit, Cont | ||
396 | }, | 417 | }, |
397 | {emitEvent: false} | 418 | {emitEvent: false} |
398 | ); | 419 | ); |
420 | + const showTitle: boolean = this.widgetSettings.get('showTitle').value; | ||
421 | + if (showTitle) { | ||
422 | + this.widgetSettings.get('titleTooltip').enable({emitEvent: false}); | ||
423 | + this.widgetSettings.get('titleStyle').enable({emitEvent: false}); | ||
424 | + this.widgetSettings.get('showTitleIcon').enable({emitEvent: false}); | ||
425 | + } else { | ||
426 | + this.widgetSettings.get('titleTooltip').disable({emitEvent: false}); | ||
427 | + this.widgetSettings.get('titleStyle').disable({emitEvent: false}); | ||
428 | + this.widgetSettings.get('showTitleIcon').disable({emitEvent: false}); | ||
429 | + } | ||
399 | const showTitleIcon: boolean = this.widgetSettings.get('showTitleIcon').value; | 430 | const showTitleIcon: boolean = this.widgetSettings.get('showTitleIcon').value; |
400 | if (showTitleIcon) { | 431 | if (showTitleIcon) { |
401 | this.widgetSettings.get('titleIcon').enable({emitEvent: false}); | 432 | this.widgetSettings.get('titleIcon').enable({emitEvent: false}); |
433 | + this.widgetSettings.get('iconColor').enable({emitEvent: false}); | ||
434 | + this.widgetSettings.get('iconSize').enable({emitEvent: false}); | ||
402 | } else { | 435 | } else { |
403 | this.widgetSettings.get('titleIcon').disable({emitEvent: false}); | 436 | this.widgetSettings.get('titleIcon').disable({emitEvent: false}); |
437 | + this.widgetSettings.get('iconColor').disable({emitEvent: false}); | ||
438 | + this.widgetSettings.get('iconSize').disable({emitEvent: false}); | ||
404 | } | 439 | } |
405 | const showLegend: boolean = this.widgetSettings.get('showLegend').value; | 440 | const showLegend: boolean = this.widgetSettings.get('showLegend').value; |
406 | if (showLegend) { | 441 | if (showLegend) { |
@@ -92,14 +92,16 @@ export class MaterialIconSelectComponent extends PageComponent implements OnInit | @@ -92,14 +92,16 @@ export class MaterialIconSelectComponent extends PageComponent implements OnInit | ||
92 | } | 92 | } |
93 | 93 | ||
94 | openIconDialog() { | 94 | openIconDialog() { |
95 | - this.dialogs.materialIconPicker(this.materialIconFormGroup.get('icon').value).subscribe( | ||
96 | - (icon) => { | ||
97 | - if (icon) { | ||
98 | - this.materialIconFormGroup.patchValue( | ||
99 | - {icon}, {emitEvent: true} | ||
100 | - ); | 95 | + if (!this.disabled) { |
96 | + this.dialogs.materialIconPicker(this.materialIconFormGroup.get('icon').value).subscribe( | ||
97 | + (icon) => { | ||
98 | + if (icon) { | ||
99 | + this.materialIconFormGroup.patchValue( | ||
100 | + {icon}, {emitEvent: true} | ||
101 | + ); | ||
102 | + } | ||
101 | } | 103 | } |
102 | - } | ||
103 | - ); | 104 | + ); |
105 | + } | ||
104 | } | 106 | } |
105 | } | 107 | } |
@@ -3030,7 +3030,7 @@ | @@ -3030,7 +3030,7 @@ | ||
3030 | "title": "Title", | 3030 | "title": "Title", |
3031 | "title-tooltip": "Title Tooltip", | 3031 | "title-tooltip": "Title Tooltip", |
3032 | "general-settings": "General settings", | 3032 | "general-settings": "General settings", |
3033 | - "display-title": "Display title", | 3033 | + "display-title": "Display widget title", |
3034 | "drop-shadow": "Drop shadow", | 3034 | "drop-shadow": "Drop shadow", |
3035 | "enable-fullscreen": "Enable fullscreen", | 3035 | "enable-fullscreen": "Enable fullscreen", |
3036 | "background-color": "Background color", | 3036 | "background-color": "Background color", |
@@ -3039,7 +3039,7 @@ | @@ -3039,7 +3039,7 @@ | ||
3039 | "margin": "Margin", | 3039 | "margin": "Margin", |
3040 | "widget-style": "Widget style", | 3040 | "widget-style": "Widget style", |
3041 | "title-style": "Title style", | 3041 | "title-style": "Title style", |
3042 | - "mobile-mode-settings": "Mobile mode settings", | 3042 | + "mobile-mode-settings": "Mobile mode", |
3043 | "order": "Order", | 3043 | "order": "Order", |
3044 | "height": "Height", | 3044 | "height": "Height", |
3045 | "mobile-hide": "Hide widget in mobile mode", | 3045 | "mobile-hide": "Hide widget in mobile mode", |
@@ -3048,6 +3048,7 @@ | @@ -3048,6 +3048,7 @@ | ||
3048 | "timewindow": "Timewindow", | 3048 | "timewindow": "Timewindow", |
3049 | "use-dashboard-timewindow": "Use dashboard timewindow", | 3049 | "use-dashboard-timewindow": "Use dashboard timewindow", |
3050 | "display-timewindow": "Display timewindow", | 3050 | "display-timewindow": "Display timewindow", |
3051 | + "legend": "Legend", | ||
3051 | "display-legend": "Display legend", | 3052 | "display-legend": "Display legend", |
3052 | "datasources": "Datasources", | 3053 | "datasources": "Datasources", |
3053 | "maximum-datasources": "Maximum { count, plural, 1 {1 datasource is allowed.} other {# datasources are allowed} }", | 3054 | "maximum-datasources": "Maximum { count, plural, 1 {1 datasource is allowed.} other {# datasources are allowed} }", |
@@ -3075,9 +3076,12 @@ | @@ -3075,9 +3076,12 @@ | ||
3075 | "delete-action": "Delete action", | 3076 | "delete-action": "Delete action", |
3076 | "delete-action-title": "Delete widget action", | 3077 | "delete-action-title": "Delete widget action", |
3077 | "delete-action-text": "Are you sure you want delete widget action with name '{{actionName}}'?", | 3078 | "delete-action-text": "Are you sure you want delete widget action with name '{{actionName}}'?", |
3079 | + "title-icon": "Title icon", | ||
3078 | "display-icon": "Display title icon", | 3080 | "display-icon": "Display title icon", |
3079 | "icon-color": "Icon color", | 3081 | "icon-color": "Icon color", |
3080 | - "icon-size": "Icon size" | 3082 | + "icon-size": "Icon size", |
3083 | + "advanced-settings": "Advanced settings", | ||
3084 | + "data-settings": "Data settings" | ||
3081 | }, | 3085 | }, |
3082 | "widget-type": { | 3086 | "widget-type": { |
3083 | "import": "Import widget type", | 3087 | "import": "Import widget type", |
@@ -1631,7 +1631,7 @@ | @@ -1631,7 +1631,7 @@ | ||
1631 | "advanced": "Дополнительно", | 1631 | "advanced": "Дополнительно", |
1632 | "title": "Название", | 1632 | "title": "Название", |
1633 | "general-settings": "Общие настройки", | 1633 | "general-settings": "Общие настройки", |
1634 | - "display-title": "Показать название", | 1634 | + "display-title": "Показать название на виджете", |
1635 | "drop-shadow": "Тень", | 1635 | "drop-shadow": "Тень", |
1636 | "enable-fullscreen": "Во весь экран", | 1636 | "enable-fullscreen": "Во весь экран", |
1637 | "background-color": "Цвет фона", | 1637 | "background-color": "Цвет фона", |
@@ -1640,7 +1640,7 @@ | @@ -1640,7 +1640,7 @@ | ||
1640 | "margin": "Margin", | 1640 | "margin": "Margin", |
1641 | "widget-style": "Стиль виджета", | 1641 | "widget-style": "Стиль виджета", |
1642 | "title-style": "Стиль названия", | 1642 | "title-style": "Стиль названия", |
1643 | - "mobile-mode-settings": "Настройки мобильного режима", | 1643 | + "mobile-mode-settings": "Мобильный режим", |
1644 | "order": "Порядок", | 1644 | "order": "Порядок", |
1645 | "height": "Высота", | 1645 | "height": "Высота", |
1646 | "units": "Специальный символ после значения", | 1646 | "units": "Специальный символ после значения", |
@@ -1648,6 +1648,7 @@ | @@ -1648,6 +1648,7 @@ | ||
1648 | "timewindow": "Временное окно", | 1648 | "timewindow": "Временное окно", |
1649 | "use-dashboard-timewindow": "Использовать временное окно дашборда", | 1649 | "use-dashboard-timewindow": "Использовать временное окно дашборда", |
1650 | "display-timewindow": "Показывать временное окно", | 1650 | "display-timewindow": "Показывать временное окно", |
1651 | + "legend": "Легенда", | ||
1651 | "display-legend": "Показать легенду", | 1652 | "display-legend": "Показать легенду", |
1652 | "datasources": "Источники данных", | 1653 | "datasources": "Источники данных", |
1653 | "maximum-datasources": "Максимальной количество источников данных равно {{count}}", | 1654 | "maximum-datasources": "Максимальной количество источников данных равно {{count}}", |
@@ -1673,9 +1674,12 @@ | @@ -1673,9 +1674,12 @@ | ||
1673 | "delete-action": "Удалить действие", | 1674 | "delete-action": "Удалить действие", |
1674 | "delete-action-title": "Удалить действие виджета", | 1675 | "delete-action-title": "Удалить действие виджета", |
1675 | "delete-action-text": "Вы точно хотите удалить действие виджета '{{actionName}}'?", | 1676 | "delete-action-text": "Вы точно хотите удалить действие виджета '{{actionName}}'?", |
1676 | - "display-icon": "Показывать иконку в названии", | 1677 | + "title-icon": "Иконка в названии виджета", |
1678 | + "display-icon": "Показывать иконку в названии виджета", | ||
1677 | "icon-color": "Цвет иконки", | 1679 | "icon-color": "Цвет иконки", |
1678 | - "icon-size": "Размер иконки" | 1680 | + "icon-size": "Размер иконки", |
1681 | + "advanced-settings": "Расширенные настройки", | ||
1682 | + "data-settings": "Настройки данных" | ||
1679 | }, | 1683 | }, |
1680 | "widget-type": { | 1684 | "widget-type": { |
1681 | "import": "Импортировать тип виджета", | 1685 | "import": "Импортировать тип виджета", |
@@ -2202,7 +2202,7 @@ | @@ -2202,7 +2202,7 @@ | ||
2202 | "advanced": "Додатково", | 2202 | "advanced": "Додатково", |
2203 | "title": "Назва", | 2203 | "title": "Назва", |
2204 | "general-settings": "Загальні налаштування", | 2204 | "general-settings": "Загальні налаштування", |
2205 | - "display-title": "Відобразити назву", | 2205 | + "display-title": "Відобразити назву у віджеті", |
2206 | "drop-shadow": "Тінь", | 2206 | "drop-shadow": "Тінь", |
2207 | "enable-fullscreen": "Увімкнути повноекранний режим", | 2207 | "enable-fullscreen": "Увімкнути повноекранний режим", |
2208 | "enable-data-export": "Увімкнути експорт даних", | 2208 | "enable-data-export": "Увімкнути експорт даних", |
@@ -2212,7 +2212,7 @@ | @@ -2212,7 +2212,7 @@ | ||
2212 | "margin": "Границі", | 2212 | "margin": "Границі", |
2213 | "widget-style": "Стиль віджетів", | 2213 | "widget-style": "Стиль віджетів", |
2214 | "title-style": "Стиль заголовка", | 2214 | "title-style": "Стиль заголовка", |
2215 | - "mobile-mode-settings": "Налаштування мобільного режиму", | 2215 | + "mobile-mode-settings": "мобільний режим", |
2216 | "order": "Порядок", | 2216 | "order": "Порядок", |
2217 | "height": "Висота", | 2217 | "height": "Висота", |
2218 | "units": "Спеціальний символ після значення", | 2218 | "units": "Спеціальний символ після значення", |
@@ -2220,6 +2220,7 @@ | @@ -2220,6 +2220,7 @@ | ||
2220 | "timewindow": "Вікно часу", | 2220 | "timewindow": "Вікно часу", |
2221 | "use-dashboard-timewindow": "Використати вікно часу на панелі візуалізації", | 2221 | "use-dashboard-timewindow": "Використати вікно часу на панелі візуалізації", |
2222 | "display-timewindow": "Показувати вікно часу", | 2222 | "display-timewindow": "Показувати вікно часу", |
2223 | + "legend": "Легенда", | ||
2223 | "display-legend": "Показати легенду", | 2224 | "display-legend": "Показати легенду", |
2224 | "datasources": "Джерела даних", | 2225 | "datasources": "Джерела даних", |
2225 | "maximum-datasources": "Максимально { count, plural, 1 {1 дозволене джерело даних.} other {# дозволені джерела даних } }", | 2226 | "maximum-datasources": "Максимально { count, plural, 1 {1 дозволене джерело даних.} other {# дозволені джерела даних } }", |
@@ -2245,9 +2246,12 @@ | @@ -2245,9 +2246,12 @@ | ||
2245 | "delete-action": "Видалити дію", | 2246 | "delete-action": "Видалити дію", |
2246 | "delete-action-title": "Видалити дію віджета", | 2247 | "delete-action-title": "Видалити дію віджета", |
2247 | "delete-action-text": "Ви впевнені, що хочете видалити дію віджета '{{actionName}}'?", | 2248 | "delete-action-text": "Ви впевнені, що хочете видалити дію віджета '{{actionName}}'?", |
2248 | - "display-icon": "Показувати іконку у назві", | 2249 | + "title-icon": "Іконка у назві віджету", |
2250 | + "display-icon": "Показувати іконку у назві віджету", | ||
2249 | "icon-color": "Колір іконки", | 2251 | "icon-color": "Колір іконки", |
2250 | - "icon-size": "Розмір іконки" | 2252 | + "icon-size": "Розмір іконки", |
2253 | + "advanced-settings": "Розширені налаштування", | ||
2254 | + "data-settings": "Налаштування даних" | ||
2251 | }, | 2255 | }, |
2252 | "widget-type": { | 2256 | "widget-type": { |
2253 | "import": "Імпортувати тип віджета", | 2257 | "import": "Імпортувати тип віджета", |