diff --git a/src/pages/infrastructure/dialogs/edit-ic-dialog.js b/src/pages/infrastructure/dialogs/edit-ic-dialog.js
new file mode 100644
index 0000000..9a87e7d
--- /dev/null
+++ b/src/pages/infrastructure/dialogs/edit-ic-dialog.js
@@ -0,0 +1,248 @@
+/**
+ * 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 { Form, Col, Row } from 'react-bootstrap';
+import Dialog from '../../../common/dialogs/dialog';
+import ParametersEditor from '../../../common/parameters-editor';
+import NotificationsDataManager from "../../../common/data-managers/notifications-data-manager";
+import NotificationsFactory from "../../../common/data-managers/notifications-factory";
+
+class EditICDialog extends React.Component {
+ valid = true;
+
+ constructor(props) {
+ super(props);
+
+ this.state = {
+ name: '',
+ websocketurl: '',
+ apiurl: '',
+ location: '',
+ description: '',
+ type: '',
+ category: '',
+ icstate: '',
+ managedexternally: false,
+ startparameterschema: {}
+ };
+ }
+
+
+ onClose(canceled) {
+ if (canceled === false) {
+ if (this.valid) {
+ let data = JSON.parse(JSON.stringify(this.props.ic));
+
+ if (this.state.name != null && this.state.name !== "" && this.state.name !== this.props.ic.name) {
+ data.name = this.state.name;
+ }
+
+ data.websocketurl = this.state.websocketurl;
+ data.apiurl = this.state.apiurl;
+
+ if (this.state.location != null && this.state.location !== this.props.ic.location) {
+ data.location = this.state.location;
+ }
+
+ if (this.state.description != null && this.state.description !== this.props.ic.description) {
+ data.description = this.state.description;
+ }
+
+ if (this.state.type != null && this.state.type !== "" && this.state.type !== this.props.ic.type) {
+ data.type = this.state.type;
+ }
+
+ if (this.state.category != null && this.state.category !== "" && this.state.category !== this.props.ic.category) {
+ data.category = this.state.category;
+ }
+
+ if (this.state.icstate != null && this.state.icstate !== "" && this.state.icstate !== this.props.ic.state) {
+ data.state = this.state.icstate;
+ }
+
+ if (Object.keys(this.state.startparameterschema).length === 0 && this.state.startparameterschema.constructor === Object) {
+ data.startparameterschema = this.state.startparameterschema;
+ }
+
+ data.managedexternally = this.state.managedexternally;
+
+ this.props.onClose(data);
+ this.setState({managedexternally: false});
+ }
+ } else {
+ this.props.onClose();
+ this.setState({managedexternally: false});
+ }
+ }
+
+ handleChange(e) {
+ if(e.target.id === "managedexternally"){
+ this.setState({ managedexternally : !this.state.managedexternally});
+ }
+ else{
+ this.setState({ [e.target.id]: e.target.value });
+ }
+ }
+
+ handleStartParameterSchemaChange(data) {
+ this.setState({ startparameterschema: data });
+ }
+
+ resetState() {
+ this.setState({
+ name: this.props.ic.name,
+ websocketurl: this.props.ic.websocketurl,
+ apiurl: this.props.ic.apiurl,
+ type: this.props.ic.type,
+ location: this.props.ic.location,
+ description: this.props.ic.description,
+ category: this.props.ic.category,
+ icstate: this.props.ic.state,
+ managedexternally: false,
+ startparameterschema: this.props.ic.startparameterschema || {},
+ });
+ }
+
+ selectStartParamsFile(event) {
+ const file = event.target.files[0];
+
+ if (!file.type.match('application/json')) {
+ console.error("Not a json file. Will not process file '" + file.name + "'.")
+ NotificationsDataManager.addNotification(NotificationsFactory.UPDATE_ERROR("Not a json file. Will not process file \'" + file.name + "\'."));
+ return;
+ }
+
+ let reader = new FileReader();
+ reader.readAsText(file);
+
+ reader.onload = event => {
+ const params = JSON.parse(reader.result);
+ this.setState({ startparameterschema: params})
+ }
+ };
+
+ render() {
+ let typeOptions = [];
+ switch(this.state.category){
+ case "simulator":
+ typeOptions = ["dummy","generic","dpsim","rtlab","rscad","rtlab","kubernetes"];
+ break;
+ case "manager":
+ typeOptions = ["villas-node","villas-relay","generic"];
+ break;
+ case "gateway":
+ typeOptions = ["villas-node","villas-relay"];
+ break;
+ case "service":
+ typeOptions = ["ems","custom"];
+ break;
+ case "equipment":
+ typeOptions = ["chroma-emulator","chroma-loads","sma-sunnyboy","fleps","sonnenbatterie"];
+ break;
+ default:
+ typeOptions =[];
+ }
+
+ let stateOptions = ["idle", "starting", "running", "pausing", "paused", "resuming", "stopping", "resetting", "error", "gone", "shuttingdown", "shutdown"];
+
+ return (
+
+ );
+ }
+}
+
+export default EditICDialog;
diff --git a/src/pages/infrastructure/dialogs/import-ic-dialog.js b/src/pages/infrastructure/dialogs/import-ic-dialog.js
new file mode 100644
index 0000000..e8db469
--- /dev/null
+++ b/src/pages/infrastructure/dialogs/import-ic-dialog.js
@@ -0,0 +1,148 @@
+/**
+ * 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 { Form } from 'react-bootstrap';
+import _ from 'lodash';
+import Dialog from '../../../common/dialogs/dialog';
+
+class ImportICDialog extends React.Component {
+ valid = false;
+ imported = false;
+
+ constructor(props) {
+ super(props);
+
+ this.state = {
+ name: '',
+ websocketurl: '',
+ uuid: ''
+ };
+ }
+
+ onClose(canceled) {
+ if (canceled === false) {
+ if (this.valid) {
+ const data = {
+ properties: {
+ name: this.state.name
+ },
+ uuid: this.state.uuid
+ };
+
+ if (this.state.websocketurl != null && this.state.websocketurl !== "" && this.state.websocketurl !== 'http://') {
+ data.websocketurl = this.state.websocketurl;
+ }
+
+ this.props.onClose(data);
+ }
+ } else {
+ this.props.onClose();
+ }
+ }
+
+ handleChange(e) {
+ this.setState({ [e.target.id]: e.target.value });
+ }
+
+ resetState() {
+ this.setState({ name: '', websocketurl: 'http://', uuid: '' });
+ }
+
+ loadFile(fileList) {
+ // get file
+ const file = fileList[0];
+ if (!file.type.match('application/json')) {
+ return;
+ }
+
+ // create file reader
+ const reader = new FileReader();
+ const self = this;
+
+ reader.onload = function(event) {
+ // read component
+ const ic = JSON.parse(event.target.result);
+ self.imported = true;
+ self.setState({
+ name: _.get(ic, 'properties.name') || _.get(ic, 'rawProperties.name'),
+ websocketurl: _.get(ic, 'websocketurl'),
+ uuid: ic.uuid
+ });
+ };
+
+ reader.readAsText(file);
+ }
+
+ validateForm(target) {
+ // check all controls
+ let name = true;
+ let uuid = true;
+
+ if (this.state.name === '') {
+ name = false;
+ }
+
+ if (this.state.uuid === '') {
+ uuid = false;
+ }
+
+ this.valid = name || uuid;
+
+ // return state to control
+ if (target === 'name') return name ? "success" : "error";
+ if (target === 'uuid') return uuid ? "success" : "error";
+ }
+
+ render() {
+ return (
+
+ );
+ }
+}
+
+export default ImportICDialog;
diff --git a/src/pages/infrastructure/dialogs/new-ic-dialog.js b/src/pages/infrastructure/dialogs/new-ic-dialog.js
new file mode 100644
index 0000000..a4380e7
--- /dev/null
+++ b/src/pages/infrastructure/dialogs/new-ic-dialog.js
@@ -0,0 +1,354 @@
+/**
+ * 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 { Form as BForm, OverlayTrigger, Tooltip} from 'react-bootstrap';
+import Dialog from '../../../common/dialogs/dialog';
+import ParametersEditor from '../../../common/parameters-editor';
+import Form from "@rjsf/core";
+import $RefParser from '@apidevtools/json-schema-ref-parser';
+
+class NewICDialog extends React.Component {
+ valid = false;
+
+ constructor(props) {
+ super(props);
+
+ this.state = {
+ name: '',
+ websocketurl: '',
+ apiurl: '',
+ uuid: '',
+ type: '',
+ category: '',
+ managedexternally: false,
+ description: '',
+ location: '',
+ manager: '',
+ properties: {},
+ schema: {},
+ formData: {},
+ };
+ }
+
+ onClose(canceled) {
+ if (canceled === false) {
+ if (this.valid) {
+ const parameters = {
+ name: this.state.name,
+ type: this.state.type,
+ category: this.state.category,
+ uuid: this.state.uuid,
+ location: this.state.location,
+ description: this.state.description,
+ }
+
+ const data = {
+ managedexternally: this.state.managedexternally,
+ manager: this.state.manager,
+ name: this.state.name,
+ type: this.state.type,
+ category: this.state.category,
+ uuid: this.state.uuid,
+ description: this.state.description,
+ location: this.state.location,
+ parameters: parameters
+ };
+
+ // Add custom properties
+ if (this.state.managedexternally)
+ Object.assign(parameters, this.state.properties);
+
+ if (this.state.websocketurl != null && this.state.websocketurl !== "") {
+ parameters.websocketurl = this.state.websocketurl;
+ data.websocketurl = this.state.websocketurl;
+ }
+
+ if (this.state.apiurl != null && this.state.apiurl !== "") {
+ parameters.apiurl = this.state.apiurl;
+ data.apiurl = this.state.apiurl;
+ }
+
+ this.props.onClose(data);
+ this.setState({managedexternally: false});
+ }
+ } else {
+ this.props.onClose();
+ this.setState({managedexternally: false});
+ }
+ }
+
+ handleChange(e) {
+ if(e.target.id === "managedexternally"){
+ this.setState({ managedexternally : !this.state.managedexternally});
+ }
+ else{
+ this.setState({ [e.target.id]: e.target.value });
+ }
+ }
+
+ setManager(e) {
+ this.setState({ [e.target.id]: e.target.value });
+
+ if (this.props.managers) {
+ let schema = this.props.managers.find(m => m.uuid === e.target.value).createparameterschema
+ if (schema) {
+ $RefParser.dereference(schema, (err, deref) => {
+ if (err) {
+ console.error(err)
+ }
+ else {
+ this.setState({schema: schema})
+ }
+ })
+ }
+ }
+ }
+
+ handlePropertiesChange = properties => {
+ this.setState({
+ properties: properties
+ });
+ };
+
+ handleFormChange({formData}) {
+ this.setState({properties: formData, formData: formData})
+ }
+
+ resetState() {
+ this.setState({
+ name: '',
+ websocketurl: '',
+ apiurl: '',
+ uuid: this.uuidv4(),
+ type: '',
+ category: '',
+ managedexternally: false,
+ description: '',
+ location: '',
+ properties: {},
+ });
+ }
+
+ validateForm(target) {
+
+ if (this.state.managedexternally) {
+ this.valid = this.state.manager !== '';
+ return this.state.manager !== '' ? "success" : "error";
+ }
+
+ // check all controls
+ let name = true;
+ let uuid = true;
+ let type = true;
+ let category = true;
+
+ if (this.state.name === '') {
+ name = false;
+ }
+
+ if (this.state.uuid === '') {
+ uuid = false;
+ }
+
+ if (this.state.type === '') {
+ type = false;
+ }
+
+ if (this.state.category === '') {
+ category = false;
+ }
+
+ this.valid = name && uuid && type && category;
+
+ // return state to control
+ if (target === 'name') return name ? "success" : "error";
+ if (target === 'uuid') return uuid ? "success" : "error";
+ if (target === 'type') return type ? "success" : "error";
+ if (target === 'category') return category ? "success" : "error";
+
+ return this.valid;
+ }
+
+ uuidv4() {
+ return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
+ // eslint-disable-next-line
+ var r = Math.random() * 16 | 0, v = c === 'x' ? r : (r & 0x3 | 0x8);
+ return v.toString(16);
+ });
+ }
+
+ render() {
+ let typeOptions = [];
+ switch(this.state.category){
+ case "simulator":
+ typeOptions = ["dummy","generic","dpsim","rtlab","rscad","rtlab","kubernetes"];
+ break;
+ case "manager":
+ typeOptions = ["villas-node","villas-relay","generic","kubernetes"];
+ break;
+ case "gateway":
+ typeOptions = ["villas-node","villas-relay"];
+ break;
+ case "service":
+ typeOptions = ["ems","custom"];
+ break;
+ case "equipment":
+ typeOptions = ["chroma-emulator","chroma-loads","sma-sunnyboy","fleps","sonnenbatterie"];
+ break;
+ default:
+ typeOptions =[];
+ }
+
+ let managerOptions = [];
+ managerOptions.push();
+ for (let m of this.props.managers) {
+ managerOptions.push (
+
+ );
+ }
+
+ return (
+
+ );
+ }
+}
+
+export default NewICDialog;
diff --git a/src/pages/infrastructure/ic-action-board.js b/src/pages/infrastructure/ic-action-board.js
new file mode 100644
index 0000000..f330777
--- /dev/null
+++ b/src/pages/infrastructure/ic-action-board.js
@@ -0,0 +1,114 @@
+/**
+ * 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 { Form, Row, Col } from 'react-bootstrap';
+import DateTimePicker from 'react-datetime-picker';
+import ActionBoardButtonGroup from '../../common/buttons/action-board-button-group';
+import classNames from 'classnames';
+import { useState } from 'react';
+import { useSelector, useDispatch } from 'react-redux';
+import { sessionToken } from '../../localStorage';
+import { clearCheckedICs, deleteIC, loadAllICs, sendActionToIC } from '../../store/icSlice';
+
+const ICActionBoard = (props) => {
+ const dispatch = useDispatch();
+ const checkedICsIds = useSelector(state => state.infrastructure.checkedICsIds);
+
+ let pickedTime = new Date();
+ pickedTime.setMinutes(5 * Math.round(pickedTime.getMinutes() / 5 + 1));
+
+ const [time, setTime] = useState(pickedTime);
+
+ const onReset = () => {
+ let newAction = {};
+ newAction['action'] = 'reset';
+ newAction['when'] = time;
+
+ checkedICsIds.forEach((id) => {
+ dispatch(sendActionToIC({token: sessionToken, id: id, actions: newAction}));
+ });
+ }
+
+ const onRecreate = () => {
+ let newAction = {};
+ newAction['action'] = 'create';
+ newAction['when'] = time;
+
+ checkedICsIds.forEach((id) => {
+ dispatch(sendActionToIC({token: sessionToken, id: id, actions: newAction}));
+ });
+ }
+
+ const onDelete = () => {
+ checkedICsIds.forEach((id) => {
+ console.log(id)
+ dispatch(deleteIC({token: sessionToken, id: id}));
+ });
+
+ dispatch(clearCheckedICs());
+ dispatch(loadAllICs({token: sessionToken}));
+ }
+
+ const onShutdown = () => {
+ let newAction = {};
+ newAction['action'] = 'shutdown';
+ newAction['when'] = time;
+
+ checkedICsIds.forEach((id) => {
+ dispatch(sendActionToIC({token: sessionToken, id: id, actions: newAction}));
+ });
+ }
+
+ return (
+
+
+
+
+
+ onReset()}
+ onShutdown={() => onShutdown()}
+ onDelete={() => onDelete()}
+ onRecreate={() => onRecreate()}
+ paused={false}
+ />
+
+ {false ?
+
+
+
+
+ : <>>
+ }
+
+
Select time for synced command execution
+
);
+}
+
+export default ICActionBoard;
diff --git a/src/pages/infrastructure/ic-category-table.js b/src/pages/infrastructure/ic-category-table.js
index dce214a..3e3a38a 100644
--- a/src/pages/infrastructure/ic-category-table.js
+++ b/src/pages/infrastructure/ic-category-table.js
@@ -15,41 +15,25 @@
* along with VILLASweb. If not, see .
******************************************************************************/
-import { useSelector, useDispatch } from "react-redux";
+import { useState, useEffect } from "react";
+import { useSelector, useDispatch } from "react-redux";
import {Table, ButtonColumn, CheckboxColumn, DataColumn, LabelColumn, LinkColumn } from '../../common/table';
import { Badge } from 'react-bootstrap';
import FileSaver from 'file-saver';
import _ from 'lodash';
import moment from 'moment'
import IconToggleButton from "../../common/buttons/icon-toggle-button";
-
-import { checkICsByCategory } from "../../store/icSlice";
-import { useState } from "react";
-
+import { updateCheckedICs, openDeleteModal, openEditModal } from "../../store/icSlice";
import { stateLabelStyle } from "./styles";
+import { currentUser } from "../../localStorage";
//a Table of IC components of specific category from props.category
//titled with props.title
const ICCategoryTable = (props) => {
-
+ const dispatch = useDispatch();
const ics = useSelector(state => state.infrastructure.ICsArray);
-
- let currentUser = JSON.parse(localStorage.getItem("currentUser"));
-
- const checkedICs = useSelector(state => state.infrastructure.checkedICsArray);
-
- const [isGenericDisplayed, setIsGenericDisplayed] = useState(false)
-
- const exportIC = (index) => {
- // filter properties
- let ic = Object.assign({}, ics[index]);
- delete ic.id;
-
- // show save dialog
- const blob = new Blob([JSON.stringify(ic, null, 2)], { type: 'application/json' });
- FileSaver.saveAs(blob, 'ic-' + (_.get(ic, 'name') || 'undefined') + '.json');
- }
+ const [isGenericDisplayed, setIsGenericDisplayed] = useState(false);
const modifyUptimeColumn = (uptime, component) => {
if (uptime >= 0) {
@@ -89,8 +73,6 @@ const ICCategoryTable = (props) => {
return 99;
}
}
-
-
//if category of the table is manager we need to filter the generic-typed ics
//according to the state of IconToggleButton
let tableData = [];
@@ -113,29 +95,63 @@ const ICCategoryTable = (props) => {
}
})
- const isLocalIC = (index, ics) => {
- let ic = ics[index]
+ const [checkedICs, setCheckedICs] = useState({});
+ const [areAllICsChecked, setAreAllICsChecked] = useState(false);
+
+ useEffect(() => {
+ if(tableData.length > 0){
+ for(let ic in tableData){
+ if(!checkedICs.hasOwnProperty(tableData[ic].id) && !isLocalIC(tableData[ic])){
+ setCheckedICs(prevState => ({...prevState, [tableData[ic].id]: false}));
+ }
+ }
+ }
+ }, [tableData])
+
+ useEffect(() => {
+ dispatch(updateCheckedICs(checkedICs));
+
+ //every time some ic is checked we need to check wether or not all ics are checked afterwards
+ if(Object.keys(checkedICs).length > 0){
+ setAreAllICsChecked(Object.values(checkedICs).every((value)=> value))
+ }
+ }, [checkedICs])
+
+ const exportIC = (index) => {
+ // filter properties
+ let toExport = {...tableData[index]};
+ delete toExport.id;
+
+ const fileName = toExport.name.replace(/\s+/g, '-').toLowerCase();
+
+ // show save dialog
+ const blob = new Blob([JSON.stringify(toExport, null, 2)], { type: 'application/json' });
+ FileSaver.saveAs(blob, 'ic-' + fileName + '.json');
+ }
+
+ const isLocalIC = (ic) => {
return !ic.managedexternally
}
- const checkAllICs = (ics, title) => {
- //TODO
- }
-
- const isICchecked = (ic) => {
- //TODO
- return false
- }
-
- const areAllChecked = (title) => {
- //TODO
- return false
- }
-
- const onICChecked = (ic, event) => {
- //TODO
+ const checkAllICs = () => {
+ if(areAllICsChecked){
+ for(const id in checkedICs){
+ setCheckedICs(prevState => ({...prevState, [id]: false}));
+ }
+ } else {
+ for(const id in checkedICs){
+ setCheckedICs(prevState => ({...prevState, [id]: true}));
+ }
+ }
}
+ const toggleCheck = (id) => {
+ setCheckedICs(prevState => {
+ return {
+ ...prevState, [id]: !prevState[id]
+ }
+ })
+ }
return (
{props.title}
@@ -157,11 +173,11 @@ const ICCategoryTable = (props) => {
checkAllICs(ics, props.title)}
- allChecked={areAllChecked(props.title)}
- checkboxDisabled={(index) => isLocalIC(index, ics) === true}
- checked={(ic) => isICchecked(ic)}
- onChecked={(ic, event) => onICChecked(ic, event)}
+ onCheckAll={() => checkAllICs()}
+ allChecked={areAllICsChecked}
+ checkboxDisabled={(index) => isLocalIC(tableData[index])}
+ checked={(ic) => checkedICs[ic.id]}
+ onChecked={(ic, event) => toggleCheck(ic.id)}
width='30'
/>
{currentUser.role === "Admin" ?
@@ -202,13 +218,13 @@ const ICCategoryTable = (props) => {
width='150'
align='right'
editButton
- showEditButton ={(index) => isLocalIC(index, ics)}
+ showEditButton ={(index) => isLocalIC(tableData[index])}
exportButton
deleteButton
showDeleteButton = {null}
- onEdit={index => {}}
+ onEdit={index => {dispatch(openEditModal(tableData[index]))}}
onExport={index => exportIC(index)}
- onDelete={index => {}}
+ onDelete={index => {dispatch(openDeleteModal(tableData[index]))}}
/>
:
{
const dispatch = useDispatch();
- const ICsArray = useSelector(state => state.infrastructure.ICsArray);
+ const ics = useSelector(state => state.infrastructure.ICsArray);
+ const externalICs = ics.filter(ic => ic.managedexternally === true);
//track status of the modals
- const [isEditModalOpened, setIsEditModalOpened] = useState(false);
const [isNewModalOpened, setIsNewModalOpened] = useState(false);
const [isImportModalOpened, setIsImportModalOpened] = useState(false);
- const [isDeleteModalOpened, setIsDeleteModalOpened] = useState(false);
const [isICModalOpened, setIsICModalOpened] = useState(false);
-
const [checkedICs, setCheckedICs] = useState([]);
-
- const currentUser = JSON.parse(localStorage.getItem("currentUser"));
-
+
useEffect(() => {
//load array of ics and start a timer for periodic refresh
dispatch(loadAllICs({token: sessionToken}));
@@ -62,21 +61,69 @@ const Infrastructure = (props) => {
}
}
- const buttonStyle = {
- marginLeft: '10px',
- }
-
- const iconStyle = {
- height: '30px',
- width: '30px'
+ //modal actions and selectors
+
+ const isEditModalOpened = useSelector(state => state.infrastructure.isEditModalOpened);
+ const isDeleteModalOpened = useSelector(state => state.infrastructure.isDeleteModalOpened);
+ const editModalIC = useSelector(state => state.infrastructure.editModalIC);
+ const deleteModalIC = useSelector(state => state.infrastructure.deleteModalIC);
+
+ const onNewModalClose = (data) => {
+ setIsNewModalOpened(false);
+
+ console.log("Adding ic. External: ", !data.managedexternally)
+
+ if(data){
+ if(!data.managedexternally){
+ dispatch(addIC({token: sessionToken, ic: data})).then(res => dispatch(loadAllICs({token: sessionToken})));
+ }else {
+ // externally managed IC: dispatch create action to selected manager
+ let newAction = {};
+
+ newAction["action"] = "create";
+ newAction["parameters"] = data.parameters;
+ newAction["when"] = new Date();
+
+ // find the manager IC
+ const managerIC = ics.find(ic => ic.uuid === data.manager)
+ if (managerIC === null || managerIC === undefined) {
+ NotificationsDataManager.addNotification(NotificationsFactory.ADD_ERROR("Could not find manager IC with UUID " + data.manager));
+ return;
+ }
+
+ dispatch(sendActionToIC({token: sessionToken, id: managerIC.id, actions: newAction})).then(res => dispatch(loadAllICs({token: sessionToken})));
+ }
+ }
}
+ const onImportModalClose = (data) => {
+ setIsImportModalOpened(false);
+
+ dispatch(addIC({token: sessionToken, ic: data})).then(res => dispatch(loadAllICs({token: sessionToken})));
+ }
+
+ const onEditModalClose = (data) => {
+ if(data){
+ //some changes where done
+ dispatch(editIC({token: sessionToken, ic: data})).then(res => dispatch(loadAllICs({token: sessionToken})));
+ }
+ dispatch(closeEditModal(data));
+ }
+
+ const onCloseDeleteModal = (isDeleteConfirmed) => {
+ if(isDeleteConfirmed){
+ dispatch(deleteIC({token: sessionToken, id:deleteModalIC.id})).then(res => dispatch(loadAllICs({token: sessionToken})));
+ }
+ dispatch(closeDeleteModal());
+ }
+
+ //getting list of managers for the new IC modal
+ const managers = ics.filter(ic => ic.category === "manager");
return (
Infrastructure
- {//TODO
- /* {currentUser.role === "Admin" ?
+ {currentUser.role === "Admin" ?
{
/>
:
-
- } */}
+ }
{
category={"equipment"}
/>
+ {currentUser.role === "Admin" ? : null}
+
- {//TODO
- /*
this.closeNewModal(data)} managers={this.state.managers} />
- this.closeEditModal(data)} ic={this.state.modalIC} />
- this.closeImportModal(data)} />
- this.closeDeleteModal(e)} /> */}
-
+ onNewModalClose(data)} managers={managers} />
+ onImportModalClose(data)} />
+ onEditModalClose(data)}
+ ic={editModalIC ? editModalIC : {}}
+ />
+ onCloseDeleteModal(e)}
+ />
);
}
-export default Infrastructure;
\ No newline at end of file
+export default Infrastructure;