mirror of
https://git.rwth-aachen.de/acs/public/villas/web/
synced 2025-03-09 00:00:01 +01:00
Changed: icstatus due to bouncing, player for responsiveness, python dialog for a slew specific endpoint
Signed-off-by: SystemsPurge <naktiyoussef@proton.me>
This commit is contained in:
parent
4197c08551
commit
5f735bf73e
4 changed files with 65 additions and 31 deletions
|
@ -22,13 +22,11 @@ import { loadICbyId } from "../../../../store/icSlice";
|
|||
import { sessionToken } from "../../../../localStorage";
|
||||
import { useDispatch } from "react-redux";
|
||||
|
||||
let timer = null
|
||||
const WidgetICstatus = (props) => {
|
||||
const dispatch = useDispatch()
|
||||
const [ics,setIcs] = useState(props.ics)
|
||||
|
||||
useEffect(() => {
|
||||
// Function to refresh data
|
||||
const refresh = async() => {
|
||||
const refresh = async() => {
|
||||
if (props.ics) {
|
||||
let iccs = [];
|
||||
for(let ic of props.ics){
|
||||
|
@ -38,10 +36,11 @@ const WidgetICstatus = (props) => {
|
|||
setIcs(iccs)
|
||||
}
|
||||
};
|
||||
useEffect(() => {
|
||||
window.clearInterval(timer)
|
||||
timer = window.setInterval(refresh,3000)
|
||||
// Function to refresh data
|
||||
refresh()
|
||||
// Start timer for periodic refresh
|
||||
const timer = window.setInterval(() => refresh(), 3000);
|
||||
|
||||
// Cleanup function equivalent to componentWillUnmount
|
||||
return () => {
|
||||
window.clearInterval(timer);
|
||||
|
|
|
@ -14,9 +14,9 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with VILLASweb. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
|
||||
import JSZip from 'jszip';
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { Container, Row, Col } from 'react-bootstrap';
|
||||
import { Container, Row, Col,Form } from 'react-bootstrap';
|
||||
import {sendActionToIC,loadICbyId} from "../../../../store/icSlice";
|
||||
import { sessionToken } from '../../../../localStorage';
|
||||
import IconButton from '../../../../common/buttons/icon-button';
|
||||
|
@ -25,20 +25,21 @@ import ParametersEditor from '../../../../common/parameters-editor';
|
|||
import ResultPythonDialog from '../../../scenarios/dialogs/result-python-dialog';
|
||||
import { playerMachine } from '../widget-player/player-machine';
|
||||
import { interpret } from 'xstate';
|
||||
import { useSendActionMutation, useLazyDownloadFileQuery, useGetResultsQuery, useGetFilesQuery } from '../../../../store/apiSlice';
|
||||
import { useAddResultMutation, useLazyDownloadFileQuery, useGetResultsQuery, useGetFilesQuery } from '../../../../store/apiSlice';
|
||||
import notificationsDataManager from '../../../../common/data-managers/notifications-data-manager';
|
||||
import NotificationsFactory from '../../../../common/data-managers/notifications-factory';
|
||||
import { start } from 'xstate/lib/actions';
|
||||
import FileSaver from "file-saver";
|
||||
import { useDispatch } from 'react-redux';
|
||||
|
||||
const WidgetPlayer = (
|
||||
{widget, editing, configs, onStarted, ics, results, files, scenarioID}) => {
|
||||
const dispatch = useDispatch()
|
||||
const zip = new JSZip()
|
||||
const [triggerDownloadFile] = useLazyDownloadFileQuery();
|
||||
const {refetch: refetchResults} = useGetResultsQuery(scenarioID);
|
||||
const {refetch: refetchFiles} = useGetFilesQuery(scenarioID);
|
||||
|
||||
|
||||
const [addResult, {isError: isErrorAddingResult}] = useAddResultMutation();
|
||||
const [playerState, setPlayerState] = useState(playerMachine.initialState);
|
||||
const [configID, setConfigID] = useState(-1);
|
||||
const [config, setConfig] = useState({});
|
||||
|
@ -109,7 +110,9 @@ const WidgetPlayer = (
|
|||
case 'stopping': // if configured, show results
|
||||
if (isUploadResultsChecked) {
|
||||
refetchResults();
|
||||
refetchFiles();
|
||||
refetchFiles().then(v=>{
|
||||
setFilesToDownload(v.data.files)
|
||||
});
|
||||
}
|
||||
newState = transitionState(playerState, 'FINISH')
|
||||
setPlayerState(newState);
|
||||
|
@ -133,11 +136,24 @@ const WidgetPlayer = (
|
|||
}
|
||||
|
||||
const clickStart = async () => {
|
||||
const startConfig = { ...config };
|
||||
startConfig.startParameters = startParameters;
|
||||
|
||||
try {
|
||||
dispatch(sendActionToIC({token:sessionToken,id:config.icID,actions:[{action:"start",when:Math.round((new Date()).getTime() / 1000),parameters:{...config.startParameters}}]}))
|
||||
let pld = {action:"start",when:Math.round((new Date()).getTime() / 1000),parameters:{...config.startParameters}}
|
||||
if(isUploadResultsChecked){
|
||||
addResult({result: {
|
||||
scenarioID: scenarioID
|
||||
}})
|
||||
.then(v=>{
|
||||
pld.results = {
|
||||
url: `https://slew.k8s.eonerc.rwth-aachen.de/api/v2/results/${v.data.result.id}/file`,
|
||||
type: "url",
|
||||
token: sessionToken
|
||||
}
|
||||
dispatch(sendActionToIC({token:sessionToken,id:config.icID,actions:[pld]}))
|
||||
})
|
||||
.catch(e=>{
|
||||
notificationsDataManager.addNotification(NotificationsFactory.LOAD_ERROR(e.toString()));
|
||||
})
|
||||
}
|
||||
//sendAction({ icid: startConfig.icID, action: "start", when: Math.round((new Date()).getTime() / 1000), parameters: {...startParameters } }).unwrap();
|
||||
} catch(error) {
|
||||
notificationsDataManager.addNotification(NotificationsFactory.LOAD_ERROR(error?.data?.message));
|
||||
|
@ -175,18 +191,28 @@ const WidgetPlayer = (
|
|||
}
|
||||
|
||||
setFilesToDownload(toDownload);
|
||||
|
||||
}
|
||||
|
||||
const handleDownloadFile = async (fileID) => {
|
||||
try {
|
||||
const res = await triggerDownloadFile(fileID);
|
||||
const file = files.find(f => f.id === fileID);
|
||||
const blob = new Blob([res], { type: 'application/octet-stream' });
|
||||
triggerDownloadFile(fileID)
|
||||
.then(v=>{
|
||||
console.log(filesToDownload)
|
||||
const file = filesToDownload.find(f => f.id === fileID);
|
||||
const blob = new Blob([v.data], { type: 'application/octet-stream' });
|
||||
zip.file(file.name, blob);
|
||||
} catch (error) {
|
||||
notificationsDataManager.addNotification(NotificationsFactory.UPDATE_ERROR(error?.data?.message));
|
||||
}
|
||||
zip.generateAsync({ type: 'blob' })
|
||||
.then((content) => {
|
||||
FileSaver.saveAs(content, `result-${file.id}.zip`);
|
||||
})
|
||||
.catch((err) => {
|
||||
notificationsDataManager.addNotification(NotificationsFactory.UPDATE_ERROR('Failed to create ZIP archive'));
|
||||
console.error('Failed to create ZIP archive', err);
|
||||
});
|
||||
})
|
||||
.catch(e=>{
|
||||
notificationsDataManager.addNotification(NotificationsFactory.UPDATE_ERROR(e));
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
const openPythonDialog = () => {
|
||||
|
@ -255,10 +281,21 @@ const WidgetPlayer = (
|
|||
</span>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row className="justify-content-md-center">
|
||||
<Col lg='auto'>
|
||||
<Form.Group controlId="resultCheck">
|
||||
<Form.Check
|
||||
type="checkbox"
|
||||
label="Results"
|
||||
checked={isUploadResultsChecked}
|
||||
onChange={() => setIsUploadResultsChecked(prevState => !prevState)}
|
||||
/>
|
||||
</Form.Group>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
{isUploadResultsChecked ?
|
||||
<div>
|
||||
<p style={{ marginTop: '8px', marginBottom: '0px', textAlign: 'center' }}>Results</p>
|
||||
<Row style={{ marginTop: '0px' }}>
|
||||
<Col lg={{ span: 6 }}>
|
||||
<span className='play-button'>
|
||||
|
@ -266,7 +303,7 @@ const WidgetPlayer = (
|
|||
childKey={0}
|
||||
onClick={() => openPythonDialog()}
|
||||
icon={['fab', 'python']}
|
||||
disabled={(playerState && playerState.matches('finished')) ? false : true}
|
||||
disabled={(playerState && playerState.matches('finished')&& isUploadResultsChecked) ? false : true}
|
||||
iconStyle={iconStyle}
|
||||
/>
|
||||
</span>
|
||||
|
@ -277,7 +314,7 @@ const WidgetPlayer = (
|
|||
childKey={1}
|
||||
onClick={() => downloadResultFiles()}
|
||||
icon='file-download'
|
||||
disabled={(playerState && playerState.matches('finished')) ? false : true}
|
||||
disabled={(playerState && playerState.matches('finished') ) ? false : true}
|
||||
iconStyle={iconStyle}
|
||||
/>
|
||||
</span>
|
||||
|
|
|
@ -105,7 +105,7 @@ class ResultPythonDialog extends React.Component {
|
|||
code_snippets.push(code_imports)
|
||||
|
||||
/* Result object */
|
||||
code_snippets.push(`r = Result(${result.id}, '${token}')`);
|
||||
code_snippets.push(`r = Result(${result.id}, '${token}', endpoint='https://slew.k8s.eonerc.rwth-aachen.de')`);
|
||||
|
||||
/* Examples */
|
||||
code_snippets.push(`# Get result metadata
|
||||
|
|
|
@ -20,7 +20,6 @@ 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 { useSendActionMutation, useAddResultMutation, useLazyGetSignalsQuery, useGetResultsQuery } from '../../../store/apiSlice';
|
||||
import NotificationsFactory from "../../../common/data-managers/notifications-factory";
|
||||
|
@ -83,7 +82,6 @@ const ConfigActionBoard = ({selectedConfigs, scenarioID}) => {
|
|||
const res = await addResult({result: newResult}).unwrap();
|
||||
|
||||
if(!isErrorAddingResult){
|
||||
console.log("result", res)
|
||||
const url = window.location.origin;
|
||||
action.results = {
|
||||
url: `https://slew.k8s.eonerc.rwth-aachen.de/api/v2/results/${res.result.id}/file`,
|
||||
|
|
Loading…
Add table
Reference in a new issue