Angular 18 migration

This commit is contained in:
Igor Kulikov 2024-10-02 19:49:20 +03:00
parent d9dad92c2f
commit 8273c3fafd
23 changed files with 776 additions and 570 deletions

View File

@ -12,31 +12,34 @@
},
"private": true,
"dependencies": {
"@angular/animations": "^18.2.6",
"@angular/cdk": "^18.2.6",
"@angular/common": "^18.2.6",
"@angular/compiler": "^18.2.6",
"@angular/core": "^18.2.6",
"@angular/animations": "18.2.6",
"@angular/cdk": "18.2.6",
"@angular/common": "18.2.6",
"@angular/compiler": "18.2.6",
"@angular/core": "18.2.6",
"@angular/flex-layout": "^15.0.0-beta.42",
"@angular/forms": "^18.2.6",
"@angular/material": "^18.2.6",
"@angular/platform-browser": "^18.2.6",
"@angular/platform-browser-dynamic": "^18.2.6",
"@angular/router": "^18.2.6",
"@angular/forms": "18.2.6",
"@angular/material": "18.2.6",
"@angular/platform-browser": "18.2.6",
"@angular/platform-browser-dynamic": "18.2.6",
"@angular/router": "18.2.6",
"@auth0/angular-jwt": "^5.2.0",
"@date-io/core": "1.3.7",
"@date-io/date-fns": "1.3.7",
"@emotion/react": "11.13.3",
"@emotion/styled": "11.13.0",
"@flowjs/flow.js": "^2.14.1",
"@flowjs/ngx-flow": "~0.8.1",
"@fortawesome/fontawesome-svg-core": "^6.6.0",
"@geoman-io/leaflet-geoman-free": "2.14.2",
"@iplab/ngx-color-picker": "^18.0.1",
"@mat-datetimepicker/core": "~14.0.0",
"@material-ui/core": "4.12.3",
"@material-ui/icons": "4.11.2",
"@material-ui/pickers": "3.3.10",
"@mdi/svg": "^7.4.47",
"@messageformat/core": "^3.3.0",
"@mui/icons-material": "6.1.1",
"@mui/lab": "6.0.0-beta.10",
"@mui/material": "6.1.1",
"@mui/styles": "6.1.1",
"@mui/system": "6.1.1",
"@mui/x-date-pickers": "7.18.0",
"@ngrx/effects": "^18.0.2",
"@ngrx/store": "^18.0.2",
"@ngrx/store-devtools": "^18.0.2",
@ -45,14 +48,13 @@
"@svgdotjs/svg.js": "^3.2.4",
"@svgdotjs/svg.panzoom.js": "^2.1.2",
"@tinymce/tinymce-angular": "^8.0.1",
"ace-builds": "1.4.13",
"ace-builds": "1.36.2",
"ace-diff": "^3.0.3",
"angular-gridster2": "~18.0.1",
"angular2-hotkeys": "^16.0.1",
"canvas-gauges": "^2.1.7",
"core-js": "^3.38.1",
"date-fns": "2.0.0-alpha.27",
"dayjs": "1.11.4",
"dayjs": "1.11.13",
"echarts": "https://github.com/thingsboard/echarts/archive/5.5.0-TB.tar.gz",
"flot": "https://github.com/thingsboard/flot.git#0.9-work",
"flot.curvedlines": "https://github.com/MichaelZinsmaier/CurvedLines.git#master",
@ -87,11 +89,11 @@
"prop-types": "^15.8.1",
"qrcode": "^1.5.4",
"raphael": "^2.3.0",
"rc-select": "13.2.1",
"react": "17.0.2",
"react-ace": "9.5.0",
"react-dom": "17.0.2",
"react-dropzone": "^11.4.2",
"rc-select": "14.15.2",
"react": "18.3.1",
"react-ace": "12.0.0",
"react-dom": "18.3.1",
"react-dropzone": "14.2.3",
"reactcss": "^1.2.3",
"rxjs": "~7.8.1",
"schema-inspector": "^2.1.0",
@ -110,18 +112,18 @@
},
"devDependencies": {
"@angular-builders/custom-webpack": "~18.0.0",
"@angular-devkit/build-angular": "^18.2.6",
"@angular-devkit/core": "^18.2.6",
"@angular-devkit/schematics": "^18.2.6",
"@angular-devkit/build-angular": "18.2.7",
"@angular-devkit/core": "18.2.7",
"@angular-devkit/schematics": "18.2.7",
"@angular-eslint/builder": "18.3.1",
"@angular-eslint/eslint-plugin": "18.3.1",
"@angular-eslint/eslint-plugin-template": "18.3.1",
"@angular-eslint/schematics": "18.3.1",
"@angular-eslint/template-parser": "18.3.1",
"@angular/cli": "^18.2.6",
"@angular/compiler-cli": "^18.2.6",
"@angular/language-service": "^18.2.6",
"@ngtools/webpack": "18.2.6",
"@angular/cli": "18.2.7",
"@angular/compiler-cli": "18.2.6",
"@angular/language-service": "18.2.6",
"@ngtools/webpack": "18.2.7",
"@types/ace-diff": "^2.1.1",
"@types/canvas-gauges": "^2.1.4",
"@types/flot": "^0.0.32",
@ -138,8 +140,8 @@
"@types/lodash": "^4.17.9",
"@types/node": "~18.15.11",
"@types/raphael": "^2.3.2",
"@types/react": "17.0.37",
"@types/react-dom": "17.0.11",
"@types/react": "18.3.10",
"@types/react-dom": "18.3.0",
"@types/systemjs": "6.13.1",
"@types/tinycolor2": "^1.4.6",
"@types/tooltipster": "^0.0.35",
@ -161,10 +163,9 @@
"webpack": "5.95.0"
},
"resolutions": {
"@types/react": "17.0.37",
"@date-io/core": "1.3.7",
"rc-virtual-list": "3.4.13",
"ace-builds": "1.4.13",
"@types/react": "18.3.10",
"rc-virtual-list": "3.5.2",
"ace-builds": "1.36.2",
"tinymce": "6.8.4"
}
}

View File

@ -42,7 +42,6 @@ import { RafService } from '@core/services/raf.service';
import { EntityAliases } from '@shared/models/alias.models';
import { EntityInfo } from '@app/shared/models/entity.models';
import { IDashboardComponent } from '@home/models/dashboard-component.models';
import moment_ from 'moment';
import {
AlarmData,
AlarmDataPageLink,

View File

@ -78,7 +78,6 @@ import {
SaveWidgetTypeAsDialogResult
} from '@home/pages/widget/save-widget-type-as-dialog.component';
import { WidgetService } from '@core/http/widget.service';
import { de } from 'date-fns/locale';
@Component({
selector: 'tb-scada-symbol',

View File

@ -18,11 +18,11 @@ import {
ChangeDetectorRef,
Component,
ElementRef,
forwardRef, Injector,
forwardRef,
Input,
OnChanges,
OnDestroy,
OnInit, Renderer2,
Renderer2,
SimpleChanges,
ViewChild, ViewContainerRef,
ViewEncapsulation
@ -32,20 +32,15 @@ import { coerceBooleanProperty } from '@angular/cdk/coercion';
import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state';
import { deepClone, isString } from '@app/core/utils';
import { TranslateService } from '@ngx-translate/core';
import { JsonFormProps } from './react/json-form.models';
import inspector from 'schema-inspector';
import tinycolor from 'tinycolor2';
import { DialogService } from '@app/core/services/dialog.service';
// import * as React from 'react';
// import * as ReactDOM from 'react-dom';
// import ReactSchemaForm from './react/json-form-react';
import JsonFormUtils from './react/json-form-utils';
import { JsonFormComponentData } from './json-form-component.models';
import { GroupInfo } from '@shared/models/widget.models';
import { Observable } from 'rxjs/internal/Observable';
import { forkJoin, from } from 'rxjs';
import { MouseEvent } from 'react';
import { TbPopoverService } from '@shared/components/popover.service';
@Component({
@ -66,7 +61,7 @@ import { TbPopoverService } from '@shared/components/popover.service';
],
encapsulation: ViewEncapsulation.None
})
export class JsonFormComponent implements OnInit, ControlValueAccessor, Validator, OnChanges, OnDestroy {
export class JsonFormComponent implements ControlValueAccessor, Validator, OnChanges, OnDestroy {
@ViewChild('reactRoot', {static: true})
reactRootElmRef: ElementRef<HTMLElement>;
@ -109,13 +104,14 @@ export class JsonFormComponent implements OnInit, ControlValueAccessor, Validato
isFullscreen = false;
fullscreenFinishFn: (el: Element) => void;
private reactRoot: any;
private propagateChange = null;
private propagateChangePending = false;
private writingValue = false;
private updateViewPending = false;
constructor(public elementRef: ElementRef,
private translate: TranslateService,
private dialogs: DialogService,
private popoverService: TbPopoverService,
private renderer: Renderer2,
@ -124,9 +120,6 @@ export class JsonFormComponent implements OnInit, ControlValueAccessor, Validato
private cd: ChangeDetectorRef) {
}
ngOnInit(): void {
}
ngOnDestroy(): void {
this.destroyReactSchemaForm();
}
@ -269,33 +262,25 @@ export class JsonFormComponent implements OnInit, ControlValueAccessor, Validato
}
// import ReactSchemaForm from './react/json-form-react';
const reactSchemaFormObservables: Observable<any>[] = [];
reactSchemaFormObservables.push(from(import('react')));
reactSchemaFormObservables.push(from(import('react-dom')));
reactSchemaFormObservables.push(from(import('./react/json-form-react')));
const reactSchemaFormObservables: Observable<any>[] = [
from(import('react')),
from(import('react-dom')),
from(import('react-dom/client')),
from(import('./react/json-form-react'))
];
forkJoin(reactSchemaFormObservables).subscribe(
(modules) => {
const react = modules[0];
const reactDom = modules[1];
const jsonFormReact = modules[2].default;
reactDom.render(react.createElement(jsonFormReact, this.formProps), this.reactRootElmRef.nativeElement);
const react = modules[0];
const reactDomClient = modules[2];
const jsonFormReact = modules[3].default;
this.reactRoot = reactDomClient.createRoot(this.reactRootElmRef.nativeElement);
this.reactRoot.render(react.createElement(jsonFormReact, this.formProps));
}
);
/* import('./react/json-form-react').then(
(mod) => {
ReactDOM.render(React.createElement(mod.default, this.formProps), this.reactRootElmRef.nativeElement);
}
);*/
// ReactDOM.render(React.createElement(ReactSchemaForm, this.formProps), this.reactRootElmRef.nativeElement);
}
private destroyReactSchemaForm() {
import('react-dom').then(
(reactDom) => {
reactDom.unmountComponentAtNode(this.reactRootElmRef.nativeElement);
}
);
// ReactDOM.unmountComponentAtNode(this.reactRootElmRef.nativeElement);
this.reactRoot?.unmount();
}
private validateModel(): boolean {

View File

@ -17,16 +17,16 @@ import * as React from 'react';
import * as ReactDOM from 'react-dom';
import ThingsboardBaseComponent from './json-form-base-component';
import reactCSS from 'reactcss';
import Button from '@material-ui/core/Button';
import Button from '@mui/material/Button';
import { JsonFormFieldProps, JsonFormFieldState } from '@shared/components/json-form/react/json-form.models';
import { IEditorProps } from 'react-ace/src/types';
import { mergeMap } from 'rxjs/operators';
import { getAce } from '@shared/models/ace/ace.models';
import { from } from 'rxjs';
import { Observable } from 'rxjs/internal/Observable';
import { CircularProgress, IconButton } from '@material-ui/core';
import { CircularProgress, IconButton } from '@mui/material';
import { MouseEvent } from 'react';
import { Help, HelpOutline } from '@material-ui/icons';
import { Help, HelpOutline } from '@mui/icons-material';
const ReactAce = React.lazy(() => {
return getAce().pipe(

View File

@ -16,12 +16,12 @@
import * as React from 'react';
import JsonFormUtils from './json-form-utils';
import ThingsboardBaseComponent from './json-form-base-component';
import Button from '@material-ui/core/Button';
import Button from '@mui/material/Button';
import _ from 'lodash';
import IconButton from '@material-ui/core/IconButton';
import Clear from '@material-ui/icons/Clear';
import Add from '@material-ui/icons/Add';
import Tooltip from '@material-ui/core/Tooltip';
import IconButton from '@mui/material/IconButton';
import Clear from '@mui/icons-material/Clear';
import Add from '@mui/icons-material/Add';
import Tooltip from '@mui/material/Tooltip';
import {
JsonFormData,
JsonFormFieldProps,

View File

@ -42,8 +42,10 @@ export default ThingsboardBaseComponent => class<P extends JsonFormFieldProps>
onChangeValidate(e, forceUpdate?: boolean) {
let value = null;
if (this.props.form.schema.type === 'integer' || this.props.form.schema.type === 'number') {
if (e.target.value === null || e.target.value === '') {
if (!e || e.target?.value === null || e.target?.value === '') {
value = undefined;
} else if (typeof e === 'number') {
value = Number(e);
} else if (e.target.value.indexOf('.') === -1) {
value = parseInt(e.target.value, 10);
} else {

View File

@ -15,9 +15,9 @@
*/
import * as React from 'react';
import ThingsboardBaseComponent from './json-form-base-component';
import Checkbox from '@material-ui/core/Checkbox';
import Checkbox from '@mui/material/Checkbox';
import { JsonFormFieldProps, JsonFormFieldState } from './json-form.models.js';
import FormControlLabel from '@material-ui/core/FormControlLabel';
import FormControlLabel from '@mui/material/FormControlLabel';
class ThingsboardCheckbox extends React.Component<JsonFormFieldProps, JsonFormFieldState> {
render() {
@ -26,6 +26,7 @@ class ThingsboardCheckbox extends React.Component<JsonFormFieldProps, JsonFormFi
<FormControlLabel
control={
<Checkbox
color={'secondary'}
name={this.props.form.key.slice(-1)[0] + ''}
value={this.props.form.key.slice(-1)[0]}
checked={this.props.value || false}

View File

@ -14,15 +14,14 @@
* 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 tinycolor from 'tinycolor2';
import TextField from '@material-ui/core/TextField';
import TextField from '@mui/material/TextField';
import { JsonFormFieldProps, JsonFormFieldState } from '@shared/components/json-form/react/json-form.models';
import IconButton from '@material-ui/core/IconButton';
import Clear from '@material-ui/icons/Clear';
import Tooltip from '@material-ui/core/Tooltip';
import IconButton from '@mui/material/IconButton';
import Clear from '@mui/icons-material/Clear';
import Tooltip from '@mui/material/Tooltip';
interface ThingsboardColorState extends JsonFormFieldState {
color: tinycolor.ColorFormats.RGBA | null;
@ -31,6 +30,8 @@ interface ThingsboardColorState extends JsonFormFieldState {
class ThingsboardColor extends React.Component<JsonFormFieldProps, ThingsboardColorState> {
containerRef = React.createRef<HTMLDivElement>();
constructor(props) {
super(props);
this.onBlur = this.onBlur.bind(this);
@ -55,17 +56,17 @@ class ThingsboardColor extends React.Component<JsonFormFieldProps, ThingsboardCo
}
componentDidMount() {
const node = ReactDOM.findDOMNode(this);
const node = this.containerRef.current;
const colContainer = $(node).children('#color-container');
colContainer.click((event) => {
colContainer.click(() => {
if (!this.props.form.readonly) {
this.onSwatchClick(event);
this.onSwatchClick();
}
});
}
componentWillUnmount() {
const node = ReactDOM.findDOMNode(this);
const node = this.containerRef.current;
const colContainer = $(node).children('#color-container');
colContainer.off( 'click' );
}
@ -91,7 +92,7 @@ class ThingsboardColor extends React.Component<JsonFormFieldProps, ThingsboardCo
});
}
onSwatchClick(event) {
onSwatchClick() {
this.props.onColorClick(this.props.form.key, this.state.color,
(color) => {
this.onValueChanged(color);
@ -99,7 +100,7 @@ class ThingsboardColor extends React.Component<JsonFormFieldProps, ThingsboardCo
);
}
onClear(event) {
onClear(event: React.MouseEvent) {
if (event) {
event.stopPropagation();
}
@ -159,12 +160,13 @@ class ThingsboardColor extends React.Component<JsonFormFieldProps, ThingsboardCo
}
return (
<div style={ styles.container }>
<div ref={this.containerRef} style={ styles.container }>
<div id='color-container' style={ styles.colorContainer }>
<div className='tb-color-preview' style={ styles.swatch }>
<div className='tb-color-result' style={ styles.color }/>
</div>
<TextField
variant={'standard'}
className={fieldClass}
label={this.props.form.title}
error={!this.props.valid}

View File

@ -15,9 +15,10 @@
*/
import * as React from 'react';
import ThingsboardBaseComponent from './json-form-base-component';
import DateFnsUtils from '@date-io/date-fns';
import { KeyboardDatePicker, MuiPickersUtilsProvider } from '@material-ui/pickers';
import { AdapterMoment } from '@mui/x-date-pickers/AdapterMoment'
import { LocalizationProvider, DatePicker } from '@mui/x-date-pickers';
import { JsonFormFieldProps, JsonFormFieldState } from '@shared/components/json-form/react/json-form.models';
import moment from 'moment';
interface ThingsboardDateState extends JsonFormFieldState {
currentValue: Date | null;
@ -38,11 +39,11 @@ class ThingsboardDate extends React.Component<JsonFormFieldProps, ThingsboardDat
}
onDatePicked(date: Date | null) {
onDatePicked(date: moment.Moment | null) {
this.setState({
currentValue: date
currentValue: date?.toDate()
});
this.props.onChangeValidate(date ? date.getTime() : null);
this.props.onChangeValidate(date ? date.valueOf() : null);
}
render() {
@ -56,22 +57,20 @@ class ThingsboardDate extends React.Component<JsonFormFieldProps, ThingsboardDat
}
return (
<MuiPickersUtilsProvider utils={DateFnsUtils}>
<LocalizationProvider dateAdapter={AdapterMoment}>
<div style={{width: '100%', display: 'block'}}>
<KeyboardDatePicker
disableToolbar
variant='inline'
format='MM/dd/yyyy'
margin='normal'
<DatePicker
format='MM/DD/YYYY'
className={fieldClass}
label={this.props.form.title}
value={this.state.currentValue}
value={moment(this.state.currentValue?.valueOf())}
onChange={this.onDatePicked}
disabled={this.props.form.readonly}
style={this.props.form.style || {width: '100%'}}/>
sx={this.props.form.style || {width: '100%'}}
/>
</div>
</MuiPickersUtilsProvider>
</LocalizationProvider>
);
}
}

View File

@ -17,12 +17,12 @@ 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 TextField from '@mui/material/TextField';
import IconButton from '@mui/material/IconButton';
import { JsonFormFieldProps, JsonFormFieldState } from '@shared/components/json-form/react/json-form.models';
import Clear from '@material-ui/icons/Clear';
import Icon from '@material-ui/core/Icon';
import Tooltip from '@material-ui/core/Tooltip';
import Clear from '@mui/icons-material/Clear';
import Icon from '@mui/material/Icon';
import Tooltip from '@mui/material/Tooltip';
interface ThingsboardIconState extends JsonFormFieldState {
icon: string | null;

View File

@ -17,9 +17,9 @@ import React from 'react';
import Dropzone from 'react-dropzone';
import ThingsboardBaseComponent from './json-form-base-component';
import { JsonFormFieldProps, JsonFormFieldState } from '@shared/components/json-form/react/json-form.models';
import IconButton from '@material-ui/core/IconButton';
import Clear from '@material-ui/icons/Clear';
import Tooltip from '@material-ui/core/Tooltip';
import IconButton from '@mui/material/IconButton';
import Clear from '@mui/icons-material/Clear';
import Tooltip from '@mui/material/Tooltip';
interface ThingsboardImageState extends JsonFormFieldState {
imageUrl: string;
@ -91,7 +91,7 @@ class ThingsboardImage extends React.Component<JsonFormFieldProps, ThingsboardIm
</Tooltip>
</div>
<Dropzone onDrop={this.onDrop}
accept='image/*' multiple={false}>
accept={ {'image/*': []} } multiple={false}>
{({getRootProps, getInputProps}) => (
<div className='tb-dropzone' {...getRootProps()}>
<div>Drop an image or click to select a file to upload.</div>

View File

@ -16,7 +16,7 @@
import * as React from 'react';
import ThingsboardBaseComponent from './json-form-base-component';
import { JsonFormFieldProps, JsonFormFieldState } from '@shared/components/json-form/react/json-form.models';
import { TextField } from '@material-ui/core';
import { TextField } from '@mui/material';
interface ThingsboardNumberState extends JsonFormFieldState {
focused: boolean;
@ -78,6 +78,7 @@ class ThingsboardNumber extends React.Component<JsonFormFieldProps, ThingsboardN
return (
<div>
<TextField
variant={'standard'}
className={fieldClass}
label={this.props.form.title}
type='number'

View File

@ -15,9 +15,9 @@
*/
import * as React from 'react';
import { JsonFormFieldProps, JsonFormFieldState } from '@shared/components/json-form/react/json-form.models';
import FormControlLabel from '@material-ui/core/FormControlLabel';
import { FormLabel, Radio, RadioGroup } from '@material-ui/core';
import FormControl from '@material-ui/core/FormControl';
import FormControlLabel from '@mui/material/FormControlLabel';
import { FormLabel, Radio, RadioGroup } from '@mui/material';
import FormControl from '@mui/material/FormControl';
import ThingsboardBaseComponent from '@shared/components/json-form/react/json-form-base-component';
class ThingsboardRadios extends React.Component<JsonFormFieldProps, JsonFormFieldState> {

View File

@ -134,10 +134,10 @@ class ThingsboardRcSelect extends React.Component<JsonFormFieldProps, Thingsboar
render() {
let options: JSX.Element[] = [];
let options: React.JSX.Element[] = [];
if (this.state.items && this.state.items.length > 0) {
options = this.state.items.map((item, idx) => (
<Option key={idx} value={item.value}>{item.label}</Option>
options = this.state.items.map((item) => (
<Option key={item.value} value={item.value}>{item.label}</Option>
));
}

View File

@ -14,7 +14,7 @@
* limitations under the License.
*/
import * as React from 'react';
import { createTheme, ThemeProvider } from '@material-ui/core/styles';
import { createTheme, ThemeProvider } from '@mui/material/styles';
import thingsboardTheme from './styles/thingsboardTheme';
import ThingsboardSchemaForm from './json-form-schema-form';
import { JsonFormProps } from './json-form.models';

View File

@ -46,7 +46,7 @@ import _ from 'lodash';
import tinycolor from 'tinycolor2';
import { GroupInfo } from '@shared/models/widget.models';
import ThingsboardMarkdown from '@shared/components/json-form/react/json-form-markdown';
import { MouseEvent } from 'react';
import { MouseEvent, ReactNode } from 'react';
class ThingsboardSchemaForm extends React.Component<JsonFormProps, any> {
@ -149,7 +149,7 @@ class ThingsboardSchemaForm extends React.Component<JsonFormProps, any> {
if (this.props.mapper) {
mapper = _.merge(this.mapper, this.props.mapper);
}
const forms = merged.map(function(form, index) {
const forms: ReactNode[] = merged.map(function(form, index) {
return this.builder(form, this.props.model, index, this.onChange, this.onColorClick,
this.onIconClick, this.onToggleFullscreen, this.onHelpClick, mapper);
}.bind(this));

View File

@ -15,11 +15,12 @@
*/
import * as React from 'react';
import { JsonFormFieldProps, JsonFormFieldState } from '@shared/components/json-form/react/json-form.models';
import MenuItem from '@material-ui/core/MenuItem';
import FormControl from '@material-ui/core/FormControl';
import InputLabel from '@material-ui/core/InputLabel';
import Select from '@material-ui/core/Select';
import MenuItem from '@mui/material/MenuItem';
import FormControl from '@mui/material/FormControl';
import InputLabel from '@mui/material/InputLabel';
import Select, { SelectChangeEvent } from '@mui/material/Select';
import ThingsboardBaseComponent from '@shared/components/json-form/react/json-form-base-component';
import { isObject } from '@core/utils';
interface ThingsboardSelectState extends JsonFormFieldState {
currentValue: any;
@ -27,34 +28,39 @@ interface ThingsboardSelectState extends JsonFormFieldState {
class ThingsboardSelect extends React.Component<JsonFormFieldProps, ThingsboardSelectState> {
static getDerivedStateFromProps(props) {
if (props.model && props.form.key) {
return {
currentValue: ThingsboardSelect.getModelKey(props.model, props.form.key)
|| (props.form.titleMap != null ? props.form.titleMap[0].value : '')
}
}
}
static getModelKey(model, key) {
if (Array.isArray(key)) {
const res = key.reduce((cur, nxt) => (cur[nxt] || {}), model);
if (res && isObject(res)) {
return undefined;
} else {
return res;
}
} else {
return model[key];
}
}
constructor(props) {
super(props);
this.onSelected = this.onSelected.bind(this);
const possibleValue = this.getModelKey(this.props.model, this.props.form.key);
const possibleValue = ThingsboardSelect.getModelKey(this.props.model, this.props.form.key);
this.state = {
currentValue: this.props.model !== undefined && possibleValue ? possibleValue : this.props.form.titleMap != null ?
this.props.form.titleMap[0].value : ''
};
}
componentWillReceiveProps(nextProps) {
if (nextProps.model && nextProps.form.key) {
this.setState({
currentValue: this.getModelKey(nextProps.model, nextProps.form.key)
|| (nextProps.form.titleMap != null ? nextProps.form.titleMap[0].value : '')
});
}
}
getModelKey(model, key) {
if (Array.isArray(key)) {
return key.reduce((cur, nxt) => (cur[nxt] || {}), model);
} else {
return model[key];
}
}
onSelected(event: React.ChangeEvent<{ name?: string; value: any }>) {
onSelected(event: SelectChangeEvent<any>) {
this.setState({
currentValue: event.target.value
@ -72,8 +78,9 @@ class ThingsboardSelect extends React.Component<JsonFormFieldProps, ThingsboardS
<FormControl className={this.props.form.htmlClass}
disabled={this.props.form.readonly}
fullWidth={true}>
<InputLabel htmlFor='select-field'>{this.props.form.title}</InputLabel>
<InputLabel variant={'standard'} htmlFor='select-field'>{this.props.form.title}</InputLabel>
<Select
variant={'standard'}
value={this.state.currentValue}
onChange={this.onSelected}>
{menuItems}

View File

@ -15,7 +15,7 @@
*/
import * as React from 'react';
import ThingsboardBaseComponent from './json-form-base-component';
import TextField from '@material-ui/core/TextField';
import TextField from '@mui/material/TextField';
import { JsonFormFieldProps, JsonFormFieldState } from '@shared/components/json-form/react/json-form.models';
interface ThingsboardTextState extends JsonFormFieldState {
@ -67,6 +67,7 @@ class ThingsboardText extends React.Component<JsonFormFieldProps, ThingsboardTex
return (
<div>
<TextField
variant={'standard'}
className={fieldClass}
type={this.props.form.type}
label={this.props.form.title}
@ -79,7 +80,7 @@ class ThingsboardText extends React.Component<JsonFormFieldProps, ThingsboardTex
defaultValue={this.props.value}
disabled={this.props.form.readonly}
rows={rows}
rowsMax={rowsMax}
maxRows={rowsMax}
onFocus={this.onFocus}
onBlur={this.onBlur}
style={this.props.form.style || {width: '100%', minHeight: minHeight + 'px'}}/>

View File

@ -14,9 +14,9 @@
/// limitations under the License.
///
import { indigo, deepOrange } from '@material-ui/core/colors';
import { ThemeOptions } from '@material-ui/core/styles';
import { PaletteOptions } from '@material-ui/core/styles/createPalette';
import { indigo, deepOrange } from '@mui/material/colors';
import { ThemeOptions } from '@mui/material/styles';
import { PaletteOptions } from '@mui/material/styles/createPalette';
import { mergeDeep } from '@core/utils';
const PRIMARY_COLOR = '#305680';

View File

@ -15,6 +15,7 @@
///
import { Ace } from 'ace-builds';
import { deepClone } from '@core/utils';
export type tbMetaType = 'object' | 'function' | 'service' | 'property' | 'argument';
@ -41,9 +42,9 @@ export interface TbEditorCompletion {
children?: TbEditorCompletions;
}
interface TbEditorAceCompletion extends Ace.Completion {
interface TbEditorAceCompletion extends Ace.SnippetCompletion {
isTbEditorAceCompletion: true;
snippet: string;
title: string;
description?: string;
type?: string;
args?: FunctionArg[];
@ -124,10 +125,9 @@ export class TbEditorCompleter implements Ace.Completer {
const aceCompletion: TbEditorAceCompletion = {
isTbEditorAceCompletion: true,
snippet: parentPrefix + name,
name,
title: name,
caption: parentPrefix + name,
score: 100000,
value: parentPrefix + name,
meta: completion.meta,
type: completion.type,
description: completion.description,
@ -139,14 +139,14 @@ export class TbEditorCompleter implements Ace.Completer {
getDocTooltip(completion: TbEditorAceCompletion) {
if (completion && completion.isTbEditorAceCompletion) {
return {
docHTML: this.createDocHTML(completion)
};
const aceCompletion = deepClone(completion);
aceCompletion.docHTML = this.createDocHTML(completion);
return aceCompletion;
}
}
private createDocHTML(completion: TbEditorAceCompletion): string {
let title = `<b>${completion.name}</b>`;
let title = `<b>${completion.title}</b>`;
if (completion.meta === 'function') {
title += '(';
if (completion.args) {

View File

@ -33,7 +33,6 @@ import {
} from '@core/utils';
import { TranslateService } from '@ngx-translate/core';
import { AlarmInfo, AlarmSearchStatus, AlarmSeverity } from '../alarm.models';
import { Filter } from '@material-ui/icons';
import { DatePipe } from '@angular/common';
import { UserId } from '../id/user-id';
import { Direction } from '@shared/models/page/sort-order';

File diff suppressed because it is too large Load Diff