1
0
Fork 0
mirror of https://git.rwth-aachen.de/acs/public/villas/web/ synced 2025-03-09 00:00:01 +01:00

Removes componentWillUpdate and componentWillReceiveProps due conflicts with React's unsafe life cycles #212

This commit is contained in:
Sonja Happ 2020-01-16 15:11:17 +01:00
parent 374437dfad
commit 6f4604c75e
41 changed files with 5049 additions and 3225 deletions

7374
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -3,51 +3,54 @@
"version": "0.1.0",
"private": true,
"dependencies": {
"@fortawesome/fontawesome-svg-core": "^1.2.19",
"@fortawesome/free-solid-svg-icons": "^5.9.0",
"@fortawesome/react-fontawesome": "^0.1.4",
"@fortawesome/fontawesome-svg-core": "^1.2.26",
"@fortawesome/free-solid-svg-icons": "^5.12.0",
"@fortawesome/react-fontawesome": "^0.1.8",
"babel-runtime": "^6.26.0",
"bootstrap": "^4.3.1",
"bootstrap": "^4.4.1",
"classnames": "^2.2.6",
"d3-array": "^2.2.0",
"d3-array": "^2.4.0",
"d3-axis": "^1.0.12",
"d3-scale": "^3.0.0",
"d3-scale-chromatic": "^1.3.3",
"d3-selection": "^1.4.0",
"d3-shape": "^1.3.5",
"d3-time-format": "^2.1.3",
"d3-scale": "^3.2.1",
"d3-scale-chromatic": "^1.5.0",
"d3-selection": "^1.4.1",
"d3-shape": "^1.3.7",
"d3-time-format": "^2.2.3",
"es6-promise": "^4.2.8",
"fibers": "^4.0.2",
"file-saver": "^2.0.2",
"flux": "^3.1.3",
"frontend-collective-react-dnd-scrollzone": "^1.0.2",
"gaugeJS": "^1.3.7",
"handlebars": "^4.5.1",
"handlebars": "^4.7.1",
"immutable": "^4.0.0-rc.12",
"jquery": "^3.4.1",
"jszip": "^3.2.2",
"libcimsvg": "git+https://git.rwth-aachen.de/acs/public/cim/pintura-npm-package.git",
"lodash": "^4.17.15",
"node-sass": "^4.13.0",
"prop-types": "^15.7.2",
"rc-slider": "^8.6.13",
"react": "^16.8.6",
"react-bootstrap": "^1.0.0-beta.9",
"rc-slider": "^8.7.1",
"react": "^16.12.0",
"react-bootstrap": "^1.0.0-beta.16",
"react-contexify": "^4.1.1",
"react-d3": "^0.4.0",
"react-dnd": "^9.3.2",
"react-dnd-html5-backend": "^9.3.2",
"react-dom": "^16.8.6",
"react-dnd": "^9.5.1",
"react-dnd-html5-backend": "^9.5.1",
"react-dom": "^16.12.0",
"react-fullscreenable": "^2.5.1-0",
"react-grid-system": "^4.4.10",
"react-grid-system": "^4.4.11",
"react-json-view": "^1.19.1",
"react-notification-system": "^0.2.17",
"react-rnd": "^10.0.0",
"react-router": "^5.0.1",
"react-router-dom": "^5.0.1",
"react-scripts": "^3.0.1",
"react-sortable-tree": "^2.6.2",
"react-svg-pan-zoom": "^3.1.0",
"superagent": "^5.1.0",
"typescript": "^3.5.3",
"react-rnd": "^10.1.4",
"react-router": "^5.1.2",
"react-router-dom": "^5.1.2",
"react-scripts": "^3.3.0",
"react-sortable-tree": "^2.7.1",
"react-svg-pan-zoom": "^3.8.0",
"sass": "^1.24.4",
"superagent": "^5.2.1",
"typescript": "^3.7.4",
"validator": "^11.1.0"
},
"devDependencies": {

View file

@ -68,7 +68,9 @@ class App extends React.Component {
};
}
componentWillMount() {
componentDidMount() {
NotificationsDataManager.setSystem(this.refs.notificationSystem);
// if token stored locally, request user
let token = localStorage.getItem("token");
let currentUser = JSON.parse(localStorage.getItem("currentUser"));
@ -79,9 +81,7 @@ class App extends React.Component {
currentUser: currentUser
});
}
}
componentDidMount() {
// load all simulators and scenarios to fetch data
// AppDispatcher.dispatch({
// type: 'simulators/start-load',
@ -93,7 +93,7 @@ class App extends React.Component {
// token: this.state.token
// });
NotificationsDataManager.setSystem(this.refs.notificationSystem);
}
showSidebarMenu = () => {

View file

@ -36,8 +36,10 @@ class EditableHeader extends React.Component {
};
}
componentWillReceiveProps(nextProps) {
this.setState({ title: nextProps.title });
static getDerivedStateFromProps(props, state){
return {
title: props.title
};
}
edit = () => {

View file

@ -45,12 +45,6 @@ class Home extends React.Component {
return '?';
}
componentWillMount() {
//RestAPI.get('/api/v1/counts').then(response => {
// this.setState({ counts: response });
//});
}
render() {
return (
<div className="home-container">

View file

@ -32,7 +32,7 @@ class CustomTable extends Component {
this.activeInput = null;
this.state = {
rows: this.getRows(props),
rows: CustomTable.getRows(props),
editCell: [ -1, -1 ]
};
}
@ -45,7 +45,7 @@ class CustomTable extends Component {
this.setState({ editCell: [ column, row ]}); // x, y
}
addCell(data, index, child) {
static addCell(data, index, child) {
// add data to cell
let content = null;
@ -112,7 +112,7 @@ class CustomTable extends Component {
}
if (child.props.checkbox) {
const checkboxKey = this.props.checkboxKey;
const checkboxKey = child.props.checkboxKey;
cell.push(<FormCheck className="table-control-checkbox" inline checked={checkboxKey ? data[checkboxKey] : null} onChange={e => child.props.onChecked(index, e)} />);
}
@ -122,12 +122,12 @@ class CustomTable extends Component {
}
return cell;
}
} // addCell
componentWillReceiveProps(nextProps) {
const rows = this.getRows(nextProps);
static getDerivedStateFromProps(props, state){
const rows = CustomTable.getRows(props);
this.setState({ rows });
return { rows };
}
componentDidUpdate() {
@ -147,7 +147,7 @@ class CustomTable extends Component {
this.setState({ editCell: [ -1, -1 ] });
}
getRows(props) {
static getRows(props) {
if (props.data == null) {
return [];
}
@ -156,13 +156,13 @@ class CustomTable extends Component {
// check if multiple columns
if (Array.isArray(props.children) === false) {
// table only has a single column
return [ this.addCell(data, index, props.children) ];
return [ CustomTable.addCell(data, index, props.children) ];
}
const row = [];
for (let child of props.children) {
row.push(this.addCell(data, index, child));
row.push(CustomTable.addCell(data, index, child));
}
return row;

View file

@ -29,123 +29,123 @@ import LoginStore from '../user/login-store';
import AppDispatcher from '../common/app-dispatcher';
class SelectFile extends React.Component {
static getStores() {
return [ FileStore, LoginStore ];
static getStores() {
return [ FileStore, LoginStore ];
}
static calculateState() {
return {
files: FileStore.getState(),
sessionToken: LoginStore.getState().token,
selectedFile: '',
uploadFile: null,
uploadProgress: 0
};
}
componentDidMount() {
AppDispatcher.dispatch({
type: 'files/start-load',
token: this.state.sessionToken
});
}
static getDerivedStateFromProps(props, state){
if (props.value === state.selectedSimulator) {
return null;
}
static calculateState() {
return {
files: FileStore.getState(),
sessionToken: LoginStore.getState().token,
selectedFile: '',
uploadFile: null,
uploadProgress: 0
};
let selectedSimulator = props.value;
if (selectedSimulator == null) {
if (state.simulators.length > 0) {
selectedSimulator = state.simulators[0]._id;
} else {
selectedSimulator = '';
}
}
componentDidMount() {
AppDispatcher.dispatch({
type: 'files/start-load',
token: this.state.sessionToken
});
}
return {selectedSimulator};
}
componentWillReceiveProps(nextProps) {
if (nextProps.value === this.state.selectedSimulator) {
return;
}
handleChange = event => {
this.setState({ selectedFile: event.target.value });
let selectedSimulator = nextProps.value;
if (selectedSimulator == null) {
if (this.state.simulators.length > 0) {
selectedSimulator = this.state.simulators[0]._id;
} else {
selectedSimulator = '';
}
}
// send file to callback
if (this.props.onChange != null) {
const file = this.state.files.find(f => f._id === event.target.value);
this.setState({ selectedSimulator });
}
this.props.onChange(file);
}
};
handleChange = event => {
this.setState({ selectedFile: event.target.value });
selectUploadFile = event => {
this.setState({ uploadFile: event.target.files[0] });
};
// send file to callback
if (this.props.onChange != null) {
const file = this.state.files.find(f => f._id === event.target.value);
startFileUpload = () => {
// upload file
const formData = new FormData();
formData.append(0, this.state.uploadFile);
this.props.onChange(file);
}
}
AppDispatcher.dispatch({
type: 'files/start-upload',
data: formData,
token: this.state.sessionToken,
progressCallback: this.updateUploadProgress,
finishedCallback: this.clearProgress
});
};
selectUploadFile = event => {
this.setState({ uploadFile: event.target.files[0] });
}
updateUploadProgress = event => {
this.setState({ uploadProgress: parseInt(event.percent.toFixed(), 10) });
};
startFileUpload = () => {
// upload file
const formData = new FormData();
formData.append(0, this.state.uploadFile);
clearProgress = () => {
// select uploaded file
const selectedFile = this.state.files[this.state.files.length - 1]._id;
this.setState({ selectedFile, uploadProgress: 0 });
};
AppDispatcher.dispatch({
type: 'files/start-upload',
data: formData,
token: this.state.sessionToken,
progressCallback: this.updateUploadProgress,
finishedCallback: this.clearProgress
});
}
render() {
const fileOptions = this.state.files.map(f =>
<option key={f._id} value={f._id}>{f.name}</option>
);
updateUploadProgress = event => {
this.setState({ uploadProgress: parseInt(event.percent.toFixed(), 10) });
}
const progressBarStyle = {
marginLeft: '100px',
marginTop: '-25px'
};
clearProgress = () => {
// select uploaded file
const selectedFile = this.state.files[this.state.files.length - 1]._id;
this.setState({ selectedFile, uploadProgress: 0 });
}
return <div>
<FormGroup>
<Col componentClass={FormLabel} sm={3} md={2}>
{this.props.name}
</Col>
render() {
const fileOptions = this.state.files.map(f =>
<option key={f._id} value={f._id}>{f.name}</option>
);
<Col sm={9} md={10}>
<FormControl disabled={this.props.disabled} componentClass='select' placeholder='Select file' onChange={this.handleChange}>
{fileOptions}
</FormControl>
</Col>
</FormGroup>
const progressBarStyle = {
marginLeft: '100px',
marginTop: '-25px'
};
<FormGroup>
<Col sm={9} md={10} smOffset={3} mdOffset={2}>
<FormControl disabled={this.props.disabled} type='file' onChange={this.selectUploadFile} />
</Col>
</FormGroup>
return <div>
<FormGroup>
<Col componentClass={FormLabel} sm={3} md={2}>
{this.props.name}
</Col>
<FormGroup>
<Col sm={9} md={10} smOffset={3} mdOffset={2}>
<Button disabled={this.props.disabled} bsSize='small' onClick={this.startFileUpload}>
Upload file
</Button>
<Col sm={9} md={10}>
<FormControl disabled={this.props.disabled} componentClass='select' placeholder='Select file' onChange={this.handleChange}>
{fileOptions}
</FormControl>
</Col>
</FormGroup>
<FormGroup>
<Col sm={9} md={10} smOffset={3} mdOffset={2}>
<FormControl disabled={this.props.disabled} type='file' onChange={this.selectUploadFile} />
</Col>
</FormGroup>
<FormGroup>
<Col sm={9} md={10} smOffset={3} mdOffset={2}>
<Button disabled={this.props.disabled} bsSize='small' onClick={this.startFileUpload}>
Upload file
</Button>
<ProgressBar striped active now={this.state.uploadProgress} label={this.state.uploadProgress + '%'} style={progressBarStyle} />
</Col>
</FormGroup>
</div>;
}
<ProgressBar striped active now={this.state.uploadProgress} label={this.state.uploadProgress + '%'} style={progressBarStyle} />
</Col>
</FormGroup>
</div>;
}
}
let fluxContainerConverter = require('../common/FluxContainerConverter');

View file

@ -41,12 +41,15 @@ class SignalMapping extends React.Component {
};
}
componentWillReceiveProps(nextProps) {
if (nextProps.length === this.state.length && nextProps.signals === this.state.signals) {
return;
}
static getDerivedStateFromProps(props, state){
if (props.length === state.length && props.signals === state.signals) {
return null
}
this.setState({ length: nextProps.length, signals: nextProps.signals });
return{
length: props.length,
signals: props.signals
};
}
validateLength(){

View file

@ -47,7 +47,7 @@ class SimulationModel extends React.Component {
};
}
componentWillMount() {
componentDidMount() {
AppDispatcher.dispatch({
type: 'simulationModels/start-load',
data: this.props.match.params.simulationModel,

View file

@ -38,21 +38,23 @@ class SelectSimulator extends React.Component {
};
}
componentWillReceiveProps(nextProps) {
if (nextProps.value === this.state.selectedSimulator) {
return;
}
static getDerivedStateFromProps(props, state){
if (props.value === state.selectedSimulator) {
return null; // no change
}
let selectedSimulator = nextProps.value;
if (selectedSimulator == null) {
if (this.state.simulators.length > 0) {
selectedSimulator = this.state.simulators[0].id;
} else {
selectedSimulator = '';
}
let selectedSimulator = props.value;
if (selectedSimulator == null) {
if (state.simulators.length > 0) {
selectedSimulator = state.simulators[0].id;
} else {
selectedSimulator = '';
}
}
this.setState({ selectedSimulator });
return {
selectedSimulator
};
}
handleChange = event => {
@ -64,7 +66,7 @@ class SelectSimulator extends React.Component {
this.props.onChange(simulator);
}
}
};
render() {
const simulatorOptions = this.state.simulators.map(s =>

View file

@ -31,12 +31,15 @@ class SimulatorAction extends React.Component {
};
}
componentWillReceiveProps(nextProps) {
if (this.state.selectedAction == null) {
if (nextProps.actions != null && nextProps.actions.length > 0) {
this.setState({ selectedAction: nextProps.actions[0] });
}
static getDerivedStateFromProps(props, state){
if (state.selectedAction == null) {
if (props.actions != null && props.actions.length > 0) {
return{
selectedAction: props.actions[0]
};
}
}
return null
}
setAction = id => {
@ -46,7 +49,7 @@ class SimulatorAction extends React.Component {
this.setState({ selectedAction: action });
}
}
}
};
render() {
const actionList = this.props.actions.map(action => (

View file

@ -87,7 +87,7 @@ class Simulators extends Component {
};
}
componentWillMount() {
componentDidMount() {
AppDispatcher.dispatch({
type: 'simulators/start-load',
token: this.state.sessionToken,

View file

@ -50,13 +50,14 @@ class Login extends Component {
NotificationsDataManager.setSystem(this.refs.notificationSystem);
}
componentWillUpdate(nextProps, nextState) {
componentDidUpdate(prevProps: Readonly<P>, prevState: Readonly<S>, snapshot: SS): void {
// if token stored locally, request user
if (nextState.token == null) {
if (this.state.token == null) {
const token = localStorage.getItem('token');
const currentUser = localStorage.getItem('currentUser');
if (token != null && token !== '' && nextState.currentUser == null) {
if (token != null && token !== '' && this.state.currentUser == null) {
AppDispatcher.dispatch({
type: 'users/logged-in',
token: token,
@ -65,12 +66,13 @@ class Login extends Component {
}
} else {
// check if logged in
if (nextState.currentUser != null) {
if (this.state.currentUser != null) {
// save login in local storage
localStorage.setItem('token', nextState.token);
localStorage.setItem('currentUser', JSON.stringify(nextState.currentUser));
localStorage.setItem('token', this.state.token);
localStorage.setItem('currentUser', JSON.stringify(this.state.currentUser));
}
}
}
render() {

View file

@ -25,7 +25,7 @@ import { Redirect } from 'react-router-dom';
import AppDispatcher from '../common/app-dispatcher';
class Logout extends React.Component {
componentWillMount() {
componentDidMount() {
AppDispatcher.dispatch({
type: 'users/logout'
});

View file

@ -35,8 +35,10 @@ class EditWidgetAspectControl extends React.Component {
};
}
componentWillReceiveProps(nextProps) {
this.setState({ widget: nextProps.widget });
static getDerivedStateFromProps(props, state){
return{
widget: props.widget
};
}
render() {

View file

@ -35,8 +35,10 @@ class EditWidgetCheckboxControl extends React.Component {
};
}
componentWillReceiveProps(nextProps) {
this.setState({ widget: nextProps.widget });
static getDerivedStateFromProps(props, state){
return{
widget: props.widget
};
}
render() {

View file

@ -49,9 +49,10 @@ class EditWidgetColorControl extends Component {
};
}
componentWillReceiveProps(nextProps) {
// Update state's widget with props
this.setState({ widget: nextProps.widget });
static getDerivedStateFromProps(props, state){
return {
widget: props.widget
};
}
render() {

View file

@ -41,8 +41,10 @@ class EditWidgetColorZonesControl extends React.Component {
};
}
componentWillReceiveProps(nextProps) {
this.setState({ widget: nextProps.widget });
static getDerivedStateFromProps(props, state){
return {
widget: props.widget
};
}
addZone = () => {

View file

@ -36,9 +36,10 @@ class EditWidgetHTMLContent extends React.Component {
event.stopPropagation();
}
componentWillReceiveProps(nextProps) {
// Update state's widget with props
this.setState({ widget: nextProps.widget });
static getDerivedStateFromProps(props, state){
return {
widget: props.widget
};
}
render() {

View file

@ -39,8 +39,10 @@ class EditImageWidgetControl extends React.Component {
};
}
componentWillReceiveProps(nextProps) {
this.setState({ widget: nextProps.widget });
static getDerivedStateFromProps(props, state){
return {
widget: props.widget
};
}
startFileUpload = () => {

View file

@ -35,8 +35,10 @@ class EditWidgetMinMaxControl extends React.Component {
}
}
componentWillReceiveProps(nextProps) {
this.setState({ widget: nextProps.widget });
static getDerivedStateFromProps(props, state){
return{
widget: props.widget
};
}
render() {

View file

@ -33,9 +33,10 @@ class EditWidgetNumberControl extends Component {
};
}
componentWillReceiveProps(nextProps) {
// Update state's widget with props
this.setState({ widget: nextProps.widget });
static getDerivedStateFromProps(props, state){
return{
widget: props.widget
};
}
render() {

View file

@ -35,9 +35,10 @@ class EditWidgetOrientation extends Component {
};
}
componentWillReceiveProps(nextProps) {
// Update state's widget with props
this.setState({ widget: nextProps.widget });
static getDerivedStateFromProps(props, state){
return {
widget: props.widget
};
}
handleOrientationChange(orientation) {

View file

@ -32,9 +32,10 @@ class EditWidgetParametersControl extends Component {
};
}
componentWillReceiveProps(nextProps) {
// Update state's widget with props
this.setState({ widget: nextProps.widget });
static getDerivedStateFromProps(props, state){
return {
widget: props.widget
};
}
handleChange(value) {

View file

@ -33,9 +33,10 @@ class EditWidgetSignalControl extends Component {
};
}
componentWillReceiveProps(nextProps) {
// Update state's widget with props
this.setState({ widget: nextProps.widget });
static getDerivedStateFromProps(props, state){
return {
widget: props.widget
};
}
render() {

View file

@ -33,9 +33,10 @@ class EditWidgetSignalsControl extends Component {
};
}
componentWillReceiveProps(nextProps) {
// Update state's widget with props
this.setState({ widget: nextProps.widget });
static getDerivedStateFromProps(props, state){
return {
widget: props.widget
};
}
handleSignalChange(checked, index) {

View file

@ -31,9 +31,10 @@ class EditWidgetTextControl extends Component {
};
}
componentWillReceiveProps(nextProps) {
// Update state's widget with props
this.setState({ widget: nextProps.widget });
static getDerivedStateFromProps(props, state){
return {
widget: props.widget
};
}
render() {

View file

@ -33,8 +33,10 @@ class EditWidgetTimeControl extends Component {
};
}
componentWillReceiveProps(nextProps) {
this.setState({ widget: nextProps.widget });
static getDerivedStateFromProps(props, state){
return{
widget: props.widget
};
}
render() {

View file

@ -77,26 +77,26 @@ class Plot extends React.Component {
this.removeInterval();
}
componentWillReceiveProps(nextProps) {
if (nextProps.time !== this.props.time) {
componentDidUpdate(prevProps: Readonly<P>, prevState: Readonly<S>, snapshot: SS): void {
if (prevProps.time !== this.props.time) {
this.createInterval();
}
let labelMargin = 0;
if (nextProps.yLabel !== '') {
if (this.props.yLabel !== '') {
labelMargin = 30;
}
// check if data is invalid
if (nextProps.data == null || nextProps.data.length === 0 || nextProps.data[0].length === 0) {
if (this.props.data == null || this.props.data.length === 0 || this.props.data[0].length === 0) {
// create empty plot axes
const xScale = scaleTime().domain([Date.now() - nextProps.time * 1000, Date.now()]).range([0, nextProps.width - leftMargin - labelMargin - rightMargin]);
const xScale = scaleTime().domain([Date.now() - this.props.time * 1000, Date.now()]).range([0, this.props.width - leftMargin - labelMargin - rightMargin]);
let yScale;
if (nextProps.yUseMinMax) {
yScale = scaleLinear().domain([nextProps.yMin, nextProps.yMax]).range([nextProps.height + topMargin - bottomMargin, topMargin]);
if (this.props.yUseMinMax) {
yScale = scaleLinear().domain([this.props.yMin, this.props.yMax]).range([this.props.height + topMargin - bottomMargin, topMargin]);
} else {
yScale = scaleLinear().domain([0, 10]).range([nextProps.height + topMargin - bottomMargin, topMargin]);
yScale = scaleLinear().domain([0, 10]).range([this.props.height + topMargin - bottomMargin, topMargin]);
}
const xAxis = axisBottom().scale(xScale).ticks(5).tickFormat(timeFormat("%M:%S"));
@ -106,17 +106,20 @@ class Plot extends React.Component {
return;
}
// only show data in requested time
let data = nextProps.data;
// check if requested time frame has changed
if(this.props.time !== prevProps.time) {
// only show data in requested time
let data = this.props.data;
const firstTimestamp = data[0][data[0].length - 1].x - (nextProps.time + 1) * 1000;
if (data[0][0].x < firstTimestamp) {
// only show data in range (+100 ms)
const index = data[0].findIndex(value => value.x >= firstTimestamp - 100);
data = data.map(values => values.slice(index));
const firstTimestamp = data[0][data[0].length - 1].x - (this.props.time + 1) * 1000;
if (data[0][0].x < firstTimestamp) {
// only show data in range (+100 ms)
const index = data[0].findIndex(value => value.x >= firstTimestamp - 100);
data = data.map(values => values.slice(index));
}
this.setState({data, labelMargin});
}
this.setState({ data, labelMargin });
}
createInterval() {

View file

@ -78,7 +78,7 @@ class Widget extends React.Component {
};
}
componentWillMount() {
componentDidMount() {
if (this.state.sessionToken == null) {
return;
}
@ -125,7 +125,7 @@ class Widget extends React.Component {
simulationModel = model;
}
if (widget.type === 'CustomAction') {
return <WidgetCustomAction widget={widget} data={this.state.simulatorData} dummy={this.state.sequence} simulationModel={simulationModel} />
} else if (widget.type === 'Action') {
@ -162,7 +162,7 @@ class Widget extends React.Component {
return null;
}
rn
rn
render() {
const element = this.createWidget(this.props.data);

View file

@ -37,17 +37,17 @@ class WidgetCustomAction extends Component {
}
static getStores() {
return [ SimulatorStore ];
return [ SimulatorStore, LoginStore ];
}
componentWillReceiveProps(props) {
static getDerivedStateFromProps(props, state){
if (props.simulationModel === null)
return;
return null; //no change
this.setState({
return{
simulator: SimulatorStore.getState().find(s => s._id === props.simulationModel.simulator),
sessionToken: LoginStore.getState().token
});
};
}
onClick() {

View file

@ -22,6 +22,7 @@
import React, { Component } from 'react';
import { Gauge } from 'gaugeJS';
//import {update} from "immutable";
class WidgetGauge extends Component {
constructor(props) {
@ -33,7 +34,7 @@ class WidgetGauge extends Component {
this.state = {
value: 0,
minValue: null,
maxValue: null
maxValue: null,
};
}
@ -47,99 +48,122 @@ class WidgetGauge extends Component {
//this.updateLabels(this.state.minValue, this.state.maxValue);
}
componentWillReceiveProps(nextProps) {
if (nextProps.simulationModel == null) {
this.setState({ value: 0 });
return;
componentDidUpdate(prevProps: Readonly<P>, prevState: Readonly<S>, snapshot: SS): void {
if(prevState.minValue !== this.state.minValue){
this.gauge.setMinValue(this.state.minValue);
}
if(prevState.maxValue !== this.state.maxValue){
this.gauge.maxValue = this.state.maxValue
}
const simulator = nextProps.simulationModel.simulator;
// update gauge's value
if(prevState.value !== this.state.value){
this.gauge.set(this.state.value)
}
// update labels
if(prevState.minValue !== this.state.minValue || prevState.maxValue !== this.state.maxValue){
this.updateLabels(this.state.minValue, this.state.maxValue)
}
}
static getDerivedStateFromProps(props, state){
if (props.simulationModel == null) {
return{value:0};
}
const simulator = props.simulationModel.simulator;
// update value
if (nextProps.data == null || nextProps.data[simulator] == null
|| nextProps.data[simulator].output == null
|| nextProps.data[simulator].output.values == null
|| nextProps.data[simulator].output.values.length === 0
|| nextProps.data[simulator].output.values[0].length === 0) {
this.setState({ value: 0 });
return;
if (props.data == null
|| props.data[simulator] == null
|| props.data[simulator].output == null
|| props.data[simulator].output.values == null
|| props.data[simulator].output.values.length === 0
|| props.data[simulator].output.values[0].length === 0) {
return{value:0};
}
// memorize if min or max value is updated
let updateValue = false;
let updateMinValue = false;
let updateMaxValue = false;
// check if value has changed
const signal = nextProps.data[simulator].output.values[nextProps.widget.customProperties.signal];
const signal = props.data[simulator].output.values[props.widget.customProperties.signal];
// Take just 3 decimal positions
// Note: Favor this method over Number.toFixed(n) in order to avoid a type conversion, since it returns a String
if (signal != null) {
const value = Math.round(signal[signal.length - 1].y * 1e3) / 1e3;
if (this.state.value !== value && value != null) {
this.setState({ value });
let minValue = null;
let maxValue = null;
if (state.value !== value && value != null) {
//value has changed
updateValue = true;
// update min-max if needed
let updateLabels = false;
let minValue = this.state.minValue;
let maxValue = this.state.maxValue;
minValue = state.minValue;
maxValue = state.maxValue;
if (minValue == null) {
minValue = value - 0.5;
updateLabels = true;
this.setState({ minValue });
this.gauge.setMinValue(minValue);
updateMinValue = true;
}
if (maxValue == null) {
maxValue = value + 0.5;
updateLabels = true;
this.setState({ maxValue });
this.gauge.maxValue = maxValue;
updateMaxValue = true;
}
if (nextProps.widget.customProperties.valueUseMinMax) {
if (this.state.minValue > nextProps.widget.customProperties.valueMin) {
minValue = nextProps.widget.customProperties.valueMin;
this.setState({ minValue });
this.gauge.setMinValue(minValue);
if (props.widget.customProperties.valueUseMinMax) {
if (state.minValue > props.widget.customProperties.valueMin) {
minValue = props.widget.customProperties.valueMin;
updateMinValue = true;
updateLabels = true;
}
if (this.state.maxValue < nextProps.widget.customProperties.valueMax) {
maxValue = nextProps.widget.customProperties.valueMax;
this.setState({ maxValue });
this.gauge.maxValue = maxValue;
if (state.maxValue < props.widget.customProperties.valueMax) {
maxValue = props.widget.customProperties.valueMax;
updateMaxValue = true;
updateLabels = true;
}
}
if (updateLabels === false) {
// check if min/max changed
if (minValue > this.gauge.minValue) {
minValue = this.gauge.minValue;
updateLabels = true;
this.setState({ minValue });
if (minValue > state.gauge.minValue) {
minValue = state.gauge.minValue;
updateMinValue = true;
}
if (maxValue < this.gauge.maxValue) {
maxValue = this.gauge.maxValue;
updateLabels = true;
this.setState({ maxValue });
if (maxValue < state.gauge.maxValue) {
maxValue = state.gauge.maxValue;
updateMaxValue = true;
}
}
if (updateLabels) {
this.updateLabels(minValue, maxValue);
}
// update gauge's value
this.gauge.set(value);
}
}
// prepare returned state
let returnState = null;
if(updateValue === true){
returnState["value"] = value;
}
if(updateMinValue === true){
returnState["minValue"] = minValue;
}
if(updateMaxValue === true){
returnState["maxValue"] = maxValue;
}
return returnState
} // if there is a signal
}
updateLabels(minValue, maxValue, force) {

View file

@ -25,14 +25,15 @@ import AppDispatcher from '../../common/app-dispatcher';
import config from '../../config';
class WidgetImage extends React.Component {
componentWillReceiveProps(nextProps) {
componentDidMount() {
// Query the image referenced by the widget
let widgetFile = nextProps.widget.customProperties.file;
if (widgetFile && !nextProps.files.find(file => file._id === widgetFile)) {
let widgetFile = this.props.widget.customProperties.file;
if (widgetFile && !this.props.files.find(file => file.id === widgetFile)) {
AppDispatcher.dispatch({
type: 'files/start-load',
data: widgetFile,
token: nextProps.token
token: this.props.token
});
}
}

View file

@ -34,24 +34,25 @@ class WidgetInput extends Component {
};
}
componentWillReceiveProps(nextProps) {
if (nextProps.simulationModel == null) {
return;
static getDerivedStateFromProps(props, state){
if (props.simulationModel == null) {
return null;
}
let returnState = null;
// Update value
if (nextProps.widget.customProperties.default_value && this.state.value === undefined) {
this.setState({
value: nextProps.widget.customProperties.default_value
});
if (props.widget.customProperties.default_value && this.state.value === undefined) {
returnState["value"] = props.widget.customProperties.default_value;
}
// Update unit
if (nextProps.widget.customProperties.simulationModel && nextProps.simulationModel.inputMapping && this.state.unit !== nextProps.simulationModel.inputMapping[nextProps.widget.customProperties.signal].type) {
this.setState({
unit: nextProps.simulationModel.inputMapping[nextProps.widget.customProperties.signal].type
});
if (props.widget.customProperties.simulationModel
&& props.simulationModel.inputMapping
&& state.unit !== props.simulationModel.inputMapping[props.widget.customProperties.signal].type) {
returnState["unit"] = props.simulationModel.inputMapping[props.widget.customProperties.signal].type;
}
return returnState;
}
valueIsChanging(newValue) {

View file

@ -33,25 +33,28 @@ class WidgetLamp extends Component {
};
}
componentWillReceiveProps(nextProps) {
if (nextProps.simulationModel == null) {
this.setState({ value: '' });
return;
static getDerivedStateFromProps(props, state){
if (props.simulationModel == null) {
return{ value: ''};
}
const simulator = nextProps.simulationModel.simulator;
const simulator = props.simulationModel.simulator;
// update value
if (nextProps.data == null || nextProps.data[simulator] == null || nextProps.data[simulator].output == null || nextProps.data[simulator].output.values == null) {
this.setState({ value: '' });
return;
if (props.data == null
|| props.data[simulator] == null
|| props.data[simulator].output == null
|| props.data[simulator].output.values == null) {
return{value:''};
}
// check if value has changed
const signal = nextProps.data[simulator].output.values[nextProps.widget.customProperties.signal];
if (signal != null && this.state.value !== signal[signal.length - 1].y) {
this.setState({ value: signal[signal.length - 1].y });
const signal = props.data[simulator].output.values[props.widget.customProperties.signal];
if (signal != null && state.value !== signal[signal.length - 1].y) {
return { value: signal[signal.length - 1].y };
}
return null;
}
render() {

View file

@ -36,25 +36,25 @@ class WidgetPlotTable extends Component {
};
}
componentWillReceiveProps(nextProps) {
if (nextProps.simulationModel == null) {
componentDidUpdate(prevProps: Readonly<P>, prevState: Readonly<S>, snapshot: SS): void {
if (this.props.simulationModel == null) {
return;
}
// Update internal selected signals state with props (different array objects)
if (this.props.widget.customProperties.signals !== nextProps.widget.customProperties.signals) {
this.setState( {signals: nextProps.widget.customProperties.signals});
if (prevProps.widget.customProperties.signals !== this.props.widget.customProperties.signals) {
this.setState( {signals: this.props.widget.customProperties.signals});
}
// Identify if there was a change in the preselected signals
if (JSON.stringify(nextProps.widget.customProperties.preselectedSignals) !== JSON.stringify(this.props.widget.customProperties.preselectedSignals) || this.state.preselectedSignals.length === 0) {
if (JSON.stringify(prevProps.widget.customProperties.preselectedSignals) !== JSON.stringify(this.props.widget.customProperties.preselectedSignals)
|| this.state.preselectedSignals.length === 0) {
// Update the currently selected signals by intersecting with the preselected signalsWidget
// Do the same with the plot values
var intersection = this.computeIntersection(nextProps.widget.customProperties.preselectedSignals, nextProps.widget.customProperties.signals);
var intersection = this.computeIntersection(this.props.widget.customProperties.preselectedSignals, this.props.widget.customProperties.signals);
this.setState({ signals: intersection });
this.updatePreselectedSignalsState(nextProps);
return;
this.updatePreselectedSignalsState(this.props);
}
}
@ -63,14 +63,14 @@ class WidgetPlotTable extends Component {
return preselectedSignals.filter( s => selectedSignals.includes(s));
}
updatePreselectedSignalsState(nextProps) {
updatePreselectedSignalsState(props) {
// Create checkboxes using the signal indices from simulation model
if(nextProps.simulationModel.outputMapping){
const preselectedSignals = nextProps.simulationModel.outputMapping.reduce(
if(props.simulationModel.outputMapping){
const preselectedSignals = props.simulationModel.outputMapping.reduce(
// Loop through simulation model signals
(accum, model_signal, signal_index) => {
// Append them if they belong to the current selected type
if (nextProps.widget.customProperties.preselectedSignals.indexOf(signal_index) > -1) {
if (props.widget.customProperties.preselectedSignals.indexOf(signal_index) > -1) {
accum.push(
{
index: signal_index,
@ -81,7 +81,7 @@ class WidgetPlotTable extends Component {
}
return accum;
}, []);
this.setState({ preselectedSignals });
}
}

View file

@ -34,24 +34,28 @@ class WidgetPlot extends React.Component {
};
}
componentWillReceiveProps(nextProps) {
if (nextProps.simulationModel == null) {
this.setState({ data: [], legend: [] });
return;
static getDerivedStateFromProps(props, state){
if (props.simulationModel == null) {
return{
data: [],
legend: [],
};
}
const simulator = nextProps.simulationModel.simulator;
const simulator = props.simulationModel.simulator;
// Proceed if a simulation with models and a simulator are available
if (simulator && nextProps.data[simulator] != null && nextProps.data[simulator] != null && nextProps.data[simulator].output != null && nextProps.data[simulator].output.values != null) {
const chosenSignals = nextProps.widget.customProperties.signals;
if (simulator && props.data[simulator] != null && props.data[simulator] != null && props.data[simulator].output != null && props.data[simulator].output.values != null) {
const chosenSignals = props.widget.customProperties.signals;
const data = nextProps.data[simulator].output.values.filter((values, index) => (
nextProps.widget.customProperties.signals.findIndex(value => value === index) !== -1
const data = props.data[simulator].output.values.filter((values, index) => (
props.widget.customProperties.signals.findIndex(value => value === index) !== -1
));
// Query the signals that will be displayed in the legend
const legend = nextProps.simulationModel.outputMapping.reduce( (accum, model_signal, signal_index) => {
const legend = props.simulationModel.outputMapping.reduce( (accum, model_signal, signal_index) => {
if (chosenSignals.includes(signal_index)) {
accum.push({ index: signal_index, name: model_signal.name, type: model_signal.type });
}
@ -59,10 +63,17 @@ class WidgetPlot extends React.Component {
return accum;
}, []);
this.setState({ data, legend });
return{
data: data,
legend: legend,
};
} else {
this.setState({ data: [], legend: [] });
return{
data: [],
legend: [],
};
}
}
render() {

View file

@ -40,32 +40,42 @@ class WidgetSlider extends Component {
this.state = {
unit: 'bla',
};
}
componentWillReceiveProps(nextProps) {
if (nextProps.simulationModel == null) {
return;
static getDerivedStateFromProps(props, state){
if (props.simulationModel == null) {
return null;
}
let returnState = {};
// Update value
if (nextProps.widget.customProperties.default_value && this.state.value === undefined) {
this.setState({
value: nextProps.widget.customProperties.default_value,
});
if (props.widget.customProperties.default_value && state.value === undefined) {
returnState["value"] = props.widget.customProperties.default_value;
}
// Update unit
if (nextProps.widget.customProperties.simulationModel && nextProps.simulationModel.inputMapping && this.state.unit !== nextProps.simulationModel.inputMapping[nextProps.widget.customProperties.signal].type) {
this.setState({
unit: nextProps.simulationModel.inputMapping[nextProps.widget.customProperties.signal].type
});
if (props.widget.customProperties.simulationModel
&& props.simulationModel.inputMapping &&
state.unit !== props.simulationModel.inputMapping[props.widget.customProperties.signal].type) {
returnState["unit"] = props.simulationModel.inputMapping[props.widget.customProperties.signal].type;
}
if (returnState !== {}){
return returnState;
}
else{
return null;
}
}
componentDidUpdate(prevProps: Readonly<P>, prevState: Readonly<S>, snapshot: SS): void {
// Check if the orientation changed, update the size if it did
if (this.props.widget.customProperties.orientation !== nextProps.widget.customProperties.orientation) {
let baseWidget = nextProps.widget;
if (this.props.widget.customProperties.orientation !== prevProps.widget.customProperties.orientation) {
let baseWidget = this.props.widget;
// Exchange dimensions and constraints
let newWidget = Object.assign({}, baseWidget, {
@ -77,8 +87,9 @@ class WidgetSlider extends Component {
maxHeight: baseWidget.customProperties.maxWidth
});
nextProps.onWidgetChange(newWidget);
this.props.onWidgetChange(newWidget);
}
}
valueIsChanging(newValue) {
@ -141,4 +152,4 @@ export default WidgetSlider;
{ fields.value }
{ this.props.widget.customProperties.showUnit && fields.unit }
</div>
)*/
)*/

View file

@ -36,45 +36,55 @@ class WidgetTable extends Component {
};
}
componentWillReceiveProps(nextProps) {
if (nextProps.simulationModel == null) {
this.setState({ rows: [], sequence: null });
return;
static getDerivedStateFromProps(props, state){
if (props.simulationModel == null) {
return{
rows: [],
sequence: null,
};
}
const simulator = nextProps.simulationModel.simulator;
const simulator = props.simulationModel.simulator;
// check data
if (nextProps.data == null
|| nextProps.data[simulator] == null
|| nextProps.data[simulator].output == null
|| nextProps.data[simulator].output.values.length === 0
|| nextProps.data[simulator].output.values[0].length === 0) {
if (props.data == null
|| props.data[simulator] == null
|| props.data[simulator].output == null
|| props.data[simulator].output.values.length === 0
|| props.data[simulator].output.values[0].length === 0) {
// clear values
this.setState({ rows: [], sequence: null, showUnit: false });
return;
return{
rows: [],
sequence: null,
showUnit: false,
};
}
// check if new data, otherwise skip
/*if (this.state.sequence >= nextProps.data[simulator.node][simulator.simulator].sequence) {
/*if (state.sequence >= props.data[simulator.node][simulator.simulator].sequence) {
return;
}*/
// get rows
const rows = [];
nextProps.data[simulator].output.values.forEach((signal, index) => {
if (index < nextProps.simulationModel.outputMapping.length) {
props.data[simulator].output.values.forEach((signal, index) => {
if (index < props.simulationModel.outputMapping.length) {
rows.push({
name: nextProps.simulationModel.outputMapping[index].name,
unit: nextProps.simulationModel.outputMapping[index].type,
name: props.simulationModel.outputMapping[index].name,
unit: props.simulationModel.outputMapping[index].type,
value: signal[signal.length - 1].y
});
}
});
this.setState({ showUnit: nextProps.showUnit, rows: rows, sequence: nextProps.data[simulator].output.sequence });
return {
showUnit: props.showUnit,
rows: rows,
sequence: props.data[simulator].output.sequence
};
}
render() {

View file

@ -28,12 +28,12 @@ import { cimsvg } from 'libcimsvg';
// Do not show Pintura's grid
const pinturaGridStyle = {
display: 'none'
}
};
// Avoid another color in the frontend
const pinturaBackingStyle = {
fill: 'transparent'
}
};
// Center spinner
const spinnerContainerStyle = {
@ -42,16 +42,16 @@ const spinnerContainerStyle = {
display: 'flex',
justifyContent: 'center',
alignItems: 'center'
}
};
// Topology failed message
const msgContainerStyle = Object.assign({
backgroundColor: '#ececec'
},spinnerContainerStyle)
},spinnerContainerStyle);
const msgStyle = {
fontWeight: 'bold'
}
};
// Initialize functions
function attachComponentEvents() {
@ -105,10 +105,12 @@ class WidgetTopology extends React.Component {
detachComponentEvents();
}
componentWillReceiveProps(nextProps) {
const file = nextProps.files.find(file => file._id === nextProps.widget.customProperties.file);
componentDidUpdate(prevProps: Readonly<P>, prevState: Readonly<S>, snapshot: SS): void {
const file = this.props.files.find(file => file._id === this.props.widget.customProperties.file);
// Ensure model is requested only once or a different was selected
if (this.props.widget.customProperties.file !== nextProps.widget.customProperties.file || (this.state.dashboardState === 'initial' && file)) {
if (prevProps.widget.customProperties.file !== this.props.widget.customProperties.file
|| (prevState.dashboardState === 'initial' && file)) {
this.setState({'dashboardState': 'loading' });
if (file) {
fetch(new Request('/' + config.publicPathBase + file.path))
@ -141,7 +143,7 @@ class WidgetTopology extends React.Component {
}
} else {
// No file has been selected
if (!nextProps.widget.customProperties.file) {
if (!this.props.widget.customProperties.file) {
this.setState({
'dashboardState': 'show_message',
'message': 'Select a topology model first.'});

View file

@ -32,28 +32,31 @@ class WidgetValue extends Component {
};
}
componentWillReceiveProps(nextProps) {
if (nextProps.simulationModel == null) {
this.setState({ value: '' });
return;
static getDerivedStateFromProps(props, state){
if (props.simulationModel == null) {
return{ value: '' };
}
const simulator = nextProps.simulationModel.simulator;
const simulator = props.simulationModel.simulator;
// update value
if (nextProps.data == null || nextProps.data[simulator] == null || nextProps.data[simulator].output == null || nextProps.data[simulator].output.values == null) {
this.setState({ value: '' });
return;
if (props.data == null || props.data[simulator] == null || props.data[simulator].output == null || props.data[simulator].output.values == null) {
return{ value: '' };
}
//const unit = nextProps.simulationModel.outputMapping[nextProps.widget.customProperties.signal].type;
// TODO fixme (unit)
//const unit = props.simulationModel.outputMapping[props.widget.customProperties.signal].type;
const unit = 42;
// check if value has changed
const signal = nextProps.data[simulator].output.values[nextProps.widget.customProperties.signal];
if (signal != null && this.state.value !== signal[signal.length - 1].y) {
this.setState({ value: signal[signal.length - 1].y, unit });
const signal = props.data[simulator].output.values[props.widget.customProperties.signal];
if (signal != null && state.value !== signal[signal.length - 1].y) {
return {
value: signal[signal.length - 1].y,
unit: unit,
};
}
}
render() {