diff --git a/src/pages/dashboards/dashboard.js b/src/pages/dashboards/dashboard.js index 5cffa1d..2839929 100644 --- a/src/pages/dashboards/dashboard.js +++ b/src/pages/dashboards/dashboard.js @@ -23,6 +23,7 @@ import classNames from 'classnames'; import 'react-contexify/dist/ReactContexify.min.css'; import EditWidget from './widget/edit-widget/edit-widget'; import EditSignalMappingDialog from '../scenarios/dialogs/edit-signal-mapping' +import EditFilesDialog from './dialogs/edit-files-dialog' import WidgetToolbox from './widget/widget-toolbox'; import WidgetArea from './widget-area'; import DashboardButtonGroup from './dashboard-button-group'; @@ -42,7 +43,9 @@ import { useLazyGetFilesQuery, useUpdateDashboardMutation, useGetICSQuery, - useLazyGetSignalsQuery + useLazyGetSignalsQuery, + useDeleteFileMutation, + useAddFileMutation } from '../../store/apiSlice'; const startUpdaterWidgets = new Set(['Slider', 'Button', 'NumberInput']); @@ -58,6 +61,8 @@ const Dashboard = ({ isFullscreen, toggleFullscreen }) => { const [triggerGetWidgets] = useLazyGetWidgetsQuery(); const [triggerGetConfigs] = useLazyGetConfigsQuery(); const [triggerGetFiles] = useLazyGetFilesQuery(); + const [triggerDeleteFile] = useDeleteFileMutation(); + const [triggerUploadFile] = useAddFileMutation(); const [triggerGetSignals] = useLazyGetSignalsQuery(); const [addWidget] = useAddWidgetMutation(); const [updateWidget] = useUpdateWidgetMutation(); @@ -76,7 +81,6 @@ const Dashboard = ({ isFullscreen, toggleFullscreen }) => { const [editOutputSignalsModal, setEditOutputSignalsModal] = useState(false); const [editInputSignalsModal, setEditInputSignalsModal] = useState(false); const [filesEditModal, setFilesEditModal] = useState(false); - const [filesEditSaveState, setFilesEditSaveState] = useState([]); const [modalData, setModalData] = useState(null); const [modalIndex, setModalIndex] = useState(null); const [widgetChangeData, setWidgetChangeData] = useState([]); @@ -247,6 +251,40 @@ const Dashboard = ({ isFullscreen, toggleFullscreen }) => { setModalIndex(index); }; + const uploadFile = async (file) =>{ + await triggerUploadFile({scenarioID:dashboard.scenarioID, file:file}) + .then(async ()=>{ + await triggerGetFiles(dashboard.scenarioID) + .then((fs)=>{ + setFiles(fs.data.files) + }) + }) + .catch((e)=>{ + console.log(`File upload failed: ${e}`) + }) + } + + const deleteFile = async (index) =>{ + let file = files[index] + if(file !== undefined){ + await triggerDeleteFile(file.id) + .then(async ()=>{ + await triggerGetFiles(dashboard.scenarioID) + .then((fs)=>{ + setFiles(fs.data.files) + }) + .catch((e)=>{ + console.log(`Error fetching files: ${e}`) + }) + }) + .catch((e)=>{ + console.log(`Error deleting: ${e}`) + }) + + } + + } + const duplicateWidget = async (widget) => { let widgetCopy = { ...widget, id: undefined, x: widget.x + 50, y: widget.y + 50 }; try { @@ -262,13 +300,12 @@ const Dashboard = ({ isFullscreen, toggleFullscreen }) => { const startEditFiles = () => { let tempFiles = files.map(file => ({ id: file.id, name: file.name })); setFilesEditModal(true); - setFilesEditSaveState(tempFiles); }; const closeEditFiles = () => { widgets.forEach(widget => { if (widget.type === "Image") { - //widget.customProperties.update = true; + widget.customProperties.update = true; } }); setFilesEditModal(false); @@ -531,16 +568,17 @@ const Dashboard = ({ isFullscreen, toggleFullscreen }) => { scenarioID={dashboard.scenarioID} /> - {/* */} + sessionToken={sessionToken} + show={filesEditModal} + uploadFile={uploadFile} + deleteFile={deleteFile} + onClose={closeEditFiles} + files={files} + scenarioID={dashboard.scenarioID} + locked={locked} + /> . - ******************************************************************************/ - -import React from 'react'; -import {Form, Button, Col, ProgressBar, Row} from 'react-bootstrap'; -import Dialog from '../../../common/dialogs/dialog'; -import { Table, ButtonColumn, DataColumn } from "../../../common/table"; -import EditFileContent from "./edit-file-content"; - -class EditFilesDialog extends React.Component { - valid = true; - - constructor(props) { - super(props); - - this.state = { - uploadFile: null, - uploadProgress: 0, - editModal: false, - modalFile: {} - }; - } - - onClose() { - this.props.onClose(); - } - - selectUploadFile(event) { - this.setState({ uploadFile: event.target.files[0] }); - }; - - startFileUpload(){ - // upload file - const formData = new FormData(); - formData.append("file", this.state.uploadFile); - - AppDispatcher.dispatch({ - type: 'files/start-upload', - data: formData, - token: this.props.sessionToken, - progressCallback: this.updateUploadProgress, - finishedCallback: this.clearProgress, - scenarioID: this.props.scenarioID, - }); - - this.setState({ uploadFile: null }); - }; - - updateUploadProgress = (event) => { - if (event.hasOwnProperty("percent")){ - this.setState({ uploadProgress: parseInt(event.percent.toFixed(), 10) }); - } else { - this.setState({ uploadProgress: 0 }); - } - }; - - clearProgress = (newFileID) => { - this.setState({ uploadProgress: 0 }); - }; - - closeEditModal() { - this.setState({editModal: false}); - } - - deleteFile(index){ - let file = this.props.files[index] - AppDispatcher.dispatch({ - type: 'files/start-remove', - data: file, - token: this.props.sessionToken - }); - } - - render() { - let fileOptions = []; - if (this.props.files.length > 0){ - fileOptions.push( - - ) - fileOptions.push(this.props.files.map((file, index) => ( - - ))) - } else { - fileOptions = - } - - const progressBarStyle = { - marginLeft: '100px', - marginTop: '-40px' - }; - - let title = this.props.locked ? "View files of scenario" : "Edit Files of Scenario"; - - return ( - this.onClose()} - blendOutCancel = {true} - valid={true} - > - - - - - - this.deleteFile(index)} - editButton - onEdit={index => this.setState({ editModal: true, modalFile: this.props.files[index] })} - locked={this.props.locked} - /> -
- -
-
Add file
- - - this.selectUploadFile(event)} - disabled={this.props.locked} - /> - - - - - - - -
- -
- - - - - -
- - this.closeEditModal(data)} - sessionToken={this.props.sessionToken} - file={this.state.modalFile} - /> -
- ); - } -} - -export default EditFilesDialog; \ No newline at end of file diff --git a/src/pages/dashboards/dialogs/edit-files-dialog.jsx b/src/pages/dashboards/dialogs/edit-files-dialog.jsx new file mode 100644 index 0000000..f6c8f7a --- /dev/null +++ b/src/pages/dashboards/dialogs/edit-files-dialog.jsx @@ -0,0 +1,135 @@ +/** + * 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, { useState } from 'react'; +import {Form, Button, Col, ProgressBar, Row} from 'react-bootstrap'; +import Dialog from '../../../common/dialogs/dialog'; +import { Table, ButtonColumn, DataColumn } from "../../../common/table"; +import EditFileContent from "./edit-file-content"; + +const EditFilesDialog = (props)=> { + const [uploadFile,setUploadFile] = useState(null) + const [uploadProgress,setUploadProgress] = useState(0) + const [editModal,setEditModal] = useState(false) + const [modalFile,setModalFile] = useState({}) + + const onClose = ()=>{ + props.onClose(); + } + + const selectUploadFile = (e)=>{ + setUploadFile(e.target.files[0]) + }; + + const closeEditModal=()=> { + setEditModal(false) + } + + let fileOptions = []; + if (props.files.length > 0){ + fileOptions.push( + + ) + fileOptions.push(props.files.map((file, index) => ( + + ))) + } else { + fileOptions = + } + + + let title = props.locked ? "View files of scenario" : "Edit Files of Scenario"; + + return ( + onClose()} + blendOutCancel = {true} + valid={true} + > + + + + + + { + setEditModal(true) + setModalFile(props.files[index]) + } + } + locked={props.locked} + /> +
+ +
+
Add file
+ + + selectUploadFile(event)} + disabled={props.locked} + /> + + + + + + + +
+ +
+ +
+ + closeEditModal(data)} + sessionToken={props.sessionToken} + file={modalFile} + /> +
+ ); +} + +export default EditFilesDialog; \ No newline at end of file diff --git a/src/pages/scenarios/scenario.js b/src/pages/scenarios/scenario.js index ed63521..9317f18 100644 --- a/src/pages/scenarios/scenario.js +++ b/src/pages/scenarios/scenario.js @@ -23,18 +23,34 @@ import IconToggleButton from "../../common/buttons/icon-toggle-button"; import ConfigsTable from "./tables/configs-table"; import DashboardsTable from "./tables/dashboards-table"; import ResultsTable from "./tables/results-table"; +import EditFilesDialog from '../dashboards/dialogs/edit-files-dialog' import UsersTable from "./tables/users-table"; -import { +import { useEffect, useState } from "react"; +import { + useGetDashboardQuery, + useLazyGetWidgetsQuery, + useLazyGetConfigsQuery, + useAddWidgetMutation, + useUpdateWidgetMutation, + useDeleteWidgetMutation, useUpdateScenarioMutation, + useLazyGetFilesQuery, + useUpdateDashboardMutation, useGetICSQuery, -} from "../../store/apiSlice"; + useLazyGetSignalsQuery, + useDeleteFileMutation, + useAddFileMutation +} from '../../store/apiSlice'; const Scenario = (props) => { const params = useParams(); const id = params.scenario; - + const [triggerGetFiles] = useLazyGetFilesQuery(); + const [triggerDeleteFile] = useDeleteFileMutation(); + const [triggerUploadFile] = useAddFileMutation(); const { user: currentUser, token: sessionToken } = useSelector((state) => state.auth); - + + const [filesEditModal, setFilesEditModal] = useState(false); const { data: fetchedScenarios, isLoading: isScenarioLoading, refetch: refetchScenario } = useGetScenarioByIdQuery(id); const scenario = fetchedScenarios?.scenario; @@ -42,6 +58,8 @@ const Scenario = (props) => { const ics = fetchedICs?.ics; const [updateScenario, {isLoadingUpdate}] = useUpdateScenarioMutation(); + const [files, setFiles] = useState([]); + const [locked, setLocked] = useState(false); const buttonStyle = { marginLeft: '10px', @@ -52,6 +70,53 @@ const Scenario = (props) => { width: '30px' } + useEffect(async ()=>{ + + await triggerGetFiles(id) + .then((fs)=>{ + setFiles(fs.data.files) + }) + + },[]) + + const uploadFile = async (file) =>{ + await triggerUploadFile({scenarioID:id, file:file}) + .then(async ()=>{ + await triggerGetFiles(id) + .then((fs)=>{ + setFiles(fs.data.files) + }) + }) + .catch((e)=>{ + console.log(`File upload failed: ${e}`) + }) + } + + const deleteFile = async (index) =>{ + let file = files[index] + if(file !== undefined){ + await triggerDeleteFile(file.id) + .then(async ()=>{ + await triggerGetFiles(id) + .then((fs)=>{ + setFiles(fs.data.files) + }) + .catch((e)=>{ + console.log(`Error fetching files: ${e}`) + }) + }) + .catch((e)=>{ + console.log(`Error deleting: ${e}`) + }) + + } + + } + + const closeEditFiles = () => { + setFilesEditModal(false); + }; + const onScenarioLock = async (index) => { try{ const data = {...scenario}; @@ -74,7 +139,7 @@ const Scenario = (props) => { console.log("click")} + onClick={() => {setFilesEditModal(true)}} icon="file" buttonStyle={buttonStyle} iconStyle={iconStyle} @@ -99,20 +164,23 @@ const Scenario = (props) => { - {/* */} + show={filesEditModal} + uploadFile={uploadFile} + deleteFile={deleteFile} + onClose={closeEditFiles} + files={files} + scenarioID={id} + locked={locked} + /> { areICsLoading?
isLoading...
: diff --git a/src/pages/scenarios/tables/configs-table.js b/src/pages/scenarios/tables/configs-table.js index 7e9c63f..62574ec 100644 --- a/src/pages/scenarios/tables/configs-table.js +++ b/src/pages/scenarios/tables/configs-table.js @@ -39,7 +39,7 @@ import { } from "../../../store/apiSlice"; import ConfigActionBoard from "./config-action-board"; -const ConfigsTable = ({scenario, ics}) => { +const ConfigsTable = ({scenario, ics,files}) => { const {data, refetch: refetchConfigs } = useGetConfigsQuery(scenario.id); const [addComponentConfig] = useAddComponentConfigMutation(); const [updateComponentConfig] = useUpdateComponentConfigMutation(); @@ -49,8 +49,6 @@ const ConfigsTable = ({scenario, ics}) => { const configs = data ? data.configs : []; const [signals, setSignals] = useState({}); - const {data: filesData } = useGetFilesQuery(scenario.id); - const files = filesData ? filesData.files : []; const [isNewModalOpened, setIsNewModalOpened] = useState(false); const [isEditModalOpened, setIsEditModalOpened] = useState(false); diff --git a/src/store/endpoints/file-endpoints.js b/src/store/endpoints/file-endpoints.js index 765c03f..118a68c 100644 --- a/src/store/endpoints/file-endpoints.js +++ b/src/store/endpoints/file-endpoints.js @@ -25,7 +25,7 @@ export const fileEndpoints = (builder) => ({ addFile: builder.mutation({ query: ({ scenarioID, file }) => { const formData = new FormData(); - formData.append('inputFile', file); + formData.append('file', file); return { url: `files?scenarioID=${scenarioID}`, method: 'POST',