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<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;
private SandboxedParserConfiguration parserConfig;
@ -183,11 +181,6 @@ public class DefaultTbelInvokeService extends AbstractScriptInvokeService implem
lock.unlock();
}
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) {
throw new TbScriptException(scriptId, TbScriptException.ErrorCode.COMPILATION, scriptBody, e);
}

2
pom.xml

@ -78,7 +78,7 @@
<zookeeper.version>3.8.1</zookeeper.version>
<protobuf.version>3.21.9</protobuf.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>
<paho.client.version>1.2.4</paho.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">
<mat-toolbar color="primary">
<h2 translate>widget.add</h2>
<span fxFlex>: {{data.widgetInfo.widgetName}}</span>
<div fxLayout="row" fxLayoutAlign="start center" fxLayoutGap="16px">
<tb-toggle-select *ngIf="hasBasicMode" appearance="fill-invert" disablePagination [(ngModel)]="widgetConfigMode" [ngModelOptions]="{standalone: true}">
<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-select>
<div [tb-help]="helpLinkIdForWidgetType()"></div>
<div class="tb-add-widget-toolbar">
<h2 fxFlex>{{'widget.add' | translate}}: {{data.widgetInfo.widgetName}}</h2>
<div fxLayout="row" fxLayoutAlign="start center" fxLayoutGap.gt-xs="16px">
<tb-toggle-select *ngIf="hasBasicMode" appearance="fill-invert" selectMediaBreakpoint="xs"
[(ngModel)]="widgetConfigMode" [ngModelOptions]="{standalone: true}">
<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-select>
<div [tb-help]="helpLinkIdForWidgetType()"></div>
</div>
</div>
<button mat-icon-button
(click)="cancel()"

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

@ -26,4 +26,13 @@
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()">
<div class="tb-dashboard-action-panels" fxLayout="column" fxLayout.gt-sm="row"
fxLayoutAlign="center stretch" fxLayoutAlign.gt-sm="space-between center">
<div class="tb-dashboard-action-panel" fxFlex="auto" fxLayout="row-reverse" [fxHide]="isMobileApp && !isEdit"
fxLayoutAlign.gt-sm="end center" fxLayoutAlign="space-between center" fxLayoutGap.lt-lg="6px" fxLayoutGap.gt-md="12px">
<div class="tb-dashboard-action-panel tb-left-panel" [fxHide]="isMobileApp && !isEdit">
<tb-user-menu *ngIf="!isPublicUser() && forceFullscreen" fxHide.gt-sm displayUserInfo="true">
</tb-user-menu>
<ng-container *ngIf="isEdit">
@ -74,8 +73,7 @@
<img *ngIf="showDashboardLogo()" [src]="dashboardLogo"
aria-label="dashboard_logo" class="dashboard_logo"/>
</div>
<div class="tb-dashboard-action-panel" fxFlex="1 0 auto" fxLayout="row-reverse"
fxLayoutAlign.gt-sm="start center" fxLayoutAlign="space-between center" fxLayoutGap.lt-lg="6px" fxLayoutGap.gt-md="12px">
<div class="tb-dashboard-action-panel">
<button [fxShow]="showCloseToolbar()" mat-icon-button class="close-action"
matTooltip="{{ 'dashboard.close-toolbar' | translate }}"
matTooltipPosition="below"
@ -235,8 +233,21 @@
</tb-timewindow>
</ng-container>
</ng-template>
<button [fxShow]="isEdit" mat-stroked-button (click)="addWidget($event)">
<mat-icon>add</mat-icon>{{ 'dashboard.add-widget-button-text' | translate }}</button>
<ng-container *ngIf="isEdit">
<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()"
tooltipPosition="below"
[aliasController]="dashboardCtx.aliasController">
@ -360,7 +371,7 @@
[isReadOnly]="true"
(closeDetails)="onEditWidgetClosed()">
<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="advanced">{{ 'widget.advanced-mode' | translate }}</tb-toggle-option>
</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 {
return (this.hideToolbarValue || this.hideToolbarSetting()) && !this.isEdit;
return ((this.hideToolbarValue || this.hideToolbarSetting()) && !this.isEdit) || (this.isEditingWidget || this.isAddingWidget);
}
@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} {
height: $mobile-toolbar-height;
max-height: $mobile-toolbar-height;
padding: 0 8px !important;
}
.close-action {
@ -150,8 +151,44 @@ tb-dashboard-toolbar {
.tb-dashboard-action-panel {
min-width: 0;
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} {
place-content: center flex-start;
&.tb-left-panel {
place-content: center flex-end;
}
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>
{{ 'action.back' | translate }}
</button>
</div>
<div class="tb-widget-config-header-suffix" fxLayout="row" fxLayoutAlign="start center" fxLayoutGap="12px">
<button *ngIf="!previewMode" [disabled]="(isLoading$ | async) || widgetFormGroup.invalid"
mat-button color="primary"
(click)="previewMode = true">
<button *ngIf="!previewMode"
fxHide.gt-sm
[disabled]="widgetFormGroup.invalid"
mat-button color="primary"
(click)="previewMode = true">
<mat-icon>visibility</mat-icon>
{{ 'widget-config.preview' | translate }}
</button>
<button [disabled]="(isLoading$ | async) || !widgetFormGroup.dirty"
mat-stroked-button color="primary"
(click)="onRevertWidgetConfig()">
<mat-icon>close</mat-icon>
{{ 'action.decline' | translate }}
</button>
<button [disabled]="(isLoading$ | async) || widgetFormGroup.invalid || !widgetFormGroup.dirty"
mat-flat-button color="primary"
(click)="onApplyWidgetConfig()">
<mat-icon>done</mat-icon>
{{ 'action.apply' | translate }}
</div>
<div fxFlex.lt-md class="tb-widget-config-header-suffix" fxLayout="row" fxLayoutAlign="end center" fxLayoutGap="12px">
<button *ngIf="!previewMode"
fxHide.lt-md
[disabled]="widgetFormGroup.invalid"
mat-button color="primary"
(click)="previewMode = true">
<mat-icon>visibility</mat-icon>
{{ 'widget-config.preview' | translate }}
</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>
</tb-widget-config>
<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 {
.widget-preview-background {
position: absolute;
top: 72px;
top: 68px;
left: 0;
right: 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="tb-details-title" fxLayout="row" fxLayoutAlign="start center">
<ng-content select=".prefix-title-buttons"></ng-content>
<span>{{ headerTitle }}</span>
<span class="tb-details-title-text">{{ headerTitle }}</span>
</div>
<span class="tb-details-subtitle">{{ headerSubtitle }}</span>
<span style="width: 100%;">

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

@ -32,16 +32,14 @@
max-height: 120px;
&.tb-details-title-header {
min-width: 0;
padding: 0 16px 0 8px;
}
}
.tb-details-title {
width: inherit;
margin: 20px 8px 0 0;
overflow: hidden;
font-size: 1rem;
font-weight: 400;
text-overflow: ellipsis;
white-space: nowrap;
@media #{$mat-gt-sm} {
font-size: 1.5rem;
@ -49,13 +47,16 @@
}
.tb-details-subtitle {
width: inherit;
margin: 10px 0;
overflow: hidden;
font-size: 1rem;
opacity: .8;
}
.tb-details-title-text, .tb-details-subtitle {
width: inherit;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
opacity: .8;
}
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>
</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>
<mat-chip-listbox multiple formControlName="cardButtons">
<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
* limitations under the License.
*/
@import '../../../../../../../scss/constants';
:host {
display: flex;
flex-direction: column;
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>
</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>
<mat-chip-listbox multiple formControlName="cardButtons">
<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 }}">
</mat-form-field>
</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>
<mat-chip-listbox multiple formControlName="cardButtons">
<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>
</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>
<mat-chip-listbox multiple formControlName="cardButtons">
<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>
</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>
<mat-chip-listbox multiple formControlName="cardButtons">
<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>
</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>
<mat-chip-listbox multiple formControlName="cardButtons">
<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>
</div>
<div class="tb-form-table-row-cell-buttons">
<button type="button"
<button fxHide.lt-lg
type="button"
mat-icon-button
(click)="editKey(true)"
[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
* limitations under the License.
*/
@import '../../../../../../../../scss/constants';
.tb-data-key-row {
.mat-mdc-form-field.tb-inline-field.tb-key-field {
.mat-mdc-text-field-wrapper:not(.mdc-text-field--outlined) {
padding-left: 8px;
padding-right: 0;
.mat-mdc-form-field-infix {
padding-top: 0;
padding-bottom: 6px;
@ -38,16 +43,21 @@
}
.tb-source-field {
width: 120px;
min-width: 120px;
width: 108px;
min-width: 108px;
}
.tb-key-field {
flex: 1 1 60%;
flex: 1;
min-width: 150px;
@media #{$mat-gt-sm} {
flex: 1 1 60%;
}
}
.tb-label-field {
flex: 1 1 40%;
min-width: 100px;
}
.tb-color-field, .tb-units-field, .tb-decimals-field {
@ -62,8 +72,20 @@
min-width: 80px;
}
.tb-color-field, .tb-decimals-field {
.tb-color-field {
width: 40px;
min-width: 40px;
}
.tb-decimals-field {
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)">
</tb-data-key-row>
<div class="tb-form-table-row-cell-buttons">
<button mat-icon-button
<button fxHide.lt-lg
mat-icon-button
type="button"
cdkDragHandle
[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
* limitations under the License.
*/
@import '../../../../../../../../scss/constants';
.tb-form-table-header-cell {
&.tb-source-header {
width: 120px;
min-width: 120px;
width: 108px;
min-width: 108px;
}
&.tb-key-header {
flex: 1 1 60%;
flex: 1;
min-width: 150px;
@media #{$mat-gt-sm} {
flex: 1 1 60%;
}
}
&.tb-label-header {
flex: 1 1 40%;
min-width: 100px;
}
&.tb-units-header {
width: 80px;
min-width: 80px;
}
&.tb-color-header, &.tb-decimals-header {
&.tb-color-header {
width: 40px;
min-width: 40px;
}
&.tb-decimals-header {
width: 60px;
min-width: 60px;
}
&.tb-actions-header {
width: 114px;
min-width: 114px;
width: 40px;
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 fxLayout="row" fxLayoutAlign="space-between center">
<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]="false">{{ 'widget-config.use-widget-timewindow' | translate }}</tb-toggle-option>
</tb-toggle-select>
</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"
strokedButton
noMargin
isEdit="true"
alwaysDisplayTypePrefix
[historyOnly]="onlyHistoryTimewindow"
quickIntervalOnly="{{ widgetType === widgetTypes.latest }}"
aggregation="{{ widgetType === widgetTypes.timeseries }}"
formControlName="timewindow"></tb-timewindow>
<mat-slide-toggle class="mat-slide" formControlName="displayTimewindow">
{{ 'widget-config.display-timewindow' | translate }}
</mat-slide-toggle>
</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-form-field>
</div>
<div class="tb-form-row space-between">
<div class="tb-form-row space-between column-lt-md">
<div translate>legend.show-values</div>
<mat-chip-listbox multiple formControlName="showValues">
<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;
flex-direction: column;
gap: 16px;
@media #{$mat-xs} {
gap: 8px;
}
.tb-widget-settings {
.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"
appearance="fill" [options]="headerOptions" [(ngModel)]="selectedOption">
</tb-toggle-select>
<ng-content select=".tb-widget-config-header-prefix"></ng-content>
<ng-content select=".tb-widget-config-header-suffix"></ng-content>
<div class="tb-widget-config-header-components">
<ng-content select=".tb-widget-config-header-prefix"></ng-content>
<ng-content select=".tb-widget-config-header-suffix"></ng-content>
</div>
</div>
<div *ngIf="widgetConfigMode === widgetConfigModes.advanced; else basicMode" class="tb-widget-config-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 }}">
</mat-form-field>
</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">
{{ 'widget-config.display-icon' | translate }}
</mat-slide-toggle>
<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
[color]="widgetSettings.get('iconColor').value"
formControlName="titleIcon">
</tb-material-icon-select>
<mat-form-field appearance="outline" subscriptSizing="dynamic">
<input matInput formControlName="iconSize">
</mat-form-field>
<tb-color-input asBoxInput
formControlName="iconColor">
</tb-color-input>
@ -247,7 +249,7 @@
</div>
<div *ngIf="displayLimits" class="tb-form-panel" [formGroup]="widgetSettings">
<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>
<mat-form-field appearance="outline" class="number" subscriptSizing="dynamic">
<input matInput formControlName="pageSize" type="number" min="1" step="1">
@ -258,19 +260,19 @@
<ng-template #appearance>
<div *ngIf="displayAppearanceDataSettings" class="tb-form-panel" [formGroup]="widgetSettings">
<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>
<tb-unit-input
formControlName="units">
</tb-unit-input>
</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>
<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 }}">
</mat-form-field>
</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>
<mat-form-field fxFlex appearance="outline" subscriptSizing="dynamic">
<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 {
display: flex;
flex-direction: column;
gap: 16px;
gap: 8px;
.tb-widget-config-header {
padding: 24px 24px 8px;
height: 56px;
padding: 24px 24px 0;
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
gap: 12px;
flex-direction: column-reverse;
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 {
& > .mat-content {
padding-top: 8px;
@media #{$mat-xs} {
padding-left: 8px;
padding-right: 8px;
}
}
flex: 1;
overflow: auto;
& > div {
@ -39,6 +59,9 @@
display: flex;
flex-direction: column;
gap: 16px;
@media #{$mat-xs} {
gap: 8px;
}
}
}
.tb-basic-mode-directive-error {

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

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

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

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

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

@ -16,13 +16,14 @@
-->
<button mat-icon-button
type="button"
[disabled]="!leftPaginationEnabled"
(click)="handlePaginatorClick('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>
</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
class="tb-toggle-header"
[ngClass]="{'tb-fill': (appearance === 'fill' || appearance === 'fill-invert'),
@ -34,10 +35,11 @@
</mat-button-toggle-group>
</div>
<button mat-icon-button
type="button"
[disabled]="!rightPaginationEnabled"
(click)="handlePaginatorClick('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>
</button>
<ng-template #select>

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

@ -178,9 +178,6 @@
line-height: 16px;
letter-spacing: 0.25px;
}
.mat-mdc-select-value {
color: rgba(0, 0, 0, 0.38);
}
.mat-mdc-select-arrow-wrapper {
height: 12px;
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 { Store } from '@ngrx/store';
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 { MediaBreakpoints } from '@shared/models/constants';
import { coerceBoolean } from '@shared/decorators/coercion';
@ -159,9 +159,20 @@ export class ToggleHeaderComponent extends _ToggleBase implements OnInit, AfterV
@coerceBoolean()
disablePagination = false;
@Input()
selectMediaBreakpoint = 'md-lg';
@Input()
@coerceBoolean()
useSelectOnMdLg = true;
set useSelectOnMdLg(value: boolean) {
if (value) {
this.selectMediaBreakpoint = 'md-lg';
} else {
if (this.selectMediaBreakpoint === 'md-lg') {
this.selectMediaBreakpoint = '';
}
}
}
@Input()
@coerceBoolean()
@ -174,7 +185,14 @@ export class ToggleHeaderComponent extends _ToggleBase implements OnInit, AfterV
@coerceBoolean()
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;
@ -186,11 +204,19 @@ export class ToggleHeaderComponent extends _ToggleBase implements OnInit, AfterV
}
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
.observe(MediaBreakpoints['md-lg'])
.observe(mediaBreakpoints)
.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();
}
);
@ -202,18 +228,21 @@ export class ToggleHeaderComponent extends _ToggleBase implements OnInit, AfterV
}
ngOnDestroy() {
if (this.toggleGroupResize$) {
this.toggleGroupResize$.disconnect();
}
this.stopObservePagination();
super.ngOnDestroy();
}
ngAfterViewInit() {
if (!this.disablePagination && !this.useSelectOnMdLg) {
this.toggleGroupResize$ = new ResizeObserver(() => {
this.updatePagination();
if (!this.disablePagination) {
this.useSelect$.pipe(takeUntil(this._destroyed)).subscribe((useSelect) => {
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) {
const viewLength = this.toggleGroup.nativeElement.offsetWidth;
// 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"
[appearance]="appearance"
[disablePagination]="disablePagination"
[selectMediaBreakpoint]="selectMediaBreakpoint"
[options]="options"
[value]="modelValue"
(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()
disabled: boolean;
@Input()
selectMediaBreakpoint;
@Input()
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;
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 === ";") {
p = peek();
@ -9219,7 +9215,7 @@ var JSHINT = (function() {
statements(0);
}
if (state.tokens.next.id !== "(end)"&& state.tokens.next.value !== "switch") {
if (state.tokens.next.id !== "(end)") {
quit("E041", state.tokens.curr);
}
@ -11270,8 +11266,7 @@ var errors = {
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 " +
"enable strict mode.",
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."
E066: "Asynchronous iteration is only available with for-of loops."
};
var warnings = {

66
ui-ngx/src/form.scss

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

Loading…
Cancel
Save