Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
8baa961
feat: Add EditRunDialog component for editing model run parameters
Felipedino Jan 26, 2026
928d774
feat: Enhance RunCard component with editing capabilities for model r…
Felipedino Jan 26, 2026
7b71d8b
feat: Add LiveMetricsChart and HyperparameterPlots components for enh…
Felipedino Jan 26, 2026
f8e6787
Merge branch 'develop' into feat/models-live-metrics
Felipedino Jan 27, 2026
108375c
Merge branch 'develop' into feat/models-live-metrics
Felipedino Jan 27, 2026
ab6f061
Fix translation issues in models
Felipedino Jan 27, 2026
81eccb1
fix precommit
Felipedino Jan 27, 2026
e6a3c79
Fix translations errors
Felipedino Feb 1, 2026
fe3192a
fix: Now the optimizer info in "show parameters" is displayed only wh…
Felipedino Feb 1, 2026
0889771
fix: update run parameters to include optional name and clean up unus…
Felipedino Feb 1, 2026
b606a16
Fix1 precommit
Felipedino Feb 1, 2026
dfc3763
fix requirements transformers test
Felipedino Feb 1, 2026
bc6e2e4
Fixing precommit try 1
cristian-tamblay Feb 23, 2026
d5d3a65
Merge branch 'develop' into feat/models-live-metrics
cristian-tamblay Feb 23, 2026
9a283d4
Merge branch 'develop' into feat/models-live-metrics
Felipedino Feb 25, 2026
15eaa3e
feat: explainers cards have same width when plots are hidden
Felipedino Feb 25, 2026
1e99222
feat: remove JobQueueWidget from multiple components and create only …
Felipedino Feb 25, 2026
d54c351
feat: Added a dialog to confirm when try to edit parameters and the m…
Felipedino Feb 25, 2026
4a82723
fix copilot github overview.
Felipedino Feb 25, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions DashAI/front/src/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import NewPipeline from "./pages/pipelines/NewPipeline";
import PluginsDetails from "./pages/plugins/components/PluginsDetails";
import Generative from "./pages/generative/Generative";
import NewPipelineWrapper from "./pages/pipelines/newPipelineWrapper";
import JobQueueWidget from "./components/jobs/JobQueueWidget";

function App() {
return (
Expand Down Expand Up @@ -53,6 +54,7 @@ function App() {
</Route>
</Route>
</Routes>
<JobQueueWidget />
</BrowserRouter>
);
}
Expand Down
2 changes: 2 additions & 0 deletions DashAI/front/src/api/run.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,12 +60,14 @@ export const deleteRun = async (runId: string): Promise<void> => {

export const updateRunParameters = async (
runId: string,
name?: string,
parameters?: object,
optimizer?: string,
optimizer_parameters?: object,
goal_metric?: string,
): Promise<IRun> => {
const response = await api.patch<IRun>(`/v1/run/${runId}`, {
run_name: name,
parameters,
optimizer,
optimizer_parameters,
Expand Down
3 changes: 0 additions & 3 deletions DashAI/front/src/components/DatasetVisualization.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ import {
getDatasetFileFiltered,
} from "../api/datasets";
import { useTourContext } from "./tour/TourProvider";
import JobQueueWidget from "./jobs/JobQueueWidget";
import { formatDate } from "../pages/results/constants/formatDate";
import Header from "./notebooks/dataset/header/Header";
import Tooltip from "@mui/material/Tooltip";
Expand Down Expand Up @@ -415,8 +414,6 @@ export default function DatasetVisualization({
</Box>
)}
</Box>

<JobQueueWidget />
</>
);
}
22 changes: 1 addition & 21 deletions DashAI/front/src/components/custom/CustomLayout.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import React from "react";
import PropTypes from "prop-types";
import Container from "@mui/material/Container";
import { useMediaQuery, Typography, Box } from "@mui/material";
import JobQueueWidget from "../jobs/JobQueueWidget";
import { useTheme } from "@mui/material/styles";

/**
Expand All @@ -21,26 +20,8 @@ function CustomLayout({
const theme = useTheme();
const matches = useMediaQuery(theme.breakpoints.up(xxl));

const jobQueueWidgetElement = (
<Box
sx={{
position: "fixed",
bottom: "20px",
right: "20px",
zIndex: 1000,
}}
>
<JobQueueWidget />
</Box>
);

if (disableContainer) {
return (
<React.Fragment>
{children}
{jobQueueWidgetElement}
</React.Fragment>
);
return <React.Fragment>{children}</React.Fragment>;
}

return (
Expand All @@ -58,7 +39,6 @@ function CustomLayout({
)}
<Box sx={{ p: padding }}>{children}</Box>
</Container>
{jobQueueWidgetElement}
</React.Fragment>
);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
import React, { useState } from "react";
import { GridActionsCellItem } from "@mui/x-data-grid";
import { Edit } from "@mui/icons-material";
import { updateRunParameters } from "../../../api/run";

import { Box } from "@mui/system";
import RunInfoModal from "./RunInfoModal";
import { useTranslation } from "react-i18next";

export default function EditRunDialog({ experiment, run, setRun }) {
const isRunning = run.status === 1 || run.status === 2; // Delivered or Started
const isRunning = run.status === 1 || run.status === 2;
if (isRunning) {
return null;
}
Expand Down
85 changes: 43 additions & 42 deletions DashAI/front/src/components/explainers/ExplainersPlot.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { React, useEffect, useState } from "react";
import {
FormControl,
InputLabel,
Grid,
MenuItem,
Select,
CircularProgress,
Expand Down Expand Up @@ -59,47 +58,49 @@ export default function ExplainersPlot({ explainer, scope }) {
}, [explainer.status]);

return (
<Grid container flexDirection={"row"} justifyContent={"space-between"}>
<Grid size={{ xs: 8 }}>
{!loading && isLocal && (
<FormControl variant="outlined" sx={{ minWidth: "200px" }}>
<InputLabel id="select-type-label">Select an instance</InputLabel>
<Select
id="select-type"
value={currentPlot}
onChange={(event) => setCurrentPlot(event.target.value)}
label="class"
autoWidth
>
{explainersPlots.map((_, i) => (
<MenuItem key={i} value={i}>
{t("explainers:label.instanceNumber", { number: i + 1 })}
</MenuItem>
))}
</Select>
</FormControl>
)}
</Grid>
<Grid size={{ xs: 8 }}>
{!loading && explainer.status === 3 ? (
<Plot
data={explainersPlots[currentPlot].data}
layout={{
...explainersPlots[currentPlot].layout,
width: 730,
height: 380,
}}
config={{ staticPlot: false }}
/>
) : explainer.status === 4 ? (
<Box>{t("explainers:error.explainerFailed")}</Box>
) : (
<Box sx={{ display: "flex", justifyContent: "flex-start", p: 2 }}>
<CircularProgress />
</Box>
)}
</Grid>
</Grid>
<Box
sx={{
display: "flex",
flexDirection: "column",
alignItems: "flex-start",
}}
>
{!loading && isLocal && (
<FormControl variant="outlined" sx={{ minWidth: "200px", mb: 1 }}>
<InputLabel id="select-type-label">Select an instance</InputLabel>
<Select
id="select-type"
value={currentPlot}
onChange={(event) => setCurrentPlot(event.target.value)}
label="class"
autoWidth
>
{explainersPlots.map((_, i) => (
<MenuItem key={i} value={i}>
{t("explainers:label.instanceNumber", { number: i + 1 })}
</MenuItem>
))}
</Select>
</FormControl>
)}
{!loading && explainer.status === 3 ? (
<Plot
data={explainersPlots[currentPlot].data}
layout={{
...explainersPlots[currentPlot].layout,
width: 730,
height: 380,
}}
config={{ staticPlot: false }}
/>
) : explainer.status === 4 ? (
<Box sx={{ p: 2 }}>{t("explainers:error.explainerFailed")}</Box>
) : (
<Box sx={{ display: "flex", justifyContent: "flex-start", p: 2 }}>
<CircularProgress />
</Box>
)}
</Box>
);
}

Expand Down
40 changes: 32 additions & 8 deletions DashAI/front/src/components/explainers/ExplanainersCard.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,17 @@ export default function ExplainersCard({
compact = false,
}) {
const [open, setOpen] = useState(false);
const [expanded, setExpanded] = useState(true);
const [expanded, setExpanded] = useState(() => {
const saved = localStorage.getItem(`explainer-${explainer.id}-expanded`);
return saved !== null ? JSON.parse(saved) : true;
});

useEffect(() => {
localStorage.setItem(
`explainer-${explainer.id}-expanded`,
JSON.stringify(expanded),
);
}, [expanded, explainer.id]);
const [componentData, setComponentData] = useState(null);
const { t } = useTranslation(["explainers"]);

Expand Down Expand Up @@ -77,7 +87,7 @@ export default function ExplainersCard({
if (compact) {
return (
<>
<Paper elevation={2} sx={{ p: 2, width: "100%" }}>
<Paper elevation={2} sx={{ p: 2 }}>
<Grid container direction="column" gap={1}>
<Grid
item
Expand All @@ -86,14 +96,28 @@ export default function ExplainersCard({
justifyContent="space-between"
alignItems="center"
>
<Grid item>
<Typography variant="subtitle2" fontWeight="medium">
<Grid item sx={{ width: 300, minWidth: 0, overflow: "hidden" }}>
<Typography
variant="subtitle2"
fontWeight="medium"
sx={{
display: "flex",
alignItems: "center",
gap: 1,
flexWrap: "wrap",
wordBreak: "break-word",
}}
>
{componentData
? componentData.display_name
: plotName(explainer.explainer_name)}
</Typography>
<Typography variant="caption" color="text.secondary">
{explainer.name}
<Typography
variant="caption"
color="text.secondary"
component="span"
>
{explainer.name}
</Typography>
</Typography>
</Grid>
<Grid item>
Expand Down Expand Up @@ -158,7 +182,7 @@ export default function ExplainersCard({
// Full mode for standalone page
return (
<Paper elevation={3}>
<Grid container item minWidth={800} maxWidth={800} p={4} gap={2}>
<Grid container item sx={{ width: 800 }} p={4} gap={2}>
<Grid
item
container
Expand Down
3 changes: 0 additions & 3 deletions DashAI/front/src/components/generative/GenerativeChat.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ import InfoSessionModal from "./InfoSessionModal";
import { useSnackbar } from "notistack";
import { TextInput } from "./TextInput";
import { MediaInput } from "./MediaInput";
import JobQueueWidget from "../jobs/JobQueueWidget";
import { getRunStatus } from "../../utils/runStatus";
import { Trans, useTranslation } from "react-i18next";

Expand Down Expand Up @@ -334,8 +333,6 @@ export default function GenerativeChat({ sessionId, taskName, paramsVersion }) {
onClose={() => setSessionInfoVisible(false)}
/>
)}

<JobQueueWidget />
</Box>
);
}
39 changes: 29 additions & 10 deletions DashAI/front/src/components/jobs/JobQueueWidget.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,6 @@ const JobQueueWidget = () => {
const [clearingAll, setClearingAll] = useState(false);
const [forceUpdate, setForceUpdate] = useState(0);
const [isHovered, setIsHovered] = useState(false);
const prevActiveJobsCount = useRef(0);

const handleClearAllJobs = () => {
setConfirmClearAll(true);
Expand Down Expand Up @@ -139,18 +138,38 @@ const JobQueueWidget = () => {
const finishedJobs = jobs.filter((job) => job.status === "finished");
const errorJobs = jobs.filter((job) => job.status === "error");

const hasInitializedRef = useRef(false);
const prevActiveCountRef = useRef(0);

// Snapshot del estado inicial al completar la primera carga (evita tratar
// jobs ya existentes como nuevos y disparar el expand al montar)
useEffect(() => {
if (
activeJobs.length > 0 &&
activeJobs.length !== prevActiveJobsCount.current &&
!expanded
) {
if (!loading && !hasInitializedRef.current) {
hasInitializedRef.current = true;
prevActiveCountRef.current = activeJobs.length;
}
}, [loading, activeJobs.length]);

// Auto expand/collapse por transiciones reales durante la sesión
useEffect(() => {
if (!hasInitializedRef.current) return;
const prev = prevActiveCountRef.current;
const curr = activeJobs.length;
if (prev === 0 && curr > 0) {
setExpanded(true);
const toastTimeout = setTimeout(() => {}, 100);
return () => clearTimeout(toastTimeout);
} else if (prev > 0 && curr === 0) {
setExpanded(false);
}
prevActiveCountRef.current = curr;
}, [activeJobs.length]);

useEffect(() => {
try {
localStorage.setItem("jobQueueWidgetExpanded", String(expanded));
} catch (e) {
// ignore
}
prevActiveJobsCount.current = activeJobs.length;
}, [activeJobs.length, expanded]);
}, [expanded]);

const handleToggleExpand = () => {
setExpanded(!expanded);
Expand Down
2 changes: 1 addition & 1 deletion DashAI/front/src/components/models/AddModelDialog.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ import { useTourContext } from "../tour/TourProvider";
/**
* Dialog for adding a new model run to a session
* Step 1: Configure model name and parameters
* Step 2: Configure optimizer
* Step 2: Configure optimizer for train
*/
function AddModelDialog({
open,
Expand Down
5 changes: 1 addition & 4 deletions DashAI/front/src/components/models/CreateSessionSteps.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import { useTourContext } from "../tour/TourProvider";
import SetNameAndDatasetStep from "./SetNameAndDatasetStep";
import PrepareDatasetStep from "../experiments/PrepareDatasetStep";
import FormSchemaButtonGroup from "../shared/FormSchemaButtonGroup";
import JobQueueWidget from "../jobs/JobQueueWidget";
import { createModelSession } from "../../api/modelSession";
import { getComponents } from "../../api/component";
import { generateSequentialName } from "../../utils/nameGenerator";
Expand Down Expand Up @@ -309,9 +308,7 @@ function CreateSessionSteps({
right: "20px",
zIndex: 1000,
}}
>
<JobQueueWidget />
</Box>
></Box>
</>
);
}
Expand Down
Loading