Merge with develop/3.5.2
This commit is contained in:
commit
36f1cd00e7
23
application/src/main/data/upgrade/3.5.0/schema_update.sql
Normal file
23
application/src/main/data/upgrade/3.5.0/schema_update.sql
Normal file
@ -0,0 +1,23 @@
|
||||
--
|
||||
-- Copyright © 2016-2023 The Thingsboard Authors
|
||||
--
|
||||
-- Licensed under the Apache License, Version 2.0 (the "License");
|
||||
-- you may not use this file except in compliance with the License.
|
||||
-- You may obtain a copy of the License at
|
||||
--
|
||||
-- http://www.apache.org/licenses/LICENSE-2.0
|
||||
--
|
||||
-- Unless required by applicable law or agreed to in writing, software
|
||||
-- distributed under the License is distributed on an "AS IS" BASIS,
|
||||
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
-- See the License for the specific language governing permissions and
|
||||
-- limitations under the License.
|
||||
--
|
||||
|
||||
-- FIX DASHBOARD TEMPLATES AFTER ANGULAR MIGRATION TO VER.15
|
||||
|
||||
UPDATE dashboard SET configuration = REPLACE(configuration, 'mat-button mat-icon-button', 'mat-icon-button')
|
||||
WHERE configuration like '%mat-button mat-icon-button%';
|
||||
|
||||
UPDATE widget_type SET descriptor = REPLACE(descriptor, 'mat-button mat-icon-button', 'mat-icon-button')
|
||||
WHERE descriptor like '%mat-button mat-icon-button%';
|
||||
@ -256,6 +256,7 @@ public class ThingsboardInstallService {
|
||||
}
|
||||
case "3.5.0":
|
||||
log.info("Upgrading ThingsBoard from version 3.5.0 to 3.5.1 ...");
|
||||
databaseEntitiesUpgradeService.upgradeDatabase("3.5.0");
|
||||
case "3.5.1":
|
||||
log.info("Upgrading ThingsBoard from version 3.5.1 to 3.5.2 ...");
|
||||
databaseEntitiesUpgradeService.upgradeDatabase("3.5.1");
|
||||
|
||||
@ -714,10 +714,23 @@ public class SqlDatabaseUpgradeService implements DatabaseEntitiesUpgradeService
|
||||
log.error("Failed updating schema!!!", e);
|
||||
}
|
||||
break;
|
||||
case "3.5.1":
|
||||
case "3.5.0":
|
||||
try (Connection conn = DriverManager.getConnection(dbUrl, dbUserName, dbPassword)) {
|
||||
log.info("Updating schema ...");
|
||||
if (isOldSchema(conn, 3005000)) {
|
||||
schemaUpdateFile = Paths.get(installScripts.getDataDir(), "upgrade", "3.5.0", SCHEMA_UPDATE_SQL);
|
||||
loadSql(schemaUpdateFile, conn);
|
||||
conn.createStatement().execute("UPDATE tb_schema_settings SET schema_version = 3005001;");
|
||||
}
|
||||
log.info("Schema updated.");
|
||||
} catch (Exception e) {
|
||||
log.error("Failed updating schema!!!", e);
|
||||
}
|
||||
break;
|
||||
case "3.5.1":
|
||||
try (Connection conn = DriverManager.getConnection(dbUrl, dbUserName, dbPassword)) {
|
||||
log.info("Updating schema ...");
|
||||
if (isOldSchema(conn, 3005001)) {
|
||||
schemaUpdateFile = Paths.get(installScripts.getDataDir(), "upgrade", "3.5.1", SCHEMA_UPDATE_SQL);
|
||||
loadSql(schemaUpdateFile, conn);
|
||||
|
||||
|
||||
@ -32,6 +32,7 @@ import {
|
||||
import { isDefined, isDefinedAndNotNull, isString, isUndefined } from '@core/utils';
|
||||
import {
|
||||
Datasource,
|
||||
datasourcesHasOnlyComparisonAggregation,
|
||||
DatasourceType,
|
||||
defaultLegendConfig,
|
||||
Widget,
|
||||
@ -249,7 +250,8 @@ export class DashboardUtilsService {
|
||||
}
|
||||
});
|
||||
if (type === widgetType.latest) {
|
||||
widgetConfig.timewindow = initModelFromDefaultTimewindow(widgetConfig.timewindow, true, this.timeService);
|
||||
const onlyHistoryTimewindow = datasourcesHasOnlyComparisonAggregation(widgetConfig.datasources);
|
||||
widgetConfig.timewindow = initModelFromDefaultTimewindow(widgetConfig.timewindow, true, onlyHistoryTimewindow, this.timeService);
|
||||
}
|
||||
if (type === widgetType.alarm) {
|
||||
if (!widgetConfig.alarmFilterConfig) {
|
||||
|
||||
@ -29,6 +29,7 @@ import {
|
||||
} from '@shared/components/dialog/material-icons-dialog.component';
|
||||
import { ConfirmDialogComponent } from '@shared/components/dialog/confirm-dialog.component';
|
||||
import { AlertDialogComponent } from '@shared/components/dialog/alert-dialog.component';
|
||||
import { ErrorAlertDialogComponent } from '@shared/components/dialog/error-alert-dialog.component';
|
||||
import { TodoDialogComponent } from '@shared/components/dialog/todo-dialog.component';
|
||||
|
||||
@Injectable(
|
||||
@ -78,6 +79,23 @@ export class DialogService {
|
||||
return dialogRef.afterClosed();
|
||||
}
|
||||
|
||||
errorAlert(title: string, message: string, error: any, ok: string = null, fullscreen: boolean = false): Observable<any> {
|
||||
const dialogConfig: MatDialogConfig = {
|
||||
disableClose: true,
|
||||
data: {
|
||||
title,
|
||||
message,
|
||||
error,
|
||||
ok: ok || this.translate.instant('action.ok')
|
||||
}
|
||||
};
|
||||
if (fullscreen) {
|
||||
dialogConfig.panelClass = ['tb-fullscreen-dialog'];
|
||||
}
|
||||
const dialogRef = this.dialog.open(ErrorAlertDialogComponent, dialogConfig);
|
||||
return dialogRef.afterClosed();
|
||||
}
|
||||
|
||||
colorPicker(color: string): Observable<string> {
|
||||
return this.dialog.open<ColorPickerDialogComponent, ColorPickerDialogData, string>(ColorPickerDialogComponent,
|
||||
{
|
||||
|
||||
@ -188,6 +188,10 @@ export class UtilsService {
|
||||
|
||||
public processWidgetException(exception: any): ExceptionData {
|
||||
const data = this.parseException(exception, -6);
|
||||
if (data.message?.startsWith('NG0')) {
|
||||
data.message = `${this.translate.instant('widget.widget-template-error')}<br/>
|
||||
<br/><i>${this.translate.instant('dialog.error-message-title')}</i><br/><br/>${data.message}`;
|
||||
}
|
||||
if (this.widgetEditMode) {
|
||||
const message: WindowMessage = {
|
||||
type: 'widgetException',
|
||||
|
||||
@ -14,7 +14,16 @@
|
||||
/// limitations under the License.
|
||||
///
|
||||
|
||||
import { AfterViewInit, ChangeDetectorRef, Component, Input, OnInit, ViewChild, ViewContainerRef } from '@angular/core';
|
||||
import {
|
||||
AfterViewInit,
|
||||
ChangeDetectorRef,
|
||||
Component,
|
||||
Input,
|
||||
OnDestroy,
|
||||
OnInit,
|
||||
ViewChild,
|
||||
ViewContainerRef
|
||||
} from '@angular/core';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { DatePipe } from '@angular/common';
|
||||
import { MatDialog } from '@angular/material/dialog';
|
||||
@ -32,7 +41,7 @@ import { Subscription } from 'rxjs';
|
||||
templateUrl: './event-table.component.html',
|
||||
styleUrls: ['./event-table.component.scss']
|
||||
})
|
||||
export class EventTableComponent implements OnInit, AfterViewInit {
|
||||
export class EventTableComponent implements OnInit, AfterViewInit, OnDestroy {
|
||||
|
||||
@Input()
|
||||
tenantId: string;
|
||||
|
||||
@ -33,6 +33,8 @@ import {
|
||||
CustomDialogComponent,
|
||||
CustomDialogData
|
||||
} from '@home/components/widget/dialog/custom-dialog.component';
|
||||
import { DialogService } from '@core/services/dialog.service';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
|
||||
export interface CustomDialogContainerData {
|
||||
controller: (instance: CustomDialogComponent) => void;
|
||||
@ -54,6 +56,8 @@ export class CustomDialogContainerComponent extends DialogComponent<CustomDialog
|
||||
protected router: Router,
|
||||
public viewContainerRef: ViewContainerRef,
|
||||
public dialogRef: MatDialogRef<CustomDialogContainerComponent>,
|
||||
private dialogService: DialogService,
|
||||
private translate: TranslateService,
|
||||
@Inject(MAT_DIALOG_DATA) public data: CustomDialogContainerData) {
|
||||
super(store, router, dialogRef);
|
||||
let customDialogData: CustomDialogData = {
|
||||
@ -72,7 +76,19 @@ export class CustomDialogContainerComponent extends DialogComponent<CustomDialog
|
||||
useValue: dialogRef
|
||||
}]
|
||||
});
|
||||
try {
|
||||
this.customComponentRef = this.viewContainerRef.createComponent(this.data.customComponentFactory, 0, injector);
|
||||
} catch (e: any) {
|
||||
let message;
|
||||
if (e.message?.startsWith('NG0')) {
|
||||
message = this.translate.instant('widget-action.custom-pretty-template-error');
|
||||
} else {
|
||||
message = this.translate.instant('widget-action.custom-pretty-controller-error');
|
||||
}
|
||||
dialogRef.close();
|
||||
console.error(e);
|
||||
this.dialogService.errorAlert(this.translate.instant('widget-action.custom-pretty-error-title'), message, e);
|
||||
}
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
|
||||
@ -22,7 +22,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="tb-absolute-fill tb-widget-error" *ngIf="widgetErrorData">
|
||||
<span>Widget Error: {{ widgetErrorData.name + ": " + widgetErrorData.message}}</span>
|
||||
<span [innerHtml]="('Widget Error:<br/><br/>' + widgetErrorData.message) | safe:'html'"></span>
|
||||
</div>
|
||||
<div class="tb-absolute-fill tb-widget-no-data" *ngIf="displayNoData">
|
||||
<span fxLayoutAlign="center center"
|
||||
|
||||
@ -489,9 +489,6 @@ export class WidgetEditorComponent extends PageComponent implements OnInit, OnDe
|
||||
if (!this.gotError) {
|
||||
this.gotError = true;
|
||||
let errorInfo = 'Error:';
|
||||
if (details.name) {
|
||||
errorInfo += ' ' + details.name + ':';
|
||||
}
|
||||
if (details.message) {
|
||||
errorInfo += ' ' + details.message;
|
||||
}
|
||||
|
||||
@ -16,7 +16,7 @@
|
||||
|
||||
-->
|
||||
<h2 mat-dialog-title>{{data.title}}</h2>
|
||||
<div mat-dialog-content [innerHTML]="data.message"></div>
|
||||
<div mat-dialog-content [innerHTML]="data.message | safe:'html'"></div>
|
||||
<div mat-dialog-actions fxLayoutAlign="end center">
|
||||
<button mat-button color="primary" [mat-dialog-close]="true" cdkFocusInitial>{{data.ok}}</button>
|
||||
</div>
|
||||
|
||||
@ -0,0 +1,30 @@
|
||||
<!--
|
||||
|
||||
Copyright © 2016-2023 The Thingsboard Authors
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
-->
|
||||
<h2 mat-dialog-title>{{title}}</h2>
|
||||
<div mat-dialog-content class="tb-error-alert-dialog-content">
|
||||
<div>{{ message }}</div>
|
||||
<div class="error-message-title" translate>dialog.error-message-title</div>
|
||||
<div class="error-message-content"> {{ errorMessage }} </div>
|
||||
<mat-expansion-panel *ngIf="errorDetails">
|
||||
<mat-expansion-panel-header>{{ 'dialog.error-details-title' | translate }}</mat-expansion-panel-header>
|
||||
<small class="error-details-content" [innerHTML]="errorDetails"></small>
|
||||
</mat-expansion-panel>
|
||||
</div>
|
||||
<div mat-dialog-actions fxLayoutAlign="end center">
|
||||
<button mat-button color="primary" [mat-dialog-close]="true" cdkFocusInitial>{{data.ok}}</button>
|
||||
</div>
|
||||
@ -0,0 +1,37 @@
|
||||
/**
|
||||
* Copyright © 2016-2023 The Thingsboard Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
:host {
|
||||
.mat-mdc-dialog-content {
|
||||
padding: 0 24px 24px;
|
||||
}
|
||||
.tb-error-alert-dialog-content {
|
||||
.error-message-title {
|
||||
font-style: italic;
|
||||
}
|
||||
.error-message-content {
|
||||
color: red;
|
||||
}
|
||||
.error-details-content {
|
||||
display: block;
|
||||
border: solid 1px #d3d3d3;
|
||||
padding: 8px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
& > *:not(:last-child) {
|
||||
padding-bottom: 16px;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,49 @@
|
||||
///
|
||||
/// Copyright © 2016-2023 The Thingsboard Authors
|
||||
///
|
||||
/// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
/// you may not use this file except in compliance with the License.
|
||||
/// You may obtain a copy of the License at
|
||||
///
|
||||
/// http://www.apache.org/licenses/LICENSE-2.0
|
||||
///
|
||||
/// Unless required by applicable law or agreed to in writing, software
|
||||
/// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
/// See the License for the specific language governing permissions and
|
||||
/// limitations under the License.
|
||||
///
|
||||
|
||||
import { Component, Inject } from '@angular/core';
|
||||
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
|
||||
|
||||
export interface ErrorAlertDialogData {
|
||||
title: string;
|
||||
message: string;
|
||||
error: any;
|
||||
ok: string;
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'tb-error-alert-dialog',
|
||||
templateUrl: './error-alert-dialog.component.html',
|
||||
styleUrls: ['./error-alert-dialog.component.scss']
|
||||
})
|
||||
export class ErrorAlertDialogComponent {
|
||||
|
||||
title: string;
|
||||
message: string;
|
||||
errorMessage: string;
|
||||
errorDetails?: string;
|
||||
|
||||
constructor(public dialogRef: MatDialogRef<ErrorAlertDialogComponent>,
|
||||
@Inject(MAT_DIALOG_DATA) public data: ErrorAlertDialogData) {
|
||||
this.title = this.data.title;
|
||||
this.message = this.data.message;
|
||||
this.errorMessage = this.data.error.message ? this.data.error.message : JSON.stringify(this.data.error);
|
||||
if (this.data.error.stack) {
|
||||
this.errorDetails = this.data.error.stack.replaceAll('\n', '<br/>');
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -51,7 +51,7 @@
|
||||
padding: 0 18px;
|
||||
margin: 8px;
|
||||
.toast-text {
|
||||
padding: 0 6px;
|
||||
padding: 8px;
|
||||
width: 100%;
|
||||
}
|
||||
button {
|
||||
|
||||
@ -54,7 +54,7 @@
|
||||
(click)="toggleTimewindow($event)"
|
||||
matTooltip="{{ 'timewindow.edit' | translate }}"
|
||||
[matTooltipPosition]="tooltipPosition">
|
||||
{{innerValue?.displayValue}} <span [fxShow]="innerValue?.displayTimezoneAbbr !== ''">| <span class="timezone-abbr">{{innerValue.displayTimezoneAbbr}}</span></span>
|
||||
{{innerValue?.displayValue}} <span [fxShow]="innerValue?.displayTimezoneAbbr !== ''">| <span class="timezone-abbr">{{innerValue?.displayTimezoneAbbr}}</span></span>
|
||||
</span>
|
||||
<button *ngIf="direction === 'right'" [disabled]="timewindowDisabled" mat-icon-button class="tb-mat-32"
|
||||
type="button"
|
||||
|
||||
@ -21,8 +21,6 @@ import {
|
||||
forwardRef,
|
||||
Injector,
|
||||
Input,
|
||||
OnDestroy,
|
||||
OnInit,
|
||||
StaticProvider,
|
||||
ViewContainerRef
|
||||
} from '@angular/core';
|
||||
@ -66,7 +64,7 @@ import { coerceBoolean } from '@shared/decorators/coercion';
|
||||
}
|
||||
]
|
||||
})
|
||||
export class TimewindowComponent implements OnInit, OnDestroy, ControlValueAccessor {
|
||||
export class TimewindowComponent implements ControlValueAccessor {
|
||||
|
||||
historyOnlyValue = false;
|
||||
|
||||
@ -89,60 +87,29 @@ export class TimewindowComponent implements OnInit, OnDestroy, ControlValueAcces
|
||||
@coerceBoolean()
|
||||
forAllTimeEnabled = false;
|
||||
|
||||
alwaysDisplayTypePrefixValue = false;
|
||||
@Input()
|
||||
@coerceBoolean()
|
||||
alwaysDisplayTypePrefix = false;
|
||||
|
||||
@Input()
|
||||
set alwaysDisplayTypePrefix(val) {
|
||||
this.alwaysDisplayTypePrefixValue = coerceBooleanProperty(val);
|
||||
}
|
||||
|
||||
get alwaysDisplayTypePrefix() {
|
||||
return this.alwaysDisplayTypePrefixValue;
|
||||
}
|
||||
|
||||
quickIntervalOnlyValue = false;
|
||||
@coerceBoolean()
|
||||
quickIntervalOnly = false;
|
||||
|
||||
@Input()
|
||||
set quickIntervalOnly(val) {
|
||||
this.quickIntervalOnlyValue = coerceBooleanProperty(val);
|
||||
}
|
||||
|
||||
get quickIntervalOnly() {
|
||||
return this.quickIntervalOnlyValue;
|
||||
}
|
||||
|
||||
aggregationValue = false;
|
||||
@coerceBoolean()
|
||||
aggregation = false;
|
||||
|
||||
@Input()
|
||||
set aggregation(val) {
|
||||
this.aggregationValue = coerceBooleanProperty(val);
|
||||
}
|
||||
|
||||
get aggregation() {
|
||||
return this.aggregationValue;
|
||||
}
|
||||
|
||||
timezoneValue = false;
|
||||
@coerceBoolean()
|
||||
timezone = false;
|
||||
|
||||
@Input()
|
||||
set timezone(val) {
|
||||
this.timezoneValue = coerceBooleanProperty(val);
|
||||
}
|
||||
|
||||
get timezone() {
|
||||
return this.timezoneValue;
|
||||
}
|
||||
|
||||
asButtonValue = false;
|
||||
@coerceBoolean()
|
||||
isToolbar = false;
|
||||
|
||||
@Input()
|
||||
set asButton(val) {
|
||||
this.asButtonValue = coerceBooleanProperty(val);
|
||||
}
|
||||
|
||||
get asButton() {
|
||||
return this.asButtonValue;
|
||||
}
|
||||
@coerceBoolean()
|
||||
asButton = false;
|
||||
|
||||
@Input()
|
||||
@coerceBoolean()
|
||||
@ -178,7 +145,9 @@ export class TimewindowComponent implements OnInit, OnDestroy, ControlValueAcces
|
||||
@Input()
|
||||
tooltipPosition: TooltipPosition = 'above';
|
||||
|
||||
@Input() disabled: boolean;
|
||||
@Input()
|
||||
@coerceBoolean()
|
||||
disabled: boolean;
|
||||
|
||||
innerValue: Timewindow;
|
||||
|
||||
@ -196,12 +165,6 @@ export class TimewindowComponent implements OnInit, OnDestroy, ControlValueAcces
|
||||
public viewContainerRef: ViewContainerRef) {
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
}
|
||||
|
||||
toggleTimewindow($event: Event) {
|
||||
if ($event) {
|
||||
$event.stopPropagation();
|
||||
@ -213,7 +176,6 @@ export class TimewindowComponent implements OnInit, OnDestroy, ControlValueAcces
|
||||
maxHeight: '80vh',
|
||||
height: 'min-content'
|
||||
});
|
||||
config.hasBackdrop = true;
|
||||
const connectedPosition: ConnectedPosition = {
|
||||
originX: 'start',
|
||||
originY: 'bottom',
|
||||
@ -260,13 +222,11 @@ export class TimewindowComponent implements OnInit, OnDestroy, ControlValueAcces
|
||||
}
|
||||
|
||||
private onHistoryOnlyChanged(): boolean {
|
||||
if (this.historyOnlyValue && this.innerValue) {
|
||||
if (this.innerValue.selectedTab !== TimewindowType.HISTORY) {
|
||||
if (this.historyOnlyValue && this.innerValue && this.innerValue.selectedTab !== TimewindowType.HISTORY) {
|
||||
this.innerValue.selectedTab = TimewindowType.HISTORY;
|
||||
this.updateDisplayValue();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -283,7 +243,7 @@ export class TimewindowComponent implements OnInit, OnDestroy, ControlValueAcces
|
||||
}
|
||||
|
||||
writeValue(obj: Timewindow): void {
|
||||
this.innerValue = initModelFromDefaultTimewindow(obj, this.quickIntervalOnly, this.timeService);
|
||||
this.innerValue = initModelFromDefaultTimewindow(obj, this.quickIntervalOnly, this.historyOnly, this.timeService);
|
||||
this.timewindowDisabled = this.isTimewindowDisabled();
|
||||
if (this.onHistoryOnlyChanged()) {
|
||||
setTimeout(() => {
|
||||
|
||||
@ -245,7 +245,8 @@ const getTimewindowType = (timewindow: Timewindow): TimewindowType => {
|
||||
}
|
||||
};
|
||||
|
||||
export const initModelFromDefaultTimewindow = (value: Timewindow, quickIntervalOnly: boolean, timeService: TimeService): Timewindow => {
|
||||
export const initModelFromDefaultTimewindow = (value: Timewindow, quickIntervalOnly: boolean,
|
||||
historyOnly: boolean, timeService: TimeService): Timewindow => {
|
||||
const model = defaultTimewindow(timeService);
|
||||
if (value) {
|
||||
model.hideInterval = value.hideInterval;
|
||||
@ -316,6 +317,9 @@ export const initModelFromDefaultTimewindow = (value: Timewindow, quickIntervalO
|
||||
if (quickIntervalOnly) {
|
||||
model.realtime.realtimeType = RealtimeWindowType.INTERVAL;
|
||||
}
|
||||
if (historyOnly) {
|
||||
model.selectedTab = TimewindowType.HISTORY;
|
||||
}
|
||||
return model;
|
||||
};
|
||||
|
||||
|
||||
@ -123,6 +123,7 @@ import { JsFuncComponent } from '@shared/components/js-func.component';
|
||||
import { JsonFormComponent } from '@shared/components/json-form/json-form.component';
|
||||
import { ConfirmDialogComponent } from '@shared/components/dialog/confirm-dialog.component';
|
||||
import { AlertDialogComponent } from '@shared/components/dialog/alert-dialog.component';
|
||||
import { ErrorAlertDialogComponent } from '@shared/components/dialog/error-alert-dialog.component';
|
||||
import { TodoDialogComponent } from '@shared/components/dialog/todo-dialog.component';
|
||||
import { MaterialIconsDialogComponent } from '@shared/components/dialog/material-icons-dialog.component';
|
||||
import { MaterialIconSelectComponent } from '@shared/components/material-icon-select.component';
|
||||
@ -306,6 +307,7 @@ export function MarkedOptionsFactory(markedOptionsService: MarkedOptionsService)
|
||||
WidgetsBundleSelectComponent,
|
||||
ConfirmDialogComponent,
|
||||
AlertDialogComponent,
|
||||
ErrorAlertDialogComponent,
|
||||
TodoDialogComponent,
|
||||
ColorPickerDialogComponent,
|
||||
MaterialIconsDialogComponent,
|
||||
@ -530,6 +532,7 @@ export function MarkedOptionsFactory(markedOptionsService: MarkedOptionsService)
|
||||
MarkdownModule,
|
||||
ConfirmDialogComponent,
|
||||
AlertDialogComponent,
|
||||
ErrorAlertDialogComponent,
|
||||
TodoDialogComponent,
|
||||
ColorPickerDialogComponent,
|
||||
MaterialIconsDialogComponent,
|
||||
|
||||
@ -1798,7 +1798,9 @@
|
||||
}
|
||||
},
|
||||
"dialog": {
|
||||
"close": "Close dialog"
|
||||
"close": "Close dialog",
|
||||
"error-message-title": "Error message:",
|
||||
"error-details-title": "Error details"
|
||||
},
|
||||
"direction": {
|
||||
"column": "Column",
|
||||
@ -4017,7 +4019,8 @@
|
||||
"alarm-data-overflow": "Widget displays alarms for {{allowedEntities}} (maximum allowed) entities out of {{totalEntities}} entities",
|
||||
"search": "Search widget",
|
||||
"filter": "Widget filter type",
|
||||
"loading-widgets": "Loading widgets..."
|
||||
"loading-widgets": "Loading widgets...",
|
||||
"widget-template-error": "Invalid widget HTML template."
|
||||
},
|
||||
"widget-action": {
|
||||
"header-button": "Widget header button",
|
||||
@ -4026,6 +4029,9 @@
|
||||
"open-dashboard": "Navigate to other dashboard",
|
||||
"custom": "Custom action",
|
||||
"custom-pretty": "Custom action (with HTML template)",
|
||||
"custom-pretty-error-title": "Custom dialog error",
|
||||
"custom-pretty-template-error": "Invalid custom dialog template.",
|
||||
"custom-pretty-controller-error": "Error occurred while evaluating custom dialog function.",
|
||||
"mobile-action": "Mobile action",
|
||||
"target-dashboard-state": "Target dashboard state",
|
||||
"target-dashboard-state-required": "Target dashboard state is required",
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user