From 6840402b1f982ae4eb1bfffcf954d47c121f5195 Mon Sep 17 00:00:00 2001 From: IDONTSUDO Date: Tue, 9 Apr 2024 16:31:25 +0300 Subject: [PATCH] deleted unnecessary files added new features --- .DS_Store | Bin 6148 -> 6148 bytes .gitignore | 1 + server/src/core/controllers/app.ts | 2 +- .../src/core/controllers/http_controller.ts | 22 +- server/src/core/controllers/routes.ts | 27 +- server/src/core/helpers/worker_computed.ts | 2 - server/src/core/models/process_model.ts | 2 +- server/src/core/models/robossembler_assets.ts | 161 +-------- server/src/core/models/static_files.ts | 1 + ...d_json_to_plain_instance_class_scenario.ts | 1 + ...e_pipeline_to_realtime_service_scenario.ts | 8 +- server/src/core/services/stack_service.ts | 2 +- server/src/core/services/trigger_service.ts | 2 +- .../core/usecases/create_folder_usecase.ts | 1 + .../src/core/usecases/exec_process_usecase.ts | 26 ++ .../read_by_id_database_model_usecase.ts | 10 +- .../usecases/search_database_model_usecase.ts | 4 +- .../nix_store_manager.ts | 2 +- .../models/pipeline_database_model.ts | 4 +- .../models/pipeline_model.ts | 4 +- .../models/pipeline_validation_model.ts | 2 +- .../pipeline_presentation.ts | 0 .../models/process_database_model.ts | 0 .../models/process_validation_model.ts | 0 .../process_presentation.ts | 0 .../models/project_database_model.ts | 12 +- .../models/project_validation_model.ts | 0 .../_projects/projects_presentation.ts | 13 + .../domain/pipeline_status_usecase.ts | 0 .../domain/run_instance_pipeline_usecase.ts | 7 +- .../realtime_presentation.ts | 0 .../models/trigger_database_model.ts | 0 .../models/trigger_validation_model.ts | 0 .../triggers_presentation.ts | 0 .../datasets/datasets_presentation.ts | 17 + .../domain/create_dataset_scanario.ts | 92 ++++++ .../get_dataset_active_project_scenario.ts | 15 + .../datasets/models/dataset_database_model.ts | 37 +++ .../models/dataset_validation_model.ts | 34 ++ .../domain/create_new_project_scenario.ts | 22 -- ...ssembler_assets_network_mapper_scenario.ts | 33 -- .../project_instance_presentation.ts | 49 --- .../domain/create_new_project_scenario.ts | 34 ++ .../domain/get_active_project_scenario.ts | 12 + ...ssembler_assets_network_mapper_scenario.ts | 33 ++ .../domain/save_active_scene_scenario.ts | 2 +- .../domain/set_active_project_use_scenario.ts | 39 ++- .../upload_file_to_to_project_scenario.ts | 32 +- .../models/project_instance_database_model.ts | 8 +- .../project_instance_validation_model.ts | 3 - .../projects/projects_presentation.ts | 38 ++- server/src/main.ts | 4 +- server/test/model/mock_pipelines.ts | 2 +- server/test/services/trigger_service_test.ts | 2 +- server/test/test.ts | 2 +- ui/package-lock.json | 309 +++++++++++++++++- ui/package.json | 3 +- ui/src/core/extensions/extensions.ts | 5 +- ui/src/core/extensions/string.ts | 25 ++ .../model/robossembler_assets.ts | 16 +- .../core/repository/core_three_repository.ts | 27 +- ui/src/core/routers/routers.tsx | 67 ++-- ui/src/core/ui/form_builder/form_builder.tsx | 138 ++++++++ .../ui/form_builder/form_builder_store.ts | 103 ++++++ .../core/ui/form_builder/form_view_model.ts | 171 ++++++++++ ui/src/core/ui/form_builder/readme.md | 33 ++ .../all_projects/data/project_repository.ts | 7 +- .../all_projects/model/project_model.ts | 2 +- .../presentation/all_projects_screen.tsx | 46 +-- .../presentation/all_projects_store.ts | 18 +- .../model/editor_view.ts | 21 +- .../behavior_tree_builder_screen.tsx | 36 +- .../behavior_tree_builder_store.tsx | 34 +- .../presentation/ui/editor/editor.tsx | 2 +- .../ui/editor/nodes/controls_node.tsx | 8 +- .../data/create_pipeline_repository.ts | 18 - .../create_pipeline/model/pipeline_model.ts | 8 - .../presentation/create_pipeline_screen.tsx | 63 ---- .../presentation/create_pipeline_store.ts | 99 ------ .../create_process/data/process_repostiory.ts | 8 - .../create_process/model/process_model.ts | 29 -- .../presentation/create_process_screen.tsx | 65 ---- .../presentation/logic/process_store.ts | 16 - .../create_project_repository.ts | 12 +- .../create_project/create_project_screen.tsx | 89 ++--- .../create_project/create_project_store.ts | 46 +-- .../features/create_project/project_model.ts | 2 - .../create_project_instance.tsx | 37 --- .../create_project_instance_repository.ts | 16 - .../create_project_instance_store.ts | 39 --- .../new_project_model.ts | 17 - .../create_trigger/data/trigger_repository.ts | 8 - .../model/trigger_form_view_model.ts | 10 - .../components/code_trigger_form.tsx | 41 --- .../components/file_trigger_form.tsx | 51 --- .../presentation/create_trigger_screen.tsx | 75 ----- .../presentation/trigger_store.ts | 84 ----- ui/src/features/dataset/dataset_form_mock.ts | 75 +++++ ui/src/features/dataset/dataset_model.ts | 25 ++ ui/src/features/dataset/dataset_repository.ts | 16 + ui/src/features/dataset/dataset_screen.tsx | 94 ++++++ ui/src/features/dataset/dataset_store.ts | 102 ++++++ .../pipeline_instance_screen.tsx | 18 +- .../scene_manager/data/scene_repository.ts | 2 +- .../scene_manager/model/scene_assets.ts | 8 +- .../presentation/scene_manager.tsx | 2 +- .../presentation/scene_manager_store.ts | 8 +- .../data/select_project_repository.ts | 12 - .../select_project/model/project_model.ts | 9 - .../presentation/select_project.tsx | 40 --- .../presentation/select_project_store.ts | 28 -- .../model/stick_objects_marking_store_mode.ts | 7 + .../model/sticky_helper.ts | 20 ++ .../model/sticky_loader_mode.ts | 4 + .../stick_objects_marking_screen.tsx | 23 +- .../stick_objects_marking_store.tsx | 88 ++--- .../stick_objects_marking_three_repository.ts | 28 +- ui/src/index.tsx | 16 +- ui/tsconfig.json | 2 +- 119 files changed, 1835 insertions(+), 1522 deletions(-) create mode 100644 .gitignore create mode 100644 server/src/core/usecases/exec_process_usecase.ts rename server/src/features/{nix_store_manager => _nix_store_manager}/nix_store_manager.ts (96%) rename server/src/features/{pipelines => _pipelines}/models/pipeline_database_model.ts (81%) rename server/src/features/{pipelines => _pipelines}/models/pipeline_model.ts (75%) rename server/src/features/{pipelines => _pipelines}/models/pipeline_validation_model.ts (80%) rename server/src/features/{pipelines => _pipelines}/pipeline_presentation.ts (100%) rename server/src/features/{process => _process}/models/process_database_model.ts (100%) rename server/src/features/{process => _process}/models/process_validation_model.ts (100%) rename server/src/features/{process => _process}/process_presentation.ts (100%) rename server/src/features/{projects => _projects}/models/project_database_model.ts (63%) rename server/src/features/{projects => _projects}/models/project_validation_model.ts (100%) create mode 100644 server/src/features/_projects/projects_presentation.ts rename server/src/features/{realtime => _realtime}/domain/pipeline_status_usecase.ts (100%) rename server/src/features/{realtime => _realtime}/domain/run_instance_pipeline_usecase.ts (90%) rename server/src/features/{realtime => _realtime}/realtime_presentation.ts (100%) rename server/src/features/{triggers => _triggers}/models/trigger_database_model.ts (100%) rename server/src/features/{triggers => _triggers}/models/trigger_validation_model.ts (100%) rename server/src/features/{triggers => _triggers}/triggers_presentation.ts (100%) create mode 100644 server/src/features/datasets/datasets_presentation.ts create mode 100644 server/src/features/datasets/domain/create_dataset_scanario.ts create mode 100644 server/src/features/datasets/domain/get_dataset_active_project_scenario.ts create mode 100644 server/src/features/datasets/models/dataset_database_model.ts create mode 100644 server/src/features/datasets/models/dataset_validation_model.ts delete mode 100644 server/src/features/project_instance/domain/create_new_project_scenario.ts delete mode 100644 server/src/features/project_instance/domain/robossembler_assets_network_mapper_scenario.ts delete mode 100644 server/src/features/project_instance/project_instance_presentation.ts create mode 100644 server/src/features/projects/domain/create_new_project_scenario.ts create mode 100644 server/src/features/projects/domain/get_active_project_scenario.ts create mode 100644 server/src/features/projects/domain/robossembler_assets_network_mapper_scenario.ts rename server/src/features/{project_instance => projects}/domain/save_active_scene_scenario.ts (94%) rename server/src/features/{project_instance => projects}/domain/set_active_project_use_scenario.ts (50%) rename server/src/features/{project_instance => projects}/domain/upload_file_to_to_project_scenario.ts (50%) rename server/src/features/{project_instance => projects}/models/project_instance_database_model.ts (73%) rename server/src/features/{project_instance => projects}/models/project_instance_validation_model.ts (85%) rename ui/src/{features/scene_manager => core}/model/robossembler_assets.ts (89%) create mode 100644 ui/src/core/ui/form_builder/form_builder.tsx create mode 100644 ui/src/core/ui/form_builder/form_builder_store.ts create mode 100644 ui/src/core/ui/form_builder/form_view_model.ts create mode 100644 ui/src/core/ui/form_builder/readme.md delete mode 100644 ui/src/features/create_pipeline/data/create_pipeline_repository.ts delete mode 100644 ui/src/features/create_pipeline/model/pipeline_model.ts delete mode 100644 ui/src/features/create_pipeline/presentation/create_pipeline_screen.tsx delete mode 100644 ui/src/features/create_pipeline/presentation/create_pipeline_store.ts delete mode 100644 ui/src/features/create_process/data/process_repostiory.ts delete mode 100644 ui/src/features/create_process/model/process_model.ts delete mode 100644 ui/src/features/create_process/presentation/create_process_screen.tsx delete mode 100644 ui/src/features/create_process/presentation/logic/process_store.ts delete mode 100644 ui/src/features/create_project_instance/create_project_instance.tsx delete mode 100644 ui/src/features/create_project_instance/create_project_instance_repository.ts delete mode 100644 ui/src/features/create_project_instance/create_project_instance_store.ts delete mode 100644 ui/src/features/create_project_instance/new_project_model.ts delete mode 100644 ui/src/features/create_trigger/data/trigger_repository.ts delete mode 100644 ui/src/features/create_trigger/model/trigger_form_view_model.ts delete mode 100644 ui/src/features/create_trigger/presentation/components/code_trigger_form.tsx delete mode 100644 ui/src/features/create_trigger/presentation/components/file_trigger_form.tsx delete mode 100644 ui/src/features/create_trigger/presentation/create_trigger_screen.tsx delete mode 100644 ui/src/features/create_trigger/presentation/trigger_store.ts create mode 100644 ui/src/features/dataset/dataset_form_mock.ts create mode 100644 ui/src/features/dataset/dataset_model.ts create mode 100644 ui/src/features/dataset/dataset_repository.ts create mode 100644 ui/src/features/dataset/dataset_screen.tsx create mode 100644 ui/src/features/dataset/dataset_store.ts delete mode 100644 ui/src/features/select_project/data/select_project_repository.ts delete mode 100644 ui/src/features/select_project/model/project_model.ts delete mode 100644 ui/src/features/select_project/presentation/select_project.tsx delete mode 100644 ui/src/features/select_project/presentation/select_project_store.ts create mode 100644 ui/src/features/stick_objects_marking/model/stick_objects_marking_store_mode.ts create mode 100644 ui/src/features/stick_objects_marking/model/sticky_helper.ts create mode 100644 ui/src/features/stick_objects_marking/model/sticky_loader_mode.ts diff --git a/.DS_Store b/.DS_Store index fd6d5acc49e931778b288643c9eedc906f4b3283..989ca3050c772de3341f64aa6b89bcce35fd118c 100644 GIT binary patch literal 6148 zcmZQzU|@7AO)+F(5MW?n;9!8zEL;p&0Z1N%F(jFwB0?bZKxX8m8wMxm=N3T4N2$>e z7!85J9Ri@d%fg_?kj{|FP=btG%B<18MfeH+bv|}94&m46`l~2Jd zUyy-RHs~vWLWP|{kD-jAm?4=VpCN@I6~%T2HX8;81~e7OZdf$YzjxO`up2N`AzXr6 z6^eTp!0usVC}v1yC}JoBk)ApE$x#1-3dt@81_qn|U;uJD1BzN?mvf|M7%?!Q$|Jiw zC-JO|`~|SPQOwBAN4Of78e}(f9|OCCiJ_Ds6V0ulkTVB6^*=%lvKw7P57sd-Fo5+U zyUqH47b7%Yp>hZ}q01q=CHT|_utlT9kO~1th-*2xA@nFY8UmvsFd72z5CD}Apo$Sh zJ3!j_3=I$(B*ef7szM-q7MLbRP(J`72GR;r1JVkjL0TCYK`gL5r1!wc0MW__?uIZh zFoL@zAR4Tlfsp~Moq-W-GXn!7*k%R>Mu>I>Mu>I>MraR(5mZ@&%!g=aV1#IgId7C6 z4S~@RfQA4wgcbnR|E>%SxcdJPRior+2#kinunYl47MEZbCs3t{!+W5*7F3@mK;=Po yFsL?X1l7|JeIO-ZStiJUq6C-&kppQ3Rr}zon2`ZelaDq8U?DV0kA?vKLjVA2sh#xz delta 89 zcmZoMXfc=|#>CJ*F;Q%yo}wrd0|Nsi1A_nqLn=d&XHI@{Qcix-#6 { await result.fold( async (_s) => { await new CheckAndCreateStaticFilesFolderUseCase().call(); - await new SetLastActivePipelineToRealTimeServiceScenario().call(); + // await new SetLastActivePipelineToRealTimeServiceScenario().call(); }, async (_e) => { this.setServerStatus(ServerStatus.error); diff --git a/server/src/core/controllers/http_controller.ts b/server/src/core/controllers/http_controller.ts index 7d9d6b9..7fd5561 100644 --- a/server/src/core/controllers/http_controller.ts +++ b/server/src/core/controllers/http_controller.ts @@ -26,7 +26,7 @@ export abstract class CallBackStrategyWithQueryPage { export abstract class CallbackStrategyWithFileUpload { abstract checkingFileExpression: RegExp; abstract idValidationExpression: CoreValidation; - abstract call(file: File, id: string, description: string): ResponseBase; + abstract call(file: File, id: string): ResponseBase; } interface ISubSetFeatureRouter { @@ -122,12 +122,12 @@ export class CoreHttpController implements ICoreHttpController { res.status(400).json("need file to form data request"); return; } - if (req.query.description === undefined) { - res - .status(400) - .json("request query description is null, need query description &description={description:String}"); - return; - } + // if (req.query.description === undefined) { + // res + // .status(400) + // .json("request query description is null, need query description &description={description:String}"); + // return; + // } if (req.query.id === undefined) { res.status(400).json("request query id is null, need query id ?id={id:String}"); return; @@ -142,7 +142,7 @@ export class CoreHttpController implements ICoreHttpController { return; } } - await this.responseHelper(res, el.fn.call(req["files"]["file"], req.query.id, req.query.description)); + await this.responseHelper(res, el.fn.call(req["files"]["file"], req.query.id)); } }); }); @@ -197,12 +197,10 @@ export class CoreHttpController implements ICoreHttpController { } (await useCase(payload)).fold( (ok) => { - res.json(ok); - return; + return res.json(ok); }, (err) => { - res.status(400).json({ error: String(err) }); - return; + return res.status(400).json({ error: String(err) }); } ); } diff --git a/server/src/core/controllers/routes.ts b/server/src/core/controllers/routes.ts index b76963d..b63fc5b 100644 --- a/server/src/core/controllers/routes.ts +++ b/server/src/core/controllers/routes.ts @@ -1,30 +1,9 @@ -import { NixStoreManagerPresentation } from "../../features/nix_store_manager/nix_store_manager"; -import { PipelinePresentation } from "../../features/pipelines/pipeline_presentation"; -import { ProcessPresentation } from "../../features/process/process_presentation"; -import { - ProjectInstancePresentation, - RobossemblerAssetsPresentation, -} from "../../features/project_instance/project_instance_presentation"; +import { DatasetsPresentation } from "../../features/datasets/datasets_presentation"; import { ProjectsPresentation } from "../../features/projects/projects_presentation"; -import { RealTimePresentation } from "../../features/realtime/realtime_presentation"; -import { TriggerPresentation } from "../../features/triggers/triggers_presentation"; +// import { ProjectsPresentation } from "../../features/_projects/projects_presentation"; import { extensions } from "../extensions/extensions"; import { Routes } from "../interfaces/router"; extensions(); -export const routersImplementPureCrud = [ - new TriggerPresentation(), - new ProjectsPresentation(), - new ProcessPresentation(), - new PipelinePresentation(), -]; - -export const httpRoutes: Routes[] = [ - new RealTimePresentation(), - new ProjectInstancePresentation(), - new NixStoreManagerPresentation(), - new RobossemblerAssetsPresentation(), -] - .concat(routersImplementPureCrud) - .map((el) => el.call()); +export const httpRoutes: Routes[] = [new ProjectsPresentation(), new DatasetsPresentation()].map((el) => el.call()); diff --git a/server/src/core/helpers/worker_computed.ts b/server/src/core/helpers/worker_computed.ts index bc88fad..6a9b7a0 100644 --- a/server/src/core/helpers/worker_computed.ts +++ b/server/src/core/helpers/worker_computed.ts @@ -17,8 +17,6 @@ export interface WorkerDataExec { process.on("message", async (message) => { const workerData = message as WorkerDataExec; if (workerData.type == WorkerType.SPAWN) { - // Maybe error - // const subprocess = cp.spawn(workerData.command, workerData.cliArgs, { const subprocess = cp.spawn(workerData.command, { cwd: workerData.execPath, }); diff --git a/server/src/core/models/process_model.ts b/server/src/core/models/process_model.ts index 9f601ed..85167f5 100644 --- a/server/src/core/models/process_model.ts +++ b/server/src/core/models/process_model.ts @@ -1,4 +1,4 @@ -import { Trigger } from "../../features/triggers/models/trigger_database_model"; +import { Trigger } from "../../features/_triggers/models/trigger_database_model"; import { EXEC_TYPE } from "./exec_error_model"; export interface IPipeline { diff --git a/server/src/core/models/robossembler_assets.ts b/server/src/core/models/robossembler_assets.ts index d0a99f2..8d4c9c3 100644 --- a/server/src/core/models/robossembler_assets.ts +++ b/server/src/core/models/robossembler_assets.ts @@ -1,160 +1,23 @@ -import { IsArray, IsEnum, IsNumber, IsOptional, IsString, ValidateNested } from "class-validator"; +import { IsArray, IsString } from "class-validator"; import { Type } from "class-transformer"; - -export class Gravity { - @IsNumber() - x: number; - @IsNumber() - y: number; - @IsNumber() - z: number; +class Asset { + @IsString() + public name: string; + @IsString() + public mesh: string; + @IsString() + public image: string; } - -export class Pose { - @IsNumber() - x: number; - @IsNumber() - y: number; - @IsNumber() - z: number; - @IsNumber() - roll: number; - @IsNumber() - pitch: number; - @IsNumber() - yaw: number; -} - -export class Position { - @IsNumber() - x: number; - @IsNumber() - y: number; - @IsNumber() - z: number; -} - -export enum InstanceType { - RGB_CAMERA = "rgb_camera", - SCENE_SIMPLE_OBJECT = "scene_simple_object", -} - -abstract class CoreInstances {} - -export class Instance extends CoreInstances { - @IsEnum(InstanceType) - instanceType: InstanceType; - @Type(() => Position) - position: Position; - @IsArray() - quaternion: number[]; - @IsOptional() - @IsString() - instanceAt: null | string = null; -} - -export class SceneSimpleObject extends Instance {} - -export class InstanceRgbCamera extends Instance { - @IsString() - cameraLink: string; - @IsString() - topicCameraInfo: string; - @IsOptional() - @IsString() - topicDepth: string | null; - @IsString() - topicImage: string; -} -export class Asset { - @IsString() - name: string; - @IsString() - ixx: string; - @IsString() - ixy: string; - @IsString() - ixz: string; - @IsString() - iyy: string; - @IsString() - izz: string; - @IsString() - mass: string; - @IsString() - posX: string; - @IsString() - posY: string; - @IsString() - posZ: string; - @IsString() - eulerX: string; - @IsString() - eulerY: string; - @IsString() - eulerZ: string; - @IsString() - iyz: string; - @IsString() - meshPath: string; - @IsString() - friction: string; - @IsString() - centerMassX: string; - @IsString() - centerMassY: string; - @IsString() - centerMassZ: string; -} - -export class Physics { - @IsString() - engine_name: string; - @Type(() => Gravity) - gravity: Gravity; -} - export class RobossemblerAssets { - @ValidateNested() + @IsArray() @Type(() => Asset) assets: Asset[]; - - @IsArray() - @Type(() => Instance, { - discriminator: { - property: "type", - subTypes: [ - { value: InstanceRgbCamera, name: InstanceType.RGB_CAMERA }, - { value: SceneSimpleObject, name: InstanceType.SCENE_SIMPLE_OBJECT }, - ], - }, - keepDiscriminatorProperty: true, - }) - instances: Instance[]; - - @IsOptional() - @ValidateNested() - @Type(() => Physics) - physics: Physics; - - convertLocalPathsToServerPaths(server_address: string): RobossemblerAssets { + convertLocalPathsToServerPaths(serverAddress: string): RobossemblerAssets { this.assets = this.assets.map((el) => { - el.meshPath = server_address + el.meshPath; + el.mesh = `${serverAddress}/${el.mesh.slice(2, el.mesh.length)}`; + el.image = `${serverAddress}/${el.image.slice(2, el.image.length)}`; return el; }); return this; } - - getAssetPath(assetName: string): string { - const findElement = this.assets.find((el) => el.name === assetName); - - if (findElement === undefined) { - throw new Error("RobossemblerAssets.getAssetPath not found asset by name:" + assetName); - } - return findElement.meshPath; - } - - getAssetAtInstance(instanceAt: string): Asset { - return this.assets.filter((el) => el.name === instanceAt)[0]; - } } diff --git a/server/src/core/models/static_files.ts b/server/src/core/models/static_files.ts index dfe36c4..aed291c 100644 --- a/server/src/core/models/static_files.ts +++ b/server/src/core/models/static_files.ts @@ -1,3 +1,4 @@ export enum StaticFiles { robossembler_assets = "robossembler_assets.json", + assets = "/assets/assets.json", } diff --git a/server/src/core/scenarios/read_file_and_json_to_plain_instance_class_scenario.ts b/server/src/core/scenarios/read_file_and_json_to_plain_instance_class_scenario.ts index 03738ba..a8671ce 100644 --- a/server/src/core/scenarios/read_file_and_json_to_plain_instance_class_scenario.ts +++ b/server/src/core/scenarios/read_file_and_json_to_plain_instance_class_scenario.ts @@ -13,6 +13,7 @@ export class ReadingJsonFileAndConvertingToInstanceClassScenario { } call = async (path: string): Promise> => { try { + console.log(path); const result = await new ReadFileAndParseJsonUseCase().call(path); if (result.isFailure()) { return result.forward(); diff --git a/server/src/core/scenarios/set_active_pipeline_to_realtime_service_scenario.ts b/server/src/core/scenarios/set_active_pipeline_to_realtime_service_scenario.ts index 5a8398a..fa4bf7d 100644 --- a/server/src/core/scenarios/set_active_pipeline_to_realtime_service_scenario.ts +++ b/server/src/core/scenarios/set_active_pipeline_to_realtime_service_scenario.ts @@ -1,8 +1,8 @@ import { IProjectInstanceModel, ProjectInstanceDbModel, -} from "../../features/project_instance/models/project_instance_database_model"; -import { pipelineRealTimeService } from "../../features/realtime/realtime_presentation"; +} from "../../features/projects/models/project_instance_database_model"; +import { pipelineRealTimeService } from "../../features/_realtime/realtime_presentation"; import { App } from "../controllers/app"; import { CreateFolderUseCase } from "../usecases/create_folder_usecase"; import { SearchDataBaseModelUseCase } from "../usecases/search_database_model_usecase"; @@ -15,6 +15,10 @@ export class SetLastActivePipelineToRealTimeServiceScenario { }) ).fold( async (projectModel) => { + if (projectModel.project === null) { + return; + } + const projectPath = App.staticFilesStoreDir() + projectModel.rootDir + "/"; await new CreateFolderUseCase().call(projectPath); pipelineRealTimeService.setPipelineDependency( diff --git a/server/src/core/services/stack_service.ts b/server/src/core/services/stack_service.ts index 336b758..16f105b 100644 --- a/server/src/core/services/stack_service.ts +++ b/server/src/core/services/stack_service.ts @@ -7,7 +7,7 @@ import { Result } from "../helpers/result"; import { ExecutorResult } from "../models/executor_result"; import { delay } from "../helpers/delay"; import { TriggerService } from "./trigger_service"; -import { Trigger } from "../../features/triggers/models/trigger_database_model"; +import { Trigger } from "../../features/_triggers/models/trigger_database_model"; export interface Iteration { hashes: IHashesCache | null; diff --git a/server/src/core/services/trigger_service.ts b/server/src/core/services/trigger_service.ts index e4979f1..940b814 100644 --- a/server/src/core/services/trigger_service.ts +++ b/server/src/core/services/trigger_service.ts @@ -3,7 +3,7 @@ import { IHashesCache } from "./files_change_notifier_service"; import { EventsFileChanger } from "../models/meta_data_file_manager_model"; import { Result } from "../helpers/result"; import { TypedEvent } from "../helpers/typed_event"; -import { Trigger, TriggerType } from "../../features/triggers/models/trigger_database_model"; +import { Trigger, TriggerType } from "../../features/_triggers/models/trigger_database_model"; export class TriggerCallResult { results: Array; diff --git a/server/src/core/usecases/create_folder_usecase.ts b/server/src/core/usecases/create_folder_usecase.ts index 5a007fe..7aefa57 100644 --- a/server/src/core/usecases/create_folder_usecase.ts +++ b/server/src/core/usecases/create_folder_usecase.ts @@ -8,6 +8,7 @@ export class CreateFolderUseCase { } call = async (path: string): Promise> => { try { + console.log(path); if (await this.fileSystemRepository.dirIsExists(path)) { return Result.ok("ok"); } diff --git a/server/src/core/usecases/exec_process_usecase.ts b/server/src/core/usecases/exec_process_usecase.ts new file mode 100644 index 0000000..0b6f032 --- /dev/null +++ b/server/src/core/usecases/exec_process_usecase.ts @@ -0,0 +1,26 @@ +import { Result } from "../helpers/result"; +import { TypedEvent } from "../helpers/typed_event"; +import { EXEC_TYPE, ExecError, SpawnError } from "../models/exec_error_model"; +import { ExecutorResult } from "../models/executor_result"; +import { ExecutorProgramService } from "../services/executor_program_service"; + +export class ExecProcessUseCase { + call = async ( + path: string, + command: string, + watcher?: TypedEvent> + ): Promise> => { + try { + const executorProgramService = new ExecutorProgramService(path); + if (watcher) + executorProgramService.on((event) => { + watcher.emit(event); + }); + executorProgramService.call(EXEC_TYPE.EXEC, command); + + return Result.ok("ok"); + } catch (error) { + return Result.error(error); + } + }; +} diff --git a/server/src/core/usecases/read_by_id_database_model_usecase.ts b/server/src/core/usecases/read_by_id_database_model_usecase.ts index 8d14c0f..63f294e 100644 --- a/server/src/core/usecases/read_by_id_database_model_usecase.ts +++ b/server/src/core/usecases/read_by_id_database_model_usecase.ts @@ -9,7 +9,15 @@ export class ReadByIdDataBaseModelUseCase { call = async (id: string): Promise> => { try { const dbModel = this.databaseModel as any; - return Result.ok(await dbModel.findById(id)); + const model = await dbModel.findById(id); + if (model === null) { + return Result.error( + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-expect-error + Error(`the database table ${this.databaseModel.modelName} does not contain an object with this ID`) + ); + } + return Result.ok(model); } catch (error) { return Result.error(error); } diff --git a/server/src/core/usecases/search_database_model_usecase.ts b/server/src/core/usecases/search_database_model_usecase.ts index 44ad0d2..c8e6fd4 100644 --- a/server/src/core/usecases/search_database_model_usecase.ts +++ b/server/src/core/usecases/search_database_model_usecase.ts @@ -7,10 +7,10 @@ export class SearchDataBaseModelUseCase { this.model = model; } - call = async (findFilter: Partial): Promise> => { + call = async (findFilter: Partial, error: string = "not found database"): Promise> => { const result = await this.model.findOne(findFilter); if (result === null) { - return Result.error(null); + return Result.error(error); } else { return Result.ok(result); } diff --git a/server/src/features/nix_store_manager/nix_store_manager.ts b/server/src/features/_nix_store_manager/nix_store_manager.ts similarity index 96% rename from server/src/features/nix_store_manager/nix_store_manager.ts rename to server/src/features/_nix_store_manager/nix_store_manager.ts index 145bfd5..d9b56c2 100644 --- a/server/src/features/nix_store_manager/nix_store_manager.ts +++ b/server/src/features/_nix_store_manager/nix_store_manager.ts @@ -4,7 +4,7 @@ import { EXEC_TYPE } from "../../core/models/exec_error_model"; import { ExecutorResult } from "../../core/models/executor_result"; import { IPipeline, IssueType, StackGenerateType } from "../../core/models/process_model"; import { StackService } from "../../core/services/stack_service"; -import { TriggerType } from "../triggers/models/trigger_database_model"; +import { TriggerType } from "../_triggers/models/trigger_database_model"; class NixStoreModel {} diff --git a/server/src/features/pipelines/models/pipeline_database_model.ts b/server/src/features/_pipelines/models/pipeline_database_model.ts similarity index 81% rename from server/src/features/pipelines/models/pipeline_database_model.ts rename to server/src/features/_pipelines/models/pipeline_database_model.ts index 1d39bd7..dac4f36 100644 --- a/server/src/features/pipelines/models/pipeline_database_model.ts +++ b/server/src/features/_pipelines/models/pipeline_database_model.ts @@ -1,7 +1,7 @@ import { Schema, model } from "mongoose"; import { IPipeline } from "../../../core/models/process_model"; -import { schemaProcess } from "../../process/models/process_database_model"; -import { triggerSchema } from "../../triggers/models/trigger_database_model"; +import { schemaProcess } from "../../_process/models/process_database_model"; +import { triggerSchema } from "../../_triggers/models/trigger_database_model"; export const PipelineSchema = new Schema({ process: { diff --git a/server/src/features/pipelines/models/pipeline_model.ts b/server/src/features/_pipelines/models/pipeline_model.ts similarity index 75% rename from server/src/features/pipelines/models/pipeline_model.ts rename to server/src/features/_pipelines/models/pipeline_model.ts index 69cd0fc..fca67ba 100644 --- a/server/src/features/pipelines/models/pipeline_model.ts +++ b/server/src/features/_pipelines/models/pipeline_model.ts @@ -1,8 +1,8 @@ import { IsOptional, ValidateNested } from "class-validator"; import { IPipeline, IProcess, StackGenerateType } from "../../../core/models/process_model"; import { Type } from "class-transformer"; -import { ProcessModel } from "../../process/models/process_validation_model"; -import { TriggerModelValidationModel } from "../../triggers/models/trigger_validation_model"; +import { ProcessModel } from "../../_process/models/process_validation_model"; +import { TriggerModelValidationModel } from "../../_triggers/models/trigger_validation_model"; export class PipelineModel implements IPipeline { @ValidateNested() diff --git a/server/src/features/pipelines/models/pipeline_validation_model.ts b/server/src/features/_pipelines/models/pipeline_validation_model.ts similarity index 80% rename from server/src/features/pipelines/models/pipeline_validation_model.ts rename to server/src/features/_pipelines/models/pipeline_validation_model.ts index d16382e..59fc6b3 100644 --- a/server/src/features/pipelines/models/pipeline_validation_model.ts +++ b/server/src/features/_pipelines/models/pipeline_validation_model.ts @@ -1,6 +1,6 @@ import { IsMongoId, IsOptional } from "class-validator"; import { IProcess, StackGenerateType } from "../../../core/models/process_model"; -import { TriggerModelValidationModel } from "../../triggers/models/trigger_validation_model"; +import { TriggerModelValidationModel } from "../../_triggers/models/trigger_validation_model"; export class PipelineValidationModel { @IsMongoId() diff --git a/server/src/features/pipelines/pipeline_presentation.ts b/server/src/features/_pipelines/pipeline_presentation.ts similarity index 100% rename from server/src/features/pipelines/pipeline_presentation.ts rename to server/src/features/_pipelines/pipeline_presentation.ts diff --git a/server/src/features/process/models/process_database_model.ts b/server/src/features/_process/models/process_database_model.ts similarity index 100% rename from server/src/features/process/models/process_database_model.ts rename to server/src/features/_process/models/process_database_model.ts diff --git a/server/src/features/process/models/process_validation_model.ts b/server/src/features/_process/models/process_validation_model.ts similarity index 100% rename from server/src/features/process/models/process_validation_model.ts rename to server/src/features/_process/models/process_validation_model.ts diff --git a/server/src/features/process/process_presentation.ts b/server/src/features/_process/process_presentation.ts similarity index 100% rename from server/src/features/process/process_presentation.ts rename to server/src/features/_process/process_presentation.ts diff --git a/server/src/features/projects/models/project_database_model.ts b/server/src/features/_projects/models/project_database_model.ts similarity index 63% rename from server/src/features/projects/models/project_database_model.ts rename to server/src/features/_projects/models/project_database_model.ts index 2948f94..e45b146 100644 --- a/server/src/features/projects/models/project_database_model.ts +++ b/server/src/features/_projects/models/project_database_model.ts @@ -1,6 +1,5 @@ import { Schema, model } from "mongoose"; -import { schemaPipeline } from "../../pipelines/models/pipeline_database_model"; -import { PipelineValidationModel } from "../../pipelines/models/pipeline_validation_model"; +import { PipelineValidationModel } from "../../_pipelines/models/pipeline_validation_model"; export interface IProjectModel { _id?: string; @@ -11,15 +10,12 @@ export interface IProjectModel { } export const ProjectSchema = new Schema({ - pipelines: { - type: Array, - ref: schemaPipeline, - autopopulate: true, - default: null, - }, description: { type: String, }, + rootDir: { + type: String, + }, isActive: { type: Boolean, default: false, diff --git a/server/src/features/projects/models/project_validation_model.ts b/server/src/features/_projects/models/project_validation_model.ts similarity index 100% rename from server/src/features/projects/models/project_validation_model.ts rename to server/src/features/_projects/models/project_validation_model.ts diff --git a/server/src/features/_projects/projects_presentation.ts b/server/src/features/_projects/projects_presentation.ts new file mode 100644 index 0000000..253bf2c --- /dev/null +++ b/server/src/features/_projects/projects_presentation.ts @@ -0,0 +1,13 @@ +import { CrudController } from "../../core/controllers/crud_controller"; +import { ProjectDBModel } from "./models/project_database_model"; +import { ProjectValidationModel } from "./models/project_validation_model"; + +export class ProjectsPresentation extends CrudController { + constructor() { + super({ + url: "project", + validationModel: ProjectValidationModel, + databaseModel: ProjectDBModel, + }); + } +} diff --git a/server/src/features/realtime/domain/pipeline_status_usecase.ts b/server/src/features/_realtime/domain/pipeline_status_usecase.ts similarity index 100% rename from server/src/features/realtime/domain/pipeline_status_usecase.ts rename to server/src/features/_realtime/domain/pipeline_status_usecase.ts diff --git a/server/src/features/realtime/domain/run_instance_pipeline_usecase.ts b/server/src/features/_realtime/domain/run_instance_pipeline_usecase.ts similarity index 90% rename from server/src/features/realtime/domain/run_instance_pipeline_usecase.ts rename to server/src/features/_realtime/domain/run_instance_pipeline_usecase.ts index 37c1c1a..b47b873 100644 --- a/server/src/features/realtime/domain/run_instance_pipeline_usecase.ts +++ b/server/src/features/_realtime/domain/run_instance_pipeline_usecase.ts @@ -3,11 +3,8 @@ import { CallbackStrategyWithEmpty } from "../../../core/controllers/http_contro import { Result } from "../../../core/helpers/result"; import { IPipeline } from "../../../core/models/process_model"; import { ReadByIdDataBaseModelUseCase } from "../../../core/usecases/read_by_id_database_model_usecase"; -import { PipelineValidationModel } from "../../pipelines/models/pipeline_validation_model"; -import { - IProjectInstanceModel, - ProjectInstanceDbModel, -} from "../../project_instance/models/project_instance_database_model"; +import { PipelineValidationModel } from "../../_pipelines/models/pipeline_validation_model"; +import { IProjectInstanceModel, ProjectInstanceDbModel } from "../../projects/models/project_instance_database_model"; import { pipelineRealTimeService } from "../realtime_presentation"; import { PipelineStatusUseCase } from "./pipeline_status_usecase"; diff --git a/server/src/features/realtime/realtime_presentation.ts b/server/src/features/_realtime/realtime_presentation.ts similarity index 100% rename from server/src/features/realtime/realtime_presentation.ts rename to server/src/features/_realtime/realtime_presentation.ts diff --git a/server/src/features/triggers/models/trigger_database_model.ts b/server/src/features/_triggers/models/trigger_database_model.ts similarity index 100% rename from server/src/features/triggers/models/trigger_database_model.ts rename to server/src/features/_triggers/models/trigger_database_model.ts diff --git a/server/src/features/triggers/models/trigger_validation_model.ts b/server/src/features/_triggers/models/trigger_validation_model.ts similarity index 100% rename from server/src/features/triggers/models/trigger_validation_model.ts rename to server/src/features/_triggers/models/trigger_validation_model.ts diff --git a/server/src/features/triggers/triggers_presentation.ts b/server/src/features/_triggers/triggers_presentation.ts similarity index 100% rename from server/src/features/triggers/triggers_presentation.ts rename to server/src/features/_triggers/triggers_presentation.ts diff --git a/server/src/features/datasets/datasets_presentation.ts b/server/src/features/datasets/datasets_presentation.ts new file mode 100644 index 0000000..d86cd4e --- /dev/null +++ b/server/src/features/datasets/datasets_presentation.ts @@ -0,0 +1,17 @@ +import { CrudController } from "../../core/controllers/crud_controller"; +import { CreateDataSetScenario } from "./domain/create_dataset_scanario"; +import { GetDatasetActiveProjectScenario } from "./domain/get_dataset_active_project_scenario"; +import { DatasetDBModel } from "./models/dataset_database_model"; +import { DatasetValidationModel } from "./models/dataset_validation_model"; + +export class DatasetsPresentation extends CrudController { + constructor() { + super({ + url: "datasets", + validationModel: DatasetValidationModel, + databaseModel: DatasetDBModel, + }); + super.post(new CreateDataSetScenario().call); + super.get(new GetDatasetActiveProjectScenario().call); + } +} diff --git a/server/src/features/datasets/domain/create_dataset_scanario.ts b/server/src/features/datasets/domain/create_dataset_scanario.ts new file mode 100644 index 0000000..dc6258b --- /dev/null +++ b/server/src/features/datasets/domain/create_dataset_scanario.ts @@ -0,0 +1,92 @@ +import { ObjectId } from "mongoose"; +import { CallbackStrategyWithValidationModel, ResponseBase } from "../../../core/controllers/http_controller"; +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"; + +export class ProcessWatcherAndDatabaseUpdateService extends TypedEvent> { + databaseId: ObjectId; + constructor(databaseId: ObjectId) { + super(); + this.databaseId = databaseId; + this.on((event) => this.lister(event)); + } + + lister(event: Result) { + event.fold( + async (success) => { + if (success.event == EXEC_EVENT.END) { + const dbModel = await DatasetDBModel.findById(this.databaseId); + if (dbModel !== null) { + dbModel.local_path; + dbModel.processStatus = "end"; + dbModel.processLogs = success.data; + await dbModel.save(); + } + } + }, + async (error) => { + const dbModel = await DatasetDBModel.findById(this.databaseId); + if (dbModel !== null) { + dbModel.processStatus = "error"; + dbModel.processLogs = error.message; + await dbModel.save(); + } + } + ); + } +} +export class CreateDataSetScenario extends CallbackStrategyWithValidationModel { + validationModel: DatasetValidationModel; + call = async (model: DatasetValidationModel): ResponseBase => { + return ( + await new SearchDataBaseModelUseCase(ProjectDBModel).call({ isActive: true }, "no active projects") + ).map(async (project) => { + model.processStatus = "exec"; + model.local_path = project.rootDir; + model.projectId = project._id; + const d = new DatasetDBModel(); + Object.assign(d, model); + await d.save(); + + await new ExecProcessUseCase().call( + `${project.rootDir}/`, + `python3 $PYTHON_BLENDER_PROC --path '${project.rootDir}/${model.name}' --cfg '${JSON.stringify(model)}'`, + new ProcessWatcherAndDatabaseUpdateService(d._id as unknown as ObjectId) + ); + return Result.ok("create dataset ok"); + }); + }; +} +// сохрнать formbuilder result и передать его в python +// { +// "typedataset": ${typedataset:Enum:"ObjectDetection"}, +// "dataset_path": ${DATASET_PATH:string:""}, +// "models":${models:Array:[]}, +// "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}] +// }, +// "scene":{ +// "objects": ${OBJECTS_SCENE:Array:[]}, +// "lights": ${LIGHTS:Array:[]}, +// }, +// "camera_position":{ +// "center_shell": [${CENTER_SHELL_1:number:0}, ${CENTER_SHELL_2:number:0}, ${CENTER_SHELL_3:number:0}], +// "radius_range": [${RADIUS_RANGE_1:number:0.4}, ${RADIUS_RANGE_2:number:1.4}], +// "elevation_range": [${ELEVATION_RANGE_1:number:10}, ${ELEVATION_RANGE_2:number:90}] +// }, +// "generation":{ +// "n_cam_pose": ${N_CAM_POSE:number:5}, +// "n_sample_on_pose": ${N_SAMPLE_ON_POSE:number:3}, +// "n_series": ${N_SERIES:number:100}, +// "image_format": ${image_format:Enum:"jpg"}, +// "image_size_wh": [${IMAGE_SIZE_WH_1:number:640}, ${IMAGE_SIZE_WH_2:number:480}] +// } +// } diff --git a/server/src/features/datasets/domain/get_dataset_active_project_scenario.ts b/server/src/features/datasets/domain/get_dataset_active_project_scenario.ts new file mode 100644 index 0000000..081df22 --- /dev/null +++ b/server/src/features/datasets/domain/get_dataset_active_project_scenario.ts @@ -0,0 +1,15 @@ +import { CallbackStrategyWithEmpty, ResponseBase } from "../../../core/controllers/http_controller"; +import { Result } from "../../../core/helpers/result"; +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"; + +export class GetDatasetActiveProjectScenario extends CallbackStrategyWithEmpty { + call = async (): ResponseBase => { + return ( + await new SearchDataBaseModelUseCase(ProjectDBModel).call({ isActive: true }, "no active projects") + ).map(async (project) => { + return Result.ok(await DatasetDBModel.find({ projectId: project._id })); + }); + }; +} diff --git a/server/src/features/datasets/models/dataset_database_model.ts b/server/src/features/datasets/models/dataset_database_model.ts new file mode 100644 index 0000000..27ec312 --- /dev/null +++ b/server/src/features/datasets/models/dataset_database_model.ts @@ -0,0 +1,37 @@ +import { Mongoose, Schema, model } from "mongoose"; +import { IDatasetModel } from "./dataset_validation_model"; +import { projectSchema } from "../../_projects/models/project_database_model"; + +export const DatasetSchema = new Schema({ + name: { + type: String, + }, + local_path: { + type: String, + }, + dataSetObjects: { + type: Array, + of: String, + }, + formBuilder: { + type: Schema.Types.Mixed, + of: String, + }, + processStatus: { + type: String, + default: "none", + }, + projectId: { + type: Schema.Types.ObjectId, + ref: projectSchema, + autopopulate: false, + default: null, + }, + processLogs: { + type: String, + }, +}).plugin(require("mongoose-autopopulate")); + +export const datasetSchema = "Dataset"; + +export const DatasetDBModel = model(datasetSchema, DatasetSchema); diff --git a/server/src/features/datasets/models/dataset_validation_model.ts b/server/src/features/datasets/models/dataset_validation_model.ts new file mode 100644 index 0000000..e9a365d --- /dev/null +++ b/server/src/features/datasets/models/dataset_validation_model.ts @@ -0,0 +1,34 @@ +import { Type } from "class-transformer"; +import { IsArray, IsString, ValidateNested } from "class-validator"; + +export class FormBuilderValidationModel { + @IsString() + public result: string; + @IsString() + public context: string; + @IsArray() + public form: []; +} + +export interface IDatasetModel { + name: string; + local_path: string; + dataSetObjects: string[]; + formBuilder: FormBuilderValidationModel; + processLogs: string; + processStatus: string; +} + +export class DatasetValidationModel implements IDatasetModel { + @IsString() + public name: string; + @IsArray() + public dataSetObjects: string[]; + @ValidateNested() + @Type(() => FormBuilderValidationModel) + public formBuilder: FormBuilderValidationModel; + public local_path: string; + public processStatus: string; + public projectId: string; + public processLogs: string; +} diff --git a/server/src/features/project_instance/domain/create_new_project_scenario.ts b/server/src/features/project_instance/domain/create_new_project_scenario.ts deleted file mode 100644 index 76023b1..0000000 --- a/server/src/features/project_instance/domain/create_new_project_scenario.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { App } from "../../../core/controllers/app"; -import { Result } from "../../../core/helpers/result"; -import { CreateDataBaseModelUseCase } from "../../../core/usecases/create_database_model_usecase"; -import { CreateFolderUseCase } from "../../../core/usecases/create_folder_usecase"; -import { pipelineRealTimeService } from "../../realtime/realtime_presentation"; -import { ProjectInstanceDbModel } from "../models/project_instance_database_model"; -import { ProjectInstanceValidationModel } from "../models/project_instance_validation_model"; -import { v4 as uuidv4 } from "uuid"; -import { SetActiveProjectScenario } from "./set_active_project_use_scenario"; - -export class CreateNewProjectInstanceScenario { - call = async (): Promise> => { - try { - // (await new SetActiveProjectScenario().call(id)).map(() => { - // return Result.ok({ status: "ok" }); - // }); - } catch (error) { - console.log(error); - return Result.error(error as Error); - } - }; -} diff --git a/server/src/features/project_instance/domain/robossembler_assets_network_mapper_scenario.ts b/server/src/features/project_instance/domain/robossembler_assets_network_mapper_scenario.ts deleted file mode 100644 index ead9008..0000000 --- a/server/src/features/project_instance/domain/robossembler_assets_network_mapper_scenario.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { CallbackStrategyWithEmpty, ResponseBase } from "../../../core/controllers/http_controller"; -import { Result } from "../../../core/helpers/result"; -import { RobossemblerAssets } from "../../../core/models/robossembler_assets"; -import { StaticFiles } from "../../../core/models/static_files"; -import { ReadingJsonFileAndConvertingToInstanceClassScenario } from "../../../core/scenarios/read_file_and_json_to_plain_instance_class_scenario"; -import { GetServerAddressUseCase } from "../../../core/usecases/get_server_address_usecase"; -import { PipelineStatusUseCase } from "../../realtime/domain/pipeline_status_usecase"; - -export class RobossemblerAssetsNetworkMapperScenario extends CallbackStrategyWithEmpty { - async call(): ResponseBase { - try { - const result = await new PipelineStatusUseCase().call(); - - return await result.map(async (activeInstanceModel) => { - return ( - await new ReadingJsonFileAndConvertingToInstanceClassScenario(RobossemblerAssets).call( - `${activeInstanceModel.path}${StaticFiles.robossembler_assets}` - ) - ).map((robossemblerAssets) => { - return new GetServerAddressUseCase().call().map((address) => { - return Result.ok( - robossemblerAssets.convertLocalPathsToServerPaths( - `${address}/${activeInstanceModel.rootDir.pathNormalize()}` - ) - ); - }); - }); - }); - } catch (error) { - return Result.error(error); - } - } -} diff --git a/server/src/features/project_instance/project_instance_presentation.ts b/server/src/features/project_instance/project_instance_presentation.ts deleted file mode 100644 index 5732113..0000000 --- a/server/src/features/project_instance/project_instance_presentation.ts +++ /dev/null @@ -1,49 +0,0 @@ -import { CrudController } from "../../core/controllers/crud_controller"; -import { CoreHttpController } from "../../core/controllers/http_controller"; -import { RobossemblerAssets } from "../../core/models/robossembler_assets"; - -import { CreateNewProjectInstanceScenario } from "./domain/create_new_project_scenario"; -import { RobossemblerAssetsNetworkMapperScenario } from "./domain/robossembler_assets_network_mapper_scenario"; -import { SaveActiveSceneScenario } from "./domain/save_active_scene_scenario"; -import { SetActiveProjectScenario } from "./domain/set_active_project_use_scenario"; -import { UploadCadFileToProjectScenario } from "./domain/upload_file_to_to_project_scenario"; -import { ProjectInstanceDbModel } from "./models/project_instance_database_model"; -import { ProjectInstanceValidationModel } from "./models/project_instance_validation_model"; - -export class ProjectInstancePresentation extends CrudController< - ProjectInstanceValidationModel, - typeof ProjectInstanceDbModel -> { - constructor() { - super({ - validationModel: ProjectInstanceValidationModel, - url: "project_instance", - databaseModel: ProjectInstanceDbModel, - }); - - super.post(new CreateNewProjectInstanceScenario().call); - - this.subRoutes.push({ - method: "POST", - subUrl: "set/active/project", - fn: new SetActiveProjectScenario(), - }); - - this.subRoutes.push({ - method: "POST", - subUrl: "upload", - fn: new UploadCadFileToProjectScenario(), - }); - } -} - -export class RobossemblerAssetsPresentation extends CoreHttpController { - constructor() { - super({ - url: "robossembler_assets", - validationModel: RobossemblerAssets, - }); - super.get(new RobossemblerAssetsNetworkMapperScenario().call); - super.post(new SaveActiveSceneScenario().call); - } -} diff --git a/server/src/features/projects/domain/create_new_project_scenario.ts b/server/src/features/projects/domain/create_new_project_scenario.ts new file mode 100644 index 0000000..b2ee76c --- /dev/null +++ b/server/src/features/projects/domain/create_new_project_scenario.ts @@ -0,0 +1,34 @@ +import { App } from "../../../core/controllers/app"; +import { Result } from "../../../core/helpers/result"; +import { v4 as uuidv4 } from "uuid"; +import { IsString } from "class-validator"; +import { ProjectDBModel } from "../../_projects/models/project_database_model"; +import { CreateDataBaseModelUseCase } from "../../../core/usecases/create_database_model_usecase"; +import { CreateFolderUseCase } from "../../../core/usecases/create_folder_usecase"; + +export class ProjectValidationModel { + @IsString() + description: string; +} +export class CreateNewProjectInstanceScenario { + call = async (model: ProjectValidationModel): Promise> => { + try { + const projectFolder = uuidv4(); + return (await new CreateFolderUseCase().call(App.staticFilesStoreDir() + projectFolder)).map(async (_) => { + for await (const el of await ProjectDBModel.find({ isActive: true })) { + el.isActive = false; + await el.save(); + } + + const projectDbModel = await new ProjectDBModel({ + isActive: true, + rootDir: App.staticFilesStoreDir() + projectFolder, + description: model.description, + }).save(); + return Result.ok({ id: projectDbModel._id }); + }); + } catch (error) { + return Result.error(error as Error); + } + }; +} diff --git a/server/src/features/projects/domain/get_active_project_scenario.ts b/server/src/features/projects/domain/get_active_project_scenario.ts new file mode 100644 index 0000000..ecf4b6b --- /dev/null +++ b/server/src/features/projects/domain/get_active_project_scenario.ts @@ -0,0 +1,12 @@ +import { CallbackStrategyWithEmpty, ResponseBase } from "../../../core/controllers/http_controller"; +import { Result } from "../../../core/helpers/result"; +import { SearchDataBaseModelUseCase } from "../../../core/usecases/search_database_model_usecase"; +import { IProjectModel, ProjectDBModel } from "../../_projects/models/project_database_model"; + +export class GetActiveProjectScenario extends CallbackStrategyWithEmpty { + async call(): ResponseBase { + return ( + await new SearchDataBaseModelUseCase(ProjectDBModel).call({ isActive: true }, "no active projects") + ).map((model) => Result.ok({ id: model._id })); + } +} diff --git a/server/src/features/projects/domain/robossembler_assets_network_mapper_scenario.ts b/server/src/features/projects/domain/robossembler_assets_network_mapper_scenario.ts new file mode 100644 index 0000000..c788900 --- /dev/null +++ b/server/src/features/projects/domain/robossembler_assets_network_mapper_scenario.ts @@ -0,0 +1,33 @@ +import { CallbackStrategyWithEmpty, ResponseBase } from "../../../core/controllers/http_controller"; +import { Result } from "../../../core/helpers/result"; +import { RobossemblerAssets } from "../../../core/models/robossembler_assets"; +import { StaticFiles } from "../../../core/models/static_files"; +import { ReadingJsonFileAndConvertingToInstanceClassScenario } from "../../../core/scenarios/read_file_and_json_to_plain_instance_class_scenario"; +import { GetServerAddressUseCase } from "../../../core/usecases/get_server_address_usecase"; +import { ProjectDBModel } from "../../_projects/models/project_database_model"; + +export class RobossemblerAssetsNetworkMapperScenario extends CallbackStrategyWithEmpty { + async call(): ResponseBase { + const projectDbModel = await ProjectDBModel.findOne({ isActive: true }); + if (projectDbModel === null) { + return Result.error("is dont active projects"); + } + const { rootDir } = projectDbModel; + + return new GetServerAddressUseCase().call().map(async (address) => + ( + await new ReadingJsonFileAndConvertingToInstanceClassScenario(RobossemblerAssets).call( + rootDir + StaticFiles.assets + ) + ).map((model) => { + return Result.ok( + model.convertLocalPathsToServerPaths( + `${address}/${ + rootDir.match(new RegExp(/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/gm))[0] + }/assets` + ) + ); + }) + ); + } +} diff --git a/server/src/features/project_instance/domain/save_active_scene_scenario.ts b/server/src/features/projects/domain/save_active_scene_scenario.ts similarity index 94% rename from server/src/features/project_instance/domain/save_active_scene_scenario.ts rename to server/src/features/projects/domain/save_active_scene_scenario.ts index 6ab753a..2f7b2fa 100644 --- a/server/src/features/project_instance/domain/save_active_scene_scenario.ts +++ b/server/src/features/projects/domain/save_active_scene_scenario.ts @@ -4,7 +4,7 @@ import { RobossemblerAssets } from "../../../core/models/robossembler_assets"; import { StaticFiles } from "../../../core/models/static_files"; import { ReadingJsonFileAndConvertingToInstanceClassScenario } from "../../../core/scenarios/read_file_and_json_to_plain_instance_class_scenario"; import { WriteFileSystemFileUseCase } from "../../../core/usecases/write_file_system_file_usecase"; -import { PipelineStatusUseCase } from "../../realtime/domain/pipeline_status_usecase"; +import { PipelineStatusUseCase } from "../../_realtime/domain/pipeline_status_usecase"; export class SaveActiveSceneScenario extends CallbackStrategyWithValidationModel { validationModel: RobossemblerAssets = new RobossemblerAssets(); diff --git a/server/src/features/project_instance/domain/set_active_project_use_scenario.ts b/server/src/features/projects/domain/set_active_project_use_scenario.ts similarity index 50% rename from server/src/features/project_instance/domain/set_active_project_use_scenario.ts rename to server/src/features/projects/domain/set_active_project_use_scenario.ts index 2d18dc8..5bc82d8 100644 --- a/server/src/features/project_instance/domain/set_active_project_use_scenario.ts +++ b/server/src/features/projects/domain/set_active_project_use_scenario.ts @@ -12,24 +12,31 @@ export class SetActiveProjectScenario extends CallbackStrategyWithIdQuery { idValidationExpression = new MongoIdValidation(); async call(id: string): ResponseBase { - const result = await new ReadByIdDataBaseModelUseCase(ProjectInstanceDbModel).call(id); - // id + try { + const result = await new ReadByIdDataBaseModelUseCase(ProjectInstanceDbModel).call(id); + // id - if (result.isFailure()) { - return result.forward(); - } - const model = result.value; + if (result.isFailure()) { + return result.forward(); + } + const model = result.value; - return await ( - await new CreateFolderUseCase().call(App.staticFilesStoreDir() + model.rootDir) - ).map(async () => { - model.isActive = true; - return (await new UpdateDataBaseModelUseCase(ProjectInstanceDbModel).call(model)).map(async (el) => { - // TODO(IDONTSUDO): move it to a separate UseCase - await ProjectInstanceDbModel.updateMany({ _id: { $ne: el._id }, isActive: { $eq: true } }, { isActive: false }); - await new SetLastActivePipelineToRealTimeServiceScenario().call(); - return Result.ok(`project ${id} is active`); + return await ( + await new CreateFolderUseCase().call(App.staticFilesStoreDir() + model.rootDir) + ).map(async () => { + model.isActive = true; + return (await new UpdateDataBaseModelUseCase(ProjectInstanceDbModel).call(model)).map(async (el) => { + // TODO(IDONTSUDO): move it to a separate UseCase + await ProjectInstanceDbModel.updateMany( + { _id: { $ne: el._id }, isActive: { $eq: true } }, + { isActive: false } + ); + await new SetLastActivePipelineToRealTimeServiceScenario().call(); + return Result.ok(`project ${id} is active`); + }); }); - }); + } catch (error) { + return Result.error("SetActiveProjectScenario error:" + String(error)); + } } } diff --git a/server/src/features/project_instance/domain/upload_file_to_to_project_scenario.ts b/server/src/features/projects/domain/upload_file_to_to_project_scenario.ts similarity index 50% rename from server/src/features/project_instance/domain/upload_file_to_to_project_scenario.ts rename to server/src/features/projects/domain/upload_file_to_to_project_scenario.ts index deb06e8..ada5d73 100644 --- a/server/src/features/project_instance/domain/upload_file_to_to_project_scenario.ts +++ b/server/src/features/projects/domain/upload_file_to_to_project_scenario.ts @@ -6,32 +6,28 @@ import { CreateDataBaseModelUseCase } from "../../../core/usecases/create_databa import { CreateFileUseCase } from "../../../core/usecases/create_file_usecase"; import { CreateFolderUseCase } from "../../../core/usecases/create_folder_usecase"; import { MongoIdValidation } from "../../../core/validations/mongo_id_validation"; -import { ProjectInstanceDbModel } from "../models/project_instance_database_model"; +import { IProjectInstanceModel, ProjectInstanceDbModel } from "../models/project_instance_database_model"; import { ProjectInstanceValidationModel } from "../models/project_instance_validation_model"; import { v4 as uuidv4 } from "uuid"; import { SetActiveProjectScenario } from "./set_active_project_use_scenario"; +import { ReadByIdDataBaseModelUseCase } from "../../../core/usecases/read_by_id_database_model_usecase"; +import { ProjectDBModel } from "../../_projects/models/project_database_model"; +import { ExecProcessUseCase } from "../../../core/usecases/exec_process_usecase"; export class UploadCadFileToProjectScenario extends CallbackStrategyWithFileUpload { - checkingFileExpression: RegExp = RegExp(".FCStd"); + checkingFileExpression: RegExp = new RegExp(".FCStd"); idValidationExpression = new MongoIdValidation(); - async call(file: IFile, id: string, description: string): ResponseBase { - const folderName = uuidv4() + "/"; - const model = new ProjectInstanceValidationModel(); - model["project"] = id; - model["description"] = description; - model["rootDir"] = folderName; - model["isActive"] = true; - return (await new CreateFolderUseCase().call(App.staticFilesStoreDir() + folderName)).map(async () => - (await new CreateDataBaseModelUseCase(ProjectInstanceDbModel).call(model)).map(async (databaseModel) => - (await new SetActiveProjectScenario().call(databaseModel.id)).map(async () => - (await new CreateFileUseCase().call(App.staticFilesStoreDir() + folderName + file.name, file.data)).map( - () => { - return Result.ok("ok"); - } - ) + async call(file: IFile, id: string): ResponseBase { + return (await new ReadByIdDataBaseModelUseCase(ProjectDBModel).call(id)).map( + async (databaseModel) => + (await new CreateFileUseCase().call(`${databaseModel.rootDir}/${file.name}`, file.data)).map( + async () => + await new ExecProcessUseCase().call( + `${databaseModel.rootDir}/`, + `python3 $PYTHON_BLENDER --path '${databaseModel.rootDir}/assets/'` + ) ) - ) ); } } diff --git a/server/src/features/project_instance/models/project_instance_database_model.ts b/server/src/features/projects/models/project_instance_database_model.ts similarity index 73% rename from server/src/features/project_instance/models/project_instance_database_model.ts rename to server/src/features/projects/models/project_instance_database_model.ts index b0111bc..604f8b9 100644 --- a/server/src/features/project_instance/models/project_instance_database_model.ts +++ b/server/src/features/projects/models/project_instance_database_model.ts @@ -1,5 +1,5 @@ import { Schema, model } from "mongoose"; -import { IProjectModel, projectSchema } from "../../projects/models/project_database_model"; +import { IProjectModel, projectSchema } from "../../_projects/models/project_database_model"; export interface IProjectInstanceModel { _id: string; @@ -10,12 +10,6 @@ export interface IProjectInstanceModel { } export const ProjectInstanceSchema = new Schema({ - project: { - type: Schema.Types.ObjectId, - ref: projectSchema, - autopopulate: true, - default: null, - }, description: { type: String, }, diff --git a/server/src/features/project_instance/models/project_instance_validation_model.ts b/server/src/features/projects/models/project_instance_validation_model.ts similarity index 85% rename from server/src/features/project_instance/models/project_instance_validation_model.ts rename to server/src/features/projects/models/project_instance_validation_model.ts index cb3149a..ef7b6b0 100644 --- a/server/src/features/project_instance/models/project_instance_validation_model.ts +++ b/server/src/features/projects/models/project_instance_validation_model.ts @@ -1,9 +1,6 @@ import { IsMongoId, IsOptional, IsString } from "class-validator"; export class ProjectInstanceValidationModel { - @IsMongoId() - public project: string; - @IsString() public description: string; diff --git a/server/src/features/projects/projects_presentation.ts b/server/src/features/projects/projects_presentation.ts index 253bf2c..1fa0714 100644 --- a/server/src/features/projects/projects_presentation.ts +++ b/server/src/features/projects/projects_presentation.ts @@ -1,13 +1,41 @@ import { CrudController } from "../../core/controllers/crud_controller"; -import { ProjectDBModel } from "./models/project_database_model"; -import { ProjectValidationModel } from "./models/project_validation_model"; +import { ProjectDBModel } from "../_projects/models/project_database_model"; +import { CreateNewProjectInstanceScenario } from "./domain/create_new_project_scenario"; +import { GetActiveProjectScenario } from "./domain/get_active_project_scenario"; +import { RobossemblerAssetsNetworkMapperScenario } from "./domain/robossembler_assets_network_mapper_scenario"; +import { SetActiveProjectScenario } from "./domain/set_active_project_use_scenario"; +import { UploadCadFileToProjectScenario } from "./domain/upload_file_to_to_project_scenario"; +import { ProjectInstanceValidationModel as ProjectsValidationModel } from "./models/project_instance_validation_model"; -export class ProjectsPresentation extends CrudController { +export class ProjectsPresentation extends CrudController { constructor() { super({ - url: "project", - validationModel: ProjectValidationModel, + validationModel: ProjectsValidationModel, + url: "projects", databaseModel: ProjectDBModel, }); + + super.post(new CreateNewProjectInstanceScenario().call); + + this.subRoutes.push({ + method: "POST", + subUrl: "set/active/project", + fn: new SetActiveProjectScenario(), + }); + this.subRoutes.push({ + method: "GET", + subUrl: "get/active/project/id", + fn: new GetActiveProjectScenario(), + }); + this.subRoutes.push({ + method: "POST", + subUrl: "upload", + fn: new UploadCadFileToProjectScenario(), + }); + this.subRoutes.push({ + method: "GET", + subUrl: "assets", + fn: new RobossemblerAssetsNetworkMapperScenario(), + }); } } diff --git a/server/src/main.ts b/server/src/main.ts index f2682ca..6591d87 100644 --- a/server/src/main.ts +++ b/server/src/main.ts @@ -3,12 +3,10 @@ import { App } from "./core/controllers/app"; import { SocketSubscriber } from "./core/controllers/socket_controller"; import { extensions } from "./core/extensions/extensions"; import { httpRoutes } from "./core/controllers/routes"; -import { pipelineRealTimeService } from "./features/realtime/realtime_presentation"; -import { main } from "./p"; +import { pipelineRealTimeService } from "./features/_realtime/realtime_presentation"; extensions(); const socketSubscribers = [new SocketSubscriber(pipelineRealTimeService, "realtime")]; new App(httpRoutes, socketSubscribers).listen(); -main(); diff --git a/server/test/model/mock_pipelines.ts b/server/test/model/mock_pipelines.ts index 3dd865d..34e73c2 100644 --- a/server/test/model/mock_pipelines.ts +++ b/server/test/model/mock_pipelines.ts @@ -1,6 +1,6 @@ import { EXEC_TYPE } from "../../src/core/models/exec_error_model"; import { IPipeline, IssueType, StackGenerateType } from "../../src/core/models/process_model"; -import { TriggerType } from "../../src/features/triggers/models/trigger_database_model"; +import { TriggerType } from "../../src/features/_triggers/models/trigger_database_model"; export const mockSimplePipeline: IPipeline[] = [ { diff --git a/server/test/services/trigger_service_test.ts b/server/test/services/trigger_service_test.ts index 970168c..1013d44 100644 --- a/server/test/services/trigger_service_test.ts +++ b/server/test/services/trigger_service_test.ts @@ -1,7 +1,7 @@ import { EventsFileChanger, MetaDataFileManagerModel } from "../../src/core/models/meta_data_file_manager_model"; import { TriggerService } from "../../src/core/services/trigger_service"; -import { TriggerType } from "../../src/features/triggers/models/trigger_database_model"; +import { TriggerType } from "../../src/features/_triggers/models/trigger_database_model"; import { assert } from "../test"; abstract class TriggerTest { abstract test(): Promise; diff --git a/server/test/test.ts b/server/test/test.ts index d0487c5..977850e 100644 --- a/server/test/test.ts +++ b/server/test/test.ts @@ -14,7 +14,7 @@ import { UpdateDataBaseModelUseCaseTest } from "./usecases/update_database_model import { PaginationDataBaseModelUseCaseTest } from "./usecases/pagination_database_model_usecase_test"; import { extensions } from "../src/core/extensions/extensions"; import { CrudControllerTest } from "./controllers/crud_controller_test"; -import { TriggerPresentation } from "../src/features/triggers/triggers_presentation"; +import { TriggerPresentation } from "../src/features/_triggers/triggers_presentation"; import { App, Environment, ServerStatus } from "../src/core/controllers/app"; import { httpRoutes } from "../src/core/controllers/routes"; import { DataBaseConnectUseCase } from "../src/core/usecases/database_connect_usecase"; diff --git a/ui/package-lock.json b/ui/package-lock.json index d2ada4c..656fe65 100644 --- a/ui/package-lock.json +++ b/ui/package-lock.json @@ -26,15 +26,22 @@ "mobx-react-lite": "^4.0.4", "mobx-store-inheritance": "^1.0.6", "react": "^18.2.0", + "react-accessible-treeview": "^2.8.3", + "react-dnd": "^16.0.1", + "react-dnd-html5-backend": "^16.0.1", "react-dom": "^18.2.0", "react-i18next": "^13.3.1", "react-infinite-scroll-component": "^6.1.0", "react-router-dom": "^6.18.0", "react-scripts": "5.0.1", "reflect-metadata": "^0.1.13", + "rete-connection-plugin": "^2.0.0", + "rete-react-plugin": "^2.0.4", + "rete-render-utils": "^2.0.1", "sass": "^1.66.1", "serve": "^14.2.1", "socket.io-client": "^4.7.2", + "styled-components": "^6.1.8", "three": "^0.159.0", "three-stdlib": "^2.28.9", "three-transform-controls": "^1.0.4", @@ -42,7 +49,8 @@ "typescript": "^4.9.5", "urdf-loader": "^0.12.1", "uuid": "^9.0.1", - "web-vitals": "^2.1.4" + "web-vitals": "^2.1.4", + "xml-formatter": "^3.6.2" }, "devDependencies": { "@types/three": "^0.158.3" @@ -2503,6 +2511,24 @@ "node": ">=10" } }, + "node_modules/@emotion/is-prop-valid": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.2.1.tgz", + "integrity": "sha512-61Mf7Ufx4aDxx1xlDeOm8aFFigGHE4z+0sKCa+IHCeZKiyP9RLD0Mmx7m8b9/Cf37f7NAvQOOJAbQQGVr5uERw==", + "dependencies": { + "@emotion/memoize": "^0.8.1" + } + }, + "node_modules/@emotion/memoize": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.1.tgz", + "integrity": "sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA==" + }, + "node_modules/@emotion/unitless": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.8.0.tgz", + "integrity": "sha512-VINS5vEYAscRl2ZUDiT3uMPlrFQupiKgHz5AA4bCH1miKBg4qtwkim1qPmJj/4WG6TreYMY111rEFsjupcOKHw==" + }, "node_modules/@eslint-community/eslint-utils": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", @@ -3232,6 +3258,21 @@ "react-dom": ">=16.9.0" } }, + "node_modules/@react-dnd/asap": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@react-dnd/asap/-/asap-5.0.2.tgz", + "integrity": "sha512-WLyfoHvxhs0V9U+GTsGilGgf2QsPl6ZZ44fnv0/b8T3nQyvzxidxsg/ZltbWssbsRDlYW8UKSQMTGotuTotZ6A==" + }, + "node_modules/@react-dnd/invariant": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@react-dnd/invariant/-/invariant-4.0.2.tgz", + "integrity": "sha512-xKCTqAK/FFauOM9Ta2pswIyT3D8AQlfrYdOi/toTPEhqCuAs1v5tcJ3Y08Izh1cJ5Jchwy9SeAXmMg6zrKs2iw==" + }, + "node_modules/@react-dnd/shallowequal": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@react-dnd/shallowequal/-/shallowequal-4.0.2.tgz", + "integrity": "sha512-/RVXdLvJxLg4QKvMoM5WlwNR9ViO9z8B/qPcc+C0Sa/teJY7QG7kJ441DwzOjMYEY7GmU4dj5EcGHIkKZiQZCA==" + }, "node_modules/@remix-run/router": { "version": "1.15.0", "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.15.0.tgz", @@ -4048,6 +4089,11 @@ "integrity": "sha512-pXNfAD3KHOdif9EQXZ9deK82HVNaXP5ZIF5RP2QG6OQFNTaY2YIetfrE9t528vEreGQvEPRDDc8muaoYeK0SxQ==", "dev": true }, + "node_modules/@types/stylis": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@types/stylis/-/stylis-4.2.0.tgz", + "integrity": "sha512-n4sx2bqL0mW1tvDf/loQ+aMX7GQD3lc3fkCMC55VFNDu/vBOabO+LTIeXKM14xK0ppk5TUGcWRjiSpIlUpghKw==" + }, "node_modules/@types/testing-library__jest-dom": { "version": "5.14.9", "resolved": "https://registry.npmjs.org/@types/testing-library__jest-dom/-/testing-library__jest-dom-5.14.9.tgz", @@ -5635,6 +5681,14 @@ "node": ">= 6" } }, + "node_modules/camelize": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/camelize/-/camelize-1.0.1.tgz", + "integrity": "sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/caniuse-api": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz", @@ -6244,6 +6298,14 @@ "postcss": "^8.4" } }, + "node_modules/css-color-keywords": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/css-color-keywords/-/css-color-keywords-1.0.0.tgz", + "integrity": "sha512-FyyrDHZKEjXDpNJYvVsV960FiqQyXc/LlYmsxl2BcdMb2WPx0OGRVgTg55rPSyLSNMqP52R9r8geSp7apN3Ofg==", + "engines": { + "node": ">=4" + } + }, "node_modules/css-declaration-sorter": { "version": "6.4.1", "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-6.4.1.tgz", @@ -6434,6 +6496,16 @@ "resolved": "https://registry.npmjs.org/css-select-base-adapter/-/css-select-base-adapter-0.1.1.tgz", "integrity": "sha512-jQVeeRG70QI08vSTwf1jHxp74JoZsr2XSgETae8/xC8ovSnL2WF87GTLO86Sbwdt2lK4Umg4HnnwMO4YF3Ce7w==" }, + "node_modules/css-to-react-native": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/css-to-react-native/-/css-to-react-native-3.2.0.tgz", + "integrity": "sha512-e8RKaLXMOFii+02mOlqwjbD00KSEKqblnpO9e++1aXS1fPQOpS1YoqdVHBqPjHNoxeF2mimzVqawm2KCbEdtHQ==", + "dependencies": { + "camelize": "^1.0.0", + "css-color-keywords": "^1.0.0", + "postcss-value-parser": "^4.0.2" + } + }, "node_modules/css-tree": { "version": "1.0.0-alpha.37", "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.37.tgz", @@ -6906,6 +6978,16 @@ "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==" }, + "node_modules/dnd-core": { + "version": "16.0.1", + "resolved": "https://registry.npmjs.org/dnd-core/-/dnd-core-16.0.1.tgz", + "integrity": "sha512-HK294sl7tbw6F6IeuK16YSBUoorvHpY8RHO+9yFfaJyCDVb6n7PRcezrOEOa2SBCqiYpemh5Jx20ZcjKdFAVng==", + "dependencies": { + "@react-dnd/asap": "^5.0.1", + "@react-dnd/invariant": "^4.0.1", + "redux": "^4.2.0" + } + }, "node_modules/dns-packet": { "version": "5.6.1", "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.6.1.tgz", @@ -8980,7 +9062,6 @@ "version": "3.3.2", "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", - "peer": true, "dependencies": { "react-is": "^16.7.0" } @@ -14375,6 +14456,17 @@ "node": ">=0.10.0" } }, + "node_modules/react-accessible-treeview": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/react-accessible-treeview/-/react-accessible-treeview-2.8.3.tgz", + "integrity": "sha512-taDTIYZ6p96/zIhJBUKvyGTXcInudatP/9fwKG0BW+VRf1PmU5hOT2FkDovDKzSwj2VSOj1PRx+E6ojhOA+2xA==", + "peerDependencies": { + "classnames": "^2.2.6", + "prop-types": "^15.7.2", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, "node_modules/react-app-polyfill": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/react-app-polyfill/-/react-app-polyfill-3.0.0.tgz", @@ -14438,6 +14530,43 @@ "node": ">= 12.13.0" } }, + "node_modules/react-dnd": { + "version": "16.0.1", + "resolved": "https://registry.npmjs.org/react-dnd/-/react-dnd-16.0.1.tgz", + "integrity": "sha512-QeoM/i73HHu2XF9aKksIUuamHPDvRglEwdHL4jsp784BgUuWcg6mzfxT0QDdQz8Wj0qyRKx2eMg8iZtWvU4E2Q==", + "dependencies": { + "@react-dnd/invariant": "^4.0.1", + "@react-dnd/shallowequal": "^4.0.1", + "dnd-core": "^16.0.1", + "fast-deep-equal": "^3.1.3", + "hoist-non-react-statics": "^3.3.2" + }, + "peerDependencies": { + "@types/hoist-non-react-statics": ">= 3.3.1", + "@types/node": ">= 12", + "@types/react": ">= 16", + "react": ">= 16.14" + }, + "peerDependenciesMeta": { + "@types/hoist-non-react-statics": { + "optional": true + }, + "@types/node": { + "optional": true + }, + "@types/react": { + "optional": true + } + } + }, + "node_modules/react-dnd-html5-backend": { + "version": "16.0.1", + "resolved": "https://registry.npmjs.org/react-dnd-html5-backend/-/react-dnd-html5-backend-16.0.1.tgz", + "integrity": "sha512-Wu3dw5aDJmOGw8WjH1I1/yTH+vlXEL4vmjk5p+MHxP8HuHJS1lAGeIdG/hze1AvNeXWo/JgULV87LyQOr+r5jw==", + "dependencies": { + "dnd-core": "^16.0.1" + } + }, "node_modules/react-dom": { "version": "18.2.0", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", @@ -14671,6 +14800,14 @@ "node": ">=8" } }, + "node_modules/redux": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/redux/-/redux-4.2.1.tgz", + "integrity": "sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w==", + "dependencies": { + "@babel/runtime": "^7.9.2" + } + }, "node_modules/reflect-metadata": { "version": "0.1.14", "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.14.tgz", @@ -14953,6 +15090,69 @@ "node": ">=10" } }, + "node_modules/rete": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/rete/-/rete-2.0.3.tgz", + "integrity": "sha512-/xzcyEBhVXhMZVZHElnYaLKOmTEuwlnul9Wfjvxw5sdl/+6Nqn2nyqIaW4koefrFpIWZy9aitnjnP3zeCMVDuw==", + "hasInstallScript": true, + "peer": true, + "dependencies": { + "@babel/runtime": "^7.21.0" + } + }, + "node_modules/rete-area-plugin": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/rete-area-plugin/-/rete-area-plugin-2.0.2.tgz", + "integrity": "sha512-pMRNRl5jNFwsEcaIWvaHgB9QV4CrqfGipEPpxPrbS1oQXezDJ18sbELU68WceJ534OMAcu/9XiN2VLpGbRWoog==", + "peer": true, + "dependencies": { + "@babel/runtime": "^7.21.0" + }, + "peerDependencies": { + "rete": "^2.0.0" + } + }, + "node_modules/rete-connection-plugin": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/rete-connection-plugin/-/rete-connection-plugin-2.0.1.tgz", + "integrity": "sha512-KE1IcjeOQtHgkByODtWS5hgRJDGhR3Z9sZyJAEd7YMgI6o+KUIflcNjbkvhJvPeIAv6WlEAh7ZkwdLhF9bkr4w==", + "dependencies": { + "@babel/runtime": "^7.21.0" + }, + "peerDependencies": { + "rete": "^2.0.1", + "rete-area-plugin": "^2.0.0" + } + }, + "node_modules/rete-react-plugin": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/rete-react-plugin/-/rete-react-plugin-2.0.5.tgz", + "integrity": "sha512-xoui2+Mv6iqpRTxccAu3MZv3+l5LYk4AmtqGWEqlCIwZjplrsAoVeOLYq235spwf+vd3ujzapnycEzYF9aj3cA==", + "dependencies": { + "@babel/runtime": "^7.21.0", + "usehooks-ts": "^2.9.1" + }, + "peerDependencies": { + "react": "^16.8.6 || ^17 || ^18", + "react-dom": "^16.8.6 || ^17 || ^18", + "rete": "^2.0.1", + "rete-area-plugin": "^2.0.0", + "rete-render-utils": "^2.0.0", + "styled-components": "^5.3.6 || ^6" + } + }, + "node_modules/rete-render-utils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/rete-render-utils/-/rete-render-utils-2.0.2.tgz", + "integrity": "sha512-f4kj+dFL5QrebOkjCdwi8htHteDFbKyqrVdFDToEUvGuGod1sdLeKxOPBOhwyYDB4Zxd3Cq84I93vD2etrTL9g==", + "dependencies": { + "@babel/runtime": "^7.21.0" + }, + "peerDependencies": { + "rete": "^2.0.0", + "rete-area-plugin": "^2.0.0" + } + }, "node_modules/retry": { "version": "0.13.1", "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", @@ -15535,8 +15735,7 @@ "node_modules/shallowequal": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz", - "integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==", - "peer": true + "integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==" }, "node_modules/shebang-command": { "version": "2.0.0", @@ -16137,6 +16336,70 @@ "webpack": "^5.0.0" } }, + "node_modules/styled-components": { + "version": "6.1.8", + "resolved": "https://registry.npmjs.org/styled-components/-/styled-components-6.1.8.tgz", + "integrity": "sha512-PQ6Dn+QxlWyEGCKDS71NGsXoVLKfE1c3vApkvDYS5KAK+V8fNWGhbSUEo9Gg2iaID2tjLXegEW3bZDUGpofRWw==", + "dependencies": { + "@emotion/is-prop-valid": "1.2.1", + "@emotion/unitless": "0.8.0", + "@types/stylis": "4.2.0", + "css-to-react-native": "3.2.0", + "csstype": "3.1.2", + "postcss": "8.4.31", + "shallowequal": "1.1.0", + "stylis": "4.3.1", + "tslib": "2.5.0" + }, + "engines": { + "node": ">= 16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/styled-components" + }, + "peerDependencies": { + "react": ">= 16.8.0", + "react-dom": ">= 16.8.0" + } + }, + "node_modules/styled-components/node_modules/csstype": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz", + "integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==" + }, + "node_modules/styled-components/node_modules/postcss": { + "version": "8.4.31", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", + "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "nanoid": "^3.3.6", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/styled-components/node_modules/tslib": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" + }, "node_modules/stylehacks": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-5.1.1.tgz", @@ -16152,6 +16415,11 @@ "postcss": "^8.2.15" } }, + "node_modules/stylis": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.1.tgz", + "integrity": "sha512-EQepAV+wMsIaGVGX1RECzgrcqRRU/0sYOHkeLsZ3fzHaHXZy4DaOOX0vOlGQdlsjkh3mFHAIlVimpwAs4dslyQ==" + }, "node_modules/sucrase": { "version": "3.35.0", "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz", @@ -17104,6 +17372,20 @@ "react": "^16.8.0 || ^17.0.0 || ^18.0.0" } }, + "node_modules/usehooks-ts": { + "version": "2.16.0", + "resolved": "https://registry.npmjs.org/usehooks-ts/-/usehooks-ts-2.16.0.tgz", + "integrity": "sha512-bez95WqYujxp6hFdM/CpRDiVPirZPxlMzOH2QB8yopoKQMXpscyZoxOjpEdaxvV+CAWUDSM62cWnqHE0E/MZ7w==", + "dependencies": { + "lodash.debounce": "^4.0.8" + }, + "engines": { + "node": ">=16.15.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17 || ^18" + } + }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -18164,11 +18446,30 @@ } } }, + "node_modules/xml-formatter": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/xml-formatter/-/xml-formatter-3.6.2.tgz", + "integrity": "sha512-enWhevZNOwffZFUhzl1WMcha8lFLZUgJ7NzFs5Ug4ZOFCoNheGYXz1J9Iz/e+cTn9rCkuT1GwTacz+YlmFHOGw==", + "dependencies": { + "xml-parser-xo": "^4.1.0" + }, + "engines": { + "node": ">= 14" + } + }, "node_modules/xml-name-validator": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz", "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==" }, + "node_modules/xml-parser-xo": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/xml-parser-xo/-/xml-parser-xo-4.1.1.tgz", + "integrity": "sha512-Ggf2y90+Y6e9IK5hoPuembVHJ03PhDSdhldEmgzbihzu9k0XBo0sfcFxaSi4W1PlUSSI1ok+MJ0JCXUn+U4Ilw==", + "engines": { + "node": ">= 14" + } + }, "node_modules/xmlchars": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", diff --git a/ui/package.json b/ui/package.json index 70da4b2..8a23e6b 100644 --- a/ui/package.json +++ b/ui/package.json @@ -44,7 +44,8 @@ "typescript": "^4.9.5", "urdf-loader": "^0.12.1", "uuid": "^9.0.1", - "web-vitals": "^2.1.4" + "web-vitals": "^2.1.4", + "xml-formatter": "^3.6.2" }, "scripts": { "dev": "react-scripts start", diff --git a/ui/src/core/extensions/extensions.ts b/ui/src/core/extensions/extensions.ts index a6d5383..1612cad 100644 --- a/ui/src/core/extensions/extensions.ts +++ b/ui/src/core/extensions/extensions.ts @@ -26,6 +26,9 @@ declare global { interface String { isEmpty(): boolean; isNotEmpty(): boolean; + replaceMany(searchValues: string[], replaceValue: string): string; + isEqual(str: string): boolean; + isEqualMany(str: string[]): boolean; } interface Map { addValueOrMakeCallback(key: K, value: V, callBack: CallBackVoidFunction): void; @@ -37,8 +40,8 @@ declare global { } } export const extensions = () => { - ArrayExtensions(); StringExtensions(); + ArrayExtensions(); NumberExtensions(); MapExtensions(); }; diff --git a/ui/src/core/extensions/string.ts b/ui/src/core/extensions/string.ts index 86b5246..79709c1 100644 --- a/ui/src/core/extensions/string.ts +++ b/ui/src/core/extensions/string.ts @@ -1,3 +1,4 @@ +/* eslint-disable no-extend-native */ export const StringExtensions = () => { if ("".isEmpty === undefined) { // eslint-disable-next-line no-extend-native @@ -11,4 +12,28 @@ export const StringExtensions = () => { return this.length !== 0; }; } + if ("".replaceMany === undefined) { + String.prototype.replaceMany = function (searchValues: string[], replaceValue: string) { + let result = this as string; + searchValues.forEach((el) => { + result = result.replaceAll(el, replaceValue); + }); + return result; + }; + } + if ("".isEqual === undefined) { + String.prototype.isEqual = function (str: string) { + return this === str; + }; + } + if ("".isEqualMany === undefined) { + String.prototype.isEqualMany = function (str: string[]) { + for (const el of str) { + if (el === this) { + return true; + } + } + return false; + }; + } }; diff --git a/ui/src/features/scene_manager/model/robossembler_assets.ts b/ui/src/core/model/robossembler_assets.ts similarity index 89% rename from ui/src/features/scene_manager/model/robossembler_assets.ts rename to ui/src/core/model/robossembler_assets.ts index 7c98cd8..8e26306 100644 --- a/ui/src/features/scene_manager/model/robossembler_assets.ts +++ b/ui/src/core/model/robossembler_assets.ts @@ -105,6 +105,9 @@ export class Asset { centerMassY: string; @IsString() centerMassZ: string; + @IsArray() + @IsOptional() + actions: string[]; } export class Physics { @@ -116,13 +119,22 @@ export class Physics { export class RobossemblerAssets { @ValidateNested() - @Type(() => Asset) + @Type(() => Asset, { + discriminator: { + property: "type", + subTypes: [ + { value: InstanceRgbCamera, name: InstanceType.RGB_CAMERA }, + { value: SceneSimpleObject, name: InstanceType.SCENE_SIMPLE_OBJECT }, + ], + }, + keepDiscriminatorProperty: true, + }) assets: Asset[]; @IsArray() @Type(() => Instance, { discriminator: { - property: "instanceType", + property: "type", subTypes: [ { value: InstanceRgbCamera, name: InstanceType.RGB_CAMERA }, { value: SceneSimpleObject, name: InstanceType.SCENE_SIMPLE_OBJECT }, diff --git a/ui/src/core/repository/core_three_repository.ts b/ui/src/core/repository/core_three_repository.ts index 1d82d30..ea22b31 100644 --- a/ui/src/core/repository/core_three_repository.ts +++ b/ui/src/core/repository/core_three_repository.ts @@ -35,11 +35,7 @@ import { } from "../../features/scene_manager/model/scene_assets"; import { SceneMode } from "../../features/scene_manager/model/scene_view"; import { throttle } from "../helper/throttle"; -import { - InstanceRgbCamera, - RobossemblerAssets, - SceneSimpleObject, -} from "../../features/scene_manager/model/robossembler_assets"; +import { Asset, InstanceRgbCamera, RobossemblerAssets, SceneSimpleObject } from "../model/robossembler_assets"; import { CoreVector3 } from "../model/core_vector3"; export enum UserData { @@ -157,6 +153,15 @@ export class CoreThreeRepository extends TypedEvent { } }); } + loadInstance(asset: Asset, loadCallback?: Function) { + this.loader( + asset.meshPath, + loadCallback ? loadCallback : () => {}, + asset.name, + new Vector3(Number(asset.posX), Number(asset.posY), Number(asset.posZ)), + new Quaternion(0, 0, 0, 0) + ); + } setTransformMode(mode?: SceneMode) { switch (mode) { @@ -283,18 +288,6 @@ export class CoreThreeRepository extends TypedEvent { floor.userData = {}; floor.userData[UserData.cameraInitialization] = true; this.scene.add(floor); - - const planeMesh = new Mesh( - new PlaneGeometry(10, 10, 10, 10), - new MeshBasicMaterial({ color: 0x808080, wireframe: true }) - ); - planeMesh.userData[UserData.selectedObject] = true; - planeMesh.userData[UserData.objectForMagnetism] = true; - planeMesh.rotation.x = -Math.PI / 2; - this.makeCube(1); - this.makeCube(2, new Vector3(20, 0, 10), "yellow"); - - this.scene.add(planeMesh); } render() { diff --git a/ui/src/core/routers/routers.tsx b/ui/src/core/routers/routers.tsx index 75731d4..ab308e5 100644 --- a/ui/src/core/routers/routers.tsx +++ b/ui/src/core/routers/routers.tsx @@ -4,28 +4,19 @@ import { PipelineInstanceScreen, PipelineInstanceScreenPath, } from "../../features/pipeline_instance_main_screen/pipeline_instance_screen"; -import { - SelectProjectScreen, - SelectProjectScreenPath, -} from "../../features/select_project/presentation/select_project"; -import { - CreatePipelineScreen, - CreatePipelineScreenPath, -} from "../../features/create_pipeline/presentation/create_pipeline_screen"; + import { CreateProjectScreen, CreateProjectScreenPath } from "../../features/create_project/create_project_screen"; -import { - CreateTriggerScreenPath, - TriggerScreen, -} from "../../features/create_trigger/presentation/create_trigger_screen"; -import { - CreateProcessScreen, - CreateProcessScreenPath, -} from "../../features/create_process/presentation/create_process_screen"; -import { - CreateProjectInstancePath, - CreateProjectInstanceScreen, -} from "../../features/create_project_instance/create_project_instance"; + import { SceneManger, SceneManagerPath } from "../../features/scene_manager/presentation/scene_manager"; +import { + BehaviorTreeBuilderPath, + BehaviorTreeBuilderScreen, +} from "../../features/behavior_tree_builder/presentation/behavior_tree_builder_screen"; +import { + StickObjectsMarkingScreen, + StickObjectsMarkingScreenPath, +} from "../../features/stick_objects_marking/stick_objects_marking_screen"; +import { DataSetScreen, DatasetsScreenPath } from "../../features/dataset/dataset_screen"; const idURL = ":id"; @@ -38,32 +29,26 @@ export const router = createBrowserRouter([ path: PipelineInstanceScreenPath + idURL, element: , }, - { - path: SelectProjectScreenPath, - element: , - }, - { - path: CreatePipelineScreenPath, - element: , - }, + { path: CreateProjectScreenPath, element: , }, + { - path: CreateTriggerScreenPath, - element: , - }, - { - path: CreateProcessScreenPath, - element: , - }, - { - path: CreateProjectInstancePath + idURL, - element: , - }, - { - path: SceneManagerPath + idURL, + path: SceneManagerPath, element: , }, + { + path: BehaviorTreeBuilderPath, + element: , + }, + { + path: StickObjectsMarkingScreenPath, + element: , + }, + { + path: DatasetsScreenPath, + element: , + }, ]); diff --git a/ui/src/core/ui/form_builder/form_builder.tsx b/ui/src/core/ui/form_builder/form_builder.tsx new file mode 100644 index 0000000..be91d15 --- /dev/null +++ b/ui/src/core/ui/form_builder/form_builder.tsx @@ -0,0 +1,138 @@ +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 { extensions } from "../../extensions/extensions"; +import { FormBuilderValidationModel } from "../../../features/dataset/dataset_store"; +extensions(); + +export interface IFormBuilder { + context: string; + result: string; + onChange: (change: FormBuilderValidationModel | undefined) => void; +} + +export const FormBuilder = observer((props: IFormBuilder) => { + const [store] = React.useState(() => new FormBuilderStore()); + + React.useEffect(() => { + store.init(props.context, props.result); + store.changerForm.on((event) => props.onChange(event)); + }, [store, props]); + + return ( +
+ {store.isError ? ( + <>Error + ) : ( +
+ {store.formViewModel?.inputs.map((element) => { + if (element.type.isEqual(InputType.ENUM)) { + const values = element.values as string[]; + return ( + <> +
{element.name}
+ + { + store.changeTotalSubValue(element.id, subIndex, e); + }} + options={subSubArrayItem.values?.map((el) => { + return { value: el }; + })} + /> + + ); + } + if (subSubArrayItem.type.isEqualMany([InputType.NUMBER, InputType.STRING])) + return ( +
+
{subSubArrayItem.name}
+ { + store.changeTotalSubValue(element.id, subIndex, e.target.value); + }} + defaultValue={subSubArrayItem.defaultValue} + /> +
+ ); + + return <>Error; + })} + + ); + }) + : null} +
+ ) : null} +
{ + store.open(element.id); + }} + > + + +
+
+ ); + } + + if (element.type.isEqualMany([InputType.NUMBER, InputType.STRING])) + return ( +
+
{element.name}
+ { + store.changeTotalValue(element.id, e.target.value); + }} + defaultValue={element.defaultValue} + /> +
+ ); + + 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 new file mode 100644 index 0000000..484ade0 --- /dev/null +++ b/ui/src/core/ui/form_builder/form_builder_store.ts @@ -0,0 +1,103 @@ +import { makeAutoObservable } from "mobx"; +import { FormViewModel } from "./form_view_model"; +import { TypedEvent } from "../../helper/typed_event"; +import { FormBuilderValidationModel } from "../../../features/dataset/dataset_store"; + +export class ChangerForm extends TypedEvent {} + +export class FormBuilderStore { + isError = false; + formViewModel?: FormViewModel; + changerForm: ChangerForm; + constructor() { + makeAutoObservable(this); + this.changerForm = new ChangerForm(); + } + + changeTotalSubValue(id: string, subIndex: number, value: string) { + if (this.formViewModel?.inputs) + this.formViewModel.inputs = this.formViewModel?.inputs.map((el) => { + if (!el.id.isEqual(id)) { + return el; + } else { + if (el.totalValue instanceof Array) { + el.totalValue = el.totalValue.map((subElement) => { + if (subElement instanceof Array) { + subElement.map((subSubElement, i) => { + if (subIndex !== i) { + return subSubElement; + } + + subSubElement.totalValue = value; + + return subSubElement; + }); + } + return subElement; + }); + return el; + } + return el; + } + }); + this.changerForm.emit(this.formViewModel?.fromFormBuilderValidationModel()); + } + + changeTotalValue(id: string, value: string) { + if (this.formViewModel?.inputs) + this.formViewModel.inputs = this.formViewModel?.inputs.map((el) => { + if (!el.id.isEqual(id)) { + return el; + } + el.totalValue = value; + return el; + }); + this.changerForm.emit(this.formViewModel?.fromFormBuilderValidationModel()); + } + + deleteTotalValueSubItem(id: string, index: number): void { + if (this.formViewModel?.inputs) + this.formViewModel.inputs = this.formViewModel?.inputs.map((el) => { + if (!el.id.isEqual(id)) { + return el; + } else { + if (el.totalValue instanceof Array) { + el.totalValue = el.totalValue.filter((_, i) => index !== i); + return el; + } + return el; + } + }); + this.changerForm.emit(this.formViewModel?.fromFormBuilderValidationModel()); + } + + saveForm(): void { + console.log(this.formViewModel?.toResult()); + } + + open = (id: string) => { + if (this.formViewModel) + this.formViewModel.inputs = this.formViewModel?.inputs.map((el) => { + if (!el.id.isEqual(id)) { + return el; + } + + el.isOpen = true; + + if (!(el.totalValue instanceof Array)) { + el.totalValue = []; + } + el.totalValue.push(el.values); + return el; + }); + }; + + init(context: string, result: string) { + FormViewModel.fromString(result, context).fold( + (model) => { + this.formViewModel = model; + }, + () => (this.isError = true) + ); + } +} diff --git a/ui/src/core/ui/form_builder/form_view_model.ts b/ui/src/core/ui/form_builder/form_view_model.ts new file mode 100644 index 0000000..5ea410c --- /dev/null +++ b/ui/src/core/ui/form_builder/form_view_model.ts @@ -0,0 +1,171 @@ +import { makeAutoObservable, observable } from "mobx"; +import { Result } from "../../helper/result"; +import { v4 as uuidv4 } from "uuid"; +import { FormBuilderValidationModel } from "../../../features/dataset/dataset_store"; + +export enum InputType { + NUMBER = "number", + STRING = "string", + ARRAY = "Array", + ENUM = "Enum", +} + +export class InputBuilderViewModel { + id: string; + constructor( + public name: string, + public type: InputType, + public defaultValue: string, + public values: string[] | undefined | InputBuilderViewModel[] = undefined, + public totalValue: any | undefined = undefined, + public isOpen: boolean = false, + public subType: string | undefined = undefined + ) { + this.id = uuidv4(); + } + static fromJSON(json: any) { + return new InputBuilderViewModel(json.name, json.type, json.defaultValue, json.values, json.isOpen, json.id); + } + public toJson(): string { + return JSON.stringify(this); + } +} + +export const tagParse = new RegExp(/\${.*?}/gm); +export const bracketParser = new RegExp(/<.*?>/gm); +export const enumParser = new RegExp(/ENUM.*=..*?;/gm); +export const enumBodyParse = new RegExp(/".*?;/gm); +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 class FormViewModel { + @observable + inputs: InputBuilderViewModel[]; + + constructor(inputs: InputBuilderViewModel[], public result: string, public context: string) { + this.inputs = inputs; + makeAutoObservable(this); + } + public fromFormBuilderValidationModel() { + console.log(this.toResult()); + return new FormBuilderValidationModel( + this.context, + this.result, + this.inputs.map((el) => el.toJson()), + this.toResult() + ); + } + public toResult() { + let result = this.result; + + this.inputs.forEach((element) => { + let inputResult = element.totalValue ?? element.defaultValue; + if (element.type.isEqualMany([InputType.STRING, InputType.ENUM])) { + inputResult = `"${String(inputResult)}"`; + } + if (element.type.isEqual(InputType.NUMBER)) { + inputResult = Number(inputResult); + } + if (element.type.isEqual(InputType.ARRAY)) { + if (element.totalValue === undefined) { + inputResult = "[]"; + } else { + inputResult = []; + // @ts-ignore + element.totalValue.forEach((el) => { + const objectUnion = {}; + if (el instanceof Array) + el.forEach((subElement) => { + let subResult = subElement.totalValue ?? subElement.defaultValue; + if (element.type.isEqualMany([InputType.STRING, InputType.ENUM])) { + subResult = `"${String(subResult)}"`; + } + if (element.type.isEqual(InputType.NUMBER)) { + subResult = Number(subResult); + } + // @ts-ignore + objectUnion[subElement.name] = subResult; + }); + if (Object.keys(objectUnion).length !== 0) { + inputResult.push(objectUnion); + } + }); + } + } + if (inputResult instanceof Array) inputResult = JSON.stringify(inputResult); + result = result.replace(new RegExp("\\${" + element.name + ".*?}"), inputResult); + }); + return result; + } + static fromString(result: string, context: string): Result { + try { + const enums = new Map(); + const types = new Map(); + + context.match(enumParser)?.forEach((el) => { + const enumMatch = el.match(enumBodyParse)?.at(0); + if (enumMatch !== undefined) { + const EnumValue = enumMatch.slice(0, enumMatch.length - 2).split(","); + const enumBody = EnumValue.map((el) => el.replaceAll('"', "")); + const enumName = el.match(enumNameParse)?.at(0)?.split(" ").at(1); + if (enumBody.isNotEmpty() && enumName) enums.set(enumName, enumBody); + } + }); + + context.match(typeParse)?.forEach((type) => { + const matchTypeName = type.match(typeNameParse)?.at(0)?.split(" ").at(1); + const typeBody = type.match(typeBodyParse)?.at(0); + + if (typeBody && matchTypeName) types.set(matchTypeName, this.typeParse(typeBody, enums)); + }); + + return Result.ok(new FormViewModel(this.typeParse(result, enums, types), result, context)); + } catch (error) { + console.log(error); + return Result.error(undefined); + } + } + static typeParse( + result: string, + enums: Map, + types: Map | undefined = undefined + ) { + 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)); + } + } + 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; + }) + .filter((el) => el !== undefined) as InputBuilderViewModel[]; + } +} diff --git a/ui/src/core/ui/form_builder/readme.md b/ui/src/core/ui/form_builder/readme.md new file mode 100644 index 0000000..5673db6 --- /dev/null +++ b/ui/src/core/ui/form_builder/readme.md @@ -0,0 +1,33 @@ +# RESULT + +``` +{ + "scene":{ + "objects": \${OBJECTS_SCENE:Array:[]}, + }, + "camera_position":{ + "center_shell": [\${CENTER_SHELL_1:string:0}, \${COLISION_SHAPE:Enum:"BOX"}] + } +} +``` + +# CONTEXT + +### хранит в себе type и enum для result + +``` +ENUM T = "ObjectDetection","PoseEstimation"; +ENUM L = "POINT","SUN"; + +type MODELS = { +"id": \${IMAGE_FORMAT:Enum:"jpg"},, +"name": \${NAME:string:""}, +"model": \${MODEL:string:"models/1.fbx"} +}; + +type OBJECTS_SCENE = { +"name": \${NAME:string:""}, +"collision_shape": \${COLISION_SHAPE:Enum:"BOX"}, +"loc_xyz": [\${TEST123:string:"test123"}, \${LOC_XYZ_2:number:0}, \${LOC_XYZ_3:number:0}], +}; +``` diff --git a/ui/src/features/all_projects/data/project_repository.ts b/ui/src/features/all_projects/data/project_repository.ts index 4cc8038..fc69f18 100644 --- a/ui/src/features/all_projects/data/project_repository.ts +++ b/ui/src/features/all_projects/data/project_repository.ts @@ -2,13 +2,16 @@ import { ActivePipeline } from "../../../core/model/active_pipeline"; import { HttpMethod, HttpRepository } from "../../../core/repository/http_repository"; import { IProjectModel } from "../model/project_model"; +export interface UUID { + id: string; +} export class ProjectRepository extends HttpRepository { async getAllProject() { - return this._jsonRequest(HttpMethod.GET, "/project_instance"); + return this._jsonRequest(HttpMethod.GET, "/projects"); } async getActivePipeline() { - return this._jsonRequest(HttpMethod.GET, "/realtime"); + return this._jsonRequest(HttpMethod.GET, "/projects/get/active/project/id"); } async setActivePipeline(id: string) { return this._jsonRequest(HttpMethod.POST, `/project_instance/set/active/project?id=${id}`); diff --git a/ui/src/features/all_projects/model/project_model.ts b/ui/src/features/all_projects/model/project_model.ts index e74166b..4d39434 100644 --- a/ui/src/features/all_projects/model/project_model.ts +++ b/ui/src/features/all_projects/model/project_model.ts @@ -2,7 +2,7 @@ import { PipelineModel } from "../../create_project/create_project_repository"; export interface IProjectModel { _id?: string; - pipelines: [PipelineModel]; rootDir: string; description: string; + isActive?: boolean; } diff --git a/ui/src/features/all_projects/presentation/all_projects_screen.tsx b/ui/src/features/all_projects/presentation/all_projects_screen.tsx index 92bcea5..c7d1041 100644 --- a/ui/src/features/all_projects/presentation/all_projects_screen.tsx +++ b/ui/src/features/all_projects/presentation/all_projects_screen.tsx @@ -3,19 +3,19 @@ import { AllProjectStore } from "./all_projects_store"; import { ProjectRepository } from "../data/project_repository"; import { LoadPage } from "../../../core/ui/pages/load_page"; import { observer } from "mobx-react-lite"; -import { SelectProjectScreenPath } from "../../select_project/presentation/select_project"; import { useNavigate } from "react-router-dom"; import { Button } from "antd"; import { PipelineInstanceScreenPath } from "../../pipeline_instance_main_screen/pipeline_instance_screen"; +import { CreateProjectScreenPath } from "../../create_project/create_project_screen"; export const AllProjectScreenPath = "/"; export const AllProjectScreen: React.FunctionComponent = observer(() => { - const [allProjectStore] = React.useState(() => new AllProjectStore(new ProjectRepository())); + const [store] = React.useState(() => new AllProjectStore(new ProjectRepository())); const navigate = useNavigate(); React.useEffect(() => { - allProjectStore.init(); - }, [allProjectStore]); + store.init(); + }, [store]); return ( <> @@ -23,35 +23,23 @@ export const AllProjectScreen: React.FunctionComponent = observer(() => { largeText={"Projects"} needBackButton={false} minText="create project?" - path={SelectProjectScreenPath} - isError={allProjectStore.isError} - isLoading={allProjectStore.isLoading} + path={CreateProjectScreenPath} + isError={store.isError} + isLoading={store.isLoading} children={
-

Projects

-
- - {allProjectStore.activePipeline?.projectId ?? "loading"} -
- {allProjectStore.projectsModels?.map((el) => { + {store.projectsModels?.map((el) => { return (
- + {el.isActive ? ( + + ) : null}
{el.description}
); diff --git a/ui/src/features/all_projects/presentation/all_projects_store.ts b/ui/src/features/all_projects/presentation/all_projects_store.ts index 7e512dc..b73e6d9 100644 --- a/ui/src/features/all_projects/presentation/all_projects_store.ts +++ b/ui/src/features/all_projects/presentation/all_projects_store.ts @@ -1,5 +1,5 @@ import makeAutoObservable from "mobx-store-inheritance"; -import { ProjectRepository } from "../data/project_repository"; +import { ProjectRepository, UUID } from "../data/project_repository"; import { IProjectModel } from "../model/project_model"; import { SimpleErrorState } from "../../../core/store/base_store"; import { ActivePipeline } from "../../../core/model/active_pipeline"; @@ -21,8 +21,8 @@ export class ProjectView { } export class AllProjectStore extends SimpleErrorState { projectsModels?: IProjectModel[]; + activeProjectId?: UUID; repository: ProjectRepository; - activePipeline?: ActivePipeline; constructor(repository: ProjectRepository) { super(); this.repository = repository; @@ -31,18 +31,14 @@ export class AllProjectStore extends SimpleErrorState { async getProjects(): Promise { await this.mapOk("projectsModels", this.repository.getAllProject()); } - - async getActiveProject(): Promise { - await this.mapOk("activePipeline", this.repository.getActivePipeline()); + async getActiveProjectId(): Promise { + await this.mapOk("activeProjectId", this.repository.getActivePipeline()); } - async init() { - await Promise.all([this.getProjects(), this.getActiveProject()]); - await this.projectViewGenerate(); - } - projectViewGenerate() { - this.projectsModels = this.projectsModels?.filter((el) => el._id !== this.activePipeline?.projectId); + await Promise.all([this.getProjects(), this.getActiveProjectId()]); + this.projectsModels?.map((el) => (el._id === this.activeProjectId ? ((el.isActive = true), el) : el)); } + async setPipelineActive(id: string) { await this.httpHelper(this.repository.setActivePipeline(id)); } diff --git a/ui/src/features/behavior_tree_builder/model/editor_view.ts b/ui/src/features/behavior_tree_builder/model/editor_view.ts index b99a58b..800d994 100644 --- a/ui/src/features/behavior_tree_builder/model/editor_view.ts +++ b/ui/src/features/behavior_tree_builder/model/editor_view.ts @@ -15,14 +15,19 @@ export class BtNodeView extends TypedEvent {} export class ReteObserver extends TypedEvent {} export class BtBuilderModel { public static result = ""; - static fromReteScene(editor: NodeEditor, area: AreaPlugin) { - this.getFirstSequence(editor).map((sortedSequence) => { - const firstNodeId = sortedSequence.getKeyFromValueIsExists(1) as string; - this.findSequence(firstNodeId, editor, sortedSequence, 2); - this.result += `<${this.getNodeLabelAtId(editor, firstNodeId)} id="${firstNodeId}">`; - this.toXML(sortedSequence as Map, editor, area, firstNodeId); - this.result += ``; - }); + static fromReteScene(editor: NodeEditor, area: AreaPlugin): Result { + try { + this.getFirstSequence(editor).map((sortedSequence) => { + const firstNodeId = sortedSequence.getKeyFromValueIsExists(1) as string; + this.findSequence(firstNodeId, editor, sortedSequence, 2); + this.result += `<${this.getNodeLabelAtId(editor, firstNodeId)} id="${firstNodeId}">`; + this.toXML(sortedSequence as Map, editor, area, firstNodeId); + this.result += ``; + }); + return Result.ok(this.result); + } catch (error) { + return Result.error("BtBuilderModel fromReteScene error"); + } } public static getNodeLabelAtId(editor: NodeEditor, id: string) { return editor.getNode(id).label; diff --git a/ui/src/features/behavior_tree_builder/presentation/behavior_tree_builder_screen.tsx b/ui/src/features/behavior_tree_builder/presentation/behavior_tree_builder_screen.tsx index cbf58de..936041e 100644 --- a/ui/src/features/behavior_tree_builder/presentation/behavior_tree_builder_screen.tsx +++ b/ui/src/features/behavior_tree_builder/presentation/behavior_tree_builder_screen.tsx @@ -26,13 +26,15 @@ const skills = { ], }; export const behaviorTreeBuilderStore = new BehaviorTreeBuilderStore(); - +export const BehaviorTreeBuilderPath = "/behavior/tree/"; export function BehaviorTreeBuilderScreen() { const store = behaviorTreeBuilderStore; const [ref] = useRete(createEditor); React.useEffect(() => { store.init(); + // @ts-expect-error + console.log(ref.current.clientHeight); store.dragZoneSetOffset( // @ts-expect-error @@ -40,9 +42,9 @@ export function BehaviorTreeBuilderScreen() { // @ts-expect-error ref.current.offsetLeft, // @ts-expect-error - Number(String(ref.current.style.width).replaceAll("px", "")), + ref.current.clientWidth, // @ts-expect-error - Number(String(ref.current.style.height).replaceAll("px", "")) + ref.current.clientHeight ); return () => { @@ -60,28 +62,6 @@ export function BehaviorTreeBuilderScreen() { }} > - - store.setBt(e.target.value)} placeholder="bt JSON" /> - -
+ > + +
{ + saveBt(): void { + this.reteNode?.emit("200"); + } validateBt() {} area?: I2DArea; btNodeView: BtNodeView = new BtNodeView(); @@ -95,9 +99,31 @@ export class BehaviorTreeBuilderStore extends UiErrorState { setBt(value: string): void { JSON.parse(value) as BtNodeView[]; } - bt(editor: NodeEditor, area: AreaPlugin) { - console.log(BtBuilderModel.fromReteScene(editor, area)); - } + bt = async (editor: NodeEditor, area: AreaPlugin) => { + (await BtBuilderModel.fromReteScene(editor, area)).fold( + (s) => { + console.log( + xmlFormat(` + + + ${s} + + + + + + + + + + + + `) + ); + }, + (_) => _ + ); + }; copyBt = () => { this.reteNode?.emit("200"); }; @@ -110,7 +136,7 @@ export class BehaviorTreeBuilderStore extends UiErrorState { this.canRun = false; setTimeout(() => { this.canRun = true; - }, 1000); + }, 100); } }; drawSkillCheck(x: number, y: number, name: string) { diff --git a/ui/src/features/behavior_tree_builder/presentation/ui/editor/editor.tsx b/ui/src/features/behavior_tree_builder/presentation/ui/editor/editor.tsx index 9a71a9e..3b5d810 100644 --- a/ui/src/features/behavior_tree_builder/presentation/ui/editor/editor.tsx +++ b/ui/src/features/behavior_tree_builder/presentation/ui/editor/editor.tsx @@ -29,7 +29,7 @@ export async function createEditor(container: HTMLElement) { node.addInput("a", new ClassicPreset.Input(socket)); await editor.addNode(node); await areaContainer.translate(node.id, { x, y }); - }, 50); + }, 100); }); observer.on(() => { diff --git a/ui/src/features/behavior_tree_builder/presentation/ui/editor/nodes/controls_node.tsx b/ui/src/features/behavior_tree_builder/presentation/ui/editor/nodes/controls_node.tsx index 7188fbe..a098d48 100644 --- a/ui/src/features/behavior_tree_builder/presentation/ui/editor/nodes/controls_node.tsx +++ b/ui/src/features/behavior_tree_builder/presentation/ui/editor/nodes/controls_node.tsx @@ -104,13 +104,7 @@ export function SequenceNode(props: Props) return ( -
{ - e.stopPropagation(); - }} - className="title" - data-testid="title" - > +
{}} className="title" data-testid="title"> {label}
{id}
diff --git a/ui/src/features/create_pipeline/data/create_pipeline_repository.ts b/ui/src/features/create_pipeline/data/create_pipeline_repository.ts deleted file mode 100644 index 7532737..0000000 --- a/ui/src/features/create_pipeline/data/create_pipeline_repository.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { HttpMethod, HttpRepository } from "../../../core/repository/http_repository"; -import { ITriggerModel } from "../../../core/model/trigger_model"; -import { Result } from "../../../core/helper/result"; -import { IProcess } from "../../create_process/model/process_model"; -import { PipelineModelDataBase } from "../model/pipeline_model"; - -export class CreatePipelineRepository extends HttpRepository { - async savePipeline(model: PipelineModelDataBase): Promise> { - return await this._jsonRequest(HttpMethod.POST, `/pipeline`, model); - } - async getTriggers(page = 1): Promise> { - return await this._jsonRequest(HttpMethod.GET, `/trigger?${page}`); - } - - async getProcessed(page = 1): Promise> { - return await this._jsonRequest(HttpMethod.GET, `/process?${page}`); - } -} diff --git a/ui/src/features/create_pipeline/model/pipeline_model.ts b/ui/src/features/create_pipeline/model/pipeline_model.ts deleted file mode 100644 index 74352a1..0000000 --- a/ui/src/features/create_pipeline/model/pipeline_model.ts +++ /dev/null @@ -1,8 +0,0 @@ -export interface IColor { - color: string; -} - -export interface PipelineModelDataBase { - process: string; - trigger: string; -} \ No newline at end of file diff --git a/ui/src/features/create_pipeline/presentation/create_pipeline_screen.tsx b/ui/src/features/create_pipeline/presentation/create_pipeline_screen.tsx deleted file mode 100644 index aac631a..0000000 --- a/ui/src/features/create_pipeline/presentation/create_pipeline_screen.tsx +++ /dev/null @@ -1,63 +0,0 @@ -import * as React from "react"; -import { Row, Button } from "antd"; -import { LoadPage } from "../../../core/ui/pages/load_page"; - -import { observer } from "mobx-react-lite"; -import { Icon, List } from "../../../core/ui/list/list"; -import { CreateTriggerScreenPath } from "../../create_trigger/presentation/create_trigger_screen"; -import { CreateProcessScreenPath } from "../../create_process/presentation/create_process_screen"; -import { CreatePipelineStore } from "./create_pipeline_store"; -import { CreatePipelineRepository } from "../data/create_pipeline_repository"; - -export const CreatePipelineScreenPath = "/create_pipeline"; - -export const CreatePipelineScreen: React.FunctionComponent = observer(() => { - const [createPipelineStore] = React.useState(() => new CreatePipelineStore(new CreatePipelineRepository())); - - React.useEffect(() => {}, [createPipelineStore]); - return ( - <> - - - { - return { text: el.description, id: el._id }; - })} - onClick={(e) => createPipelineStore.addProcess(e.text, e.id!)} - icon={Icon.add} - /> -
- - { - createPipelineStore.filterPipelineViewModel(index); - }} - /> -
- - { - return { text: el.description, id: el._id }; - })} - onClick={(e) => createPipelineStore.addTrigger(e.text, e.id!)} - icon={Icon.add} - /> -
- - } - /> - - ); -}); diff --git a/ui/src/features/create_pipeline/presentation/create_pipeline_store.ts b/ui/src/features/create_pipeline/presentation/create_pipeline_store.ts deleted file mode 100644 index e3b076a..0000000 --- a/ui/src/features/create_pipeline/presentation/create_pipeline_store.ts +++ /dev/null @@ -1,99 +0,0 @@ -import makeAutoObservable from "mobx-store-inheritance"; -import { CreatePipelineRepository } from "../data/create_pipeline_repository"; -import { ITriggerModel } from "../../../core/model/trigger_model"; -import { IProcess } from "../../create_process/model/process_model"; -import { message } from "antd"; -import { SimpleErrorState } from "../../../core/store/base_store"; - -enum Type { - PROCESS, - TRIGGER, -} -export interface UnionView { - text: string; - color: string; - type: Type; - uuid?: string; -} - -export class CreatePipelineStore extends SimpleErrorState { - repository: CreatePipelineRepository; - triggersModels: ITriggerModel[] = []; - processModels: IProcess[] = []; - pipelineViewModels: UnionView[] = []; - - constructor(repository: CreatePipelineRepository) { - super(); - this.repository = repository; - makeAutoObservable(this); - this.init(); - } - private init() { - this.loadTriggers(); - this.loadProcess(); - } - - filterPipelineViewModel(index: number): void { - this.pipelineViewModels = this.pipelineViewModels.filter((_el, i) => i !== index); - } - addTrigger(e: string, id: string): void { - const lastElement = this.pipelineViewModels.lastElement(); - if (this.pipelineViewModels.length === 2) { - return; - } - if (lastElement !== undefined) { - if (lastElement.type !== Type.PROCESS) { - message.error("Need process"); - - return; - } - } - this.pipelineViewModels.push({ - uuid: id, - text: e, - color: "blanchedalmond", - type: Type.TRIGGER, - }); - } - addProcess(e: string, id: string): void { - const lastElement = this.pipelineViewModels.lastElement(); - if (this.pipelineViewModels.length === 2) { - return; - } - if (lastElement !== undefined) { - if (lastElement.type !== Type.TRIGGER) { - message.error("Need trigger"); - return; - } - } - - this.pipelineViewModels.push({ - uuid: id, - text: e, - color: "activeborder", - type: Type.PROCESS, - }); - } - - async createPipeline(): Promise { - if (this.pipelineViewModels.isEmpty()) { - message.error("not found pipelines process"); - return; - } - const triggerId = this.pipelineViewModels.find((el) => el.type === Type.TRIGGER)!.uuid as string; - const processId = this.pipelineViewModels.find((el) => el.type === Type.PROCESS)!.uuid as string; - - this.repository.savePipeline({ - process: processId, - trigger: triggerId, - }); - } - - async loadProcess() { - this.mapOk("processModels", this.repository.getProcessed()); - } - - async loadTriggers() { - this.mapOk("triggersModels", this.repository.getTriggers()); - } -} diff --git a/ui/src/features/create_process/data/process_repostiory.ts b/ui/src/features/create_process/data/process_repostiory.ts deleted file mode 100644 index 5b8f64b..0000000 --- a/ui/src/features/create_process/data/process_repostiory.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { HttpMethod, HttpRepository } from "../../../core/repository/http_repository"; -import { IProcess } from "../model/process_model"; - -export class ProcessRepository extends HttpRepository { - async save(model: IProcess): Promise { - await this._jsonRequest(HttpMethod.POST, "/process", model); - } -} diff --git a/ui/src/features/create_process/model/process_model.ts b/ui/src/features/create_process/model/process_model.ts deleted file mode 100644 index ac128f4..0000000 --- a/ui/src/features/create_process/model/process_model.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { DatabaseModel } from "../../../core/model/database_model"; - -export interface IProcess extends DatabaseModel { - description: string; - type: EXEC_TYPE | string; - command: string; - isGenerating: boolean; - isLocaleCode: boolean; - issueType: IssueType | string; - timeout?: number; - commit?: string | undefined; -} - -export enum EXEC_TYPE { - SPAWN = "SPAWN", - EXEC = "EXEC", -} -export enum IssueType { - WARNING = "WARNING", - ERROR = "ERROR", -} -export const processModelMock: IProcess = { - description: "", - type: EXEC_TYPE.SPAWN, - command: "", - isGenerating: true, - isLocaleCode: true, - issueType: IssueType.WARNING, -}; diff --git a/ui/src/features/create_process/presentation/create_process_screen.tsx b/ui/src/features/create_process/presentation/create_process_screen.tsx deleted file mode 100644 index 0bf13d7..0000000 --- a/ui/src/features/create_process/presentation/create_process_screen.tsx +++ /dev/null @@ -1,65 +0,0 @@ -import * as React from "react"; -import { processStore } from "./logic/process_store"; -import { observer } from "mobx-react-lite"; -import { SubmitButton, Input, ResetButton, Form, Radio, Switch } from "formik-antd"; -import { Formik } from "formik"; -import { Row, Col } from "antd"; -import { EXEC_TYPE, IssueType, processModelMock } from "../model/process_model"; -export const CreateProcessScreenPath = "/create/process"; -export const CreateProcessScreen = observer(() => { - return ( -
-
- { - await processStore.saveResult(values); - actions.setSubmitting(false); - actions.resetForm(); - }} - validate={(values) => { - if (!values.command) { - return { command: "required" }; - } - if (!values.description) { - return { description: "required" }; - } - return {}; - }} - render={() => ( -
-
- - - - - - - - - - - - - - - - Reset - Submit - - -
-
- )} - /> -
-
- ); -}); diff --git a/ui/src/features/create_process/presentation/logic/process_store.ts b/ui/src/features/create_process/presentation/logic/process_store.ts deleted file mode 100644 index d9e5afc..0000000 --- a/ui/src/features/create_process/presentation/logic/process_store.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { makeAutoObservable } from "mobx"; -import { ProcessRepository } from "../../data/process_repostiory"; -import { IProcess } from "../../model/process_model"; - -class ProcessStore { - repository: ProcessRepository; - constructor(repository: ProcessRepository) { - this.repository = repository; - makeAutoObservable(this); - } - async saveResult(model: IProcess) { - await this.repository.save(model); - } -} - -export const processStore = new ProcessStore(new ProcessRepository()); diff --git a/ui/src/features/create_project/create_project_repository.ts b/ui/src/features/create_project/create_project_repository.ts index 68082f3..750aad6 100644 --- a/ui/src/features/create_project/create_project_repository.ts +++ b/ui/src/features/create_project/create_project_repository.ts @@ -2,19 +2,19 @@ import { Result } from "../../core/helper/result"; import { DatabaseModel } from "../../core/model/database_model"; import { ITriggerModel } from "../../core/model/trigger_model"; import { HttpMethod, HttpRepository } from "../../core/repository/http_repository"; -import { IProcess } from "../create_process/model/process_model"; +import { UUID } from "../all_projects/data/project_repository"; import { ICreateProjectViewModel } from "./project_model"; export interface PipelineModel extends DatabaseModel { - process: IProcess; + process: any; trigger: ITriggerModel; } export class CreateProjectRepository extends HttpRepository { - async getAllPipelines(page = 1): Promise> { - return await this._jsonRequest(HttpMethod.GET, "/pipeline"); + async saveProject(model: ICreateProjectViewModel): Promise> { + return await this._jsonRequest(HttpMethod.POST, "/projects", model); } - async saveProject(model: ICreateProjectViewModel): Promise> { - return await this._jsonRequest(HttpMethod.POST, "/project", model); + async setProjectRootFile(file: File, projectId: string) { + return await this._formDataRequest(HttpMethod.POST, `/projects/upload?id=${projectId}`, file); } } diff --git a/ui/src/features/create_project/create_project_screen.tsx b/ui/src/features/create_project/create_project_screen.tsx index 273193e..ff07100 100644 --- a/ui/src/features/create_project/create_project_screen.tsx +++ b/ui/src/features/create_project/create_project_screen.tsx @@ -1,85 +1,46 @@ import * as React from "react"; import { LoadPage as MainPage } from "../../core/ui/pages/load_page"; import { observer } from "mobx-react-lite"; -import { Col, Row, Input, Button } from "antd"; -import { ReactComponent as AddIcon } from "../../core/assets/icons/add.svg"; -import { CreatePipelineScreenPath } from "../create_pipeline/presentation/create_pipeline_screen"; +import { Col, Row, Input, Button, Upload } from "antd"; +import type { UploadProps } from "antd"; import { CreateProjectStore } from "./create_project_store"; import { CreateProjectRepository } from "./create_project_repository"; export const CreateProjectScreenPath = "/create_project"; - export const CreateProjectScreen: React.FunctionComponent = observer(() => { - const [createProjectStore] = React.useState(() => new CreateProjectStore(new CreateProjectRepository())); + const [store] = React.useState(() => new CreateProjectStore(new CreateProjectRepository())); React.useEffect(() => { - createProjectStore.init(); - }, [createProjectStore]); + store.init(); + }, [store]); return ( <> - - <>Pipelines - {createProjectStore.pipelineModels?.map((el) => { - return ( -
+ + + store.setDescriptionToNewProject(e.target.value)} + placeholder="project description" + /> + { + store.file = e.file.originFileObj; }} > -
{el.process.description}
-
{el.trigger.description}
- { - createProjectStore.addPipeline(el); - }} - /> -
- ); - })} - - - - createProjectStore.setDescriptionToNewProject(e.target.value)} - placeholder="project description" - /> - - - - - {createProjectStore.newProjectViews.map((el, index) => { - return ( -
-
{el.process.description}
-
{el.trigger.description}
-
{index + 1}
-
- ); - })} - + + + + + + } /> diff --git a/ui/src/features/create_project/create_project_store.ts b/ui/src/features/create_project/create_project_store.ts index c330d02..33d74ed 100644 --- a/ui/src/features/create_project/create_project_store.ts +++ b/ui/src/features/create_project/create_project_store.ts @@ -1,30 +1,20 @@ import makeAutoObservable from "mobx-store-inheritance"; -import { CreateProjectRepository, PipelineModel } from "./create_project_repository"; +import { CreateProjectRepository } from "./create_project_repository"; import { message } from "antd"; import { SimpleErrorState } from "../../core/store/base_store"; export class CreateProjectStore extends SimpleErrorState { repository: CreateProjectRepository; - pipelineModels?: PipelineModel[]; newProjectDescription: string = ""; - newProjectViews: PipelineModel[] = []; + file?: File; constructor(repository: CreateProjectRepository) { super(); this.repository = repository; makeAutoObservable(this); } - async init() { - await this.loadPipelines(); - } - async addPipeline(model: PipelineModel) { - this.newProjectViews.push(model); - } - - async loadPipelines() { - this.mapOk("pipelineModels", this.repository.getAllPipelines()); - } + async init() {} setDescriptionToNewProject(value: string): void { this.newProjectDescription = value; @@ -35,27 +25,27 @@ export class CreateProjectStore extends SimpleErrorState { message.error("project description is not empty"); return; } - if (this.newProjectViews.isEmpty()) { - message.error("project view is not empty"); + if (this.file === undefined) { + message.error("upload file"); return; } + this.isLoading = true; - const result = await this.repository.saveProject({ - description: this.newProjectDescription, - pipelines: this.newProjectViews.map((el) => el._id ?? ""), - }); - - this.newProjectDescription = ""; - this.newProjectViews = []; - this.isLoading = false; - - result.fold( - (_s) => { - message.success("save"); + ( + await this.repository.saveProject({ + description: this.newProjectDescription, + }) + ).fold( + (uuid) => { + this.newProjectDescription = ""; + this.isLoading = false; + this.repository.setProjectRootFile(this.file as File, uuid.id); }, - (_e) => { + (_) => { this.isError = true; } ); + + // } } diff --git a/ui/src/features/create_project/project_model.ts b/ui/src/features/create_project/project_model.ts index a124f49..ee9c740 100644 --- a/ui/src/features/create_project/project_model.ts +++ b/ui/src/features/create_project/project_model.ts @@ -1,5 +1,3 @@ export interface ICreateProjectViewModel { - pipelines: string[]; - description: string; } diff --git a/ui/src/features/create_project_instance/create_project_instance.tsx b/ui/src/features/create_project_instance/create_project_instance.tsx deleted file mode 100644 index 3927516..0000000 --- a/ui/src/features/create_project_instance/create_project_instance.tsx +++ /dev/null @@ -1,37 +0,0 @@ -import * as React from "react"; -import { CreateProjectInstanceStore } from "./create_project_instance_store"; -import { CreateProjectInstanceRepository } from "./create_project_instance_repository"; -import { observer } from "mobx-react-lite"; -import { Upload, Button } from "antd"; -import { useNavigate, useParams } from "react-router-dom"; -import { Input } from "antd"; - -export const CreateProjectInstancePath = "/create/project/instance/"; - -export const CreateProjectInstanceScreen = observer(() => { - const [createProjectInstanceStore] = React.useState( - () => new CreateProjectInstanceStore(new CreateProjectInstanceRepository()) - ); - const id = useParams().id; - const navigate = useNavigate(); - - React.useEffect(() => { - createProjectInstanceStore.init(navigate, id as string); - }, [id, createProjectInstanceStore, navigate]); - - return ( - <> -

project description

- createProjectInstanceStore.setProjectDescription(e.target.value)}> -

root entity

- { - createProjectInstanceStore.file = e.file.originFileObj; - }} - > - - - - - ); -}); diff --git a/ui/src/features/create_project_instance/create_project_instance_repository.ts b/ui/src/features/create_project_instance/create_project_instance_repository.ts deleted file mode 100644 index b835961..0000000 --- a/ui/src/features/create_project_instance/create_project_instance_repository.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { HttpMethod, HttpRepository } from "../../core/repository/http_repository"; -import { NewProjectModel } from "./new_project_model"; - -export class CreateProjectInstanceRepository extends HttpRepository { - async setProjectRootFile(file: File) { - return await this._formDataRequest(HttpMethod.POST, "/project_instance/upload", file); - } - - async createNewProject(project: NewProjectModel) { - return await this._jsonRequest(HttpMethod.POST, "/project_instance", project); - } - - async setActiveProject(id: string) { - return await this._jsonRequest(HttpMethod.POST, `/project_instance/set/active/project?id=${id}`); - } -} diff --git a/ui/src/features/create_project_instance/create_project_instance_store.ts b/ui/src/features/create_project_instance/create_project_instance_store.ts deleted file mode 100644 index 1730a75..0000000 --- a/ui/src/features/create_project_instance/create_project_instance_store.ts +++ /dev/null @@ -1,39 +0,0 @@ -import makeAutoObservable from "mobx-store-inheritance"; -import { SimpleErrorState } from "../../core/store/base_store"; -import { CreateProjectInstanceRepository } from "./create_project_instance_repository"; -import { message } from "antd"; -import { HttpMethod } from "../../core/repository/http_repository"; -import { NavigateFunction } from "react-router-dom"; -import { NewProjectModel } from "./new_project_model"; - -export class CreateProjectInstanceStore extends SimpleErrorState { - newProjectModel: NewProjectModel; - repository: CreateProjectInstanceRepository; - file?: File; - navigate?: NavigateFunction; - constructor(repository: CreateProjectInstanceRepository) { - super(); - this.repository = repository; - makeAutoObservable(this); - this.newProjectModel = NewProjectModel.empty(); - } - - setProjectDescription(value: string): void { - this.newProjectModel.description = value; - } - init(navigate: NavigateFunction, projectId: string) { - this.navigate = navigate; - this.newProjectModel.project = projectId; - } - async saveInstance(): Promise { - if (this.file === undefined) { - message.error("Need upload file"); - } else { - if (this.newProjectModel.isValid()) { - await this.repository.createNewProject(this.newProjectModel); - await this.repository.setProjectRootFile(this.file); - if (this.navigate !== undefined) this.navigate("/"); - } - } - } -} diff --git a/ui/src/features/create_project_instance/new_project_model.ts b/ui/src/features/create_project_instance/new_project_model.ts deleted file mode 100644 index 805ec64..0000000 --- a/ui/src/features/create_project_instance/new_project_model.ts +++ /dev/null @@ -1,17 +0,0 @@ -export class NewProjectModel { - project: string; - description: string; - constructor(project: string, description: string) { - this.project = project; - this.description = description; - } - static empty() { - return new NewProjectModel("", ""); - } - isValid(): boolean { - return this.project.isNotEmpty() && this.description.isNotEmpty(); - } - messages() { - return ""; - } -} diff --git a/ui/src/features/create_trigger/data/trigger_repository.ts b/ui/src/features/create_trigger/data/trigger_repository.ts deleted file mode 100644 index 9cd2b25..0000000 --- a/ui/src/features/create_trigger/data/trigger_repository.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { HttpMethod, HttpRepository } from "../../../core/repository/http_repository"; -import { ITriggerModel } from "../../../core/model/trigger_model"; - -export class TriggerRepository extends HttpRepository { - public async save(model: ITriggerModel) { - return await this._jsonRequest(HttpMethod.POST, "/trigger", model); - } -} diff --git a/ui/src/features/create_trigger/model/trigger_form_view_model.ts b/ui/src/features/create_trigger/model/trigger_form_view_model.ts deleted file mode 100644 index 9ffe677..0000000 --- a/ui/src/features/create_trigger/model/trigger_form_view_model.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { TriggerType } from "../../../core/model/trigger_model"; - -export interface ITriggerViewValueModel { - value: string; -} - -export interface TriggerViewModel extends ITriggerViewValueModel { - id: string; - type: TriggerType; -} diff --git a/ui/src/features/create_trigger/presentation/components/code_trigger_form.tsx b/ui/src/features/create_trigger/presentation/components/code_trigger_form.tsx deleted file mode 100644 index d399667..0000000 --- a/ui/src/features/create_trigger/presentation/components/code_trigger_form.tsx +++ /dev/null @@ -1,41 +0,0 @@ -import * as React from "react"; -import Editor from "@monaco-editor/react"; -import { Button } from "antd"; -import { observer } from "mobx-react-lite"; -import { CallBackStringVoidFunction } from "../../../../core/extensions/extensions"; - -interface ICodeTriggerFormProps { - codeTriggerValue: string; - clearTriggerCode: VoidFunction; - saveCode: VoidFunction; - writeNewTrigger: CallBackStringVoidFunction; -} - -export const CodeTriggerForm: React.FunctionComponent = observer( - (props: ICodeTriggerFormProps) => { - return ( - <> -
- - { - props.writeNewTrigger(v ?? ""); - }} - onValidate={(_m) => {}} - /> - -
-
- - - - - - ); - } -); diff --git a/ui/src/features/create_trigger/presentation/components/file_trigger_form.tsx b/ui/src/features/create_trigger/presentation/components/file_trigger_form.tsx deleted file mode 100644 index 2f6936d..0000000 --- a/ui/src/features/create_trigger/presentation/components/file_trigger_form.tsx +++ /dev/null @@ -1,51 +0,0 @@ -import * as React from "react"; -import { Formik } from "formik"; -import { SubmitButton, Input, ResetButton, Form, FormItem } from "formik-antd"; -import { Row, Col } from "antd"; -import { observer } from "mobx-react-lite"; -import { TriggerType } from "../../../../core/model/trigger_model"; -import { validateRequired } from "../../../../core/helper/validate"; -export interface IFileTriggerFormProps { - pushTrigger: (value: string, type: TriggerType) => void; -} -export const FileTriggerForm: React.FunctionComponent = observer( - (props: IFileTriggerFormProps) => { - return ( - <> -
- { - props.pushTrigger(values.value, TriggerType.FILE); - actions.setSubmitting(false); - actions.resetForm(); - }} - validate={(values) => { - if (values.value.length === 0) { - return false; - } - return {}; - }} - render={() => ( -
-
- - - - - - Reset - Submit - - -
-
- )} - /> -
- - ); - } -); diff --git a/ui/src/features/create_trigger/presentation/create_trigger_screen.tsx b/ui/src/features/create_trigger/presentation/create_trigger_screen.tsx deleted file mode 100644 index 243f62e..0000000 --- a/ui/src/features/create_trigger/presentation/create_trigger_screen.tsx +++ /dev/null @@ -1,75 +0,0 @@ -import * as React from "react"; -import { Button, Col, Row, Switch, Typography, Input } from "antd"; -import { CodeTriggerForm } from "./components/code_trigger_form"; -import { observer } from "mobx-react-lite"; -import { FileTriggerForm } from "./components/file_trigger_form"; -import { ReactComponent as DeleteIcon } from "../../../core/assets/icons/delete.svg"; -import { Loader } from "../../../core/ui/loader/loader"; -import { TriggerRepository } from "../data/trigger_repository"; -import { TriggerStore } from "./trigger_store"; -import { TriggerViewModel } from "../model/trigger_form_view_model"; -import { CallBackStringVoidFunction } from "../../../core/extensions/extensions"; - -const { Title } = Typography; - -const Bottom = observer((props: { triggers: TriggerViewModel[]; callBack: CallBackStringVoidFunction }) => { - return ( - - {props.triggers.map((el) => { - return ( - - {el.value} - props.callBack(el.id)} /> - - ); - })} - - ); -}); -export const CreateTriggerScreenPath = "/create/trigger"; - -export const TriggerScreen: React.FunctionComponent = observer(() => { - const [triggerStore] = React.useState(() => new TriggerStore(new TriggerRepository())); - return ( - <> -
- {!triggerStore.isLoading ? ( - <> - -
- triggerStore.setTriggerType()} /> -
- Trigger editor: {triggerStore.getTriggerDescription()} -
- -
- triggerStore.changeTriggerDescription} /> - {triggerStore.getTriggerType() ? ( - <> - - - ) : ( - <> - - - )} - - - ) : ( - <> - - - )} -
- - ); -}); diff --git a/ui/src/features/create_trigger/presentation/trigger_store.ts b/ui/src/features/create_trigger/presentation/trigger_store.ts deleted file mode 100644 index bc251d7..0000000 --- a/ui/src/features/create_trigger/presentation/trigger_store.ts +++ /dev/null @@ -1,84 +0,0 @@ -import makeAutoObservable from "mobx-store-inheritance"; -import { v4 as uuidv4 } from "uuid"; -import { TriggerType } from "../../../core/model/trigger_model"; -import { TriggerRepository } from "../data/trigger_repository"; -import { TriggerViewModel } from "../model/trigger_form_view_model"; -import { SimpleErrorState } from "../../../core/store/base_store"; - -export class TriggerStore extends SimpleErrorState { - constructor(repository: TriggerRepository) { - super(); - this.triggerType = TriggerType.FILE; - this.repository = repository; - makeAutoObservable(this); - } - - triggerDescription: string = ""; - triggerType: TriggerType; - codeTriggerValue = ""; - triggers: TriggerViewModel[] = []; - repository: TriggerRepository; - - changeTriggerDescription(value: string): void { - this.triggerDescription = value; - } - - deleteItem(id: string): void { - this.triggers = this.triggers.filter((el) => el.id !== id); - } - - getTriggerType = (): boolean => { - return this.triggerType === TriggerType.FILE; - }; - setTriggerType = (): void => { - this.triggers = []; - if (this.triggerType === TriggerType.FILE) { - this.triggerType = TriggerType.PROCESS; - return; - } - this.triggerType = TriggerType.FILE; - }; - getTriggerDescription = (): string => { - return this.triggerType === TriggerType.FILE ? TriggerType.FILE : TriggerType.PROCESS; - }; - pushTrigger = (value: string, type: TriggerType): void => { - this.triggers.push({ - value: value, - id: uuidv4(), - type: type, - }); - }; - - writeNewTrigger(v: string | undefined): void { - if (v === undefined) { - throw new Error("Editor Value is undefined"); - } - this.codeTriggerValue = v; - } - clearTriggerCode(): void { - this.codeTriggerValue = ""; - } - saveCode(): void { - if (this.codeTriggerValue !== "") { - this.triggers.push({ - id: uuidv4(), - value: this.codeTriggerValue, - type: TriggerType.PROCESS, - }); - - this.codeTriggerValue = ""; - } - } - async saveResult(): Promise { - await this.httpHelper( - this.repository.save({ - type: this.getTriggerDescription(), - description: this.triggerDescription, - value: this.triggers.map((el) => { - return el.value; - }), - }) - ); - } -} -export const triggerStore = new TriggerStore(new TriggerRepository()); diff --git a/ui/src/features/dataset/dataset_form_mock.ts b/ui/src/features/dataset/dataset_form_mock.ts new file mode 100644 index 0000000..0277a82 --- /dev/null +++ b/ui/src/features/dataset/dataset_form_mock.ts @@ -0,0 +1,75 @@ +export const datasetTypes = ["Object Detection - YOLOv8", "Pose Estimation - DOPE"]; + +export const datasetFormMockResult = `{ + "typedataset": \${typedataset:Enum:"ObjectDetection"}, + "dataset_path": \${ПУТЬ ДАТАСЕТА:string:""}, + "models":\${models:Array:[]}, + "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}] + }, + "scene":{ + "objects": \${OBJECTS_SCENE:Array:[]}, + "lights": \${LIGHTS:Array:[]}, + }, + "camera_position":{ + "center_shell": [\${CENTER_SHELL_1:number:0}, \${CENTER_SHELL_2:number:0}, \${CENTER_SHELL_3:number:0}], + "radius_range": [\${RADIUS_RANGE_1:number:0.4}, \${RADIUS_RANGE_2:number:1.4}], + "elevation_range": [\${ELEVATION_RANGE_1:number:10}, \${ELEVATION_RANGE_2:number:90}] + }, + "generation":{ + "n_cam_pose": \${N_CAM_POSE:number:5}, + "n_sample_on_pose": \${N_SAMPLE_ON_POSE:number:3}, + "n_series": \${N_SERIES:number:100}, + "image_format": \${image_format:Enum:"jpg"}, + "image_size_wh": [\${IMAGE_SIZE_WH_1:number:640}, \${IMAGE_SIZE_WH_2:number:480}] + } + } +`; + +export const datasetFormMockContext = ` +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:""}, + "model": \${MODEL:string:"models/1.fbx"} +}; +type OBJECTS_SCENE = { +"name": \${NAME:string:""}, +"collision_shape": \${collision_shape:Enum:"BOX"}, +"loc_xyz": [\${LOC_XYZ_1:number:0}, \${LOC_XYZ_2:number:0}, \${LOC_XYZ_3:number:0}], +"rot_euler": [\${ROT_EULER_1:number:0},\${ROT_EULER_2:number:0}, \${ROT_EULER_3:number:0}], +"material_randomization": { + "specular": [\${SPECULAR_1:number:0}, \${SPECULAR_2:number:1}], + "roughness": [\${ROUGHNESS_1:number:0}, \${ROUGHNESS_2:number:1}], + "metallic": [\${METALLIC_1:number:0}, \${METALLIC_2:number:1}], + "base_color": [ + [ + \${BASE_COLOR_1:number:0}, + \${BASE_COLOR_2:number:0}, + \${BASE_COLOR_3:number:0}, + \${BASE_COLOR_4:number:1} + ], + [ + \${BASE_COLOR_5:number:1}, + \${BASE_COLOR_6:number:1}, + \${BASE_COLOR_7:number:1}, + \${BASE_COLOR_8:number:1} + ] + ] +} +}; +type LIGHTS = { +"id": \${ID:number:1}, +"type": \${type:Enum:"POINT"}, +"loc_xyz": [\${LOC_XYZ_1:number:5}, \${LOC_XYZ_2:number:5}, \${LOC_XYZ_3:number:5}], +"rot_euler": [\${ROT_EULER_1:number:-0.06}, \${ROT_EULER_2:number:0.61}, \${ROT_EULER_3:number:-0.19}], +"color_range_low": [\${COLOR_RANGE_LOW_1:number:0.5}, \${COLOR_RANGE_LOW_2:number:0.5}, \${COLOR_RANGE_LOW_3:number:0.5}], +"color_range_high":[\${COLOR_RANGE_HIGH_1:number:1}, \${COLOR_RANGE_HIGH_2:number:1}, $\{COLOR_RANGE_HIGH_3:number:1}], +"energy_range":[\${ENERGY_RANGE_1:number:400},\${ENERGY_RANGE_2:number:900}] +}; +`; diff --git a/ui/src/features/dataset/dataset_model.ts b/ui/src/features/dataset/dataset_model.ts new file mode 100644 index 0000000..2ce19fb --- /dev/null +++ b/ui/src/features/dataset/dataset_model.ts @@ -0,0 +1,25 @@ +import { InputBuilderViewModel } from "../../core/ui/form_builder/form_view_model"; + +export interface Dataset { + name: string; + local_path: string; + dataSetObjects: string[]; + unixDate: number; + formBuilder: FormBuilder; +} + +export interface FormBuilder { + result: string; + context: string; + form: InputBuilderViewModel[]; +} + +export interface Assets { + assets: Asset[]; +} + +export interface Asset { + name: string; + mesh: string; + image: string; +} diff --git a/ui/src/features/dataset/dataset_repository.ts b/ui/src/features/dataset/dataset_repository.ts new file mode 100644 index 0000000..14f8b2d --- /dev/null +++ b/ui/src/features/dataset/dataset_repository.ts @@ -0,0 +1,16 @@ +import { Result } from "../../core/helper/result"; +import { HttpError, HttpMethod, HttpRepository } from "../../core/repository/http_repository"; +import { Assets, Dataset } from "./dataset_model"; +import { DataSetModel, IDatasetModel } from "./dataset_store"; + +export class DataSetRepository extends HttpRepository { + getAssetsActiveProject = async (): Promise> => { + return this._jsonRequest(HttpMethod.GET, "/projects/assets"); + }; + saveDataSet = async (model: DataSetModel) => { + return this._jsonRequest(HttpMethod.POST, "/datasets", model); + }; + getDatasetsActiveProject = async (): Promise> => { + return this._jsonRequest(HttpMethod.GET, "/datasets"); + }; +} diff --git a/ui/src/features/dataset/dataset_screen.tsx b/ui/src/features/dataset/dataset_screen.tsx new file mode 100644 index 0000000..3cc8ff6 --- /dev/null +++ b/ui/src/features/dataset/dataset_screen.tsx @@ -0,0 +1,94 @@ +import * as React from "react"; +import { Drawer, Button, Radio, Card, Checkbox, Input } from "antd"; +import { FormBuilder } from "../../core/ui/form_builder/form_builder"; +import { datasetFormMockContext, datasetFormMockResult, datasetTypes } from "./dataset_form_mock"; +import { DataSetStore } from "./dataset_store"; +import { observer } from "mobx-react-lite"; + +export const DatasetsScreenPath = "/dataset"; + +export const DataSetScreen: React.FunctionComponent = observer(() => { + const [store] = React.useState(() => new DataSetStore()); + + React.useEffect(() => { + store.init(); + }, [store]); + + const [open, setOpen] = React.useState(false); + const [open1, setOpen1] = React.useState(false); + return ( + <> + + {store.datasets?.isEmpty() ? ( +
empty dataset
+ ) : ( +
+

Datasets

+
+ {store.datasets?.map((el, index) => { + return ( + +

dataset objects:

+
+ {el.dataSetObjects.map((el) => ( +
{el}
+ ))} +
+

process status

+
{el.processStatus}
+ +
+ ); + })} +
+
+ )} + setOpen(false)} open={open}> + (store.dataSetModel.name = e.target.value)} /> + + + + { + store.dataSetModel.datasetType = e.target.value; + }} + > + {datasetTypes.map((el) => ( + <> + {el} + + ))} + + + {store.assets?.assets.map((el) => { + return ( + <> + { + store.dataSetModel.dataSetObjects.push(el.name); + }} + defaultChecked={store.dataSetModel.dataSetObjects.includes(el.name)} + > + include? + + + error + + + ); + })} + + + setOpen1(false)} open={open1}> + { + if (el) store.dataSetModel.formBuilder = el; + }} + /> + + + ); +}); diff --git a/ui/src/features/dataset/dataset_store.ts b/ui/src/features/dataset/dataset_store.ts new file mode 100644 index 0000000..b5e59f9 --- /dev/null +++ b/ui/src/features/dataset/dataset_store.ts @@ -0,0 +1,102 @@ +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 } from "./dataset_model"; +import { datasetFormMockContext, datasetFormMockResult, datasetTypes } from "./dataset_form_mock"; +import { Result } from "../../core/helper/result"; +import { message } from "antd"; + +export class FormBuilderValidationModel { + public result: string; + public context: string; + public form: string[]; + public output: string; + constructor(context: string, result: string, form: string[], output: string) { + this.context = context; + this.result = result; + this.form = form; + this.output = output; + } + static empty() { + return new FormBuilderValidationModel(datasetFormMockContext, datasetFormMockResult, [], ""); + } +} + +export class DataSetModel { + dataSetObjects: string[]; + datasetType: string; + name: string; + formBuilder: FormBuilderValidationModel = FormBuilderValidationModel.empty(); + + constructor(dataSetObjects: string[], datasetType = datasetTypes[0], datasetName: string) { + this.dataSetObjects = dataSetObjects; + this.datasetType = datasetType; + this.name = datasetName; + makeAutoObservable(this); + } + + static empty() { + return new DataSetModel([], "", ""); + } + + isValid(): Result { + if (this.dataSetObjects.isEmpty()) { + return Result.error("not selected details"); + } + if (this.datasetType.isEmpty()) { + return Result.error("dataset type is empty"); + } + if (this.name.isEmpty()) { + return Result.error("dataset name is empty"); + } + return Result.ok(); + } +} + +export class DataSetStore extends UiErrorState { + dataSetRepository: DataSetRepository; + assets?: Assets; + datasets?: IDatasetModel[]; + dataSetModel = DataSetModel.empty(); + constructor() { + super(); + this.dataSetRepository = new DataSetRepository(); + makeAutoObservable(this); + } + errorHandingStrategy = (error: HttpError) => {}; + saveDataset(): void { + this.dataSetModel.isValid().fold( + async () => { + (await this.dataSetRepository.saveDataSet(this.dataSetModel)).fold( + () => { + message.success("save dataset"); + }, + (error) => message.error(error.message) + ); + }, + async (error) => message.error(error) + ); + } + init = async () => { + await this.mapOk("assets", this.dataSetRepository.getAssetsActiveProject()); + await this.mapOk("datasets", this.dataSetRepository.getDatasetsActiveProject()); + }; +} +export interface IDatasetModel { + _id: string; + dataSetObjects: string[]; + processStatus: string; + projectId: string; + name: string; + formBuilder: FormBuilder; + local_path: string; + __v: number; + processLogs: string; +} + +export interface FormBuilder { + result: string; + context: string; + form: any[]; +} diff --git a/ui/src/features/pipeline_instance_main_screen/pipeline_instance_screen.tsx b/ui/src/features/pipeline_instance_main_screen/pipeline_instance_screen.tsx index 5476534..655b400 100644 --- a/ui/src/features/pipeline_instance_main_screen/pipeline_instance_screen.tsx +++ b/ui/src/features/pipeline_instance_main_screen/pipeline_instance_screen.tsx @@ -1,18 +1,32 @@ import * as React from "react"; import { LoadPage } from "../../core/ui/pages/load_page"; import { PipelineInstanceStore } from "./pipeline_instance_store"; - +import { Button } from "antd"; +import { useNavigate } from "react-router-dom"; +import { BehaviorTreeBuilderPath } from "../behavior_tree_builder/presentation/behavior_tree_builder_screen"; +import { SceneManagerPath } from "../scene_manager/presentation/scene_manager"; +import { StickObjectsMarkingScreenPath } from "../stick_objects_marking/stick_objects_marking_screen"; +import { DatasetsScreenPath } from "../dataset/dataset_screen"; export const PipelineInstanceScreenPath = "/pipeline_instance/"; export const PipelineInstanceScreen: React.FunctionComponent = () => { const [pipelineInstanceStore] = React.useState(() => new PipelineInstanceStore()); React.useEffect(() => {}, [pipelineInstanceStore]); + const navigate = useNavigate(); + return (
} + children={ +
+ + + + +
+ } /> ); }; diff --git a/ui/src/features/scene_manager/data/scene_repository.ts b/ui/src/features/scene_manager/data/scene_repository.ts index 30e8575..810e576 100644 --- a/ui/src/features/scene_manager/data/scene_repository.ts +++ b/ui/src/features/scene_manager/data/scene_repository.ts @@ -1,7 +1,7 @@ import { Result } from "../../../core/helper/result"; import { HttpMethod, HttpRepository } from "../../../core/repository/http_repository"; import { CoreError } from "../../../core/store/base_store"; -import { RobossemblerAssets } from "../model/robossembler_assets"; +import { RobossemblerAssets } from "../../../core/model/robossembler_assets"; export class SceneHttpRepository extends HttpRepository { async getRobossemblerAssets() { diff --git a/ui/src/features/scene_manager/model/scene_assets.ts b/ui/src/features/scene_manager/model/scene_assets.ts index 8efc8de..4e1e913 100644 --- a/ui/src/features/scene_manager/model/scene_assets.ts +++ b/ui/src/features/scene_manager/model/scene_assets.ts @@ -1,7 +1,13 @@ import { CameraHelper, Object3D, PerspectiveCamera, Quaternion, Scene, Vector3 } from "three"; import { v4 as uuidv4 } from "uuid"; import { UserData } from "../../../core/repository/core_three_repository"; -import { Asset, Instance, InstanceRgbCamera, InstanceType, SceneSimpleObject } from "./robossembler_assets"; +import { + Asset, + Instance, + InstanceRgbCamera, + InstanceType, + SceneSimpleObject, +} from "../../../core/model/robossembler_assets"; export enum RobossemblerFiles { robossemblerAssets = "robossembler_assets.json", diff --git a/ui/src/features/scene_manager/presentation/scene_manager.tsx b/ui/src/features/scene_manager/presentation/scene_manager.tsx index 47e2884..f3eec84 100644 --- a/ui/src/features/scene_manager/presentation/scene_manager.tsx +++ b/ui/src/features/scene_manager/presentation/scene_manager.tsx @@ -18,7 +18,7 @@ export const SceneManger = observer(() => { React.useEffect(() => { store.init(); - store.loadScene(id, canvasRef.current!); + store.loadScene(canvasRef.current!); document.body.style.overflow = "hidden"; return () => { document.body.style.overflow = "scroll"; 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 2093419..7e38487 100644 --- a/ui/src/features/scene_manager/presentation/scene_manager_store.ts +++ b/ui/src/features/scene_manager/presentation/scene_manager_store.ts @@ -1,6 +1,6 @@ import makeAutoObservable from "mobx-store-inheritance"; -import { CoreThreeRepository, UserData } from "../../../core/repository/core_three_repository"; -import { Object3D, Vector2, Vector3 } from "three"; +import { CoreThreeRepository } from "../../../core/repository/core_three_repository"; +import { Object3D, Vector2 } from "three"; import { HttpError } from "../../../core/repository/http_repository"; import { UiErrorState } from "../../../core/store/base_store"; import { UiBaseError } from "../../../core/model/ui_base_error"; @@ -8,7 +8,7 @@ import { SceneMenu, SceneMode } from "../model/scene_view"; import { BaseSceneItemModel, CameraViewModel, RobossemblerFiles, StaticAssetItemModel } from "../model/scene_assets"; import { SceneHttpRepository } from "../data/scene_repository"; import { message } from "antd"; -import { RobossemblerAssets } from "../model/robossembler_assets"; +import { RobossemblerAssets } from "../../../core/model/robossembler_assets"; export class SceneMangerStore extends UiErrorState { sceneMode: SceneMode; @@ -112,7 +112,7 @@ export class SceneMangerStore extends UiErrorState { } }; - async loadScene(sceneId: string, canvasRef: HTMLCanvasElement) { + async loadScene(canvasRef: HTMLCanvasElement) { this.loadWebGl(canvasRef); await this.mapOk("robossemblerAssets", this.sceneHttpRepository.getRobossemblerAssets()); if (this.robossemblerAssets) { diff --git a/ui/src/features/select_project/data/select_project_repository.ts b/ui/src/features/select_project/data/select_project_repository.ts deleted file mode 100644 index 16607a5..0000000 --- a/ui/src/features/select_project/data/select_project_repository.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { Result } from "../../../core/helper/result"; -import { HttpMethod, HttpRepository } from "../../../core/repository/http_repository"; -import { IProjectModel } from "../model/project_model"; - -export class SelectProjectRepository extends HttpRepository { - async setActiveProject(id: string) { - return await this._jsonRequest(HttpMethod.POST, `/project?${id}`); - } - async getAllProjects(page = 1): Promise> { - return await this._jsonRequest(HttpMethod.GET, `/project?${page}`); - } -} diff --git a/ui/src/features/select_project/model/project_model.ts b/ui/src/features/select_project/model/project_model.ts deleted file mode 100644 index 6b98740..0000000 --- a/ui/src/features/select_project/model/project_model.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { DatabaseModel } from "../../../core/model/database_model"; -import { IProcess } from "../../create_process/model/process_model"; - -export interface IProjectModel extends DatabaseModel { - pipelines: [IProcess]; - rootDir: string; - description: string; -} - \ No newline at end of file diff --git a/ui/src/features/select_project/presentation/select_project.tsx b/ui/src/features/select_project/presentation/select_project.tsx deleted file mode 100644 index c4e29cc..0000000 --- a/ui/src/features/select_project/presentation/select_project.tsx +++ /dev/null @@ -1,40 +0,0 @@ -import * as React from "react"; -import { observer } from "mobx-react-lite"; -import { LoadPage } from "../../../core/ui/pages/load_page"; -import { CreateProjectScreenPath } from "../../create_project/create_project_screen"; -import { SelectProjectStore } from "./select_project_store"; -import { useNavigate } from "react-router-dom"; -import { CreateProjectInstancePath } from "../../create_project_instance/create_project_instance"; -import { Button } from "antd"; -export const SelectProjectScreenPath = "/select_project"; - -export const SelectProjectScreen: React.FunctionComponent = observer(() => { - const [selectProjectStore] = React.useState(() => new SelectProjectStore()); - const navigate = useNavigate(); - - React.useEffect(() => { - selectProjectStore.init(); - }, [selectProjectStore, navigate]); - - return ( - <> - { - return ( - <> -
{el.description}
-
- -
- - ); - })} - /> - - ); -}); diff --git a/ui/src/features/select_project/presentation/select_project_store.ts b/ui/src/features/select_project/presentation/select_project_store.ts deleted file mode 100644 index dd210dd..0000000 --- a/ui/src/features/select_project/presentation/select_project_store.ts +++ /dev/null @@ -1,28 +0,0 @@ -import makeAutoObservable from "mobx-store-inheritance"; -import { SelectProjectRepository } from "../data/select_project_repository"; -import { IProjectModel } from "../model/project_model"; -import { CoreError, UiErrorState } from "../../../core/store/base_store"; - -export class SelectProjectStore extends UiErrorState { - errorHandingStrategy = (error: CoreError) => {}; - repository: SelectProjectRepository; - errors = []; - page = 1; - projects: IProjectModel[] = []; - - constructor() { - super(); - - this.repository = new SelectProjectRepository(); - makeAutoObservable(this); - } - async setActiveProject(id: string): Promise { - this.httpHelper(this.repository.setActiveProject(id)); - } - async getPipelines(): Promise { - await this.mapOk("projects", this.repository.getAllProjects(this.page)); - } - async init() { - await this.getPipelines(); - } -} diff --git a/ui/src/features/stick_objects_marking/model/stick_objects_marking_store_mode.ts b/ui/src/features/stick_objects_marking/model/stick_objects_marking_store_mode.ts new file mode 100644 index 0000000..ef1699e --- /dev/null +++ b/ui/src/features/stick_objects_marking/model/stick_objects_marking_store_mode.ts @@ -0,0 +1,7 @@ +export enum StickObjectsMarkingStoreMode { + objectsToWhichItSticks = "objectsToWhichItSticks", + objectThatSticks = "objectThatSticks", + addPointsObjectsToWhichItSticks = "addPointsObjectsToWhichItSticks", + addPointsObjectThatSticks = "addPointsObjectThatSticks", + move = "move", +} diff --git a/ui/src/features/stick_objects_marking/model/sticky_helper.ts b/ui/src/features/stick_objects_marking/model/sticky_helper.ts new file mode 100644 index 0000000..df82c3c --- /dev/null +++ b/ui/src/features/stick_objects_marking/model/sticky_helper.ts @@ -0,0 +1,20 @@ +import { Vector3 } from "three"; + +export class StickyHelper { + objectThatSticksName: string; + objectThatSticksNamePoints: Vector3[] = []; + objectsToWhichItSticksName: string; + objectsToWhichItSticksPoints: Vector3[] = []; + + constructor( + objectThatSticksName: string, + objectThatSticksNamePoints: Vector3[], + objectsToWhichItSticksName: string, + objectsToWhichItSticksPoints: Vector3[] + ) { + this.objectThatSticksName = objectThatSticksName; + this.objectThatSticksNamePoints = objectThatSticksNamePoints; + this.objectsToWhichItSticksName = objectsToWhichItSticksName; + this.objectsToWhichItSticksPoints = objectsToWhichItSticksPoints; + } +} diff --git a/ui/src/features/stick_objects_marking/model/sticky_loader_mode.ts b/ui/src/features/stick_objects_marking/model/sticky_loader_mode.ts new file mode 100644 index 0000000..3c21147 --- /dev/null +++ b/ui/src/features/stick_objects_marking/model/sticky_loader_mode.ts @@ -0,0 +1,4 @@ +export enum StickyLoaderMode { + IN = "IN", + OUT = "OUT", +} diff --git a/ui/src/features/stick_objects_marking/stick_objects_marking_screen.tsx b/ui/src/features/stick_objects_marking/stick_objects_marking_screen.tsx index 74d0056..dc16830 100644 --- a/ui/src/features/stick_objects_marking/stick_objects_marking_screen.tsx +++ b/ui/src/features/stick_objects_marking/stick_objects_marking_screen.tsx @@ -2,8 +2,10 @@ import * as React from "react"; import { observer } from "mobx-react-lite"; import { useParams } from "react-router-dom"; import { Button } from "antd"; -import { StickObjectsMarkingStore, StickObjectsMarkingStoreMode } from "./stick_objects_marking_store"; +import { StickObjectsMarkingStore } from "./stick_objects_marking_store"; import { Vector3 } from "three"; +import { StickObjectsMarkingStoreMode } from "./model/stick_objects_marking_store_mode"; +import { StickyLoaderMode } from "./model/sticky_loader_mode"; export const StickObjectsMarking = "/stick/objects/marking"; interface StickButtonsProps { @@ -53,7 +55,7 @@ export const StickButtons: React.FunctionComponent = observer ); }); - +export const StickObjectsMarkingScreenPath = "/sticky/objects/mark"; export const StickObjectsMarkingScreen = observer(() => { const canvasRef = React.useRef(null); const [store] = React.useState(() => new StickObjectsMarkingStore()); @@ -82,7 +84,20 @@ export const StickObjectsMarkingScreen = observer(() => { width: "100vw", }} > -
+
+ {store.stickyObjects?.map((el) => { + return ( +
+
+ + +
+
{el.name}
+
+ ); + })} +
+ {/*
{Object.keys(store.points).map((el) => { // @ts-expect-error const v = store.points[el]; @@ -126,7 +141,7 @@ export const StickObjectsMarkingScreen = observer(() => { run
-
+
*/}
); diff --git a/ui/src/features/stick_objects_marking/stick_objects_marking_store.tsx b/ui/src/features/stick_objects_marking/stick_objects_marking_store.tsx index 644f9f1..dc68b23 100644 --- a/ui/src/features/stick_objects_marking/stick_objects_marking_store.tsx +++ b/ui/src/features/stick_objects_marking/stick_objects_marking_store.tsx @@ -6,76 +6,48 @@ import { UiBaseError } from "../../core/model/ui_base_error"; import { RobossemblerFiles } from "../scene_manager/model/scene_assets"; import { StickObjectsMarkingThreeRepository } from "./stick_objects_marking_three_repository"; import { UserData } from "../../core/repository/core_three_repository"; -import { ObjectExtensionsIsKeyExists } from "../../core/extensions/object"; - -export enum StickObjectsMarkingStoreMode { - objectsToWhichItSticks = "objectsToWhichItSticks", - objectThatSticks = "objectThatSticks", - addPointsObjectsToWhichItSticks = "addPointsObjectsToWhichItSticks", - addPointsObjectThatSticks = "addPointsObjectThatSticks", - move = "move", -} - -export class StickyHelper { - objectThatSticksName: string; - objectThatSticksNamePoints: Vector3[] = []; - objectsToWhichItSticksName: string; - objectsToWhichItSticksPoints: Vector3[] = []; - - constructor( - objectThatSticksName: string, - objectThatSticksNamePoints: Vector3[], - objectsToWhichItSticksName: string, - objectsToWhichItSticksPoints: Vector3[] - ) { - this.objectThatSticksName = objectThatSticksName; - this.objectThatSticksNamePoints = objectThatSticksNamePoints; - this.objectsToWhichItSticksName = objectsToWhichItSticksName; - this.objectsToWhichItSticksPoints = objectsToWhichItSticksPoints; - } -} +import { SceneHttpRepository } from "../scene_manager/data/scene_repository"; +import { Asset, RobossemblerAssets } from "../../core/model/robossembler_assets"; +import { StickObjectsMarkingStoreMode } from "./model/stick_objects_marking_store_mode"; +import { StickyHelper } from "./model/sticky_helper"; +import { StickyLoaderMode } from "./model/sticky_loader_mode"; export class StickObjectsMarkingStore extends UiErrorState { mode: StickObjectsMarkingStoreMode; stickObjectsMarkingThreeRepository: null | StickObjectsMarkingThreeRepository = null; + sceneHttpRepository: SceneHttpRepository; objectThatSticksName: string; objectThatSticksNamePoints: Vector3[] = []; objectsToWhichItSticksName: string; objectsToWhichItSticksPoints: Vector3[] = []; + sceneAssets?: RobossemblerAssets; points = {}; + + get stickyObjects() { + return this.sceneAssets?.assets.filter((el) => el.actions.includes("Sticking")); + } + constructor() { super(); makeAutoObservable(this); this.points = {}; this.mode = StickObjectsMarkingStoreMode.move; - this.loadStickyJSON( - '{"objectThatSticksName":"cube2","objectThatSticksNamePoints":[{"x":5,"y":-0.5419443937360455,"z":0.041458499858311626}],"objectsToWhichItSticksName":"cube1","objectsToWhichItSticksPoints":[{"x":-5,"y":-2.2134708060033113,"z":1.1937718220731925}]}' - ); + this.sceneHttpRepository = new SceneHttpRepository(); } updatePoint = (key: string, value: any) => { // @ts-expect-error this.points[key] = value; }; - onSaveSticky(): void { - window.prompt( - "Copy to clipboard: Ctrl+C, Enter", - JSON.stringify( - new StickyHelper( - this.objectThatSticksName, - this.objectThatSticksNamePoints, - this.objectsToWhichItSticksName, - this.objectsToWhichItSticksPoints - ) - ) - ); - } + onSaveSticky(): void {} setMode(stickObjectsMarkingStoreMode: StickObjectsMarkingStoreMode): void { this.mode = stickObjectsMarkingStoreMode; } loaderWatcher() {} - async init(): Promise {} + async init(): Promise { + this.mapOk("sceneAssets", this.sceneHttpRepository.getRobossemblerAssets()); + } errorHandingStrategy = (error: HttpError) => { if (error.status === 404) { @@ -137,28 +109,12 @@ export class StickObjectsMarkingStore extends UiErrorState { }); } } - + loadAsset(asset: Asset, mode: StickyLoaderMode): void { + this.stickObjectsMarkingThreeRepository?.loadInstance(asset,() =>{ + + }); + } dispose() { window.removeEventListener("click", this.clickLister); } - loadStickyJSON(value: string): void { - const object = JSON.parse(value) as Object; - if ( - ObjectExtensionsIsKeyExists(object, [ - "objectThatSticksName", - "objectThatSticksNamePoints", - "objectsToWhichItSticksName", - "objectsToWhichItSticksPoints", - ]) - ) { - // @ts-expect-error - this.objectThatSticksName = object["objectThatSticksName"]; - // @ts-expect-error - this.objectThatSticksNamePoints = object["objectThatSticksNamePoints"]; - // @ts-expect-error - this.objectsToWhichItSticksName = object["objectsToWhichItSticksName"]; - // @ts-expect-error - this.objectsToWhichItSticksPoints = object["objectsToWhichItSticksPoints"]; - } - } } diff --git a/ui/src/features/stick_objects_marking/stick_objects_marking_three_repository.ts b/ui/src/features/stick_objects_marking/stick_objects_marking_three_repository.ts index b9f136d..67f3846 100644 --- a/ui/src/features/stick_objects_marking/stick_objects_marking_three_repository.ts +++ b/ui/src/features/stick_objects_marking/stick_objects_marking_three_repository.ts @@ -1,7 +1,7 @@ import { Box3, BoxGeometry, Mesh, MeshBasicMaterial, Object3D, Vector3 } from "three"; import { CoreThreeRepository } from "../../core/repository/core_three_repository"; -import { StickyHelper } from "./stick_objects_marking_store"; import { CoreVector3 } from "../../core/model/core_vector3"; +import { StickyHelper } from "./model/sticky_helper"; export class StickObjectsMarkingThreeRepository extends CoreThreeRepository { stickyObjects: StickyHelper[]; @@ -45,9 +45,8 @@ export class StickObjectsMarkingThreeRepository extends CoreThreeRepository { ); }); } - getCenter(obj: Object3D) { - return new Box3().setFromObject(obj).getCenter(new Vector3()); - } + getCenter = (obj: Object3D) => new Box3().setFromObject(obj).getCenter(new Vector3()); + sceneWatcher() { this.transformControls.addEventListener("objectChange", (event) => { //@ts-expect-error @@ -55,11 +54,7 @@ export class StickObjectsMarkingThreeRepository extends CoreThreeRepository { this.stickyObjects.forEach((stickyHelper) => { if (sceneActiveObject.name === stickyHelper.objectThatSticksName) { - //локальные векторы точек - const objectThatSticksNameLocalVector = stickyHelper.objectThatSticksNamePoints[0]; const objectsToWhichItSticksPointLocalVector = stickyHelper.objectsToWhichItSticksPoints[0]; - - //глобальные векторы обьектов const globalVectorObjStickyName = this.scene.getObjectByName(stickyHelper.objectThatSticksName); const globalVectorObjToWhichSticks = this.scene.getObjectByName(stickyHelper.objectsToWhichItSticksName); @@ -72,28 +67,11 @@ export class StickObjectsMarkingThreeRepository extends CoreThreeRepository { .getObjectByName("cube2:point:0objectThatSticksNamePoints") ?.position.copy(objectsToWhichItSticksNamePosition); - // this.scene.getObjectByName("cube2:point:0objectThatSticksNamePoints")?.position; - globalVectorObjStickyName?.position.copy( this.scene .getObjectByName("cube2:point:0objectThatSticksNamePoints")! .position.add(objectsToWhichItSticksPointLocalVector) ); - - // console.log(this.scene.children.map((e) => console.log(e.name))); - // cube2:point:0objectThatSticksNamePoints - // cube1:point:0objectsToWhichItSticksPoints - - // this.makePoint(objectThatSticksNamePosition, "red", 1.1); - // this.makePoint(objectsToWhichItSticksNamePosition, "red", 1.1); - - // const movePosition = objectThatSticksNamePosition.sub(objectsToWhichItSticksNamePosition); - // const movePosition = new Vector3().subVectors( - // objectThatSticksNamePosition, - // objectsToWhichItSticksNamePosition - // ); - - // this.scene.getObjectByName(stickyHelper.objectsToWhichItSticksName)?.position.copy(movePosition); } }); }); diff --git a/ui/src/index.tsx b/ui/src/index.tsx index e93ad76..69c84c6 100644 --- a/ui/src/index.tsx +++ b/ui/src/index.tsx @@ -8,24 +8,14 @@ import { extensions } from "./core/extensions/extensions"; import { SocketLister } from "./features/socket_lister/socket_lister"; import { RouterProvider } from "react-router-dom"; import { router } from "./core/routers/routers"; -import { SceneManger } from "./features/scene_manager/presentation/scene_manager"; -import { BehaviorTreeBuilderScreen } from "./features/behavior_tree_builder/presentation/behavior_tree_builder_screen"; -import { StickObjectsMarkingScreen } from "./features/stick_objects_marking/stick_objects_marking_screen"; extensions(); const root = ReactDOM.createRoot(document.getElementById("root") as HTMLElement); root.render( <> - {/* */} - {/* */} - - {/* */} - <> - {/* */} - {/* */} - - - + + + ); diff --git a/ui/tsconfig.json b/ui/tsconfig.json index f13dfaf..ebca409 100644 --- a/ui/tsconfig.json +++ b/ui/tsconfig.json @@ -1,6 +1,6 @@ { "compilerOptions": { - "target": "es5", + "target": "es6", "lib": ["dom", "dom.iterable", "esnext"], "allowJs": true, "skipLibCheck": true,