1
0
Fork 0
mirror of https://git.rwth-aachen.de/acs/public/villas/web/ synced 2025-03-09 00:00:01 +01:00

Restored files edit dialog, rewrote into functional component

Signed-off-by: SystemsPurge <naktiyoussef@proton.me>
This commit is contained in:
SystemsPurge 2024-11-18 11:03:02 +01:00
parent b0344ba503
commit 647573943c
No known key found for this signature in database
6 changed files with 269 additions and 222 deletions

View file

@ -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}
/>
{/* <EditFilesDialog
<EditFilesDialog
key={"edit-files-dialog"}
sessionToken={this.state.sessionToken}
show={this.state.filesEditModal}
onClose={this.closeEditFiles.bind(this)}
signals={this.state.signals}
files={this.state.files}
scenarioID={this.state.dashboard.scenarioID}
locked={this.state.locked}
/> */}
sessionToken={sessionToken}
show={filesEditModal}
uploadFile={uploadFile}
deleteFile={deleteFile}
onClose={closeEditFiles}
files={files}
scenarioID={dashboard.scenarioID}
locked={locked}
/>
<EditSignalMappingDialog
key={"edit-signal-mapping-input-dialog"}

View file

@ -1,192 +0,0 @@
/**
* 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 <http://www.gnu.org/licenses/>.
******************************************************************************/
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(
<option key = {0} default>Select image file</option>
)
fileOptions.push(this.props.files.map((file, index) => (
<option key={index+1} value={file.id}>{file.name}</option>
)))
} else {
fileOptions = <option disabled value style={{ display: 'none' }}>No files found, please upload one first.</option>
}
const progressBarStyle = {
marginLeft: '100px',
marginTop: '-40px'
};
let title = this.props.locked ? "View files of scenario" : "Edit Files of Scenario";
return (
<Dialog
show={this.props.show}
title={title}
buttonTitle="Close"
onClose={() => this.onClose()}
blendOutCancel = {true}
valid={true}
>
<Table breakWord={true} data={this.props.files}>
<DataColumn
title='ID'
dataKey='id'
width={50}
/>
<DataColumn
title='Name'
dataKey='name'
/>
<DataColumn
title='Size (bytes)'
dataKey='size'
/>
<DataColumn
title='Type'
dataKey='type'
/>
<ButtonColumn
align='right'
deleteButton
onDelete={(index) => this.deleteFile(index)}
editButton
onEdit={index => this.setState({ editModal: true, modalFile: this.props.files[index] })}
locked={this.props.locked}
/>
</Table>
<div style={{ float: 'center' }}>
<h5>Add file</h5>
<Row>
<Col xs lg="4">
<Form.Control
type='file'
onChange={(event) => this.selectUploadFile(event)}
disabled={this.props.locked}
/>
</Col>
<Col xs lg="2">
<span className='solid-button'>
<Button
variant='secondary'
disabled={this.state.uploadFile === null || this.props.locked}
onClick={() => this.startFileUpload()}>
Upload
</Button>
</span>
</Col>
</Row>
</div>
<br />
<Form.Group as={Col} >
<ProgressBar
striped={true}
animated={true}
now={this.state.uploadProgress}
label={this.state.uploadProgress + '%'}
/>
</Form.Group>
<div style={{ clear: 'both' }} />
<EditFileContent
show={this.state.editModal}
onClose={(data) => this.closeEditModal(data)}
sessionToken={this.props.sessionToken}
file={this.state.modalFile}
/>
</Dialog>
);
}
}
export default EditFilesDialog;

View file

@ -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 <http://www.gnu.org/licenses/>.
******************************************************************************/
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(
<option key = {0} default>Select image file</option>
)
fileOptions.push(props.files.map((file, index) => (
<option key={index+1} value={file.id}>{file.name}</option>
)))
} else {
fileOptions = <option disabled value style={{ display: 'none' }}>No files found, please upload one first.</option>
}
let title = props.locked ? "View files of scenario" : "Edit Files of Scenario";
return (
<Dialog
show={props.show}
title={title}
buttonTitle="Close"
onClose={() => onClose()}
blendOutCancel = {true}
valid={true}
>
<Table breakWord={true} data={props.files}>
<DataColumn
title='ID'
dataKey='id'
width={50}
/>
<DataColumn
title='Name'
dataKey='name'
/>
<DataColumn
title='Size (bytes)'
dataKey='size'
/>
<DataColumn
title='Type'
dataKey='type'
/>
<ButtonColumn
align='right'
deleteButton
onDelete={props.deleteFile}
editButton
onEdit={(index) => {
setEditModal(true)
setModalFile(props.files[index])
}
}
locked={props.locked}
/>
</Table>
<div style={{ float: 'center' }}>
<h5>Add file</h5>
<Row>
<Col xs lg="4">
<Form.Control
type='file'
onChange={(event) => selectUploadFile(event)}
disabled={props.locked}
/>
</Col>
<Col xs lg="2">
<span className='solid-button'>
<Button
variant='secondary'
disabled={uploadFile === null || props.locked}
onClick={()=>{props.uploadFile(uploadFile)}}>
Upload
</Button>
</span>
</Col>
</Row>
</div>
<br />
<div style={{ clear: 'both' }} />
<EditFileContent
show={editModal}
onClose={(data) => closeEditModal(data)}
sessionToken={props.sessionToken}
file={modalFile}
/>
</Dialog>
);
}
export default EditFilesDialog;

View file

@ -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) => {
<IconButton
childKey="0"
tooltip={tooltip}
onClick={() => console.log("click")}
onClick={() => {setFilesEditModal(true)}}
icon="file"
buttonStyle={buttonStyle}
iconStyle={iconStyle}
@ -99,20 +164,23 @@ const Scenario = (props) => {
</span>
</h1>
{/* <EditFilesDialog
<EditFilesDialog
key={"edit-files-dialog"}
sessionToken={sessionToken}
show={false}
onClose={null}
signals={null}
files={[]}
scenarioID={scenario.id}
locked={scenario.isLocked}
/> */}
show={filesEditModal}
uploadFile={uploadFile}
deleteFile={deleteFile}
onClose={closeEditFiles}
files={files}
scenarioID={id}
locked={locked}
/>
{ areICsLoading?
<div>isLoading...</div>
:
<ConfigsTable
files={files}
ics={ics}
scenario={scenario}
/>

View file

@ -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);

View file

@ -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',