- {renderTraceback()}
+ {loading ? (
+
+
+ ) : (
+ traceback && (
+
+ {renderTraceback()}
+
+ )
)}
>
)}
- {row.status === "FINISHED" && imageUrl && (
-
-
-
+ {row.status === "FINISHED" && (
+ <>
+ {loading ? (
+
+
+
+ ) : (
+ imageUrl && (
+
+
+
+ )
+ )}
+ >
)}
diff --git a/frontend/src/components/Layout/AIModels/AIModelEditor/Trainings.js b/frontend/src/components/Layout/AIModels/AIModelEditor/Trainings.js
index b4456bc2..ab4ab86a 100644
--- a/frontend/src/components/Layout/AIModels/AIModelEditor/Trainings.js
+++ b/frontend/src/components/Layout/AIModels/AIModelEditor/Trainings.js
@@ -1,6 +1,13 @@
import React, { useContext, useEffect, useState } from "react";
import { DataGrid } from "@mui/x-data-grid";
-import { Grid, IconButton, Tooltip, Typography } from "@mui/material";
+import {
+ Grid,
+ IconButton,
+ Tooltip,
+ Typography,
+ CircularProgress,
+} from "@mui/material";
+
import { useMutation, useQuery } from "react-query";
import axios from "../../../../axios";
import Alert from "@material-ui/lab/Alert";
@@ -23,6 +30,8 @@ const DEFAULT_FILTER = {
const AIModelsList = (props) => {
const [error, setError] = useState(null);
const [popupOpen, setPopupOpen] = useState(false);
+ const [publishing, setPublishing] = useState(false);
+
const [popupRow, setPopupRow] = useState(null);
const handlePopupOpen = (row) => {
@@ -61,6 +70,13 @@ const AIModelsList = (props) => {
field: "description",
headerName: "Description",
flex: 1,
+ renderCell: (params) => {
+ return (
+
+ {params.value}
+
+ );
+ },
},
{
field: "epochs",
@@ -172,13 +188,16 @@ const AIModelsList = (props) => {
mutate(params.row.id);
}}
>
-
+ {publishing ? (
+
+ ) : (
+
+ )}
)}
>
);
- //
{`${params.row.status} and id ${params.row.id}`}
;
},
},
];
@@ -191,6 +210,7 @@ const AIModelsList = (props) => {
const { accessToken } = useContext(AuthContext);
const publishModel = async (trainingId) => {
+ setPublishing(true);
try {
const headers = {
"access-token": accessToken,
@@ -213,8 +233,10 @@ const AIModelsList = (props) => {
console.log("isError");
setError(JSON.stringify(e));
} finally {
+ setPublishing(false);
}
};
+
const { mutate } = useMutation(publishModel);
return (
<>
diff --git a/frontend/src/components/Layout/AIModels/AIModelsList/AIModelsList.js b/frontend/src/components/Layout/AIModels/AIModelsList/AIModelsList.js
index e9e6163e..7e2d7d3a 100644
--- a/frontend/src/components/Layout/AIModels/AIModelsList/AIModelsList.js
+++ b/frontend/src/components/Layout/AIModels/AIModelsList/AIModelsList.js
@@ -51,6 +51,14 @@ const AIModelsList = (props) => {
{
field: "name",
headerName: "Name",
+ width: 250,
+ renderCell: (params) => {
+ return (
+
+ {params.value}
+
+ );
+ },
},
{
field: "created_at",
@@ -79,6 +87,7 @@ const AIModelsList = (props) => {
{
field: "dataset",
headerName: "Dataset ID",
+ width: 150,
renderCell: (params) => {
return
{params.value};
diff --git a/frontend/src/components/Layout/Start/ModelsMap/ModelsMap.js b/frontend/src/components/Layout/Start/ModelsMap/ModelsMap.js
index 6bf3b87d..ce1960f2 100644
--- a/frontend/src/components/Layout/Start/ModelsMap/ModelsMap.js
+++ b/frontend/src/components/Layout/Start/ModelsMap/ModelsMap.js
@@ -47,7 +47,18 @@ const PublishedAIModelsList = (props) => {
);
},
},
- { field: "name", headerName: "Name" },
+ {
+ field: "name",
+ headerName: "Name",
+ width: 250,
+ renderCell: (params) => {
+ return (
+
+ {params.value}
+
+ );
+ },
+ },
{
field: "last_modified",
headerName: "Last Modified",
diff --git a/frontend/src/components/Layout/Start/Prediction/Prediction.js b/frontend/src/components/Layout/Start/Prediction/Prediction.js
index 6aa9a00f..31d70427 100644
--- a/frontend/src/components/Layout/Start/Prediction/Prediction.js
+++ b/frontend/src/components/Layout/Start/Prediction/Prediction.js
@@ -17,6 +17,8 @@ import { GeoJSON } from "react-leaflet";
const Prediction = () => {
const { id } = useParams();
const [error, setError] = useState(false);
+ const [apiCallInProgress, setApiCallInProgress] = useState(false);
+
const [map, setMap] = useState(null);
const [zoom, setZoom] = useState(0);
const [responseTime, setResponseTime] = useState(0);
@@ -28,6 +30,20 @@ const Prediction = () => {
]);
const [josmEnabled, setJosmEnabled] = useState(false);
+ useEffect(() => {
+ if (!apiCallInProgress) {
+ return;
+ }
+
+ const timer = setInterval(() => {
+ setResponseTime((prevResponseTime) => prevResponseTime + 1);
+ }, 1000);
+
+ return () => {
+ clearInterval(timer);
+ };
+ }, [apiCallInProgress]);
+
useEffect(() => {
getModel();
}, []);
@@ -80,6 +96,7 @@ const Prediction = () => {
data: predictions,
isLoading: predictionLoading,
} = useMutation(async () => {
+ setApiCallInProgress(true);
const headers = {
"access-token": accessToken,
};
@@ -98,6 +115,7 @@ const Prediction = () => {
const res = await axios.post(`/prediction/`, body, { headers });
const endTime = new Date().getTime(); // measure end time
setResponseTime((endTime - startTime) / 1000); // calculate and store response time in seconds
+ setApiCallInProgress(false);
if (res.error) {
setError(
`${res.error.response.statusText}, ${JSON.stringify(
diff --git a/frontend/src/components/Layout/TrainingDS/DatasetList/DatasetList.js b/frontend/src/components/Layout/TrainingDS/DatasetList/DatasetList.js
index afbbfa3a..0ea4e679 100644
--- a/frontend/src/components/Layout/TrainingDS/DatasetList/DatasetList.js
+++ b/frontend/src/components/Layout/TrainingDS/DatasetList/DatasetList.js
@@ -52,6 +52,13 @@ const DatasetList = (props) => {
field: "name",
headerName: "Name",
width: 250,
+ renderCell: (params) => {
+ return (
+
+ {params.value}
+
+ );
+ },
},
{
field: "created_at",