This commit is contained in:
IDONTSUDO 2024-04-11 22:02:57 +03:00
parent c17515d571
commit 0c03906518
25 changed files with 475 additions and 201 deletions

31
.vscode/settings.json vendored
View file

@ -1,32 +1,3 @@
{
"files.exclude": {
"**/.git": false,
"**/.svn": false,
"**/.hg": false,
"**/CVS": false,
"**/__pycache__": false,
"*.DS_Store": false,
"*.DS_Store.*": false,
"*.git": false,
"*.git.*": false,
"*.vscode": false,
"*.vscode.*": false,
"*server.*": false,
"*ui": false,
"*ui.*": false
},
"cSpell.words": [
"запущен",
"процесс",
"antd",
"Collada",
"Contolls",
"fileupload",
"lerp",
"metadatas",
"Skils",
"undici",
"uuidv"
],
"editor.rulers": [100]
"cSpell.words": ["Ведите"]
}

2
p.ts
View file

@ -1,2 +0,0 @@
console.log([1, 2, 3, 4, 5, 6].reduce((element, acc) => (acc += element)));
console.log(["1", "2", "3", "4", "5", "6"].reduce((element, acc) => (acc += element)));

View file

@ -13,7 +13,6 @@ export class ReadingJsonFileAndConvertingToInstanceClassScenario<T> {
}
call = async (path: string): Promise<Result<string, T>> => {
try {
console.log(path);
const result = await new ReadFileAndParseJsonUseCase().call(path);
if (result.isFailure()) {
return result.forward();

View file

@ -8,7 +8,6 @@ export class CreateFolderUseCase {
}
call = async (path: string): Promise<Result<Error, string>> => {
try {
console.log(path);
if (await this.fileSystemRepository.dirIsExists(path)) {
return Result.ok("ok");
}

View file

@ -31,7 +31,6 @@ export class ExecProcessUseCase {
try {
executorProgramService.execPath = path;
executorProgramService.on((event) => {
console.log(event);
if (watcher) watcher.emit(event);
});
executorProgramService.call(EXEC_TYPE.EXEC, command);

View file

@ -1,6 +1,6 @@
import { CrudController } from "../../core/controllers/crud_controller";
import { IsHaveActiveProcessUseCase, KillLastProcessUseCase } from "../../core/usecases/exec_process_usecase";
import { CreateDataSetScenario } from "./domain/create_dataset_scanario";
import { CreateDataSetScenario } from "./domain/create_dataset_scenario";
import { ExecDatasetProcessScenario } from "./domain/exec_process_scenario";
import { GetDatasetActiveProjectScenario } from "./domain/get_dataset_active_project_scenario";
import { DatasetDBModel } from "./models/dataset_database_model";

View file

@ -4,11 +4,10 @@ import { Result } from "../../../core/helpers/result";
import { TypedEvent } from "../../../core/helpers/typed_event";
import { EXEC_EVENT, ExecError, SpawnError } from "../../../core/models/exec_error_model";
import { ExecutorResult } from "../../../core/models/executor_result";
import { ExecProcessUseCase } from "../../../core/usecases/exec_process_usecase";
import { SearchDataBaseModelUseCase } from "../../../core/usecases/search_database_model_usecase";
import { IProjectModel, ProjectDBModel } from "../../_projects/models/project_database_model";
import { DatasetDBModel } from "../models/dataset_database_model";
import { DatasetValidationModel } from "../models/dataset_validation_model";
import { DatasetValidationModel, ProcessStatus } from "../models/dataset_validation_model";
export class ProcessWatcherAndDatabaseUpdateService extends TypedEvent<Result<ExecError | SpawnError, ExecutorResult>> {
databaseId: ObjectId;
@ -25,7 +24,7 @@ export class ProcessWatcherAndDatabaseUpdateService extends TypedEvent<Result<Ex
const dbModel = await DatasetDBModel.findById(this.databaseId);
if (dbModel !== null) {
dbModel.local_path;
dbModel.processStatus = "end";
dbModel.processStatus = ProcessStatus.END;
dbModel.processLogs = success.data;
await dbModel.save();
}
@ -34,7 +33,7 @@ export class ProcessWatcherAndDatabaseUpdateService extends TypedEvent<Result<Ex
async (error) => {
const dbModel = await DatasetDBModel.findById(this.databaseId);
if (dbModel !== null) {
dbModel.processStatus = "error";
dbModel.processStatus = ProcessStatus.ERROR;
dbModel.processLogs = error.message;
await dbModel.save();
}
@ -48,7 +47,7 @@ export class CreateDataSetScenario extends CallbackStrategyWithValidationModel<D
return (
await new SearchDataBaseModelUseCase<IProjectModel>(ProjectDBModel).call({ isActive: true }, "no active projects")
).map(async (project) => {
model.processStatus = "new";
model.processStatus = ProcessStatus.NEW;
model.local_path = project.rootDir;
model.projectId = project._id;
const d = new DatasetDBModel();

View file

@ -5,7 +5,7 @@ import { ReadByIdDataBaseModelUseCase } from "../../../core/usecases/read_by_id_
import { MongoIdValidation } from "../../../core/validations/mongo_id_validation";
import { DatasetDBModel } from "../models/dataset_database_model";
import { IDatasetModel } from "../models/dataset_validation_model";
import { ProcessWatcherAndDatabaseUpdateService } from "./create_dataset_scanario";
import { ProcessWatcherAndDatabaseUpdateService } from "./create_dataset_scenario";
export class ExecDatasetProcessScenario extends CallbackStrategyWithIdQuery {
idValidationExpression = new MongoIdValidation();

View file

@ -10,14 +10,18 @@ export class FormBuilderValidationModel {
@IsArray()
public form: [];
}
export enum ProcessStatus {
END = "END",
ERROR = "ERROR",
NEW = "NEW",
}
export interface IDatasetModel {
name: string;
local_path: string;
dataSetObjects: string[];
formBuilder: FormBuilderValidationModel;
processLogs: string;
processStatus: string;
processStatus: ProcessStatus;
project?: IProjectModel;
}
@ -30,7 +34,7 @@ export class DatasetValidationModel implements IDatasetModel {
@Type(() => FormBuilderValidationModel)
public formBuilder: FormBuilderValidationModel;
public local_path: string;
public processStatus: string;
public processStatus: ProcessStatus;
public projectId: string;
public processLogs: string;
}

View file

@ -20,5 +20,10 @@
<style>
@import url('https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&display=swap')
</style>
<style>
[contenteditable]:focus {
outline: 0px solid transparent;
}
</style>
</html>

View file

@ -51,4 +51,10 @@ export const ArrayExtensions = () => {
return this.indexOf(element) !== -1;
};
}
if ([].repeat === undefined) {
// eslint-disable-next-line no-extend-native
Array.prototype.repeat = function (quantity) {
return Array(quantity).fill(this[0]);
};
}
};

View file

@ -19,6 +19,7 @@ declare global {
isEmpty(): boolean;
isNotEmpty(): boolean;
hasIncludeElement(element: T): boolean;
repeat(quantity: number): Array<T>;
}
interface Number {
fromArray(): number[];

View file

@ -1,9 +1,12 @@
import * as React from "react";
import { Input, Select, Button } from "antd";
import { InputBuilderViewModel, InputType } from "./form_view_model";
import { observer } from "mobx-react-lite";
import { FormBuilderStore } from "./form_builder_store";
import { FormBuilderValidationModel } from "../../../features/dataset/dataset_model";
import { SelectCore } from "../select/select";
import { CoreInput } from "../input/input";
import { Icon } from "../icons/icons";
import { CoreText, CoreTextType } from "../text/text";
export interface IFormBuilder {
context: string;
@ -28,107 +31,107 @@ export const FormBuilder = observer((props: IFormBuilder) => {
{store.formViewModel?.inputs.map((element) => {
if (element.type.isEqual(InputType.ENUM)) {
const values = element.values as string[];
console.log(element.totalValue);
return (
<>
<div>{element.name}</div>
<Select
defaultValue={element.defaultValue}
style={{ width: 120 }}
onChange={(e) => {
store.changeTotalValue(element.id, e);
}}
options={values?.map((el) => {
return { value: el };
})}
/>
</>
<SelectCore
items={values}
value={element.totalValue ?? element.defaultValue}
onChange={(value) => store.changeTotalValue(element.id, value)}
label={element.name}
style={{ margin: 10 }}
/>
);
}
if (element.type.isEqual(InputType.ARRAY)) {
return (
<div>
<div style={{ fontSize: "large" }}>{element.name}</div>
<div style={{ border: "1px black solid", margin: 10 }}>
<div
style={{
display: "flex",
justifyContent: "space-between",
margin: 10,
alignItems: "center",
paddingRight: 10,
}}
onClick={() => {
store.open(element.id);
}}
>
<CoreText text={element.name} type={CoreTextType.large} />
<Icon type="PlusCircle" style={{ width: 22 }} />
</div>
{element.isOpen ? (
<div>
<div style={{ margin: 10 }}>
{element.totalValue instanceof Array
? element.totalValue?.map((subArray, index) => {
return (
<>
<div style={{ paddingLeft: "10px" }}>
index: {index}
<Button onClick={() => store.deleteTotalValueSubItem(element.id, index)}>
Delete item
</Button>
<div style={{ margin: 10 }}>
<div style={{ display: "flex" }}>
<CoreText text={(element.subType ?? "") + ` ${index}`} type={CoreTextType.medium} />
<Icon
style={{ paddingLeft: 10 }}
type="DeleteCircle"
onClick={() => store.deleteTotalValueSubItem(element.id, index)}
/>
</div>
{subArray.map((subSubArrayItem: InputBuilderViewModel, subIndex: number) => {
if (subSubArrayItem.type.isEqual(InputType.ENUM)) {
return (
<>
<div>{subSubArrayItem.name}</div>
<Select
defaultValue={subSubArrayItem.defaultValue}
style={{ width: 120 }}
onChange={(e) => {
store.changeTotalSubValue(element.id, subIndex, e);
}}
options={subSubArrayItem.values?.map((el) => {
return { value: el };
})}
<SelectCore
items={subSubArrayItem.values?.map((el) => String(el)) ?? []}
value={subSubArrayItem.totalValue ?? subSubArrayItem.defaultValue}
onChange={(value) => store.changeTotalSubValue(element.id, subIndex, value)}
label={element.name}
style={{ margin: 5 }}
/>
</>
);
}
if (subSubArrayItem.type.isEqualMany([InputType.NUMBER, InputType.STRING]))
return (
<div style={{ width: "200px" }}>
<div>{subSubArrayItem.name}</div>
<Input
<div>
<CoreInput
style={{ margin: 5 }}
onChange={(e) => {
store.changeTotalSubValue(element.id, subIndex, e.target.value);
store.changeTotalSubValue(element.id, subIndex, e);
}}
defaultValue={subSubArrayItem.defaultValue}
value={subSubArrayItem.defaultValue}
label={subSubArrayItem.name}
/>
</div>
);
return <>Error</>;
})}
</>
</div>
);
})
: null}
</div>
) : null}
<div
onClick={() => {
store.open(element.id);
}}
>
+
</div>
</div>
);
}
if (element.type.isEqualMany([InputType.NUMBER, InputType.STRING]))
return (
<div style={{ width: "200px" }}>
<div>{element.name}</div>
<Input
<div>
<CoreInput
onChange={(e) => {
store.changeTotalValue(element.id, e.target.value);
store.changeTotalValue(element.id, e);
}}
defaultValue={element.defaultValue}
value={element.defaultValue}
label={element.name}
style={{ margin: 10 }}
/>
</div>
);
return <>Error</>;
})}
<Button onClick={() => store.saveForm()}>SAVE FORM</Button>
</div>
)}
</div>

View file

@ -4,16 +4,31 @@ import { Result } from "../../helper/result";
export interface IIconsProps {
type: string;
style?: React.CSSProperties;
onClick?: Function;
}
export function Icon(props: IIconsProps) {
const icon = getIconSvg(props.type);
return icon.fold(
(node) => {
return <div style={props.style}>{node}</div>;
return (
<div
onClick={() => {
if (props.onClick) props.onClick();
}}
style={props.style}
>
{node}
</div>
);
},
() => (
<div style={props.style}>
<div
onClick={() => {
if (props.onClick) props.onClick();
}}
style={props.style}
>
<svg width="12" height="12" viewBox="0 0 12 12" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
fill-rule="evenodd"
@ -28,6 +43,23 @@ export function Icon(props: IIconsProps) {
}
const getIconSvg = (type: string): Result<undefined, React.JSX.Element> => {
switch (type) {
case "DeleteCircle":
return Result.ok(
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M10 0C4.47 0 0 4.47 0 10C0 15.53 4.47 20 10 20C15.53 20 20 15.53 20 10C20 4.47 15.53 0 10 0ZM10 18C5.59 18 2 14.41 2 10C2 5.59 5.59 2 10 2C14.41 2 18 5.59 18 10C18 14.41 14.41 18 10 18ZM10 8.59L13.59 5L15 6.41L11.41 10L15 13.59L13.59 15L10 11.41L6.41 15L5 13.59L8.59 10L5 6.41L6.41 5L10 8.59Z"
fill="#49454F"
/>
</svg>
);
case "Check":
return Result.ok(
<svg width="12" height="10" viewBox="0 0 12 10" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M4 9.4L0 5.4L1.4 4L4 6.6L10.6 0L12 1.4L4 9.4Z" fill="white" />
</svg>
);
case "PlusCircle":
return Result.ok(
<svg width="33" height="33" viewBox="0 0 33 33" fill="none" xmlns="http://www.w3.org/2000/svg">

View file

@ -0,0 +1,38 @@
import { CoreText, CoreTextType } from "../text/text";
interface IInputProps {
label: string;
value?: string;
onChange?: (value: string) => void;
style?: React.CSSProperties;
}
export const CoreInput = (props: IInputProps) => {
return (
<div
style={Object.assign(
{
backgroundColor: "rgba(230, 224, 233, 1)",
height: 58,
borderRadius: " 4px 4px 0px 0px",
borderBottom: "solid 1px black",
padding: "10px 10px 10px 10px",
},
props.style
)}
>
<CoreText type={CoreTextType.small} text={props.label} />
<div
onChange={(event) => {
console.log(event);
}}
onInput={(e) => {
if (props.onChange && e.currentTarget.textContent) props.onChange(e.currentTarget.textContent);
}}
style={{ fontSize: 16, fontFamily: "Roboto", color: "#1D1B20", height: 24 }}
contentEditable="true"
/>
</div>
);
};

View file

@ -0,0 +1,67 @@
import React from "react";
import { CoreText, CoreTextType } from "../text/text";
interface ISelectCoreProps {
items: string[];
value: string;
label: string;
onChange: (value: string) => void;
style?: React.CSSProperties;
}
export const SelectCore = (props: ISelectCoreProps) => {
const ref = React.useRef<HTMLDivElement>(null);
const [cursorIsCorses, setCursorIsCorses] = React.useState(false);
const [value, setValue] = React.useState(props.value);
React.useEffect(() => {
ref.current?.addEventListener("mousemove", () => {
setCursorIsCorses(true);
});
ref.current?.addEventListener("mouseleave", () => {
setCursorIsCorses(false);
});
}, [ref, setCursorIsCorses]);
return (
<div ref={ref} style={props.style}>
<div
style={{
backgroundColor: "rgba(230, 224, 233, 1)",
height: 58,
borderRadius: "4px 4px 0px 0px",
borderBottom: "solid 1px black",
padding: "10px 10px 10px 10px",
}}
>
<CoreText type={CoreTextType.small} text={props.label} />
<div style={{ fontSize: 16, fontFamily: "Roboto", color: "#1D1B20", height: 24 }}>{value}</div>
</div>
<div
style={{
backgroundColor: "rgba(243, 237, 247, 1)",
boxShadow: "0px 1px 2px rgba(0, 0, 0, 0.3), 0px 2px 6px 2px rgba(0, 0, 0, 0.15)",
borderRadius: 4,
}}
>
{cursorIsCorses
? props.items.map((el) => (
<div
onClick={() => {
setValue(el);
props.onChange(el);
}}
style={{
height: 48,
textAlign: "center",
alignContent: "center",
cursor: "pointer",
borderBottom: "1px solid",
}}
>
{el}
</div>
))
: null}
</div>
</div>
);
};

View file

@ -0,0 +1,19 @@
import { Icon } from "../icons/icons";
interface ISwitchProps {
isSelected: boolean;
id: string;
onChange: (status: boolean, id: string) => void;
}
export const CoreSwitch = (props: ISwitchProps) => {
return (
<div
style={{ height: 40, width: 40, borderRadius: 2, alignContent: "center", cursor: "pointer" }}
onClick={() => props.onChange(props.isSelected, props.id)}
>
<div style={{ backgroundColor: "rgba(104, 80, 164, 1)", width: 20, height: 20, textAlign: "center" }}>
{props.isSelected ? <Icon type={"Check"} /> : null}
</div>
</div>
);
};

View file

@ -4,6 +4,7 @@ export enum CoreTextType {
header,
medium,
large,
small,
}
export interface ITextProps {
@ -13,6 +14,22 @@ export interface ITextProps {
}
export function CoreText(props: ITextProps) {
if (props.type === CoreTextType.small) {
return (
<div
style={{
color: props.color ?? "rgba(73, 69, 79, 1)",
fontSize: 12,
fontFamily: "Roboto",
fontWeight: 400,
fontSizeAdjust: 14,
textOverflow: "ellipsis",
}}
>
{props.text}
</div>
);
}
if (props.type === CoreTextType.large) {
return (
<div

View file

@ -34,8 +34,6 @@ export function BehaviorTreeBuilderScreen() {
React.useEffect(() => {
store.init();
// @ts-expect-error
console.log(ref.current.clientHeight);
store.dragZoneSetOffset(
// @ts-expect-error

View file

@ -1,9 +1,17 @@
import { Spin } from "antd";
import { LoadingOutlined } from "@ant-design/icons";
import poseIMG from "../../assets/images/pose_estemation.jpg";
import { Icon } from "../icons/icons";
import { CoreText, CoreTextType } from "../text/text";
import { CoreButton } from "../button/button";
import poseIMG from "../../core/assets/images/pose_estemation.jpg";
import { Icon } from "../../core/ui/icons/icons";
import { CoreText, CoreTextType } from "../../core/ui/text/text";
import { CoreButton } from "../../core/ui/button/button";
import type { MenuProps } from "antd";
import { Dropdown } from "antd";
import { ProcessStatus } from "./dataset_model";
interface IMenuItem {
onClick: Function;
name: string;
}
export const enum CardDataSetType {
EMPTY = "EMPTY",
@ -19,10 +27,22 @@ interface ICardDataSetProps {
processStatus?: string;
onClickButton?: (id: string) => void;
onClickEmptyCard?: Function;
onEdit?: Function;
onDelete?: Function;
id?: string;
}
export const CardDataSet = (props: ICardDataSetProps) => {
const menu: IMenuItem[] = [
{ onClick: () => props.onEdit?.call(props.id), name: "Редактировать" },
{ onClick: () => props.onDelete?.call(props.id), name: "Удалить" },
];
const items: MenuProps["items"] = menu.map((el, index) => {
return {
key: String(index),
label: <CoreText text={el.name} type={CoreTextType.medium} />,
};
});
return (
<div
style={{
@ -48,7 +68,11 @@ export const CardDataSet = (props: ICardDataSetProps) => {
<CoreText text={props.neuralNetworkAction ?? ""} type={CoreTextType.medium} />
</div>
<div>
<Icon type="Settings" />
<Dropdown overlayStyle={{ backgroundColor: "rgba(243, 237, 247, 1)" }} menu={{ items }}>
<div>
<Icon type="Settings" />
</div>
</Dropdown>
</div>
</div>
)}
@ -75,7 +99,7 @@ export const CardDataSet = (props: ICardDataSetProps) => {
<Spin indicator={<LoadingOutlined style={{ fontSize: 34, color: "rgba(103, 80, 164, 1)" }} spin />} />
) : null}
<div style={{ width: 20 }} />
{props.processStatus === "new" ? (
{props.processStatus === ProcessStatus.NEW ? (
<CoreButton
onClick={() => {
if (props.type.isEqual(CardDataSetType.COMPLETED) && props.onClickButton && props.id) {
@ -85,9 +109,19 @@ export const CardDataSet = (props: ICardDataSetProps) => {
filled={true}
text="Старт"
/>
) : (
<CoreButton text="Завершено" block={true} />
)}
) : null}
{props.processStatus === ProcessStatus.ERROR ? (
<CoreButton
onClick={() => {
if (props.type.isEqual(CardDataSetType.COMPLETED) && props.onClickButton && props.id) {
props.onClickButton(props.id);
}
}}
filled={true}
text="Ошибка"
/>
) : null}
</div>
</div>
)}

View file

@ -1,11 +1,16 @@
import { InputBuilderViewModel } from "../../core/ui/form_builder/form_view_model";
import { Result } from "../../core/helper/result";
import makeAutoObservable from "mobx-store-inheritance";
export enum ProcessStatus {
END = "END",
ERROR = "ERROR",
NEW = "NEW",
}
export interface IDatasetModel {
_id: string;
dataSetObjects: string[];
processStatus: string;
processStatus: ProcessStatus;
projectId: string;
name: string;
formBuilder: FormBuilder;
@ -77,13 +82,13 @@ export class DataSetModel {
return Result.error("project is unknow");
}
if (this.dataSetObjects.isEmpty()) {
return Result.error("not selected details");
return Result.error("Не выделены детали");
}
if (this.datasetType.isEmpty()) {
return Result.error("dataset type is empty");
return Result.error("Навык датасета не выбран");
}
if (this.name.isEmpty()) {
return Result.error("dataset name is empty");
return Result.error("ВВедите имя датасета");
}
return Result.ok();
}
@ -93,8 +98,6 @@ export const datasetTypes = ["Object Detection - YOLOv8", "Pose Estimation - DOP
export const datasetFormMockResult = `{
"typedataset": \${typedataset:Enum<T>:ObjectDetection},
"dataset_path": \${ПУТЬ ДАТАСЕТА:string:none},
"models":\${models:Array<MODELS>:[]},
"models_randomization":{
"loc_range_low": [\${LOC_RANGE_LOW_1:number:-1}, \${LOC_RANGE_LOW_2:number:-1},/\${LOC_RANGE_LOW_3:number:0}],
"loc_range_high": [\${LOC_RANGE_HIGH_1:number:1}, \${LOC_RANGE_HIGH_2:number:1},/\${LOC_RANGE_HIGH_3:number:2}]
@ -123,12 +126,7 @@ ENUM T = "ObjectDetection","PoseEstimation";
ENUM L = "POINT","SUN";
ENUM F = "JPEG","PNG";
ENUM COLLISION_SHAPE = "SHAPE","COLLISION";
type MODELS = {
"id": \${ID:number:1},
"name": \${NAME:string:none},
"model": \${MODEL:string:models/1.fbx}
};
type OBJECTS_SCENE = {
"name": \${NAME:string:default},
"collision_shape": \${collision_shape:Enum<COLLISION_SHAPE>:BOX},

View file

@ -1,11 +1,15 @@
import * as React from "react";
import { Drawer, Button, Radio, Card, Checkbox, Input } from "antd";
import { Drawer } from "antd";
import { FormBuilder } from "../../core/ui/form_builder/form_builder";
import { DataSetStore } from "./dataset_store";
import { DataSetStore, DrawersDataset } from "./dataset_store";
import { observer } from "mobx-react-lite";
import { datasetTypes } from "./dataset_model";
import { MainPage } from "../../core/ui/pages/main_page";
import { CardDataSet, CardDataSetType } from "../../core/ui/card/card_dataset";
import { CardDataSet, CardDataSetType } from "./card_dataset";
import { CoreInput } from "../../core/ui/input/input";
import { CoreButton } from "../../core/ui/button/button";
import { ListItem } from "./list_item";
import { datasetTypes } from "./dataset_model";
import { CoreText, CoreTextType } from "../../core/ui/text/text";
export const DatasetsScreenPath = "/dataset";
@ -15,9 +19,6 @@ export const DataSetScreen: React.FunctionComponent = observer(() => {
React.useEffect(() => {
store.init();
}, [store]);
const [open, setOpen] = React.useState(false);
const [open1, setOpen1] = React.useState(false);
return (
<>
<MainPage
@ -36,7 +37,6 @@ export const DataSetScreen: React.FunctionComponent = observer(() => {
}}
>
{store.datasets?.map((el) => {
console.log(el);
return (
<CardDataSet
type={CardDataSetType.COMPLETED}
@ -46,18 +46,23 @@ export const DataSetScreen: React.FunctionComponent = observer(() => {
neuralNetworkAction={el.datasetType.split(" - ").at(0)}
neuralNetworkName={el.datasetType.split(" - ").at(1)}
id={el._id}
onClickButton={(id) => store.runProcess(id)}
onClickButton={(id: string) => store.runProcess(id)}
onDelete={(id: string) => store.deleteDataset(id)}
onEdit={(id: string) => store.editDataset(id)}
/>
);
})}
<CardDataSet
type={CardDataSetType.EMPTY}
onClickEmptyCard={() => {
setOpen(true);
store.editDrawer(DrawersDataset.NewDataset, true);
}}
/>
<Drawer title="Form builder Drawer" onClose={() => setOpen1(false)} open={open1}>
<Drawer
title={DrawersDataset.FormBuilderDrawer}
onClose={() => store.editDrawer(DrawersDataset.FormBuilderDrawer, false)}
open={store.drawers.find((el) => el.name === DrawersDataset.FormBuilderDrawer)?.status ?? false}
>
<FormBuilder
context={store.dataSetModel.formBuilder.context}
result={store.dataSetModel.formBuilder.result}
@ -65,42 +70,69 @@ export const DataSetScreen: React.FunctionComponent = observer(() => {
if (el) store.dataSetModel.formBuilder = el;
}}
/>
<div style={{ display: "flex" }}>
<CoreButton text="Сохранить" filled={true} />
<div style={{ width: 10 }} />
<CoreButton text="Отмена" onClick={() => store.editDrawer(DrawersDataset.FormBuilderDrawer, false)} />
</div>
</Drawer>
<Drawer title="New Dataset" onClose={() => setOpen(false)} open={open}>
<Input placeholder="Dataset name" onChange={(e) => (store.dataSetModel.name = e.target.value)} />
<Button onClick={() => setOpen1(true)}>edit dataset settings</Button>
<Button onClick={() => store.saveDataset()}>save dataset</Button>
<Radio.Group
value={store.dataSetModel.datasetType}
onChange={(e) => {
store.dataSetModel.datasetType = e.target.value;
}}
<Drawer
title={DrawersDataset.NewDataset}
onClose={() => store.editDrawer(DrawersDataset.NewDataset, false)}
open={store.drawers.find((el) => el.name === DrawersDataset.NewDataset)?.status}
>
<div
style={{ display: "flex", flexDirection: "column", justifyContent: "space-between", height: "100%" }}
>
{datasetTypes.map((el) => (
<>
<Radio.Button value={el}>{el}</Radio.Button>
</>
))}
</Radio.Group>
<div>
<CoreInput label={"Имя датасета"} onChange={(e) => store.setNewDatasetName(e)} />
<div>
<CoreText type={CoreTextType.header} text="Тип навыка" />
{datasetTypes.map((el) => {
return (
<div
onClick={() => store.setSkillSelected(el)}
style={{
backgroundColor: store.skillIsSelected(el) ? "rgb(103 80 164)" : "rgba(254, 247, 255, 1)",
borderRadius: 25,
color: store.skillIsSelected(el) ? "white" : "",
margin: 10,
padding: 10,
cursor: "pointer",
}}
>
{el}
</div>
);
})}
</div>
<div style={{ width: 180, marginTop: 10, marginBottom: 30 }}>
<CoreButton
onClick={() => store.editDrawer(DrawersDataset.FormBuilderDrawer, true)}
text="Настройки датасета"
filled={true}
/>
</div>
{store.assets?.assets?.map((el) => {
return (
<ListItem
status={store.assetStatus(el.name)}
name={el.name}
imgURL={el.image}
onChange={() => {
store.datasetCheckBox(el);
}}
/>
);
})}
</div>
{store.assets?.assets.map((el) => {
return (
<>
<Checkbox
onChange={() => {
store.dataSetModel.dataSetObjects.push(el.name);
}}
defaultChecked={store.dataSetModel.dataSetObjects.includes(el.name)}
>
include?
</Checkbox>
<Card title={el.name} style={{ width: 300 }}>
<img src={el.image} alt="error" />
</Card>
</>
);
})}
<div style={{ display: "flex" }}>
<CoreButton text="Сохранить" filled={true} onClick={() => store.saveDataset()} />
<div style={{ width: 10 }} />
<CoreButton text="Отмена" onClick={() => store.editDrawer(DrawersDataset.NewDataset, false)} />
</div>
</div>
</Drawer>
</div>
}
@ -108,31 +140,3 @@ export const DataSetScreen: React.FunctionComponent = observer(() => {
</>
);
});
{
/* <Button onClick={() => setOpen(true)}>new dataset</Button>
{store.datasets?.isEmpty() ? (
<div>empty dataset</div>
) : (
<div>
<h1>Datasets</h1>
<div>
{store.datasets?.map((el, index) => {
return (
<Card title={el.name}>
<h2>dataset objects:</h2>
<div>
{el.dataSetObjects.map((el) => (
<div>{el}</div>
))}
</div>
<h2>process status</h2>
<div>{el.processStatus}</div>
<Button>Edit process</Button>
</Card>
);
})}
</div>
</div>
)}
</> */
}

View file

@ -2,28 +2,80 @@ import makeAutoObservable from "mobx-store-inheritance";
import { DataSetRepository } from "./dataset_repository";
import { UiErrorState } from "../../core/store/base_store";
import { HttpError } from "../../core/repository/http_repository";
import { Assets, DataSetModel, IDatasetModel } from "./dataset_model";
import { Asset, Assets, DataSetModel, IDatasetModel } from "./dataset_model";
import { message } from "antd";
import { UUID } from "../all_projects/data/project_repository";
export enum DrawersDataset {
NewDataset = "Новый датасет",
FormBuilderDrawer = "Редактировать датасет",
}
export interface Drawer {
name: string;
status: boolean;
}
export class DataSetStore extends UiErrorState<HttpError> {
dataSetRepository: DataSetRepository;
assets?: Assets;
datasets?: IDatasetModel[];
activeProject: UUID;
dataSetModel = DataSetModel.empty();
drawers: Drawer[];
constructor() {
super();
this.dataSetRepository = new DataSetRepository();
this.drawers = Object.entries(DrawersDataset).map((k, v) => {
return {
name: k.at(1) ?? "",
status: false,
};
});
makeAutoObservable(this);
}
setNewDatasetName(e: string): void {
this.dataSetModel.name = e;
}
setSkillSelected(el: string): void {
this.dataSetModel.datasetType = el;
}
skillIsSelected(el: string): boolean {
return el === this.dataSetModel.datasetType;
}
assetStatus(name: string): boolean {
return this.dataSetModel.dataSetObjects.includes(name);
}
datasetCheckBox(asset: Asset): void {
if (this.assetStatus(asset.name)) {
this.dataSetModel.dataSetObjects = this.dataSetModel.dataSetObjects.filter((el) => !el.isEqual(asset.name));
} else {
this.dataSetModel.dataSetObjects.push(asset.name);
}
}
editDrawer(drawerName: DrawersDataset, status: boolean): void {
this.drawers = this.drawers.map((el) => {
if (el.name === drawerName) {
el.status = status;
}
return el;
});
}
editDataset(id: string) {}
deleteDataset(id: string) {}
runProcess = async (id: string): Promise<void> => {
(await this.dataSetRepository.isRunningProcess()).fold(
async (s) => {
(await this.dataSetRepository.execDatasetProcess(id)).fold(
() => {
message.success("процесс запущен");
message.success("Процесс запущен");
},
(e) => message.error(e.message)
);
@ -41,7 +93,7 @@ export class DataSetStore extends UiErrorState<HttpError> {
async () => {
(await this.dataSetRepository.saveDataSet(this.dataSetModel)).fold(
() => {
message.success("датасет сохранен");
message.success("Датасет сохранен");
},
(error) => message.error(error.message)
);

View file

@ -0,0 +1,31 @@
import { CoreSwitch } from "../../core/ui/switch/switch";
import { CoreText, CoreTextType } from "../../core/ui/text/text";
export interface IListItemProps {
name: string;
imgURL: string;
status: boolean;
onChange: (status: boolean, id: string) => void;
}
export const ListItem = (props: IListItemProps) => {
return (
<div
style={{
backgroundColor: "rgba(254, 247, 255, 1)",
border: "1px #6750a4 solid",
width: "100%",
height: 110,
display: "flex",
justifyContent: "space-between",
alignItems: "center",
borderRadius: 12,
marginTop: 10,
marginBottom: 10,
}}
>
<img style={{ height: 50, margin: 10 }} src={props.imgURL} alt="" />
<CoreText text={props.name} type={CoreTextType.large} />
<CoreSwitch isSelected={props.status} id={props.name} onChange={props.onChange} />
</div>
);
};

View file

@ -2,7 +2,7 @@ import * as React from "react";
import { PipelineInstanceStore } from "./pipeline_instance_store";
import { useNavigate } from "react-router-dom";
import { Icon } from "../../core/ui/icons/icons";
import { CardDataSet, CardDataSetType } from "../../core/ui/card/card_dataset";
import { CardDataSet, CardDataSetType } from "../dataset/card_dataset";
import { MainPage } from "../../core/ui/pages/main_page";
export const PipelineInstanceScreenPath = "/pipeline_instance/";