Browse Source

Merge remote-tracking branch 'upstream/develop/3.5.2' into customer-removing-alarm-unassign

pull/9035/head
imbeacon 3 years ago
parent
commit
2dfe20e9ca
  1. 7
      common/script/script-api/src/main/java/org/thingsboard/script/api/tbel/DefaultTbelInvokeService.java
  2. 2
      pom.xml
  3. 18
      ui-ngx/src/app/modules/home/components/dashboard-page/add-widget-dialog.component.html
  4. 9
      ui-ngx/src/app/modules/home/components/dashboard-page/add-widget-dialog.component.scss
  5. 25
      ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-page.component.html
  6. 2
      ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-page.component.ts
  7. 37
      ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-toolbar.component.scss
  8. 44
      ui-ngx/src/app/modules/home/components/dashboard-page/edit-widget.component.html
  9. 2
      ui-ngx/src/app/modules/home/components/dashboard-page/edit-widget.component.scss
  10. 2
      ui-ngx/src/app/modules/home/components/details-panel.component.html
  11. 13
      ui-ngx/src/app/modules/home/components/details-panel.component.scss
  12. 2
      ui-ngx/src/app/modules/home/components/widget/config/basic/alarm/alarms-table-basic-config.component.html
  13. 6
      ui-ngx/src/app/modules/home/components/widget/config/basic/basic-config.scss
  14. 2
      ui-ngx/src/app/modules/home/components/widget/config/basic/cards/entities-table-basic-config.component.html
  15. 2
      ui-ngx/src/app/modules/home/components/widget/config/basic/cards/simple-card-basic-config.component.html
  16. 2
      ui-ngx/src/app/modules/home/components/widget/config/basic/cards/timeseries-table-basic-config.component.html
  17. 2
      ui-ngx/src/app/modules/home/components/widget/config/basic/cards/value-card-basic-config.component.html
  18. 2
      ui-ngx/src/app/modules/home/components/widget/config/basic/chart/flot-basic-config.component.html
  19. 3
      ui-ngx/src/app/modules/home/components/widget/config/basic/common/data-key-row.component.html
  20. 30
      ui-ngx/src/app/modules/home/components/widget/config/basic/common/data-key-row.component.scss
  21. 3
      ui-ngx/src/app/modules/home/components/widget/config/basic/common/data-keys-panel.component.html
  22. 40
      ui-ngx/src/app/modules/home/components/widget/config/basic/common/data-keys-panel.component.scss
  23. 11
      ui-ngx/src/app/modules/home/components/widget/config/timewindow-config-panel.component.html
  24. 2
      ui-ngx/src/app/modules/home/components/widget/lib/settings/common/legend-config.component.html
  25. 3
      ui-ngx/src/app/modules/home/components/widget/lib/settings/widget-settings.scss
  26. 22
      ui-ngx/src/app/modules/home/components/widget/widget-config.component.html
  27. 35
      ui-ngx/src/app/modules/home/components/widget/widget-config.component.scss
  28. 3
      ui-ngx/src/app/shared/components/time/timewindow.component.scss
  29. 7
      ui-ngx/src/app/shared/components/time/timewindow.component.ts
  30. 8
      ui-ngx/src/app/shared/components/toggle-header.component.html
  31. 3
      ui-ngx/src/app/shared/components/toggle-header.component.scss
  32. 74
      ui-ngx/src/app/shared/components/toggle-header.component.ts
  33. 1
      ui-ngx/src/app/shared/components/toggle-select.component.html
  34. 3
      ui-ngx/src/app/shared/components/toggle-select.component.ts
  35. 9
      ui-ngx/src/app/shared/models/ace/tbel/worker-tbel.js
  36. 66
      ui-ngx/src/form.scss
  37. 29
      ui-ngx/src/styles.scss

7
common/script/script-api/src/main/java/org/thingsboard/script/api/tbel/DefaultTbelInvokeService.java

@ -66,8 +66,6 @@ public class DefaultTbelInvokeService extends AbstractScriptInvokeService implem
protected final Map<UUID, String> scriptIdToHash = new ConcurrentHashMap<>(); protected final Map<UUID, String> scriptIdToHash = new ConcurrentHashMap<>();
protected final Map<String, TbelScript> scriptMap = new ConcurrentHashMap<>(); protected final Map<String, TbelScript> scriptMap = new ConcurrentHashMap<>();
private final String tbelSwitch = "switch";
private final String tbelSwitchErrorMsg = "TBEL does not support the 'switch'.";
protected Cache<String, Serializable> compiledScriptsCache; protected Cache<String, Serializable> compiledScriptsCache;
private SandboxedParserConfiguration parserConfig; private SandboxedParserConfiguration parserConfig;
@ -183,11 +181,6 @@ public class DefaultTbelInvokeService extends AbstractScriptInvokeService implem
lock.unlock(); lock.unlock();
} }
return scriptId; return scriptId;
} catch (CompileException ce) {
if ( ce.getExpr() != null && new String(ce.getExpr()).contains(tbelSwitch)) {
ce = new CompileException(tbelSwitchErrorMsg, ce.getExpr(), ce.getCursor(), ce.getCause());
}
throw new TbScriptException(scriptId, TbScriptException.ErrorCode.COMPILATION, scriptBody, ce);
} catch (Exception e) { } catch (Exception e) {
throw new TbScriptException(scriptId, TbScriptException.ErrorCode.COMPILATION, scriptBody, e); throw new TbScriptException(scriptId, TbScriptException.ErrorCode.COMPILATION, scriptBody, e);
} }

2
pom.xml

@ -78,7 +78,7 @@
<zookeeper.version>3.8.1</zookeeper.version> <zookeeper.version>3.8.1</zookeeper.version>
<protobuf.version>3.21.9</protobuf.version> <protobuf.version>3.21.9</protobuf.version>
<grpc.version>1.42.1</grpc.version> <grpc.version>1.42.1</grpc.version>
<tbel.version>1.0.6</tbel.version> <tbel.version>1.0.7</tbel.version>
<lombok.version>1.18.18</lombok.version> <lombok.version>1.18.18</lombok.version>
<paho.client.version>1.2.4</paho.client.version> <paho.client.version>1.2.4</paho.client.version>
<paho.mqttv5.client.version>1.2.5</paho.mqttv5.client.version> <paho.mqttv5.client.version>1.2.5</paho.mqttv5.client.version>

18
ui-ngx/src/app/modules/home/components/dashboard-page/add-widget-dialog.component.html

@ -17,14 +17,16 @@
--> -->
<form class="tb-add-widget-dialog" [formGroup]="widgetFormGroup"> <form class="tb-add-widget-dialog" [formGroup]="widgetFormGroup">
<mat-toolbar color="primary"> <mat-toolbar color="primary">
<h2 translate>widget.add</h2> <div class="tb-add-widget-toolbar">
<span fxFlex>: {{data.widgetInfo.widgetName}}</span> <h2 fxFlex>{{'widget.add' | translate}}: {{data.widgetInfo.widgetName}}</h2>
<div fxLayout="row" fxLayoutAlign="start center" fxLayoutGap="16px"> <div fxLayout="row" fxLayoutAlign="start center" fxLayoutGap.gt-xs="16px">
<tb-toggle-select *ngIf="hasBasicMode" appearance="fill-invert" disablePagination [(ngModel)]="widgetConfigMode" [ngModelOptions]="{standalone: true}"> <tb-toggle-select *ngIf="hasBasicMode" appearance="fill-invert" selectMediaBreakpoint="xs"
<tb-toggle-option value="basic">{{ 'widget.basic-mode' | translate }}</tb-toggle-option> [(ngModel)]="widgetConfigMode" [ngModelOptions]="{standalone: true}">
<tb-toggle-option value="advanced">{{ 'widget.advanced-mode' | translate }}</tb-toggle-option> <tb-toggle-option value="basic">{{ 'widget.basic-mode' | translate }}</tb-toggle-option>
</tb-toggle-select> <tb-toggle-option value="advanced">{{ 'widget.advanced-mode' | translate }}</tb-toggle-option>
<div [tb-help]="helpLinkIdForWidgetType()"></div> </tb-toggle-select>
<div [tb-help]="helpLinkIdForWidgetType()"></div>
</div>
</div> </div>
<button mat-icon-button <button mat-icon-button
(click)="cancel()" (click)="cancel()"

9
ui-ngx/src/app/modules/home/components/dashboard-page/add-widget-dialog.component.scss

@ -26,4 +26,13 @@
height: 900px; height: 900px;
} }
} }
.tb-add-widget-toolbar {
flex: 1;
min-width: 0;
display: flex;
flex-direction: row;
place-content: center flex-start;
align-items: center;
gap: 8px;
}
} }

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

@ -25,8 +25,7 @@
[toolbarOpened]="toolbarOpened" (triggerClick)="openToolbar()"> [toolbarOpened]="toolbarOpened" (triggerClick)="openToolbar()">
<div class="tb-dashboard-action-panels" fxLayout="column" fxLayout.gt-sm="row" <div class="tb-dashboard-action-panels" fxLayout="column" fxLayout.gt-sm="row"
fxLayoutAlign="center stretch" fxLayoutAlign.gt-sm="space-between center"> fxLayoutAlign="center stretch" fxLayoutAlign.gt-sm="space-between center">
<div class="tb-dashboard-action-panel" fxFlex="auto" fxLayout="row-reverse" [fxHide]="isMobileApp && !isEdit" <div class="tb-dashboard-action-panel tb-left-panel" [fxHide]="isMobileApp && !isEdit">
fxLayoutAlign.gt-sm="end center" fxLayoutAlign="space-between center" fxLayoutGap.lt-lg="6px" fxLayoutGap.gt-md="12px">
<tb-user-menu *ngIf="!isPublicUser() && forceFullscreen" fxHide.gt-sm displayUserInfo="true"> <tb-user-menu *ngIf="!isPublicUser() && forceFullscreen" fxHide.gt-sm displayUserInfo="true">
</tb-user-menu> </tb-user-menu>
<ng-container *ngIf="isEdit"> <ng-container *ngIf="isEdit">
@ -74,8 +73,7 @@
<img *ngIf="showDashboardLogo()" [src]="dashboardLogo" <img *ngIf="showDashboardLogo()" [src]="dashboardLogo"
aria-label="dashboard_logo" class="dashboard_logo"/> aria-label="dashboard_logo" class="dashboard_logo"/>
</div> </div>
<div class="tb-dashboard-action-panel" fxFlex="1 0 auto" fxLayout="row-reverse" <div class="tb-dashboard-action-panel">
fxLayoutAlign.gt-sm="start center" fxLayoutAlign="space-between center" fxLayoutGap.lt-lg="6px" fxLayoutGap.gt-md="12px">
<button [fxShow]="showCloseToolbar()" mat-icon-button class="close-action" <button [fxShow]="showCloseToolbar()" mat-icon-button class="close-action"
matTooltip="{{ 'dashboard.close-toolbar' | translate }}" matTooltip="{{ 'dashboard.close-toolbar' | translate }}"
matTooltipPosition="below" matTooltipPosition="below"
@ -235,8 +233,21 @@
</tb-timewindow> </tb-timewindow>
</ng-container> </ng-container>
</ng-template> </ng-template>
<button [fxShow]="isEdit" mat-stroked-button (click)="addWidget($event)"> <ng-container *ngIf="isEdit">
<mat-icon>add</mat-icon>{{ 'dashboard.add-widget-button-text' | translate }}</button> <button fxHide.gt-xs mat-icon-button
matTooltip="{{ 'dashboard.add-widget-button-text' | translate }}"
matTooltipPosition="below"
(click)="addWidget($event)">
<mat-icon>add</mat-icon>
</button>
<button fxHide.lt-sm mat-stroked-button
matTooltip="{{ 'dashboard.add-widget-button-text' | translate }}"
matTooltipPosition="below"
(click)="addWidget($event)">
<mat-icon>add</mat-icon>
{{ 'dashboard.add-widget-button-text' | translate }}
</button>
</ng-container>
<tb-filters-edit [fxShow]="!isEdit && displayFilters()" <tb-filters-edit [fxShow]="!isEdit && displayFilters()"
tooltipPosition="below" tooltipPosition="below"
[aliasController]="dashboardCtx.aliasController"> [aliasController]="dashboardCtx.aliasController">
@ -360,7 +371,7 @@
[isReadOnly]="true" [isReadOnly]="true"
(closeDetails)="onEditWidgetClosed()"> (closeDetails)="onEditWidgetClosed()">
<div class="details-buttons" fxLayout="row" fxLayoutAlign="start center" fxLayoutGap="16px"> <div class="details-buttons" fxLayout="row" fxLayoutAlign="start center" fxLayoutGap="16px">
<tb-toggle-select *ngIf="tbEditWidget.hasBasicMode" appearance="fill-invert" disablePagination [(ngModel)]="tbEditWidget.widgetConfigMode"> <tb-toggle-select *ngIf="tbEditWidget.hasBasicMode" appearance="fill-invert" selectMediaBreakpoint="xs" [(ngModel)]="tbEditWidget.widgetConfigMode">
<tb-toggle-option value="basic">{{ 'widget.basic-mode' | translate }}</tb-toggle-option> <tb-toggle-option value="basic">{{ 'widget.basic-mode' | translate }}</tb-toggle-option>
<tb-toggle-option value="advanced">{{ 'widget.advanced-mode' | translate }}</tb-toggle-option> <tb-toggle-option value="advanced">{{ 'widget.advanced-mode' | translate }}</tb-toggle-option>
</tb-toggle-select> </tb-toggle-select>

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

@ -191,7 +191,7 @@ export class DashboardPageComponent extends PageComponent implements IDashboardC
} }
get hideToolbar(): boolean { get hideToolbar(): boolean {
return (this.hideToolbarValue || this.hideToolbarSetting()) && !this.isEdit; return ((this.hideToolbarValue || this.hideToolbarSetting()) && !this.isEdit) || (this.isEditingWidget || this.isAddingWidget);
} }
@Input() @Input()

37
ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-toolbar.component.scss

@ -126,6 +126,7 @@ tb-dashboard-toolbar {
@media #{$mat-lt-md} { @media #{$mat-lt-md} {
height: $mobile-toolbar-height; height: $mobile-toolbar-height;
max-height: $mobile-toolbar-height; max-height: $mobile-toolbar-height;
padding: 0 8px !important;
} }
.close-action { .close-action {
@ -150,8 +151,44 @@ tb-dashboard-toolbar {
.tb-dashboard-action-panel { .tb-dashboard-action-panel {
min-width: 0; min-width: 0;
height: $half-mobile-toolbar-height; height: $half-mobile-toolbar-height;
flex: 1 0 auto;
display: flex;
flex-direction: row-reverse;
place-content: center space-between;
align-items: center;
&.tb-left-panel {
flex: 1 1 auto;
}
@media #{$mat-lt-md} {
padding-left: 12px;
}
@media #{$mat-xs} {
gap: 3px;
padding-left: 0;
&.tb-left-panel {
padding-left: 12px;
}
}
@media #{$mat-sm} {
gap: 6px;
}
@media #{$mat-md} {
gap: 6px;
}
@media #{$mat-gt-md} {
gap: 12px;
}
@media #{$mat-gt-sm} { @media #{$mat-gt-sm} {
place-content: center flex-start;
&.tb-left-panel {
place-content: center flex-end;
}
height: 46px; height: 46px;
} }

44
ui-ngx/src/app/modules/home/components/dashboard-page/edit-widget.component.html

@ -32,26 +32,38 @@
<mat-icon>chevron_left</mat-icon> <mat-icon>chevron_left</mat-icon>
{{ 'action.back' | translate }} {{ 'action.back' | translate }}
</button> </button>
</div> <button *ngIf="!previewMode"
<div class="tb-widget-config-header-suffix" fxLayout="row" fxLayoutAlign="start center" fxLayoutGap="12px"> fxHide.gt-sm
<button *ngIf="!previewMode" [disabled]="(isLoading$ | async) || widgetFormGroup.invalid" [disabled]="widgetFormGroup.invalid"
mat-button color="primary" mat-button color="primary"
(click)="previewMode = true"> (click)="previewMode = true">
<mat-icon>visibility</mat-icon> <mat-icon>visibility</mat-icon>
{{ 'widget-config.preview' | translate }} {{ 'widget-config.preview' | translate }}
</button> </button>
<button [disabled]="(isLoading$ | async) || !widgetFormGroup.dirty" </div>
mat-stroked-button color="primary" <div fxFlex.lt-md class="tb-widget-config-header-suffix" fxLayout="row" fxLayoutAlign="end center" fxLayoutGap="12px">
(click)="onRevertWidgetConfig()"> <button *ngIf="!previewMode"
<mat-icon>close</mat-icon> fxHide.lt-md
{{ 'action.decline' | translate }} [disabled]="widgetFormGroup.invalid"
</button> mat-button color="primary"
<button [disabled]="(isLoading$ | async) || widgetFormGroup.invalid || !widgetFormGroup.dirty" (click)="previewMode = true">
mat-flat-button color="primary" <mat-icon>visibility</mat-icon>
(click)="onApplyWidgetConfig()"> {{ 'widget-config.preview' | translate }}
<mat-icon>done</mat-icon>
{{ 'action.apply' | translate }}
</button> </button>
<div fxLayout="row" fxLayoutAlign="start center" fxLayoutGap="12px">
<button [disabled]="!widgetFormGroup.dirty"
mat-stroked-button color="primary"
(click)="onRevertWidgetConfig()">
<mat-icon>close</mat-icon>
{{ 'action.decline' | translate }}
</button>
<button [disabled]="widgetFormGroup.invalid || !widgetFormGroup.dirty"
mat-flat-button color="primary"
(click)="onApplyWidgetConfig()">
<mat-icon>done</mat-icon>
{{ 'action.apply' | translate }}
</button>
</div>
</div> </div>
</tb-widget-config> </tb-widget-config>
<div *ngIf="previewMode" class="widget-preview-background"> <div *ngIf="previewMode" class="widget-preview-background">

2
ui-ngx/src/app/modules/home/components/dashboard-page/edit-widget.component.scss

@ -16,7 +16,7 @@
:host { :host {
.widget-preview-background { .widget-preview-background {
position: absolute; position: absolute;
top: 72px; top: 68px;
left: 0; left: 0;
right: 0; right: 0;
bottom: 0; bottom: 0;

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

@ -21,7 +21,7 @@
<div class="mat-toolbar-tools tb-details-title-header" fxFlex fxLayout="column" fxLayoutAlign="start start" [fxHide]="showSearchPane"> <div class="mat-toolbar-tools tb-details-title-header" fxFlex fxLayout="column" fxLayoutAlign="start start" [fxHide]="showSearchPane">
<div class="tb-details-title" fxLayout="row" fxLayoutAlign="start center"> <div class="tb-details-title" fxLayout="row" fxLayoutAlign="start center">
<ng-content select=".prefix-title-buttons"></ng-content> <ng-content select=".prefix-title-buttons"></ng-content>
<span>{{ headerTitle }}</span> <span class="tb-details-title-text">{{ headerTitle }}</span>
</div> </div>
<span class="tb-details-subtitle">{{ headerSubtitle }}</span> <span class="tb-details-subtitle">{{ headerSubtitle }}</span>
<span style="width: 100%;"> <span style="width: 100%;">

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

@ -32,16 +32,14 @@
max-height: 120px; max-height: 120px;
&.tb-details-title-header { &.tb-details-title-header {
min-width: 0; min-width: 0;
padding: 0 16px 0 8px;
} }
} }
.tb-details-title { .tb-details-title {
width: inherit; width: inherit;
margin: 20px 8px 0 0; margin: 20px 8px 0 0;
overflow: hidden;
font-size: 1rem; font-size: 1rem;
font-weight: 400; font-weight: 400;
text-overflow: ellipsis;
white-space: nowrap;
@media #{$mat-gt-sm} { @media #{$mat-gt-sm} {
font-size: 1.5rem; font-size: 1.5rem;
@ -49,13 +47,16 @@
} }
.tb-details-subtitle { .tb-details-subtitle {
width: inherit;
margin: 10px 0; margin: 10px 0;
overflow: hidden;
font-size: 1rem; font-size: 1rem;
opacity: .8;
}
.tb-details-title-text, .tb-details-subtitle {
width: inherit;
overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
white-space: nowrap; white-space: nowrap;
opacity: .8;
} }
tb-dashboard { tb-dashboard {

2
ui-ngx/src/app/modules/home/components/widget/config/basic/alarm/alarms-table-basic-config.component.html

@ -72,7 +72,7 @@
</tb-color-input> </tb-color-input>
</div> </div>
</div> </div>
<div class="tb-form-row space-between"> <div class="tb-form-row space-between column-lt-md">
<div translate>widget-config.show-card-buttons</div> <div translate>widget-config.show-card-buttons</div>
<mat-chip-listbox multiple formControlName="cardButtons"> <mat-chip-listbox multiple formControlName="cardButtons">
<mat-chip-option value="search">{{ 'action.search' | translate }}</mat-chip-option> <mat-chip-option value="search">{{ 'action.search' | translate }}</mat-chip-option>

6
ui-ngx/src/app/modules/home/components/widget/config/basic/basic-config.scss

@ -13,8 +13,14 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
@import '../../../../../../../scss/constants';
:host { :host {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 16px; gap: 16px;
@media #{$mat-xs} {
gap: 8px;
}
} }

2
ui-ngx/src/app/modules/home/components/widget/config/basic/cards/entities-table-basic-config.component.html

@ -61,7 +61,7 @@
</tb-color-input> </tb-color-input>
</div> </div>
</div> </div>
<div class="tb-form-row space-between"> <div class="tb-form-row space-between column-lt-md">
<div translate>widget-config.show-card-buttons</div> <div translate>widget-config.show-card-buttons</div>
<mat-chip-listbox multiple formControlName="cardButtons"> <mat-chip-listbox multiple formControlName="cardButtons">
<mat-chip-option value="search">{{ 'action.search' | translate }}</mat-chip-option> <mat-chip-option value="search">{{ 'action.search' | translate }}</mat-chip-option>

2
ui-ngx/src/app/modules/home/components/widget/config/basic/cards/simple-card-basic-config.component.html

@ -61,7 +61,7 @@
<input matInput formControlName="decimals" type="number" min="0" max="15" step="1" placeholder="{{ 'widget-config.set' | translate }}"> <input matInput formControlName="decimals" type="number" min="0" max="15" step="1" placeholder="{{ 'widget-config.set' | translate }}">
</mat-form-field> </mat-form-field>
</div> </div>
<div class="tb-form-row space-between"> <div class="tb-form-row space-between column-lt-md">
<div translate>widget-config.show-card-buttons</div> <div translate>widget-config.show-card-buttons</div>
<mat-chip-listbox multiple formControlName="cardButtons"> <mat-chip-listbox multiple formControlName="cardButtons">
<mat-chip-option value="fullscreen">{{ 'fullscreen.fullscreen' | translate }}</mat-chip-option> <mat-chip-option value="fullscreen">{{ 'fullscreen.fullscreen' | translate }}</mat-chip-option>

2
ui-ngx/src/app/modules/home/components/widget/config/basic/cards/timeseries-table-basic-config.component.html

@ -61,7 +61,7 @@
</tb-color-input> </tb-color-input>
</div> </div>
</div> </div>
<div class="tb-form-row space-between"> <div class="tb-form-row space-between column-lt-md">
<div translate>widget-config.show-card-buttons</div> <div translate>widget-config.show-card-buttons</div>
<mat-chip-listbox multiple formControlName="cardButtons"> <mat-chip-listbox multiple formControlName="cardButtons">
<mat-chip-option value="search">{{ 'action.search' | translate }}</mat-chip-option> <mat-chip-option value="search">{{ 'action.search' | translate }}</mat-chip-option>

2
ui-ngx/src/app/modules/home/components/widget/config/basic/cards/value-card-basic-config.component.html

@ -105,7 +105,7 @@
<tb-background-settings formControlName="background"> <tb-background-settings formControlName="background">
</tb-background-settings> </tb-background-settings>
</div> </div>
<div class="tb-form-row space-between"> <div class="tb-form-row space-between column-lt-md">
<div translate>widget-config.show-card-buttons</div> <div translate>widget-config.show-card-buttons</div>
<mat-chip-listbox multiple formControlName="cardButtons"> <mat-chip-listbox multiple formControlName="cardButtons">
<mat-chip-option value="fullscreen">{{ 'fullscreen.fullscreen' | translate }}</mat-chip-option> <mat-chip-option value="fullscreen">{{ 'fullscreen.fullscreen' | translate }}</mat-chip-option>

2
ui-ngx/src/app/modules/home/components/widget/config/basic/chart/flot-basic-config.component.html

@ -61,7 +61,7 @@
</tb-color-input> </tb-color-input>
</div> </div>
</div> </div>
<div class="tb-form-row space-between"> <div class="tb-form-row space-between column-lt-md">
<div translate>widget-config.show-card-buttons</div> <div translate>widget-config.show-card-buttons</div>
<mat-chip-listbox multiple formControlName="cardButtons"> <mat-chip-listbox multiple formControlName="cardButtons">
<mat-chip-option value="fullscreen">{{ 'fullscreen.fullscreen' | translate }}</mat-chip-option> <mat-chip-option value="fullscreen">{{ 'fullscreen.fullscreen' | translate }}</mat-chip-option>

3
ui-ngx/src/app/modules/home/components/widget/config/basic/common/data-key-row.component.html

@ -158,7 +158,8 @@
</mat-form-field> </mat-form-field>
</div> </div>
<div class="tb-form-table-row-cell-buttons"> <div class="tb-form-table-row-cell-buttons">
<button type="button" <button fxHide.lt-lg
type="button"
mat-icon-button mat-icon-button
(click)="editKey(true)" (click)="editKey(true)"
[matTooltip]="keySettingsTitle" [matTooltip]="keySettingsTitle"

30
ui-ngx/src/app/modules/home/components/widget/config/basic/common/data-key-row.component.scss

@ -13,9 +13,14 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
@import '../../../../../../../../scss/constants';
.tb-data-key-row { .tb-data-key-row {
.mat-mdc-form-field.tb-inline-field.tb-key-field { .mat-mdc-form-field.tb-inline-field.tb-key-field {
.mat-mdc-text-field-wrapper:not(.mdc-text-field--outlined) { .mat-mdc-text-field-wrapper:not(.mdc-text-field--outlined) {
padding-left: 8px;
padding-right: 0;
.mat-mdc-form-field-infix { .mat-mdc-form-field-infix {
padding-top: 0; padding-top: 0;
padding-bottom: 6px; padding-bottom: 6px;
@ -38,16 +43,21 @@
} }
.tb-source-field { .tb-source-field {
width: 120px; width: 108px;
min-width: 120px; min-width: 108px;
} }
.tb-key-field { .tb-key-field {
flex: 1 1 60%; flex: 1;
min-width: 150px;
@media #{$mat-gt-sm} {
flex: 1 1 60%;
}
} }
.tb-label-field { .tb-label-field {
flex: 1 1 40%; flex: 1 1 40%;
min-width: 100px;
} }
.tb-color-field, .tb-units-field, .tb-decimals-field { .tb-color-field, .tb-units-field, .tb-decimals-field {
@ -62,8 +72,20 @@
min-width: 80px; min-width: 80px;
} }
.tb-color-field, .tb-decimals-field { .tb-color-field {
width: 40px;
min-width: 40px;
}
.tb-decimals-field {
width: 60px; width: 60px;
min-width: 60px; min-width: 60px;
} }
.tb-label-field, .tb-units-field, .tb-color-field, .tb-decimals-field {
display: none;
@media #{$mat-gt-sm} {
display: block;
}
}
} }

3
ui-ngx/src/app/modules/home/components/widget/config/basic/common/data-keys-panel.component.html

@ -42,7 +42,8 @@
(keyRemoved)="removeKey($index)"> (keyRemoved)="removeKey($index)">
</tb-data-key-row> </tb-data-key-row>
<div class="tb-form-table-row-cell-buttons"> <div class="tb-form-table-row-cell-buttons">
<button mat-icon-button <button fxHide.lt-lg
mat-icon-button
type="button" type="button"
cdkDragHandle cdkDragHandle
[ngClass]="{'tb-hidden': !dragEnabled}" [ngClass]="{'tb-hidden': !dragEnabled}"

40
ui-ngx/src/app/modules/home/components/widget/config/basic/common/data-keys-panel.component.scss

@ -13,27 +13,55 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
@import '../../../../../../../../scss/constants';
.tb-form-table-header-cell { .tb-form-table-header-cell {
&.tb-source-header { &.tb-source-header {
width: 120px; width: 108px;
min-width: 120px; min-width: 108px;
} }
&.tb-key-header { &.tb-key-header {
flex: 1 1 60%; flex: 1;
min-width: 150px;
@media #{$mat-gt-sm} {
flex: 1 1 60%;
}
} }
&.tb-label-header { &.tb-label-header {
flex: 1 1 40%; flex: 1 1 40%;
min-width: 100px;
} }
&.tb-units-header { &.tb-units-header {
width: 80px; width: 80px;
min-width: 80px; min-width: 80px;
} }
&.tb-color-header, &.tb-decimals-header { &.tb-color-header {
width: 40px;
min-width: 40px;
}
&.tb-decimals-header {
width: 60px; width: 60px;
min-width: 60px; min-width: 60px;
} }
&.tb-actions-header { &.tb-actions-header {
width: 114px; width: 40px;
min-width: 114px; min-width: 40px;
@media #{$mat-gt-md} {
width: 120px;
min-width: 120px;
}
}
&.tb-label-header, &.tb-units-header, &.tb-color-header, &.tb-decimals-header {
display: none;
@media #{$mat-gt-sm} {
display: block;
}
}
}
.tb-form-table-body {
tb-data-key-row {
overflow: hidden;
} }
} }

11
ui-ngx/src/app/modules/home/components/widget/config/timewindow-config-panel.component.html

@ -18,22 +18,23 @@
<div [formGroup]="timewindowConfig" class="tb-form-panel"> <div [formGroup]="timewindowConfig" class="tb-form-panel">
<div fxLayout="row" fxLayoutAlign="space-between center"> <div fxLayout="row" fxLayoutAlign="space-between center">
<div class="tb-form-panel-title" translate>timewindow.timewindow</div> <div class="tb-form-panel-title" translate>timewindow.timewindow</div>
<tb-toggle-select formControlName="useDashboardTimewindow"> <tb-toggle-select formControlName="useDashboardTimewindow" selectMediaBreakpoint="xs">
<tb-toggle-option [value]="true">{{ 'widget-config.use-dashboard-timewindow' | translate }}</tb-toggle-option> <tb-toggle-option [value]="true">{{ 'widget-config.use-dashboard-timewindow' | translate }}</tb-toggle-option>
<tb-toggle-option [value]="false">{{ 'widget-config.use-widget-timewindow' | translate }}</tb-toggle-option> <tb-toggle-option [value]="false">{{ 'widget-config.use-widget-timewindow' | translate }}</tb-toggle-option>
</tb-toggle-select> </tb-toggle-select>
</div> </div>
<div class="tb-form-row"> <div class="tb-form-row column-xs">
<mat-slide-toggle class="mat-slide" formControlName="displayTimewindow">
{{ 'widget-config.display-timewindow' | translate }}
</mat-slide-toggle>
<tb-timewindow asButton="true" <tb-timewindow asButton="true"
strokedButton strokedButton
noMargin
isEdit="true" isEdit="true"
alwaysDisplayTypePrefix alwaysDisplayTypePrefix
[historyOnly]="onlyHistoryTimewindow" [historyOnly]="onlyHistoryTimewindow"
quickIntervalOnly="{{ widgetType === widgetTypes.latest }}" quickIntervalOnly="{{ widgetType === widgetTypes.latest }}"
aggregation="{{ widgetType === widgetTypes.timeseries }}" aggregation="{{ widgetType === widgetTypes.timeseries }}"
formControlName="timewindow"></tb-timewindow> formControlName="timewindow"></tb-timewindow>
<mat-slide-toggle class="mat-slide" formControlName="displayTimewindow">
{{ 'widget-config.display-timewindow' | translate }}
</mat-slide-toggle>
</div> </div>
</div> </div>

2
ui-ngx/src/app/modules/home/components/widget/lib/settings/common/legend-config.component.html

@ -38,7 +38,7 @@
</mat-select> </mat-select>
</mat-form-field> </mat-form-field>
</div> </div>
<div class="tb-form-row space-between"> <div class="tb-form-row space-between column-lt-md">
<div translate>legend.show-values</div> <div translate>legend.show-values</div>
<mat-chip-listbox multiple formControlName="showValues"> <mat-chip-listbox multiple formControlName="showValues">
<mat-chip-option value="min">{{ 'legend.min-option' | translate }}</mat-chip-option> <mat-chip-option value="min">{{ 'legend.min-option' | translate }}</mat-chip-option>

3
ui-ngx/src/app/modules/home/components/widget/lib/settings/widget-settings.scss

@ -19,6 +19,9 @@
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 16px; gap: 16px;
@media #{$mat-xs} {
gap: 8px;
}
.tb-widget-settings { .tb-widget-settings {
.fields-group { .fields-group {

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

@ -20,8 +20,10 @@
<tb-toggle-select *ngIf="!hideToggleHeader && widgetConfigMode === widgetConfigModes.advanced" <tb-toggle-select *ngIf="!hideToggleHeader && widgetConfigMode === widgetConfigModes.advanced"
appearance="fill" [options]="headerOptions" [(ngModel)]="selectedOption"> appearance="fill" [options]="headerOptions" [(ngModel)]="selectedOption">
</tb-toggle-select> </tb-toggle-select>
<ng-content select=".tb-widget-config-header-prefix"></ng-content> <div class="tb-widget-config-header-components">
<ng-content select=".tb-widget-config-header-suffix"></ng-content> <ng-content select=".tb-widget-config-header-prefix"></ng-content>
<ng-content select=".tb-widget-config-header-suffix"></ng-content>
</div>
</div> </div>
<div *ngIf="widgetConfigMode === widgetConfigModes.advanced; else basicMode" class="tb-widget-config-content"> <div *ngIf="widgetConfigMode === widgetConfigModes.advanced; else basicMode" class="tb-widget-config-content">
<div *ngIf="widgetType !== widgetTypes.static" [fxShow]="selectedOption === 'data'" class="mat-content"> <div *ngIf="widgetType !== widgetTypes.static" [fxShow]="selectedOption === 'data'" class="mat-content">
@ -48,18 +50,18 @@
<input matInput formControlName="titleTooltip" placeholder="{{ 'widget-config.set' | translate }}"> <input matInput formControlName="titleTooltip" placeholder="{{ 'widget-config.set' | translate }}">
</mat-form-field> </mat-form-field>
</div> </div>
<div class="tb-form-row space-between"> <div class="tb-form-row space-between column-xs">
<mat-slide-toggle class="mat-slide" formControlName="showTitleIcon"> <mat-slide-toggle class="mat-slide" formControlName="showTitleIcon">
{{ 'widget-config.display-icon' | translate }} {{ 'widget-config.display-icon' | translate }}
</mat-slide-toggle> </mat-slide-toggle>
<div fxLayout="row" fxLayoutAlign="start center" fxLayoutGap="8px"> <div fxLayout="row" fxLayoutAlign="start center" fxLayoutGap="8px">
<mat-form-field appearance="outline" subscriptSizing="dynamic">
<input matInput formControlName="iconSize">
</mat-form-field>
<tb-material-icon-select asBoxInput <tb-material-icon-select asBoxInput
[color]="widgetSettings.get('iconColor').value" [color]="widgetSettings.get('iconColor').value"
formControlName="titleIcon"> formControlName="titleIcon">
</tb-material-icon-select> </tb-material-icon-select>
<mat-form-field appearance="outline" subscriptSizing="dynamic">
<input matInput formControlName="iconSize">
</mat-form-field>
<tb-color-input asBoxInput <tb-color-input asBoxInput
formControlName="iconColor"> formControlName="iconColor">
</tb-color-input> </tb-color-input>
@ -247,7 +249,7 @@
</div> </div>
<div *ngIf="displayLimits" class="tb-form-panel" [formGroup]="widgetSettings"> <div *ngIf="displayLimits" class="tb-form-panel" [formGroup]="widgetSettings">
<div class="tb-form-panel-title" translate>widget-config.limits</div> <div class="tb-form-panel-title" translate>widget-config.limits</div>
<div class="tb-form-row space-between"> <div class="tb-form-row space-between column-xs">
<div translate>widget-config.data-page-size</div> <div translate>widget-config.data-page-size</div>
<mat-form-field appearance="outline" class="number" subscriptSizing="dynamic"> <mat-form-field appearance="outline" class="number" subscriptSizing="dynamic">
<input matInput formControlName="pageSize" type="number" min="1" step="1"> <input matInput formControlName="pageSize" type="number" min="1" step="1">
@ -258,19 +260,19 @@
<ng-template #appearance> <ng-template #appearance>
<div *ngIf="displayAppearanceDataSettings" class="tb-form-panel" [formGroup]="widgetSettings"> <div *ngIf="displayAppearanceDataSettings" class="tb-form-panel" [formGroup]="widgetSettings">
<div class="tb-form-panel-title" translate>widget-config.data-settings</div> <div class="tb-form-panel-title" translate>widget-config.data-settings</div>
<div *ngIf="displayUnitsConfig" class="tb-form-row space-between"> <div *ngIf="displayUnitsConfig" class="tb-form-row space-between column-xs">
<div translate>widget-config.units</div> <div translate>widget-config.units</div>
<tb-unit-input <tb-unit-input
formControlName="units"> formControlName="units">
</tb-unit-input> </tb-unit-input>
</div> </div>
<div *ngIf="displayUnitsConfig" class="tb-form-row space-between"> <div *ngIf="displayUnitsConfig" class="tb-form-row space-between column-xs">
<div translate>widget-config.decimals</div> <div translate>widget-config.decimals</div>
<mat-form-field appearance="outline" class="number" subscriptSizing="dynamic"> <mat-form-field appearance="outline" class="number" subscriptSizing="dynamic">
<input matInput formControlName="decimals" type="number" min="0" max="15" step="1" placeholder="{{ 'widget-config.set' | translate }}"> <input matInput formControlName="decimals" type="number" min="0" max="15" step="1" placeholder="{{ 'widget-config.set' | translate }}">
</mat-form-field> </mat-form-field>
</div> </div>
<div *ngIf="displayNoDataDisplayMessageConfig" class="tb-form-row"> <div *ngIf="displayNoDataDisplayMessageConfig" class="tb-form-row column-xs">
<div class="fixed-title-width" translate>widget-config.no-data-display-message</div> <div class="fixed-title-width" translate>widget-config.no-data-display-message</div>
<mat-form-field fxFlex appearance="outline" subscriptSizing="dynamic"> <mat-form-field fxFlex appearance="outline" subscriptSizing="dynamic">
<input matInput formControlName="noDataDisplayMessage" placeholder="{{ 'widget-config.set-message' | translate }}"> <input matInput formControlName="noDataDisplayMessage" placeholder="{{ 'widget-config.set-message' | translate }}">

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

@ -20,16 +20,36 @@
.tb-widget-config { .tb-widget-config {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 16px; gap: 8px;
.tb-widget-config-header { .tb-widget-config-header {
padding: 24px 24px 8px; padding: 24px 24px 0;
height: 56px;
display: flex; display: flex;
flex-direction: row; gap: 12px;
align-items: center; flex-direction: column-reverse;
justify-content: space-between; align-items: flex-start;
@media #{$mat-gt-sm} {
gap: 0;
flex-direction: row;
align-items: center;
justify-content: space-between;
}
.tb-widget-config-header-components {
width: 100%;
flex: 1;
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
}
} }
.tb-widget-config-content { .tb-widget-config-content {
& > .mat-content {
padding-top: 8px;
@media #{$mat-xs} {
padding-left: 8px;
padding-right: 8px;
}
}
flex: 1; flex: 1;
overflow: auto; overflow: auto;
& > div { & > div {
@ -39,6 +59,9 @@
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 16px; gap: 16px;
@media #{$mat-xs} {
gap: 8px;
}
} }
} }
.tb-basic-mode-directive-error { .tb-basic-mode-directive-error {

3
ui-ngx/src/app/shared/components/time/timewindow.component.scss

@ -17,6 +17,9 @@
min-width: 48px; min-width: 48px;
margin: 8px 0; margin: 8px 0;
max-width: 100%; max-width: 100%;
&.no-margin {
margin: 0;
}
.mdc-button { .mdc-button {
max-width: 100%; max-width: 100%;
} }

7
ui-ngx/src/app/shared/components/time/timewindow.component.ts

@ -18,7 +18,7 @@ import {
ChangeDetectorRef, ChangeDetectorRef,
Component, Component,
ElementRef, ElementRef,
forwardRef, forwardRef, HostBinding,
Injector, Injector,
Input, Input,
StaticProvider, StaticProvider,
@ -83,6 +83,11 @@ export class TimewindowComponent implements ControlValueAccessor {
return this.historyOnlyValue; return this.historyOnlyValue;
} }
@HostBinding('class.no-margin')
@Input()
@coerceBoolean()
noMargin = false;
@Input() @Input()
@coerceBoolean() @coerceBoolean()
forAllTimeEnabled = false; forAllTimeEnabled = false;

8
ui-ngx/src/app/shared/components/toggle-header.component.html

@ -16,13 +16,14 @@
--> -->
<button mat-icon-button <button mat-icon-button
type="button"
[disabled]="!leftPaginationEnabled" [disabled]="!leftPaginationEnabled"
(click)="handlePaginatorClick('before', $event)" (click)="handlePaginatorClick('before', $event)"
(touchstart)="handlePaginatorTouchStart('before', $event)" (touchstart)="handlePaginatorTouchStart('before', $event)"
class="tb-toggle-header-pagination-button" [class]="{'tb-mat-32': (ignoreMdLgSize || !isMdLg), 'tb-mat-24': !ignoreMdLgSize && isMdLg}"> class="tb-toggle-header-pagination-button" [class]="{'tb-mat-32': !isMdLg, 'tb-mat-24': isMdLg}">
<mat-icon>chevron_left</mat-icon> <mat-icon>chevron_left</mat-icon>
</button> </button>
<div #toggleGroupContainer class="tb-toggle-container" [class]="{'tb-disable-pagination': disablePagination}" *ngIf="!isMdLg || !useSelectOnMdLg; else select" > <div #toggleGroupContainer class="tb-toggle-container" [class]="{'tb-disable-pagination': disablePagination}" *ngIf="(useSelect$ | async) === false; else select" >
<mat-button-toggle-group #toggleGroup <mat-button-toggle-group #toggleGroup
class="tb-toggle-header" class="tb-toggle-header"
[ngClass]="{'tb-fill': (appearance === 'fill' || appearance === 'fill-invert'), [ngClass]="{'tb-fill': (appearance === 'fill' || appearance === 'fill-invert'),
@ -34,10 +35,11 @@
</mat-button-toggle-group> </mat-button-toggle-group>
</div> </div>
<button mat-icon-button <button mat-icon-button
type="button"
[disabled]="!rightPaginationEnabled" [disabled]="!rightPaginationEnabled"
(click)="handlePaginatorClick('after', $event)" (click)="handlePaginatorClick('after', $event)"
(touchstart)="handlePaginatorTouchStart('after', $event)" (touchstart)="handlePaginatorTouchStart('after', $event)"
class="tb-toggle-header-pagination-button" [class]="{'tb-mat-32': (ignoreMdLgSize || !isMdLg), 'tb-mat-24': !ignoreMdLgSize && isMdLg}"> class="tb-toggle-header-pagination-button" [class]="{'tb-mat-32': !isMdLg, 'tb-mat-24': isMdLg}">
<mat-icon>chevron_right</mat-icon> <mat-icon>chevron_right</mat-icon>
</button> </button>
<ng-template #select> <ng-template #select>

3
ui-ngx/src/app/shared/components/toggle-header.component.scss

@ -178,9 +178,6 @@
line-height: 16px; line-height: 16px;
letter-spacing: 0.25px; letter-spacing: 0.25px;
} }
.mat-mdc-select-value {
color: rgba(0, 0, 0, 0.38);
}
.mat-mdc-select-arrow-wrapper { .mat-mdc-select-arrow-wrapper {
height: 12px; height: 12px;
padding-left: 6px; padding-left: 6px;

74
ui-ngx/src/app/shared/components/toggle-header.component.ts

@ -35,7 +35,7 @@ import {
import { PageComponent } from '@shared/components/page.component'; import { PageComponent } from '@shared/components/page.component';
import { Store } from '@ngrx/store'; import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state'; import { AppState } from '@core/core.state';
import { Subject, Subscription } from 'rxjs'; import { BehaviorSubject, Subject, Subscription } from 'rxjs';
import { BreakpointObserver, BreakpointState } from '@angular/cdk/layout'; import { BreakpointObserver, BreakpointState } from '@angular/cdk/layout';
import { MediaBreakpoints } from '@shared/models/constants'; import { MediaBreakpoints } from '@shared/models/constants';
import { coerceBoolean } from '@shared/decorators/coercion'; import { coerceBoolean } from '@shared/decorators/coercion';
@ -159,9 +159,20 @@ export class ToggleHeaderComponent extends _ToggleBase implements OnInit, AfterV
@coerceBoolean() @coerceBoolean()
disablePagination = false; disablePagination = false;
@Input()
selectMediaBreakpoint = 'md-lg';
@Input() @Input()
@coerceBoolean() @coerceBoolean()
useSelectOnMdLg = true; set useSelectOnMdLg(value: boolean) {
if (value) {
this.selectMediaBreakpoint = 'md-lg';
} else {
if (this.selectMediaBreakpoint === 'md-lg') {
this.selectMediaBreakpoint = '';
}
}
}
@Input() @Input()
@coerceBoolean() @coerceBoolean()
@ -174,7 +185,14 @@ export class ToggleHeaderComponent extends _ToggleBase implements OnInit, AfterV
@coerceBoolean() @coerceBoolean()
disabled = false; disabled = false;
isMdLg: boolean; get isMdLg(): boolean {
return !this.ignoreMdLgSize && this.isMdLgValue;
}
private isMdLgValue: boolean;
private useSelectSubject = new BehaviorSubject(false);
useSelect$ = this.useSelectSubject.asObservable();
private observeBreakpointSubscription: Subscription; private observeBreakpointSubscription: Subscription;
@ -186,11 +204,19 @@ export class ToggleHeaderComponent extends _ToggleBase implements OnInit, AfterV
} }
ngOnInit() { ngOnInit() {
this.isMdLg = this.breakpointObserver.isMatched(MediaBreakpoints['md-lg']); const mediaBreakpoints = [MediaBreakpoints['md-lg']];
if (this.selectMediaBreakpoint && this.selectMediaBreakpoint !== 'md-lg') {
mediaBreakpoints.push(MediaBreakpoints[this.selectMediaBreakpoint]);
}
this.observeBreakpointSubscription = this.breakpointObserver this.observeBreakpointSubscription = this.breakpointObserver
.observe(MediaBreakpoints['md-lg']) .observe(mediaBreakpoints)
.subscribe((state: BreakpointState) => { .subscribe((state: BreakpointState) => {
this.isMdLg = state.matches; this.isMdLgValue = state.breakpoints[MediaBreakpoints['md-lg']];
if (this.selectMediaBreakpoint) {
this.useSelectSubject.next(state.breakpoints[MediaBreakpoints[this.selectMediaBreakpoint]]);
} else {
this.useSelectSubject.next(false);
}
this.cd.markForCheck(); this.cd.markForCheck();
} }
); );
@ -202,18 +228,21 @@ export class ToggleHeaderComponent extends _ToggleBase implements OnInit, AfterV
} }
ngOnDestroy() { ngOnDestroy() {
if (this.toggleGroupResize$) { this.stopObservePagination();
this.toggleGroupResize$.disconnect();
}
super.ngOnDestroy(); super.ngOnDestroy();
} }
ngAfterViewInit() { ngAfterViewInit() {
if (!this.disablePagination && !this.useSelectOnMdLg) { if (!this.disablePagination) {
this.toggleGroupResize$ = new ResizeObserver(() => { this.useSelect$.pipe(takeUntil(this._destroyed)).subscribe((useSelect) => {
this.updatePagination(); if (useSelect) {
this.removePagination();
} else {
setTimeout(() => {
this.startObservePagination();
}, 0);
}
}); });
this.toggleGroupResize$.observe(this.toggleGroupContainer.nativeElement);
} }
} }
@ -243,6 +272,25 @@ export class ToggleHeaderComponent extends _ToggleBase implements OnInit, AfterV
} }
} }
private startObservePagination() {
this.toggleGroupResize$ = new ResizeObserver(() => {
this.updatePagination();
});
this.toggleGroupResize$.observe(this.toggleGroupContainer.nativeElement);
}
private removePagination() {
this.stopObservePagination();
this.showPaginationControls = false;
}
private stopObservePagination() {
if (this.toggleGroupResize$) {
this.toggleGroupResize$.disconnect();
this.toggleGroupResize$ = null;
}
}
private scrollHeader(direction: ScrollDirection) { private scrollHeader(direction: ScrollDirection) {
const viewLength = this.toggleGroup.nativeElement.offsetWidth; const viewLength = this.toggleGroup.nativeElement.offsetWidth;
// Move the scroll distance one-third the length of the tab list's viewport. // Move the scroll distance one-third the length of the tab list's viewport.

1
ui-ngx/src/app/shared/components/toggle-select.component.html

@ -21,6 +21,7 @@
[disabled]="disabled" [disabled]="disabled"
[appearance]="appearance" [appearance]="appearance"
[disablePagination]="disablePagination" [disablePagination]="disablePagination"
[selectMediaBreakpoint]="selectMediaBreakpoint"
[options]="options" [options]="options"
[value]="modelValue" [value]="modelValue"
(valueChange)="updateModel($event)"> (valueChange)="updateModel($event)">

3
ui-ngx/src/app/shared/components/toggle-select.component.ts

@ -42,6 +42,9 @@ export class ToggleSelectComponent extends _ToggleBase implements ControlValueAc
@coerceBoolean() @coerceBoolean()
disabled: boolean; disabled: boolean;
@Input()
selectMediaBreakpoint;
@Input() @Input()
appearance: ToggleHeaderAppearance = 'stroked'; appearance: ToggleHeaderAppearance = 'stroked';

9
ui-ngx/src/app/shared/models/ace/tbel/worker-tbel.js

@ -5229,10 +5229,6 @@ var JSHINT = (function() {
var a = [], p; var a = [], p;
while (!state.tokens.next.reach && state.tokens.next.id !== "(end)") { while (!state.tokens.next.reach && state.tokens.next.id !== "(end)") {
if (state.tokens.next.value === "switch") {
warning("E067", state.tokens.next, "switch");
break;
}
if (state.tokens.next.id === ";") { if (state.tokens.next.id === ";") {
p = peek(); p = peek();
@ -9219,7 +9215,7 @@ var JSHINT = (function() {
statements(0); statements(0);
} }
if (state.tokens.next.id !== "(end)"&& state.tokens.next.value !== "switch") { if (state.tokens.next.id !== "(end)") {
quit("E041", state.tokens.curr); quit("E041", state.tokens.curr);
} }
@ -11270,8 +11266,7 @@ var errors = {
E064: "Super call may only be used within class method bodies.", E064: "Super call may only be used within class method bodies.",
E065: "Functions defined outside of strict mode with non-simple parameter lists may not " + E065: "Functions defined outside of strict mode with non-simple parameter lists may not " +
"enable strict mode.", "enable strict mode.",
E066: "Asynchronous iteration is only available with for-of loops.", E066: "Asynchronous iteration is only available with for-of loops."
E067: "Expected an 'if/else' and instead saw 'switch'. TBEL does not support the 'switch' statement."
}; };
var warnings = { var warnings = {

66
ui-ngx/src/form.scss

@ -16,6 +16,15 @@
@import './scss/constants'; @import './scss/constants';
@mixin form-row-column($breakpoint) {
@media #{$breakpoint} {
flex-direction: column;
align-items: stretch;
gap: 12px;
padding: 12px 12px 12px 16px;
}
}
.tb-default, .tb-dark { .tb-default, .tb-dark {
.tb-form-panel { .tb-form-panel {
box-shadow: 0 0 10px 6px rgba(11, 17, 51, 0.04); box-shadow: 0 0 10px 6px rgba(11, 17, 51, 0.04);
@ -27,6 +36,10 @@
color: rgba(0, 0, 0, 0.87); color: rgba(0, 0, 0, 0.87);
letter-spacing: 0.15px; letter-spacing: 0.15px;
position: relative; position: relative;
@media #{$mat-xs} {
padding: 12px;
gap: 8px;
}
&.no-padding-bottom { &.no-padding-bottom {
padding-bottom: 0; padding-bottom: 0;
} }
@ -52,7 +65,6 @@
> .mat-expansion-panel { > .mat-expansion-panel {
padding: 16px; padding: 16px;
.mat-expansion-panel-header { .mat-expansion-panel-header {
height: 32px;
.mat-slide { .mat-slide {
margin: 0; margin: 0;
} }
@ -66,6 +78,7 @@
overflow: visible; overflow: visible;
} }
> .mat-expansion-panel-header { > .mat-expansion-panel-header {
height: fit-content;
user-select: none; user-select: none;
font-weight: 500; font-weight: 500;
font-size: 16px; font-size: 16px;
@ -98,6 +111,10 @@
flex-direction: column; flex-direction: column;
gap: 16px; gap: 16px;
padding: 16px 0 0 !important; padding: 16px 0 0 !important;
@media #{$mat-xs} {
padding: 12px 0 0 !important;
gap: 8px;
}
} }
} }
.tb-json-object-panel, .tb-css-content-panel { .tb-json-object-panel, .tb-css-content-panel {
@ -139,6 +156,14 @@
padding: 7px 7px 7px 16px; padding: 7px 7px 7px 16px;
border: 1px solid rgba(0, 0, 0, 0.12); border: 1px solid rgba(0, 0, 0, 0.12);
border-radius: 6px; border-radius: 6px;
&.column {
&-xs {
@include form-row-column($mat-xs)
}
&-lt-md {
@include form-row-column($mat-lt-md)
}
}
&.no-border { &.no-border {
border: none; border: none;
border-radius: 0; border-radius: 0;
@ -344,10 +369,14 @@
.tb-form-table-header, .tb-form-table-row { .tb-form-table-header, .tb-form-table-row {
display: flex; display: flex;
flex-direction: row; flex-direction: row;
gap: 12px; gap: 8px;
padding-left: 12px; padding-left: 8px;
place-content: center flex-start; place-content: center flex-start;
align-items: center; align-items: center;
@media #{$mat-gt-md} {
gap: 12px;
padding-left: 12px;
}
&-cell { &-cell {
font-weight: 400; font-weight: 400;
font-size: 14px; font-size: 14px;
@ -365,8 +394,6 @@
} }
.tb-form-table-row { .tb-form-table-row {
height: 38px;
&.tb-draggable { &.tb-draggable {
gap: 0; gap: 0;
padding-left: 0; padding-left: 0;
@ -381,12 +408,7 @@
display: flex; display: flex;
flex-direction: row; flex-direction: row;
button.mat-mdc-icon-button.mat-mdc-button-base { button.mat-mdc-icon-button.mat-mdc-button-base {
padding: 7px; color: rgba(0, 0, 0, 0.38);
width: 38px;
height: 38px;
.mat-icon {
color: rgba(0, 0, 0, 0.38);
}
&.tb-hidden { &.tb-hidden {
visibility: hidden; visibility: hidden;
} }
@ -435,21 +457,18 @@
} }
} }
button.mat-mdc-button-base.tb-box-button { button.mat-mdc-button-base.tb-box-button, .tb-form-table-row-cell-buttons button.mat-mdc-icon-button.mat-mdc-button-base {
width: 40px; width: 40px;
min-width: 40px; min-width: 40px;
height: 40px; height: 40px;
padding: 7px; padding: 8px;
&.mat-mdc-outlined-button {
padding: 7px;
}
.mat-mdc-button-touch-target { .mat-mdc-button-touch-target {
width: 40px; width: 40px;
height: 40px; height: 40px;
} }
&:not(:disabled) {
color: rgba(0, 0, 0, 0.54);
}
&:disabled {
color: rgba(0, 0, 0, 0.12);
}
> .mat-icon { > .mat-icon {
width: 24px; width: 24px;
height: 24px; height: 24px;
@ -457,4 +476,13 @@
margin: 0; margin: 0;
} }
} }
button.mat-mdc-button-base.tb-box-button {
&:not(:disabled) {
color: rgba(0, 0, 0, 0.54);
}
&:disabled {
color: rgba(0, 0, 0, 0.12);
}
}
} }

29
ui-ngx/src/styles.scss

@ -625,9 +625,36 @@ mat-label {
color: white; color: white;
} }
} }
.mat-mdc-select-value, .mat-mdc-select-arrow { .mat-mdc-select-value, .mat-mdc-select-arrow, .mat-mdc-select-arrow:after {
color: white; color: white;
} }
.mat-mdc-text-field-wrapper {
&.mdc-text-field--outlined {
&:not(.mdc-text-field--focused):not(.mdc-text-field--disabled):not(.mdc-text-field--invalid) {
&:not(:hover) {
.mdc-notched-outline {
.mdc-notched-outline__leading, .mdc-notched-outline__trailing {
border-color: white;
}
}
}
&:hover {
.mdc-notched-outline {
.mdc-notched-outline__leading, .mdc-notched-outline__trailing {
border-color: rgba(255, 255, 255, 0.87);
}
}
}
}
&:not(.mdc-text-field--disabled).mdc-text-field--focused {
.mdc-notched-outline {
.mdc-notched-outline__leading, .mdc-notched-outline__trailing {
border-color: rgba(255, 255, 255, 0.67);
}
}
}
}
}
} }
.mat-toolbar.mat-mdc-table-toolbar { .mat-toolbar.mat-mdc-table-toolbar {

Loading…
Cancel
Save