diff --git a/src/result/edit-result.js b/src/result/edit-result.js index c956c06..d1fa784 100644 --- a/src/result/edit-result.js +++ b/src/result/edit-result.js @@ -18,11 +18,13 @@ import React from 'react'; import {FormGroup, FormControl, FormLabel, Col, Button, ProgressBar} from 'react-bootstrap'; import AppDispatcher from "../common/app-dispatcher"; +import FileStore from "../file/file-store" + import Table from "../common/table"; +import TableColumn from "../common/table-column"; import Dialog from '../common/dialogs/dialog'; -import ParametersEditor from '../common/parameters-editor'; class EditResultDialog extends React.Component { valid = true; @@ -35,6 +37,9 @@ class EditResultDialog extends React.Component { description: '', uploadFile: null, uploadProgress: 0, + fileIDs: [], + files: null, + resultChanged: false, }; } @@ -60,6 +65,8 @@ class EditResultDialog extends React.Component { id: this.props.result.id, description: this.props.result.description, result: this.props.result, + fileIDs: this.props.result.resultFileIDs, + files: FileStore.getState().filter(file => this.props.result.resultFileIDs.includes(file.id)), }); }; @@ -72,11 +79,8 @@ class EditResultDialog extends React.Component { }; startFileUpload(){ - // upload file const formData = new FormData(); formData.append("file", this.state.uploadFile); - //console.log("formData: "); - //console.log(formData); AppDispatcher.dispatch({ type: 'resultfiles/start-upload', @@ -99,21 +103,47 @@ class EditResultDialog extends React.Component { this.setState({ uploadProgress: parseInt(event.percent.toFixed(), 10) }); }; + deleteFile(index){ + let file = this.state.files[index] + AppDispatcher.dispatch({ + type: 'files/start-remove', + data: file, + token: this.props.sessionToken + }); + } + render() { + if (this.props.show) { + } return + valid={true} + size = 'lg'> -
+ +
Description + + + + + + this.deleteFile(index)} + /> +
+ + Add Result File this.selectUploadFile(event)} /> @@ -136,23 +166,9 @@ class EditResultDialog extends React.Component { /> - +
; } } -export default EditResultDialog; - -/* - - - - - this.deleteFile(index)} - /> -
- - '*/ +export default EditResultDialog; \ No newline at end of file diff --git a/src/result/new-result.js b/src/result/new-result.js index d07f94e..11023a1 100644 --- a/src/result/new-result.js +++ b/src/result/new-result.js @@ -56,13 +56,7 @@ class NewResultDialog extends React.Component { render() { return ( this.onClose(c)} onReset={() => this.resetState()} valid={true}> -
- - Config Snapshots - this.handleChange(e)} /> - - - + Description this.handleChange(e)} /> diff --git a/src/result/result-store.js b/src/result/result-store.js index 3437d7e..f59edb4 100644 --- a/src/result/result-store.js +++ b/src/result/result-store.js @@ -18,6 +18,7 @@ import ArrayStore from '../common/array-store'; import ResultsDataManager from './results-data-manager'; +import FilesDataManager from '../file/files-data-manager' class ResultStore extends ArrayStore { constructor() { @@ -74,11 +75,11 @@ class ResultStore extends ArrayStore { return super.reduce(state, action); case 'resultfiles/start-download': - ResultsDataManager.download(action) + //FilesDataManager.download(action) return state case 'resultfiles/start-upload': - ResultsDataManager.upload(action.data, action.resultID, action.token, action.progressCallback, action.finishedCallback, action.scenarioID); + ResultsDataManager.uploadFile(action.data, action.resultID, action.token, action.progressCallback, action.finishedCallback, action.scenarioID); return state; case 'resultfiles/uploaded': diff --git a/src/result/results-data-manager.js b/src/result/results-data-manager.js index 6720b3d..bae49da 100644 --- a/src/result/results-data-manager.js +++ b/src/result/results-data-manager.js @@ -25,16 +25,23 @@ class ResultsDataManager extends RestDataManager{ super('result', '/results'); } - upload(file, resultID, token = null, progressCallback = null, finishedCallback = null, scenarioID) { + uploadFile(file, resultID, token = null, progressCallback = null, finishedCallback = null, scenarioID) { RestAPI.upload(this.makeURL(this.url + '/' + resultID + '/file') , file, token, progressCallback, scenarioID).then(response => { AppDispatcher.dispatch({ - type: 'resultfiles/uploaded', + type: 'files/uploaded', + }); + + // Trigger a results reload + AppDispatcher.dispatch({ + type: 'results/start-load', + param: '?scenarioID=' + scenarioID, + token: token }); // Trigger a files reload AppDispatcher.dispatch({ - type: 'results/start-load', + type: 'files/start-load', param: '?scenarioID=' + scenarioID, token: token }); @@ -44,7 +51,7 @@ class ResultsDataManager extends RestDataManager{ } }).catch(error => { AppDispatcher.dispatch({ - type: 'resultfiles/upload-error', + type: 'files/upload-error', error }); }); diff --git a/src/scenario/scenario.js b/src/scenario/scenario.js index 5b3f3e6..217d98e 100644 --- a/src/scenario/scenario.js +++ b/src/scenario/scenario.js @@ -50,6 +50,8 @@ import ResultStore from "../result/result-store" import { Redirect } from 'react-router-dom'; import NotificationsDataManager from "../common/data-managers/notifications-data-manager"; +var JSZip = require("jszip"); + class Scenario extends React.Component { static getStores() { @@ -114,6 +116,7 @@ class Scenario extends React.Component { modalResultsIndex: 0, newResultModal: false, editFilesModal: false, + filesToDownload: [], editOutputSignalsModal: prevState.editOutputSignalsModal || false, editInputSignalsModal: prevState.editInputSignalsModal || false, @@ -154,6 +157,33 @@ class Scenario extends React.Component { }); } + componentDidUpdate(prevProps, prevState) { + // check whether file data has been loaded + if (this.state.filesToDownload.length > 0 ) { // todo: for download all - wait until data for all has arrived + console.log(this.state.files); + if (this.state.filesToDownload.length === 1) { + let fileToDownload = FileStore.getState().filter(file => file.id === this.state.filesToDownload[0]) + if (fileToDownload.length === 1 && fileToDownload[0].data) { + const blob = new Blob([fileToDownload[0].data], {type: fileToDownload[0].type}); + FileSaver.saveAs(blob, fileToDownload[0].name); + this.setState({ filesToDownload: [] }); + } + } else { // zip and save several files + let filesToDownload = FileStore.getState().filter(file => this.state.filesToDownload.includes(file.id) && file.data); + if (filesToDownload.length === this.state.filesToDownload.length) { // all requested files have been loaded + var zip = new JSZip(); + filesToDownload.forEach(file => { + zip.file(file.name, file.data); + }); + zip.generateAsync({type: "blob"}).then(function(content) { + saveAs(content, "results.zip"); + }); + this.setState({ filesToDownload: [] }); + } + } + } + } + /* ############################################## * User modification methods ############################################## */ @@ -592,8 +622,24 @@ class Scenario extends React.Component { } } - downloadData(index) { - console.log(index); + downloadResultData(param) { + let toDownload = []; + + if (typeof(param) === 'object') { + toDownload = param.resultFileIDs; + } else { + toDownload.push(param); + } + + toDownload.forEach(fileid => { + AppDispatcher.dispatch({ + type: 'files/start-download', + data: fileid, + token: this.state.sessionToken + }); + }); + + this.setState({ filesToDownload: toDownload }); } closeDeleteResultsModal(confirmDelete) { @@ -683,7 +729,7 @@ class Scenario extends React.Component { dataKey='resultFileIDs' linkKey='filebuttons' width='300' - onDownload={(index) => this.downloadData(index)} + onDownload={(index) => this.downloadResultData(index)} /> this.setState({ editResultsModal: true, modalResultsData: this.state.results[index], modalResultsIndex: index })} - onDownloadAll={(index) => this.downloadData(this.state.results[index])} + onDownloadAll={(index) => this.downloadResultData(this.state.results[index])} onDelete={(index) => this.setState({ deleteResultsModal: true, modalResultsData: this.state.results[index], modalResultsIndex: index })} />