diff --git a/src/app.js b/src/app.js
index cf4ce3b..b077ea9 100644
--- a/src/app.js
+++ b/src/app.js
@@ -31,6 +31,7 @@ import Footer from './common/footer';
import Menu from './common/menu';
import InfrastructureComponents from './ic/ics';
+import InfrastructureComponent from './ic/ic';
import Dashboard from './dashboard/dashboard';
import Scenarios from './scenario/scenarios';
import Scenario from './scenario/scenario';
@@ -117,7 +118,8 @@ class App extends React.Component {
-
+
+
diff --git a/src/common/table.js b/src/common/table.js
index c5edd2e..dfba04f 100644
--- a/src/common/table.js
+++ b/src/common/table.js
@@ -291,7 +291,7 @@ class CustomTable extends Component {
for (let child of props.children) {
// check whether empty <>> object has been given
- if (Object.keys(child.props).length != 0) {
+ if (Object.keys(child.props).length !== 0) {
row.push(CustomTable.addCell(data, index, child));
}
}
diff --git a/src/ic/ic-dialog.js b/src/ic/ic-dialog.js
deleted file mode 100644
index 25fe61a..0000000
--- a/src/ic/ic-dialog.js
+++ /dev/null
@@ -1,195 +0,0 @@
-import React from 'react';
-import { Button, Row, Col } from 'react-bootstrap';
-import Dialog from '../common/dialogs/dialog';
-import Icon from "../common/icon";
-import ConfirmCommand from './confirm-command';
-import ReactJson from 'react-json-view';
-import FileSaver from 'file-saver';
-import moment from 'moment';
-
-class ICDialog extends React.Component {
- valid = true;
-
- constructor(props) {
- super(props);
-
- this.state = {
- confirmCommand: false,
- command: '',
- };
- }
-
- onClose(canceled) {
- this.props.onClose();
- }
-
- handleChange(e) {
-
- }
-
- showFurtherInfo(key){
- if(typeof this.state[key] === 'undefined') this.setState({[key]: false});
- this.setState({[key]: !this.state[key]});
- }
-
- closeConfirmModal(canceled){
- if(!canceled){
- this.props.sendControlCommand(this.state.command,this.props.ic);
- }
-
- this.setState({confirmCommand: false, command: ''});
- }
-
- async downloadGraph(url) {
-
- let blob = await fetch(url).then(r => r.blob())
- FileSaver.saveAs(blob, this.props.ic.name + ".svg");
- }
-
- isJSON(data){
- if (data === undefined || data === null){
- return false;
- }
- let str = JSON.stringify(data);
- try
- {
- JSON.parse(str)
- }
- catch(ex){
- return false
- }
-
- return true
- }
-
-
- render() {
-
- let graphURL = ""
- if (this.props.ic.apiurl !== ""){
- graphURL = this.props.ic.apiurl + "/graph.svg"
- }
-
- return (
-
- );
- }
-}
-
-export default ICDialog;
diff --git a/src/ic/ic.js b/src/ic/ic.js
new file mode 100644
index 0000000..9bb730f
--- /dev/null
+++ b/src/ic/ic.js
@@ -0,0 +1,240 @@
+/**
+ * This file is part of VILLASweb.
+ *
+ * VILLASweb is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * VILLASweb is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with VILLASweb. If not, see .
+ ******************************************************************************/
+
+import React from 'react';
+import InfrastructureComponentStore from './ic-store';
+import { Container as FluxContainer } from 'flux/utils';
+import AppDispatcher from '../common/app-dispatcher';
+import { Container, Col, Row, Table, Button } from 'react-bootstrap';
+import moment from 'moment';
+import ReactJson from 'react-json-view';
+import ConfirmCommand from './confirm-command';
+import Icon from "../common/icon";
+
+
+
+class InfrastructureComponent extends React.Component {
+ constructor(props) {
+ super(props);
+
+ this.state = {
+ confirmCommand: false,
+ command: '',
+ };
+ }
+
+ static getStores() {
+ return [InfrastructureComponentStore];
+ }
+
+ static calculateState(prevState, props) {
+ if (prevState == null) {
+ prevState = {};
+ }
+
+ return {
+ sessionToken: localStorage.getItem("token"),
+ currentUser: JSON.parse(localStorage.getItem("currentUser")),
+ ic: InfrastructureComponentStore.getState().find(ic => ic.id === parseInt(props.match.params.ic, 10))
+ }
+ }
+
+ componentDidMount() {
+ let icID = parseInt(this.props.match.params.ic, 10);
+
+ AppDispatcher.dispatch({
+ type: 'ics/start-load',
+ data: icID,
+ token: this.state.sessionToken,
+ });
+ }
+
+ isJSON(data) {
+ if (data === undefined || data === null) {
+ return false;
+ }
+ let str = JSON.stringify(data);
+ try {
+ JSON.parse(str)
+ }
+ catch (ex) {
+ return false
+ }
+ return true
+ }
+
+ async downloadGraph(url) {
+ let blob = await fetch(url).then(r => r.blob())
+ FileSaver.saveAs(blob, this.state.ic.name + ".svg");
+ }
+
+ sendControlCommand() {
+ if (this.state.command === "restart") {
+ AppDispatcher.dispatch({
+ type: 'ics/restart',
+ url: this.state.ic.apiurl + "/restart",
+ token: this.state.sessionToken,
+ });
+ } else if (this.state.command === "shutdown") {
+ AppDispatcher.dispatch({
+ type: 'ics/shutdown',
+ url: this.state.ic.apiurl + "/shutdown",
+ token: this.state.sessionToken,
+ });
+ }
+ }
+
+ confirmCommand(canceled){
+ if(!canceled){
+ this.sendControlCommand();
+ }
+
+ this.setState({confirmCommand: false, command: ''});
+ }
+
+ async downloadGraph(url) {
+
+ let blob = await fetch(url).then(r => r.blob())
+ FileSaver.saveAs(blob, this.props.ic.name + ".svg");
+ }
+
+ render() {
+ if (this.state.ic === undefined) {
+ return
Loading Infrastructure Component...
;
+ }
+
+ let graphURL = ""
+ if (this.state.ic.apiurl !== "") {
+ graphURL = this.state.ic.apiurl + "/graph.svg"
+ }
+
+ return
+
{this.state.ic.name}
+
+
+
+
+
+
+ Name |
+ {this.state.ic.name} |
+
+
+ Description |
+ {this.state.ic.description} |
+
+
+ UUID |
+ {this.state.ic.uuid} |
+
+
+ State |
+ {this.state.ic.state} |
+
+
+ Category |
+ {this.state.ic.category} |
+
+
+ Type |
+ {this.state.ic.type} |
+
+
+ Uptime |
+ {moment.duration(this.state.ic.uptime, "seconds").humanize()} |
+
+
+ Location |
+ {this.state.ic.location} |
+
+
+ Websocket URL |
+ {this.state.ic.websocketurl} |
+
+
+ API URL |
+ {this.state.ic.apiurl} |
+
+
+ Start parameter schema |
+
+
+ |
+
+
+
+
+ Raw Status
+ {this.isJSON(this.state.ic.statusupdateraw) ?
+ : No valid JSON raw data available.
}
+
+ {this.state.ic.type === "villas-node" ?
+ <>
+
+
+
+
+ Graph:
+
+

+
+
+ {this.state.currentUser.role === "Admin" ?
+
+
+
Controls:
+
+
+
+
+
+ :
+ }
+ this.confirmCommand(c)} />
+ >
+ : }
+
+
+
+
+
;
+ }
+
+}
+
+let fluxContainerConverter = require('../common/FluxContainerConverter');
+export default FluxContainer.create(fluxContainerConverter.convert(InfrastructureComponent), { withProps: true });
\ No newline at end of file
diff --git a/src/ic/ics.js b/src/ic/ics.js
index b0a5016..6ef3562 100644
--- a/src/ic/ics.js
+++ b/src/ic/ics.js
@@ -367,32 +367,11 @@ class InfrastructureComponents extends Component {
}
}
- modifyNameColumn(name, component){
- let index = this.state.ics.indexOf(component);
- return
- }
-
openICStatus(ic){
let index = this.state.ics.indexOf(ic);
this.setState({ icModal: true, modalIC: ic, modalIndex: index })
}
- sendControlCommand(command,ic){
- if(command === "restart"){
- AppDispatcher.dispatch({
- type: 'ics/restart',
- url: ic.apiurl + "/restart",
- token: this.state.sessionToken,
- });
- }else if(command === "shutdown"){
- AppDispatcher.dispatch({
- type: 'ics/shutdown',
- url: ic.apiurl + "/shutdown",
- token: this.state.sessionToken,
- });
- }
- }
-
isLocalIC(index, ics){
let ic = ics[index]
return !ic.managedexternally
@@ -419,7 +398,8 @@ class InfrastructureComponents extends Component {
this.modifyNameColumn(name, component)}
+ link='/infrastructure/'
+ linkKey='id'
/>
+