Propagate UI changes
This commit is contained in:
parent
19dac7d5aa
commit
a122563619
@ -395,7 +395,7 @@ export class UtilsService {
|
|||||||
} else if (variableName === 'deviceName') {
|
} else if (variableName === 'deviceName') {
|
||||||
label = label.split(variable).join(datasource.entityName);
|
label = label.split(variable).join(datasource.entityName);
|
||||||
} else if (variableName === 'entityLabel') {
|
} else if (variableName === 'entityLabel') {
|
||||||
label = label.split(variable).join(datasource.entityLabel);
|
label = label.split(variable).join(datasource.entityLabel || datasource.entityName);
|
||||||
} else if (variableName === 'aliasName') {
|
} else if (variableName === 'aliasName') {
|
||||||
label = label.split(variable).join(datasource.aliasName);
|
label = label.split(variable).join(datasource.aliasName);
|
||||||
} else if (variableName === 'entityDescription') {
|
} else if (variableName === 'entityDescription') {
|
||||||
|
|||||||
@ -82,14 +82,19 @@
|
|||||||
<div *ngIf="widget.hasWidgetTitleTemplate">
|
<div *ngIf="widget.hasWidgetTitleTemplate">
|
||||||
TODO:
|
TODO:
|
||||||
</div>
|
</div>
|
||||||
<span [fxShow]="widget.showTitle" [ngStyle]="widget.titleStyle" class="mat-subheading-2 title">
|
<span [fxShow]="widget.showTitle"
|
||||||
|
[ngStyle]="widget.titleStyle"
|
||||||
|
[matTooltip]="widget.titleTooltip"
|
||||||
|
matTooltipPosition="above"
|
||||||
|
class="mat-subheading-2 title">
|
||||||
<mat-icon *ngIf="widget.showTitleIcon" [ngStyle]="widget.titleIconStyle">{{widget.titleIcon}}</mat-icon>
|
<mat-icon *ngIf="widget.showTitleIcon" [ngStyle]="widget.titleIconStyle">{{widget.titleIcon}}</mat-icon>
|
||||||
{{widget.title}}
|
{{widget.title}}
|
||||||
</span>
|
</span>
|
||||||
<tb-timewindow *ngIf="widget.hasTimewindow"
|
<tb-timewindow *ngIf="widget.hasTimewindow"
|
||||||
#timewindowComponent
|
#timewindowComponent
|
||||||
aggregation="{{widget.hasAggregation}}"
|
aggregation="{{widget.hasAggregation}}"
|
||||||
[ngModel]="widgetComponent.widget.config.timewindow"
|
[isEdit]="isEdit"
|
||||||
|
[(ngModel)]="widgetComponent.widget.config.timewindow"
|
||||||
(ngModelChange)="widgetComponent.onTimewindowChanged($event)">
|
(ngModelChange)="widgetComponent.onTimewindowChanged($event)">
|
||||||
</tb-timewindow>
|
</tb-timewindow>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -32,6 +32,7 @@
|
|||||||
<section fxFlex fxLayout="row" fxLayoutAlign="start center" style="margin-bottom: 16px;">
|
<section fxFlex fxLayout="row" fxLayoutAlign="start center" style="margin-bottom: 16px;">
|
||||||
<span [ngClass]="{'tb-disabled-label': dataSettings.get('useDashboardTimewindow').value}" translate style="padding-right: 8px;">widget-config.timewindow</span>
|
<span [ngClass]="{'tb-disabled-label': dataSettings.get('useDashboardTimewindow').value}" translate style="padding-right: 8px;">widget-config.timewindow</span>
|
||||||
<tb-timewindow asButton="true"
|
<tb-timewindow asButton="true"
|
||||||
|
isEdit="true"
|
||||||
aggregation="{{ widgetType === widgetTypes.timeseries }}"
|
aggregation="{{ widgetType === widgetTypes.timeseries }}"
|
||||||
fxFlex formControlName="timewindow"></tb-timewindow>
|
fxFlex formControlName="timewindow"></tb-timewindow>
|
||||||
</section>
|
</section>
|
||||||
@ -307,6 +308,10 @@
|
|||||||
<mat-label translate>widget-config.icon-size</mat-label>
|
<mat-label translate>widget-config.icon-size</mat-label>
|
||||||
<input matInput formControlName="iconSize">
|
<input matInput formControlName="iconSize">
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
|
<mat-form-field fxFlex>
|
||||||
|
<mat-label translate>widget-config.title-tooltip</mat-label>
|
||||||
|
<input matInput formControlName="titleTooltip">
|
||||||
|
</mat-form-field>
|
||||||
</div>
|
</div>
|
||||||
<div fxLayout="column" fxLayoutAlign="center" fxLayout.gt-sm="row" fxLayoutAlign.gt-sm="start center"
|
<div fxLayout="column" fxLayoutAlign="center" fxLayout.gt-sm="row" fxLayoutAlign.gt-sm="start center"
|
||||||
fxLayoutGap="8px">
|
fxLayoutGap="8px">
|
||||||
|
|||||||
@ -173,6 +173,7 @@ export class WidgetConfigComponent extends PageComponent implements OnInit, Cont
|
|||||||
titleIcon: [null, []],
|
titleIcon: [null, []],
|
||||||
iconColor: [null, []],
|
iconColor: [null, []],
|
||||||
iconSize: [null, []],
|
iconSize: [null, []],
|
||||||
|
titleTooltip: [null, []],
|
||||||
showTitle: [null, []],
|
showTitle: [null, []],
|
||||||
dropShadow: [null, []],
|
dropShadow: [null, []],
|
||||||
enableFullscreen: [null, []],
|
enableFullscreen: [null, []],
|
||||||
@ -344,6 +345,7 @@ export class WidgetConfigComponent extends PageComponent implements OnInit, Cont
|
|||||||
titleIcon: isDefined(config.titleIcon) ? config.titleIcon : '',
|
titleIcon: isDefined(config.titleIcon) ? config.titleIcon : '',
|
||||||
iconColor: isDefined(config.iconColor) ? config.iconColor : 'rgba(0, 0, 0, 0.87)',
|
iconColor: isDefined(config.iconColor) ? config.iconColor : 'rgba(0, 0, 0, 0.87)',
|
||||||
iconSize: isDefined(config.iconSize) ? config.iconSize : '24px',
|
iconSize: isDefined(config.iconSize) ? config.iconSize : '24px',
|
||||||
|
titleTooltip: isDefined(config.titleTooltip) ? config.titleTooltip : '',
|
||||||
showTitle: config.showTitle,
|
showTitle: config.showTitle,
|
||||||
dropShadow: isDefined(config.dropShadow) ? config.dropShadow : true,
|
dropShadow: isDefined(config.dropShadow) ? config.dropShadow : true,
|
||||||
enableFullscreen: isDefined(config.enableFullscreen) ? config.enableFullscreen : true,
|
enableFullscreen: isDefined(config.enableFullscreen) ? config.enableFullscreen : true,
|
||||||
|
|||||||
@ -1052,9 +1052,9 @@ export class WidgetComponent extends PageComponent implements OnInit, AfterViewI
|
|||||||
if (e.id) {
|
if (e.id) {
|
||||||
const descriptors = this.getActionDescriptors('elementClick');
|
const descriptors = this.getActionDescriptors('elementClick');
|
||||||
if (descriptors.length) {
|
if (descriptors.length) {
|
||||||
$event.stopPropagation();
|
|
||||||
descriptors.forEach((descriptor) => {
|
descriptors.forEach((descriptor) => {
|
||||||
if (descriptor.name === e.id) {
|
if (descriptor.name === e.id) {
|
||||||
|
$event.stopPropagation();
|
||||||
const entityInfo = this.getActiveEntityInfo();
|
const entityInfo = this.getActiveEntityInfo();
|
||||||
const entityId = entityInfo ? entityInfo.entityId : null;
|
const entityId = entityInfo ? entityInfo.entityId : null;
|
||||||
const entityName = entityInfo ? entityInfo.entityName : null;
|
const entityName = entityInfo ? entityInfo.entityName : null;
|
||||||
|
|||||||
@ -295,6 +295,7 @@ export class DashboardWidget implements GridsterItem, IDashboardWidget {
|
|||||||
margin: string;
|
margin: string;
|
||||||
|
|
||||||
title: string;
|
title: string;
|
||||||
|
titleTooltip: string;
|
||||||
showTitle: boolean;
|
showTitle: boolean;
|
||||||
titleStyle: {[klass: string]: any};
|
titleStyle: {[klass: string]: any};
|
||||||
|
|
||||||
@ -360,6 +361,8 @@ export class DashboardWidget implements GridsterItem, IDashboardWidget {
|
|||||||
|
|
||||||
this.title = isDefined(this.widgetContext.widgetTitle)
|
this.title = isDefined(this.widgetContext.widgetTitle)
|
||||||
&& this.widgetContext.widgetTitle.length ? this.widgetContext.widgetTitle : this.widget.config.title;
|
&& this.widgetContext.widgetTitle.length ? this.widgetContext.widgetTitle : this.widget.config.title;
|
||||||
|
this.titleTooltip = isDefined(this.widgetContext.widgetTitleTooltip)
|
||||||
|
&& this.widgetContext.widgetTitleTooltip.length ? this.widgetContext.widgetTitleTooltip : this.widget.config.titleTooltip;
|
||||||
this.showTitle = isDefined(this.widget.config.showTitle) ? this.widget.config.showTitle : true;
|
this.showTitle = isDefined(this.widget.config.showTitle) ? this.widget.config.showTitle : true;
|
||||||
this.titleStyle = this.widget.config.titleStyle ? this.widget.config.titleStyle : {};
|
this.titleStyle = this.widget.config.titleStyle ? this.widget.config.titleStyle : {};
|
||||||
|
|
||||||
|
|||||||
@ -178,6 +178,7 @@ export class WidgetContext {
|
|||||||
|
|
||||||
widgetTitleTemplate?: string;
|
widgetTitleTemplate?: string;
|
||||||
widgetTitle?: string;
|
widgetTitle?: string;
|
||||||
|
widgetTitleTooltip?: string;
|
||||||
customHeaderActions?: Array<WidgetHeaderAction>;
|
customHeaderActions?: Array<WidgetHeaderAction>;
|
||||||
widgetActions?: Array<WidgetAction>;
|
widgetActions?: Array<WidgetAction>;
|
||||||
|
|
||||||
|
|||||||
@ -55,6 +55,7 @@
|
|||||||
</button>
|
</button>
|
||||||
<tb-timewindow [fxShow]="isEdit || displayDashboardTimewindow()"
|
<tb-timewindow [fxShow]="isEdit || displayDashboardTimewindow()"
|
||||||
isToolbar="true"
|
isToolbar="true"
|
||||||
|
[isEdit]="isEdit"
|
||||||
direction="left"
|
direction="left"
|
||||||
tooltipPosition="below"
|
tooltipPosition="below"
|
||||||
aggregation="true"
|
aggregation="true"
|
||||||
|
|||||||
@ -87,6 +87,7 @@ export class JsonFormComponent implements OnInit, ControlValueAccessor, Validato
|
|||||||
},
|
},
|
||||||
onModelChange: this.onModelChange.bind(this),
|
onModelChange: this.onModelChange.bind(this),
|
||||||
onColorClick: this.onColorClick.bind(this),
|
onColorClick: this.onColorClick.bind(this),
|
||||||
|
onIconClick: this.onIconClick.bind(this),
|
||||||
onToggleFullscreen: this.onToggleFullscreen.bind(this)
|
onToggleFullscreen: this.onToggleFullscreen.bind(this)
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -201,6 +202,16 @@ export class JsonFormComponent implements OnInit, ControlValueAccessor, Validato
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private onIconClick(key: (string | number)[],
|
||||||
|
val: string,
|
||||||
|
iconSelectedFn: (icon: string) => void) {
|
||||||
|
this.dialogs.materialIconPicker(val).subscribe((icon) => {
|
||||||
|
if (icon && iconSelectedFn) {
|
||||||
|
iconSelectedFn(icon);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
private onToggleFullscreen(element: HTMLElement, fullscreenFinishFn?: () => void) {
|
private onToggleFullscreen(element: HTMLElement, fullscreenFinishFn?: () => void) {
|
||||||
this.targetFullscreenElement = element;
|
this.targetFullscreenElement = element;
|
||||||
this.isFullscreen = !this.isFullscreen;
|
this.isFullscreen = !this.isFullscreen;
|
||||||
|
|||||||
@ -143,7 +143,7 @@ class ThingsboardArray extends React.Component<JsonFormFieldProps, ThingsboardAr
|
|||||||
const forms = (this.props.form.items as JsonFormData[]).map((form, index) => {
|
const forms = (this.props.form.items as JsonFormData[]).map((form, index) => {
|
||||||
const copy = this.copyWithIndex(form, i);
|
const copy = this.copyWithIndex(form, i);
|
||||||
return this.props.builder(copy, this.props.model, index, this.props.onChange,
|
return this.props.builder(copy, this.props.model, index, this.props.onChange,
|
||||||
this.props.onColorClick, this.props.onToggleFullscreen, this.props.mapper);
|
this.props.onColorClick, this.props.onIconClick, this.props.onToggleFullscreen, this.props.mapper);
|
||||||
});
|
});
|
||||||
arrays.push(
|
arrays.push(
|
||||||
<li key={keys[i]} className='list-group-item'>
|
<li key={keys[i]} className='list-group-item'>
|
||||||
|
|||||||
@ -25,7 +25,7 @@ class ThingsboardFieldSet extends React.Component<JsonFormFieldProps, JsonFormFi
|
|||||||
render() {
|
render() {
|
||||||
const forms = (this.props.form.items as JsonFormData[]).map((form: JsonFormData, index) => {
|
const forms = (this.props.form.items as JsonFormData[]).map((form: JsonFormData, index) => {
|
||||||
return this.props.builder(form, this.props.model, index, this.props.onChange,
|
return this.props.builder(form, this.props.model, index, this.props.onChange,
|
||||||
this.props.onColorClick, this.props.onToggleFullscreen, this.props.mapper);
|
this.props.onColorClick, this.props.onIconClick, this.props.onToggleFullscreen, this.props.mapper);
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@ -0,0 +1,159 @@
|
|||||||
|
/*
|
||||||
|
* Copyright © 2016-2020 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 * as React from 'react';
|
||||||
|
import * as ReactDOM from 'react-dom';
|
||||||
|
import ThingsboardBaseComponent from './json-form-base-component';
|
||||||
|
import reactCSS from 'reactcss';
|
||||||
|
import TextField from '@material-ui/core/TextField';
|
||||||
|
import IconButton from '@material-ui/core/IconButton';
|
||||||
|
import { JsonFormFieldProps, JsonFormFieldState } from '@shared/components/json-form/react/json-form.models';
|
||||||
|
import ClearIcon from '@material-ui/icons/Clear';
|
||||||
|
import Icon from '@material-ui/core/Icon';
|
||||||
|
import Tooltip from '@material-ui/core/Tooltip';
|
||||||
|
|
||||||
|
interface ThingsboardIconState extends JsonFormFieldState {
|
||||||
|
icon: string | null;
|
||||||
|
focused: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
class ThingsboardIcon extends React.Component<JsonFormFieldProps, ThingsboardIconState> {
|
||||||
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.onBlur = this.onBlur.bind(this);
|
||||||
|
this.onFocus = this.onFocus.bind(this);
|
||||||
|
this.onValueChanged = this.onValueChanged.bind(this);
|
||||||
|
this.onIconClick = this.onIconClick.bind(this);
|
||||||
|
this.onClear = this.onClear.bind(this);
|
||||||
|
const icon = props.value ? props.value : '';
|
||||||
|
this.state = {
|
||||||
|
icon,
|
||||||
|
focused: false
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
onBlur() {
|
||||||
|
this.setState({focused: false});
|
||||||
|
}
|
||||||
|
|
||||||
|
onFocus() {
|
||||||
|
this.setState({focused: true});
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
const node = ReactDOM.findDOMNode(this);
|
||||||
|
const iconContainer = $(node).children('#icon-container');
|
||||||
|
iconContainer.click((event) => {
|
||||||
|
if (!this.props.form.readonly) {
|
||||||
|
this.onIconClick(event);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillUnmount () {
|
||||||
|
const node = ReactDOM.findDOMNode(this);
|
||||||
|
const iconContainer = $(node).children('#icon-container');
|
||||||
|
iconContainer.off( 'click' );
|
||||||
|
}
|
||||||
|
|
||||||
|
onValueChanged(value: string | null) {
|
||||||
|
const icon = value;
|
||||||
|
this.setState({
|
||||||
|
icon: value
|
||||||
|
});
|
||||||
|
this.props.onChange(this.props.form.key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
onIconClick(event) {
|
||||||
|
this.props.onIconClick(this.props.form.key, this.state.icon,
|
||||||
|
(color) => {
|
||||||
|
this.onValueChanged(color);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
onClear(event) {
|
||||||
|
if (event) {
|
||||||
|
event.stopPropagation();
|
||||||
|
}
|
||||||
|
this.onValueChanged('');
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
|
||||||
|
const styles = reactCSS({
|
||||||
|
default: {
|
||||||
|
container: {
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'row',
|
||||||
|
alignItems: 'center'
|
||||||
|
},
|
||||||
|
icon: {
|
||||||
|
marginRight: '10px',
|
||||||
|
marginBottom: 'auto',
|
||||||
|
cursor: 'pointer',
|
||||||
|
border: 'solid 1px rgba(0, 0, 0, .27)',
|
||||||
|
borderRadius: '0'
|
||||||
|
},
|
||||||
|
iconContainer: {
|
||||||
|
display: 'flex',
|
||||||
|
width: '100%'
|
||||||
|
},
|
||||||
|
iconText: {
|
||||||
|
width: '100%'
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
let fieldClass = 'tb-field';
|
||||||
|
if (this.props.form.required) {
|
||||||
|
fieldClass += ' tb-required';
|
||||||
|
}
|
||||||
|
if (this.state.focused) {
|
||||||
|
fieldClass += ' tb-focused';
|
||||||
|
}
|
||||||
|
|
||||||
|
let pickedIcon = 'more_horiz';
|
||||||
|
let icon = '';
|
||||||
|
if (this.state.icon !== '') {
|
||||||
|
pickedIcon = this.state.icon;
|
||||||
|
icon = this.state.icon;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div style={ styles.container }>
|
||||||
|
<div id='icon-container' style={ styles.iconContainer }>
|
||||||
|
<IconButton style={ styles.icon }>
|
||||||
|
<Icon>{pickedIcon}</Icon>
|
||||||
|
</IconButton>
|
||||||
|
<TextField
|
||||||
|
className={fieldClass}
|
||||||
|
label={this.props.form.title}
|
||||||
|
error={!this.props.valid}
|
||||||
|
helperText={this.props.valid ? this.props.form.placeholder : this.props.error}
|
||||||
|
value={icon}
|
||||||
|
disabled={this.props.form.readonly}
|
||||||
|
onFocus={this.onFocus}
|
||||||
|
onBlur={this.onBlur}
|
||||||
|
style={ styles.iconText } />
|
||||||
|
</div>
|
||||||
|
<Tooltip title='Clear' placement='top'><IconButton onClick={this.onClear}><ClearIcon/></IconButton></Tooltip>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ThingsboardBaseComponent(ThingsboardIcon);
|
||||||
@ -32,7 +32,8 @@ import ThingsboardImage from './json-form-image';
|
|||||||
import ThingsboardCheckbox from './json-form-checkbox';
|
import ThingsboardCheckbox from './json-form-checkbox';
|
||||||
import ThingsboardHelp from './json-form-help';
|
import ThingsboardHelp from './json-form-help';
|
||||||
import ThingsboardFieldSet from './json-form-fieldset';
|
import ThingsboardFieldSet from './json-form-fieldset';
|
||||||
import { JsonFormProps, JsonFormData, onChangeFn, OnColorClickFn } from './json-form.models';
|
import ThingsboardIcon from './json-form-icon';
|
||||||
|
import { JsonFormProps, JsonFormData, onChangeFn, OnColorClickFn, OnIconClickFn } from './json-form.models';
|
||||||
|
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import * as tinycolor_ from 'tinycolor2';
|
import * as tinycolor_ from 'tinycolor2';
|
||||||
@ -65,11 +66,13 @@ class ThingsboardSchemaForm extends React.Component<JsonFormProps, any> {
|
|||||||
css: ThingsboardCss,
|
css: ThingsboardCss,
|
||||||
color: ThingsboardColor,
|
color: ThingsboardColor,
|
||||||
'rc-select': ThingsboardRcSelect,
|
'rc-select': ThingsboardRcSelect,
|
||||||
fieldset: ThingsboardFieldSet
|
fieldset: ThingsboardFieldSet,
|
||||||
|
icon: ThingsboardIcon
|
||||||
};
|
};
|
||||||
|
|
||||||
this.onChange = this.onChange.bind(this);
|
this.onChange = this.onChange.bind(this);
|
||||||
this.onColorClick = this.onColorClick.bind(this);
|
this.onColorClick = this.onColorClick.bind(this);
|
||||||
|
this.onIconClick = this.onIconClick.bind(this);
|
||||||
this.onToggleFullscreen = this.onToggleFullscreen.bind(this);
|
this.onToggleFullscreen = this.onToggleFullscreen.bind(this);
|
||||||
this.hasConditions = false;
|
this.hasConditions = false;
|
||||||
}
|
}
|
||||||
@ -86,6 +89,11 @@ class ThingsboardSchemaForm extends React.Component<JsonFormProps, any> {
|
|||||||
this.props.onColorClick(key, val, colorSelectedFn);
|
this.props.onColorClick(key, val, colorSelectedFn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onIconClick(key: (string | number)[], val: string,
|
||||||
|
iconSelectedFn: (icon: string) => void) {
|
||||||
|
this.props.onIconClick(key, val, iconSelectedFn);
|
||||||
|
}
|
||||||
|
|
||||||
onToggleFullscreen(element: HTMLElement, fullscreenFinishFn?: () => void) {
|
onToggleFullscreen(element: HTMLElement, fullscreenFinishFn?: () => void) {
|
||||||
this.props.onToggleFullscreen(element, fullscreenFinishFn);
|
this.props.onToggleFullscreen(element, fullscreenFinishFn);
|
||||||
}
|
}
|
||||||
@ -96,6 +104,7 @@ class ThingsboardSchemaForm extends React.Component<JsonFormProps, any> {
|
|||||||
index: number,
|
index: number,
|
||||||
onChange: onChangeFn,
|
onChange: onChangeFn,
|
||||||
onColorClick: OnColorClickFn,
|
onColorClick: OnColorClickFn,
|
||||||
|
onIconClick: OnIconClickFn,
|
||||||
onToggleFullscreen: () => void,
|
onToggleFullscreen: () => void,
|
||||||
mapper: {[type: string]: any}): JSX.Element {
|
mapper: {[type: string]: any}): JSX.Element {
|
||||||
const type = form.type;
|
const type = form.type;
|
||||||
@ -113,6 +122,7 @@ class ThingsboardSchemaForm extends React.Component<JsonFormProps, any> {
|
|||||||
}
|
}
|
||||||
return <Field model={model} form={form} key={index} onChange={onChange}
|
return <Field model={model} form={form} key={index} onChange={onChange}
|
||||||
onColorClick={onColorClick}
|
onColorClick={onColorClick}
|
||||||
|
onIconClick={onIconClick}
|
||||||
onToggleFullscreen={onToggleFullscreen}
|
onToggleFullscreen={onToggleFullscreen}
|
||||||
mapper={mapper} builder={this.builder}/>;
|
mapper={mapper} builder={this.builder}/>;
|
||||||
}
|
}
|
||||||
@ -124,7 +134,8 @@ class ThingsboardSchemaForm extends React.Component<JsonFormProps, any> {
|
|||||||
mapper = _.merge(this.mapper, this.props.mapper);
|
mapper = _.merge(this.mapper, this.props.mapper);
|
||||||
}
|
}
|
||||||
const forms = merged.map(function(form, index) {
|
const forms = merged.map(function(form, index) {
|
||||||
return this.builder(form, this.props.model, index, this.onChange, this.onColorClick, this.onToggleFullscreen, mapper);
|
return this.builder(form, this.props.model, index, this.onChange, this.onColorClick,
|
||||||
|
this.onIconClick, this.onToggleFullscreen, mapper);
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
|
|
||||||
let formClass = 'SchemaForm';
|
let formClass = 'SchemaForm';
|
||||||
|
|||||||
@ -49,6 +49,8 @@ export interface DefaultsFormOptions {
|
|||||||
export type onChangeFn = (key: (string | number)[], val: any, forceUpdate?: boolean) => void;
|
export type onChangeFn = (key: (string | number)[], val: any, forceUpdate?: boolean) => void;
|
||||||
export type OnColorClickFn = (key: (string | number)[], val: tinycolor.ColorFormats.RGBA,
|
export type OnColorClickFn = (key: (string | number)[], val: tinycolor.ColorFormats.RGBA,
|
||||||
colorSelectedFn: (color: tinycolor.ColorFormats.RGBA) => void) => void;
|
colorSelectedFn: (color: tinycolor.ColorFormats.RGBA) => void) => void;
|
||||||
|
export type OnIconClickFn = (key: (string | number)[], val: string,
|
||||||
|
iconSelectedFn: (icon: string) => void) => void;
|
||||||
export type onToggleFullscreenFn = (element: HTMLElement, fullscreenFinishFn?: () => void) => void;
|
export type onToggleFullscreenFn = (element: HTMLElement, fullscreenFinishFn?: () => void) => void;
|
||||||
|
|
||||||
export interface JsonFormProps {
|
export interface JsonFormProps {
|
||||||
@ -61,6 +63,7 @@ export interface JsonFormProps {
|
|||||||
option: FormOption;
|
option: FormOption;
|
||||||
onModelChange?: onChangeFn;
|
onModelChange?: onChangeFn;
|
||||||
onColorClick?: OnColorClickFn;
|
onColorClick?: OnColorClickFn;
|
||||||
|
onIconClick?: OnIconClickFn;
|
||||||
onToggleFullscreen?: onToggleFullscreenFn;
|
onToggleFullscreen?: onToggleFullscreenFn;
|
||||||
mapper?: {[type: string]: any};
|
mapper?: {[type: string]: any};
|
||||||
}
|
}
|
||||||
@ -107,6 +110,7 @@ export type ComponentBuilderFn = (form: JsonFormData,
|
|||||||
index: number,
|
index: number,
|
||||||
onChange: onChangeFn,
|
onChange: onChangeFn,
|
||||||
onColorClick: OnColorClickFn,
|
onColorClick: OnColorClickFn,
|
||||||
|
onIconClick: OnIconClickFn,
|
||||||
onToggleFullscreen: onToggleFullscreenFn,
|
onToggleFullscreen: onToggleFullscreenFn,
|
||||||
mapper: {[type: string]: any}) => JSX.Element;
|
mapper: {[type: string]: any}) => JSX.Element;
|
||||||
|
|
||||||
@ -118,6 +122,7 @@ export interface JsonFormFieldProps {
|
|||||||
mapper?: {[type: string]: any};
|
mapper?: {[type: string]: any};
|
||||||
onChange?: onChangeFn;
|
onChange?: onChangeFn;
|
||||||
onColorClick?: OnColorClickFn;
|
onColorClick?: OnColorClickFn;
|
||||||
|
onIconClick?: OnIconClickFn;
|
||||||
onChangeValidate?: (e: any, forceUpdate?: boolean) => void;
|
onChangeValidate?: (e: any, forceUpdate?: boolean) => void;
|
||||||
onToggleFullscreen?: onToggleFullscreenFn;
|
onToggleFullscreen?: onToggleFullscreenFn;
|
||||||
valid?: boolean;
|
valid?: boolean;
|
||||||
|
|||||||
@ -21,13 +21,13 @@
|
|||||||
<mat-placeholder translate>datetime.date-from</mat-placeholder>
|
<mat-placeholder translate>datetime.date-from</mat-placeholder>
|
||||||
<mat-datetimepicker-toggle [for]="startDatePicker" matPrefix></mat-datetimepicker-toggle>
|
<mat-datetimepicker-toggle [for]="startDatePicker" matPrefix></mat-datetimepicker-toggle>
|
||||||
<mat-datetimepicker #startDatePicker type="date" openOnFocus="true"></mat-datetimepicker>
|
<mat-datetimepicker #startDatePicker type="date" openOnFocus="true"></mat-datetimepicker>
|
||||||
<input matInput [(ngModel)]="startDate" [matDatetimepicker]="startDatePicker" (ngModelChange)="onStartDateChange()">
|
<input matInput [disabled]="disabled" [(ngModel)]="startDate" [matDatetimepicker]="startDatePicker" (ngModelChange)="onStartDateChange()">
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
<mat-form-field>
|
<mat-form-field>
|
||||||
<mat-placeholder translate>datetime.time-from</mat-placeholder>
|
<mat-placeholder translate>datetime.time-from</mat-placeholder>
|
||||||
<mat-datetimepicker-toggle [for]="startTimePicker" matPrefix></mat-datetimepicker-toggle>
|
<mat-datetimepicker-toggle [for]="startTimePicker" matPrefix></mat-datetimepicker-toggle>
|
||||||
<mat-datetimepicker #startTimePicker type="time" openOnFocus="true"></mat-datetimepicker>
|
<mat-datetimepicker #startTimePicker type="time" openOnFocus="true"></mat-datetimepicker>
|
||||||
<input matInput [(ngModel)]="startDate" [matDatetimepicker]="startTimePicker" (ngModelChange)="onStartDateChange()">
|
<input matInput [disabled]="disabled" [(ngModel)]="startDate" [matDatetimepicker]="startTimePicker" (ngModelChange)="onStartDateChange()">
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
</section>
|
</section>
|
||||||
<section fxLayout="row" fxLayoutAlign="start start" fxLayoutGap="16px">
|
<section fxLayout="row" fxLayoutAlign="start start" fxLayoutGap="16px">
|
||||||
@ -35,13 +35,13 @@
|
|||||||
<mat-placeholder translate>datetime.date-to</mat-placeholder>
|
<mat-placeholder translate>datetime.date-to</mat-placeholder>
|
||||||
<mat-datetimepicker-toggle [for]="endDatePicker" matPrefix></mat-datetimepicker-toggle>
|
<mat-datetimepicker-toggle [for]="endDatePicker" matPrefix></mat-datetimepicker-toggle>
|
||||||
<mat-datetimepicker #endDatePicker type="date" openOnFocus="true"></mat-datetimepicker>
|
<mat-datetimepicker #endDatePicker type="date" openOnFocus="true"></mat-datetimepicker>
|
||||||
<input matInput [(ngModel)]="endDate" [matDatetimepicker]="endDatePicker" (ngModelChange)="onEndDateChange()">
|
<input matInput [disabled]="disabled" [(ngModel)]="endDate" [matDatetimepicker]="endDatePicker" (ngModelChange)="onEndDateChange()">
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
<mat-form-field>
|
<mat-form-field>
|
||||||
<mat-placeholder translate>datetime.time-to</mat-placeholder>
|
<mat-placeholder translate>datetime.time-to</mat-placeholder>
|
||||||
<mat-datetimepicker-toggle [for]="endTimePicker" matPrefix></mat-datetimepicker-toggle>
|
<mat-datetimepicker-toggle [for]="endTimePicker" matPrefix></mat-datetimepicker-toggle>
|
||||||
<mat-datetimepicker #endTimePicker type="time" openOnFocus="true"></mat-datetimepicker>
|
<mat-datetimepicker #endTimePicker type="time" openOnFocus="true"></mat-datetimepicker>
|
||||||
<input matInput [(ngModel)]="endDate" [matDatetimepicker]="endTimePicker" (ngModelChange)="onEndDateChange()">
|
<input matInput [disabled]="disabled" [(ngModel)]="endDate" [matDatetimepicker]="endTimePicker" (ngModelChange)="onEndDateChange()">
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
</section>
|
</section>
|
||||||
</section>
|
</section>
|
||||||
|
|||||||
@ -16,39 +16,43 @@
|
|||||||
|
|
||||||
-->
|
-->
|
||||||
<section fxLayout="row">
|
<section fxLayout="row">
|
||||||
<section class="interval-section" fxLayout="column" fxFlex [fxShow]="advanced">
|
<section fxLayout="column" [fxShow]="isEdit">
|
||||||
|
<label class="tb-small hide-label" translate>timewindow.hide</label>
|
||||||
|
<mat-checkbox [(ngModel)]="hideFlag" (ngModelChange)="onHideFlagChange()"></mat-checkbox>
|
||||||
|
</section>
|
||||||
|
<section class="interval-section" fxLayout="column" fxFlex [fxShow]="advanced && (isEdit || !hideFlag)">
|
||||||
<label class="tb-small interval-label" translate>{{ predefinedName }}</label>
|
<label class="tb-small interval-label" translate>{{ predefinedName }}</label>
|
||||||
<section fxLayout="row" fxLayoutAlign="start start" fxFlex fxLayoutGap="6px">
|
<section fxLayout="row" fxLayoutAlign="start start" fxFlex fxLayoutGap="6px">
|
||||||
<mat-form-field class="number-input">
|
<mat-form-field class="number-input">
|
||||||
<mat-label translate>timeinterval.days</mat-label>
|
<mat-label translate>timeinterval.days</mat-label>
|
||||||
<input matInput type="number" step="1" min="0" [(ngModel)]="days" (ngModelChange)="onTimeInputChange('days')"/>
|
<input matInput [disabled]="hideFlag || disabled" type="number" step="1" min="0" [(ngModel)]="days" (ngModelChange)="onTimeInputChange('days')"/>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
<mat-form-field class="number-input">
|
<mat-form-field class="number-input">
|
||||||
<mat-label translate>timeinterval.hours</mat-label>
|
<mat-label translate>timeinterval.hours</mat-label>
|
||||||
<input matInput type="number" step="1" [(ngModel)]="hours" (ngModelChange)="onTimeInputChange('hours')"/>
|
<input matInput [disabled]="hideFlag || disabled" type="number" step="1" [(ngModel)]="hours" (ngModelChange)="onTimeInputChange('hours')"/>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
<mat-form-field class="number-input">
|
<mat-form-field class="number-input">
|
||||||
<mat-label translate>timeinterval.minutes</mat-label>
|
<mat-label translate>timeinterval.minutes</mat-label>
|
||||||
<input matInput type="number" step="1" [(ngModel)]="mins" (ngModelChange)="onTimeInputChange('mins')"/>
|
<input matInput [disabled]="hideFlag || disabled" type="number" step="1" [(ngModel)]="mins" (ngModelChange)="onTimeInputChange('mins')"/>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
<mat-form-field class="number-input">
|
<mat-form-field class="number-input">
|
||||||
<mat-label translate>timeinterval.seconds</mat-label>
|
<mat-label translate>timeinterval.seconds</mat-label>
|
||||||
<input matInput type="number" step="1" [(ngModel)]="secs" (ngModelChange)="onTimeInputChange('secs')"/>
|
<input matInput [disabled]="hideFlag || disabled" type="number" step="1" [(ngModel)]="secs" (ngModelChange)="onTimeInputChange('secs')"/>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
</section>
|
</section>
|
||||||
</section>
|
</section>
|
||||||
<section class="interval-section" fxLayout="row" fxFlex [fxShow]="!advanced">
|
<section class="interval-section" fxLayout="row" fxFlex [fxShow]="!advanced && (isEdit || !hideFlag)">
|
||||||
<mat-form-field fxFlex>
|
<mat-form-field fxFlex>
|
||||||
<mat-label translate>{{ predefinedName }}</mat-label>
|
<mat-label translate>{{ predefinedName }}</mat-label>
|
||||||
<mat-select matInput [(ngModel)]="intervalMs" (ngModelChange)="onIntervalMsChange()" style="min-width: 150px;">
|
<mat-select matInput [disabled]="hideFlag || disabled" [(ngModel)]="intervalMs" (ngModelChange)="onIntervalMsChange()" style="min-width: 150px;">
|
||||||
<mat-option *ngFor="let interval of intervals" [value]="interval.value">
|
<mat-option *ngFor="let interval of intervals" [value]="interval.value">
|
||||||
{{ interval.name | translate:interval.translateParams }}
|
{{ interval.name | translate:interval.translateParams }}
|
||||||
</mat-option>
|
</mat-option>
|
||||||
</mat-select>
|
</mat-select>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
</section>
|
</section>
|
||||||
<section fxLayout="column" fxLayoutAlign="center center">
|
<section fxLayout="column" fxLayoutAlign="center center" [fxShow]="(isEdit || !hideFlag)">
|
||||||
<label class="tb-small advanced-label" translate>timeinterval.advanced</label>
|
<label class="tb-small advanced-label" translate>timeinterval.advanced</label>
|
||||||
<mat-slide-toggle class="advanced-switch" [(ngModel)]="advanced" (ngModelChange)="onAdvancedChange()"></mat-slide-toggle>
|
<mat-slide-toggle [disabled]="hideFlag || disabled" class="advanced-switch" [(ngModel)]="advanced" (ngModelChange)="onAdvancedChange()"></mat-slide-toggle>
|
||||||
</section>
|
</section>
|
||||||
</section>
|
</section>
|
||||||
|
|||||||
@ -24,6 +24,11 @@
|
|||||||
margin: 5px 0;
|
margin: 5px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.hide-label {
|
||||||
|
margin-bottom: 5px;
|
||||||
|
margin-right: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
.interval-section {
|
.interval-section {
|
||||||
min-height: 66px;
|
min-height: 66px;
|
||||||
.interval-label {
|
.interval-label {
|
||||||
|
|||||||
@ -14,7 +14,7 @@
|
|||||||
/// limitations under the License.
|
/// limitations under the License.
|
||||||
///
|
///
|
||||||
|
|
||||||
import { ChangeDetectorRef, Component, forwardRef, Input, OnInit } from '@angular/core';
|
import { ChangeDetectorRef, Component, EventEmitter, forwardRef, Input, OnInit, Output } from '@angular/core';
|
||||||
import {
|
import {
|
||||||
ControlValueAccessor,
|
ControlValueAccessor,
|
||||||
FormControl,
|
FormControl,
|
||||||
@ -24,6 +24,7 @@ import {
|
|||||||
} from '@angular/forms';
|
} from '@angular/forms';
|
||||||
import { Timewindow } from '@shared/models/time/time.models';
|
import { Timewindow } from '@shared/models/time/time.models';
|
||||||
import { TimeInterval, TimeService } from '@core/services/time.service';
|
import { TimeInterval, TimeService } from '@core/services/time.service';
|
||||||
|
import { coerceBooleanProperty } from '@angular/cdk/coercion';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'tb-timeinterval',
|
selector: 'tb-timeinterval',
|
||||||
@ -61,6 +62,31 @@ export class TimeintervalComponent implements OnInit, ControlValueAccessor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Input() predefinedName: string;
|
@Input() predefinedName: string;
|
||||||
|
|
||||||
|
isEditValue = false;
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
set isEdit(val) {
|
||||||
|
this.isEditValue = coerceBooleanProperty(val);
|
||||||
|
}
|
||||||
|
|
||||||
|
get isEdit() {
|
||||||
|
return this.isEditValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
hideFlagValue = false;
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
get hideFlag() {
|
||||||
|
return this.hideFlagValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
set hideFlag(val) {
|
||||||
|
this.hideFlagValue = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Output() hideFlagChange = new EventEmitter<boolean>();
|
||||||
|
|
||||||
@Input() disabled: boolean;
|
@Input() disabled: boolean;
|
||||||
|
|
||||||
days = 0;
|
days = 0;
|
||||||
@ -189,6 +215,10 @@ export class TimeintervalComponent implements OnInit, ControlValueAccessor {
|
|||||||
this.updateView();
|
this.updateView();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onHideFlagChange() {
|
||||||
|
this.hideFlagChange.emit(this.hideFlagValue);
|
||||||
|
}
|
||||||
|
|
||||||
onTimeInputChange(type: string) {
|
onTimeInputChange(type: string) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 'secs':
|
case 'secs':
|
||||||
|
|||||||
@ -23,6 +23,9 @@
|
|||||||
<mat-tab label="{{ 'timewindow.realtime' | translate }}">
|
<mat-tab label="{{ 'timewindow.realtime' | translate }}">
|
||||||
<div formGroupName="realtime" class="mat-content mat-padding" fxLayout="column">
|
<div formGroupName="realtime" class="mat-content mat-padding" fxLayout="column">
|
||||||
<tb-timeinterval
|
<tb-timeinterval
|
||||||
|
[(hideFlag)]="timewindow.hideInterval"
|
||||||
|
(hideFlagChange)="onHideIntervalChanged()"
|
||||||
|
[isEdit]="isEdit"
|
||||||
formControlName="timewindowMs"
|
formControlName="timewindowMs"
|
||||||
predefinedName="timewindow.last"
|
predefinedName="timewindow.last"
|
||||||
[required]="timewindow.selectedTab === timewindowTypes.REALTIME"
|
[required]="timewindow.selectedTab === timewindowTypes.REALTIME"
|
||||||
@ -30,66 +33,95 @@
|
|||||||
</div>
|
</div>
|
||||||
</mat-tab>
|
</mat-tab>
|
||||||
<mat-tab label="{{ 'timewindow.history' | translate }}">
|
<mat-tab label="{{ 'timewindow.history' | translate }}">
|
||||||
<div formGroupName="history" class="mat-content mat-padding" style="padding-top: 8px;">
|
<section fxLayout="row">
|
||||||
<mat-radio-group formControlName="historyType">
|
<section *ngIf="isEdit" fxLayout="column" style="padding-top: 8px; padding-left: 16px;">
|
||||||
<mat-radio-button [value]="historyTypes.LAST_INTERVAL" color="primary">
|
<label class="tb-small hide-label" translate>timewindow.hide</label>
|
||||||
<section fxLayout="column">
|
<mat-checkbox [ngModelOptions]="{standalone: true}" [(ngModel)]="timewindow.hideInterval"
|
||||||
<tb-timeinterval
|
(ngModelChange)="onHideIntervalChanged()"></mat-checkbox>
|
||||||
formControlName="timewindowMs"
|
</section>
|
||||||
predefinedName="timewindow.last"
|
<section fxLayout="column" [fxShow]="isEdit || !timewindow.hideInterval">
|
||||||
[fxShow]="timewindowForm.get('history').get('historyType').value === historyTypes.LAST_INTERVAL"
|
<div formGroupName="history" class="mat-content mat-padding" style="padding-top: 8px;">
|
||||||
[required]="timewindow.selectedTab === timewindowTypes.HISTORY &&
|
<mat-radio-group formControlName="historyType">
|
||||||
|
<mat-radio-button [value]="historyTypes.LAST_INTERVAL" color="primary">
|
||||||
|
<section fxLayout="column">
|
||||||
|
<tb-timeinterval
|
||||||
|
formControlName="timewindowMs"
|
||||||
|
predefinedName="timewindow.last"
|
||||||
|
[fxShow]="timewindowForm.get('history').get('historyType').value === historyTypes.LAST_INTERVAL"
|
||||||
|
[required]="timewindow.selectedTab === timewindowTypes.HISTORY &&
|
||||||
timewindowForm.get('history').get('historyType').value === historyTypes.LAST_INTERVAL"
|
timewindowForm.get('history').get('historyType').value === historyTypes.LAST_INTERVAL"
|
||||||
style="padding-top: 8px;"></tb-timeinterval>
|
style="padding-top: 8px;"></tb-timeinterval>
|
||||||
</section>
|
</section>
|
||||||
</mat-radio-button>
|
</mat-radio-button>
|
||||||
<mat-radio-button [value]="historyTypes.FIXED" color="primary">
|
<mat-radio-button [value]="historyTypes.FIXED" color="primary">
|
||||||
<section fxLayout="column">
|
<section fxLayout="column">
|
||||||
<span translate>timewindow.time-period</span>
|
<span translate>timewindow.time-period</span>
|
||||||
<tb-datetime-period
|
<tb-datetime-period
|
||||||
formControlName="fixedTimewindow"
|
formControlName="fixedTimewindow"
|
||||||
[fxShow]="timewindowForm.get('history').get('historyType').value === historyTypes.FIXED"
|
[fxShow]="timewindowForm.get('history').get('historyType').value === historyTypes.FIXED"
|
||||||
[required]="timewindow.selectedTab === timewindowTypes.HISTORY &&
|
[required]="timewindow.selectedTab === timewindowTypes.HISTORY &&
|
||||||
timewindowForm.get('history').get('historyType').value === historyTypes.FIXED"
|
timewindowForm.get('history').get('historyType').value === historyTypes.FIXED"
|
||||||
style="padding-top: 8px;"></tb-datetime-period>
|
style="padding-top: 8px;"></tb-datetime-period>
|
||||||
</section>
|
</section>
|
||||||
</mat-radio-button>
|
</mat-radio-button>
|
||||||
</mat-radio-group>
|
</mat-radio-group>
|
||||||
</div>
|
</div>
|
||||||
|
</section>
|
||||||
|
</section>
|
||||||
</mat-tab>
|
</mat-tab>
|
||||||
</mat-tab-group>
|
</mat-tab-group>
|
||||||
<div *ngIf="aggregation" formGroupName="aggregation" class="mat-content mat-padding" fxLayout="column">
|
<div *ngIf="aggregation" formGroupName="aggregation" class="mat-content mat-padding" fxLayout="column">
|
||||||
<mat-form-field>
|
<section fxLayout="row">
|
||||||
<mat-label translate>aggregation.function</mat-label>
|
<section fxLayout="column" [fxShow]="isEdit">
|
||||||
<mat-select matInput formControlName="type" style="min-width: 150px;">
|
<label class="tb-small hide-label" translate>timewindow.hide</label>
|
||||||
<mat-option *ngFor="let aggregation of aggregations" [value]="aggregation">
|
<mat-checkbox [ngModelOptions]="{standalone: true}" [(ngModel)]="timewindow.hideAggregation"
|
||||||
{{ aggregationTypesTranslations.get(aggregationTypes[aggregation]) | translate }}
|
(ngModelChange)="onHideAggregationChanged()"></mat-checkbox>
|
||||||
</mat-option>
|
</section>
|
||||||
</mat-select>
|
<section fxFlex fxLayout="column" [fxShow]="isEdit || !timewindow.hideAggregation">
|
||||||
</mat-form-field>
|
<mat-form-field>
|
||||||
<div *ngIf="timewindowForm.get('aggregation').get('type').value === aggregationTypes.NONE"
|
<mat-label translate>aggregation.function</mat-label>
|
||||||
class="limit-slider-container"
|
<mat-select matInput formControlName="type" style="min-width: 150px;">
|
||||||
fxLayout="row" fxLayoutAlign="start center">
|
<mat-option *ngFor="let aggregation of aggregations" [value]="aggregation">
|
||||||
<span translate>aggregation.limit</span>
|
{{ aggregationTypesTranslations.get(aggregationTypes[aggregation]) | translate }}
|
||||||
<mat-slider fxFlex formControlName="limit"
|
</mat-option>
|
||||||
thumbLabel
|
</mat-select>
|
||||||
[value]="timewindowForm.get('aggregation').get('limit').value"
|
</mat-form-field>
|
||||||
min="{{minDatapointsLimit()}}"
|
</section>
|
||||||
max="{{maxDatapointsLimit()}}">
|
</section>
|
||||||
</mat-slider>
|
<section fxLayout="row" [fxShow]="timewindowForm.get('aggregation').get('type').value === aggregationTypes.NONE">
|
||||||
<mat-form-field style="max-width: 80px;">
|
<section fxLayout="column" [fxShow]="isEdit">
|
||||||
<input matInput formControlName="limit" type="number" step="1"
|
<label class="tb-small hide-label" translate>timewindow.hide</label>
|
||||||
[value]="timewindowForm.get('aggregation').get('limit').value"
|
<mat-checkbox [ngModelOptions]="{standalone: true}" [(ngModel)]="timewindow.hideAggInterval"
|
||||||
min="{{minDatapointsLimit()}}"
|
(ngModelChange)="onHideAggIntervalChanged()"></mat-checkbox>
|
||||||
max="{{maxDatapointsLimit()}}"/>
|
</section>
|
||||||
</mat-form-field>
|
<section fxLayout="column" [fxShow]="isEdit || !timewindow.hideAggInterval">
|
||||||
</div>
|
<div class="limit-slider-container"
|
||||||
|
fxLayout="row" fxLayoutAlign="start center">
|
||||||
|
<span translate>aggregation.limit</span>
|
||||||
|
<mat-slider fxFlex formControlName="limit"
|
||||||
|
thumbLabel
|
||||||
|
[value]="timewindowForm.get('aggregation').get('limit').value"
|
||||||
|
min="{{minDatapointsLimit()}}"
|
||||||
|
max="{{maxDatapointsLimit()}}">
|
||||||
|
</mat-slider>
|
||||||
|
<mat-form-field style="max-width: 80px;">
|
||||||
|
<input matInput formControlName="limit" type="number" step="1"
|
||||||
|
[value]="timewindowForm.get('aggregation').get('limit').value"
|
||||||
|
min="{{minDatapointsLimit()}}"
|
||||||
|
max="{{maxDatapointsLimit()}}"/>
|
||||||
|
</mat-form-field>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</section>
|
||||||
</div>
|
</div>
|
||||||
<div formGroupName="realtime"
|
<div formGroupName="realtime"
|
||||||
*ngIf="aggregation && timewindowForm.get('aggregation').get('type').value !== aggregationTypes.NONE &&
|
*ngIf="aggregation && timewindowForm.get('aggregation').get('type').value !== aggregationTypes.NONE &&
|
||||||
timewindow.selectedTab === timewindowTypes.REALTIME" class="mat-content mat-padding" fxLayout="column">
|
timewindow.selectedTab === timewindowTypes.REALTIME" class="mat-content mat-padding" fxLayout="column">
|
||||||
<tb-timeinterval
|
<tb-timeinterval
|
||||||
formControlName="interval"
|
formControlName="interval"
|
||||||
|
[isEdit]="isEdit"
|
||||||
|
[(hideFlag)]="timewindow.hideAggInterval"
|
||||||
|
(hideFlagChange)="onHideAggIntervalChanged()"
|
||||||
[min]="minRealtimeAggInterval()" [max]="maxRealtimeAggInterval()"
|
[min]="minRealtimeAggInterval()" [max]="maxRealtimeAggInterval()"
|
||||||
predefinedName="aggregation.group-interval">
|
predefinedName="aggregation.group-interval">
|
||||||
</tb-timeinterval>
|
</tb-timeinterval>
|
||||||
@ -99,6 +131,9 @@
|
|||||||
timewindow.selectedTab === timewindowTypes.HISTORY" class="mat-content mat-padding" fxLayout="column">
|
timewindow.selectedTab === timewindowTypes.HISTORY" class="mat-content mat-padding" fxLayout="column">
|
||||||
<tb-timeinterval
|
<tb-timeinterval
|
||||||
formControlName="interval"
|
formControlName="interval"
|
||||||
|
[isEdit]="isEdit"
|
||||||
|
[(hideFlag)]="timewindow.hideAggInterval"
|
||||||
|
(hideFlagChange)="onHideAggIntervalChanged()"
|
||||||
[min]="minHistoryAggInterval()" [max]="maxHistoryAggInterval()"
|
[min]="minHistoryAggInterval()" [max]="maxHistoryAggInterval()"
|
||||||
predefinedName="aggregation.group-interval">
|
predefinedName="aggregation.group-interval">
|
||||||
</tb-timeinterval>
|
</tb-timeinterval>
|
||||||
|
|||||||
@ -30,6 +30,11 @@
|
|||||||
padding: 0 16px;
|
padding: 0 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.hide-label {
|
||||||
|
margin-bottom: 5px;
|
||||||
|
margin-right: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
.limit-slider-container {
|
.limit-slider-container {
|
||||||
>:first-child {
|
>:first-child {
|
||||||
margin-right: 16px;
|
margin-right: 16px;
|
||||||
|
|||||||
@ -48,6 +48,7 @@ export interface TimewindowPanelData {
|
|||||||
historyOnly: boolean;
|
historyOnly: boolean;
|
||||||
timewindow: Timewindow;
|
timewindow: Timewindow;
|
||||||
aggregation: boolean;
|
aggregation: boolean;
|
||||||
|
isEdit: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
@ -61,6 +62,8 @@ export class TimewindowPanelComponent extends PageComponent implements OnInit {
|
|||||||
|
|
||||||
aggregation = false;
|
aggregation = false;
|
||||||
|
|
||||||
|
isEdit = false;
|
||||||
|
|
||||||
timewindow: Timewindow;
|
timewindow: Timewindow;
|
||||||
|
|
||||||
result: Timewindow;
|
result: Timewindow;
|
||||||
@ -82,18 +85,19 @@ export class TimewindowPanelComponent extends PageComponent implements OnInit {
|
|||||||
protected store: Store<AppState>,
|
protected store: Store<AppState>,
|
||||||
public fb: FormBuilder,
|
public fb: FormBuilder,
|
||||||
private timeService: TimeService,
|
private timeService: TimeService,
|
||||||
private translate: TranslateService,
|
|
||||||
private millisecondsToTimeStringPipe: MillisecondsToTimeStringPipe,
|
|
||||||
private datePipe: DatePipe,
|
|
||||||
private overlay: Overlay,
|
|
||||||
public viewContainerRef: ViewContainerRef) {
|
public viewContainerRef: ViewContainerRef) {
|
||||||
super(store);
|
super(store);
|
||||||
this.historyOnly = data.historyOnly;
|
this.historyOnly = data.historyOnly;
|
||||||
this.timewindow = data.timewindow;
|
this.timewindow = data.timewindow;
|
||||||
this.aggregation = data.aggregation;
|
this.aggregation = data.aggregation;
|
||||||
|
this.isEdit = data.isEdit;
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
|
const hideInterval = this.timewindow.hideInterval || false;
|
||||||
|
const hideAggregation = this.timewindow.hideAggregation || false;
|
||||||
|
const hideAggInterval = this.timewindow.hideAggInterval || false;
|
||||||
|
|
||||||
this.timewindowForm = this.fb.group({
|
this.timewindowForm = this.fb.group({
|
||||||
realtime: this.fb.group(
|
realtime: this.fb.group(
|
||||||
{
|
{
|
||||||
@ -109,42 +113,46 @@ export class TimewindowPanelComponent extends PageComponent implements OnInit {
|
|||||||
),
|
),
|
||||||
history: this.fb.group(
|
history: this.fb.group(
|
||||||
{
|
{
|
||||||
historyType: [
|
historyType: this.fb.control({
|
||||||
this.timewindow.history && typeof this.timewindow.history.historyType !== 'undefined'
|
value: this.timewindow.history && typeof this.timewindow.history.historyType !== 'undefined'
|
||||||
? this.timewindow.history.historyType : HistoryWindowType.LAST_INTERVAL
|
? this.timewindow.history.historyType : HistoryWindowType.LAST_INTERVAL,
|
||||||
],
|
disabled: hideInterval
|
||||||
timewindowMs: [
|
}),
|
||||||
this.timewindow.history && typeof this.timewindow.history.timewindowMs !== 'undefined'
|
timewindowMs: this.fb.control({
|
||||||
? this.timewindow.history.timewindowMs : null
|
value: this.timewindow.history && typeof this.timewindow.history.timewindowMs !== 'undefined'
|
||||||
],
|
? this.timewindow.history.timewindowMs : null,
|
||||||
|
disabled: hideInterval
|
||||||
|
}),
|
||||||
interval: [
|
interval: [
|
||||||
this.timewindow.history && typeof this.timewindow.history.interval !== 'undefined'
|
this.timewindow.history && typeof this.timewindow.history.interval !== 'undefined'
|
||||||
? this.timewindow.history.interval : null
|
? this.timewindow.history.interval : null
|
||||||
],
|
],
|
||||||
fixedTimewindow: [
|
fixedTimewindow: this.fb.control({
|
||||||
this.timewindow.history && typeof this.timewindow.history.fixedTimewindow !== 'undefined'
|
value: this.timewindow.history && typeof this.timewindow.history.fixedTimewindow !== 'undefined'
|
||||||
? this.timewindow.history.fixedTimewindow : null
|
? this.timewindow.history.fixedTimewindow : null,
|
||||||
]
|
disabled: hideInterval
|
||||||
|
})
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
aggregation: this.fb.group(
|
aggregation: this.fb.group(
|
||||||
{
|
{
|
||||||
type: [
|
type: this.fb.control({
|
||||||
this.timewindow.aggregation && typeof this.timewindow.aggregation.type !== 'undefined'
|
value: this.timewindow.aggregation && typeof this.timewindow.aggregation.type !== 'undefined'
|
||||||
? this.timewindow.aggregation.type : null
|
? this.timewindow.aggregation.type : null,
|
||||||
],
|
disabled: hideAggregation
|
||||||
limit: [
|
}),
|
||||||
this.timewindow.aggregation && typeof this.timewindow.aggregation.limit !== 'undefined'
|
limit: this.fb.control({
|
||||||
|
value: this.timewindow.aggregation && typeof this.timewindow.aggregation.limit !== 'undefined'
|
||||||
? this.timewindow.aggregation.limit : null,
|
? this.timewindow.aggregation.limit : null,
|
||||||
[Validators.min(this.minDatapointsLimit()), Validators.max(this.maxDatapointsLimit())]
|
disabled: hideAggInterval
|
||||||
]
|
}, [Validators.min(this.minDatapointsLimit()), Validators.max(this.maxDatapointsLimit())])
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
update() {
|
update() {
|
||||||
const timewindowFormValue = this.timewindowForm.value;
|
const timewindowFormValue = this.timewindowForm.getRawValue();
|
||||||
this.timewindow.realtime = {
|
this.timewindow.realtime = {
|
||||||
timewindowMs: timewindowFormValue.realtime.timewindowMs,
|
timewindowMs: timewindowFormValue.realtime.timewindowMs,
|
||||||
interval: timewindowFormValue.realtime.interval
|
interval: timewindowFormValue.realtime.interval
|
||||||
@ -194,7 +202,7 @@ export class TimewindowPanelComponent extends PageComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
currentHistoryTimewindow() {
|
currentHistoryTimewindow() {
|
||||||
const timewindowFormValue = this.timewindowForm.value;
|
const timewindowFormValue = this.timewindowForm.getRawValue();
|
||||||
if (timewindowFormValue.history.historyType === HistoryWindowType.LAST_INTERVAL) {
|
if (timewindowFormValue.history.historyType === HistoryWindowType.LAST_INTERVAL) {
|
||||||
return timewindowFormValue.history.timewindowMs;
|
return timewindowFormValue.history.timewindowMs;
|
||||||
} else {
|
} else {
|
||||||
@ -203,4 +211,35 @@ export class TimewindowPanelComponent extends PageComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onHideIntervalChanged() {
|
||||||
|
if (this.timewindow.hideInterval) {
|
||||||
|
this.timewindowForm.get('history').get('historyType').disable({emitEvent: false});
|
||||||
|
this.timewindowForm.get('history').get('timewindowMs').disable({emitEvent: false});
|
||||||
|
this.timewindowForm.get('history').get('fixedTimewindow').disable({emitEvent: false});
|
||||||
|
} else {
|
||||||
|
this.timewindowForm.get('history').get('historyType').enable({emitEvent: false});
|
||||||
|
this.timewindowForm.get('history').get('timewindowMs').enable({emitEvent: false});
|
||||||
|
this.timewindowForm.get('history').get('fixedTimewindow').enable({emitEvent: false});
|
||||||
|
}
|
||||||
|
this.timewindowForm.markAsDirty();
|
||||||
|
}
|
||||||
|
|
||||||
|
onHideAggregationChanged() {
|
||||||
|
if (this.timewindow.hideAggregation) {
|
||||||
|
this.timewindowForm.get('aggregation').get('type').disable({emitEvent: false});
|
||||||
|
} else {
|
||||||
|
this.timewindowForm.get('aggregation').get('type').enable({emitEvent: false});
|
||||||
|
}
|
||||||
|
this.timewindowForm.markAsDirty();
|
||||||
|
}
|
||||||
|
|
||||||
|
onHideAggIntervalChanged() {
|
||||||
|
if (this.timewindow.hideAggInterval) {
|
||||||
|
this.timewindowForm.get('aggregation').get('limit').disable({emitEvent: false});
|
||||||
|
} else {
|
||||||
|
this.timewindowForm.get('aggregation').get('limit').enable({emitEvent: false});
|
||||||
|
}
|
||||||
|
this.timewindowForm.markAsDirty();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,7 +15,7 @@
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
|
|
||||||
-->
|
-->
|
||||||
<button *ngIf="asButton" cdkOverlayOrigin #timewindowPanelOrigin="cdkOverlayOrigin" [disabled]="disabled"
|
<button *ngIf="asButton" cdkOverlayOrigin #timewindowPanelOrigin="cdkOverlayOrigin" [disabled]="timewindowDisabled"
|
||||||
type="button"
|
type="button"
|
||||||
mat-raised-button color="primary" (click)="openEditMode()">
|
mat-raised-button color="primary" (click)="openEditMode()">
|
||||||
<mat-icon class="material-icons">query_builder</mat-icon>
|
<mat-icon class="material-icons">query_builder</mat-icon>
|
||||||
@ -23,7 +23,7 @@
|
|||||||
</button>
|
</button>
|
||||||
<section *ngIf="!asButton" cdkOverlayOrigin #timewindowPanelOrigin="cdkOverlayOrigin"
|
<section *ngIf="!asButton" cdkOverlayOrigin #timewindowPanelOrigin="cdkOverlayOrigin"
|
||||||
class="tb-timewindow" fxLayout="row" fxLayoutAlign="start center">
|
class="tb-timewindow" fxLayout="row" fxLayoutAlign="start center">
|
||||||
<button *ngIf="direction === 'left'" [disabled]="disabled" mat-button mat-icon-button class="tb-mat-32"
|
<button *ngIf="direction === 'left'" [disabled]="timewindowDisabled" mat-button mat-icon-button class="tb-mat-32"
|
||||||
type="button"
|
type="button"
|
||||||
(click)="openEditMode()"
|
(click)="openEditMode()"
|
||||||
matTooltip="{{ 'timewindow.edit' | translate }}"
|
matTooltip="{{ 'timewindow.edit' | translate }}"
|
||||||
@ -36,7 +36,7 @@
|
|||||||
[matTooltipPosition]="tooltipPosition">
|
[matTooltipPosition]="tooltipPosition">
|
||||||
{{innerValue?.displayValue}}
|
{{innerValue?.displayValue}}
|
||||||
</span>
|
</span>
|
||||||
<button *ngIf="direction === 'right'" [disabled]="disabled" mat-button mat-icon-button class="tb-mat-32"
|
<button *ngIf="direction === 'right'" [disabled]="timewindowDisabled" mat-button mat-icon-button class="tb-mat-32"
|
||||||
type="button"
|
type="button"
|
||||||
(click)="openEditMode()"
|
(click)="openEditMode()"
|
||||||
matTooltip="{{ 'timewindow.edit' | translate }}"
|
matTooltip="{{ 'timewindow.edit' | translate }}"
|
||||||
|
|||||||
@ -53,6 +53,7 @@ import { WINDOW } from '@core/services/window.service';
|
|||||||
import { TimeService } from '@core/services/time.service';
|
import { TimeService } from '@core/services/time.service';
|
||||||
import { TooltipPosition } from '@angular/material/tooltip';
|
import { TooltipPosition } from '@angular/material/tooltip';
|
||||||
import { deepClone } from '@core/utils';
|
import { deepClone } from '@core/utils';
|
||||||
|
import { coerceBooleanProperty } from '@angular/cdk/coercion';
|
||||||
|
|
||||||
// @dynamic
|
// @dynamic
|
||||||
@Component({
|
@Component({
|
||||||
@ -73,7 +74,7 @@ export class TimewindowComponent implements OnInit, OnDestroy, ControlValueAcces
|
|||||||
|
|
||||||
@Input()
|
@Input()
|
||||||
set historyOnly(val) {
|
set historyOnly(val) {
|
||||||
this.historyOnlyValue = true;
|
this.historyOnlyValue = coerceBooleanProperty(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
get historyOnly() {
|
get historyOnly() {
|
||||||
@ -84,7 +85,7 @@ export class TimewindowComponent implements OnInit, OnDestroy, ControlValueAcces
|
|||||||
|
|
||||||
@Input()
|
@Input()
|
||||||
set aggregation(val) {
|
set aggregation(val) {
|
||||||
this.aggregationValue = true;
|
this.aggregationValue = coerceBooleanProperty(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
get aggregation() {
|
get aggregation() {
|
||||||
@ -95,7 +96,7 @@ export class TimewindowComponent implements OnInit, OnDestroy, ControlValueAcces
|
|||||||
|
|
||||||
@Input()
|
@Input()
|
||||||
set isToolbar(val) {
|
set isToolbar(val) {
|
||||||
this.isToolbarValue = true;
|
this.isToolbarValue = coerceBooleanProperty(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
get isToolbar() {
|
get isToolbar() {
|
||||||
@ -106,13 +107,25 @@ export class TimewindowComponent implements OnInit, OnDestroy, ControlValueAcces
|
|||||||
|
|
||||||
@Input()
|
@Input()
|
||||||
set asButton(val) {
|
set asButton(val) {
|
||||||
this.asButtonValue = true;
|
this.asButtonValue = coerceBooleanProperty(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
get asButton() {
|
get asButton() {
|
||||||
return this.asButtonValue;
|
return this.asButtonValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isEditValue = false;
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
set isEdit(val) {
|
||||||
|
this.isEditValue = coerceBooleanProperty(val);
|
||||||
|
this.timewindowDisabled = this.isTimewindowDisabled();
|
||||||
|
}
|
||||||
|
|
||||||
|
get isEdit() {
|
||||||
|
return this.isEditValue;
|
||||||
|
}
|
||||||
|
|
||||||
@Input()
|
@Input()
|
||||||
direction: 'left' | 'right' = 'left';
|
direction: 'left' | 'right' = 'left';
|
||||||
|
|
||||||
@ -125,6 +138,8 @@ export class TimewindowComponent implements OnInit, OnDestroy, ControlValueAcces
|
|||||||
|
|
||||||
innerValue: Timewindow;
|
innerValue: Timewindow;
|
||||||
|
|
||||||
|
timewindowDisabled: boolean;
|
||||||
|
|
||||||
private propagateChange = (_: any) => {};
|
private propagateChange = (_: any) => {};
|
||||||
|
|
||||||
constructor(private translate: TranslateService,
|
constructor(private translate: TranslateService,
|
||||||
@ -145,7 +160,7 @@ export class TimewindowComponent implements OnInit, OnDestroy, ControlValueAcces
|
|||||||
}
|
}
|
||||||
|
|
||||||
openEditMode() {
|
openEditMode() {
|
||||||
if (this.disabled) {
|
if (this.timewindowDisabled) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const isGtSm = this.breakpointObserver.isMatched(MediaBreakpoints['gt-sm']);
|
const isGtSm = this.breakpointObserver.isMatched(MediaBreakpoints['gt-sm']);
|
||||||
@ -212,7 +227,8 @@ export class TimewindowComponent implements OnInit, OnDestroy, ControlValueAcces
|
|||||||
{
|
{
|
||||||
timewindow: deepClone(this.innerValue),
|
timewindow: deepClone(this.innerValue),
|
||||||
historyOnly: this.historyOnly,
|
historyOnly: this.historyOnly,
|
||||||
aggregation: this.aggregation
|
aggregation: this.aggregation,
|
||||||
|
isEdit: this.isEdit
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -220,6 +236,7 @@ export class TimewindowComponent implements OnInit, OnDestroy, ControlValueAcces
|
|||||||
componentRef.onDestroy(() => {
|
componentRef.onDestroy(() => {
|
||||||
if (componentRef.instance.result) {
|
if (componentRef.instance.result) {
|
||||||
this.innerValue = componentRef.instance.result;
|
this.innerValue = componentRef.instance.result;
|
||||||
|
this.timewindowDisabled = this.isTimewindowDisabled();
|
||||||
this.updateDisplayValue();
|
this.updateDisplayValue();
|
||||||
this.notifyChanged();
|
this.notifyChanged();
|
||||||
}
|
}
|
||||||
@ -243,10 +260,12 @@ export class TimewindowComponent implements OnInit, OnDestroy, ControlValueAcces
|
|||||||
|
|
||||||
setDisabledState(isDisabled: boolean): void {
|
setDisabledState(isDisabled: boolean): void {
|
||||||
this.disabled = isDisabled;
|
this.disabled = isDisabled;
|
||||||
|
this.timewindowDisabled = this.isTimewindowDisabled();
|
||||||
}
|
}
|
||||||
|
|
||||||
writeValue(obj: Timewindow): void {
|
writeValue(obj: Timewindow): void {
|
||||||
this.innerValue = initModelFromDefaultTimewindow(obj, this.timeService);
|
this.innerValue = initModelFromDefaultTimewindow(obj, this.timeService);
|
||||||
|
this.timewindowDisabled = this.isTimewindowDisabled();
|
||||||
this.updateDisplayValue();
|
this.updateDisplayValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -276,4 +295,10 @@ export class TimewindowComponent implements OnInit, OnDestroy, ControlValueAcces
|
|||||||
return this.isToolbar && !this.breakpointObserver.isMatched(MediaBreakpoints['gt-md']);
|
return this.isToolbar && !this.breakpointObserver.isMatched(MediaBreakpoints['gt-md']);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private isTimewindowDisabled(): boolean {
|
||||||
|
return this.disabled ||
|
||||||
|
(!this.isEdit && (!this.innerValue || this.innerValue.hideInterval &&
|
||||||
|
(!this.aggregation || this.innerValue.hideAggregation && this.innerValue.hideAggInterval)));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -79,6 +79,9 @@ export interface Aggregation {
|
|||||||
|
|
||||||
export interface Timewindow {
|
export interface Timewindow {
|
||||||
displayValue?: string;
|
displayValue?: string;
|
||||||
|
hideInterval?: boolean;
|
||||||
|
hideAggregation?: boolean;
|
||||||
|
hideAggInterval?: boolean;
|
||||||
selectedTab?: TimewindowType;
|
selectedTab?: TimewindowType;
|
||||||
realtime?: IntervalWindow;
|
realtime?: IntervalWindow;
|
||||||
history?: HistoryWindow;
|
history?: HistoryWindow;
|
||||||
@ -115,9 +118,12 @@ export function historyInterval(timewindowMs: number): Timewindow {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function defaultTimewindow(timeService: TimeService): Timewindow {
|
export function defaultTimewindow(timeService: TimeService): Timewindow {
|
||||||
const currentTime = Date.now();
|
const currentTime = moment().valueOf();
|
||||||
const timewindow: Timewindow = {
|
const timewindow: Timewindow = {
|
||||||
displayValue: '',
|
displayValue: '',
|
||||||
|
hideInterval: false,
|
||||||
|
hideAggregation: false,
|
||||||
|
hideAggInterval: false,
|
||||||
selectedTab: TimewindowType.REALTIME,
|
selectedTab: TimewindowType.REALTIME,
|
||||||
realtime: {
|
realtime: {
|
||||||
interval: SECOND,
|
interval: SECOND,
|
||||||
@ -143,6 +149,9 @@ export function defaultTimewindow(timeService: TimeService): Timewindow {
|
|||||||
export function initModelFromDefaultTimewindow(value: Timewindow, timeService: TimeService): Timewindow {
|
export function initModelFromDefaultTimewindow(value: Timewindow, timeService: TimeService): Timewindow {
|
||||||
const model = defaultTimewindow(timeService);
|
const model = defaultTimewindow(timeService);
|
||||||
if (value) {
|
if (value) {
|
||||||
|
model.hideInterval = value.hideInterval;
|
||||||
|
model.hideAggregation = value.hideAggregation;
|
||||||
|
model.hideAggInterval = value.hideAggInterval;
|
||||||
if (isUndefined(value.selectedTab)) {
|
if (isUndefined(value.selectedTab)) {
|
||||||
if (value.realtime) {
|
if (value.realtime) {
|
||||||
model.selectedTab = TimewindowType.REALTIME;
|
model.selectedTab = TimewindowType.REALTIME;
|
||||||
@ -206,6 +215,9 @@ export function toHistoryTimewindow(timewindow: Timewindow, startTimeMs: number,
|
|||||||
limit = timeService.getMaxDatapointsLimit();
|
limit = timeService.getMaxDatapointsLimit();
|
||||||
}
|
}
|
||||||
const historyTimewindow: Timewindow = {
|
const historyTimewindow: Timewindow = {
|
||||||
|
hideInterval: timewindow.hideInterval || false,
|
||||||
|
hideAggregation: timewindow.hideAggregation || false,
|
||||||
|
hideAggInterval: timewindow.hideAggInterval || false,
|
||||||
selectedTab: TimewindowType.HISTORY,
|
selectedTab: TimewindowType.HISTORY,
|
||||||
history: {
|
history: {
|
||||||
historyType: HistoryWindowType.FIXED,
|
historyType: HistoryWindowType.FIXED,
|
||||||
@ -319,6 +331,9 @@ export function createTimewindowForComparison(subscriptionTimewindow: Subscripti
|
|||||||
|
|
||||||
export function cloneSelectedTimewindow(timewindow: Timewindow): Timewindow {
|
export function cloneSelectedTimewindow(timewindow: Timewindow): Timewindow {
|
||||||
const cloned: Timewindow = {};
|
const cloned: Timewindow = {};
|
||||||
|
cloned.hideInterval = timewindow.hideInterval || false;
|
||||||
|
cloned.hideAggregation = timewindow.hideAggregation || false;
|
||||||
|
cloned.hideAggInterval = timewindow.hideAggInterval || false;
|
||||||
if (isDefined(timewindow.selectedTab)) {
|
if (isDefined(timewindow.selectedTab)) {
|
||||||
cloned.selectedTab = timewindow.selectedTab;
|
cloned.selectedTab = timewindow.selectedTab;
|
||||||
if (timewindow.selectedTab === TimewindowType.REALTIME) {
|
if (timewindow.selectedTab === TimewindowType.REALTIME) {
|
||||||
|
|||||||
@ -345,6 +345,7 @@ export interface WidgetConfig {
|
|||||||
showTitleIcon?: boolean;
|
showTitleIcon?: boolean;
|
||||||
iconColor?: string;
|
iconColor?: string;
|
||||||
iconSize?: string;
|
iconSize?: string;
|
||||||
|
titleTooltip?: string;
|
||||||
dropShadow?: boolean;
|
dropShadow?: boolean;
|
||||||
enableFullscreen?: boolean;
|
enableFullscreen?: boolean;
|
||||||
useDashboardTimewindow?: boolean;
|
useDashboardTimewindow?: boolean;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user