v1.0
- added task rendering instead of molecule - fied a lot of errors - changes experiment page to show generic experiment info
This commit is contained in:
@@ -1,24 +1,45 @@
|
||||
import { Card, Pill, SimpleGrid, Text, UnstyledButton } from "@mantine/core";
|
||||
import "./ExperimentsListCard.css";
|
||||
import { useNavigate } from "react-router";
|
||||
import type { Experiment, TaskData } from "Types/Experiment/Experiment";
|
||||
import type {
|
||||
ExperimentData,
|
||||
SimpleInstanceData,
|
||||
} from "Types/Experiment/Experiment";
|
||||
import { IconTrash } from "@tabler/icons-react";
|
||||
import type { MouseEvent } from "react";
|
||||
import { useExperimentStore } from "Stores/ExperimentStore";
|
||||
import { deleteExperiment } from "Api/QuantumBackend/ExperimentsManagment";
|
||||
|
||||
function ExperimentsListCard(props: {
|
||||
experiment: Experiment;
|
||||
team: { team_id: number; team_name: string } | undefined;
|
||||
}) {
|
||||
function ExperimentsListCard(props: { experiment: ExperimentData }) {
|
||||
const navigate = useNavigate();
|
||||
const { removeExperiment, tasks } = useExperimentStore();
|
||||
const { removeExperiment } = useExperimentStore();
|
||||
|
||||
const experiment_tasks = tasks.filter(
|
||||
(a) => a.id in props.experiment.tasks_ids,
|
||||
);
|
||||
const getStatusColor = (status: string) => {
|
||||
const statusLower = status;
|
||||
|
||||
switch (statusLower) {
|
||||
case "draft":
|
||||
return "var(--mantine-color-gray-5)";
|
||||
case "in queue":
|
||||
return "var(--mantine-color-blue-5)";
|
||||
case "processing":
|
||||
case "running":
|
||||
return "var(--mantine-color-yellow-5)";
|
||||
case "complete":
|
||||
return "var(--mantine-color-green-5)";
|
||||
case "error":
|
||||
case "complete with error":
|
||||
case "failed":
|
||||
return "var(--mantine-color-red-5)";
|
||||
default:
|
||||
return "var(--mantine-color-gray-5)";
|
||||
}
|
||||
};
|
||||
|
||||
const handleDelete = () => {
|
||||
removeExperiment(props.experiment.id);
|
||||
deleteExperiment(props.experiment.id).then(() => {
|
||||
removeExperiment(props.experiment.id);
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
@@ -34,30 +55,38 @@ function ExperimentsListCard(props: {
|
||||
Эксперимент: {props.experiment.name}
|
||||
</Text>
|
||||
<Text mb="sm" size="md">
|
||||
Команда: {props.team?.team_name}
|
||||
Команда: {props.experiment.team?.team_name}
|
||||
</Text>
|
||||
<div style={{ display: "flex", gap: "10px" }}>
|
||||
<Text size="md">Статус: </Text>
|
||||
<Pill style={{ backgroundColor: "var(--mantine-color-yellow-5)" }}>
|
||||
<Text size="md">{props.experiment.experiment_status}</Text>
|
||||
<Pill
|
||||
style={{
|
||||
backgroundColor: getStatusColor(
|
||||
props.experiment.status != undefined
|
||||
? props.experiment.status.toLowerCase()
|
||||
: "DRAFT",
|
||||
),
|
||||
color: "white",
|
||||
}}
|
||||
>
|
||||
<Text size="md">{props.experiment.status}</Text>
|
||||
</Pill>
|
||||
</div>
|
||||
</div>
|
||||
<div className="ExperimentSectionWithLine">
|
||||
<SimpleGrid cols={2} verticalSpacing="0px">
|
||||
<Text>Задачи:</Text>
|
||||
<SimpleGrid cols={2} verticalSpacing="0px" style={{ rowGap: "4px" }}>
|
||||
<Text size="sm">Задачи:</Text>
|
||||
|
||||
{experiment_tasks.map(
|
||||
{props.experiment.instance_preview.slice(0, 6).map(
|
||||
(
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
task: TaskData<any>,
|
||||
instance: SimpleInstanceData,
|
||||
) => {
|
||||
return (
|
||||
<Pill
|
||||
size="md"
|
||||
size="sm"
|
||||
className="ExperimentPill"
|
||||
style={{
|
||||
backgroundColor: "transparent",
|
||||
border: "2px solid black",
|
||||
alignContent: "center",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
@@ -65,40 +94,50 @@ function ExperimentsListCard(props: {
|
||||
}}
|
||||
>
|
||||
<Text
|
||||
size="md"
|
||||
size="sm"
|
||||
style={{
|
||||
textWrap: "nowrap",
|
||||
textOverflow: "ellipsis",
|
||||
overflow: "hidden",
|
||||
}}
|
||||
>
|
||||
{task.name}
|
||||
{instance.name}
|
||||
</Text>
|
||||
</Pill>
|
||||
);
|
||||
},
|
||||
)}
|
||||
{experiment_tasks.length == 0 ? (
|
||||
<Pill size="md" className="ExperimentPill2">
|
||||
{props.experiment.instances_count == 0 ? (
|
||||
<Pill size="sm" className="ExperimentPill2">
|
||||
Нет Задач
|
||||
</Pill>
|
||||
) : (
|
||||
<></>
|
||||
)}
|
||||
{props.experiment.instances_count >
|
||||
props.experiment.instance_preview.length ? (
|
||||
<Pill size="sm" className="ExperimentPill2">
|
||||
и еще{" "}
|
||||
{props.experiment.instances_count -
|
||||
props.experiment.instance_preview.length}
|
||||
</Pill>
|
||||
) : (
|
||||
<></>
|
||||
)}
|
||||
</SimpleGrid>
|
||||
</div>
|
||||
<div className="RightExperimentSection">
|
||||
<div className="TopRightContainer">
|
||||
<div className="dateContainer">
|
||||
<Text size="sm">
|
||||
{new Date(
|
||||
props.experiment.date_created + "Z",
|
||||
).toLocaleDateString("ru")}{" "}
|
||||
{new Date(props.experiment.created_at + "Z").toLocaleDateString(
|
||||
"ru",
|
||||
)}{" "}
|
||||
</Text>
|
||||
<Text size="sm">
|
||||
{new Date(
|
||||
props.experiment.date_created + "Z",
|
||||
).toLocaleTimeString("ru")}
|
||||
{new Date(props.experiment.created_at + "Z").toLocaleTimeString(
|
||||
"ru",
|
||||
)}
|
||||
</Text>
|
||||
</div>
|
||||
<UnstyledButton
|
||||
@@ -122,7 +161,7 @@ function ExperimentsListCard(props: {
|
||||
>
|
||||
<Text> Тип эксперимента: </Text>
|
||||
<Pill className="ExperimentPill">
|
||||
{props.experiment.experiment_type}
|
||||
{props.experiment.experiment_type.name}
|
||||
</Pill>
|
||||
</div>
|
||||
<Text c="dimmed" size="sm">
|
||||
|
||||
@@ -64,7 +64,8 @@ function MachinesListCard(props: SystemWithTeams) {
|
||||
//className="MachinePill"
|
||||
style={{
|
||||
marginLeft: "10px",
|
||||
backgroundColor: colors[props.system.status || "ONLINE"],
|
||||
backgroundColor:
|
||||
colors[props.system.status as "ONLINE" | "OFFLINE" | "BUSY"],
|
||||
}}
|
||||
>
|
||||
<Text size="md">{props.system.status}</Text>
|
||||
@@ -82,12 +83,12 @@ function MachinesListCard(props: SystemWithTeams) {
|
||||
</Text>
|
||||
<div style={{ display: "flex", gap: "10px", justifyContent: "right" }}>
|
||||
<Text size="sm">
|
||||
{new Date(props.system.created_at + "Z").toLocaleDateString(
|
||||
{new Date(props.system.last_updated + "Z").toLocaleDateString(
|
||||
"ru",
|
||||
)}{" "}
|
||||
</Text>
|
||||
<Text size="sm">
|
||||
{new Date(props.system.created_at + "Z").toLocaleTimeString("ru")}
|
||||
{new Date(props.system.last_updated + "Z").toLocaleTimeString("ru")}
|
||||
</Text>
|
||||
</div>
|
||||
</Card.Section>
|
||||
|
||||
28
src/Components/ListCard/TaskListCard/TaskListCard.css
Normal file
28
src/Components/ListCard/TaskListCard/TaskListCard.css
Normal file
@@ -0,0 +1,28 @@
|
||||
.InstancesListCard {
|
||||
height: 120px;
|
||||
}
|
||||
|
||||
.InstanceSectionWithLine {
|
||||
width: 250px;
|
||||
}
|
||||
|
||||
.InstanceIframeSection {
|
||||
flex-grow: 1;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.DatesContainer {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
.RightInstanceSection {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
width: 275px;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.MachinePill {
|
||||
background-color: var(--mantine-color-contrast-filled);
|
||||
color: var(--mantine-color-primary-filled);
|
||||
}
|
||||
176
src/Components/ListCard/TaskListCard/TaskListCard.tsx
Normal file
176
src/Components/ListCard/TaskListCard/TaskListCard.tsx
Normal file
@@ -0,0 +1,176 @@
|
||||
import { Card, Pill, Text, UnstyledButton } from "@mantine/core";
|
||||
import { useNavigate } from "react-router";
|
||||
import type { InstanceData } from "Types/Experiment/Experiment";
|
||||
import { IconCheck, IconTrash } from "@tabler/icons-react";
|
||||
import type { MouseEvent } from "react";
|
||||
import { IframePlugin } from "Api/PluginLoader/PluginLoader";
|
||||
import "./TaskListCard.css";
|
||||
import { deleteInstance } from "Api/QuantumBackend/ExperimentsManagment";
|
||||
import { useExperimentStore } from "Stores/ExperimentStore";
|
||||
import { notifications } from "@mantine/notifications";
|
||||
|
||||
function InstancesListCard(props: { instance: InstanceData; plugin: string }) {
|
||||
const navigate = useNavigate();
|
||||
const { removeInstance } = useExperimentStore();
|
||||
|
||||
const getStatusColor = (status: string) => {
|
||||
const statusLower = status.toLowerCase();
|
||||
|
||||
switch (statusLower) {
|
||||
case "draft":
|
||||
return "var(--mantine-color-gray-5)";
|
||||
case "in queue":
|
||||
return "var(--mantine-color-blue-5)";
|
||||
case "processing":
|
||||
case "running":
|
||||
return "var(--mantine-color-yellow-5)";
|
||||
case "complete":
|
||||
case "completed":
|
||||
return "var(--mantine-color-green-5)";
|
||||
case "error":
|
||||
case "failed":
|
||||
return "var(--mantine-color-red-5)";
|
||||
default:
|
||||
return "var(--mantine-color-gray-5)";
|
||||
}
|
||||
};
|
||||
|
||||
const handleDelete = () => {
|
||||
deleteInstance(props.instance.instance_id).then(() => {
|
||||
removeInstance(props.instance.instance_id);
|
||||
notifications.show({
|
||||
radius: "md",
|
||||
title: "Задача удалена успешно",
|
||||
message: "",
|
||||
icon: <IconCheck />,
|
||||
style: { paddingLeft: "5px" },
|
||||
});
|
||||
});
|
||||
};
|
||||
return (
|
||||
<Card
|
||||
className="InstancesListCard"
|
||||
orientation="horizontal"
|
||||
onClick={(ev) => {
|
||||
console.log("A");
|
||||
ev.stopPropagation();
|
||||
navigate(props.instance.instance_id.toString());
|
||||
}}
|
||||
>
|
||||
<Card.Section
|
||||
withBorder
|
||||
inheritPadding
|
||||
px="md"
|
||||
className="InstanceSectionWithLine"
|
||||
>
|
||||
<Text mb="sm" size="md" style={{ textDecorationLine: "underline" }}>
|
||||
Задача: {props.instance.name}
|
||||
</Text>
|
||||
<div style={{ display: "flex", gap: "10px" }}>
|
||||
<Text size="md">Статус: </Text>
|
||||
<Pill
|
||||
style={{
|
||||
backgroundColor: getStatusColor(
|
||||
props.instance.simulation_result?.status || "",
|
||||
),
|
||||
color: "white",
|
||||
}}
|
||||
>
|
||||
<Text size="md">
|
||||
{props.instance.simulation_result?.status || "DRAFT"}
|
||||
</Text>
|
||||
</Pill>
|
||||
</div>
|
||||
<div style={{ display: "flex", gap: "10px" }}>
|
||||
<Text size="md">ВС: </Text>
|
||||
<Pill className="MachinePill">
|
||||
<Text size="md">
|
||||
{props.instance.simulation_result?.comp_system?.system_name ||
|
||||
"--"}
|
||||
</Text>
|
||||
</Pill>
|
||||
</div>
|
||||
</Card.Section>
|
||||
<Card.Section withBorder className="InstanceIframeSection">
|
||||
{JSON.stringify(props.instance.instance_data) && (
|
||||
<IframePlugin
|
||||
plugin={props.plugin}
|
||||
mode="List"
|
||||
taskData={JSON.stringify(props.instance.instance_data)}
|
||||
index={props.instance.instance_id}
|
||||
qubits_needed={0}
|
||||
simProgress={JSON.stringify(
|
||||
props.instance.simulation_result?.simulation_result,
|
||||
)}
|
||||
/>
|
||||
)}
|
||||
</Card.Section>
|
||||
<Card.Section className="RightInstanceSection" inheritPadding px="sm">
|
||||
<div className="DatesContainer">
|
||||
<div className="dateContainer">
|
||||
<Text size="sm">Время начала:</Text>
|
||||
{props.instance.simulation_result ? (
|
||||
<>
|
||||
<Text size="sm">
|
||||
{new Date(
|
||||
props.instance.simulation_result?.started_at + "Z",
|
||||
).toLocaleDateString("ru")}{" "}
|
||||
</Text>
|
||||
<Text size="sm">
|
||||
{new Date(
|
||||
props.instance.simulation_result?.started_at + "Z",
|
||||
).toLocaleTimeString("ru")}
|
||||
</Text>
|
||||
</>
|
||||
) : (
|
||||
<Text size="sm">--</Text>
|
||||
)}
|
||||
</div>
|
||||
<div className="dateContainer">
|
||||
<Text size="sm">Время окончания:</Text>
|
||||
{props.instance.simulation_result?.ended_at ? (
|
||||
<>
|
||||
<Text size="sm">
|
||||
{new Date(
|
||||
props.instance.simulation_result?.ended_at + "Z",
|
||||
).toLocaleDateString("ru")}{" "}
|
||||
</Text>
|
||||
<Text size="sm">
|
||||
{new Date(
|
||||
props.instance.simulation_result?.ended_at + "Z",
|
||||
).toLocaleTimeString("ru")}
|
||||
</Text>
|
||||
</>
|
||||
) : (
|
||||
<Text size="sm">--</Text>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
justifyContent: "space-between",
|
||||
paddingLeft: "10px",
|
||||
}}
|
||||
>
|
||||
<UnstyledButton
|
||||
onClick={(e: MouseEvent) => {
|
||||
e.stopPropagation();
|
||||
handleDelete();
|
||||
}}
|
||||
style={{ cursor: "pointer" }}
|
||||
>
|
||||
<IconTrash size={20} />
|
||||
</UnstyledButton>
|
||||
|
||||
<Text c="dimmed" size="sm">
|
||||
#{props.instance.instance_id}
|
||||
</Text>
|
||||
</div>
|
||||
</Card.Section>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
|
||||
export default InstancesListCard;
|
||||
@@ -1,16 +1,26 @@
|
||||
import { Card, Text, UnstyledButton } from "@mantine/core";
|
||||
import { IconCancel, IconCheck, IconTrash } from "@tabler/icons-react";
|
||||
import type { MouseEvent } from "react";
|
||||
import { Card, NumberInput, Text, UnstyledButton } from "@mantine/core";
|
||||
import {
|
||||
IconCancel,
|
||||
IconCheck,
|
||||
IconPencil,
|
||||
IconTrash,
|
||||
} from "@tabler/icons-react";
|
||||
import { useState, type MouseEvent } from "react";
|
||||
import { notifications } from "@mantine/notifications";
|
||||
import type { SystemTeamData, SystemWithTeams } from "Types/Machine/Machine";
|
||||
import { removeSystemFromTeam } from "Api/QuantumBackend/MachineManagment";
|
||||
import {
|
||||
giveSystemToTeam,
|
||||
removeSystemFromTeam,
|
||||
} from "Api/QuantumBackend/MachineManagment";
|
||||
import { useDeviceStore } from "Stores/DeviceStore";
|
||||
|
||||
function TeamInMachineListCard(props: {
|
||||
team: SystemTeamData;
|
||||
system: SystemWithTeams;
|
||||
}) {
|
||||
const [isEditing, setIsEditing] = useState(false);
|
||||
const { updateDevice } = useDeviceStore();
|
||||
const [count, setCount] = useState(props.team.num_qubits);
|
||||
|
||||
const handleRemovePerm = () => {
|
||||
// TODO: fix delete
|
||||
@@ -76,7 +86,69 @@ function TeamInMachineListCard(props: {
|
||||
flexDirection: "row",
|
||||
}}
|
||||
>
|
||||
<Text>Количество кубит: {props.team.num_qubits}</Text>
|
||||
{isEditing && (
|
||||
<>
|
||||
<Text>Количество кубит: </Text>
|
||||
<NumberInput
|
||||
value={count}
|
||||
onChange={(ev) => {
|
||||
setCount(Number(ev.valueOf()));
|
||||
}}
|
||||
></NumberInput>
|
||||
<UnstyledButton
|
||||
onClick={() => {
|
||||
giveSystemToTeam({
|
||||
system_id: props.system.system.id,
|
||||
team_id: props.team.team.team_id,
|
||||
qubits_given: count,
|
||||
}).then(() => {
|
||||
const team = props.system.teams.find((t) => {
|
||||
return t.team.team_id == props.team.team.team_id;
|
||||
});
|
||||
if (team) {
|
||||
const updatedItem = { ...team, num_qubits: count };
|
||||
|
||||
// Create new array with the updated item in the same position
|
||||
const updatedItems = props.system.teams.map(
|
||||
(currentItem) =>
|
||||
currentItem.team.team_id === team.team.team_id
|
||||
? updatedItem
|
||||
: currentItem,
|
||||
);
|
||||
|
||||
updateDevice(props.system.system.id, {
|
||||
teams: updatedItems,
|
||||
});
|
||||
}
|
||||
|
||||
setIsEditing(false);
|
||||
});
|
||||
}}
|
||||
>
|
||||
<IconCheck size={25} />
|
||||
</UnstyledButton>
|
||||
<UnstyledButton
|
||||
onClick={() => {
|
||||
setCount(props.team.num_qubits);
|
||||
setIsEditing(false);
|
||||
}}
|
||||
>
|
||||
<IconCancel size={25} />
|
||||
</UnstyledButton>
|
||||
</>
|
||||
)}
|
||||
{!isEditing && (
|
||||
<>
|
||||
<Text>Количество кубит: {count}</Text>
|
||||
<UnstyledButton
|
||||
onClick={() => {
|
||||
setIsEditing(true);
|
||||
}}
|
||||
>
|
||||
<IconPencil size={25} />
|
||||
</UnstyledButton>
|
||||
</>
|
||||
)}
|
||||
</Card.Section>
|
||||
<Card.Section
|
||||
inheritPadding
|
||||
|
||||
@@ -8,6 +8,7 @@ import {
|
||||
UnstyledButton,
|
||||
} from "@mantine/core";
|
||||
import {
|
||||
IconCancel,
|
||||
IconCheck,
|
||||
IconCrown,
|
||||
IconForbid,
|
||||
@@ -196,23 +197,35 @@ function TeamMemberCard(props: { cur_team: Team; member: TeamMember }) {
|
||||
deleteMember({
|
||||
team_id: props.cur_team.id,
|
||||
user_id: props.member.user.keycloak_id,
|
||||
}).then(() => {
|
||||
notifications.show({
|
||||
radius: "md",
|
||||
title: "Пользователь удален успешно",
|
||||
message: "",
|
||||
icon: <IconCheck />,
|
||||
style: { paddingLeft: "5px" },
|
||||
})
|
||||
.then(() => {
|
||||
notifications.show({
|
||||
radius: "md",
|
||||
title: "Пользователь удален успешно",
|
||||
message: "",
|
||||
icon: <IconCheck />,
|
||||
style: { paddingLeft: "5px" },
|
||||
});
|
||||
updateTeam(props.cur_team.id, {
|
||||
members: [
|
||||
...props.cur_team.members.filter(
|
||||
(member) =>
|
||||
member.user.keycloak_id !=
|
||||
props.member.user.keycloak_id,
|
||||
),
|
||||
],
|
||||
});
|
||||
})
|
||||
.catch(() => {
|
||||
notifications.show({
|
||||
radius: "md",
|
||||
title: "Пользователя не получилось удалить",
|
||||
message: "",
|
||||
color: "red",
|
||||
icon: <IconCancel />,
|
||||
style: { paddingLeft: "5px" },
|
||||
});
|
||||
});
|
||||
updateTeam(props.cur_team.id, {
|
||||
members: [
|
||||
...props.cur_team.members.filter(
|
||||
(member) =>
|
||||
member.user.keycloak_id != props.member.user.keycloak_id,
|
||||
),
|
||||
],
|
||||
});
|
||||
});
|
||||
}}
|
||||
style={{
|
||||
cursor: "pointer",
|
||||
|
||||
Reference in New Issue
Block a user