Completes main page
This commit is contained in:
154
app/src/components/FlexibleGraph.js
Normal file
154
app/src/components/FlexibleGraph.js
Normal file
@@ -0,0 +1,154 @@
|
||||
import React, { Component } from "react";
|
||||
import _ from "lodash";
|
||||
import moment from "moment";
|
||||
import { FlexibleWidthXYPlot, LineSeries, VerticalGridLines, HorizontalGridLines, XAxis, YAxis, DiscreteColorLegend, Crosshair} from "react-vis";
|
||||
import "../../../node_modules/react-vis/dist/style.css";
|
||||
|
||||
|
||||
|
||||
export function findClosestXValue(tagHistory, xval){
|
||||
const mapped = _.map(tagHistory, ({timestamp, value}) => {
|
||||
const timeInt = timestamp.getTime();
|
||||
return { dist: Math.abs(xval - timeInt), x: xval, y: value };
|
||||
});
|
||||
const sorted = _.orderBy(mapped, "dist", "asc");
|
||||
return(_.omit(sorted[0], "dist"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Map an array of objects to a graph-usable array of objects
|
||||
*
|
||||
* @param {Array} values - list of objects with timestame and value properties
|
||||
*
|
||||
* @returns {Array} list of objects with x and y properties
|
||||
*/
|
||||
export const mapTimestampAndValuePropToXY = (values) => {
|
||||
return _.map(values, ({timestamp, value}) => {
|
||||
return {x: (new Date(timestamp)).getTime(), y: value};
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
export class FlexibleGraph extends Component{
|
||||
constructor(props){
|
||||
super(props);
|
||||
// props.tagHistory
|
||||
// props.tags
|
||||
// props.tagDescriptions
|
||||
// props.units
|
||||
// props.round
|
||||
|
||||
this.state = {
|
||||
crosshairValues: []
|
||||
};
|
||||
}
|
||||
|
||||
tagsExist = () => {
|
||||
if (!this.props.tags){
|
||||
return false;
|
||||
}
|
||||
|
||||
_.forEach(this.props.tags, (tag) =>{
|
||||
if (!tag || !tag.value){
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
_.forEach(this.props.tagHistory, (tag) => {
|
||||
if( !tag || !tag.value) {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
renderLegendData = () =>{
|
||||
|
||||
if (!this.tagsExist()){
|
||||
return _.map(this.props.tagDescriptions, (desc) => {
|
||||
return {title: desc};
|
||||
});
|
||||
} else {
|
||||
return _.map(this.props.tagDescriptions, (desc, key) => {
|
||||
return {title: `${desc}: ${_.round(this.props.tags[key].value, this.props.round[key])} ${this.props.units[key]}`};
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
renderCrossHairData = (values) => {
|
||||
const mappedValues = _.map(this.props.tagDescriptions, (desc, key) => {
|
||||
return {title: desc, value: _.round(values[key].y, 1) + ` ${this.props.units[key]}`};
|
||||
});
|
||||
console.log(mappedValues, this.props.tagDescriptions);
|
||||
return mappedValues;
|
||||
}
|
||||
|
||||
renderTitleData = (values) => {
|
||||
return {title: "Time", value: moment(values[0].x).format("hh:mm A")};
|
||||
}
|
||||
|
||||
/**
|
||||
* Event handler for onMouseLeave.
|
||||
* @private
|
||||
*/
|
||||
_onMouseLeave = () => {
|
||||
this.setState({crosshairValues: []});
|
||||
}
|
||||
|
||||
/**
|
||||
* Event handler for onNearestX.
|
||||
* @param {Object} value Selected value.
|
||||
* @param {index} index Index of the value in the data array.
|
||||
* @private
|
||||
*/
|
||||
_onNearestX = (value) => {
|
||||
this.setState({
|
||||
crosshairValues: _.map(this.props.tagHistory, (tagHist) => {
|
||||
return findClosestXValue(tagHist, value.x);
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
render(){
|
||||
|
||||
const lineSeries = _.map(this.props.tagHistory, (tag, key) => {
|
||||
if(key === 0){
|
||||
return <LineSeries key={key} data={mapTimestampAndValuePropToXY(tag)} onNearestX={this._onNearestX} />;
|
||||
} else {
|
||||
return <LineSeries key={key} data={mapTimestampAndValuePropToXY(tag)} />;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
if(!this.tagsExist()){
|
||||
return <span className="flexible-graph-notags"></span>;
|
||||
}
|
||||
|
||||
return(
|
||||
<div className="flexible-graph">
|
||||
<FlexibleWidthXYPlot
|
||||
height={300}
|
||||
xType="time"
|
||||
onMouseLeave={this._onMouseLeave}
|
||||
>
|
||||
<VerticalGridLines />
|
||||
<HorizontalGridLines />
|
||||
<XAxis />
|
||||
<YAxis />
|
||||
{lineSeries}
|
||||
<Crosshair
|
||||
values={this.state.crosshairValues}
|
||||
titleFormat={this.renderTitleData}
|
||||
itemsFormat = {this.renderCrossHairData}
|
||||
/>
|
||||
</FlexibleWidthXYPlot>
|
||||
<DiscreteColorLegend
|
||||
items={this.renderLegendData()}
|
||||
orientation="horizontal"
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
86
app/src/components/LiquidGauge.js
Normal file
86
app/src/components/LiquidGauge.js
Normal file
@@ -0,0 +1,86 @@
|
||||
import React from "react";
|
||||
import { color } from "d3-color";
|
||||
import { interpolateRgb } from "d3-interpolate";
|
||||
import LiquidFillGauge from "react-liquid-gauge";
|
||||
|
||||
|
||||
export function renderLabel(props, inputVal){
|
||||
const value = Math.round(parseFloat(inputVal));
|
||||
const radius = Math.min(props.height / 2, props.width / 2);
|
||||
const textPixels = (props.textSize * radius / 2);
|
||||
const valueStyle = {
|
||||
fontSize: textPixels
|
||||
};
|
||||
const percentStyle = {
|
||||
fontSize: textPixels * 0.6
|
||||
};
|
||||
|
||||
return (
|
||||
<tspan>
|
||||
<tspan className="value" style={valueStyle}>{value}</tspan>
|
||||
<tspan style={percentStyle}>{props.percent}</tspan>
|
||||
</tspan>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
export function LiquidGauge(props){
|
||||
// tag, units, maxValue, label
|
||||
if (!props.tag){
|
||||
return <span className="liquidgauge-no-tags"></span>;
|
||||
}
|
||||
const tagValue = props.tag.value;
|
||||
const endColor = "#1F4788";
|
||||
const startColor = "#dc143c";
|
||||
|
||||
const radius = 100;
|
||||
const interpolate = interpolateRgb(startColor, endColor);
|
||||
const fillColor = interpolate(tagValue / props.maxValue);
|
||||
const gradientStops = [
|
||||
{
|
||||
key: "0%",
|
||||
stopColor: color(fillColor).darker(0.5).toString(),
|
||||
stopOpacity: 1,
|
||||
offset: "0%"
|
||||
},
|
||||
{
|
||||
key: "50%",
|
||||
stopColor: fillColor,
|
||||
stopOpacity: 0.75,
|
||||
offset: "50%"
|
||||
},
|
||||
{
|
||||
key: "100%",
|
||||
stopColor: color(fillColor).brighter(0.5).toString(),
|
||||
stopOpacity: 0.5,
|
||||
offset: "100%"
|
||||
}
|
||||
];
|
||||
|
||||
return (
|
||||
<div className={"col liquidfill lqdfill-" + props.tag.name} style={{textAlign: "center"}}>
|
||||
<h3>{props.label}</h3>
|
||||
<LiquidFillGauge
|
||||
style={{ margin: "0 auto" }}
|
||||
width={radius * 2}
|
||||
height={radius * 2}
|
||||
value={tagValue / props.maxValue * 100}
|
||||
percent={props.units}
|
||||
textSize={1}
|
||||
textOffsetX={0}
|
||||
textOffsetY={0}
|
||||
textRenderer={(props) => renderLabel(props, tagValue)}
|
||||
riseAnimation
|
||||
waveAnimation
|
||||
waveFrequency={3}
|
||||
waveAmplitude={2}
|
||||
gradient
|
||||
gradientStops={gradientStops}
|
||||
circleStyle={{fill: fillColor}}
|
||||
waveStyle={{fill: fillColor}}
|
||||
textStyle={{fill: color("#444").toString(), fontFamily: "Arial"}}
|
||||
waveTextStyle={{fill: color("#fff").toString(), fontFamily: "Arial"}}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,128 +1,16 @@
|
||||
import React, { Component } from "react";
|
||||
import _ from "lodash";
|
||||
import { connect } from "react-redux";
|
||||
import { FlexibleWidthXYPlot, LineSeries, VerticalGridLines, HorizontalGridLines, XAxis, YAxis, DiscreteColorLegend } from "react-vis";
|
||||
import "../../../node_modules/react-vis/dist/style.css";
|
||||
|
||||
import { color } from "d3-color";
|
||||
import { interpolateRgb } from "d3-interpolate";
|
||||
import LiquidFillGauge from "react-liquid-gauge";
|
||||
import { LiquidGauge } from "./LiquidGauge";
|
||||
import { FlexibleGraph } from "./FlexibleGraph";
|
||||
|
||||
// const graphColors = ["#d7191c", "#fdae61", "#ffffbf", "#abd9e9", "#2c7bb6"];
|
||||
|
||||
/** Class for Main Page
|
||||
*
|
||||
* @extends React.Component
|
||||
*/
|
||||
export class Main extends Component {
|
||||
|
||||
/**
|
||||
* Map an array of objects to a graph-usable array of objects
|
||||
*
|
||||
* @param {Array} values - list of objects with timestame and value properties
|
||||
*
|
||||
* @returns {Array} list of objects with x and y properties
|
||||
*/
|
||||
mapTimestampAndValuePropToXY(values){
|
||||
return _.map(values, (val) => {
|
||||
return {x: val.timestamp, y: val.value};
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders a Liquid Gauge.
|
||||
*
|
||||
* @param {object} tag - the tag structure
|
||||
* @param {string} units - units for the tag
|
||||
* @param {number} maxValue - maximum value to be displayed
|
||||
* @param {number} label - label for the value (typically the tag name)
|
||||
* @returns {ReactElement} liquidGauge
|
||||
*/
|
||||
renderLiquidGauge(tag, units, maxValue, label){
|
||||
if (!tag){
|
||||
return <span></span>;
|
||||
}
|
||||
const tagValue = tag.value;
|
||||
const endColor = "#1F4788";
|
||||
const startColor = "#dc143c";
|
||||
|
||||
const radius = 100;
|
||||
const interpolate = interpolateRgb(startColor, endColor);
|
||||
const fillColor = interpolate(tagValue / maxValue);
|
||||
const gradientStops = [
|
||||
{
|
||||
key: "0%",
|
||||
stopColor: color(fillColor).darker(0.5).toString(),
|
||||
stopOpacity: 1,
|
||||
offset: "0%"
|
||||
},
|
||||
{
|
||||
key: "50%",
|
||||
stopColor: fillColor,
|
||||
stopOpacity: 0.75,
|
||||
offset: "50%"
|
||||
},
|
||||
{
|
||||
key: "100%",
|
||||
stopColor: color(fillColor).brighter(0.5).toString(),
|
||||
stopOpacity: 0.5,
|
||||
offset: "100%"
|
||||
}
|
||||
];
|
||||
|
||||
return (
|
||||
<div className={"col liquidfill lqdfill-" + tag.name} style={{textAlign: "center"}}>
|
||||
<h3>{label}</h3>
|
||||
<LiquidFillGauge
|
||||
style={{ margin: "0 auto" }}
|
||||
width={radius * 2}
|
||||
height={radius * 2}
|
||||
value={tagValue / maxValue * 100}
|
||||
percent={units}
|
||||
textSize={1}
|
||||
textOffsetX={0}
|
||||
textOffsetY={0}
|
||||
textRenderer={(props) => {
|
||||
const value = Math.round(tagValue);
|
||||
const radius = Math.min(props.height / 2, props.width / 2);
|
||||
const textPixels = (props.textSize * radius / 2);
|
||||
const valueStyle = {
|
||||
fontSize: textPixels
|
||||
};
|
||||
const percentStyle = {
|
||||
fontSize: textPixels * 0.6
|
||||
};
|
||||
|
||||
return (
|
||||
<tspan>
|
||||
<tspan className="value" style={valueStyle}>{value}</tspan>
|
||||
<tspan style={percentStyle}>{props.percent}</tspan>
|
||||
</tspan>
|
||||
);
|
||||
}}
|
||||
riseAnimation
|
||||
waveAnimation
|
||||
waveFrequency={3}
|
||||
waveAmplitude={2}
|
||||
gradient
|
||||
gradientStops={gradientStops}
|
||||
circleStyle={{
|
||||
fill: fillColor
|
||||
}}
|
||||
waveStyle={{
|
||||
fill: fillColor
|
||||
}}
|
||||
textStyle={{
|
||||
fill: color("#444").toString(),
|
||||
fontFamily: "Arial"
|
||||
}}
|
||||
waveTextStyle={{
|
||||
fill: color("#fff").toString(),
|
||||
fontFamily: "Arial"
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* render
|
||||
@@ -130,7 +18,8 @@ export class Main extends Component {
|
||||
* @returns {ReactElement} markup
|
||||
*/
|
||||
render(){
|
||||
if (!this.props.tagHistory){
|
||||
|
||||
if (!this.props.tagHistory || Object.keys(this.props.tagHistory).length === 0){
|
||||
return(
|
||||
<div className="container loading">
|
||||
<h1>Loading...</h1>
|
||||
@@ -147,7 +36,25 @@ export class Main extends Component {
|
||||
);
|
||||
}
|
||||
|
||||
if (Object.keys(this.props.tags).length === 0){
|
||||
if (!this.props.tags ||
|
||||
!this.props.tagHistory ||
|
||||
!this.props.tags.val_FluidLevel ||
|
||||
!this.props.tags.val_Flowmeter_BarrelsPerDay ||
|
||||
!this.props.tags.val_TubingPressure ||
|
||||
!this.props.tags.VFD_SpeedFdbk ||
|
||||
!this.props.tags.VFD_OutCurrent ||
|
||||
!this.props.tags.VFD_OutPower ||
|
||||
!this.props.tags.VFD_Temp ||
|
||||
!this.props.tagHistory.val_FluidLevel ||
|
||||
!this.props.tagHistory.val_Flowmeter_BarrelsPerDay ||
|
||||
!this.props.tagHistory.val_IntakePressure ||
|
||||
!this.props.tagHistory.val_IntakeTemperature ||
|
||||
!this.props.tagHistory.val_TubingPressure ||
|
||||
!this.props.tagHistory.VFD_SpeedFdbk ||
|
||||
!this.props.tagHistory.VFD_OutCurrent ||
|
||||
!this.props.tagHistory.VFD_OutPower ||
|
||||
!this.props.tagHistory.VFD_Temp
|
||||
){
|
||||
return(
|
||||
<div className="container waiting">
|
||||
<h1>Waiting for data...</h1>
|
||||
@@ -155,69 +62,81 @@ export class Main extends Component {
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
return (
|
||||
<div className="container main">
|
||||
<h3>Process Values</h3>
|
||||
<div className="row" style={{marginBottom: "20px"}}>
|
||||
{this.renderLiquidGauge(this.props.tags.val_FluidLevel, "ft.", 500, "Level")}
|
||||
{this.renderLiquidGauge(this.props.tags.val_Flowmeter_BarrelsPerDay, "BPD", 5000, "Flow Rate")}
|
||||
{this.renderLiquidGauge(this.props.tags.val_TubingPressure, "PSI", 400, "Tubing Pressure")}
|
||||
<LiquidGauge tag={this.props.tags.val_FluidLevel} units="ft." maxValue={500} label="Level" />
|
||||
<LiquidGauge tag={this.props.tags.val_Flowmeter_BarrelsPerDay} units="BPD" maxValue={5000} label="Flow Rate" />
|
||||
<LiquidGauge tag={this.props.tags.val_TubingPressure} units="PSI" maxValue={400} label="Tubing Pressure" />
|
||||
</div>
|
||||
|
||||
<FlexibleWidthXYPlot
|
||||
height={300}
|
||||
xType="time"
|
||||
>
|
||||
<VerticalGridLines />
|
||||
<HorizontalGridLines />
|
||||
<XAxis />
|
||||
<YAxis />
|
||||
<LineSeries data={this.mapTimestampAndValuePropToXY(this.props.tagHistory.val_IntakePressure)} />
|
||||
<LineSeries data={this.mapTimestampAndValuePropToXY(this.props.tagHistory.val_Flowmeter)} />
|
||||
<LineSeries data={this.mapTimestampAndValuePropToXY(this.props.tagHistory.val_FluidLevel)} />
|
||||
<LineSeries data={this.mapTimestampAndValuePropToXY(this.props.tagHistory.val_IntakeTemperature)} />
|
||||
<LineSeries data={this.mapTimestampAndValuePropToXY(this.props.tagHistory.val_TubingPressure)} />
|
||||
</FlexibleWidthXYPlot>
|
||||
<DiscreteColorLegend
|
||||
items={[
|
||||
{title: "Intake Pressure"},
|
||||
{title: "Flowmeter"},
|
||||
{title: "Fluid Level"},
|
||||
{title: "Intake Temp"},
|
||||
{title: "Tubing Pressure"}
|
||||
<FlexibleGraph
|
||||
tagHistory={[
|
||||
this.props.tagHistory.val_FluidLevel,
|
||||
this.props.tagHistory.val_Flowmeter,
|
||||
this.props.tagHistory.val_IntakePressure,
|
||||
this.props.tagHistory.val_IntakeTemperature,
|
||||
this.props.tagHistory.val_TubingPressure
|
||||
]}
|
||||
orientation="horizontal"
|
||||
tags={[
|
||||
this.props.tags.val_FluidLevel,
|
||||
this.props.tags.val_Flowmeter,
|
||||
this.props.tags.val_IntakePressure,
|
||||
this.props.tags.val_IntakeTemperature,
|
||||
this.props.tags.val_TubingPressure
|
||||
]}
|
||||
tagDescriptions={[
|
||||
"Level",
|
||||
"Flow Rate",
|
||||
"Intake Pres",
|
||||
"Intake Temp",
|
||||
"Tubing Pres"
|
||||
]}
|
||||
units={[
|
||||
"Ft.",
|
||||
"GPM",
|
||||
"PSI",
|
||||
"deg F",
|
||||
"PSI"
|
||||
]}
|
||||
round={[1, 2, 1, 1, 1]}
|
||||
/>
|
||||
<hr />
|
||||
|
||||
<h3>VFD Data</h3>
|
||||
<div className="row" style={{marginBottom: "20px"}}>
|
||||
{this.renderLiquidGauge(this.props.tags.VFD_OutCurrent, "A.", 100, "Current")}
|
||||
{this.renderLiquidGauge(this.props.tags.VFD_SpeedFdbk, "Hz", 60, "Frequency")}
|
||||
<LiquidGauge tag={this.props.tags.VFD_OutCurrent} units="A." maxValue={100} label="Current" />
|
||||
<LiquidGauge tag={this.props.tags.VFD_SpeedFdbk} units="Hz" maxValue={60} label="Frequency" />
|
||||
</div>
|
||||
<FlexibleWidthXYPlot
|
||||
height={300}
|
||||
xType="time"
|
||||
>
|
||||
<VerticalGridLines />
|
||||
<HorizontalGridLines />
|
||||
<XAxis />
|
||||
<YAxis />
|
||||
<LineSeries data={this.mapTimestampAndValuePropToXY(this.props.tagHistory.VFD_OutCurrent)} />
|
||||
<LineSeries data={this.mapTimestampAndValuePropToXY(this.props.tagHistory.VFD_SpeedFdbk)} />
|
||||
<LineSeries data={this.mapTimestampAndValuePropToXY(this.props.tagHistory.VFD_OutPower)} />
|
||||
<LineSeries data={this.mapTimestampAndValuePropToXY(this.props.tagHistory.VFD_Temp)} />
|
||||
</FlexibleWidthXYPlot>
|
||||
<DiscreteColorLegend
|
||||
items={[
|
||||
{title: "VFD Current"},
|
||||
{title: "VFD Speed Feedback"},
|
||||
{title: "VFD Output Power"},
|
||||
{title: "VFD Temp"}
|
||||
<FlexibleGraph
|
||||
tagHistory={[
|
||||
this.props.tagHistory.VFD_SpeedFdbk,
|
||||
this.props.tagHistory.VFD_OutCurrent,
|
||||
this.props.tagHistory.VFD_OutPower,
|
||||
this.props.tagHistory.VFD_Temp
|
||||
]}
|
||||
orientation="horizontal"
|
||||
/>
|
||||
tags={[
|
||||
this.props.tags.VFD_SpeedFdbk,
|
||||
this.props.tags.VFD_OutCurrent,
|
||||
this.props.tags.VFD_OutPower,
|
||||
this.props.tags.VFD_Temp
|
||||
]}
|
||||
tagDescriptions={[
|
||||
"Speed",
|
||||
"Current",
|
||||
"Power",
|
||||
"Temp"
|
||||
]}
|
||||
units={[
|
||||
"Hz",
|
||||
"Amps",
|
||||
"kW",
|
||||
"deg C"
|
||||
]}
|
||||
round={[2, 2, 1, 1]}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -77,18 +77,18 @@ export class Settings extends Component {
|
||||
return (
|
||||
<div className="container settings">
|
||||
<h1>Settings</h1>
|
||||
<form className="form-inline mb-2">
|
||||
<form className="form-inline">
|
||||
<div className="form-group">
|
||||
<label htmlFor="ipAddress">IP Address</label>
|
||||
<input
|
||||
id="ipAddress"
|
||||
className="form-control ip-address-field"
|
||||
className="form-control ip-address-field m-2"
|
||||
value={this.state.ipAddress}
|
||||
placeholder="PLC IP Address"
|
||||
onChange={this.onIpAddressInputChange}
|
||||
/>
|
||||
<button
|
||||
className={ipAddressBtnClass + " btn btn-primary ip-submit-button"}
|
||||
className={ipAddressBtnClass + " btn btn-primary ip-submit-button m-2"}
|
||||
onClick={(e) => this.sendIpAddress(e)}>
|
||||
Set IP Address
|
||||
</button>
|
||||
@@ -100,23 +100,35 @@ export class Settings extends Component {
|
||||
<ul className="list-group tag-list">
|
||||
{this.getTagList()}
|
||||
</ul>
|
||||
<form>
|
||||
<input
|
||||
value={this.state.newTag}
|
||||
onChange={this.onNewTagChange}
|
||||
placeholder="New Tag Name..."
|
||||
className="tag-name-input"
|
||||
/>
|
||||
<button
|
||||
className="btn btn-success float-right add-tag-button"
|
||||
onClick={(e) => this.onNewTagSubmit(e)}
|
||||
>Add Tag</button>
|
||||
|
||||
<hr />
|
||||
|
||||
<form className="form-inline">
|
||||
<div className="form-group">
|
||||
<label htmlFor="tag-name-input">New Tag</label>
|
||||
<input
|
||||
value={this.state.newTag}
|
||||
onChange={this.onNewTagChange}
|
||||
placeholder="New Tag Name..."
|
||||
className="tag-name-input form-control m-2"
|
||||
id="tag-name-input"
|
||||
/>
|
||||
<button
|
||||
className="btn btn-success float-right add-tag-button m-2"
|
||||
onClick={(e) => this.onNewTagSubmit(e)}
|
||||
>Add Tag</button>
|
||||
</div>
|
||||
</form>
|
||||
<hr />
|
||||
<div>
|
||||
<button
|
||||
className={initializeBtnClass + " btn btn-success save-button"}
|
||||
onClick={(e) => this.onSave(e)}
|
||||
>Save</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -2,6 +2,8 @@ import _ from "lodash";
|
||||
import { IPC_TAGUPDATE } from "../actions/actions_tags";
|
||||
import {history_tags as historyTags} from "../../../tagList.json";
|
||||
|
||||
const historyPoints = 50000;
|
||||
|
||||
|
||||
export default function(state = {}, action){
|
||||
switch (action.type) {
|
||||
@@ -14,7 +16,7 @@ export default function(state = {}, action){
|
||||
};
|
||||
let tagHistory = [ thisEntry ];
|
||||
if (state[name]){
|
||||
tagHistory = _.take(_.concat(tagHistory, state[name]), 500);
|
||||
tagHistory = _.take(_.concat(tagHistory, state[name]), historyPoints);
|
||||
}
|
||||
return { ...state, [name]: tagHistory};
|
||||
|
||||
|
||||
@@ -20,6 +20,8 @@ import { ipcTagUpdate } from "./actions/actions_tags";
|
||||
import { ipcPlcDetailsReceived, ipcPlcErrorReceived } from "./actions/actions_plc";
|
||||
|
||||
export const { history_tags: historyTags, event_tags: eventTags } = require("../../tagList.json");
|
||||
export const historyPoints = 5000;
|
||||
|
||||
|
||||
const ipc = createIpc({
|
||||
"tag:valueupdate": ipcTagUpdate,
|
||||
|
||||
Reference in New Issue
Block a user