diff --git a/src/api/rest-api.js b/src/api/rest-api.js
index 40329c2..d01e996 100644
--- a/src/api/rest-api.js
+++ b/src/api/rest-api.js
@@ -10,17 +10,10 @@
import request from 'superagent/lib/client';
import Promise from 'es6-promise';
-const API_URL = 'http://localhost:4000/api/v1';
-
-function makeURL(part) {
- // TODO: Add / if missing at front of part
- return API_URL + part;
-}
-
class RestAPI {
get(url) {
return new Promise(function (resolve, reject) {
- request.get(makeURL(url)).end(function (error, res) {
+ request.get(url).set('Access-Control-Allow-Origin', '*').end(function (error, res) {
if (res == null || res.status !== 200) {
reject(error);
} else {
@@ -32,7 +25,7 @@ class RestAPI {
post(url, body) {
return new Promise(function (resolve, reject) {
- request.post(makeURL(url)).send(body).end(function (error, res) {
+ request.post(url).send(body).end(function (error, res) {
if (res == null || res.status !== 200) {
reject(error);
} else {
@@ -44,7 +37,7 @@ class RestAPI {
delete(url) {
return new Promise(function (resolve, reject) {
- request.delete(makeURL(url)).end(function (error, res) {
+ request.delete(url).end(function (error, res) {
if (res == null || res.status !== 200) {
reject(error);
} else {
@@ -56,7 +49,7 @@ class RestAPI {
put(url, body) {
return new Promise(function (resolve, reject) {
- request.put(makeURL(url)).send(body).end(function (error, res) {
+ request.put(url).send(body).end(function (error, res) {
if (res == null || res.status !== 200) {
reject(error);
} else {
diff --git a/src/components/widget-plot.js b/src/components/widget-plot.js
index fad5f0c..140a0f6 100644
--- a/src/components/widget-plot.js
+++ b/src/components/widget-plot.js
@@ -11,55 +11,73 @@ import React, { Component } from 'react';
import { LineChart } from 'rd3';
class WidgetPlot extends Component {
+ constructor(props) {
+ super(props);
+
+ this.state = {
+ values: [],
+ firstTimestamp: 0,
+ latestTimestamp: 0,
+ sequence: null
+ };
+ }
+
+ componentWillReceiveProps(nextProps) {
+ // check data
+ const simulator = nextProps.widget.simulator;
+
+ if (nextProps.simulation == null || nextProps.data == null || nextProps.data[simulator] == null || nextProps.data[simulator].length === 0 || nextProps.data[simulator].values[0].length === 0) {
+ // clear values
+ this.setState({ values: [], sequence: null });
+ return;
+ }
+
+ // check if new data, otherwise skip
+ if (this.state.sequence >= nextProps.data[simulator].sequence) {
+ return;
+ }
+
+ // get timestamps
+ const latestTimestamp = nextProps.data[simulator].values[0][nextProps.data[simulator].values[0].length - 1].x;
+ const firstTimestamp = latestTimestamp - nextProps.widget.time * 100;
+
+ // find element index representing firstTimestamp
+ const firstIndex = nextProps.data[simulator].values[0].findIndex((value) => {
+ return value.x >= firstTimestamp;
+ });
+
+ // copy all values for each signal in time region
+ var values = [];
+
+ nextProps.widget.signals.forEach((signal) => {
+ values.push({
+ values: nextProps.data[simulator].values[signal].slice(firstIndex, nextProps.data[simulator].values[signal].length - 1)
+ });
+ });
+
+ this.setState({ values: values, firstTimestamp: firstTimestamp, latestTimestamp: latestTimestamp, sequence: nextProps.data[simulator].sequence });
+ }
+
render() {
- // get selected simulation model
- const widget = this.props.widget;
- var simulationModel;
-
- if (this.props.simulation && this.props.simulation.models && this.props.data[widget.simulator]) {
- this.props.simulation.models.forEach((model) => {
- if (model.simulator === widget.simulator) {
- simulationModel = model;
- }
- });
- } else {
- return (
);
+ if (this.state.sequence == null) {
+ return (Empty
);
}
- if (widget.plotType === 'table') {
- return (
- Table
- );
- } else if (widget.plotType === 'multiple') {
- // get selected data
- var lineData = [];
- const latestTimestamp = this.props.data[widget.simulator].values[0][this.props.data[widget.simulator].values[0].length - 1].x;
-
- widget.signals.forEach((signal) => {
- lineData.push({
- name: simulationModel.mapping[signal].name,
- values: this.props.data[widget.simulator].values[signal]
- });
- });
-
- return (
-
- {return new Date(d.x);}}
- hoverAnimation={false}
- circleRadius={0}
- domain={{ x: [latestTimestamp - 10000, latestTimestamp] }}
- />
-
- );
- } else {
- return (Error
);
- }
+ return (
+
+ {return new Date(d.x);}}
+ hoverAnimation={false}
+ circleRadius={0}
+ domain={{ x: [this.state.firstTimestamp, this.state.latestTimestamp] }}
+ />
+
+ );
}
}
diff --git a/src/components/widget-value.js b/src/components/widget-value.js
index 92987b6..c096695 100644
--- a/src/components/widget-value.js
+++ b/src/components/widget-value.js
@@ -10,19 +10,34 @@
import React, { Component } from 'react';
class WidgetValue extends Component {
- render() {
- // calculate value
- var value = null;
- const widget = this.props.widget;
+ constructor(props) {
+ super(props);
- if (this.props.data && this.props.data[widget.simulator] && this.props.data[widget.simulator].values) {
- const signalArray = this.props.data[widget.simulator].values[widget.signal];
- value = signalArray[signalArray.length - 1].y;
+ this.state = {
+ value: ''
+ };
+ }
+
+ componentWillReceiveProps(nextProps) {
+ // update value
+ const simulator = nextProps.widget.simulator;
+
+ if (nextProps.data == null || nextProps.data[simulator] == null || nextProps.data[simulator].values == null) {
+ this.setState({ value: '' });
+ return;
}
+ // check if value has changed
+ const signal = nextProps.data[simulator].values[nextProps.widget.signal];
+ if (this.state.value !== signal[signal.length - 1].y) {
+ this.setState({ value: signal[signal.length - 1].y });
+ }
+ }
+
+ render() {
return (
- {widget.name}: {value}
+ {this.props.widget.name}: {this.state.value}
);
}
diff --git a/src/containers/visualization.js b/src/containers/visualization.js
index 13dea0f..827d57d 100644
--- a/src/containers/visualization.js
+++ b/src/containers/visualization.js
@@ -117,8 +117,10 @@ class Visualization extends Component {
widget.signal = 0;
} else if (item.name === 'Plot') {
widget.simulator = this.state.simulation.models[0].simulator;
- widget.plotType = 'multiple';
widget.signals = [ 0 ];
+ widget.time = 300;
+ widget.width = 400;
+ widget.height = 200;
}
var visualization = this.state.visualization;
diff --git a/src/containers/widget.js b/src/containers/widget.js
index d6ac0d8..680cc6f 100644
--- a/src/containers/widget.js
+++ b/src/containers/widget.js
@@ -69,9 +69,9 @@ class Widget extends Component {
var element = null;
if (widget.type === 'Value') {
- element =
+ element =
} else if (widget.type === 'Plot') {
- element =
+ element =
}
if (this.props.editing) {
diff --git a/src/data-managers/rest-data-manager.js b/src/data-managers/rest-data-manager.js
index 0b5d178..5c5c68c 100644
--- a/src/data-managers/rest-data-manager.js
+++ b/src/data-managers/rest-data-manager.js
@@ -10,16 +10,22 @@
import RestAPI from '../api/rest-api';
import AppDispatcher from '../app-dispatcher';
+const API_URL = 'http://localhost:4000/api/v1';
+
class RestDataManager {
constructor(type, url) {
this.url = url;
this.type = type;
}
+ makeURL(part) {
+ return API_URL + part;
+ }
+
load(id) {
if (id != null) {
// load single object
- RestAPI.get(this.url + '/' + id).then(response => {
+ RestAPI.get(this.makeURL(this.url + '/' + id)).then(response => {
AppDispatcher.dispatch({
type: this.type + 's/loaded',
data: response[this.type]
@@ -32,7 +38,7 @@ class RestDataManager {
});
} else {
// load all objects
- RestAPI.get(this.url).then(response => {
+ RestAPI.get(this.makeURL(this.url)).then(response => {
AppDispatcher.dispatch({
type: this.type + 's/loaded',
data: response[this.type + 's']
@@ -50,7 +56,7 @@ class RestDataManager {
var obj = {};
obj[this.type] = object;
- RestAPI.post(this.url, obj).then(response => {
+ RestAPI.post(this.makeURL(this.url), obj).then(response => {
AppDispatcher.dispatch({
type: this.type + 's/added',
data: response[this.type]
@@ -64,7 +70,7 @@ class RestDataManager {
}
remove(object) {
- RestAPI.delete(this.url + '/' + object._id).then(response => {
+ RestAPI.delete(this.makeURL(this.url + '/' + object._id)).then(response => {
AppDispatcher.dispatch({
type: this.type + 's/removed',
data: response[this.type],
@@ -82,7 +88,7 @@ class RestDataManager {
var obj = {};
obj[this.type] = object;
- RestAPI.put(this.url + '/' + object._id, obj).then(response => {
+ RestAPI.put(this.makeURL(this.url + '/' + object._id), obj).then(response => {
AppDispatcher.dispatch({
type: this.type + 's/edited',
data: response[this.type]
diff --git a/src/data-managers/simulator-data-data-manager.js b/src/data-managers/simulator-data-data-manager.js
index 2dffa9a..aded151 100644
--- a/src/data-managers/simulator-data-data-manager.js
+++ b/src/data-managers/simulator-data-data-manager.js
@@ -23,9 +23,13 @@ class SimulatorDataDataManager {
this._sockets.close();
this._sockets[identifier] = WebsocketAPI.addSocket(endpoint, { onOpen: (event) => this.onOpen(event, identifier, signals), onClose: (event) => this.onClose(event, identifier), onMessage: (event) => this.onMessage(event, identifier) });
+
+ console.log('Modified socket');
}
} else {
this._sockets[identifier] = WebsocketAPI.addSocket(endpoint, { onOpen: (event) => this.onOpen(event, identifier, signals), onClose: (event) => this.onClose(event, identifier), onMessage: (event) => this.onMessage(event, identifier) });
+
+ console.log('New socket');
}
}
@@ -47,6 +51,8 @@ class SimulatorDataDataManager {
onMessage(event, identifier) {
var message = this.bufferToMessage(event.data);
+ //console.log(message);
+
AppDispatcher.dispatch({
type: 'simulatorData/data-changed',
data: message,
diff --git a/src/stores/simulator-data-store.js b/src/stores/simulator-data-store.js
index 1fe5816..fb97e8f 100644
--- a/src/stores/simulator-data-store.js
+++ b/src/stores/simulator-data-store.js
@@ -12,7 +12,7 @@ import { ReduceStore } from 'flux/utils';
import AppDispatcher from '../app-dispatcher';
import SimulatorDataDataManager from '../data-managers/simulator-data-data-manager';
-const MAX_VALUES = 100;
+const MAX_VALUES = 1000;
class SimulationDataStore extends ReduceStore {
constructor() {
@@ -39,27 +39,34 @@ class SimulationDataStore extends ReduceStore {
state[action.identifier].values.push([]);
}
+ console.log('Socket opened');
+
return state;
case 'simulatorData/data-changed':
- // add data to simulator
- for (i = 0; i < state[action.identifier].signals; i++) {
- state[action.identifier].values[i].push({ x: action.data.timestamp, y: action.data.values[i] });
+ // only add data, if newer than current
+ if (state[action.identifier].sequence < action.data.sequence) {
+ // add data to simulator
+ for (i = 0; i < state[action.identifier].signals; i++) {
+ state[action.identifier].values[i].push({ x: action.data.timestamp, y: action.data.values[i] });
- // erase old values
- if (state[action.identifier].values[i].length > MAX_VALUES) {
- const pos = state[action.identifier].values[i].length - MAX_VALUES;
- state[action.identifier].values[i].splice(0, pos);
+ // erase old values
+ if (state[action.identifier].values[i].length > MAX_VALUES) {
+ const pos = state[action.identifier].values[i].length - MAX_VALUES;
+ state[action.identifier].values[i].splice(0, pos);
+ }
}
+
+ // update metadata
+ state[action.identifier].timestamp = action.data.timestamp;
+ state[action.identifier].sequence = action.data.sequence;
+
+ // explicit call to prevent array copy
+ this.__emitChange();
+ } else {
+ console.log('same sequence');
}
- // update metadata
- state[action.identifier].timestamp = action.data.timestamp;
- state[action.identifier].sequence = action.data.sequence;
-
- // explicit call to prevent array copy
- this.__emitChange();
-
return state;
case 'simulatorData/closed':