Commit f579add9a777237acb1fb7b94e11f99838000ab0

Authored by Igor Kulikov
1 parent b3df9644

Layout improvements.

... ... @@ -184,6 +184,10 @@ export class DashboardComponent extends PageComponent implements IDashboardCompo
184 184 swap: false,
185 185 maxRows: 100,
186 186 minCols: this.columns ? this.columns : 24,
  187 + maxCols: 3000,
  188 + maxItemCols: 1000,
  189 + maxItemRows: 1000,
  190 + maxItemArea: 1000000,
187 191 outerMargin: true,
188 192 margin: this.margin ? this.margin : 10,
189 193 minItemCols: 1,
... ...
... ... @@ -299,14 +299,16 @@ export class ManageWidgetActionsComponent extends PageComponent implements OnIni
299 299
300 300 writeValue(obj: WidgetActionsData): void {
301 301 this.innerValue = obj;
302   - setTimeout(() => {
303   - this.dataSource.setActions(this.innerValue);
304   - if (this.viewsInited) {
305   - this.resetSortAndFilter(true);
306   - } else {
307   - this.dirtyValue = true;
308   - }
309   - }, 0);
  302 + if (this.innerValue) {
  303 + setTimeout(() => {
  304 + this.dataSource.setActions(this.innerValue);
  305 + if (this.viewsInited) {
  306 + this.resetSortAndFilter(true);
  307 + } else {
  308 + this.dirtyValue = true;
  309 + }
  310 + }, 0);
  311 + }
310 312 }
311 313
312 314 private onActionsUpdated() {
... ...
... ... @@ -29,7 +29,7 @@
29 29 <div class="tb-color-preview" (click)="showColorPicker(key)" style="margin-right: 5px;">
30 30 <div class="tb-color-result" [ngStyle]="{background: key.color}"></div>
31 31 </div>
32   - <div style="flex: 1; min-width: 0px;" fxLayout="row">
  32 + <div class="tb-chip-labels">
33 33 <div class="tb-chip-label">
34 34 <span *ngIf="datasourceType !== datasourceTypes.function && widgetType !== widgetTypes.alarm">
35 35 <span *ngIf="key.type === dataKeyTypes.attribute"
... ...
... ... @@ -30,14 +30,19 @@
30 30 }
31 31 }
32 32
33   - .tb-chip-label {
34   - overflow: hidden;
35   - text-overflow: ellipsis;
36   - white-space: nowrap;
37   - }
  33 + .tb-chip-labels {
  34 + display: flex;
  35 + flex-direction: row;
  36 + min-width: 0px;
  37 + .tb-chip-label {
  38 + overflow: hidden;
  39 + text-overflow: ellipsis;
  40 + white-space: nowrap;
  41 + }
38 42
39   - .tb-chip-separator {
40   - white-space: pre;
  43 + .tb-chip-separator {
  44 + white-space: pre;
  45 + }
41 46 }
42 47
43 48 .mat-chip-remove.mat-icon {
... ...
... ... @@ -38,16 +38,16 @@
38 38 </mat-option>
39 39 </mat-select>
40 40 </mat-form-field>
41   - <mat-checkbox fxFlex formControlName="showMin">
  41 + <mat-checkbox formControlName="showMin">
42 42 {{ 'legend.show-min' | translate }}
43 43 </mat-checkbox>
44   - <mat-checkbox fxFlex formControlName="showMax">
  44 + <mat-checkbox formControlName="showMax">
45 45 {{ 'legend.show-max' | translate }}
46 46 </mat-checkbox>
47   - <mat-checkbox fxFlex formControlName="showAvg">
  47 + <mat-checkbox formControlName="showAvg">
48 48 {{ 'legend.show-avg' | translate }}
49 49 </mat-checkbox>
50   - <mat-checkbox fxFlex formControlName="showTotal">
  50 + <mat-checkbox formControlName="showTotal">
51 51 {{ 'legend.show-total' | translate }}
52 52 </mat-checkbox>
53 53 </section>
... ...
... ... @@ -22,11 +22,10 @@
22 22 <div *ngIf="widgetType === widgetTypes.timeseries || widgetType === widgetTypes.alarm"
23 23 fxLayout="column" fxLayoutGap="8px" fxLayoutAlign="center" fxLayout.gt-sm="row" fxLayoutAlign.gt-sm="start center">
24 24 <div fxLayout="column" fxLayoutGap="8px" fxFlex>
25   - <mat-checkbox fxFlex formControlName="useDashboardTimewindow">
  25 + <mat-checkbox formControlName="useDashboardTimewindow">
26 26 {{ 'widget-config.use-dashboard-timewindow' | translate }}
27 27 </mat-checkbox>
28   - <mat-checkbox fxFlex
29   - formControlName="displayTimewindow">
  28 + <mat-checkbox formControlName="displayTimewindow">
30 29 {{ 'widget-config.display-timewindow' | translate }}
31 30 </mat-checkbox>
32 31 </div>
... ...
... ... @@ -26,6 +26,9 @@
26 26 }
27 27 .tb-datasource-type {
28 28 min-width: 110px;
  29 + @media #{$mat-gt-sm} {
  30 + max-width: 110px;
  31 + }
29 32 }
30 33 .tb-datasource {
31 34 @media #{$mat-gt-sm} {
... ...
... ... @@ -163,6 +163,10 @@ export class WidgetConfigComponent extends PageComponent implements OnInit, Cont
163 163 } else {
164 164 this.datasourceTypes = [DatasourceType.function, DatasourceType.entity];
165 165 }
  166 + this.dataSettings = this.fb.group({});
  167 + this.targetDeviceSettings = this.fb.group({});
  168 + this.alarmSourceSettings = this.fb.group({});
  169 + this.advancedSettings = this.fb.group({});
166 170 this.widgetSettings = this.fb.group({
167 171 title: [null, []],
168 172 showTitleIcon: [null, []],
... ... @@ -574,7 +578,7 @@ export class WidgetConfigComponent extends PageComponent implements OnInit, Cont
574 578 }
575 579
576 580 public displayAdvanced(): boolean {
577   - return this.modelValue.settingsSchema && this.modelValue.settingsSchema.schema;
  581 + return this.modelValue && this.modelValue.settingsSchema && this.modelValue.settingsSchema.schema;
578 582 }
579 583
580 584 public removeDatasource(index: number) {
... ... @@ -772,7 +776,7 @@ export class WidgetConfigComponent extends PageComponent implements OnInit, Cont
772 776 valid: false
773 777 }
774 778 };
775   - } else {
  779 + } else if (this.modelValue) {
776 780 const config = this.modelValue.config;
777 781 if (this.widgetType === widgetType.rpc && this.modelValue.isDataEnabled) {
778 782 if (!config.targetDeviceAliasIds || !config.targetDeviceAliasIds.length) {
... ...
... ... @@ -120,59 +120,90 @@
120 120 'tb-dashboard-toolbar-opened': toolbarOpened,
121 121 'tb-dashboard-toolbar-animated': isToolbarOpenedAnimate,
122 122 'tb-dashboard-toolbar-closed': !toolbarOpened }">
123   - <section *ngIf="!widgetEditMode" class="tb-dashboard-title" fxLayout="row" fxLayoutAlign="center center"
124   - [ngStyle]="{'color': dashboard.configuration.settings.titleColor}">
125   - <h3 [fxShow]="!isEdit && displayTitle()">{{ dashboard.title }}</h3>
126   - <mat-form-field [fxShow]="isEdit" class="mat-block" style="height: 30px;">
127   - <mat-label translate [ngStyle]="{'color': dashboard.configuration.settings.titleColor}">dashboard.title</mat-label>
128   - <input matInput class="tb-dashboard-title"
129   - [ngStyle]="{'color': dashboard.configuration.settings.titleColor}"
130   - required name="title" [(ngModel)]="dashboard.title">
131   - </mat-form-field>
132   - </section>
133   - <div class="tb-absolute-fill tb-dashboard-layouts" fxLayout="{{forceDashboardMobileMode ? 'column' : 'row'}}"
134   - [ngClass]="{ 'tb-padded' : !widgetEditMode && (isEdit || displayTitle()), 'tb-shrinked' : isEditingWidget }">
135   - <mat-drawer-container class="tb-absolute-fill">
136   - <mat-drawer *ngIf="layouts.right.show"
137   - id="tb-right-layout"
138   - [ngStyle]="{minWidth: rightLayoutWidth(),
139   - maxWidth: rightLayoutWidth(),
140   - height: rightLayoutHeight(),
141   - borderLeft: 'none'}"
142   - disableClose="true"
143   - position="end"
144   - [mode]="isMobile ? 'over' : 'side'"
145   - [(opened)]="rightLayoutOpened">
146   - <tb-dashboard-layout style="height: 100%;"
147   - [layoutCtx]="layouts.right.layoutCtx"
148   - [dashboardCtx]="dashboardCtx"
149   - [isEdit]="isEdit"
150   - [isEditingWidget]="isEditingWidget"
151   - [isMobile]="forceDashboardMobileMode"
152   - [widgetEditMode]="widgetEditMode">
153   - </tb-dashboard-layout>
154   - </mat-drawer>
155   - <mat-drawer-content [fxShow]="layouts.main.show"
156   - id="tb-main-layout"
157   - [ngStyle]="{width: mainLayoutWidth(),
158   - height: mainLayoutHeight()}">
159   - <tb-dashboard-layout
160   - [layoutCtx]="layouts.main.layoutCtx"
161   - [dashboardCtx]="dashboardCtx"
162   - [isEdit]="isEdit"
163   - [isEditingWidget]="isEditingWidget"
164   - [isMobile]="forceDashboardMobileMode"
165   - [widgetEditMode]="widgetEditMode">
166   - </tb-dashboard-layout>
167   - </mat-drawer-content>
168   - </mat-drawer-container>
169   - </div>
170   - <mat-drawer-container hasBackdrop="false" class="tb-widget-details-sidenav">
  123 + <mat-drawer-container hasBackdrop="false" class="tb-absolute-fill tb-dashboard-drawer-container">
  124 + <mat-drawer-content fxLayout="column" fxLayoutAlign="center start">
  125 + <section *ngIf="!widgetEditMode" class="tb-dashboard-title"
  126 + [ngStyle]="{'color': dashboard.configuration.settings.titleColor}">
  127 + <h3 [fxShow]="!isEdit && displayTitle()">{{ dashboard.title }}</h3>
  128 + <mat-form-field [fxShow]="isEdit" class="mat-block">
  129 + <mat-label translate [ngStyle]="{'color': dashboard.configuration.settings.titleColor}">dashboard.title</mat-label>
  130 + <input matInput class="tb-dashboard-title"
  131 + [ngStyle]="{'color': dashboard.configuration.settings.titleColor}"
  132 + required name="title" [(ngModel)]="dashboard.title">
  133 + </mat-form-field>
  134 + </section>
  135 + <mat-drawer-container class="tb-dashboard-layouts" fxFlex
  136 + [ngClass]="{ 'tb-shrinked' : isEditingWidget }">
  137 + <mat-drawer *ngIf="layouts.right.show"
  138 + id="tb-right-layout"
  139 + [ngStyle]="{minWidth: rightLayoutWidth(),
  140 + maxWidth: rightLayoutWidth(),
  141 + height: rightLayoutHeight(),
  142 + borderLeft: 'none'}"
  143 + disableClose="true"
  144 + position="end"
  145 + [mode]="isMobile ? 'over' : 'side'"
  146 + [(opened)]="rightLayoutOpened">
  147 + <tb-dashboard-layout style="height: 100%;"
  148 + [layoutCtx]="layouts.right.layoutCtx"
  149 + [dashboardCtx]="dashboardCtx"
  150 + [isEdit]="isEdit"
  151 + [isEditingWidget]="isEditingWidget"
  152 + [isMobile]="forceDashboardMobileMode"
  153 + [widgetEditMode]="widgetEditMode">
  154 + </tb-dashboard-layout>
  155 + </mat-drawer>
  156 + <mat-drawer-content [fxShow]="layouts.main.show"
  157 + id="tb-main-layout"
  158 + [ngStyle]="{width: mainLayoutWidth(),
  159 + height: mainLayoutHeight()}">
  160 + <tb-dashboard-layout
  161 + [layoutCtx]="layouts.main.layoutCtx"
  162 + [dashboardCtx]="dashboardCtx"
  163 + [isEdit]="isEdit"
  164 + [isEditingWidget]="isEditingWidget"
  165 + [isMobile]="forceDashboardMobileMode"
  166 + [widgetEditMode]="widgetEditMode">
  167 + </tb-dashboard-layout>
  168 + </mat-drawer-content>
  169 + </mat-drawer-container>
  170 + <section fxLayout="row" class="layout-wrap tb-footer-buttons" fxLayoutAlign="start end">
  171 + <tb-footer-fab-buttons [fxShow]="!isAddingWidget && isEdit && !widgetEditMode"
  172 + relative
  173 + [footerFabButtons]="addWidgetFabButtons">
  174 + </tb-footer-fab-buttons>
  175 + <button *ngIf="(isTenantAdmin() || isSystemAdmin()) && !forceFullscreen"
  176 + mat-fab color="accent" class="tb-btn-footer"
  177 + [ngClass]="{'tb-hide': !isEdit || isAddingWidget}"
  178 + [disabled]="isLoading$ | async"
  179 + (click)="saveDashboard()"
  180 + matTooltip="{{ 'action.apply-changes' | translate }}"
  181 + matTooltipPosition="above">
  182 + <mat-icon>done</mat-icon>
  183 + </button>
  184 + <button *ngIf="(isTenantAdmin() || isSystemAdmin()) && !forceFullscreen"
  185 + mat-fab color="accent" class="tb-btn-footer"
  186 + [ngClass]="{'tb-hide': isAddingWidget || (isLoading$ | async)}"
  187 + [disabled]="isLoading$ | async"
  188 + (click)="toggleDashboardEditMode()"
  189 + matTooltip="{{ (isEdit ? 'action.decline-changes': 'action.enter-edit-mode') | translate }}"
  190 + matTooltipPosition="above">
  191 + <mat-icon>{{ isEdit ? 'close' : 'edit' }}</mat-icon>
  192 + </button>
  193 + </section>
  194 + <section class="tb-powered-by-footer" [ngStyle]="{'color': dashboard.configuration.settings.titleColor}">
  195 + <span>Powered by <a href="https://thingsboard.io" target="_blank">Thingsboard v.{{ thingsboardVersion }}</a></span>
  196 + </section>
  197 + </mat-drawer-content>
171 198 <mat-drawer class="tb-details-drawer"
172   - [opened]="isEditingWidget"
  199 + [opened]="isEditingWidget || isAddingWidget"
  200 + (openedStart)="detailsDrawerOpenedStart()"
  201 + (opened)="detailsDrawerOpened()"
  202 + (closedStart)="detailsDrawerClosedStart()"
  203 + (closed)="detailsDrawerClosed()"
173 204 mode="over"
174 205 position="end">
175   - <tb-details-panel *ngIf="isEditingWidget" fxFlex
  206 + <tb-details-panel *ngIf="!isEditingWidgetClosed" fxFlex
176 207 headerTitle="{{editingWidget?.config.title}}"
177 208 headerSubtitle="{{ editingWidgetSubtitle }}"
178 209 [isReadOnly]="false"
... ... @@ -185,21 +216,14 @@
185 216 <div [tb-help]="helpLinkIdForWidgetType()"></div>
186 217 </div>
187 218 <tb-edit-widget #tbEditWidget
188   - [dashboard]="dashboard"
189   - [aliasController]="dashboardCtx.aliasController"
190   - [widgetEditMode]="widgetEditMode"
191   - [widget]="editingWidget"
192   - [widgetLayout]="editingWidgetLayout">
  219 + [dashboard]="dashboard"
  220 + [aliasController]="dashboardCtx.aliasController"
  221 + [widgetEditMode]="widgetEditMode"
  222 + [widget]="editingWidget"
  223 + [widgetLayout]="editingWidgetLayout">
193 224 </tb-edit-widget>
194 225 </tb-details-panel>
195   - </mat-drawer>
196   - </mat-drawer-container>
197   - <mat-drawer-container *ngIf="!widgetEditMode" hasBackdrop="false" class="tb-select-widget-sidenav">
198   - <mat-drawer class="tb-details-drawer"
199   - [opened]="isAddingWidget"
200   - mode="over"
201   - position="end">
202   - <tb-details-panel *ngIf="isAddingWidget" fxFlex
  226 + <tb-details-panel *ngIf="!isAddingWidgetClosed && !widgetEditMode" fxFlex
203 227 headerTitle="{{'dashboard.select-widget-title' | translate}}"
204 228 headerHeightPx="120"
205 229 [isReadOnly]="true"
... ... @@ -218,40 +242,12 @@
218 242 </div>
219 243 </div>
220 244 <tb-dashboard-widget-select *ngIf="isAddingWidget"
221   - [aliasController]="dashboardCtx.aliasController"
222   - [widgetsBundle]="widgetsBundle"
223   - (widgetSelected)="addWidgetFromType($event)">
  245 + [aliasController]="dashboardCtx.aliasController"
  246 + [widgetsBundle]="widgetsBundle"
  247 + (widgetSelected)="addWidgetFromType($event)">
224 248 </tb-dashboard-widget-select>
225 249 </tb-details-panel>
226 250 </mat-drawer>
227 251 </mat-drawer-container>
228   - <!--tb-details-sidenav TODO -->
229   - <section fxLayout="row" class="layout-wrap tb-footer-buttons" fxLayoutAlign="start end">
230   - <tb-footer-fab-buttons [fxShow]="!isAddingWidget && isEdit && !widgetEditMode"
231   - relative
232   - [footerFabButtons]="addWidgetFabButtons">
233   - </tb-footer-fab-buttons>
234   - <button *ngIf="(isTenantAdmin() || isSystemAdmin()) && !forceFullscreen"
235   - mat-fab color="accent" class="tb-btn-footer"
236   - [ngClass]="{'tb-hide': !isEdit || isAddingWidget}"
237   - [disabled]="isLoading$ | async"
238   - (click)="saveDashboard()"
239   - matTooltip="{{ 'action.apply-changes' | translate }}"
240   - matTooltipPosition="above">
241   - <mat-icon>done</mat-icon>
242   - </button>
243   - <button *ngIf="(isTenantAdmin() || isSystemAdmin()) && !forceFullscreen"
244   - mat-fab color="accent" class="tb-btn-footer"
245   - [ngClass]="{'tb-hide': isAddingWidget || (isLoading$ | async)}"
246   - [disabled]="isLoading$ | async"
247   - (click)="toggleDashboardEditMode()"
248   - matTooltip="{{ (isEdit ? 'action.decline-changes': 'action.enter-edit-mode') | translate }}"
249   - matTooltipPosition="above">
250   - <mat-icon>{{ isEdit ? 'close' : 'edit' }}</mat-icon>
251   - </button>
252   - </section>
253   - </section>
254   - <section class="tb-powered-by-footer" [ngStyle]="{'color': dashboard.configuration.settings.titleColor}">
255   - <span>Powered by <a href="https://thingsboard.io" target="_blank">Thingsboard v.{{ thingsboardVersion }}</a></span>
256 252 </section>
257 253 </div>
... ...
... ... @@ -32,9 +32,9 @@ div.tb-dashboard-page {
32 32 background-color: #eee;
33 33 }
34 34 section.tb-dashboard-title {
35   - position: absolute;
36   - top: 0;
37   - left: 20px;
  35 + position: relative;
  36 + padding-left: 20px;
  37 + max-height: 60px;
38 38 mat-form-field {
39 39 .mat-form-field-infix {
40 40 width: 100%;
... ... @@ -47,17 +47,6 @@ div.tb-dashboard-page {
47 47 letter-spacing: .005em;
48 48 }
49 49 }
50   - div.tb-padded {
51   - top: 60px;
52   - }
53   -
54   - section.tb-padded {
55   - top: 60px;
56   - }
57   -
58   - div.tb-shrinked {
59   - width: 40%;
60   - }
61 50
62 51 section.tb-dashboard-toolbar {
63 52 position: absolute;
... ... @@ -106,21 +95,16 @@ div.tb-dashboard-page {
106 95 transition: margin-top .3s cubic-bezier(.55, 0, .55, .2) .2s;
107 96 }
108 97 }
  98 + }
109 99
110   - .tb-dashboard-layouts {
111   - /*md-backdrop {
112   - z-index: 1;
113   - }*/
114   - #tb-right-layout {
115   - mat-drawer {
116   - z-index: 1;
117   - }
  100 + mat-drawer-container.tb-dashboard-drawer-container {
  101 + mat-drawer-container.tb-dashboard-layouts {
  102 + width: 100%;
  103 + &.tb-shrinked {
  104 + width: 40%;
118 105 }
119 106 }
120   - }
121 107
122   - mat-drawer-container.tb-widget-details-sidenav {
123   - position: initial;
124 108 mat-drawer.tb-details-drawer {
125 109 @media #{$mat-gt-sm} {
126 110 width: 85% !important;
... ... @@ -136,10 +120,6 @@ div.tb-dashboard-page {
136 120 }
137 121 }
138 122
139   - mat-drawer-container.tb-select-widget-sidenav {
140   - position: initial;
141   - }
142   -
143 123 section.tb-powered-by-footer {
144 124 position: absolute;
145 125 right: 25px;
... ...
... ... @@ -104,9 +104,11 @@ export class DashboardPageComponent extends PageComponent implements IDashboardC
104 104 isFullscreen = false;
105 105 isEdit = false;
106 106 isEditingWidget = false;
  107 + isEditingWidgetClosed = true;
107 108 isMobile = !this.breakpointObserver.isMatched(MediaBreakpoints['gt-sm']);
108 109 forceDashboardMobileMode = false;
109 110 isAddingWidget = false;
  111 + isAddingWidgetClosed = true;
110 112 widgetsBundle: WidgetsBundle = null;
111 113
112 114 isToolbarOpened = false;
... ... @@ -284,8 +286,10 @@ export class DashboardPageComponent extends PageComponent implements IDashboardC
284 286 this.isFullscreen = false;
285 287 this.isEdit = false;
286 288 this.isEditingWidget = false;
  289 + this.isEditingWidgetClosed = true;
287 290 this.forceDashboardMobileMode = false;
288 291 this.isAddingWidget = false;
  292 + this.isAddingWidgetClosed = true;
289 293 this.widgetsBundle = null;
290 294
291 295 this.isToolbarOpened = false;
... ... @@ -694,6 +698,31 @@ export class DashboardPageComponent extends PageComponent implements IDashboardC
694 698 this.isAddingWidget = false;
695 699 }
696 700
  701 + detailsDrawerOpenedStart() {
  702 + if (this.isEditingWidget) {
  703 + this.isEditingWidgetClosed = false;
  704 + } else if (this.isAddingWidget) {
  705 + this.isAddingWidgetClosed = false;
  706 + }
  707 + setTimeout(() => {
  708 + this.cd.detach();
  709 + }, 0);
  710 + }
  711 +
  712 + detailsDrawerOpened() {
  713 + this.cd.reattach();
  714 + }
  715 +
  716 + detailsDrawerClosedStart() {
  717 + this.cd.detach();
  718 + }
  719 +
  720 + detailsDrawerClosed() {
  721 + this.isEditingWidgetClosed = true;
  722 + this.isAddingWidgetClosed = true;
  723 + this.cd.reattach();
  724 + }
  725 +
697 726 private addWidgetToLayout(widget: Widget, layoutId: DashboardLayoutId) {
698 727 this.dashboardUtils.addWidgetToLayout(this.dashboard, this.dashboardCtx.state, layoutId, widget);
699 728 this.layouts[layoutId].layoutCtx.widgets.addWidgetId(widget.id);
... ...
... ... @@ -77,6 +77,8 @@ export class LayoutWidgetsArray implements Iterable<Widget> {
77 77 private widgetIds: string[] = [];
78 78 private pointer = 0;
79 79
  80 + private loaded = false;
  81 +
80 82 constructor(private dashboard: Dashboard) {
81 83 }
82 84
... ... @@ -84,8 +86,17 @@ export class LayoutWidgetsArray implements Iterable<Widget> {
84 86 return this.widgetIds.length;
85 87 }
86 88
  89 + isLoading() {
  90 + return !this.loaded;
  91 + }
  92 +
  93 + isEmpty() {
  94 + return this.loaded && this.widgetIds.length === 0;
  95 + }
  96 +
87 97 setWidgetIds(widgetIds: string[]) {
88 98 this.widgetIds = widgetIds;
  99 + this.loaded = true;
89 100 }
90 101
91 102 addWidgetId(widgetId: string) {
... ...
... ... @@ -102,6 +102,9 @@ export class EditWidgetComponent extends PageComponent implements OnInit, OnChan
102 102 }
103 103
104 104 private loadWidgetConfig() {
  105 + if (!this.widget) {
  106 + return;
  107 + }
105 108 const widgetInfo = this.widgetComponentService.getInstantWidgetInfo(this.widget);
106 109 const rawSettingsSchema = widgetInfo.typeSettingsSchema || widgetInfo.settingsSchema;
107 110 const rawDataKeySettingsSchema = widgetInfo.typeDataKeySettingsSchema || widgetInfo.dataKeySettingsSchema;
... ...
... ... @@ -16,10 +16,15 @@
16 16
17 17 -->
18 18 <hotkeys-cheatsheet></hotkeys-cheatsheet>
  19 +<div fxLayout="column" class="tb-progress-cover" fxLayoutAlign="center center"
  20 + *ngIf="layoutCtx.widgets.isLoading()">
  21 + <mat-spinner color="warn" mode="indeterminate" diameter="100">
  22 + </mat-spinner>
  23 +</div>
19 24 <div class="mat-content" style="position: relative; width: 100%; height: 100%;"
20 25 [style.backgroundImage]="backgroundImage"
21 26 [ngStyle]="dashboardStyle">
22   - <section *ngIf="layoutCtx.widgets.size() === 0" fxLayoutAlign="center center"
  27 + <section *ngIf="layoutCtx.widgets.isEmpty()" fxLayoutAlign="center center"
23 28 [ngStyle]="{'color': layoutCtx.gridSettings.color}"
24 29 style="text-transform: uppercase; display: flex; z-index: 1; pointer-events: none;"
25 30 class="mat-headline tb-absolute-fill">
... ...
... ... @@ -31,8 +31,8 @@
31 31 <mat-icon class="material-icons">{{ fullscreen ? 'fullscreen_exit' : 'fullscreen' }}</mat-icon>
32 32 </button>
33 33 </div>
34   - <div fxFlex="0%" id="tb-javascript-panel" class="tb-js-func-panel" fxLayout="column" tb-toast toastTarget="jsFuncEditor">
35   - <div fxFlex #javascriptEditor id="tb-javascript-input" [ngClass]="{'fill-height': fillHeight}"></div>
  34 + <div id="tb-javascript-panel" class="tb-js-func-panel" fxLayout="column" tb-toast toastTarget="jsFuncEditor">
  35 + <div #javascriptEditor id="tb-javascript-input" [ngClass]="{'fill-height': fillHeight}"></div>
36 36 </div>
37 37 <div fxLayout="row" fxLayoutAlign="start center" style="height: 40px;">
38 38 <label class="tb-title no-padding">}</label>
... ...
... ... @@ -30,7 +30,7 @@
30 30 <mat-icon class="material-icons">{{ fullscreen ? 'fullscreen_exit' : 'fullscreen' }}</mat-icon>
31 31 </button>
32 32 </div>
33   - <div fxFlex="0%" id="tb-json-panel" tb-toast toastTarget="jsonObjectEditor"
  33 + <div id="tb-json-panel" tb-toast toastTarget="jsonObjectEditor"
34 34 class="tb-json-object-panel" fxLayout="column">
35 35 <div #jsonEditor id="tb-json-input" [ngStyle]="editorStyle" [ngClass]="{'fill-height': fillHeight}"></div>
36 36 </div>
... ...
... ... @@ -144,7 +144,7 @@ class DraggableChip {
144 144 const dataTransfer = event.dataTransfer;
145 145 dataTransfer.effectAllowed = 'copyMove';
146 146 dataTransfer.dropEffect = 'move';
147   - dataTransfer.setData('text/plain', this.index() + '');
  147 + dataTransfer.setData('text', this.index() + '');
148 148 }
149 149 }
150 150
... ... @@ -222,7 +222,7 @@ class DraggableChip {
222 222 return;
223 223 }
224 224 event = (event as any).originalEvent || event;
225   - const droppedItemIndex = parseInt(event.dataTransfer.getData('text/plain'), 10);
  225 + const droppedItemIndex = parseInt(event.dataTransfer.getData('text'), 10);
226 226 const currentIndex = this.index();
227 227 let newIndex;
228 228 if (this.dropPosition === 'before') {
... ...
... ... @@ -17,94 +17,92 @@
17 17 -->
18 18 <form [formGroup]="timewindowForm" (ngSubmit)="update()">
19 19 <fieldset [disabled]="(isLoading$ | async)">
20   - <div class="mat-content" style="height: 100%;" fxFlex fxLayout="column">
21   - <section fxLayout="column">
22   - <mat-tab-group dynamicHeight [ngClass]="{'tb-headless': historyOnly}"
23   - (selectedIndexChange)="timewindowForm.markAsDirty()" [(selectedIndex)]="timewindow.selectedTab">
24   - <mat-tab label="{{ 'timewindow.realtime' | translate }}">
25   - <div formGroupName="realtime" class="mat-content mat-padding" fxLayout="column">
26   - <tb-timeinterval
27   - formControlName="timewindowMs"
28   - predefinedName="timewindow.last"
29   - [required]="timewindow.selectedTab === timewindowTypes.REALTIME"
30   - style="padding-top: 8px;"></tb-timeinterval>
31   - </div>
32   - </mat-tab>
33   - <mat-tab label="{{ 'timewindow.history' | translate }}">
34   - <div formGroupName="history" class="mat-content mat-padding" style="padding-top: 8px;">
35   - <mat-radio-group formControlName="historyType">
36   - <mat-radio-button [value]="historyTypes.LAST_INTERVAL" color="primary">
37   - <section fxLayout="column">
38   - <tb-timeinterval
39   - formControlName="timewindowMs"
40   - predefinedName="timewindow.last"
41   - [fxShow]="timewindowForm.get('history').get('historyType').value === historyTypes.LAST_INTERVAL"
42   - [required]="timewindow.selectedTab === timewindowTypes.HISTORY &&
43   - timewindowForm.get('history').get('historyType').value === historyTypes.LAST_INTERVAL"
44   - style="padding-top: 8px;"></tb-timeinterval>
45   - </section>
46   - </mat-radio-button>
47   - <mat-radio-button [value]="historyTypes.FIXED" color="primary">
48   - <section fxLayout="column">
49   - <span translate>timewindow.time-period</span>
50   - <tb-datetime-period
51   - formControlName="fixedTimewindow"
52   - [fxShow]="timewindowForm.get('history').get('historyType').value === historyTypes.FIXED"
53   - [required]="timewindow.selectedTab === timewindowTypes.HISTORY &&
54   - timewindowForm.get('history').get('historyType').value === historyTypes.FIXED"
55   - style="padding-top: 8px;"></tb-datetime-period>
56   - </section>
57   - </mat-radio-button>
58   - </mat-radio-group>
59   - </div>
60   - </mat-tab>
61   - </mat-tab-group>
62   - <div *ngIf="aggregation" formGroupName="aggregation" class="mat-content mat-padding" fxLayout="column">
63   - <mat-form-field>
64   - <mat-label translate>aggregation.function</mat-label>
65   - <mat-select matInput formControlName="type" style="min-width: 150px;">
66   - <mat-option *ngFor="let aggregation of aggregations" [value]="aggregation">
67   - {{ aggregationTypesTranslations.get(aggregation) | translate }}
68   - </mat-option>
69   - </mat-select>
70   - </mat-form-field>
71   - <div *ngIf="timewindowForm.get('aggregation').get('type').value === aggregationTypes.NONE"
72   - class="limit-slider-container"
73   - fxLayout="row" fxLayoutAlign="start center">
74   - <span translate>aggregation.limit</span>
75   - <mat-slider fxFlex formControlName="limit"
76   - thumbLabel
77   - [value]="timewindowForm.get('aggregation').get('limit').value"
78   - min="{{minDatapointsLimit()}}"
79   - max="{{maxDatapointsLimit()}}">
80   - </mat-slider>
81   - <mat-form-field style="max-width: 80px;">
82   - <input matInput formControlName="limit" type="number" step="1"
83   - [value]="timewindowForm.get('aggregation').get('limit').value"
84   - min="{{minDatapointsLimit()}}"
85   - max="{{maxDatapointsLimit()}}"/>
86   - </mat-form-field>
  20 + <div class="mat-content" style="height: 100%;" fxLayout="column">
  21 + <mat-tab-group dynamicHeight [ngClass]="{'tb-headless': historyOnly}"
  22 + (selectedIndexChange)="timewindowForm.markAsDirty()" [(selectedIndex)]="timewindow.selectedTab">
  23 + <mat-tab label="{{ 'timewindow.realtime' | translate }}">
  24 + <div formGroupName="realtime" class="mat-content mat-padding" fxLayout="column">
  25 + <tb-timeinterval
  26 + formControlName="timewindowMs"
  27 + predefinedName="timewindow.last"
  28 + [required]="timewindow.selectedTab === timewindowTypes.REALTIME"
  29 + style="padding-top: 8px;"></tb-timeinterval>
87 30 </div>
  31 + </mat-tab>
  32 + <mat-tab label="{{ 'timewindow.history' | translate }}">
  33 + <div formGroupName="history" class="mat-content mat-padding" style="padding-top: 8px;">
  34 + <mat-radio-group formControlName="historyType">
  35 + <mat-radio-button [value]="historyTypes.LAST_INTERVAL" color="primary">
  36 + <section fxLayout="column">
  37 + <tb-timeinterval
  38 + formControlName="timewindowMs"
  39 + predefinedName="timewindow.last"
  40 + [fxShow]="timewindowForm.get('history').get('historyType').value === historyTypes.LAST_INTERVAL"
  41 + [required]="timewindow.selectedTab === timewindowTypes.HISTORY &&
  42 + timewindowForm.get('history').get('historyType').value === historyTypes.LAST_INTERVAL"
  43 + style="padding-top: 8px;"></tb-timeinterval>
  44 + </section>
  45 + </mat-radio-button>
  46 + <mat-radio-button [value]="historyTypes.FIXED" color="primary">
  47 + <section fxLayout="column">
  48 + <span translate>timewindow.time-period</span>
  49 + <tb-datetime-period
  50 + formControlName="fixedTimewindow"
  51 + [fxShow]="timewindowForm.get('history').get('historyType').value === historyTypes.FIXED"
  52 + [required]="timewindow.selectedTab === timewindowTypes.HISTORY &&
  53 + timewindowForm.get('history').get('historyType').value === historyTypes.FIXED"
  54 + style="padding-top: 8px;"></tb-datetime-period>
  55 + </section>
  56 + </mat-radio-button>
  57 + </mat-radio-group>
  58 + </div>
  59 + </mat-tab>
  60 + </mat-tab-group>
  61 + <div *ngIf="aggregation" formGroupName="aggregation" class="mat-content mat-padding" fxLayout="column">
  62 + <mat-form-field>
  63 + <mat-label translate>aggregation.function</mat-label>
  64 + <mat-select matInput formControlName="type" style="min-width: 150px;">
  65 + <mat-option *ngFor="let aggregation of aggregations" [value]="aggregation">
  66 + {{ aggregationTypesTranslations.get(aggregation) | translate }}
  67 + </mat-option>
  68 + </mat-select>
  69 + </mat-form-field>
  70 + <div *ngIf="timewindowForm.get('aggregation').get('type').value === aggregationTypes.NONE"
  71 + class="limit-slider-container"
  72 + fxLayout="row" fxLayoutAlign="start center">
  73 + <span translate>aggregation.limit</span>
  74 + <mat-slider fxFlex formControlName="limit"
  75 + thumbLabel
  76 + [value]="timewindowForm.get('aggregation').get('limit').value"
  77 + min="{{minDatapointsLimit()}}"
  78 + max="{{maxDatapointsLimit()}}">
  79 + </mat-slider>
  80 + <mat-form-field style="max-width: 80px;">
  81 + <input matInput formControlName="limit" type="number" step="1"
  82 + [value]="timewindowForm.get('aggregation').get('limit').value"
  83 + min="{{minDatapointsLimit()}}"
  84 + max="{{maxDatapointsLimit()}}"/>
  85 + </mat-form-field>
88 86 </div>
89   - <div formGroupName="realtime"
90   - *ngIf="aggregation && timewindowForm.get('aggregation').get('type').value !== aggregationTypes.NONE &&
91   - timewindow.selectedTab === timewindowTypes.REALTIME" class="mat-content mat-padding" fxLayout="column">
92   - <tb-timeinterval
93   - formControlName="interval"
94   - [min]="minRealtimeAggInterval()" [max]="maxRealtimeAggInterval()"
95   - predefinedName="aggregation.group-interval">
96   - </tb-timeinterval>
97   - </div>
98   - <div formGroupName="history"
99   - *ngIf="aggregation && timewindowForm.get('aggregation').get('type').value !== aggregationTypes.NONE &&
100   - timewindow.selectedTab === timewindowTypes.HISTORY" class="mat-content mat-padding" fxLayout="column">
101   - <tb-timeinterval
102   - formControlName="interval"
103   - [min]="minHistoryAggInterval()" [max]="maxHistoryAggInterval()"
104   - predefinedName="aggregation.group-interval">
105   - </tb-timeinterval>
106   - </div>
107   - </section>
  87 + </div>
  88 + <div formGroupName="realtime"
  89 + *ngIf="aggregation && timewindowForm.get('aggregation').get('type').value !== aggregationTypes.NONE &&
  90 + timewindow.selectedTab === timewindowTypes.REALTIME" class="mat-content mat-padding" fxLayout="column">
  91 + <tb-timeinterval
  92 + formControlName="interval"
  93 + [min]="minRealtimeAggInterval()" [max]="maxRealtimeAggInterval()"
  94 + predefinedName="aggregation.group-interval">
  95 + </tb-timeinterval>
  96 + </div>
  97 + <div formGroupName="history"
  98 + *ngIf="aggregation && timewindowForm.get('aggregation').get('type').value !== aggregationTypes.NONE &&
  99 + timewindow.selectedTab === timewindowTypes.HISTORY" class="mat-content mat-padding" fxLayout="column">
  100 + <tb-timeinterval
  101 + formControlName="interval"
  102 + [min]="minHistoryAggInterval()" [max]="maxHistoryAggInterval()"
  103 + predefinedName="aggregation.group-interval">
  104 + </tb-timeinterval>
  105 + </div>
108 106 <span fxFlex></span>
109 107 <div fxLayout="row" class="tb-panel-actions">
110 108 <span fxFlex></span>
... ...