This commit is contained in:
IDONTSUDO 2024-08-13 13:03:28 +03:00
parent d41310196f
commit 48be3e6d33
110 changed files with 1722 additions and 1145 deletions

View file

@ -199,7 +199,6 @@ export class CoreHttpController<V> implements ICoreHttpController {
if (req.query.page !== undefined) {
payload = String(req.query.page);
}
if (req.query.id !== undefined) {
payload = String(req.query.id);
}

View file

@ -1,10 +1,11 @@
import { BehaviorTreesPresentation } from "../../features/behavior_trees/behavior_trees_presentation";
import { DatasetsPresentation } from "../../features/datasets/datasets_presentation";
import { WeightsPresentation } from "../../features/weights/weights_presentation";
import { CalculationsTemplatePresentation } from "../../features/calculations_templates/calculations_template_presentation";
import { ProjectsPresentation } from "../../features/projects/projects_presentation";
import { extensions } from "../extensions/extensions";
import { Routes } from "../interfaces/router";
import { ScenePresentation } from "../../features/scene/scene_presentation";
import { ScenesPresentation } from "../../features/scenes/scenes_presentation";
import { CalculationsInstancesPresentation } from "../../features/calculations_instance/calculations_instance_presentation";
extensions();
@ -12,6 +13,7 @@ export const httpRoutes: Routes[] = [
new ProjectsPresentation(),
new DatasetsPresentation(),
new BehaviorTreesPresentation(),
new WeightsPresentation(),
new ScenePresentation()
new CalculationsTemplatePresentation(),
new ScenesPresentation(),
new CalculationsInstancesPresentation(),
].map((el) => el.call());

View file

@ -1,44 +0,0 @@
// import { Service } from "typedi";
// @Service()
// export class IEnv{
// rootFolder!: string;
// constructor(){
// }
// toStringEnv(){
// return ''
// }
// static env(){
// return ''
// }
// }
// @Service()
// export class DevEnv implements IEnv {
// rootFolder:string;
// constructor(rootFolder:string){
// this.rootFolder = rootFolder
// }
// toStringEnv(): string {
// return DevEnv.env()
// }
// static env(){
// return 'DevEnv'
// }
// }
// @Service()
// export class UnitTestEnv implements IEnv{
// rootFolder:string;
// constructor(rootFolder:string){
// this.rootFolder = rootFolder
// }
// toStringEnv(): string {
// return UnitTestEnv.env()
// }
// static env(){
// return 'UnitTestEnv'
// }
// }

View file

@ -1,53 +0,0 @@
// import { DevEnv, IEnv, UnitTestEnv } from "./env";
// import { extensions } from "../extensions/extensions";
// // import { Container, Service } from 'typedi';
// export default function locator(env: IEnv) {
// extensions();
// envRegister(env);
// registerRepository(env);
// registerController(env);
// registerService(env);
// // override(MetaDataFileManagerModel, MetaDataFileManagerModel);
// }
// const envRegister = (env: IEnv) => {
// switch (env.toStringEnv()) {
// case UnitTestEnv.env():
// // override(IEnv, UnitTestEnv);
// return;
// case "DevEnv":
// // override(IEnv, DevEnv);
// return;
// }
// };
// const registerRepository = (env: IEnv) => {
// switch (env.toStringEnv()) {
// case UnitTestEnv.env():
// // override(IEnv, UnitTestEnv);
// return;
// case DevEnv.env():
// // override(IEnv, DevEnv);
// return;
// }
// };
// const registerController = (env: IEnv) => {
// switch (env.toStringEnv()) {
// case UnitTestEnv.env():
// return;
// case DevEnv.env():
// return;
// }
// };
// const registerService = (env: IEnv) => {
// switch (env.toStringEnv()) {
// case UnitTestEnv.env():
// return;
// case DevEnv.env():
// return;
// }
// };

View file

@ -1,8 +1,9 @@
export enum StaticFiles {
robossembler_assets = "robossembler_assets.json",
assets = "/assets/assets.json",
parts = '/assets/parts.json',
robots = '/robots/',
scenes = '/scenes/',
behaviorTrees = 'behavior_trees'
parts = "/assets/parts.json",
robots = "/robots/",
scenes = "/scenes/",
behaviorTrees = "behavior_trees",
process = "/process/",
}

View file

@ -22,7 +22,7 @@ export class FileSystemRepository {
}
return await this.readFileAsync(path);
}
deleteFile = async (path: string) => {
delete = async (path: string) => {
return await this.deleteDir(path);
};
readDirRecursive(path: string, filesToDir: string[] = []): string[] {

View file

@ -5,7 +5,7 @@ export class DeleteFileUseCase {
fileSystemRepository = new FileSystemRepository();
call = (path: string) => {
try {
this.fileSystemRepository.deleteFile(path);
this.fileSystemRepository.delete(path);
return Result.ok("file delete");
} catch {
return Result.error("Unknown error");

View file

@ -4,7 +4,6 @@ import { FileSystemRepository } from "../repository/file_system_repository";
export class DeleteRecursiveFolderUseCase{
repository:FileSystemRepository = new FileSystemRepository()
call = async (path:string):Promise<Result<void,void>> =>{
console.log(path)
await this.repository.deleteDirRecursive(path)
return Result.ok()
}

View file

@ -2,12 +2,12 @@ import { CrudController } from "../../core/controllers/crud_controller";
import { TriggerDBModel } from "./models/trigger_database_model";
import { TriggerModelValidationModel } from "./models/trigger_validation_model";
export class TriggerPresentation extends CrudController<TriggerModelValidationModel, typeof TriggerDBModel> {
constructor() {
super({
url: "trigger",
validationModel: TriggerModelValidationModel,
databaseModel: TriggerDBModel,
});
}
}
// export class TriggerPresentation extends CrudController<TriggerModelValidationModel, typeof TriggerDBModel> {
// constructor() {
// super({
// url: "trigger",
// validationModel: TriggerModelValidationModel,
// databaseModel: TriggerDBModel,
// });
// }
// }

View file

@ -0,0 +1,28 @@
import { CrudController } from "../../core/controllers/crud_controller";
import { ExecCalculationInstanceProcessScenario } from "./domain/exec_calculations_instance_process_scenario";
import { CalculationInstanceValidationModel } from "./models/calculations_instance_validation_model";
import { CalculationInstanceDBModel } from "./models/calculations_instance_database_model";
import { CreateCalculationInstanceScenario } from "./domain/create_calculation_instance_scenario";
import { DeleteCalculationsInstanceScenario } from "./domain/delete_calculations_instance_scenario";
export class CalculationsInstancesPresentation extends CrudController<
CalculationInstanceValidationModel,
typeof CalculationInstanceDBModel
> {
constructor() {
super({
url: "calculations/instances",
validationModel: CalculationInstanceValidationModel,
databaseModel: CalculationInstanceDBModel,
});
super.delete(new DeleteCalculationsInstanceScenario().call);
super.post(new CreateCalculationInstanceScenario().call);
this.subRoutes.push({
method: "GET",
subUrl: "exec",
fn: new ExecCalculationInstanceProcessScenario(),
});
}
}

View file

@ -0,0 +1,15 @@
import { CallbackStrategyWithValidationModel, ResponseBase } from "../../../core/controllers/http_controller";
import { CreateDataBaseModelUseCase } from "../../../core/usecases/create_database_model_usecase";
import { CreateFolderUseCase } from "../../../core/usecases/create_folder_usecase";
import { CalculationInstanceDBModel } from "../models/calculations_instance_database_model";
import { CalculationInstanceValidationModel } from "../models/calculations_instance_validation_model";
export class CreateCalculationInstanceScenario extends CallbackStrategyWithValidationModel<CalculationInstanceValidationModel> {
validationModel: CalculationInstanceValidationModel = new CalculationInstanceValidationModel();
call = async (model: CalculationInstanceValidationModel): ResponseBase => {
model.instancePath = `${model.path}/${model.instanceName}`;
return (await new CreateFolderUseCase().call(model.instancePath)).map(
async () => await new CreateDataBaseModelUseCase(CalculationInstanceDBModel).call(model)
);
};
}

View file

@ -0,0 +1,21 @@
import { CallbackStrategyWithIdQuery, ResponseBase } from "../../../core/controllers/http_controller";
import { DeleteDataBaseModelUseCase } from "../../../core/usecases/delete_database_model_usecase";
import { DeleteRecursiveFolderUseCase } from "../../../core/usecases/delete_recursive_folder_usecase";
import { ReadByIdDataBaseModelUseCase } from "../../../core/usecases/read_by_id_database_model_usecase";
import { CoreValidation } from "../../../core/validations/core_validation";
import { MongoIdValidation } from "../../../core/validations/mongo_id_validation";
import { CalculationsTemplateDBModel } from "../../calculations_templates/models/calculations_template_database_model";
import { CalculationInstanceDBModel } from "../models/calculations_instance_database_model";
import { CalculationInstanceValidationModel } from "../models/calculations_instance_validation_model";
export class DeleteCalculationsInstanceScenario extends CallbackStrategyWithIdQuery {
idValidationExpression: CoreValidation = new MongoIdValidation();
call = async (id: string): ResponseBase =>
(
await new ReadByIdDataBaseModelUseCase<CalculationInstanceValidationModel>(CalculationInstanceDBModel).call(id)
).map(async (model) => {
return (await new DeleteRecursiveFolderUseCase().call(model.instancePath)).map(
async () => await new DeleteDataBaseModelUseCase(CalculationInstanceDBModel).call(id)
);
});
}

View file

@ -0,0 +1,35 @@
import { ObjectId } from "mongoose";
import { CallbackStrategyWithIdQuery, ResponseBase } from "../../../core/controllers/http_controller";
import { ExecProcessUseCase, IsHaveActiveProcessUseCase } from "../../../core/usecases/exec_process_usecase";
import { ReadByIdDataBaseModelUseCase } from "../../../core/usecases/read_by_id_database_model_usecase";
import { MongoIdValidation } from "../../../core/validations/mongo_id_validation";
import { ProcessWatcherAndDatabaseUpdateService } from "../../datasets/domain/create_dataset_scenario";
import { CalculationInstanceDBModel, ICalculationInstance } from "../models/calculations_instance_database_model";
import { Result } from "../../../core/helpers/result";
export class ExecCalculationInstanceProcessScenario extends CallbackStrategyWithIdQuery {
idValidationExpression = new MongoIdValidation();
call = async (id: string): ResponseBase =>
(await new ReadByIdDataBaseModelUseCase<ICalculationInstance>(CalculationInstanceDBModel).call(id)).map(
async (model) => {
return (await new IsHaveActiveProcessUseCase().call()).map(async () => {
const execCommand = `${model.script} --form ${JSON.stringify(model.formBuilder)} --path ${
model.instancePath
}`;
await CalculationInstanceDBModel.findById(id).updateOne({
processStatus: "RUN",
lastProcessExecCommand: execCommand,
});
new ExecProcessUseCase().call(
// @ts-expect-error
`${model.project.rootDir}/`,
execCommand,
id,
new ProcessWatcherAndDatabaseUpdateService(id as unknown as ObjectId, CalculationInstanceDBModel)
);
return Result.ok("OK");
});
}
);
}

View file

@ -1,11 +1,11 @@
import { ResponseBase } from "../../../core/controllers/http_controller";
import { SearchManyDataBaseModelUseCase } from "../../../core/usecases/search_many_database_model_usecase";
import { GetActiveProjectIdScenario } from "../../projects/domain/get_active_project_id_scenario";
import { IWeightModel, WeightDBModel } from "../models/weights_validation_model";
import { ICalculationInstance, CalculationInstanceDBModel } from "../models/calculations_instance_database_model";
export class GetAllWeightsActiveProjectScenarios {
call = async (): ResponseBase =>
(await new GetActiveProjectIdScenario().call()).map(
async (model) => await new SearchManyDataBaseModelUseCase<IWeightModel>(WeightDBModel).call({ project: model.id })
async (model) => await new SearchManyDataBaseModelUseCase<ICalculationInstance>(CalculationInstanceDBModel).call({ project: model.id })
);
}

View file

@ -0,0 +1,77 @@
import { Schema, model } from "mongoose";
import { FormBuilderValidationModel } from "../../datasets/models/dataset_validation_model";
import { IProjectModel, projectSchema } from "../../projects/models/project_model_database_model";
export interface ICalculationInstance {
script: string;
instancePath: string;
formBuilder: FormBuilderValidationModel;
type: string;
name: string;
isEnd: boolean;
createDate: Date;
card?: string;
lastProcessLogs?: string;
lastProcessExecCommand?: string;
lastExecDate?: Date;
processStatus: string;
project?: IProjectModel | string;
}
export const CalculationInstanceSchema = new Schema({
script: {
type: String,
},
formBuilder: {
type: Schema.Types.Mixed,
},
type: {
type: String,
},
instanceName: {
type: String,
},
name: {
type: String,
},
isEnd: {
type: Boolean,
},
createDate: {
type: String,
},
card: {
type: String,
},
lastProcessLogs: {
type: String,
},
lastProcessExecCommand: {
type: String,
},
lastExecDate: {
type: String,
},
processStatus: {
type: String,
},
path: {
type: String,
},
instancePath: {
type: String,
},
project: {
type: Schema.Types.ObjectId,
ref: projectSchema,
autopopulate: true,
require: true,
},
}).plugin(require("mongoose-autopopulate"));
export const calculationInstanceSchema = "calculations_instances";
export const CalculationInstanceDBModel = model<ICalculationInstance>(
calculationInstanceSchema,
CalculationInstanceSchema
);

View file

@ -0,0 +1,31 @@
import { IsNotEmpty, IsString, IsMongoId } from "class-validator";
import { ICalculationInstance } from "./calculations_instance_database_model";
import { FormBuilderValidationModel } from "../../datasets/models/dataset_validation_model";
import { IProjectModel } from "../../projects/models/project_model_database_model";
export class CalculationInstanceValidationModel implements ICalculationInstance {
@IsNotEmpty()
@IsString()
instanceName: string;
instancePath: string;
processStatus: string;
@IsString()
path: string;
project?: string | IProjectModel;
@IsString()
@IsNotEmpty()
script: string;
formBuilder: FormBuilderValidationModel;
@IsString()
@IsNotEmpty()
type: string;
@IsString()
@IsNotEmpty()
name: string;
isEnd: boolean = false;
createDate: Date = new Date();
card?: string;
lastProcessLogs?: string;
lastProcessExecCommand?: string;
lastExecDate?: Date;
}

View file

@ -0,0 +1,20 @@
import { CrudController } from "../../core/controllers/crud_controller";
import { CreateCalculationsTemplateScenario } from "./domain/create_calculations_template_scenario";
import { DeleteCalculationsTemplateScenario } from "./domain/delete_calculations_template_scenario";
import { CalculationsTemplateValidationModel as CalculationsTemplateValidationModel } from "./models/calculations_template_validation_model";
import { CalculationsTemplateDBModel } from "./models/calculations_template_database_model";
export class CalculationsTemplatePresentation extends CrudController<
CalculationsTemplateValidationModel,
typeof CalculationsTemplateDBModel
> {
constructor() {
super({
url: "calculations/template",
validationModel: CalculationsTemplateValidationModel,
databaseModel: CalculationsTemplateDBModel,
});
super.post(new CreateCalculationsTemplateScenario().call);
super.delete(new DeleteCalculationsTemplateScenario().call);
}
}

View file

@ -0,0 +1,27 @@
import { CallbackStrategyWithValidationModel, ResponseBase } from "../../../core/controllers/http_controller";
import { Result } from "../../../core/helpers/result";
import { StaticFiles } from "../../../core/models/static_files";
import { CreateDataBaseModelUseCase } from "../../../core/usecases/create_database_model_usecase";
import { CreateFolderUseCase } from "../../../core/usecases/create_folder_usecase";
import { SearchOneDataBaseModelUseCase } from "../../../core/usecases/search_database_model_usecase";
import { IProjectModel, ProjectDBModel } from "../../projects/models/project_model_database_model";
import { CalculationsTemplateValidationModel } from "../models/calculations_template_validation_model";
import { CalculationsTemplateDBModel } from "../models/calculations_template_database_model";
export class CreateCalculationsTemplateScenario extends CallbackStrategyWithValidationModel<CalculationsTemplateValidationModel> {
validationModel: CalculationsTemplateValidationModel = new CalculationsTemplateValidationModel();
call = async (model: CalculationsTemplateValidationModel): ResponseBase => {
return (
await new SearchOneDataBaseModelUseCase<IProjectModel>(ProjectDBModel).call(
{ isActive: true },
"no active projects"
)
).map(async (project) => {
model.path = project.rootDir + StaticFiles.process + model.name;
return (await new CreateFolderUseCase().call(model.path)).map(() => {
return new CreateDataBaseModelUseCase(CalculationsTemplateDBModel).call(model);
});
});
};
}

View file

@ -0,0 +1,20 @@
import { CallbackStrategyWithIdQuery, ResponseBase } from "../../../core/controllers/http_controller";
import { DeleteDataBaseModelUseCase } from "../../../core/usecases/delete_database_model_usecase";
import { DeleteRecursiveFolderUseCase } from "../../../core/usecases/delete_recursive_folder_usecase";
import { ReadByIdDataBaseModelUseCase } from "../../../core/usecases/read_by_id_database_model_usecase";
import { CoreValidation } from "../../../core/validations/core_validation";
import { MongoIdValidation } from "../../../core/validations/mongo_id_validation";
import { CalculationsTemplateDBModel } from "../models/calculations_template_database_model";
import { CalculationsTemplateValidationModel } from "../models/calculations_template_validation_model";
export class DeleteCalculationsTemplateScenario extends CallbackStrategyWithIdQuery {
idValidationExpression: CoreValidation = new MongoIdValidation();
call = async (id: string): ResponseBase =>
(
await new ReadByIdDataBaseModelUseCase<CalculationsTemplateValidationModel>(CalculationsTemplateDBModel).call(id)
).map(async (model) => {
return (await new DeleteRecursiveFolderUseCase().call(model.path)).map(
async () => await new DeleteDataBaseModelUseCase(CalculationsTemplateDBModel).call(id)
);
});
}

View file

@ -0,0 +1,11 @@
import { ResponseBase } from "../../../core/controllers/http_controller";
import { SearchManyDataBaseModelUseCase } from "../../../core/usecases/search_many_database_model_usecase";
import { GetActiveProjectIdScenario } from "../../projects/domain/get_active_project_id_scenario";
import { ICalculationsTemplateModel, CalculationsTemplateDBModel } from "../models/calculations_template_database_model";
export class GetAllCalculationsTemplateScenarios {
call = async (): ResponseBase =>
(await new GetActiveProjectIdScenario().call()).map(
async (model) => await new SearchManyDataBaseModelUseCase<ICalculationsTemplateModel>(CalculationsTemplateDBModel).call({ project: model.id })
);
}

View file

@ -0,0 +1,54 @@
import { Schema, model } from "mongoose";
import { FormBuilderValidationModel, IDatasetModel } from "../../datasets/models/dataset_validation_model";
import { IProjectModel, projectSchema } from "../../projects/models/project_model_database_model";
export interface ICalculationsTemplateModel {
path?: string;
script: string;
formBuilder: FormBuilderValidationModel;
type: string;
name: string;
isEnd: boolean;
createDate: Date;
card?: string;
lastProcessLogs?: string;
lastProcessExecCommand?: string;
lastExecDate?: Date;
processStatus: string;
project?: IProjectModel | string;
}
export const CalculationsTemplateSchema = new Schema({
script: {
type: String,
},
formBuilder: {
type: Schema.Types.Mixed,
},
type: {
type: String,
},
name: {
type: String,
},
createDate: {
type: Number,
},
card: {
type: String,
},
project: {
type: Schema.Types.ObjectId,
ref: projectSchema,
autopopulate: true,
require: true,
},
path: {
type: String,
},
}).plugin(require("mongoose-autopopulate"));
export const calculationsTemplateSchema = "calculations_templates";
export const CalculationsTemplateDBModel = model<ICalculationsTemplateModel>(calculationsTemplateSchema, CalculationsTemplateSchema);

View file

@ -0,0 +1,27 @@
import { IsNotEmpty, IsString, IsMongoId } from "class-validator";
import { ICalculationsTemplateModel } from "./calculations_template_database_model";
import { FormBuilderValidationModel } from "../../datasets/models/dataset_validation_model";
import { IProjectModel } from "../../projects/models/project_model_database_model";
export class CalculationsTemplateValidationModel implements ICalculationsTemplateModel {
processStatus: string;
@IsMongoId()
project?: string | IProjectModel;
@IsString()
@IsNotEmpty()
script: string;
formBuilder: FormBuilderValidationModel;
@IsString()
@IsNotEmpty()
type: string;
@IsString()
@IsNotEmpty()
name: string;
isEnd: boolean = true;
createDate: Date = new Date();
card?: string;
lastProcessLogs?: string;
lastProcessExecCommand?: string;
lastExecDate?: Date;
path: string;
}

View file

@ -25,24 +25,22 @@ export class ProcessWatcherAndDatabaseUpdateService<A> extends TypedEvent<
event.fold(
async (success) => {
if (success.event == EXEC_EVENT.END) {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-expect-error
const dbModel = await this.model.findById(this.databaseId);
if (dbModel !== null) {
dbModel.local_path;
dbModel.processStatus = ProcessStatus.END;
dbModel.processLogs = success.data;
dbModel.lastProcessLogs = success.data;
await dbModel.save();
}
}
},
async (error) => {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-expect-error
const dbModel = await this.model.findById(this.databaseId);
if (dbModel !== null) {
dbModel.processStatus = ProcessStatus.ERROR;
dbModel.processLogs = error.message;
dbModel.lastProcessLogs = error.message;
await dbModel.save();
}
}

View file

@ -1,31 +0,0 @@
import { CallbackStrategyWithIdQuery, ResponseBase } from "../../core/controllers/http_controller";
import { Result } from "../../core/helpers/result";
import { StaticFiles } from "../../core/models/static_files";
import { CreateFileUseCase } from "../../core/usecases/create_file_usecase";
import { ReadByIdDataBaseModelUseCase } from "../../core/usecases/read_by_id_database_model_usecase";
import { ReadFileAndParseJsonUseCase } from "../../core/usecases/read_file_and_parse_json";
import { SearchManyDataBaseModelUseCase } from "../../core/usecases/search_many_database_model_usecase";
import { CoreValidation } from "../../core/validations/core_validation";
import { MongoIdValidation } from "../../core/validations/mongo_id_validation";
import { IProjectModel, ProjectDBModel } from "../projects/models/project_model_database_model";
import { SceneAssets, SceneModel } from "./create_new_scene_scenario";
import { SceneDBModel } from "./scene_database_model";
export class ReadSceneScenario extends CallbackStrategyWithIdQuery {
idValidationExpression: CoreValidation = new MongoIdValidation();
call = async (id: string): ResponseBase =>
(await new ReadByIdDataBaseModelUseCase<SceneModel>(SceneDBModel).call(id)).map(async (model) =>
(
await new SearchManyDataBaseModelUseCase<IProjectModel>(ProjectDBModel).call(
{ isActive: true },
"is dont active projects"
)
).map(async (projectModel) => {
const { rootDir } = projectModel[0];
return (await new ReadFileAndParseJsonUseCase().call(`${rootDir}${StaticFiles.scenes}${model.name}.json`)).map(
async (sceneAsset) => Result.ok(sceneAsset)
);
})
);
}

View file

@ -1,33 +0,0 @@
import { CrudController } from "../../core/controllers/crud_controller";
import { ReadByIdDataBaseModelScenario } from "../../core/scenarios/read_by_id_database_model_scenario";
import { BehaviorTreeDBModel } from "../behavior_trees/models/behavior_tree_database_model";
import { BehaviorTreeValidationModel } from "../behavior_trees/models/behavior_tree_validation_model";
import { CreateNewSceneScenario } from "./create_new_scene_scenario";
import { CreateRobotScenario } from "./create_robot_scenario";
import { EditSceneScenario } from "./edit_scene_scenario";
import { ReadSceneScenario } from "./read_scene_scenario";
import { SceneDBModel } from "./scene_database_model";
import { SceneValidationModel } from "./scene_validation_model";
export class ScenePresentation extends CrudController<SceneValidationModel, typeof SceneDBModel> {
constructor() {
super({
url: "scenes",
validationModel: SceneValidationModel,
databaseModel: SceneDBModel,
});
super.post(new CreateNewSceneScenario().call);
super.put(new EditSceneScenario().call);
this.subRoutes.push({
method: "POST",
subUrl: "create/robot",
fn: new CreateRobotScenario(),
});
this.subRoutes.push({
method: "GET",
subUrl: "by_id",
fn: new ReadSceneScenario(),
});
}
}

View file

@ -1,15 +1,12 @@
import { IsString } from "class-validator";
import { CallbackStrategyWithValidationModel, ResponseBase } from "../../core/controllers/http_controller";
import { Result } from "../../core/helpers/result";
import { CreateFileUseCase } from "../../core/usecases/create_file_usecase";
import { GetActiveProjectIdScenario } from "../projects/domain/get_active_project_id_scenario";
import { model } from "mongoose";
import { SearchManyDataBaseModelUseCase } from "../../core/usecases/search_many_database_model_usecase";
import { IProjectModel, ProjectDBModel } from "../projects/models/project_model_database_model";
import { StaticFiles } from "../../core/models/static_files";
import { CreateDataBaseModelUseCase } from "../../core/usecases/create_database_model_usecase";
import { SceneDBModel } from "./scene_database_model";
import { SceneValidationModel } from "./scene_validation_model";
import { CallbackStrategyWithValidationModel, ResponseBase } from "../../../core/controllers/http_controller";
import { Result } from "../../../core/helpers/result";
import { CreateFileUseCase } from "../../../core/usecases/create_file_usecase";
import { SearchManyDataBaseModelUseCase } from "../../../core/usecases/search_many_database_model_usecase";
import { IProjectModel, ProjectDBModel } from "../../projects/models/project_model_database_model";
import { StaticFiles } from "../../../core/models/static_files";
import { CreateDataBaseModelUseCase } from "../../../core/usecases/create_database_model_usecase";
import { SceneDBModel } from "../model/scene_database_model";
export class SceneModel {
@IsString()
name: string;

View file

@ -1,11 +1,11 @@
import { CallbackStrategyWithValidationModel, ResponseBase } from "../../core/controllers/http_controller";
import { Result } from "../../core/helpers/result";
import { RobotModel } from "./robot_model";
import { StaticFiles } from "../../core/models/static_files";
import { GetServerAddressUseCase } from "../../core/usecases/get_server_address_usecase";
import { SearchManyDataBaseModelUseCase } from "../../core/usecases/search_many_database_model_usecase";
import { IProjectModel, ProjectDBModel } from "../projects/models/project_model_database_model";
import { ExecProcessUseCase } from "../../core/usecases/exec_process_usecase";
import { CallbackStrategyWithValidationModel, ResponseBase } from "../../../core/controllers/http_controller";
import { Result } from "../../../core/helpers/result";
import { RobotModel } from "../model/robot_model";
import { StaticFiles } from "../../../core/models/static_files";
import { GetServerAddressUseCase } from "../../../core/usecases/get_server_address_usecase";
import { SearchManyDataBaseModelUseCase } from "../../../core/usecases/search_many_database_model_usecase";
import { IProjectModel, ProjectDBModel } from "../../projects/models/project_model_database_model";
import { ExecProcessUseCase } from "../../../core/usecases/exec_process_usecase";
export class CreateRobotScenario extends CallbackStrategyWithValidationModel<RobotModel> {
validationModel: RobotModel = new RobotModel();

View file

@ -1,13 +1,13 @@
import { CallbackStrategyWithIdQuery, ResponseBase } from "../../core/controllers/http_controller";
import { Result } from "../../core/helpers/result";
import { StaticFiles } from "../../core/models/static_files";
import { DeleteDataBaseModelUseCase } from "../../core/usecases/delete_database_model_usecase";
import { DeleteFileUseCase } from "../../core/usecases/delete_file_usecase";
import { ReadByIdDataBaseModelUseCase } from "../../core/usecases/read_by_id_database_model_usecase";
import { SearchManyDataBaseModelUseCase } from "../../core/usecases/search_many_database_model_usecase";
import { CoreValidation } from "../../core/validations/core_validation";
import { MongoIdValidation } from "../../core/validations/mongo_id_validation";
import { IProjectModel, ProjectDBModel } from "../projects/models/project_model_database_model";
import { CallbackStrategyWithIdQuery, ResponseBase } from "../../../core/controllers/http_controller";
import { Result } from "../../../core/helpers/result";
import { StaticFiles } from "../../../core/models/static_files";
import { DeleteDataBaseModelUseCase } from "../../../core/usecases/delete_database_model_usecase";
import { DeleteFileUseCase } from "../../../core/usecases/delete_file_usecase";
import { ReadByIdDataBaseModelUseCase } from "../../../core/usecases/read_by_id_database_model_usecase";
import { SearchManyDataBaseModelUseCase } from "../../../core/usecases/search_many_database_model_usecase";
import { CoreValidation } from "../../../core/validations/core_validation";
import { MongoIdValidation } from "../../../core/validations/mongo_id_validation";
import { IProjectModel, ProjectDBModel } from "../../projects/models/project_model_database_model";
import { SceneModel } from "./create_new_scene_scenario";
export class DeleteSceneScenario extends CallbackStrategyWithIdQuery {

View file

@ -1,11 +1,10 @@
import { CallbackStrategyWithValidationModel, ResponseBase } from "../../core/controllers/http_controller";
import { Result } from "../../core/helpers/result";
import { StaticFiles } from "../../core/models/static_files";
import { CreateFileUseCase } from "../../core/usecases/create_file_usecase";
import { SearchManyDataBaseModelUseCase } from "../../core/usecases/search_many_database_model_usecase";
import { IProjectModel, ProjectDBModel } from "../projects/models/project_model_database_model";
import { SceneAssets } from "./create_new_scene_scenario";
import { SceneValidationModel } from "./scene_validation_model";
import { CallbackStrategyWithValidationModel, ResponseBase } from "../../../core/controllers/http_controller";
import { Result } from "../../../core/helpers/result";
import { StaticFiles } from "../../../core/models/static_files";
import { CreateFileUseCase } from "../../../core/usecases/create_file_usecase";
import { SearchManyDataBaseModelUseCase } from "../../../core/usecases/search_many_database_model_usecase";
import { IProjectModel, ProjectDBModel } from "../../projects/models/project_model_database_model";
import { SceneValidationModel } from "../model/scene_validation_model";
export class EditSceneScenario extends CallbackStrategyWithValidationModel<SceneValidationModel> {
validationModel: SceneValidationModel;

View file

@ -0,0 +1,30 @@
import { CallbackStrategyWithIdQuery, ResponseBase } from "../../../core/controllers/http_controller";
import { Result } from "../../../core/helpers/result";
import { StaticFiles } from "../../../core/models/static_files";
import { ReadByIdDataBaseModelUseCase } from "../../../core/usecases/read_by_id_database_model_usecase";
import { ReadFileAndParseJsonUseCase } from "../../../core/usecases/read_file_and_parse_json";
import { SearchManyDataBaseModelUseCase } from "../../../core/usecases/search_many_database_model_usecase";
import { CoreValidation } from "../../../core/validations/core_validation";
import { MongoIdValidation } from "../../../core/validations/mongo_id_validation";
import { IProjectModel, ProjectDBModel } from "../../projects/models/project_model_database_model";
import { SceneModel } from "./create_new_scene_scenario";
import { SceneDBModel } from "../model/scene_database_model";
export class ReadSceneScenario extends CallbackStrategyWithIdQuery {
idValidationExpression: CoreValidation = new MongoIdValidation();
call = async (id: string): ResponseBase =>
(await new ReadByIdDataBaseModelUseCase<SceneModel>(SceneDBModel).call(id)).map(async (model) =>
(
await new SearchManyDataBaseModelUseCase<IProjectModel>(ProjectDBModel).call(
{ isActive: true },
"is dont active projects"
)
).map(async (projectModel) => {
const { rootDir } = projectModel[0];
return (await new ReadFileAndParseJsonUseCase().call(`${rootDir}${StaticFiles.scenes}${model.name}.json`)).map(
async (sceneAsset) => Result.ok(sceneAsset)
);
})
);
}

View file

@ -0,0 +1,30 @@
import { CrudController } from "../../core/controllers/crud_controller";
import { CreateNewSceneScenario } from "./domain/create_new_scene_scenario";
import { CreateRobotScenario } from "./domain/create_robot_scenario";
import { EditSceneScenario } from "./domain/edit_scene_scenario";
import { ReadSceneScenario } from "./domain/read_scene_scenario";
import { SceneDBModel } from "./model/scene_database_model";
import { SceneValidationModel } from "./model/scene_validation_model";
export class ScenesPresentation extends CrudController<SceneValidationModel, typeof SceneDBModel> {
constructor() {
super({
url: "scenes",
validationModel: SceneValidationModel,
databaseModel: SceneDBModel,
});
super.post(new CreateNewSceneScenario().call);
super.put(new EditSceneScenario().call);
this.subRoutes.push({
method: "POST",
subUrl: "create/robot",
fn: new CreateRobotScenario(),
});
this.subRoutes.push({
method: "GET",
subUrl: "by_id",
fn: new ReadSceneScenario(),
});
}
}

View file

@ -1,44 +0,0 @@
import { ObjectId } from "mongoose";
import { CallbackStrategyWithIdQuery, ResponseBase } from "../../../core/controllers/http_controller";
import { Result } from "../../../core/helpers/result";
import { ExecProcessUseCase, IsHaveActiveProcessUseCase } from "../../../core/usecases/exec_process_usecase";
import { ReadByIdDataBaseModelUseCase } from "../../../core/usecases/read_by_id_database_model_usecase";
import { MongoIdValidation } from "../../../core/validations/mongo_id_validation";
import { ProcessWatcherAndDatabaseUpdateService } from "../../datasets/domain/create_dataset_scenario";
import { WeightDBModel, IWeightModel } from "../models/weights_validation_model";
import { match } from "ts-pattern";
import { FolderStructure } from "../../projects/domain/upload_file_to_to_project_scenario";
export class ExecWeightProcessScenario extends CallbackStrategyWithIdQuery {
idValidationExpression = new MongoIdValidation();
call = async (id: string): ResponseBase =>
(await new ReadByIdDataBaseModelUseCase<IWeightModel>(WeightDBModel).call(id)).map(async (model) => {
return (await new IsHaveActiveProcessUseCase().call()).map(async () => {
await WeightDBModel.findById(id).updateOne({ processStatus: "RUN" });
return match(model.processStatus)
.with("exec", "RUN", "none", () => this.exec(id, model))
.with('before_training' , () => this.exec(id, model, true))
.otherwise(() => Result.error(`model status is ${model.processStatus}`));
});
});
exec = (id: string, model: IWeightModel, preTrain?: boolean) =>
match(typeof model.project === "object" && typeof model.datasetId === "object")
.returnType<ResponseBase>()
.with(true, async () => {
if (typeof model.project === "object" && typeof model.datasetId === "object") {
let execCommand = `python3 $PYTHON_EDUCATION --path ${model.project.rootDir}/${FolderStructure.datasets} --name ${model.name} --datasetName ${model.datasetId.name} --outpath ${model.project.rootDir}/${FolderStructure.weights} --type ${model.datasetId.formBuilder.output.typedataset} --epoch ${model.epoch}`;
if (preTrain) {
execCommand += ` --pretrain`;
}
return await new ExecProcessUseCase().call(
`${model.project.rootDir}/`,
execCommand,
id,
new ProcessWatcherAndDatabaseUpdateService(id as unknown as ObjectId, WeightDBModel)
);
}
})
.with(false, async () => Result.error("model is unknown"));
}

View file

@ -1,15 +0,0 @@
import { IsNumber, IsOptional, IsString } from "class-validator";
import { IWeightModel } from "./weights_validation_model";
export class WeightValidationModel implements IWeightModel {
public numberOfTrainedEpochs: number;
public processStatus: string;
@IsNumber()
public epoch: number;
@IsString()
public name: string;
public datasetId: string;
public project: string;
@IsOptional()
public isFinished:boolean;
}

View file

@ -1,60 +0,0 @@
import { Schema, model } from "mongoose";
import { datasetSchema } from "../../datasets/models/dataset_database_model";
import { IDatasetModel } from "../../datasets/models/dataset_validation_model";
import { IProjectModel, projectSchema } from "../../projects/models/project_model_database_model";
export interface IWeightModel {
name: string;
datasetId: string | IDatasetModel;
project: string | IProjectModel;
processStatus: string;
epoch: number;
numberOfTrainedEpochs: number;
}
export const WeightSchema = new Schema({
name: {
type: String,
},
local_path: {
type: String,
},
numberOfTrainedEpochs: {
type: Number,
default:0,
},
neuralNetworkName: {
type: String,
},
processStatus: {
type: String,
default: "none",
},
// the user selects
isFinished: {
type: Boolean,
default: false,
},
epoch: {
type: Number,
},
datasetId: {
type: Schema.Types.ObjectId,
ref: datasetSchema,
autopopulate: true,
require: true,
},
project: {
type: Schema.Types.ObjectId,
ref: projectSchema,
autopopulate: true,
require: true,
},
processLogs: {
type: String,
},
}).plugin(require("mongoose-autopopulate"));
export const weightSchema = "Weight";
export const WeightDBModel = model<IWeightModel>(weightSchema, WeightSchema);

View file

@ -1,21 +0,0 @@
import { CrudController } from "../../core/controllers/crud_controller";
import { ExecWeightProcessScenario } from "./domain/exec_weights_process_scenario";
import { GetAllWeightsActiveProjectScenarios } from "./domain/get_all_weights_active_project_scenarios";
import { WeightValidationModel } from "./models/weights_database_model";
import { WeightDBModel } from "./models/weights_validation_model";
export class WeightsPresentation extends CrudController<WeightValidationModel, typeof WeightDBModel> {
constructor() {
super({
url: "weights",
validationModel: WeightValidationModel,
databaseModel: WeightDBModel,
});
super.get(new GetAllWeightsActiveProjectScenarios().call);
this.subRoutes.push({
method: "GET",
subUrl: "exec",
fn: new ExecWeightProcessScenario(),
});
}
}

View file

@ -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 { App, Environment, ServerStatus } from "../src/core/controllers/app";
import { httpRoutes } from "../src/core/controllers/routes";
import { DataBaseConnectUseCase } from "../src/core/usecases/database_connect_usecase";
@ -51,7 +51,7 @@ const unitTest = async () => {
testCore.assert(await new usecase().test(), usecase.name);
}
};
const presentationCrudControllers = [new TriggerPresentation()];
const presentationCrudControllers = [];
const e2eTest = async () => {
const app = new App(httpRoutes, [], Environment.E2E_TEST);
await new Promise((resolve, reject) => {

View file

@ -24,7 +24,110 @@
[contenteditable]:focus {
outline: 0px solid transparent;
}
/* Absolute Center Spinner */
.loading {
}
/* Transparent Overlay */
.loading:before {
content: '';
display: block;
}
/* :not(:required) hides these rules from IE9 and below */
.loading:not(:required) {
/* hide "loading..." text */
font: 0/0 a;
color: transparent;
text-shadow: none;
background-color: transparent;
border: 0;
}
.loading:not(:required):after {
margin-top: 14px;
content: '';
display: block;
font-size: 8px;
width: 8px;
height: 8px;
-webkit-animation: spinner 1500ms infinite linear;
-moz-animation: spinner 1500ms infinite linear;
-ms-animation: spinner 1500ms infinite linear;
-o-animation: spinner 1500ms infinite linear;
animation: spinner 1500ms infinite linear;
border-radius: 0.5em;
-webkit-box-shadow: white 1.5em 0 0 0, white 1.1em 1.1em 0 0, white 0 1.5em 0 0, white -1.1em 1.1em 0 0, rgba(0, 0, 0, 0.5) -1.5em 0 0 0, rgba(0, 0, 0, 0.5) -1.1em -1.1em 0 0, white 0 -1.5em 0 0, white 1.1em -1.1em 0 0;
box-shadow: white 1.5em 0 0 0, white 1.1em 1.1em 0 0, white 0 1.5em 0 0, white -1.1em 1.1em 0 0, white -1.5em 0 0 0, white -1.1em -1.1em 0 0, white 0 -1.5em 0 0, white 1.1em -1.1em 0 0;
}
/* Animation */
@-webkit-keyframes spinner {
0% {
-webkit-transform: rotate(0deg);
-moz-transform: rotate(0deg);
-ms-transform: rotate(0deg);
-o-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(360deg);
-moz-transform: rotate(360deg);
-ms-transform: rotate(360deg);
-o-transform: rotate(360deg);
transform: rotate(360deg);
}
}
@-moz-keyframes spinner {
0% {
-webkit-transform: rotate(0deg);
-moz-transform: rotate(0deg);
-ms-transform: rotate(0deg);
-o-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(360deg);
-moz-transform: rotate(360deg);
-ms-transform: rotate(360deg);
-o-transform: rotate(360deg);
transform: rotate(360deg);
}
}
@-o-keyframes spinner {
0% {
-webkit-transform: rotate(0deg);
-moz-transform: rotate(0deg);
-ms-transform: rotate(0deg);
-o-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(360deg);
-moz-transform: rotate(360deg);
-ms-transform: rotate(360deg);
-o-transform: rotate(360deg);
transform: rotate(360deg);
}
}
@keyframes spinner {
0% {
-webkit-transform: rotate(0deg);
-moz-transform: rotate(0deg);
-ms-transform: rotate(0deg);
-o-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(360deg);
-moz-transform: rotate(360deg);
-ms-transform: rotate(360deg);
-o-transform: rotate(360deg);
transform: rotate(360deg);
}
}
</style>
</html>

View file

@ -2,6 +2,15 @@ import { Result } from "../helper/result";
/* eslint-disable @typescript-eslint/no-this-alias */
export const ArrayExtensions = () => {
if ([].indexOfR === undefined) {
Array.prototype.indexOfR = function (element) {
if (this.indexOf(element) === -1) {
return Result.error(undefined);
}
return Result.ok(this);
};
}
if ([].equals === undefined) {
Array.prototype.equals = function (array, strict = true) {
if (!array) return false;

View file

@ -0,0 +1,40 @@
export const DateExtensions = () => {
if (Date.prototype.fromUnixDate === undefined) {
Date.prototype.fromUnixDate = function (unix) {
return new Date(unix * 1000);
};
}
if (Date.prototype.formatDate === undefined) {
Date.prototype.formatDate = function () {
const days = ["Воскресенье", "Понедельник", "Вторник", "Среда", "Четверг", "Пятница", "Суббота"];
const monthNames = [
"Января",
"Февраля",
"Марта",
"Апреля",
"Майя",
"Июня",
"Июля",
"Августа",
"Сентября",
"Октября",
"Ноября",
"Декабря",
];
return (
days[this.getDay()] +
", " +
this.getDate() +
", " +
monthNames[this.getMonth()] +
", " +
this.getFullYear() +
"г.," +
this.getHours() +
":" +
this.getMinutes()
);
};
}
};

View file

@ -1,5 +1,6 @@
import { Result } from "../helper/result";
import { ArrayExtensions } from "./array";
import { DateExtensions } from "./date";
import { MapExtensions } from "./map";
import { NumberExtensions } from "./number";
import { StringExtensions } from "./string";
@ -24,6 +25,11 @@ declare global {
rFind<T>(predicate: (value: T, index: number, obj: never[]) => boolean, thisArg?: any): Result<void, T>;
maxLength(length: number): Array<T>;
add(element: T): Array<T>;
indexOfR(element: T): Result<void, Array<T>>;
}
interface Date {
formatDate(): string;
fromUnixDate(unix: number): Date;
}
interface Number {
fromArray(): number[];
@ -69,4 +75,5 @@ export const extensions = () => {
ArrayExtensions();
NumberExtensions();
MapExtensions();
DateExtensions();
};

View file

@ -11,15 +11,17 @@ export class SolidModel implements Instance {
type = SceneModelsTypes.SOLID;
@Type(() => Vector3)
public position: Vector3;
public name: string;
constructor(
vector3: Vector3,
public orientation: number[],
public name: string,
name:string,
public solidType: string,
public mesh: string,
public collisionMesh: string,
public spawnType: string
) {
this.name = name;
this.position = vector3;
}
toSceneItems = (): SceneItems => {

View file

@ -2,7 +2,7 @@ import { Result } from "../helper/result";
import { validate, ValidationError } from "class-validator";
export class ValidationModel {
valid = async (): Promise<Result<string, ValidationModel>> => {
valid = async <T>(): Promise<Result<string, T>> => {
const errors: ValidationError[] = await validate(this, {
skipMissingProperties: false,
whitelist: false,
@ -16,7 +16,7 @@ export class ValidationModel {
});
return Result.error(message.join(","));
} else {
return Result.ok(this);
return Result.ok(this as unknown as T);
}
};
}

View file

@ -8,6 +8,7 @@ export class SocketRepository extends TypedEvent<any> {
async connect():Promise<Result<boolean, boolean>> {
const socket = io(this.serverURL);
this.socket = socket;
socket.connect();
socket.on('realtime', (d) =>{

View file

@ -33,7 +33,7 @@ import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
import { TransformControls } from "three/examples/jsm/controls/TransformControls";
import { SceneMode } from "../../features/scene_manager/model/scene_view";
import { UrdfTransforms, coordsToQuaternion } from "../../features/simulations/tranforms_model";
import { ISpawnHelper, SceneItems } from "../../features/scene_manager/presentation/scene_manager_store";
import { SceneItems } from "../../features/scene_manager/presentation/scene_manager_store";
import { SolidModel } from "../model/solid_model";
import { Instance, SceneAsset } from "../model/scene_asset";
import { ZoneModel } from "../model/zone_model";
@ -41,7 +41,7 @@ import { TypedEvent } from "../helper/typed_event";
import { Result } from "../helper/result";
import { RobotModel } from "../model/robot_model";
// Object3D.DEFAULT_UP = new Vector3(0, 0, 1);
Object3D.DEFAULT_UP = new Vector3(0, 0, 1);
export enum UserData {
selectedObject = "selected_object",
@ -186,6 +186,8 @@ export class CoreThreeRepository extends TypedEvent<any> {
);
loadUrdfRobot = (robotModel: RobotModel) =>
this.urdfLoader.load(robotModel.httpUrl, (robot) => {
console.log(robot);
// Object3D.DEFAULT_UP = new Vector3(0, 0, 1);
robot.userData[UserData.selectedObject] = true;
robot.name = robotModel.name;
if (robotModel.position) robot.position.copy(robotModel.position);
@ -361,6 +363,7 @@ export class CoreThreeRepository extends TypedEvent<any> {
const gridHelper = new GridHelper(1000, 100, 0x888888, 0x444444);
gridHelper.userData = {};
gridHelper.userData[UserData.cameraInitialization] = true;
gridHelper.rotation.x = -Math.PI / 2;
this.scene.add(gridHelper);
}

View file

@ -5,12 +5,11 @@ import {
BehaviorTreeBuilderPath,
BehaviorTreeBuilderScreen,
} from "../../features/behavior_tree_builder/presentation/behavior_tree_builder_screen";
import { DataSetScreen, DatasetsScreenPath } from "../../features/dataset/dataset_screen";
import { AssemblesScreen, AssemblesScreenPath } from "../../features/assembles/assembles_screen";
import { SimulationScreen, SimulationScreenPath } from "../../features/simulations/simulations_screen";
import { EstimateScreen, EstimateScreenPath } from "../../features/estimate/estimate_screen";
import { MachineLearningPath, MachineLearningScreen } from "../../features/machine_learning/presentation/machine_learning_screen";
import { CalculationScreenPath, CalculationScreen } from "../../features/calculation/presentation/calculation_screen";
import { DetailsScreenPath, DetailsScreen } from "../../features/details/details_screen";
const idURL = ":id";
@ -57,7 +56,7 @@ export const router = createBrowserRouter([
element: <EstimateScreen />,
},
{
path: MachineLearningPath,
element: <MachineLearningScreen />,
path: CalculationScreenPath,
element: <CalculationScreen />,
},
]);

View file

@ -1,8 +1,9 @@
import { NavigateFunction } from "react-router-dom";
import { Result } from "../helper/result";
import { UiBaseError } from "../model/ui_base_error";
import { HttpError } from "../repository/http_repository";
import { HttpError } from "../repository/core_http_repository";
import { message } from "antd";
import { ClassConstructor, plainToInstance } from "class-transformer";
export type CoreError = HttpError | Error;
@ -74,7 +75,10 @@ export class ModalStore extends SimpleErrorState {
};
}
export abstract class UiErrorState<T> extends UiLoader {
abstract errorHandingStrategy: (error: T) => void;
errorHandingStrategy = (error: T) => {
// message.error(error as any);
console.log(error);
};
abstract init(navigate?: NavigateFunction): Promise<any>;
dispose() {}
errors: UiBaseError[] = [];
@ -105,12 +109,18 @@ export abstract class DrawerState<E> extends UiErrorState<E> {
export abstract class UiDrawerFormState<V, E> extends DrawerState<E> {
abstract viewModel: V;
updateForm(value: Partial<V>) {
// {"id":"123","userId":"132"}
//@ts-ignore
this.viewModel = Object.assign(this.viewModel, value);
console.log(this.viewModel)
}
loadDependency = (viewModel: V) => {
this.viewModel = viewModel;
};
loadClassInstance = (instance: ClassConstructor<V>, viewModel: V) => {
this.viewModel = plainToInstance(instance, viewModel);
};
}
export abstract class FormState<V, E> extends UiErrorState<E> {
abstract viewModel: V;
@ -121,4 +131,7 @@ export abstract class FormState<V, E> extends UiErrorState<E> {
loadDependency = (viewModel: V | undefined) => {
if (viewModel) this.viewModel = viewModel;
};
loadClassInstance = (instance: ClassConstructor<V>, viewModel: V) => {
this.viewModel = plainToInstance(instance, viewModel);
};
}

View file

@ -0,0 +1,80 @@
{
"center_shell": [
0,
0,
0
],
"scene": {
"details": [
{
"name": "body_down",
"part_path": "parts/objects/body_down.stl",
"material_path": "",
"mass": 100,
"inertia": {
"ixx": 0.1,
"ixy": 0,
"ixz": 0,
"iyy": 0.1,
"iyz": 0,
"izz": 0.1
},
"visual": ".dae",
"collision": ".stl",
"stlUrl": "http://localhost:4001/d370204b-205b-44bb-9698-3bf083b4b7a7/assets/parts/objects/body_down.stl",
"glUrl": "http://localhost:4001/d370204b-205b-44bb-9698-3bf083b4b7a7/assets/libs/objects/body_down.glb",
"daeUrl": "http://localhost:4001/d370204b-205b-44bb-9698-3bf083b4b7a7/assets/libs/objects/body_down.dae",
"objUrl": "http://localhost:4001/d370204b-205b-44bb-9698-3bf083b4b7a7/assets/libs/objects/body_down.obj",
"image": "http://localhost:4001/d370204b-205b-44bb-9698-3bf083b4b7a7/assets/libs/objects/body_down.png",
"solidType": "active",
"isSelect": true
},
{
"name": "sol_gear",
"part_path": "parts/objects/sol_gear.stl",
"material_path": "",
"mass": 100,
"inertia": {
"ixx": 0.1,
"ixy": 0,
"ixz": 0,
"iyy": 0.1,
"iyz": 0,
"izz": 0.1
},
"visual": ".dae",
"collision": ".stl",
"stlUrl": "http://localhost:4001/d370204b-205b-44bb-9698-3bf083b4b7a7/assets/parts/objects/sol_gear.stl",
"glUrl": "http://localhost:4001/d370204b-205b-44bb-9698-3bf083b4b7a7/assets/libs/objects/sol_gear.glb",
"daeUrl": "http://localhost:4001/d370204b-205b-44bb-9698-3bf083b4b7a7/assets/libs/objects/sol_gear.dae",
"objUrl": "http://localhost:4001/d370204b-205b-44bb-9698-3bf083b4b7a7/assets/libs/objects/sol_gear.obj",
"image": "http://localhost:4001/d370204b-205b-44bb-9698-3bf083b4b7a7/assets/libs/objects/sol_gear.png",
"solidType": "active",
"isSelect": true
},
{
"name": "output_shaft",
"part_path": "parts/objects/output_shaft.stl",
"material_path": "",
"mass": 100,
"inertia": {
"ixx": 0.1,
"ixy": 0,
"ixz": 0,
"iyy": 0.1,
"iyz": 0,
"izz": 0.1
},
"visual": ".dae",
"collision": ".stl",
"stlUrl": "http://localhost:4001/d370204b-205b-44bb-9698-3bf083b4b7a7/assets/parts/objects/output_shaft.stl",
"glUrl": "http://localhost:4001/d370204b-205b-44bb-9698-3bf083b4b7a7/assets/libs/objects/output_shaft.glb",
"daeUrl": "http://localhost:4001/d370204b-205b-44bb-9698-3bf083b4b7a7/assets/libs/objects/output_shaft.dae",
"objUrl": "http://localhost:4001/d370204b-205b-44bb-9698-3bf083b4b7a7/assets/libs/objects/output_shaft.obj",
"image": "http://localhost:4001/d370204b-205b-44bb-9698-3bf083b4b7a7/assets/libs/objects/output_shaft.png",
"solidType": "active",
"isSelect": true
}
]
}
}

View file

@ -38,8 +38,8 @@ export const FormBuilder = observer((props: IFormBuilder) => {
<>Error</>
) : (
<div>
{store.formViewModel?.inputs.map((element) => {
if (element.type.isEqual(InputType.ENUM)) {
{store.formViewModel?.inputs?.map((element) => {
if (element.type?.isEqual(InputType.ENUM)) {
const values = element.values as string[];
return (
<CoreSelect
@ -51,7 +51,7 @@ export const FormBuilder = observer((props: IFormBuilder) => {
/>
);
}
if (element.type.isEqual(InputType.ARRAY)) {
if (element.type?.isEqual(InputType.ARRAY)) {
return (
<div style={{ border: "1px black solid", margin: 20 }}>
<div
@ -131,7 +131,7 @@ export const FormBuilder = observer((props: IFormBuilder) => {
);
}
if (element.type.isEqualMany([InputType.NUMBER, InputType.STRING]))
if (element.type?.isEqualMany([InputType.NUMBER, InputType.STRING]))
return (
<div>
<CoreInput
@ -146,16 +146,13 @@ export const FormBuilder = observer((props: IFormBuilder) => {
/>
</div>
);
if (element.type.isEqual(InputType.OBJECT))
if (element.type?.isEqual(InputType.OBJECT))
return (
<>
{getFormBuilderComponents(
element.name.replace(">", "").replace("<", "").replace("/", ""),
element.totalValue ?? element.defaultValue,
(text) => {
store.changeTotalValue(element.id, text);
}
(text) => store.changeTotalValue(element.id, text)
).fold(
(s) => (
<>{s}</>
@ -166,7 +163,7 @@ export const FormBuilder = observer((props: IFormBuilder) => {
)}
</>
);
return <>Error</>;
return <>Error {element}</>;
})}
</div>
)}

View file

@ -47,9 +47,11 @@ export class FormBuilderStore {
changeTotalValue(id: string, value: any) {
if (this.formViewModel?.inputs)
this.formViewModel.inputs = this.formViewModel?.inputs.map((el) => {
if (!el.id.isEqual(id)) {
return el;
}
if (value instanceof String) {
el.totalValue = value;
}else{

View file

@ -85,6 +85,7 @@ export class FormViewModel {
}
public json() {
const result = this.toResult();
console.log(result)
if (result.isEmpty()) {
console.log("result is Empty error");
return;
@ -115,7 +116,7 @@ export class FormViewModel {
inputResult = Number(inputResult);
}
if (element.type.isEqual(InputType.OBJECT)) {
inputResult = JSON.stringify(element.totalValue ?? element.defaultValue);
inputResult = element.totalValue ?? element.defaultValue
}
if (element.type.isEqual(InputType.ARRAY)) {
if (element.totalValue === undefined) {

View file

@ -1,8 +1,10 @@
import { Result } from "../../../helper/result";
import { SelectScene } from "./select_scene/select_scene";
import { SelectDatasetScreen } from "./select_dataset/presentation/select_dataset_screen";
import { SelectDetail } from "./select_detail/presentation/select_detail_screen";
export enum FormBuilderComponents {
SelectScene = "SelectScene",
SelectDataset = "SelectDataset",
}
export interface IFormBuilderComponentsProps<T> {
dependency: T;
@ -14,7 +16,10 @@ export const getFormBuilderComponents = (
onChange: (text: string) => void
): Result<string, React.ReactNode> => {
if (name.isEqual(FormBuilderComponents.SelectScene)) {
return Result.ok(<SelectScene dependency={dependency} onChange={onChange}/>);
return Result.ok(<SelectDetail dependency={dependency} onChange={onChange} />);
}
if (name.isEqual(FormBuilderComponents.SelectDataset)) {
return Result.ok(<SelectDatasetScreen dependency={dependency} onChange={onChange} />);
}
return Result.error(name);
};

View file

@ -0,0 +1,6 @@
import { observer } from "mobx-react-lite";
import { IFormBuilderComponentsProps } from "../../form_builder_components";
export const SelectDatasetScreen = observer((props:IFormBuilderComponentsProps<any>) => {
return <>SELECT DATASET</>;
});

View file

@ -0,0 +1,38 @@
import { makeAutoObservable } from "mobx";
import { Parts } from "../../../../../../features/details/details_http_repository";
export class SelectDetailViewModel {
details: Parts[];
constructor(parts: Parts[]) {
this.details = parts;
makeAutoObservable(this);
}
static empty = () => new SelectDetailViewModel([]);
isSelected = (name: string) => {
for (const el of this.details) {
if (el.name.isEqual(name)) {
return el.isSelect as boolean;
}
}
return false;
};
toDependency = () => {
this.details = this.details.filter((el) => el.isSelect === true);
return this;
};
select = (part: Parts) =>
this.details.indexOfR(part).fold(
() =>
this.details.forEach((el) =>
el.name.isEqualR(part.name).map(() => {
el.isSelect = !el.isSelect;
})
),
() => {
part.isSelect = true;
this.details.push(part);
}
);
}

View file

@ -0,0 +1,30 @@
import React from "react";
import { IFormBuilderComponentsProps } from "../../form_builder_components";
import { observer } from "mobx-react-lite";
import { ListItem } from "./ui/list_item";
import { SelectDetailStore } from "./select_detail_store";
import { SelectDetailViewModel } from "../model/select_details_model";
export const SelectDetail = observer((props: IFormBuilderComponentsProps<SelectDetailViewModel>) => {
const [store] = React.useState(() => new SelectDetailStore());
React.useEffect(() => {
store.loadClassInstance(SelectDetailViewModel, props.dependency);
store.init();
}, []);
return (
<div>
{store.parts?.map((el) => {
return (
<ListItem
status={store.viewModel.isSelected(el.name)}
name={el.name}
imgURL={el.image}
onChange={() => (store.viewModel.select(el), props.onChange(store.viewModel.toDependency()))}
/>
);
})}
</div>
);
});

View file

@ -0,0 +1,21 @@
import makeAutoObservable from "mobx-store-inheritance";
import { DataSetHttpRepository } from "../../../../../../features/dataset/dataset_http_repository";
import { Parts } from "../../../../../../features/details/details_http_repository";
import { FormState } from "../../../../../store/base_store";
import { SelectDetailViewModel } from "../model/select_details_model";
export class SelectDetailStore extends FormState<SelectDetailViewModel, any> {
viewModel = SelectDetailViewModel.empty();
parts?: Parts[];
dataSetRepository: DataSetHttpRepository = new DataSetHttpRepository();
constructor() {
super();
makeAutoObservable(this);
}
init = async () => {
await this.mapOk("parts", this.dataSetRepository.getAssetsActiveProject());
};
updateCheckbox(el: Parts): void {
el.isSelect = true;
}
}

View file

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

View file

@ -1,22 +0,0 @@
import { CoreButton } from "../../../button/button";
import { IFormBuilderComponentsProps } from "../form_builder_components";
export class SceneSelectModel {
name: string;
}
export const SelectScene = (props: IFormBuilderComponentsProps<SceneSelectModel>) => {
return (
<div>
SELECT SCENE
<div>
{JSON.stringify(props.dependency)}
</div>
<CoreButton
text="CHANGE"
onClick={() => {
props.dependency.name = '15555'
props.onChange(JSON.stringify(props.dependency, () => {}, ""));
}}
/>
</div>
);
};

View file

@ -2,12 +2,8 @@
```
{
"scene":{
"objects": \${OBJECTS_SCENE:Array<OBJECTS_SCENE>:[]},
},
"camera_position":{
"center_shell": [\${CENTER_SHELL_1:string:0}, \${COLISION_SHAPE:Enum<L>:"BOX"}]
}
"name": \${NAME:string:""},
"scene":{<SelectScene/>:OBJECT:{"bricks":{"base_feature":{"path":"bricks/base_feature"},"form":{"path":"bricks/form"}}}}
}
```
@ -20,14 +16,12 @@ ENUM T = "ObjectDetection","PoseEstimation";
ENUM L = "POINT","SUN";
type MODELS = {
"id": \${IMAGE_FORMAT:Enum<L>:"jpg"},,
"name": \${NAME:string:""},
"model": \${MODEL:string:"models/1.fbx"}
};
type OBJECTS_SCENE = {
"name": \${NAME:string:""},
"collision_shape": \${COLISION_SHAPE:Enum<L>:"BOX"},
"loc_xyz": [\${TEST123:string:"test123"}, \${LOC_XYZ_2:number:0}, \${LOC_XYZ_3:number:0}],
};
```

View file

@ -54,6 +54,75 @@ const getIconSvg = (
switch (type) {
case "":
return Result.ok();
case "Error":
return Result.ok(
<svg
xmlns="http://www.w3.org/2000/svg"
width={width ? width : "20"}
height={height ? height : "20"}
viewBox="0 0 16 16"
fill="none"
>
<path
d="M7.493 0.015 C 7.442 0.021,7.268 0.039,7.107 0.055 C 5.234 0.242,3.347 1.208,2.071 2.634 C 0.660 4.211,-0.057 6.168,0.009 8.253 C 0.124 11.854,2.599 14.903,6.110 15.771 C 8.169 16.280,10.433 15.917,12.227 14.791 C 14.017 13.666,15.270 11.933,15.771 9.887 C 15.943 9.186,15.983 8.829,15.983 8.000 C 15.983 7.171,15.943 6.814,15.771 6.113 C 14.979 2.878,12.315 0.498,9.000 0.064 C 8.716 0.027,7.683 -0.006,7.493 0.015 M8.853 1.563 C 9.967 1.707,11.010 2.136,11.944 2.834 C 12.273 3.080,12.920 3.727,13.166 4.056 C 13.727 4.807,14.142 5.690,14.330 6.535 C 14.544 7.500,14.544 8.500,14.330 9.465 C 13.916 11.326,12.605 12.978,10.867 13.828 C 10.239 14.135,9.591 14.336,8.880 14.444 C 8.456 14.509,7.544 14.509,7.120 14.444 C 5.172 14.148,3.528 13.085,2.493 11.451 C 2.279 11.114,1.999 10.526,1.859 10.119 C 1.618 9.422,1.514 8.781,1.514 8.000 C 1.514 6.961,1.715 6.075,2.160 5.160 C 2.500 4.462,2.846 3.980,3.413 3.413 C 3.980 2.846,4.462 2.500,5.160 2.160 C 6.313 1.599,7.567 1.397,8.853 1.563 M7.706 4.290 C 7.482 4.363,7.355 4.491,7.293 4.705 C 7.257 4.827,7.253 5.106,7.259 6.816 C 7.267 8.786,7.267 8.787,7.325 8.896 C 7.398 9.033,7.538 9.157,7.671 9.204 C 7.803 9.250,8.197 9.250,8.329 9.204 C 8.462 9.157,8.602 9.033,8.675 8.896 C 8.733 8.787,8.733 8.786,8.741 6.816 C 8.749 4.664,8.749 4.662,8.596 4.481 C 8.472 4.333,8.339 4.284,8.040 4.276 C 7.893 4.272,7.743 4.278,7.706 4.290 M7.786 10.530 C 7.597 10.592,7.410 10.753,7.319 10.932 C 7.249 11.072,7.237 11.325,7.294 11.495 C 7.388 11.780,7.697 12.000,8.000 12.000 C 8.303 12.000,8.612 11.780,8.706 11.495 C 8.763 11.325,8.751 11.072,8.681 10.932 C 8.616 10.804,8.460 10.646,8.333 10.580 C 8.217 10.520,7.904 10.491,7.786 10.530 "
stroke="none"
fillRule="evenodd"
fill="#000000"
/>
</svg>
);
case "Log":
return Result.ok(
<svg
xmlns="http://www.w3.org/2000/svg"
xmlnsXlink="http://www.w3.org/1999/xlink"
width={width ? width : "20"}
height={height ? height : "20"}
viewBox="0 0 512 512"
version="1.1"
>
<title>log</title>
<g id="Page-1" stroke="none" strokeWidth="1" fill="none" fillRule="evenodd">
<g id="log-white" fill="#000000" transform="translate(85.572501, 42.666667)">
<path
d="M236.349632,7.10542736e-15 L1.68296533,7.10542736e-15 L1.68296533,234.666667 L44.349632,234.666667 L44.349632,192 L44.349632,169.6 L44.349632,42.6666667 L218.642965,42.6666667 L300.349632,124.373333 L300.349632,169.6 L300.349632,192 L300.349632,234.666667 L343.016299,234.666667 L343.016299,106.666667 L236.349632,7.10542736e-15 L236.349632,7.10542736e-15 Z M4.26325641e-14,405.333333 L4.26325641e-14,277.360521 L28.8096875,277.360521 L28.8096875,382.755208 L83.81,382.755208 L83.81,405.333333 L4.26325641e-14,405.333333 Z M153.17,275.102708 C173.279583,275.102708 188.692917,281.484792 199.41,294.248958 C209.705625,306.47125 214.853437,322.185625 214.853437,341.392083 C214.853437,362.404792 208.772396,379.112604 196.610312,391.515521 C186.134062,402.232604 171.653958,407.591146 153.17,407.591146 C133.060417,407.591146 117.647083,401.209062 106.93,388.444896 C96.634375,376.222604 91.4865625,360.267396 91.4865625,340.579271 C91.4865625,319.988021 97.5676042,303.490937 109.729687,291.088021 C120.266146,280.431146 134.74625,275.102708 153.17,275.102708 Z M153.079687,297.680833 C142.663646,297.680833 134.625833,302.015833 128.96625,310.685833 C123.848542,318.512917 121.289687,328.567708 121.289687,340.850208 C121.289687,355.059375 124.330208,366.0775 130.41125,373.904583 C136.131042,381.310208 143.717292,385.013021 153.17,385.013021 C163.525833,385.013021 171.59375,380.647917 177.37375,371.917708 C182.491458,364.211042 185.050312,354.035833 185.050312,341.392083 C185.050312,327.483958 182.009792,316.616354 175.92875,308.789271 C170.208958,301.383646 162.592604,297.680833 153.079687,297.680833 Z M343.91,333.715521 L343.91,399.011458 C336.564583,401.48 331.386667,403.105625 328.37625,403.888333 C319.043958,406.356875 309.019271,407.591146 298.302187,407.591146 C277.229271,407.591146 261.18375,402.292812 250.165625,391.696146 C237.943333,380.015729 231.832187,363.729375 231.832187,342.837083 C231.832187,318.813958 239.418437,300.69125 254.590937,288.468958 C265.609062,279.558125 280.480521,275.102708 299.205312,275.102708 C315.220729,275.102708 330.122292,278.022812 343.91,283.863021 L334.065937,306.350833 C327.563437,303.099583 321.87375,300.826719 316.996875,299.53224 C312.12,298.23776 306.761458,297.590521 300.92125,297.590521 C286.952917,297.590521 276.657292,302.13625 270.034375,311.227708 C264.435,318.934375 261.635312,329.079479 261.635312,341.663021 C261.635312,356.775312 265.849896,368.154687 274.279062,375.801146 C281.022396,381.942396 289.391354,385.013021 299.385937,385.013021 C305.226146,385.013021 310.765312,384.019583 316.003437,382.032708 L316.003437,356.293646 L293.967187,356.293646 L293.967187,333.715521 L343.91,333.715521 Z"
id="XLS"
></path>
</g>
</g>
</svg>
);
case "Command":
return Result.ok(
<svg
xmlns="http://www.w3.org/2000/svg"
width={width ? width : "20"}
height={height ? height : "20"}
viewBox="0 0 16 16"
fill="none"
>
<g fill="#000000">
<path d="M5.314 1.256a.75.75 0 01-.07 1.058L3.889 3.5l1.355 1.186a.75.75 0 11-.988 1.128l-2-1.75a.75.75 0 010-1.128l2-1.75a.75.75 0 011.058.07zM7.186 1.256a.75.75 0 00.07 1.058L8.611 3.5 7.256 4.686a.75.75 0 10.988 1.128l2-1.75a.75.75 0 000-1.128l-2-1.75a.75.75 0 00-1.058.07zM2.75 7.5a.75.75 0 000 1.5h10.5a.75.75 0 000-1.5H2.75zM2 11.25a.75.75 0 01.75-.75h10.5a.75.75 0 010 1.5H2.75a.75.75 0 01-.75-.75zM2.75 13.5a.75.75 0 000 1.5h6.5a.75.75 0 000-1.5h-6.5z" />
</g>
</svg>
);
case "Play":
return Result.ok(
<svg
xmlns="http://www.w3.org/2000/svg"
width={width ? width : "20"}
height={height ? height : "20"}
viewBox="0 0 24 24"
fill="none"
>
<path
d="M16.6582 9.28638C18.098 10.1862 18.8178 10.6361 19.0647 11.2122C19.2803 11.7152 19.2803 12.2847 19.0647 12.7878C18.8178 13.3638 18.098 13.8137 16.6582 14.7136L9.896 18.94C8.29805 19.9387 7.49907 20.4381 6.83973 20.385C6.26501 20.3388 5.73818 20.0469 5.3944 19.584C5 19.053 5 18.1108 5 16.2264V7.77357C5 5.88919 5 4.94701 5.3944 4.41598C5.73818 3.9531 6.26501 3.66111 6.83973 3.6149C7.49907 3.5619 8.29805 4.06126 9.896 5.05998L16.6582 9.28638Z"
stroke="#000000"
strokeWidth="2"
strokeLinejoin="round"
/>
</svg>
);
case "ArrowRightMD":
return Result.ok(
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">

View file

@ -4,7 +4,7 @@ import { IStyle } from "../../model/style";
export enum CoreInputType {
small = "small",
default = "default",
big = 'big'
big = "big",
}
interface IInputProps extends IStyle {
label: string;
@ -32,20 +32,22 @@ export const CoreInput = (props: IInputProps) => {
style={Object.assign(
{
backgroundColor: "rgba(230, 224, 233, 1)",
height: isSmall ? 40 : 58,
borderRadius: "4px 4px 0px 0px",
borderBottom: "solid 1px black",
padding: "10px 10px 10px 10px",
},
props.style
)}
>
<CoreText type={CoreTextType.small} style={isSmall ? { fontSize: 8, position:'relative',top:-8 } : {}} text={props.label} />
<CoreText
type={CoreTextType.small}
style={isSmall ? { fontSize: 8, position: "relative", top: -8 } : {}}
text={props.label}
/>
<input
size={100}
<div
contentEditable={true}
defaultValue={props.value}
style={{
backgroundColor: "#00008000",
@ -60,8 +62,8 @@ export const CoreInput = (props: IInputProps) => {
position: isSmall ? "relative" : undefined,
top: isSmall ? -8 : undefined,
}}
onChange={(e) => {
const val = e.target.value;
onInput={(e) => {
const val = e.currentTarget.innerText;
setValue(val);
if (val) {

View file

@ -9,7 +9,7 @@ import { AssemblesScreenPath } from "../../../features/assembles/assembles_scree
import { SimulationScreenPath } from "../../../features/simulations/simulations_screen";
import { EstimateScreenPath } from "../../../features/estimate/estimate_screen";
import { BehaviorTreeBuilderPath } from "../../../features/behavior_tree_builder/presentation/behavior_tree_builder_screen";
import { MachineLearningPath as SkillScreenPath } from "../../../features/machine_learning/presentation/machine_learning_screen";
import { CalculationScreenPath as SkillScreenPath } from "../../../features/calculation/presentation/calculation_screen";
import { UiBaseError } from "../../model/ui_base_error";
import { DetailsScreenPath } from "../../../features/details/details_screen";
export interface IBlockProps {
@ -64,7 +64,7 @@ export const MainPage = (props: IMainPageProps) => {
{ name: "Сборки", path: AssemblesScreenPath, icon: "Assembly" },
{ name: "Датасеты", path: DatasetsScreenPath, icon: "Datasets" },
{ name: "Сцена", path: SceneManagerPath, icon: "Scene" },
{ name: "модели", path: SkillScreenPath, icon: "Layers" },
{ name: "Вычисления", path: SkillScreenPath, icon: "Layers" },
{ name: "Поведение", path: BehaviorTreeBuilderPath, icon: "Rocket" },
{ name: "Симуляция", path: SimulationScreenPath, icon: "Simulation" },
{ name: "Оценка", path: EstimateScreenPath, icon: "Grade" },

View file

@ -19,8 +19,7 @@ export const CoreSlider = ({
React.useEffect(() => {
if (refSlider.current && refWheel.current) {
console.log((max - min) / step);
console.log(refSlider.current.clientWidth / ((max - min) / step));
const oneStep = refSlider.current.clientWidth / ((max - min) / step);
refWheel.current.style.left = ((value - min) / step) * oneStep + "px";

View file

@ -1,5 +1,5 @@
import { Result } from "../../../core/helper/result";
import { HttpMethod, CoreHttpRepository } from "../../../core/repository/http_repository";
import { HttpMethod, CoreHttpRepository } from "../../../core/repository/core_http_repository";
import { IProjectModel } from "../model/project_model";
export interface ICreateProjectViewModel {
description: string;
@ -8,19 +8,16 @@ export interface UUID {
id: string;
}
export class ProjectHttpRepository extends CoreHttpRepository {
async getAllProject() {
return this._jsonRequest<IProjectModel[]>(HttpMethod.GET, "/projects");
}
async saveProject(model: ICreateProjectViewModel): Promise<Result<Error, UUID>> {
return await this._jsonRequest<UUID>(HttpMethod.POST, "/projects", model);
}
async setProjectRootFile(file: File, projectId: string) {
featureApi = `/projects`;
getAllProject = async () => this._jsonRequest<IProjectModel[]>(HttpMethod.GET, this.featureApi);
saveProject = async (model: ICreateProjectViewModel): Promise<Result<Error, UUID>> =>
await this._jsonRequest<UUID>(HttpMethod.POST, this.featureApi, model);
setActivePipeline = async (id: string) =>
this._jsonRequest(HttpMethod.POST, `${this.featureApi}/set/active/project?id=${id}`);
setProjectRootFile = async (file: File, projectId: string) => {
const formData = new FormData();
formData.append("file", file);
return await this._formDataRequest(HttpMethod.POST, `/projects/upload?id=${projectId}`, formData);
}
async setActivePipeline(id: string) {
return this._jsonRequest(HttpMethod.POST, `/projects/set/active/project?id=${id}`);
}
return await this._formDataRequest(HttpMethod.POST, `${this.featureApi}/upload?id=${projectId}`, formData);
};
}

View file

@ -18,6 +18,7 @@ export const AllProjectScreen: React.FunctionComponent = observer(() => {
store.init();
}, []);
return (
<PreviewPage
largeText={"Проекты"}
@ -53,7 +54,7 @@ export const AllProjectScreen: React.FunctionComponent = observer(() => {
onClick={() => {
navigate(`${DetailsScreenPath}`);
}}
textStyle={{ color: "black",textAlign:'center' }}
textStyle={{ color: "black", textAlign: "center" }}
style={{ marginRight: 10, backgroundColor: "white", width: 126 }}
/>
) : (

View file

@ -1,29 +1,30 @@
import { Result } from "../../../core/helper/result";
import { Skills } from "../../../core/model/skill_model";
import { HttpError, HttpMethod, CoreHttpRepository } from "../../../core/repository/http_repository";
import { HttpError, HttpMethod, CoreHttpRepository } from "../../../core/repository/core_http_repository";
import { BehaviorTreeModel } from "../model/behavior_tree_model";
import { BehaviorTreeViewModel } from "../model/behavior_tree_view_model";
export class BehaviorTreeBuilderHttpRepository extends CoreHttpRepository {
featureApi = `/behavior/trees`;
getAllBtInstances = async () => this._jsonRequest<BehaviorTreeModel[]>(HttpMethod.GET, "/behavior/trees");
getAllBtInstances = async () => this._jsonRequest<BehaviorTreeModel[]>(HttpMethod.GET, this.featureApi);
getBtSkills = async (): Promise<Result<HttpError, Skills>> => {
return (await this._jsonToClassInstanceRequest<Skills>(
HttpMethod.GET,
"/behavior/trees/templates",
`${this.featureApi}/templates`,
Skills
)) as unknown as Promise<Result<HttpError, Skills>>;
};
saveNewBt = async (model: BehaviorTreeViewModel) => this._jsonRequest(HttpMethod.POST, "/behavior/trees", model);
saveNewBt = async (model: BehaviorTreeViewModel) => this._jsonRequest(HttpMethod.POST, this.featureApi, model);
getBtById = async (id: string): Promise<Result<HttpError, BehaviorTreeModel>> =>
this._jsonToClassInstanceRequest<BehaviorTreeModel>(
HttpMethod.GET,
`/behavior/trees/by_id?id=${id}`,
`${this.featureApi}/by_id?id=${id}`,
BehaviorTreeModel
) as unknown as Promise<Result<HttpError, BehaviorTreeModel>>;
editBt = async (model: BehaviorTreeModel) => {
await this._jsonRequest(HttpMethod.POST, "/behavior/trees/fill/tree", model);
return await this._jsonRequest(HttpMethod.PUT, "/behavior/trees", model);
await this._jsonRequest(HttpMethod.POST, `${this.featureApi}/fill/tree`, model);
return await this._jsonRequest(HttpMethod.PUT, this.featureApi, model);
};
}

View file

@ -3,7 +3,7 @@ import { Result } from "../../../core/helper/result";
import { Skills } from "../../../core/model/skill_model";
import { NodeBehaviorTree } from "./node_behavior_tree";
import { IsOptional, IsString } from "class-validator";
import { BehaviorTreeBuilderHttpRepository } from "../data/behavior_tree_builder_repository";
import { BehaviorTreeBuilderHttpRepository } from "../data/behavior_tree_builder_http_repository";
import { message } from "antd";
export class BehaviorTreeModel {

View file

@ -11,7 +11,7 @@ import { NodeEditor } from "rete";
import { AreaExtra, Schemes } from "./ui/editor/editor";
import { AreaPlugin } from "rete-area-plugin";
import { NodeBehaviorTree } from "../model/node_behavior_tree";
import { BehaviorTreeBuilderHttpRepository } from "../data/behavior_tree_builder_repository";
import { BehaviorTreeBuilderHttpRepository } from "../data/behavior_tree_builder_http_repository";
import { IParam, Skills } from "../../../core/model/skill_model";
import { ISkillView } from "./ui/skill_tree/skill_tree";
import { message } from "antd";

View file

@ -1,5 +1,5 @@
import { Cameras } from "../../../../../../core/model/cameras";
import { HttpMethod, CoreHttpRepository } from "../../../../../../core/repository/http_repository";
import { HttpMethod, CoreHttpRepository } from "../../../../../../core/repository/core_http_repository";
export class CameraDeviceHttpRepository extends CoreHttpRepository {
getAllCameras = () => this._jsonRequest<Cameras>(HttpMethod.GET, '/behavior/trees/cameras');

View file

@ -1,4 +1,4 @@
import { CoreHttpRepository } from "../../../../../../core/repository/http_repository";
import { CoreHttpRepository } from "../../../../../../core/repository/core_http_repository";
export class RobotDeviceFormHttpRepository extends CoreHttpRepository {

View file

@ -1,5 +1,5 @@
import { Topics } from "../../../../../../core/model/topics";
import { HttpMethod, CoreHttpRepository } from "../../../../../../core/repository/http_repository";
import { HttpMethod, CoreHttpRepository } from "../../../../../../core/repository/core_http_repository";
export class TopicsFormHttpRepository extends CoreHttpRepository {
getAllTopics = () => this._jsonRequest<Topics>(HttpMethod.GET, '/behavior/trees/topics');

View file

@ -1,7 +1,7 @@
import makeAutoObservable from "mobx-store-inheritance";
import { FormState, CoreError } from "../../../../../../core/store/base_store";
import { DataSetHttpRepository } from "../../../../../dataset/dataset_http_repository";
import { ISkils, SkillsHttpRepository } from "../../../../../machine_learning/data/machine_learning_http_repository";
import { ISkils, CalculationHttpRepository } from "../../../../../calculation/data/calculation_http_repository";
import { WeightsViewModel } from "./weights_view_model";
import { Parts } from "../../../../../details/details_http_repository";
@ -10,14 +10,14 @@ export class WeightsFormStore extends FormState<WeightsViewModel, CoreError> {
parts?: Parts[];
suitableWeights: string[] = [];
viewModel: WeightsViewModel = WeightsViewModel.empty();
skillsHttpRepository: SkillsHttpRepository = new SkillsHttpRepository();
skillsHttpRepository: CalculationHttpRepository = new CalculationHttpRepository();
datasetHttpRepository: DataSetHttpRepository = new DataSetHttpRepository();
constructor() {
super();
makeAutoObservable(this);
}
init = async () => {
await this.mapOk("weights", this.skillsHttpRepository.getAllSkills());
await this.mapOk("weights", this.skillsHttpRepository.getAllTemplates());
await this.mapOk("parts", this.datasetHttpRepository.getAssetsActiveProject());
};
changeDimensions = (index: number, value: number) => {

View file

@ -0,0 +1,32 @@
import { Result } from "../../../core/helper/result";
import { ValidationModel } from "../../../core/model/validation_model";
import { HttpError, HttpMethod, CoreHttpRepository } from "../../../core/repository/core_http_repository";
import { IDatasetModel } from "../../dataset/dataset_model";
import { CalculationModel } from "../model/calculation_model";
export interface ISkils {
_id: string;
name: string;
processStatus: string;
epoch: number;
isFinished: boolean;
datasetId: any;
project: any;
numberOfTrainedEpochs: number;
__v: number;
}
export class CalculationHttpRepository extends CoreHttpRepository {
featureApi = `/calculations/instances`;
subFeatureApi = `/calculations/template`;
editCalculation = (model: CalculationModel) => this._jsonRequest(HttpMethod.PUT, this.featureApi, model);
createNewInstance = (model: CalculationModel) => this._jsonRequest(HttpMethod.POST, this.featureApi, model);
createNewTemplate = (model: CalculationModel) => this._jsonRequest(HttpMethod.POST, this.subFeatureApi, model);
getAllInstances = () => this._jsonRequest(HttpMethod.GET, this.featureApi);
execInstance = (id: string) => this._jsonRequest(HttpMethod.GET, `${this.featureApi}/exec?id=${id}`);
getAllTemplates = async () => this._jsonRequest(HttpMethod.GET, this.subFeatureApi);
deleteTemplate = (id: string) => this._jsonRequest(HttpMethod.DELETE, `${this.subFeatureApi}?id=${id}`);
deleteInstance = (id: string) => this._jsonRequest(HttpMethod.DELETE, `${this.featureApi}?id=${id}`);
}

View file

@ -1,5 +1,5 @@
import { TypedEvent } from "../../../core/helper/typed_event";
import { SocketRepository, socketRepository } from "../../../core/repository/socket_repository";
import { SocketRepository, socketRepository } from "../../../core/repository/core_socket_repository";
import { ProcessStatus } from "../../dataset/dataset_model";
export interface ProcessUpdate {
@ -7,7 +7,7 @@ export interface ProcessUpdate {
status: ProcessStatus;
}
export class SkillSocketRepository extends TypedEvent<ProcessUpdate> {
export class CalculationSocketRepository extends TypedEvent<ProcessUpdate> {
socketRepository: SocketRepository = socketRepository;
constructor() {
super();

View file

@ -0,0 +1,39 @@
import { FormBuilderValidationModel } from "../../dataset/dataset_model";
import { IsNotEmpty, IsString } from "class-validator";
import { ValidationModel } from "../../../core/model/validation_model";
export enum ModelMachineLearningTypes {
OBJECT_DETECTION = "OBJECT_DETECTION",
POSE_ESTIMATE = "POSE_ESTIMATE",
}
export class CalculationModel extends ValidationModel {
_id?: string;
processStatus?:string;
instanceName: string;
@IsString()
@IsNotEmpty()
script: string;
formBuilder: FormBuilderValidationModel;
@IsString()
@IsNotEmpty()
type: string;
@IsString()
@IsNotEmpty()
name: string;
isEnd: boolean = false;
createDate: number = Date.now();
card?: string;
lastProcessLogs?: string;
lastProcessExecCommand?: string;
lastExecDate?: Date;
project?: string;
constructor(script: string, formBuilderValidationModel: FormBuilderValidationModel, type: string, card: string) {
super();
this.script = script;
this.formBuilder = formBuilderValidationModel;
this.type = type;
this.card = card;
}
static empty = () => new CalculationModel("", FormBuilderValidationModel.datasetEmpty(), "", "");
}

View file

@ -0,0 +1,214 @@
import React from "react";
import { Drawer, Modal } from "antd";
import { observer } from "mobx-react-lite";
import { MainPage } from "../../../core/ui/pages/main_page";
import { CoreText, CoreTextType } from "../../../core/ui/text/text";
import { DrawersSkill, CalculationStore, StoreTypes } from "./calculation_store";
import { CoreInput } from "../../../core/ui/input/input";
import { CoreButton } from "../../../core/ui/button/button";
import { CoreSelect } from "../../../core/ui/select/select";
import { ModelMachineLearningTypes } from "../model/calculation_model";
import { CardModel, getModelCard } from "./ui/cards/get_model_card";
import { FormBuilder } from "../../../core/ui/form_builder/form_builder";
import { match } from "ts-pattern";
import { TemplateModelCard } from "./ui/template_model_card";
import { Icon } from "../../../core/ui/icons/icons";
import { FormBuilderValidationModel, scene } from "../../dataset/dataset_model";
interface IItem {
name: string;
isActive: boolean;
}
const skills: IItem[] = [{ name: "ML", isActive: true }];
export const CalculationScreenPath = "/calculation";
export const CalculationScreen = observer(() => {
const [store] = React.useState(() => new CalculationStore());
React.useEffect(() => {
store.init();
}, []);
return (
<>
<MainPage
page={"модели"}
panelChildren={
<div style={{ justifyContent: "center", display: "flex", padding: 10 }}>
{skills.map((el, i) => (
<CoreText key={i} text={el.name} type={CoreTextType.header} />
))}
</div>
}
bodyChildren={
<div
style={{
display: "grid",
gridTemplateColumns: "repeat(auto-fill, minmax(220px,1px))",
width: "100%",
gap: 20,
margin: 12,
overflow: "auto",
height: window.innerHeight,
}}
>
{store.calculationInstances?.map((el, i) => {
return (
<span key={i}>
{getModelCard(
el,
() => store.makeEditProcess(el),
() => store.deleteInstance(el._id ?? ""),
() => store.execSkill(el._id ?? ""),
() => store.execSkill(el._id ?? "")
)}
</span>
);
})}
<div
onClick={() => {
store.editDrawer(DrawersSkill.NEW_SKILL, true);
}}
style={{
background: "rgb(247, 242, 250)",
width: 150,
height: 80,
alignContent: "center",
textAlignLast: "center",
margin: 10,
}}
>
<Icon type="PlusCircle" />
</div>
</div>
}
/>
<Drawer
width={(window.innerWidth / 100) * 50}
title={store.titleDrawer}
destroyOnClose={true}
onClose={() => store.editDrawer(DrawersSkill.EDIT_SKILL, false)}
open={store.drawers.find((el) => el.name === DrawersSkill.EDIT_SKILL)?.status}
>
<div style={{ display: "flex", flexDirection: "column", justifyContent: "space-between", height: "100%" }}>
<FormBuilder
formBuilder={store.editProcess?.formBuilder ?? FormBuilderValidationModel.empty()}
onChange={(formBuilder) => store.updateForm({ formBuilder: formBuilder })}
/>
<div style={{ display: "flex" }}>
<CoreButton text="Сохранить" filled={true} onClick={() => store.saveEdiSkill()} />
<div style={{ width: 10 }} />
<CoreButton text="Отмена" onClick={() => store.editDrawer(DrawersSkill.EDIT_SKILL, false)} />
</div>
</div>
</Drawer>
<Drawer
width={(window.innerWidth / 100) * 50}
title={store.titleDrawer}
destroyOnClose={true}
afterOpenChange={() => store.selectType(StoreTypes.empty)}
onClose={() => store.editDrawer(DrawersSkill.NEW_SKILL, false)}
open={store.drawers.find((el) => el.name === DrawersSkill.NEW_SKILL)?.status}
>
<div style={{ display: "flex", flexDirection: "column", justifyContent: "space-between", height: "100%" }}>
<div>
{match(store.storeType)
.with(StoreTypes.empty, () => (
<>
<CoreText
text={"Создать новый тип процесса"}
type={CoreTextType.header}
onClick={() => store.selectType(StoreTypes.newType)}
/>
<CoreText
text={"Создать новый инстанц процесса"}
type={CoreTextType.header}
onClick={() => store.selectType(StoreTypes.newModel)}
/>
</>
))
.with(StoreTypes.newType, () => (
<>
<CoreSelect
items={Object.keys(ModelMachineLearningTypes)}
value={store.viewModel.type}
label={"Тип навыка"}
onChange={(text: string) => store.updateForm({ type: text })}
/>
<CoreSelect
items={Object.keys(CardModel)}
value={""}
label={"Тип карточки"}
onChange={(text: string) => store.updateForm({ card: text })}
/>
<CoreInput label="Имя" onChange={(text) => store.updateForm({ name: text })} />
<CoreInput label="Команда для запуска" onChange={(text) => store.updateForm({ script: text })} />
<CoreInput
label="FormBuilder Result"
onChange={(text) => (store.viewModel.formBuilder.result = text)}
style={{ height: 200, overflow: "overlay" }}
/>
<CoreInput
label="FormBuilder Context"
onChange={(text) => (store.viewModel.formBuilder.context = text)}
style={{ height: 200, overflow: "overlay" }}
/>
<div style={{ height: 10 }} />
<CoreButton
style={{ width: 206 }}
text={"Посмотреть FormBuilder "}
onClick={() => (store.isModalOpen = true)}
/>
<div style={{ height: 10 }} />
</>
))
.with(StoreTypes.newModel, () => (
<div>
<CoreInput
label={"Имя инстанца навыка"}
onChange={(text) => store.updateForm({ instanceName: text })}
/>
<div style={{ width: "100%", display: "grid", gridTemplateColumns: "repeat(3, 240px)" }}>
{store.modelTemplate?.map((el, i) => (
<>
<TemplateModelCard
key={i}
model={el}
isSelect={store.selectTemplate?.name.isEqual(el.name) ?? false}
onDelete={() => store.deleteTemplate(el)}
onClick={() => store.setSelectTemplate(el)}
/>
</>
))}
</div>
</div>
))
.otherwise(() => (
<></>
))}
</div>
<div style={{ display: "flex" }}>
<CoreButton text="Сохранить" filled={true} onClick={() => store.clickSave()} />
<div style={{ width: 10 }} />
<CoreButton text="Отмена" onClick={() => store.editDrawer(DrawersSkill.NEW_SKILL, false)} />
</div>
</div>
</Drawer>
<Modal
destroyOnClose={true}
open={store.isModalOpen}
footer={null}
closable={false}
closeIcon={null}
onCancel={() => {
store.isModalOpen = false;
}}
>
<FormBuilder formBuilder={store.viewModel.formBuilder} onChange={() => {}} />
</Modal>
</>
);
});

View file

@ -0,0 +1,147 @@
import makeAutoObservable from "mobx-store-inheritance";
import { NavigateFunction } from "react-router-dom";
import { HttpError } from "../../../core/repository/core_http_repository";
import { Drawer, UiDrawerFormState } from "../../../core/store/base_store";
import { CalculationHttpRepository } from "../data/calculation_http_repository";
import { IDatasetModel } from "../../dataset/dataset_model";
import { message } from "antd";
import { UUID } from "../../all_projects/data/project_http_repository";
import { CalculationModel } from "../model/calculation_model";
import { ProcessUpdate, CalculationSocketRepository } from "../data/calculation_socket_repository";
import { match } from "ts-pattern";
import { plainToInstance } from "class-transformer";
export enum DrawersSkill {
NEW_SKILL = "Новое вычисление",
EDIT_SKILL = "Редактировать вычисление",
}
export enum StoreTypes {
newType = "newType",
newModel = "newModel",
empty = "empty",
}
export class CalculationStore extends UiDrawerFormState<CalculationModel, HttpError> {
deleteInstance = async (id: string) => {
await this.calculationHttpRepository.deleteInstance(id);
await this.init();
};
calculationHttpRepository: CalculationHttpRepository = new CalculationHttpRepository();
calculationSocketRepository: CalculationSocketRepository = new CalculationSocketRepository();
activeProjectId?: UUID;
storeType: StoreTypes = StoreTypes.empty;
viewModel: CalculationModel = CalculationModel.empty();
modelTemplate?: CalculationModel[];
editProcess?: CalculationModel;
calculationInstances?: CalculationModel[];
selectTemplate?: CalculationModel;
titleDrawer: string = DrawersSkill.NEW_SKILL;
drawers: Drawer[];
isModalOpen: boolean = false;
constructor() {
super({});
this.drawers = Object.entries(DrawersSkill).map((k, v) => {
return {
name: k.at(1) ?? "",
status: false,
};
});
this.viewModel = CalculationModel.empty();
this.calculationSocketRepository.on(this.socketUpdate);
makeAutoObservable(this);
}
socketUpdate = (data: ProcessUpdate) => {
this.calculationInstances?.map((el) => {
if (el?._id && el._id.isEqual(data.id)) {
el.processStatus = data.status;
}
return el;
});
};
getSkillById = (id: string) => {
// this.machineLearningProcess?.find((el) => el._id === id);
};
execSkill = async (id: string) =>
this.messageHttp(this.calculationHttpRepository.execInstance(id), {
errorMessage: "Ошибка",
successMessage: "Процесс запущен",
});
setSelectTemplate = (el: CalculationModel) => {
this.selectTemplate = el;
const instance = plainToInstance(CalculationModel, el);
instance.instanceName = this?.viewModel.instanceName;
this.viewModel = instance;
};
selectType = (newType: StoreTypes) => (this.storeType = newType);
init = async (navigate?: NavigateFunction | undefined) => {
await this.mapOk("modelTemplate", this.calculationHttpRepository.getAllTemplates());
await this.mapOk("activeProjectId", this.calculationHttpRepository.getActiveProjectId());
await this.mapOk("calculationInstances", this.calculationHttpRepository.getAllInstances());
};
clickSave = async () =>
match(this.storeType)
.with(StoreTypes.empty, () => {})
.with(StoreTypes.newType, async () =>
(await this.viewModel.valid<CalculationModel>()).fold(
async (model) => {
model.project = this.activeProjectId?.id;
await this.messageHttp(this.calculationHttpRepository.createNewTemplate(model), {
successMessage: "Создан новый тип процесса",
});
await this.init();
this.editDrawer(DrawersSkill.NEW_SKILL, false);
},
async (e) => message.error(e)
)
)
.with(StoreTypes.newModel, async () => {
(await this.viewModel.valid<CalculationModel>()).fold(
async (model) => {
delete model._id;
model.project = this.activeProjectId?.id;
await this.messageHttp(this.calculationHttpRepository.createNewInstance(model), {
successMessage: "Создан новый экземпляр процесса",
});
await this.init();
this.editDrawer(DrawersSkill.NEW_SKILL, false);
},
async (e) => {
message.error(e);
}
);
});
editDrawer(drawerName: DrawersSkill, status: boolean): void {
this.titleDrawer = drawerName;
this.drawers = this.drawers.map((el) => {
if (el.name === drawerName) {
el.status = status;
}
return el;
});
}
saveEdiSkill = async () => {
this.editDrawer(DrawersSkill.EDIT_SKILL, false);
(await this.viewModel.valid<CalculationModel>()).fold(
async (model) => await this.calculationHttpRepository.editCalculation(model),
async (err) => message.error(err)
);
};
makeEditProcess = (el: CalculationModel) => {
this.editProcess = el;
this.editDrawer(DrawersSkill.EDIT_SKILL, true);
};
deleteTemplate = async (el: CalculationModel) => {
await this.messageHttp(this.calculationHttpRepository.deleteTemplate(el._id ?? ""), {
successMessage: "Удален",
});
await this.mapOk("modelTemplate", this.calculationHttpRepository.getAllTemplates());
};
}

View file

@ -0,0 +1,102 @@
import { match } from "ts-pattern";
import { PoseEstimateCard } from "./pose_estimate_card/model_card";
import { FormBuilderValidationModel } from "../../../../dataset/dataset_model";
import { Dropdown, MenuProps, message } from "antd";
import { CoreText, CoreTextType } from "../../../../../core/ui/text/text";
import { IMenuItem } from "../../../../dataset/card_dataset";
import { Icon } from "../../../../../core/ui/icons/icons";
import { CalculationModel } from "../../../model/calculation_model";
export enum CardModel {
pose_estimate = "pose_estimate",
}
export const getModelCard = (
calculationModel: CalculationModel,
onEdit: Function,
onDelete: Function,
onPlay: Function,
onPause: Function
) => {
const menu: IMenuItem[] = [
{
onClick: () => onEdit(),
name: "Редактировать",
},
{
onClick: () => onDelete(),
name: "Удалить",
},
];
const items: MenuProps["items"] = menu.map((el, index) => {
return {
key: String(index),
label: <CoreText text={el.name} type={CoreTextType.medium} />,
onClick: () => el.onClick(),
};
});
return (
<div
style={{
display: "flex",
margin: 10,
padding: 10,
background: "#f7f2fa",
justifyContent: "space-between",
alignItems: "flex-start",
height: 150,
}}
>
<div>
<div style={{ display: "flex" }}>
{/* {calculationModel.isEnd ? (
<Icon type="Pause" onClick={() => onPause()} />
) : (
<Icon type="Play" onClick={() => onPlay()} />
)} */}
<div>
<div onClick={() => onPlay()}>EXEC</div>
<div>STATUS:{calculationModel.processStatus}</div>
</div>
<Icon
type="Log"
onClick={async () => {
await navigator.clipboard.writeText(calculationModel.lastProcessLogs ?? "");
message.success("логи последнего запуска добавлены в буфер!");
}}
/>
<Icon
type="Command"
onClick={async () => {
await navigator.clipboard.writeText(calculationModel.lastProcessExecCommand ?? "");
message.success("последняя команда запуска добавлена в буфер!");
}}
/>
</div>
<CoreText text={calculationModel.type} type={CoreTextType.small} />
<CoreText text={calculationModel.name} type={CoreTextType.small} />
<CoreText text={calculationModel.instanceName} type={CoreTextType.small} />
{match(calculationModel.card ?? "")
.with(CardModel.pose_estimate, () => {
return <PoseEstimateCard dependency={calculationModel.formBuilder} empty={false} />;
})
.otherwise(() => {
return <></>;
})}
</div>
<div style={{ height: 10 }}>
<Dropdown overlayStyle={{ backgroundColor: "rgba(243, 237, 247, 1)" }} menu={{ items }}>
<div>
<Icon type="Settings" />
</div>
</Dropdown>
</div>
</div>
);
};

View file

@ -0,0 +1,35 @@
import { CoreButton } from "../../../../../../core/ui/button/button";
import { Icon } from "../../../../../../core/ui/icons/icons";
import { Dropdown } from "antd";
import { CoreText, CoreTextType } from "../../../../../../core/ui/text/text";
import { ProcessStatus } from "../../../../../dataset/dataset_model";
import { IMenuItem } from "../../../../../dataset/card_dataset";
import type { MenuProps } from "antd";
import { match } from "ts-pattern";
export interface IModelCardProps {
dependency?: Object;
processStatus?: string;
name?: string;
isFinished?: boolean;
id?: string;
emptyOnClick?: Function;
startOnClick?: (id: string) => void;
continueOnClick?: (id: string) => void;
empty: boolean;
onEdit?: (id: string) => void;
epoch?: number;
onDelete?: (id: string) => void;
datasetName?: string;
epochNextTraining?: number;
}
export const PoseEstimateCard = (props: IModelCardProps) => {
return (
<div
>
ModelCard
</div>
);
};

View file

@ -0,0 +1,43 @@
import { CoreText, CoreTextType } from "../../../../core/ui/text/text";
import { CalculationModel } from "../../model/calculation_model";
export const TemplateModelCard = ({
model,
isSelect,
onClick,
onDelete,
}: {
model: CalculationModel;
isSelect: boolean;
onClick?: Function;
onDelete?: Function;
}) => {
return (
<div
onClick={() => {
if (onClick) onClick();
}}
style={{
backgroundColor: "rgba(104, 80, 164, 1)",
width: 180,
height: 180,
borderRadius: 10,
padding: 10,
margin: 10,
border: isSelect ? "4px solid red" : undefined,
}}
>
<div
onClick={() => {
if (onDelete) onDelete();
}}
>
DELETE
</div>
<CoreText text={model.type} type={CoreTextType.small} color="white" />
<CoreText text={new Date().fromUnixDate(model.createDate).formatDate()} type={CoreTextType.small} color="white" />
<CoreText text={model.name} type={CoreTextType.small} color="white" />
</div>
);
};

View file

@ -1,28 +1,16 @@
import { Result } from "../../core/helper/result";
import { HttpError, HttpMethod, CoreHttpRepository } from "../../core/repository/http_repository";
import { HttpError, HttpMethod, CoreHttpRepository } from "../../core/repository/core_http_repository";
import { DataSetModel, Dataset, IDatasetModel, ProcessStatus } from "./dataset_model";
export class DataSetHttpRepository extends CoreHttpRepository {
editDataset(dataSetModel: DataSetModel) {
dataSetModel.processStatus = ProcessStatus.NEW;
return this._jsonRequest<void>(HttpMethod.PUT, `/datasets`, dataSetModel);
}
deleteDataset(id: string) {
return this._jsonRequest<void>(HttpMethod.DELETE, `/datasets/dataset?id=${id}`);
}
saveDataSet = async (model: DataSetModel) => {
return this._jsonRequest<Dataset>(HttpMethod.POST, "/datasets", model);
};
getDatasetsActiveProject = async (): Promise<Result<HttpError, IDatasetModel[]>> => {
return this._jsonRequest(HttpMethod.GET, "/datasets");
};
execDatasetProcess = async (id: string) => {
return this._jsonRequest(HttpMethod.POST, `/datasets/exec?id=${id}`);
};
isRunningProcess = async () => {
return this._jsonRequest(HttpMethod.GET, "/datasets/is/running");
};
deleteProcess = async () => {
return this._jsonRequest(HttpMethod.GET, "/datasets/delete/process");
};
featureApi = `/datasets`;
editDataset = (dataSetModel: DataSetModel) => this._jsonRequest<void>(HttpMethod.PUT, this.featureApi, dataSetModel);
deleteDataset = (id: string) => this._jsonRequest<void>(HttpMethod.DELETE, `${this.featureApi}/dataset?id=${id}`);
saveDataSet = async (model: DataSetModel) => this._jsonRequest<Dataset>(HttpMethod.POST, this.featureApi, model);
getDatasetsActiveProject = async (): Promise<Result<HttpError, IDatasetModel[]>> =>
this._jsonRequest(HttpMethod.GET, this.featureApi);
execDatasetProcess = async (id: string) => this._jsonRequest(HttpMethod.POST, `${this.featureApi}/exec?id=${id}`);
isRunningProcess = async () => this._jsonRequest(HttpMethod.GET, `${this.featureApi}/is/running`);
deleteProcess = async () => this._jsonRequest(HttpMethod.GET, `${this.featureApi}/delete/process`);
}

View file

@ -37,6 +37,18 @@ export interface Asset {
image: string;
}
export class FormBuilderValidationModel {
static vision(): FormBuilderValidationModel {
return new FormBuilderValidationModel(
`ENUM PRETRAIN = "true","false";`,
`{
"numberOfEpochs": \${numberOfEpochs:number:10},
"selectDataset": \${<SelectDataset/>:OBJECT:{"dataset": {}},
"pretrain": \${pretrain:Enum<PRETRAIN>:true}
}`,
[],
''
);
}
public result: string;
public context: string;
public form: string[];
@ -54,18 +66,18 @@ export class FormBuilderValidationModel {
return new FormBuilderValidationModel("", "", [], "");
}
static emptyTest() {
return new FormBuilderValidationModel(
`
`,
``,
[],
defaultFormValue
);
return new FormBuilderValidationModel(``, ``, [], defaultFormValue);
}
static creteDataSetTest() {
return new FormBuilderValidationModel(``, scene, [], "");
}
}
export const scene = `{
"center_shell": [\${CENTER_SHELL_1:number:0}, \${CENTER_SHELL_2:number:0}, \${CENTER_SHELL_3:number:0}],
"scene":\${<SelectScene/>:OBJECT:{"details": []}
}`;
// {"name":"body_up","isSelect":true,"part_path":"parts/objects/body_up.stl","material_path":"","inertia":{"ixx":0.1,"ixy":0,"ixz":0,"iyy":0.1,"iyz":0,"izz":0.1},"visual":".dae","collision":".stl","stlUrl":"http://localhost:4001/d370204b-205b-44bb-9698-3bf083b4b7a7/assets/parts/objects/body_up.stl","glUrl":"http://localhost:4001/d370204b-205b-44bb-9698-3bf083b4b7a7/assets/libs/objects/body_up.glb","daeUrl":"http://localhost:4001/d370204b-205b-44bb-9698-3bf083b4b7a7/assets/libs/objects/body_up.dae","objUrl":"http://localhost:4001/d370204b-205b-44bb-9698-3bf083b4b7a7/assets/libs/objects/body_up.obj","image":"http://localhost:4001/d370204b-205b-44bb-9698-3bf083b4b7a7/assets/libs/objects/body_up.png","solidType":"active"}
export class DataSetModel {
dataSetObjects: string[];
datasetType: string;
@ -116,14 +128,13 @@ export class DataSetModel {
export const datasetTypes = ["Object Detection - YOLOv8", "Pose Estimation - DOPE"];
export const datasetFormMockResult = `{
"typedataset": \${typedataset:Enum<T>:ObjectDetection},
"scene":\${<SelectScene/>:OBJECT:{"bricks":{"base_feature":{"path":"bricks/base_feature"},"form":{"path":"bricks/form"}}},
"models_randomization":{
"loc_range_low": [\${LOC_RANGE_LOW_1:number:-1}, \${LOC_RANGE_LOW_2:number:-1},/\${LOC_RANGE_LOW_3:number:0}],
"loc_range_high": [\${LOC_RANGE_HIGH_1:number:1}, \${LOC_RANGE_HIGH_2:number:1},/\${LOC_RANGE_HIGH_3:number:2}]
},
"selectParts":\${<SelectScene/>:OBJECT:{"details": []},
"scene":{
"objects": \${OBJECTS_SCENE:Array<OBJECTS_SCENE>:[]},
"lights": \${LIGHTS:Array<LIGHTS>:[]}

View file

@ -101,18 +101,7 @@ export const DataSetScreen: React.FunctionComponent = observer(() => {
filled={true}
/>
</div>
{store.parts?.map((el) => {
return (
<ListItem
status={store.assetStatus(el.name)}
name={el.name}
imgURL={el.image}
onChange={() => {
store.datasetCheckBox(el);
}}
/>
);
})}
</div>
<div style={{ display: "flex" }}>

View file

@ -1,11 +1,11 @@
import makeAutoObservable from "mobx-store-inheritance";
import { DataSetHttpRepository } from "./dataset_http_repository";
import { Drawer, UiErrorState } from "../../core/store/base_store";
import { HttpError } from "../../core/repository/http_repository";
import { HttpError } from "../../core/repository/core_http_repository";
import { DataSetModel, IDatasetModel, ProcessStatus } from "./dataset_model";
import { message } from "antd";
import { UUID } from "../all_projects/data/project_http_repository";
import { SocketRepository, socketRepository } from "../../core/repository/socket_repository";
import { SocketRepository, socketRepository } from "../../core/repository/core_socket_repository";
import { Parts } from "../details/details_http_repository";
export enum DrawersDataset {
@ -140,6 +140,7 @@ export class DataSetStore extends UiErrorState<HttpError> {
async (error) => message.error(error.message)
);
} else {
this.dataSetModel.processStatus = ProcessStatus.NEW;
(await this.dataSetRepository.editDataset(this.dataSetModel)).fold(
async () => {
message.success("Настройки датасета измнены");

View file

@ -1,6 +1,7 @@
import { HttpMethod, CoreHttpRepository } from "../../core/repository/http_repository";
import { HttpMethod, CoreHttpRepository } from "../../core/repository/core_http_repository";
import { EnvelopmentViewModel } from "./envelopment_view_model";
export interface Parts {
isSelect?: boolean;
name: string;
part_path: string;
material_path: string;

View file

@ -1,39 +0,0 @@
import { Result } from "../../../core/helper/result";
import { HttpError, HttpMethod, CoreHttpRepository } from "../../../core/repository/http_repository";
import { IDatasetModel } from "../../dataset/dataset_model";
import { Model } from "../model/model_machine_learning_process";
export interface ISkils {
_id: string;
name: string;
processStatus: string;
epoch: number;
isFinished: boolean;
datasetId: any;
project: any;
numberOfTrainedEpochs: number;
__v: number;
}
export class SkillsHttpRepository extends CoreHttpRepository {
execSkill(id: string) {
return this._jsonRequest(HttpMethod.GET, `/weights/exec?id=${id}`);
}
editSkill(model: ISkils) {
return this._jsonRequest(HttpMethod.PUT, `/weights/`, model);
}
getAllSkills = async () => {
return this._jsonRequest<ISkils[]>(HttpMethod.GET, "/weights");
};
deleteSkill = async (id: string) => {
return this._jsonRequest<void>(HttpMethod.DELETE, `/weights?id=${id}`);
};
addNewSkill = async (model: Model) => {
return this._jsonRequest(HttpMethod.POST, "/weights", model);
};
getDatasetsActiveProject = async (): Promise<Result<HttpError, IDatasetModel[]>> => {
return this._jsonRequest<IDatasetModel[]>(HttpMethod.GET, "/datasets");
};
}

View file

@ -1,87 +0,0 @@
import makeAutoObservable from "mobx-store-inheritance";
import { Result } from "../../../core/helper/result";
import { ISkils } from "../data/machine_learning_http_repository";
import { FormBuilderValidationModel } from "../../dataset/dataset_model";
import { IsString } from "class-validator";
import { ValidationModel } from "../../../core/model/validation_model";
export enum ModelMachineLearningTypes {
OBJECT_DETECTION = "OBJECT_DETECTION",
POSE_ESTIMATE = "POSE_ESTIMATE",
ML = "ML",
}
export class ModelMachineLearningProcess extends ValidationModel {
@IsString()
script: string;
formBuilder: FormBuilderValidationModel;
@IsString()
type: string;
@IsString()
name: string;
isEnd: boolean = false;
createDate: Date = new Date();
card?: string;
lastProcessLogs?: string;
lastProcessExecCommand?: string;
lastExecDate?: Date;
constructor(script: string, formBuilderValidationModel: FormBuilderValidationModel, type: string, card: string) {
super();
this.script = script;
this.formBuilder = formBuilderValidationModel;
this.type = type;
this.card = card;
}
static empty = () => new ModelMachineLearningProcess("", FormBuilderValidationModel.empty(), "", "");
}
export class Model {
numberOfTrainedEpochs?: number;
id?: string;
isFinished?: boolean;
constructor(
public name: string,
public datasetId: string,
public project: string,
public epoch: number,
numberOfTrainedEpochs?: number,
id?: string,
isFinished?: boolean
) {
this.numberOfTrainedEpochs = numberOfTrainedEpochs;
this.id = id;
this.isFinished = isFinished;
makeAutoObservable(this);
}
static fromISkill(model: ISkils) {
return new Model(
model.name,
model.datasetId._id,
model.project._id,
model.epoch,
model.numberOfTrainedEpochs,
model._id,
model.isFinished
);
}
static empty() {
return new Model("", "", "", 0);
}
valid(): Result<string, Model> {
if (this.name.isEmpty()) {
return Result.error("введите имя скила");
}
if (this.datasetId.isEmpty()) {
return Result.error("datasetId is empty");
}
if (this.project.isEmpty()) {
return Result.error("project is empty");
}
if (this.epoch.isNegative()) {
return Result.error("эпоха не может принимать отрицательное число");
}
return Result.ok(this);
}
}

View file

@ -1,153 +0,0 @@
import React from "react";
import { Alert, Drawer, Modal } from "antd";
import { observer } from "mobx-react-lite";
import { MainPage } from "../../../core/ui/pages/main_page";
import { CoreText, CoreTextType } from "../../../core/ui/text/text";
import { DrawersSkill, MachineLearningStore } from "./machine_learning_store";
import { ModelCard } from "./ui/cards/pose_estimate_card/model_card";
import { CoreInput, CoreInputType } from "../../../core/ui/input/input";
import { CoreButton } from "../../../core/ui/button/button";
import { CoreSelect } from "../../../core/ui/select/select";
import { ModelMachineLearningTypes } from "../model/model_machine_learning_process";
import { CardModel } from "./ui/cards/get_model_card";
import { FormBuilder } from "../../../core/ui/form_builder/form_builder";
interface IItem {
name: string;
isActive: boolean;
}
const skills: IItem[] = [{ name: "ML", isActive: true }];
export const MachineLearningPath = "/models";
export const MachineLearningScreen = observer(() => {
const [store] = React.useState(() => new MachineLearningStore());
React.useEffect(() => {
store.init();
}, [store]);
return (
<>
<MainPage
page={"модели"}
panelChildren={
<div style={{ justifyContent: "center", display: "flex", padding: 10 }}>
{skills.map((el) => (
<CoreText text={el.name} type={CoreTextType.header} />
))}
</div>
}
bodyChildren={
<div
style={{
display: "grid",
gridTemplateColumns: "repeat(auto-fill, minmax(220px,1px))",
width: "100%",
gap: 20,
margin: 12,
overflow: "auto",
height: window.innerHeight,
}}
>
{store.skils?.map((el) => (
<ModelCard
datasetName={el.datasetId.name}
id={el._id}
isFinished={el.isFinished}
name={el.name}
processStatus={el.processStatus}
empty={false}
epoch={el.numberOfTrainedEpochs}
epochNextTraining={el.epoch}
startOnClick={(id) => store.execSkill(id)}
continueOnClick={(id) => store.continueSkill(id)}
onEdit={(id) => store.fromEditSkill(id)}
onDelete={(id) => store.deleteSkill(id)}
/>
))}
<ModelCard empty={true} emptyOnClick={() => store.editDrawer(DrawersSkill.NEW_SKILL, true)} />
</div>
}
/>
<Drawer
title={store.titleDrawer}
destroyOnClose={true}
onClose={() => store.editDrawer(DrawersSkill.EDIT_SKILL, false)}
open={store.drawers.find((el) => el.name === DrawersSkill.EDIT_SKILL)?.status}
>
<div style={{ display: "flex", flexDirection: "column", justifyContent: "space-between", height: "100%" }}>
<div style={{ display: "flex" }}>
<CoreButton text="Сохранить" filled={true} onClick={() => store.saveEdiSkill()} />
<div style={{ width: 10 }} />
<CoreButton text="Отмена" onClick={() => store.editDrawer(DrawersSkill.NEW_SKILL, false)} />
</div>
</div>
</Drawer>
<Drawer
width={(window.innerWidth / 100) * 50}
title={store.titleDrawer}
destroyOnClose={true}
onClose={() => store.editDrawer(DrawersSkill.NEW_SKILL, false)}
open={store.drawers.find((el) => el.name === DrawersSkill.NEW_SKILL)?.status}
>
<div style={{ display: "flex", flexDirection: "column", justifyContent: "space-between", height: "100%" }}>
<div>
<CoreSelect
items={Object.keys(ModelMachineLearningTypes)}
value={store.viewModel.type}
label={"Тип навыка"}
onChange={(text: string) => store.updateForm({ type: text })}
/>
<CoreSelect
items={Object.keys(CardModel)}
value={""}
label={"Тип карточки"}
onChange={(text: string) => store.updateForm({ card: text })}
/>
<CoreInput label="Имя" onChange={(text) => store.updateForm({ name: text })} />
<CoreInput label="Команда для запуска" />
<CoreInput
label="FormBuilder Result"
onChange={(text) => {
store.viewModel.formBuilder.result = text;
}}
style={{ height: 200 }}
/>
<CoreInput
label="FormBuilder Context"
onChange={(text) => {
store.viewModel.formBuilder.context = text;
}}
style={{ height: 200 }}
/>
<CoreButton
text={"Посмотреть form builder "}
onClick={() => {
store.isModalOpen = true;
}}
/>
</div>
<div style={{ display: "flex" }}>
<CoreButton text="Сохранить" filled={true} onClick={() => store.saveSkill()} />
<div style={{ width: 10 }} />
<CoreButton text="Отмена" onClick={() => store.editDrawer(DrawersSkill.NEW_SKILL, false)} />
</div>
</div>
</Drawer>
<Modal
destroyOnClose={true}
open={store.isModalOpen}
footer={null}
closable={false}
closeIcon={null}
onCancel={() => {
store.isModalOpen = false;
}}
>
<FormBuilder formBuilder={store.viewModel.formBuilder} onChange={() => {}} />
</Modal>
<Alert />
</>
);
});

View file

@ -1,127 +0,0 @@
import makeAutoObservable from "mobx-store-inheritance";
import { NavigateFunction } from "react-router-dom";
import { HttpError } from "../../../core/repository/http_repository";
import { Drawer, UiDrawerFormState } from "../../../core/store/base_store";
import { ISkils, SkillsHttpRepository } from "../data/machine_learning_http_repository";
import { IDatasetModel } from "../../dataset/dataset_model";
import { message } from "antd";
import { UUID } from "../../all_projects/data/project_http_repository";
import { Model, ModelMachineLearningProcess } from "../model/model_machine_learning_process";
import { ProcessUpdate, SkillSocketRepository } from "../data/machine_learning_socket_repository";
export enum DrawersSkill {
NEW_SKILL = "Новый навык",
EDIT_SKILL = "Редактировать навык",
}
export class MachineLearningStore extends UiDrawerFormState<ModelMachineLearningProcess, HttpError> {
skillsHttpRepository: SkillsHttpRepository;
skillSocketRepository: SkillSocketRepository = new SkillSocketRepository();
skils?: ISkils[];
datasets?: IDatasetModel[];
activeProjectId?: UUID;
viewModel: ModelMachineLearningProcess;
titleDrawer: string = DrawersSkill.NEW_SKILL;
drawers: Drawer[];
isModalOpen:boolean = false;
constructor() {
super({});
this.drawers = Object.entries(DrawersSkill).map((k, v) => {
return {
name: k.at(1) ?? "",
status: false,
};
});
this.viewModel = ModelMachineLearningProcess.empty();
this.skillsHttpRepository = new SkillsHttpRepository();
this.skillSocketRepository.on(this.socketUpdate);
makeAutoObservable(this);
}
socketUpdate = (data: ProcessUpdate) => {
this.skils?.map((el) => {
if (el._id.isEqual(data.id)) {
el.processStatus = data.status;
}
return el;
});
};
getSkillById = (id: string) => this.skils?.find((el) => el._id === id);
continueSkill = async (id: string) => {
const skill = this.getSkillById(id) as ISkils;
skill.processStatus = "before_training";
skill.numberOfTrainedEpochs += skill.epoch;
await this.skillsHttpRepository.editSkill(skill);
await this.messageHttp(this.skillsHttpRepository.execSkill(id), {
errorMessage: "Ошибка",
successMessage: "Обучение продолжено",
});
};
execSkill = async (id: string) => {
const skill = this.getSkillById(id) as ISkils;
skill.processStatus = "exec";
skill.numberOfTrainedEpochs = skill.epoch;
await this.skillsHttpRepository.editSkill(skill);
this.messageHttp(this.skillsHttpRepository.execSkill(id), {
errorMessage: "Ошибка",
successMessage: "Обучение стартовало",
});
};
errorHandingStrategy: (error: HttpError) => {};
init = async (navigate?: NavigateFunction | undefined) => {
await this.mapOk("skils", this.skillsHttpRepository.getAllSkills());
await this.mapOk("datasets", this.skillsHttpRepository.getDatasetsActiveProject());
await this.mapOk("activeProjectId", this.skillsHttpRepository.getActiveProjectId());
};
saveSkill = async () =>
(await this.viewModel.valid()).fold(
async (s) => {
message.success("URA")
},
async (e) => {
message.error(e);
}
);
// this.viewModel.project = this.activeProjectId?.id ?? "";
// this.viewModel.valid().fold(
// async (model) => {
// (await this.skillsHttpRepository.addNewSkill(model)).fold(
// async (s) => {
// message.success("Новый ");
// this.viewModel = Model.empty();
// await this.mapOk("skils", this.skillsHttpRepository.getAllSkills());
// },
// async (e) => message.error(e.message)
// );
// },
// async (e) => message.error(e)
// );
editDrawer(drawerName: DrawersSkill, status: boolean): void {
this.titleDrawer = drawerName;
this.drawers = this.drawers.map((el) => {
if (el.name === drawerName) {
el.status = status;
}
return el;
});
}
deleteSkill = async (id: string): Promise<void> => {
await this.skillsHttpRepository.deleteSkill(id);
await this.init();
};
fromEditSkill(id: string): void {
// this.viewModel = Model.fromISkill(this.getSkillById(id) as ISkils);
this.editDrawer(DrawersSkill.EDIT_SKILL, true);
}
saveEdiSkill = async () => {
// const skillOrigin = this.getSkillById(this.viewModel.id as string) as ISkils;
// skillOrigin.numberOfTrainedEpochs = this.viewModel.epoch;
// skillOrigin.isFinished = this.viewModel.isFinished ?? false;
// await this.skillsHttpRepository.editSkill(skillOrigin);
this.editDrawer(DrawersSkill.EDIT_SKILL, false);
};
}

View file

@ -1,4 +0,0 @@
export enum CardModel {
pose_estimate = "pose_estimate",
}
export const getModelCard = () => {};

View file

@ -1,165 +0,0 @@
import { CoreButton } from "../../../../../../core/ui/button/button";
import { Icon } from "../../../../../../core/ui/icons/icons";
import { Dropdown } from "antd";
import { CoreText, CoreTextType } from "../../../../../../core/ui/text/text";
import { ProcessStatus } from "../../../../../dataset/dataset_model";
import { IMenuItem } from "../../../../../dataset/card_dataset";
import type { MenuProps } from "antd";
import { match } from "ts-pattern";
export interface IModelCardProps {
processStatus?: string;
name?: string;
isFinished?: boolean;
id?: string;
emptyOnClick?: Function;
startOnClick?: (id: string) => void;
continueOnClick?: (id: string) => void;
empty: boolean;
onEdit?: (id: string) => void;
epoch?: number;
onDelete?: (id: string) => void;
datasetName?: string;
epochNextTraining?: number;
}
export const ModelCard = (props: IModelCardProps) => {
const menu: IMenuItem[] = [
{
onClick: () => {
if (props.onEdit && props.id) props.onEdit(props.id);
},
name: "Редактировать",
},
{
onClick: () => {
if (props.onDelete && props.id) props.onDelete(props.id);
},
name: "Удалить",
},
];
const items: MenuProps["items"] = menu.map((el, index) => {
return {
key: String(index),
label: <CoreText text={el.name} type={CoreTextType.medium} />,
onClick: () => el.onClick(props.id),
};
});
return (
<div
style={{
margin: 10,
backgroundColor: "#f7f2fa",
borderRadius: 10,
padding: 10,
width: 200,
height: "max-content",
alignContent: "center",
display: "flex",
flexDirection: "column",
alignItems: "stretch",
justifyContent: "space-between",
}}
>
{match(props.empty)
.with(true, () => (
<>
<div
onClick={() => {
if (props.empty && props.emptyOnClick) props.emptyOnClick();
}}
style={{ display: "flex", justifyContent: "center", alignItems: "center" }}
>
<Icon type="PlusCircle" />
</div>
</>
))
.with(false, () => (
<>
<>
<div
style={{
display: "flex",
justifyContent: "space-between",
}}
>
<div style={{ display: "flex", flexDirection: "column", margin: 10 }}>
<CoreText text={props.name ?? ""} type={CoreTextType.medium} />
<div style={{ height: 10 }} />
<CoreText text={"обученных эпох: " + props.epoch?.toString() ?? ""} type={CoreTextType.small} />
<CoreText text={"обучится эпох: " + props.epoch?.toString() ?? ""} type={CoreTextType.small} />
<div style={{ display: "flex", alignItems: "center" }}>
<CoreText text={"закончен:"} type={CoreTextType.small} />
<div style={{ width: 5 }} />
<div style={{ backgroundColor: props.isFinished ? "green" : "red", width: 10, height: 10 }} />
</div>
<CoreText text={"Датасет: " + props.datasetName ?? ""} type={CoreTextType.small} />
</div>
<div style={{ height: 10 }}>
<Dropdown overlayStyle={{ backgroundColor: "rgba(243, 237, 247, 1)" }} menu={{ items }}>
<div>
<Icon type="Settings" />
</div>
</Dropdown>
</div>
</div>
<div style={{ height: 10 }} />
<div>
{match(props.processStatus)
.with(ProcessStatus.ERROR, () => (
<>
<CoreButton
style={{
backgroundColor: "red",
}}
onClick={() => {
if (props.startOnClick && props.id) props.startOnClick(props.id);
}}
filled={true}
text="Ошибка"
/>
</>
))
.with(ProcessStatus.END, () => (
<>
<CoreButton
text="дообучение"
onClick={() => {
if (props.continueOnClick && props.id) props.continueOnClick(props.id);
}}
/>
<div style={{ height: 10 }} />
<CoreButton
text="заново"
onClick={() => {
if (props.startOnClick && props.id) props.startOnClick(props.id);
}}
/>
</>
))
.with(ProcessStatus.NONE, () => (
<>
<CoreButton
text="старт"
onClick={() => {
if (props.startOnClick && props.id) props.startOnClick(props.id);
}}
/>
</>
))
.otherwise(() => (
<></>
))}
</div>
</>
</>
))
.otherwise(() => (
<></>
))}
</div>
);
};

View file

@ -1,5 +1,5 @@
import { Result } from "../../../core/helper/result";
import { HttpMethod, CoreHttpRepository, HttpError } from "../../../core/repository/http_repository";
import { HttpMethod, CoreHttpRepository, HttpError } from "../../../core/repository/core_http_repository";
import { CoreError } from "../../../core/store/base_store";
import { SceneModel } from "../model/scene_model";
import { SceneViewModel } from "../model/scene_view_model";

View file

@ -1,5 +1,5 @@
import { RobotModel } from "../../../../../core/model/robot_model";
import { HttpMethod, HttpRepository } from "../../../../../core/repository/http_repository";
import { HttpMethod, HttpRepository } from "../../../../../core/repository/core_http_repository";
export interface RobotURL {
robotUrl: string;
}

Some files were not shown because too many files have changed in this diff Show more