From d41310196f51a360cae064f7e9283879f8c5d041 Mon Sep 17 00:00:00 2001 From: IDONTSUDO Date: Fri, 26 Jul 2024 18:50:36 +0300 Subject: [PATCH] progress machine learning screen --- ui/src/core/model/validation_model.ts | 22 +++ ui/src/core/routers/routers.tsx | 6 +- ui/src/core/ui/form_builder/form_builder.tsx | 23 +++- .../ui/form_builder/form_builder_store.ts | 8 +- .../core/ui/form_builder/form_view_model.ts | 99 +++++++++----- .../forms/form_builder_components.tsx | 20 +++ .../forms/select_scene/select_scene.tsx | 22 +++ ui/src/core/ui/input/input.tsx | 4 +- ui/src/core/ui/pages/main_page.tsx | 2 +- ui/src/core/ui/select/select.tsx | 47 ++++--- .../behavior_tree_builder_store.tsx | 2 +- .../ui/forms/weights_form/weights_store.ts | 2 +- ui/src/features/dataset/dataset_model.ts | 23 +++- .../machine_learning_http_repository.tsx} | 10 +- .../machine_learning_socket_repository.ts} | 6 +- .../model/model_machine_learning_process.ts | 87 ++++++++++++ .../presentation/machine_learning_screen.tsx} | 128 +++++++++--------- .../presentation/machine_learning_store.tsx} | 67 +++++---- .../presentation/ui/cards/get_model_card.tsx | 4 + .../cards/pose_estimate_card/model_card.tsx} | 14 +- .../presentation/forms/camera/camera_form.tsx | 2 +- .../presentation/scene_manager_store.ts | 5 +- ui/src/features/skils/skill_model.ts | 55 -------- ui/src/index.tsx | 1 + 24 files changed, 428 insertions(+), 231 deletions(-) create mode 100644 ui/src/core/model/validation_model.ts create mode 100644 ui/src/core/ui/form_builder/forms/form_builder_components.tsx create mode 100644 ui/src/core/ui/form_builder/forms/select_scene/select_scene.tsx rename ui/src/features/{skils/skills_http_repository.tsx => machine_learning/data/machine_learning_http_repository.tsx} (79%) rename ui/src/features/{skils/skill_socket_repository.ts => machine_learning/data/machine_learning_socket_repository.ts} (78%) create mode 100644 ui/src/features/machine_learning/model/model_machine_learning_process.ts rename ui/src/features/{skils/skills_screen.tsx => machine_learning/presentation/machine_learning_screen.tsx} (54%) rename ui/src/features/{skils/skills_store.tsx => machine_learning/presentation/machine_learning_store.tsx} (61%) create mode 100644 ui/src/features/machine_learning/presentation/ui/cards/get_model_card.tsx rename ui/src/features/{skils/skill_card.tsx => machine_learning/presentation/ui/cards/pose_estimate_card/model_card.tsx} (92%) delete mode 100644 ui/src/features/skils/skill_model.ts diff --git a/ui/src/core/model/validation_model.ts b/ui/src/core/model/validation_model.ts new file mode 100644 index 0000000..c97c9e2 --- /dev/null +++ b/ui/src/core/model/validation_model.ts @@ -0,0 +1,22 @@ +import { Result } from "../helper/result"; +import { validate, ValidationError } from "class-validator"; + +export class ValidationModel { + valid = async (): Promise> => { + const errors: ValidationError[] = await validate(this, { + skipMissingProperties: false, + whitelist: false, + forbidNonWhitelisted: true, + }); + + if (errors.isNotEmpty()) { + const message = errors.map((error: ValidationError) => { + if (error.constraints) return Object.values(error.constraints).join(", "); + return ""; + }); + return Result.error(message.join(",")); + } else { + return Result.ok(this); + } + }; + } \ No newline at end of file diff --git a/ui/src/core/routers/routers.tsx b/ui/src/core/routers/routers.tsx index 286deba..0368949 100644 --- a/ui/src/core/routers/routers.tsx +++ b/ui/src/core/routers/routers.tsx @@ -10,7 +10,7 @@ import { DataSetScreen, DatasetsScreenPath } from "../../features/dataset/datase import { AssemblesScreen, AssemblesScreenPath } from "../../features/assembles/assembles_screen"; import { SimulationScreen, SimulationScreenPath } from "../../features/simulations/simulations_screen"; import { EstimateScreen, EstimateScreenPath } from "../../features/estimate/estimate_screen"; -import { SkillPath, SkillScreen } from "../../features/skils/skills_screen"; +import { MachineLearningPath, MachineLearningScreen } from "../../features/machine_learning/presentation/machine_learning_screen"; import { DetailsScreenPath, DetailsScreen } from "../../features/details/details_screen"; const idURL = ":id"; @@ -57,7 +57,7 @@ export const router = createBrowserRouter([ element: , }, { - path: SkillPath, - element: , + path: MachineLearningPath, + element: , }, ]); diff --git a/ui/src/core/ui/form_builder/form_builder.tsx b/ui/src/core/ui/form_builder/form_builder.tsx index 34dffb2..5955eb2 100644 --- a/ui/src/core/ui/form_builder/form_builder.tsx +++ b/ui/src/core/ui/form_builder/form_builder.tsx @@ -7,6 +7,7 @@ import { CoreSelect } from "../select/select"; import { CoreInput } from "../input/input"; import { Icon } from "../icons/icons"; import { CoreText, CoreTextType } from "../text/text"; +import { getFormBuilderComponents } from "./forms/form_builder_components"; export interface IFormBuilder { formBuilder: FormBuilderValidationModel; @@ -33,7 +34,7 @@ export const FormBuilder = observer((props: IFormBuilder) => { return (
- {store.isError ? ( + {store.isError ? ( <>Error ) : (
@@ -51,7 +52,6 @@ export const FormBuilder = observer((props: IFormBuilder) => { ); } if (element.type.isEqual(InputType.ARRAY)) { - return (
{ />
); + if (element.type.isEqual(InputType.OBJECT)) + return ( + <> + {getFormBuilderComponents( + element.name.replace(">", "").replace("<", "").replace("/", ""), + element.totalValue ?? element.defaultValue, + (text) => { + store.changeTotalValue(element.id, text); + } + ).fold( + (s) => ( + <>{s} + ), + (error) => ( + <>{error} + ) + )} + + ); return <>Error; })}
diff --git a/ui/src/core/ui/form_builder/form_builder_store.ts b/ui/src/core/ui/form_builder/form_builder_store.ts index cbf1157..997356e 100644 --- a/ui/src/core/ui/form_builder/form_builder_store.ts +++ b/ui/src/core/ui/form_builder/form_builder_store.ts @@ -44,13 +44,17 @@ export class FormBuilderStore { } } - changeTotalValue(id: string, value: string) { + changeTotalValue(id: string, value: any) { if (this.formViewModel?.inputs) this.formViewModel.inputs = this.formViewModel?.inputs.map((el) => { if (!el.id.isEqual(id)) { return el; } - el.totalValue = value; + if (value instanceof String) { + el.totalValue = value; + }else{ + el.totalValue = JSON.stringify(value) + } return el; }); this.changerForm.emit(this.formViewModel?.fromFormBuilderValidationModel()); diff --git a/ui/src/core/ui/form_builder/form_view_model.ts b/ui/src/core/ui/form_builder/form_view_model.ts index 581c14c..38b1e93 100644 --- a/ui/src/core/ui/form_builder/form_view_model.ts +++ b/ui/src/core/ui/form_builder/form_view_model.ts @@ -8,6 +8,7 @@ export enum InputType { STRING = "string", ARRAY = "Array", ENUM = "Enum", + OBJECT = "OBJECT", } interface IOperation { @@ -29,6 +30,11 @@ export class InputBuilderViewModel { ) { this.id = id ?? uuidv4(); } + isReactComponent = () => { + if (this.name.match(new RegExp(/<.*>/gm)) === null) { + throw new Error("Is dont react component" + this); + } + }; static fromJSON(json: any) { try { const value = JSON.parse(json); @@ -58,7 +64,8 @@ export class InputBuilderViewModel { } } -export const tagParse = new RegExp(/\${.*?}/gm); +export const tagParse = new RegExp(/\${.*?.*}/g); +export const objectParse = new RegExp(/OBJECT:.*}/gm); export const bracketParser = new RegExp(/<.*?>/gm); export const enumParser = new RegExp(/ENUM.*=..*?;/gm); export const enumBodyParse = new RegExp(/".*?;/gm); @@ -66,7 +73,8 @@ export const enumNameParse = new RegExp(/^(.*?)=/gm); export const typeBodyParse = new RegExp(/{.*?};/gms); export const typeNameParse = new RegExp(/type .*?{/gms); export const typeParse = new RegExp(/type.*?};/gms); - +export const objectParseObj = new RegExp(/{.*}/gm); +export const multiTagParse = new RegExp(/\${.*?}/g); export class FormViewModel { @observable inputs: InputBuilderViewModel[]; @@ -106,6 +114,9 @@ export class FormViewModel { if (element.type.isEqual(InputType.NUMBER)) { inputResult = Number(inputResult); } + if (element.type.isEqual(InputType.OBJECT)) { + inputResult = JSON.stringify(element.totalValue ?? element.defaultValue); + } if (element.type.isEqual(InputType.ARRAY)) { if (element.totalValue === undefined) { inputResult = "[]"; @@ -171,6 +182,9 @@ export class FormViewModel { } static fromString(result: string, context: string): Result { try { + if(result.isEmpty() && context.isEmpty()){ + return Result.error(undefined) + } const enums = new Map(); const types = new Map(); @@ -205,37 +219,60 @@ export class FormViewModel { return result .match(tagParse) ?.map((el) => { - const inputArray = el.replaceMany(["$", "{", "}"], "").split(":"); - if (el.includes(InputType.ENUM)) { - const enumName = inputArray.at(1)?.replaceMany([InputType.ENUM, "<", ">"], ""); - - if (enumName && enums.get(enumName)) { - return new InputBuilderViewModel(inputArray[0], InputType.ENUM, inputArray[2], enums.get(enumName)); - } + const multiTag = el.match(multiTagParse); + const result = []; + if (multiTag?.length !== 0 && multiTag?.length !== 1) { + multiTag?.forEach((element) => { + result.push(this.tagParse(element, enums, types)); + }); + } else { + result.push(this.tagParse(el, enums, types)); } - if (el.includes(InputType.ARRAY) && types) { - const name = inputArray.at(1)?.replaceMany(["Array<", ">"], ""); - - if (name) { - return new InputBuilderViewModel( - inputArray[0], - InputType.ARRAY, - inputArray[2], - types.get(name), - undefined, - false, - name - ); - } - } - if (el.includes(InputType.NUMBER)) { - return new InputBuilderViewModel(inputArray[0], InputType.NUMBER, inputArray[2]); - } - if (el.includes(InputType.STRING)) { - return new InputBuilderViewModel(inputArray[0], InputType.STRING, inputArray[2]); - } - return el; + return result; }) + .flat() .filter((el) => el !== undefined) as InputBuilderViewModel[]; } + public static tagParse = ( + el: string, + enums: Map, + types: Map | undefined = undefined + ) => { + const inputArray = el.replaceMany(["$", "{", "}"], "").split(":"); + if (el.includes(InputType.ENUM)) { + const enumName = inputArray.at(1)?.replaceMany([InputType.ENUM, "<", ">"], ""); + + if (enumName && enums.get(enumName)) { + return new InputBuilderViewModel(inputArray[0], InputType.ENUM, inputArray[2], enums.get(enumName)); + } + } + if (el.includes(InputType.ARRAY) && types) { + const name = inputArray.at(1)?.replaceMany(["Array<", ">"], ""); + + if (name) { + return new InputBuilderViewModel( + inputArray[0], + InputType.ARRAY, + inputArray[2], + types.get(name), + undefined, + false, + name + ); + } + } + if (el.includes(InputType.OBJECT)) { + const objectParseResult = el.match(objectParse)?.at(0); + const result = objectParseResult?.slice(objectParseResult?.indexOf(":") + 1, objectParseResult.length) as string; + + return new InputBuilderViewModel(inputArray[0], InputType.OBJECT, JSON.parse(result)); + } + if (el.includes(InputType.NUMBER)) { + return new InputBuilderViewModel(inputArray[0], InputType.NUMBER, inputArray[2]); + } + if (el.includes(InputType.STRING)) { + return new InputBuilderViewModel(inputArray[0], InputType.STRING, inputArray[2]); + } + return el; + }; } diff --git a/ui/src/core/ui/form_builder/forms/form_builder_components.tsx b/ui/src/core/ui/form_builder/forms/form_builder_components.tsx new file mode 100644 index 0000000..a4806bf --- /dev/null +++ b/ui/src/core/ui/form_builder/forms/form_builder_components.tsx @@ -0,0 +1,20 @@ +import { Result } from "../../../helper/result"; +import { SelectScene } from "./select_scene/select_scene"; + +export enum FormBuilderComponents { + SelectScene = "SelectScene", +} +export interface IFormBuilderComponentsProps { + dependency: T; + onChange: (obj: any) => void; +} +export const getFormBuilderComponents = ( + name: string, + dependency: any, + onChange: (text: string) => void +): Result => { + if (name.isEqual(FormBuilderComponents.SelectScene)) { + return Result.ok(); + } + return Result.error(name); +}; diff --git a/ui/src/core/ui/form_builder/forms/select_scene/select_scene.tsx b/ui/src/core/ui/form_builder/forms/select_scene/select_scene.tsx new file mode 100644 index 0000000..9b38354 --- /dev/null +++ b/ui/src/core/ui/form_builder/forms/select_scene/select_scene.tsx @@ -0,0 +1,22 @@ +import { CoreButton } from "../../../button/button"; +import { IFormBuilderComponentsProps } from "../form_builder_components"; +export class SceneSelectModel { + name: string; +} +export const SelectScene = (props: IFormBuilderComponentsProps) => { + return ( +
+ SELECT SCENE +
+ {JSON.stringify(props.dependency)} +
+ { + props.dependency.name = '15555' + props.onChange(JSON.stringify(props.dependency, () => {}, "")); + }} + /> +
+ ); +}; diff --git a/ui/src/core/ui/input/input.tsx b/ui/src/core/ui/input/input.tsx index 157ea7f..f1cb796 100644 --- a/ui/src/core/ui/input/input.tsx +++ b/ui/src/core/ui/input/input.tsx @@ -4,6 +4,7 @@ import { IStyle } from "../../model/style"; export enum CoreInputType { small = "small", default = "default", + big = 'big' } interface IInputProps extends IStyle { label: string; @@ -32,7 +33,7 @@ export const CoreInput = (props: IInputProps) => { { backgroundColor: "rgba(230, 224, 233, 1)", - height: isSmall ? 40 : 58, + height: isSmall ? 40 : 58, borderRadius: "4px 4px 0px 0px", borderBottom: "solid 1px black", padding: "10px 10px 10px 10px", @@ -44,6 +45,7 @@ export const CoreInput = (props: IInputProps) => { { const ref = React.useRef(null); const [cursorIsCorses, setCursorIsCorses] = React.useState(false); + const [width, setWidth] = React.useState(0); const [value, setValue] = React.useState(props.value); React.useEffect(() => { ref.current?.addEventListener("mousemove", () => { @@ -19,6 +20,8 @@ export const CoreSelect = (props: ICoreSelectProps) => { ref.current?.addEventListener("mouseleave", () => { setCursorIsCorses(false); }); + + setWidth(Number(ref.current?.clientWidth)); }, [ref, setCursorIsCorses]); return ( @@ -42,26 +45,30 @@ export const CoreSelect = (props: ICoreSelectProps) => { borderRadius: 4, }} > - {cursorIsCorses - ? props.items.map((el, i) => ( -
{ - setValue(el); - props.onChange(el); - }} - style={{ - height: 48, - textAlign: "center", - alignContent: "center", - cursor: "pointer", - borderBottom: "1px solid", - }} - > - {el} -
- )) - : null} +
+ {cursorIsCorses + ? props.items.map((el, i) => ( +
{ + setValue(el); + props.onChange(el); + }} + style={{ + backgroundColor: "rgba(230, 224, 233, 1)", + width: width, + height: 48, + textAlign: "center", + alignContent: "center", + cursor: "pointer", + borderBottom: "1px solid", + }} + > + {el} +
+ )) + : null} +
); diff --git a/ui/src/features/behavior_tree_builder/presentation/behavior_tree_builder_store.tsx b/ui/src/features/behavior_tree_builder/presentation/behavior_tree_builder_store.tsx index cd9e392..8e0e89d 100644 --- a/ui/src/features/behavior_tree_builder/presentation/behavior_tree_builder_store.tsx +++ b/ui/src/features/behavior_tree_builder/presentation/behavior_tree_builder_store.tsx @@ -171,7 +171,7 @@ export class BehaviorTreeBuilderStore extends UiDrawerFormState:ObjectDetection}, + "scene":\${:OBJECT:{"bricks":{"base_feature":{"path":"bricks/base_feature"},"form":{"path":"bricks/form"}}}, "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}] diff --git a/ui/src/features/skils/skills_http_repository.tsx b/ui/src/features/machine_learning/data/machine_learning_http_repository.tsx similarity index 79% rename from ui/src/features/skils/skills_http_repository.tsx rename to ui/src/features/machine_learning/data/machine_learning_http_repository.tsx index b05287b..aaf1ec8 100644 --- a/ui/src/features/skils/skills_http_repository.tsx +++ b/ui/src/features/machine_learning/data/machine_learning_http_repository.tsx @@ -1,7 +1,7 @@ -import { Result } from "../../core/helper/result"; -import { HttpError, HttpMethod, CoreHttpRepository } from "../../core/repository/http_repository"; -import { IDatasetModel } from "../dataset/dataset_model"; -import { SkillModel } from "./skill_model"; +import { Result } from "../../../core/helper/result"; +import { HttpError, HttpMethod, CoreHttpRepository } from "../../../core/repository/http_repository"; +import { IDatasetModel } from "../../dataset/dataset_model"; +import { Model } from "../model/model_machine_learning_process"; export interface ISkils { _id: string; @@ -29,7 +29,7 @@ export class SkillsHttpRepository extends CoreHttpRepository { return this._jsonRequest(HttpMethod.DELETE, `/weights?id=${id}`); }; - addNewSkill = async (model: SkillModel) => { + addNewSkill = async (model: Model) => { return this._jsonRequest(HttpMethod.POST, "/weights", model); }; getDatasetsActiveProject = async (): Promise> => { diff --git a/ui/src/features/skils/skill_socket_repository.ts b/ui/src/features/machine_learning/data/machine_learning_socket_repository.ts similarity index 78% rename from ui/src/features/skils/skill_socket_repository.ts rename to ui/src/features/machine_learning/data/machine_learning_socket_repository.ts index 9b2634d..cd7fd41 100644 --- a/ui/src/features/skils/skill_socket_repository.ts +++ b/ui/src/features/machine_learning/data/machine_learning_socket_repository.ts @@ -1,6 +1,6 @@ -import { TypedEvent } from "../../core/helper/typed_event"; -import { SocketRepository, socketRepository } from "../../core/repository/socket_repository"; -import { ProcessStatus } from "../dataset/dataset_model"; +import { TypedEvent } from "../../../core/helper/typed_event"; +import { SocketRepository, socketRepository } from "../../../core/repository/socket_repository"; +import { ProcessStatus } from "../../dataset/dataset_model"; export interface ProcessUpdate { id: string; diff --git a/ui/src/features/machine_learning/model/model_machine_learning_process.ts b/ui/src/features/machine_learning/model/model_machine_learning_process.ts new file mode 100644 index 0000000..e11aff2 --- /dev/null +++ b/ui/src/features/machine_learning/model/model_machine_learning_process.ts @@ -0,0 +1,87 @@ +import makeAutoObservable from "mobx-store-inheritance"; +import { Result } from "../../../core/helper/result"; +import { ISkils } from "../data/machine_learning_http_repository"; +import { FormBuilderValidationModel } from "../../dataset/dataset_model"; +import { IsString } from "class-validator"; +import { ValidationModel } from "../../../core/model/validation_model"; + +export enum ModelMachineLearningTypes { + OBJECT_DETECTION = "OBJECT_DETECTION", + POSE_ESTIMATE = "POSE_ESTIMATE", + ML = "ML", +} + +export class ModelMachineLearningProcess extends ValidationModel { + @IsString() + script: string; + formBuilder: FormBuilderValidationModel; + @IsString() + type: string; + @IsString() + name: string; + isEnd: boolean = false; + createDate: Date = new Date(); + card?: string; + lastProcessLogs?: string; + lastProcessExecCommand?: string; + lastExecDate?: Date; + constructor(script: string, formBuilderValidationModel: FormBuilderValidationModel, type: string, card: string) { + super(); + this.script = script; + this.formBuilder = formBuilderValidationModel; + this.type = type; + this.card = card; + } + static empty = () => new ModelMachineLearningProcess("", FormBuilderValidationModel.empty(), "", ""); +} +export class Model { + numberOfTrainedEpochs?: number; + id?: string; + isFinished?: boolean; + constructor( + public name: string, + public datasetId: string, + public project: string, + public epoch: number, + numberOfTrainedEpochs?: number, + id?: string, + isFinished?: boolean + ) { + this.numberOfTrainedEpochs = numberOfTrainedEpochs; + this.id = id; + this.isFinished = isFinished; + makeAutoObservable(this); + } + + static fromISkill(model: ISkils) { + return new Model( + model.name, + model.datasetId._id, + model.project._id, + model.epoch, + model.numberOfTrainedEpochs, + model._id, + model.isFinished + ); + } + + static empty() { + return new Model("", "", "", 0); + } + + valid(): Result { + if (this.name.isEmpty()) { + return Result.error("введите имя скила"); + } + if (this.datasetId.isEmpty()) { + return Result.error("datasetId is empty"); + } + if (this.project.isEmpty()) { + return Result.error("project is empty"); + } + if (this.epoch.isNegative()) { + return Result.error("эпоха не может принимать отрицательное число"); + } + return Result.ok(this); + } +} diff --git a/ui/src/features/skils/skills_screen.tsx b/ui/src/features/machine_learning/presentation/machine_learning_screen.tsx similarity index 54% rename from ui/src/features/skils/skills_screen.tsx rename to ui/src/features/machine_learning/presentation/machine_learning_screen.tsx index 9afc380..50705f3 100644 --- a/ui/src/features/skils/skills_screen.tsx +++ b/ui/src/features/machine_learning/presentation/machine_learning_screen.tsx @@ -1,13 +1,16 @@ import React from "react"; -import { Drawer } from "antd"; +import { Alert, Drawer, Modal } from "antd"; import { observer } from "mobx-react-lite"; -import { MainPage } from "../../core/ui/pages/main_page"; -import { CoreText, CoreTextType } from "../../core/ui/text/text"; -import { DrawersSkill, SkillStore } from "./skills_store"; -import { SkillCard } from "./skill_card"; -import { CoreInput } from "../../core/ui/input/input"; -import { CoreButton } from "../../core/ui/button/button"; -import { CoreSwitch } from "../../core/ui/switch/switch"; +import { MainPage } from "../../../core/ui/pages/main_page"; +import { CoreText, CoreTextType } from "../../../core/ui/text/text"; +import { DrawersSkill, MachineLearningStore } from "./machine_learning_store"; +import { ModelCard } from "./ui/cards/pose_estimate_card/model_card"; +import { CoreInput, CoreInputType } from "../../../core/ui/input/input"; +import { CoreButton } from "../../../core/ui/button/button"; +import { CoreSelect } from "../../../core/ui/select/select"; +import { ModelMachineLearningTypes } from "../model/model_machine_learning_process"; +import { CardModel } from "./ui/cards/get_model_card"; +import { FormBuilder } from "../../../core/ui/form_builder/form_builder"; interface IItem { name: string; @@ -16,10 +19,10 @@ interface IItem { const skills: IItem[] = [{ name: "ML", isActive: true }]; -export const SkillPath = "/skills"; +export const MachineLearningPath = "/models"; -export const SkillScreen = observer(() => { - const [store] = React.useState(() => new SkillStore()); +export const MachineLearningScreen = observer(() => { + const [store] = React.useState(() => new MachineLearningStore()); React.useEffect(() => { store.init(); @@ -48,7 +51,7 @@ export const SkillScreen = observer(() => { }} > {store.skils?.map((el) => ( - { onDelete={(id) => store.deleteSkill(id)} /> ))} - store.editDrawer(DrawersSkill.NEW_SKILL, true)} /> + store.editDrawer(DrawersSkill.NEW_SKILL, true)} /> } /> @@ -74,23 +77,6 @@ export const SkillScreen = observer(() => { open={store.drawers.find((el) => el.name === DrawersSkill.EDIT_SKILL)?.status} >
-
- Number().isValid(value)} - error="Должно быть введено число" - onChange={(text) => store.updateForm({ epoch: Number(text) })} - /> -
-
- store.updateForm({isFinished: !store.viewModel.isFinished})} - /> -
-
store.saveEdiSkill()} />
@@ -99,46 +85,49 @@ export const SkillScreen = observer(() => {
store.editDrawer(DrawersSkill.NEW_SKILL, false)} open={store.drawers.find((el) => el.name === DrawersSkill.NEW_SKILL)?.status} >
- store.updateForm({ name: text })} - /> - store.updateForm({ epoch: Number(e) })} - /> -
- {store.datasets?.map((el) => ( -
- {el.name} - store.updateForm({ datasetId: el._id })} - /> -
- ))} +
+ store.updateForm({ type: text })} + /> + store.updateForm({ card: text })} + /> + store.updateForm({ name: text })} /> + + { + store.viewModel.formBuilder.result = text; + }} + style={{ height: 200 }} + /> + { + store.viewModel.formBuilder.context = text; + }} + style={{ height: 200 }} + /> + { + store.isModalOpen = true; + }} + />
-
store.saveSkill()} />
@@ -146,6 +135,19 @@ export const SkillScreen = observer(() => {
+ { + store.isModalOpen = false; + }} + > + {}} /> + + ); }); diff --git a/ui/src/features/skils/skills_store.tsx b/ui/src/features/machine_learning/presentation/machine_learning_store.tsx similarity index 61% rename from ui/src/features/skils/skills_store.tsx rename to ui/src/features/machine_learning/presentation/machine_learning_store.tsx index 30b1280..ba5db5f 100644 --- a/ui/src/features/skils/skills_store.tsx +++ b/ui/src/features/machine_learning/presentation/machine_learning_store.tsx @@ -1,29 +1,29 @@ import makeAutoObservable from "mobx-store-inheritance"; import { NavigateFunction } from "react-router-dom"; -import { HttpError } from "../../core/repository/http_repository"; -import { Drawer, UiDrawerFormState } from "../../core/store/base_store"; -import { ISkils, SkillsHttpRepository } from "./skills_http_repository"; -import { IDatasetModel } from "../dataset/dataset_model"; +import { HttpError } from "../../../core/repository/http_repository"; +import { Drawer, UiDrawerFormState } from "../../../core/store/base_store"; +import { ISkils, SkillsHttpRepository } from "../data/machine_learning_http_repository"; +import { IDatasetModel } from "../../dataset/dataset_model"; import { message } from "antd"; -import { UUID } from "../all_projects/data/project_http_repository"; -import { SkillModel } from "./skill_model"; -import { ProcessUpdate, SkillSocketRepository } from "./skill_socket_repository"; +import { UUID } from "../../all_projects/data/project_http_repository"; +import { Model, ModelMachineLearningProcess } from "../model/model_machine_learning_process"; +import { ProcessUpdate, SkillSocketRepository } from "../data/machine_learning_socket_repository"; export enum DrawersSkill { NEW_SKILL = "Новый навык", EDIT_SKILL = "Редактировать навык", } -export class SkillStore extends UiDrawerFormState { +export class MachineLearningStore extends UiDrawerFormState { skillsHttpRepository: SkillsHttpRepository; skillSocketRepository: SkillSocketRepository = new SkillSocketRepository(); skils?: ISkils[]; datasets?: IDatasetModel[]; activeProjectId?: UUID; - viewModel: SkillModel; + viewModel: ModelMachineLearningProcess; titleDrawer: string = DrawersSkill.NEW_SKILL; drawers: Drawer[]; - + isModalOpen:boolean = false; constructor() { super({}); this.drawers = Object.entries(DrawersSkill).map((k, v) => { @@ -32,7 +32,7 @@ export class SkillStore extends UiDrawerFormState { status: false, }; }); - this.viewModel = SkillModel.empty(); + this.viewModel = ModelMachineLearningProcess.empty(); this.skillsHttpRepository = new SkillsHttpRepository(); this.skillSocketRepository.on(this.socketUpdate); makeAutoObservable(this); @@ -75,22 +75,29 @@ export class SkillStore extends UiDrawerFormState { await this.mapOk("datasets", this.skillsHttpRepository.getDatasetsActiveProject()); await this.mapOk("activeProjectId", this.skillsHttpRepository.getActiveProjectId()); }; - saveSkill() { - this.viewModel.project = this.activeProjectId?.id ?? ""; - this.viewModel.valid().fold( - async (model) => { - (await this.skillsHttpRepository.addNewSkill(model)).fold( - async (s) => { - message.success("Новый "); - this.viewModel = SkillModel.empty(); - await this.mapOk("skils", this.skillsHttpRepository.getAllSkills()); - }, - async (e) => message.error(e.message) - ); + saveSkill = async () => + (await this.viewModel.valid()).fold( + async (s) => { + message.success("URA") }, - async (e) => message.error(e) + async (e) => { + message.error(e); + } ); - } + // this.viewModel.project = this.activeProjectId?.id ?? ""; + // this.viewModel.valid().fold( + // async (model) => { + // (await this.skillsHttpRepository.addNewSkill(model)).fold( + // async (s) => { + // message.success("Новый "); + // this.viewModel = Model.empty(); + // await this.mapOk("skils", this.skillsHttpRepository.getAllSkills()); + // }, + // async (e) => message.error(e.message) + // ); + // }, + // async (e) => message.error(e) + // ); editDrawer(drawerName: DrawersSkill, status: boolean): void { this.titleDrawer = drawerName; @@ -106,15 +113,15 @@ export class SkillStore extends UiDrawerFormState { await this.init(); }; fromEditSkill(id: string): void { - this.viewModel = SkillModel.fromISkill(this.getSkillById(id) as ISkils); + // this.viewModel = Model.fromISkill(this.getSkillById(id) as ISkils); this.editDrawer(DrawersSkill.EDIT_SKILL, true); } saveEdiSkill = async () => { - const skillOrigin = this.getSkillById(this.viewModel.id as string) as ISkils; - skillOrigin.numberOfTrainedEpochs = this.viewModel.epoch; - skillOrigin.isFinished = this.viewModel.isFinished ?? false; - await this.skillsHttpRepository.editSkill(skillOrigin); + // const skillOrigin = this.getSkillById(this.viewModel.id as string) as ISkils; + // skillOrigin.numberOfTrainedEpochs = this.viewModel.epoch; + // skillOrigin.isFinished = this.viewModel.isFinished ?? false; + // await this.skillsHttpRepository.editSkill(skillOrigin); this.editDrawer(DrawersSkill.EDIT_SKILL, false); }; } diff --git a/ui/src/features/machine_learning/presentation/ui/cards/get_model_card.tsx b/ui/src/features/machine_learning/presentation/ui/cards/get_model_card.tsx new file mode 100644 index 0000000..04b858d --- /dev/null +++ b/ui/src/features/machine_learning/presentation/ui/cards/get_model_card.tsx @@ -0,0 +1,4 @@ +export enum CardModel { + pose_estimate = "pose_estimate", +} +export const getModelCard = () => {}; diff --git a/ui/src/features/skils/skill_card.tsx b/ui/src/features/machine_learning/presentation/ui/cards/pose_estimate_card/model_card.tsx similarity index 92% rename from ui/src/features/skils/skill_card.tsx rename to ui/src/features/machine_learning/presentation/ui/cards/pose_estimate_card/model_card.tsx index 9b608cd..535f698 100644 --- a/ui/src/features/skils/skill_card.tsx +++ b/ui/src/features/machine_learning/presentation/ui/cards/pose_estimate_card/model_card.tsx @@ -1,13 +1,13 @@ -import { CoreButton } from "../../core/ui/button/button"; -import { Icon } from "../../core/ui/icons/icons"; +import { CoreButton } from "../../../../../../core/ui/button/button"; +import { Icon } from "../../../../../../core/ui/icons/icons"; import { Dropdown } from "antd"; -import { CoreText, CoreTextType } from "../../core/ui/text/text"; -import { ProcessStatus } from "../dataset/dataset_model"; -import { IMenuItem } from "../dataset/card_dataset"; +import { CoreText, CoreTextType } from "../../../../../../core/ui/text/text"; +import { ProcessStatus } from "../../../../../dataset/dataset_model"; +import { IMenuItem } from "../../../../../dataset/card_dataset"; import type { MenuProps } from "antd"; import { match } from "ts-pattern"; -export interface ISkillCardProps { +export interface IModelCardProps { processStatus?: string; name?: string; isFinished?: boolean; @@ -23,7 +23,7 @@ export interface ISkillCardProps { epochNextTraining?: number; } -export const SkillCard = (props: ISkillCardProps) => { +export const ModelCard = (props: IModelCardProps) => { const menu: IMenuItem[] = [ { onClick: () => { diff --git a/ui/src/features/scene_manager/presentation/forms/camera/camera_form.tsx b/ui/src/features/scene_manager/presentation/forms/camera/camera_form.tsx index 98c47fd..11b5642 100644 --- a/ui/src/features/scene_manager/presentation/forms/camera/camera_form.tsx +++ b/ui/src/features/scene_manager/presentation/forms/camera/camera_form.tsx @@ -51,7 +51,7 @@ export const CameraForm = observer((props: IDefaultSceneManagerFormProps) => { /> Number().isValid(text)} onChange={(text) => (store.updateForm({ near: Number(text) }), store.updateCameraScene())} /> diff --git a/ui/src/features/scene_manager/presentation/scene_manager_store.ts b/ui/src/features/scene_manager/presentation/scene_manager_store.ts index 936805c..b44adce 100644 --- a/ui/src/features/scene_manager/presentation/scene_manager_store.ts +++ b/ui/src/features/scene_manager/presentation/scene_manager_store.ts @@ -96,7 +96,10 @@ export class SceneMangerStore extends UiDrawerFormState this.sceneHttpRepository.editScene(SceneAsset.newScene(this.scene, this.sceneName ?? "")); + sceneSave = () => + this.messageHttp(this.sceneHttpRepository.editScene(SceneAsset.newScene(this.scene, this.sceneName ?? "")), { + successMessage: "Сцена сохранена", + }).then(() => (this.isVisibleSaveButton = false)); iconToSceneManagerForm = (icon: string): SceneManagerForms => { if (icon.isEqual("Camera")) { diff --git a/ui/src/features/skils/skill_model.ts b/ui/src/features/skils/skill_model.ts deleted file mode 100644 index f374e92..0000000 --- a/ui/src/features/skils/skill_model.ts +++ /dev/null @@ -1,55 +0,0 @@ -import makeAutoObservable from "mobx-store-inheritance"; -import { Result } from "../../core/helper/result"; -import { ISkils } from "./skills_http_repository"; - -export class SkillModel { - numberOfTrainedEpochs?: number; - id?: string; - isFinished?:boolean; - constructor( - public name: string, - public datasetId: string, - public project: string, - public epoch: number, - numberOfTrainedEpochs?: number, - id?: string, - isFinished?:boolean - ) { - this.numberOfTrainedEpochs = numberOfTrainedEpochs; - this.id = id; - this.isFinished = isFinished - makeAutoObservable(this); - } - - static fromISkill(model: ISkils) { - return new SkillModel( - model.name, - model.datasetId._id, - model.project._id, - model.epoch, - model.numberOfTrainedEpochs, - model._id, - model.isFinished - ); - } - - static empty() { - return new SkillModel("", "", "", 0); - } - - valid(): Result { - if (this.name.isEmpty()) { - return Result.error("введите имя скила"); - } - if (this.datasetId.isEmpty()) { - return Result.error("datasetId is empty"); - } - if (this.project.isEmpty()) { - return Result.error("project is empty"); - } - if (this.epoch.isNegative()) { - return Result.error("эпоха не может принимать отрицательное число"); - } - return Result.ok(this); - } -} diff --git a/ui/src/index.tsx b/ui/src/index.tsx index 01eff66..3a9ae2c 100644 --- a/ui/src/index.tsx +++ b/ui/src/index.tsx @@ -6,6 +6,7 @@ import { SocketLister } from "./features/socket_lister/socket_lister"; import { RouterProvider } from "react-router-dom"; import { router } from "./core/routers/routers"; import { configure } from "mobx"; + configure({ enforceActions: "never",