deleted unnecessary files
added new features
This commit is contained in:
parent
6840402b1f
commit
c17515d571
47 changed files with 1039 additions and 479 deletions
14
.vscode/settings.json
vendored
14
.vscode/settings.json
vendored
|
@ -15,6 +15,18 @@
|
|||
"*ui": false,
|
||||
"*ui.*": false
|
||||
},
|
||||
"cSpell.words": ["antd", "Collada", "Contolls", "fileupload", "lerp", "metadatas", "undici", "uuidv"],
|
||||
"cSpell.words": [
|
||||
"запущен",
|
||||
"процесс",
|
||||
"antd",
|
||||
"Collada",
|
||||
"Contolls",
|
||||
"fileupload",
|
||||
"lerp",
|
||||
"metadatas",
|
||||
"Skils",
|
||||
"undici",
|
||||
"uuidv"
|
||||
],
|
||||
"editor.rulers": [100]
|
||||
}
|
||||
|
|
2
p.ts
Normal file
2
p.ts
Normal file
|
@ -0,0 +1,2 @@
|
|||
console.log([1, 2, 3, 4, 5, 6].reduce((element, acc) => (acc += element)));
|
||||
console.log(["1", "2", "3", "4", "5", "6"].reduce((element, acc) => (acc += element)));
|
|
@ -49,18 +49,21 @@ export class ExecutorProgramService
|
|||
|
||||
if (spawnError instanceof SpawnError) {
|
||||
this.emit(Result.error(spawnError));
|
||||
this.worker = undefined;
|
||||
return;
|
||||
}
|
||||
const execError = ExecError.isExecError(e);
|
||||
|
||||
if (execError instanceof ExecError) {
|
||||
this.emit(Result.error(execError));
|
||||
this.worker = undefined;
|
||||
return;
|
||||
}
|
||||
|
||||
const executorResult = ExecutorResult.isExecutorResult(e);
|
||||
if (executorResult instanceof ExecutorResult) {
|
||||
this.emit(Result.ok(executorResult));
|
||||
this.worker = undefined;
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
@ -78,7 +81,10 @@ export class ExecutorProgramService
|
|||
console.log(error);
|
||||
}
|
||||
}
|
||||
|
||||
public deleteWorker() {
|
||||
if (this.worker) this.worker.kill();
|
||||
this.worker = undefined;
|
||||
}
|
||||
public async call(type: EXEC_TYPE, command: string, args: Array<string> | undefined = undefined): Promise<void> {
|
||||
if (type == EXEC_TYPE.EXEC) {
|
||||
this.workerExecuted(command, WorkerType.EXEC);
|
||||
|
|
|
@ -1,9 +1,27 @@
|
|||
import { CallbackStrategyWithEmpty } from "../controllers/http_controller";
|
||||
import { Result } from "../helpers/result";
|
||||
import { TypedEvent } from "../helpers/typed_event";
|
||||
import { EXEC_TYPE, ExecError, SpawnError } from "../models/exec_error_model";
|
||||
import { ExecutorResult } from "../models/executor_result";
|
||||
import { ExecutorProgramService } from "../services/executor_program_service";
|
||||
|
||||
const executorProgramService = new ExecutorProgramService("");
|
||||
export class KillLastProcessUseCase extends CallbackStrategyWithEmpty {
|
||||
call = async (): Promise<Result<undefined, string>> => {
|
||||
executorProgramService.deleteWorker();
|
||||
return Result.ok("ok");
|
||||
};
|
||||
}
|
||||
|
||||
export class IsHaveActiveProcessUseCase extends CallbackStrategyWithEmpty {
|
||||
call = async (): Promise<Result<string, string>> => {
|
||||
if (executorProgramService.worker === undefined) {
|
||||
return Result.ok("process not work");
|
||||
}
|
||||
return Result.error("process is exists");
|
||||
};
|
||||
}
|
||||
|
||||
export class ExecProcessUseCase {
|
||||
call = async (
|
||||
path: string,
|
||||
|
@ -11,10 +29,10 @@ export class ExecProcessUseCase {
|
|||
watcher?: TypedEvent<Result<ExecError | SpawnError, ExecutorResult>>
|
||||
): Promise<Result<Error, string>> => {
|
||||
try {
|
||||
const executorProgramService = new ExecutorProgramService(path);
|
||||
if (watcher)
|
||||
executorProgramService.execPath = path;
|
||||
executorProgramService.on((event) => {
|
||||
watcher.emit(event);
|
||||
console.log(event);
|
||||
if (watcher) watcher.emit(event);
|
||||
});
|
||||
executorProgramService.call(EXEC_TYPE.EXEC, command);
|
||||
|
||||
|
|
|
@ -11,4 +11,3 @@ export class TriggerPresentation extends CrudController<TriggerModelValidationMo
|
|||
});
|
||||
}
|
||||
}
|
||||
"".isEmpty();
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
import { CrudController } from "../../core/controllers/crud_controller";
|
||||
import { IsHaveActiveProcessUseCase, KillLastProcessUseCase } from "../../core/usecases/exec_process_usecase";
|
||||
import { CreateDataSetScenario } from "./domain/create_dataset_scanario";
|
||||
import { ExecDatasetProcessScenario } from "./domain/exec_process_scenario";
|
||||
import { GetDatasetActiveProjectScenario } from "./domain/get_dataset_active_project_scenario";
|
||||
import { DatasetDBModel } from "./models/dataset_database_model";
|
||||
import { DatasetValidationModel } from "./models/dataset_validation_model";
|
||||
|
@ -13,5 +15,20 @@ export class DatasetsPresentation extends CrudController<DatasetValidationModel,
|
|||
});
|
||||
super.post(new CreateDataSetScenario().call);
|
||||
super.get(new GetDatasetActiveProjectScenario().call);
|
||||
this.subRoutes.push({
|
||||
method: "POST",
|
||||
subUrl: "exec",
|
||||
fn: new ExecDatasetProcessScenario(),
|
||||
});
|
||||
this.subRoutes.push({
|
||||
method: "GET",
|
||||
subUrl: "is/running",
|
||||
fn: new IsHaveActiveProcessUseCase(),
|
||||
});
|
||||
this.subRoutes.push({
|
||||
method: "GET",
|
||||
subUrl: "delete/process",
|
||||
fn: new KillLastProcessUseCase(),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -48,45 +48,14 @@ export class CreateDataSetScenario extends CallbackStrategyWithValidationModel<D
|
|||
return (
|
||||
await new SearchDataBaseModelUseCase<IProjectModel>(ProjectDBModel).call({ isActive: true }, "no active projects")
|
||||
).map(async (project) => {
|
||||
model.processStatus = "exec";
|
||||
model.processStatus = "new";
|
||||
model.local_path = project.rootDir;
|
||||
model.projectId = project._id;
|
||||
const d = new DatasetDBModel();
|
||||
Object.assign(d, model);
|
||||
await d.save();
|
||||
|
||||
await new ExecProcessUseCase().call(
|
||||
`${project.rootDir}/`,
|
||||
`python3 $PYTHON_BLENDER_PROC --path '${project.rootDir}/${model.name}' --cfg '${JSON.stringify(model)}'`,
|
||||
new ProcessWatcherAndDatabaseUpdateService(d._id as unknown as ObjectId)
|
||||
);
|
||||
return Result.ok("create dataset ok");
|
||||
});
|
||||
};
|
||||
}
|
||||
// сохрнать formbuilder result и передать его в python
|
||||
// {
|
||||
// "typedataset": ${typedataset:Enum<T>:"ObjectDetection"},
|
||||
// "dataset_path": ${DATASET_PATH:string:""},
|
||||
// "models":${models:Array<MODELS>:[]},
|
||||
// "models_randomization":{
|
||||
// "loc_range_low": [${LOC_RANGE_LOW_1:number:-1}, ${LOC_RANGE_LOW_2:number:-1},/${LOC_RANGE_LOW_3:number:0}],
|
||||
// "loc_range_high": [${LOC_RANGE_HIGH_1:number:1}, ${LOC_RANGE_HIGH_2:number:1},/${LOC_RANGE_HIGH_3:number:2}]
|
||||
// },
|
||||
// "scene":{
|
||||
// "objects": ${OBJECTS_SCENE:Array<OBJECTS_SCENE>:[]},
|
||||
// "lights": ${LIGHTS:Array<LIGHTS>:[]},
|
||||
// },
|
||||
// "camera_position":{
|
||||
// "center_shell": [${CENTER_SHELL_1:number:0}, ${CENTER_SHELL_2:number:0}, ${CENTER_SHELL_3:number:0}],
|
||||
// "radius_range": [${RADIUS_RANGE_1:number:0.4}, ${RADIUS_RANGE_2:number:1.4}],
|
||||
// "elevation_range": [${ELEVATION_RANGE_1:number:10}, ${ELEVATION_RANGE_2:number:90}]
|
||||
// },
|
||||
// "generation":{
|
||||
// "n_cam_pose": ${N_CAM_POSE:number:5},
|
||||
// "n_sample_on_pose": ${N_SAMPLE_ON_POSE:number:3},
|
||||
// "n_series": ${N_SERIES:number:100},
|
||||
// "image_format": ${image_format:Enum<F>:"jpg"},
|
||||
// "image_size_wh": [${IMAGE_SIZE_WH_1:number:640}, ${IMAGE_SIZE_WH_2:number:480}]
|
||||
// }
|
||||
// }
|
||||
|
|
24
server/src/features/datasets/domain/exec_process_scenario.ts
Normal file
24
server/src/features/datasets/domain/exec_process_scenario.ts
Normal file
|
@ -0,0 +1,24 @@
|
|||
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 { DatasetDBModel } from "../models/dataset_database_model";
|
||||
import { IDatasetModel } from "../models/dataset_validation_model";
|
||||
import { ProcessWatcherAndDatabaseUpdateService } from "./create_dataset_scanario";
|
||||
|
||||
export class ExecDatasetProcessScenario extends CallbackStrategyWithIdQuery {
|
||||
idValidationExpression = new MongoIdValidation();
|
||||
|
||||
call = async (id: string): ResponseBase => {
|
||||
return (await new ReadByIdDataBaseModelUseCase<IDatasetModel>(DatasetDBModel).call(id)).map(async (model) => {
|
||||
return (await new IsHaveActiveProcessUseCase().call()).map(() => {
|
||||
return new ExecProcessUseCase().call(
|
||||
`${model.project.rootDir}/`,
|
||||
`python3 $PYTHON_BLENDER_PROC --cfg '${JSON.stringify(model)}' `,
|
||||
new ProcessWatcherAndDatabaseUpdateService(id as unknown as ObjectId)
|
||||
);
|
||||
});
|
||||
});
|
||||
};
|
||||
}
|
|
@ -9,7 +9,7 @@ export class GetDatasetActiveProjectScenario extends CallbackStrategyWithEmpty {
|
|||
return (
|
||||
await new SearchDataBaseModelUseCase<IProjectModel>(ProjectDBModel).call({ isActive: true }, "no active projects")
|
||||
).map(async (project) => {
|
||||
return Result.ok(await DatasetDBModel.find({ projectId: project._id }));
|
||||
return Result.ok(await DatasetDBModel.find({ project: project._id }));
|
||||
});
|
||||
};
|
||||
}
|
||||
|
|
|
@ -17,19 +17,32 @@ export const DatasetSchema = new Schema({
|
|||
type: Schema.Types.Mixed,
|
||||
of: String,
|
||||
},
|
||||
unixTime: {
|
||||
type: Number,
|
||||
default: Date.now(),
|
||||
},
|
||||
neuralNetworkAction: {
|
||||
type: String,
|
||||
},
|
||||
neuralNetworkName: {
|
||||
type: String,
|
||||
},
|
||||
processStatus: {
|
||||
type: String,
|
||||
default: "none",
|
||||
},
|
||||
projectId: {
|
||||
project: {
|
||||
type: Schema.Types.ObjectId,
|
||||
ref: projectSchema,
|
||||
autopopulate: false,
|
||||
default: null,
|
||||
autopopulate: true,
|
||||
require: true,
|
||||
},
|
||||
processLogs: {
|
||||
type: String,
|
||||
},
|
||||
datasetType: {
|
||||
type: String,
|
||||
},
|
||||
}).plugin(require("mongoose-autopopulate"));
|
||||
|
||||
export const datasetSchema = "Dataset";
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import { Type } from "class-transformer";
|
||||
import { IsArray, IsString, ValidateNested } from "class-validator";
|
||||
import { IProjectModel } from "../../_projects/models/project_database_model";
|
||||
|
||||
export class FormBuilderValidationModel {
|
||||
@IsString()
|
||||
|
@ -17,6 +18,7 @@ export interface IDatasetModel {
|
|||
formBuilder: FormBuilderValidationModel;
|
||||
processLogs: string;
|
||||
processStatus: string;
|
||||
project?: IProjectModel;
|
||||
}
|
||||
|
||||
export class DatasetValidationModel implements IDatasetModel {
|
||||
|
|
|
@ -1,15 +1,8 @@
|
|||
import { App } from "../../../core/controllers/app";
|
||||
import { CallbackStrategyWithFileUpload, ResponseBase } from "../../../core/controllers/http_controller";
|
||||
import { Result } from "../../../core/helpers/result";
|
||||
import { IFile } from "../../../core/interfaces/file";
|
||||
import { CreateDataBaseModelUseCase } from "../../../core/usecases/create_database_model_usecase";
|
||||
import { CreateFileUseCase } from "../../../core/usecases/create_file_usecase";
|
||||
import { CreateFolderUseCase } from "../../../core/usecases/create_folder_usecase";
|
||||
import { MongoIdValidation } from "../../../core/validations/mongo_id_validation";
|
||||
import { IProjectInstanceModel, ProjectInstanceDbModel } from "../models/project_instance_database_model";
|
||||
import { ProjectInstanceValidationModel } from "../models/project_instance_validation_model";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
import { SetActiveProjectScenario } from "./set_active_project_use_scenario";
|
||||
import { IProjectInstanceModel } from "../models/project_instance_database_model";
|
||||
import { ReadByIdDataBaseModelUseCase } from "../../../core/usecases/read_by_id_database_model_usecase";
|
||||
import { ProjectDBModel } from "../../_projects/models/project_database_model";
|
||||
import { ExecProcessUseCase } from "../../../core/usecases/exec_process_usecase";
|
||||
|
|
|
@ -17,5 +17,8 @@
|
|||
<div id="root"></div>
|
||||
|
||||
</body>
|
||||
<style>
|
||||
@import url('https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&display=swap')
|
||||
</style>
|
||||
|
||||
</html>
|
|
@ -1,12 +0,0 @@
|
|||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
|
||||
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Transformed by: SVG Repo Mixer Tools -->
|
||||
<svg width="64px" height="64px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
|
||||
<g id="SVGRepo_bgCarrier" stroke-width="0"/>
|
||||
|
||||
<g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
|
||||
<g id="SVGRepo_iconCarrier"> <path fill-rule="evenodd" clip-rule="evenodd" d="M2 5.75C2 5.33579 2.33579 5 2.75 5H20.75C21.1642 5 21.5 5.33579 21.5 5.75C21.5 6.16421 21.1642 6.5 20.75 6.5H2.75C2.33579 6.5 2 6.16421 2 5.75ZM2 9.75C2 9.33579 2.33579 9 2.75 9H20.75C21.1642 9 21.5 9.33579 21.5 9.75C21.5 10.1642 21.1642 10.5 20.75 10.5H2.75C2.33579 10.5 2 10.1642 2 9.75ZM20.2113 12.6586C20.5379 12.9134 20.5961 13.3847 20.3414 13.7113L16.4414 18.7113C16.3022 18.8897 16.0899 18.9958 15.8636 18.9999C15.6373 19.004 15.4213 18.9057 15.2757 18.7324L13.1757 16.2324C12.9093 15.9152 12.9504 15.4421 13.2676 15.1757C13.5848 14.9093 14.0579 14.9504 14.3243 15.2676L15.8284 17.0582L19.1586 12.7887C19.4134 12.4621 19.8847 12.4039 20.2113 12.6586ZM2 13.75C2 13.3358 2.33579 13 2.75 13H9.75C10.1642 13 10.5 13.3358 10.5 13.75C10.5 14.1642 10.1642 14.5 9.75 14.5H2.75C2.33579 14.5 2 14.1642 2 13.75ZM2 17.75C2 17.3358 2.33579 17 2.75 17H9.75C10.1642 17 10.5 17.3358 10.5 17.75C10.5 18.1642 10.1642 18.5 9.75 18.5H2.75C2.33579 18.5 2 18.1642 2 17.75Z" fill="#f46036"/> </g>
|
||||
|
||||
</svg>
|
Before Width: | Height: | Size: 1.4 KiB |
BIN
ui/src/core/assets/images/pose_estemation.jpg
Normal file
BIN
ui/src/core/assets/images/pose_estemation.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 11 KiB |
|
@ -22,7 +22,10 @@ declare global {
|
|||
}
|
||||
interface Number {
|
||||
fromArray(): number[];
|
||||
toPx(): string;
|
||||
unixFromDate(): string;
|
||||
}
|
||||
|
||||
interface String {
|
||||
isEmpty(): boolean;
|
||||
isNotEmpty(): boolean;
|
||||
|
|
|
@ -5,4 +5,17 @@ export const NumberExtensions = () => {
|
|||
return Array.from(this.toString()).map((el) => Number(el));
|
||||
};
|
||||
}
|
||||
if (Number().toPx === undefined) {
|
||||
// eslint-disable-next-line no-extend-native
|
||||
Number.prototype.toPx = function () {
|
||||
return String(this) + "px";
|
||||
};
|
||||
}
|
||||
if (Number().unixFromDate === undefined) {
|
||||
// eslint-disable-next-line no-extend-native
|
||||
Number.prototype.unixFromDate = function () {
|
||||
const date = new Date(Number(this) * 1000);
|
||||
return `${date.getUTCFullYear()}.${date.getMonth()}.${date.getDay()} ${date.getHours()}:${date.getMinutes()}`;
|
||||
};
|
||||
}
|
||||
};
|
||||
|
|
|
@ -15,8 +15,12 @@ import {
|
|||
import {
|
||||
StickObjectsMarkingScreen,
|
||||
StickObjectsMarkingScreenPath,
|
||||
} from "../../features/stick_objects_marking/stick_objects_marking_screen";
|
||||
} from "../../features/_stick_objects_marking/stick_objects_marking_screen";
|
||||
import { DataSetScreen, DatasetsScreenPath } from "../../features/dataset/dataset_screen";
|
||||
import DetailsScreen, { DetailsScreenPath } from "../../features/details/details_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";
|
||||
|
||||
const idURL = ":id";
|
||||
|
||||
|
@ -51,4 +55,21 @@ export const router = createBrowserRouter([
|
|||
path: DatasetsScreenPath,
|
||||
element: <DataSetScreen />,
|
||||
},
|
||||
{
|
||||
path: DetailsScreenPath,
|
||||
element: <DetailsScreen />,
|
||||
},
|
||||
{
|
||||
path: AssemblesScreenPath,
|
||||
element: <AssemblesScreen />,
|
||||
},
|
||||
{
|
||||
path: SimulationScreenPath,
|
||||
element: <SimulationScreen />,
|
||||
},
|
||||
|
||||
{
|
||||
path: EstimateScreenPath,
|
||||
element: <EstimateScreen />,
|
||||
},
|
||||
]);
|
||||
|
|
32
ui/src/core/ui/button/button.tsx
Normal file
32
ui/src/core/ui/button/button.tsx
Normal file
|
@ -0,0 +1,32 @@
|
|||
import * as React from "react";
|
||||
import { CoreText, CoreTextType } from "../text/text";
|
||||
|
||||
export interface IButtonProps {
|
||||
block?: boolean;
|
||||
filled?: boolean;
|
||||
text?: string;
|
||||
onClick?: any;
|
||||
}
|
||||
|
||||
export function CoreButton(props: IButtonProps) {
|
||||
return (
|
||||
<div
|
||||
onClick={() => props.onClick?.call()}
|
||||
style={{
|
||||
backgroundColor: props.filled ? "rgba(103, 80, 164, 1)" : "",
|
||||
paddingRight: 20,
|
||||
paddingLeft: 20,
|
||||
paddingTop: 10,
|
||||
paddingBottom: 10,
|
||||
borderRadius: 24,
|
||||
border: props.block ? "1px solid rgba(29, 27, 32, 0.12)" : props.filled ? "" : "1px solid black",
|
||||
}}
|
||||
>
|
||||
<CoreText
|
||||
text={props.text ?? ""}
|
||||
type={CoreTextType.medium}
|
||||
color={props.block ? "#1D1B20" : props.filled ? "white" : "rgba(103, 80, 164, 1)"}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
97
ui/src/core/ui/card/card_dataset.tsx
Normal file
97
ui/src/core/ui/card/card_dataset.tsx
Normal file
|
@ -0,0 +1,97 @@
|
|||
import { Spin } from "antd";
|
||||
import { LoadingOutlined } from "@ant-design/icons";
|
||||
import poseIMG from "../../assets/images/pose_estemation.jpg";
|
||||
import { Icon } from "../icons/icons";
|
||||
import { CoreText, CoreTextType } from "../text/text";
|
||||
import { CoreButton } from "../button/button";
|
||||
|
||||
export const enum CardDataSetType {
|
||||
EMPTY = "EMPTY",
|
||||
COMPLETED = "COMPLETED",
|
||||
}
|
||||
|
||||
interface ICardDataSetProps {
|
||||
type: CardDataSetType;
|
||||
neuralNetworkAction?: string;
|
||||
neuralNetworkName?: string;
|
||||
objects?: string[];
|
||||
unixDate?: number;
|
||||
processStatus?: string;
|
||||
onClickButton?: (id: string) => void;
|
||||
onClickEmptyCard?: Function;
|
||||
id?: string;
|
||||
}
|
||||
|
||||
export const CardDataSet = (props: ICardDataSetProps) => {
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
width: 272,
|
||||
height: 372,
|
||||
borderRadius: 12,
|
||||
border: "1px solid #CAC4D0",
|
||||
backgroundColor: "rgba(254, 247, 255, 1)",
|
||||
cursor: "pointer",
|
||||
}}
|
||||
onClick={() => {
|
||||
if (props.type.isEqual(CardDataSetType.EMPTY) && props.onClickEmptyCard) {
|
||||
props.onClickEmptyCard();
|
||||
}
|
||||
}}
|
||||
>
|
||||
<div style={{ height: 80 }}>
|
||||
{props.type.isEqual(CardDataSetType.EMPTY) ? null : (
|
||||
<div style={{ display: "flex", alignItems: "center", justifyContent: "space-between" }}>
|
||||
<div style={{ width: 70, marginTop: 11 }}></div>
|
||||
<div style={{ height: 80, alignContent: "center", marginRight: 40 }}>
|
||||
<CoreText text={props.neuralNetworkName ?? ""} type={CoreTextType.header} />
|
||||
<CoreText text={props.neuralNetworkAction ?? ""} type={CoreTextType.medium} />
|
||||
</div>
|
||||
<div>
|
||||
<Icon type="Settings" />
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<img alt="pose" style={{ width: "100%" }} src={poseIMG}></img>
|
||||
<div
|
||||
style={{
|
||||
textAlignLast: props.type.isEqual(CardDataSetType.EMPTY) ? "center" : "auto",
|
||||
marginTop: props.type.isEqual(CardDataSetType.EMPTY) ? 80 : 10,
|
||||
}}
|
||||
>
|
||||
{props.type === CardDataSetType.EMPTY ? (
|
||||
<Icon type="PlusCircle" />
|
||||
) : (
|
||||
<div style={{ margin: 10 }}>
|
||||
<CoreText text={`Объектов: ${props.objects?.length ?? 0}`} type={CoreTextType.large} />
|
||||
<CoreText text={Number(props.unixDate).unixFromDate()} type={CoreTextType.medium} color="#49454F" />
|
||||
<div style={{ height: 40 }} />
|
||||
<div style={{ width: 240, overflow: "hidden", whiteSpace: "nowrap", height: 40 }}>
|
||||
<CoreText text={props.objects?.join(", ") ?? ""} type={CoreTextType.medium} color="#49454F" />
|
||||
</div>
|
||||
<div style={{ display: "flex", flexDirection: "row", justifyContent: "flex-end", alignItems: "center" }}>
|
||||
{props.processStatus === "exec" ? (
|
||||
<Spin indicator={<LoadingOutlined style={{ fontSize: 34, color: "rgba(103, 80, 164, 1)" }} spin />} />
|
||||
) : null}
|
||||
<div style={{ width: 20 }} />
|
||||
{props.processStatus === "new" ? (
|
||||
<CoreButton
|
||||
onClick={() => {
|
||||
if (props.type.isEqual(CardDataSetType.COMPLETED) && props.onClickButton && props.id) {
|
||||
props.onClickButton(props.id);
|
||||
}
|
||||
}}
|
||||
filled={true}
|
||||
text="Старт"
|
||||
/>
|
||||
) : (
|
||||
<CoreButton text="Завершено" block={true} />
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
|
@ -3,9 +3,7 @@ import { Input, Select, Button } from "antd";
|
|||
import { InputBuilderViewModel, InputType } from "./form_view_model";
|
||||
import { observer } from "mobx-react-lite";
|
||||
import { FormBuilderStore } from "./form_builder_store";
|
||||
import { extensions } from "../../extensions/extensions";
|
||||
import { FormBuilderValidationModel } from "../../../features/dataset/dataset_store";
|
||||
extensions();
|
||||
import { FormBuilderValidationModel } from "../../../features/dataset/dataset_model";
|
||||
|
||||
export interface IFormBuilder {
|
||||
context: string;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { makeAutoObservable } from "mobx";
|
||||
import { FormViewModel } from "./form_view_model";
|
||||
import { TypedEvent } from "../../helper/typed_event";
|
||||
import { FormBuilderValidationModel } from "../../../features/dataset/dataset_store";
|
||||
import { FormBuilderValidationModel } from "../../../features/dataset/dataset_model";
|
||||
|
||||
export class ChangerForm extends TypedEvent<FormBuilderValidationModel | undefined> {}
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { makeAutoObservable, observable } from "mobx";
|
||||
import { Result } from "../../helper/result";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
import { FormBuilderValidationModel } from "../../../features/dataset/dataset_store";
|
||||
import { FormBuilderValidationModel } from "../../../features/dataset/dataset_model";
|
||||
|
||||
export enum InputType {
|
||||
NUMBER = "number",
|
||||
|
@ -48,16 +48,16 @@ export class FormViewModel {
|
|||
this.inputs = inputs;
|
||||
makeAutoObservable(this);
|
||||
}
|
||||
|
||||
public fromFormBuilderValidationModel() {
|
||||
console.log(this.toResult());
|
||||
return new FormBuilderValidationModel(
|
||||
this.context,
|
||||
this.result,
|
||||
this.inputs.map((el) => el.toJson()),
|
||||
this.toResult()
|
||||
JSON.parse(this.toResult().replaceAll("\n", "").replaceAll("\\", "").replaceAll("/", ""))
|
||||
);
|
||||
}
|
||||
public toResult() {
|
||||
public toResult(): string {
|
||||
let result = this.result;
|
||||
|
||||
this.inputs.forEach((element) => {
|
||||
|
@ -97,6 +97,7 @@ export class FormViewModel {
|
|||
if (inputResult instanceof Array) inputResult = JSON.stringify(inputResult);
|
||||
result = result.replace(new RegExp("\\${" + element.name + ".*?}"), inputResult);
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
static fromString(result: string, context: string): Result<void, FormViewModel> {
|
||||
|
|
89
ui/src/core/ui/icons/icons.tsx
Normal file
89
ui/src/core/ui/icons/icons.tsx
Normal file
|
@ -0,0 +1,89 @@
|
|||
import * as React from "react";
|
||||
import { Result } from "../../helper/result";
|
||||
|
||||
export interface IIconsProps {
|
||||
type: string;
|
||||
style?: React.CSSProperties;
|
||||
}
|
||||
|
||||
export function Icon(props: IIconsProps) {
|
||||
const icon = getIconSvg(props.type);
|
||||
return icon.fold(
|
||||
(node) => {
|
||||
return <div style={props.style}>{node}</div>;
|
||||
},
|
||||
() => (
|
||||
<div style={props.style}>
|
||||
<svg width="12" height="12" viewBox="0 0 12 12" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
clip-rule="evenodd"
|
||||
d="M6 12C9.31371 12 12 9.31371 12 6C12 2.68629 9.31371 0 6 0C2.68629 0 0 2.68629 0 6C0 9.31371 2.68629 12 6 12Z"
|
||||
fill="#49454F"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
)
|
||||
);
|
||||
}
|
||||
const getIconSvg = (type: string): Result<undefined, React.JSX.Element> => {
|
||||
switch (type) {
|
||||
case "PlusCircle":
|
||||
return Result.ok(
|
||||
<svg width="33" height="33" viewBox="0 0 33 33" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M16.5003 1.32007C8.09487 1.32007 1.32031 8.09463 1.32031 16.5001C1.32031 24.9055 8.09487 31.6801 16.5003 31.6801C24.9058 31.6801 31.6803 24.9055 31.6803 16.5001C31.6803 8.09463 24.9058 1.32007 16.5003 1.32007ZM16.5003 2.64007C24.1989 2.64007 30.3603 8.80151 30.3603 16.5001C30.3603 24.1986 24.1989 30.3601 16.5003 30.3601C8.80176 30.3601 2.64031 24.1986 2.64031 16.5001C2.64031 8.80151 8.80176 2.64007 16.5003 2.64007ZM15.8403 8.58007V15.8401H8.58031V17.1601H15.8403V24.4201H17.1603V17.1601H24.4203V15.8401H17.1603V8.58007H15.8403Z"
|
||||
fill="black"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
case "Pencil":
|
||||
return Result.ok(
|
||||
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
clip-rule="evenodd"
|
||||
d="M16.06 0.589883L17.41 1.93988C18.2 2.71988 18.2 3.98988 17.41 4.76988L4.18 17.9999H0V13.8199L10.4 3.40988L13.23 0.589883C14.01 -0.190117 15.28 -0.190117 16.06 0.589883ZM2 15.9999L3.41 16.0599L13.23 6.22988L11.82 4.81988L2 14.6399V15.9999Z"
|
||||
fill="#31111D"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
case "MenuFab":
|
||||
return Result.ok(
|
||||
<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_54850_114)">
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
clip-rule="evenodd"
|
||||
d="M11 16V14L29 14V16L11 16ZM11 21H29V19H11V21ZM11 26H29V24H11V26Z"
|
||||
fill="#49454F"
|
||||
/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_54850_114">
|
||||
<rect width="40" height="40" rx="20" fill="white" />
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
);
|
||||
case "Settings":
|
||||
return Result.ok(
|
||||
<svg width="48" height="48" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_54841_7268)">
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
clip-rule="evenodd"
|
||||
d="M27.3102 33.03C27.2102 33.71 26.5902 34.25 25.8502 34.25H22.1502C21.4102 34.25 20.7902 33.71 20.7002 32.98L20.4302 31.09C20.1602 30.95 19.9002 30.8 19.6402 30.63L17.8402 31.35C17.1402 31.61 16.3702 31.32 16.0302 30.7L14.2002 27.53C13.8502 26.87 14.0002 26.09 14.5602 25.65L16.0902 24.46C16.0802 24.31 16.0702 24.16 16.0702 24C16.0702 23.85 16.0802 23.69 16.0902 23.54L14.5702 22.35C13.9802 21.9 13.8302 21.09 14.2002 20.47L16.0502 17.28C16.3902 16.66 17.1602 16.38 17.8402 16.65L19.6502 17.38C19.9102 17.21 20.1702 17.06 20.4302 16.92L20.7002 15.01C20.7902 14.31 21.4102 13.76 22.1402 13.76H25.8402C26.5802 13.76 27.2002 14.3 27.2902 15.03L27.5602 16.92C27.8302 17.06 28.0902 17.21 28.3502 17.38L30.1502 16.66C30.8602 16.4 31.6302 16.69 31.9702 17.31L33.8102 20.49C34.1702 21.15 34.0102 21.93 33.4502 22.37L31.9302 23.56C31.9402 23.71 31.9502 23.86 31.9502 24.02C31.9502 24.18 31.9402 24.33 31.9302 24.48L33.4502 25.67C34.0102 26.12 34.1702 26.9 33.8202 27.53L31.9602 30.75C31.6202 31.37 30.8502 31.65 30.1602 31.38L28.3602 30.66C28.1002 30.83 27.8402 30.98 27.5802 31.12L27.3102 33.03ZM22.6202 32.25H25.3802L25.7502 29.7L26.2802 29.48C26.7202 29.3 27.1602 29.04 27.6202 28.7L28.0702 28.36L30.4502 29.32L31.8302 26.92L29.8002 25.34L29.8702 24.78L29.8733 24.7531C29.9023 24.5027 29.9302 24.2607 29.9302 24C29.9302 23.73 29.9002 23.47 29.8702 23.22L29.8002 22.66L31.8302 21.08L30.4402 18.68L28.0502 19.64L27.6002 19.29C27.1802 18.97 26.7302 18.71 26.2702 18.52L25.7502 18.3L25.3802 15.75H22.6202L22.2502 18.3L21.7202 18.51C21.2802 18.7 20.8402 18.95 20.3802 19.3L19.9302 19.63L17.5502 18.68L16.1602 21.07L18.1902 22.65L18.1202 23.21C18.0902 23.47 18.0602 23.74 18.0602 24C18.0602 24.26 18.0802 24.53 18.1202 24.78L18.1902 25.34L16.1602 26.92L17.5402 29.32L19.9302 28.36L20.3802 28.71C20.8102 29.04 21.2402 29.29 21.7102 29.48L22.2402 29.7L22.6202 32.25ZM27.5002 24C27.5002 25.933 25.9332 27.5 24.0002 27.5C22.0672 27.5 20.5002 25.933 20.5002 24C20.5002 22.067 22.0672 20.5 24.0002 20.5C25.9332 20.5 27.5002 22.067 27.5002 24Z"
|
||||
fill="#49454F"
|
||||
/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_54841_7268">
|
||||
<rect x="4" y="4" width="40" height="40" rx="20" fill="white" />
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
return Result.error(undefined);
|
||||
};
|
126
ui/src/core/ui/pages/main_page.tsx
Normal file
126
ui/src/core/ui/pages/main_page.tsx
Normal file
|
@ -0,0 +1,126 @@
|
|||
import { DatasetsScreenPath } from "../../../features/dataset/dataset_screen";
|
||||
import { Icon } from "../icons/icons";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { Spin } from "antd";
|
||||
import { LoadingOutlined } from "@ant-design/icons";
|
||||
import React from "react";
|
||||
import { SceneManagerPath } from "../../../features/scene_manager/presentation/scene_manager";
|
||||
import { AssemblesScreenPath } from "../../../features/assembles/assembles_screen";
|
||||
import { DetailsScreenPath } from "../../../features/details/details_screen";
|
||||
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";
|
||||
export interface IBlockProps {
|
||||
name: string;
|
||||
isActive: boolean;
|
||||
path: string;
|
||||
}
|
||||
const Block = (props: IBlockProps) => {
|
||||
const navigate = useNavigate();
|
||||
|
||||
return (
|
||||
<div onClick={() => navigate(props.path)} style={{ height: 56, cursor: "pointer" }}>
|
||||
<div
|
||||
style={
|
||||
props.isActive
|
||||
? {
|
||||
textAlignLast: "center",
|
||||
height: 32,
|
||||
backgroundColor: "rgba(232, 222, 248, 1)",
|
||||
marginLeft: 5,
|
||||
marginRight: 5,
|
||||
alignContent: "center",
|
||||
borderRadius: 12,
|
||||
}
|
||||
: { textAlignLast: "center", alignContent: "center" }
|
||||
}
|
||||
>
|
||||
<Icon type={props.name} />
|
||||
</div>
|
||||
<div style={{ textAlignLast: "center" }}>{props.name}</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
export interface IMainPageProps {
|
||||
page: string;
|
||||
bodyChildren?: JSX.Element;
|
||||
isLoading?: boolean;
|
||||
}
|
||||
export const MainPage = (props: IMainPageProps) => {
|
||||
const blocksNames = [
|
||||
{ name: "Детали", path: DetailsScreenPath },
|
||||
{ name: "Сборки", path: AssemblesScreenPath },
|
||||
{ name: "Датасеты", path: DatasetsScreenPath },
|
||||
{ name: "Сцена", path: SceneManagerPath },
|
||||
{ name: "Навыки", path: BehaviorTreeBuilderPath },
|
||||
{ name: "Симуляция", path: SimulationScreenPath },
|
||||
{ name: "Оценка", path: EstimateScreenPath },
|
||||
];
|
||||
const blocks: IBlockProps[] = blocksNames
|
||||
.map((el) => {
|
||||
return { name: el.name, isActive: false, path: el.path };
|
||||
})
|
||||
.map((el) => {
|
||||
if (el.name.isEqual(props.page)) {
|
||||
el.isActive = true;
|
||||
return el;
|
||||
}
|
||||
return el;
|
||||
});
|
||||
React.useEffect(() => {
|
||||
document.body.style.overflow = "hidden";
|
||||
return () => {
|
||||
document.body.style.overflow = "scroll";
|
||||
};
|
||||
});
|
||||
return (
|
||||
<div style={{ display: "flex" }}>
|
||||
<div
|
||||
style={{
|
||||
width: 90,
|
||||
height: window.innerHeight,
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
justifyContent: "space-between",
|
||||
alignItems: "center",
|
||||
}}
|
||||
>
|
||||
<div style={{ paddingTop: 43 }}>
|
||||
<div style={{ textAlignLast: "center" }}>
|
||||
<Icon type="MenuFab" />
|
||||
</div>
|
||||
<div
|
||||
style={{
|
||||
textAlignLast: "center",
|
||||
width: 56,
|
||||
height: 56,
|
||||
borderRadius: 12,
|
||||
backgroundColor: "#ffd9e4",
|
||||
alignContent: "center",
|
||||
}}
|
||||
>
|
||||
<Icon style={{ marginTop: 3 }} type="Pencil" />
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
{blocks.map((el) => (
|
||||
<Block isActive={el.isActive} name={el.name} path={el.path} />
|
||||
))}
|
||||
</div>
|
||||
<div style={{ paddingBottom: 10 }}>
|
||||
<Icon type={"Settings"} />
|
||||
</div>
|
||||
</div>
|
||||
{props.isLoading ? (
|
||||
<div style={{ alignContent: "center", width: "100%", textAlign: "center" }}>
|
||||
<Spin indicator={<LoadingOutlined style={{ fontSize: 68, color: "rgba(103, 80, 164, 1)" }} spin />} />
|
||||
</div>
|
||||
) : (
|
||||
<>
|
||||
<div style={{ width: 241, height: window.innerHeight, backgroundColor: "#F7F2FA", borderRadius: 16 }}> </div>
|
||||
{props.bodyChildren}
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
|
@ -2,14 +2,63 @@ import * as React from "react";
|
|||
|
||||
export enum CoreTextType {
|
||||
header,
|
||||
medium,
|
||||
large,
|
||||
}
|
||||
|
||||
export interface ITextProps {
|
||||
text: string;
|
||||
type: CoreTextType;
|
||||
color?: string;
|
||||
}
|
||||
|
||||
export function CoreText(props: ITextProps) {
|
||||
if (props.type === CoreTextType.header) return <div style={{ color: "white", fontSize: "20px" }}>{props.text}</div>;
|
||||
if (props.type === CoreTextType.large) {
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
color: props.color ?? "#1D1B20",
|
||||
fontSize: 16,
|
||||
fontFamily: "Roboto",
|
||||
fontWeight: 400,
|
||||
fontSizeAdjust: 14,
|
||||
textOverflow: "ellipsis",
|
||||
}}
|
||||
>
|
||||
{props.text}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
if (props.type === CoreTextType.medium)
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
color: props.color ?? "#1D1B20",
|
||||
fontSize: 14,
|
||||
fontFamily: "Roboto",
|
||||
fontWeight: 400,
|
||||
textOverflow: "ellipsis",
|
||||
fontSizeAdjust: 14,
|
||||
}}
|
||||
>
|
||||
{props.text}
|
||||
</div>
|
||||
);
|
||||
if (props.type === CoreTextType.header)
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
color: props.color ?? "#1D1B20",
|
||||
fontSize: 20,
|
||||
fontFamily: "Roboto",
|
||||
fontWeight: 500,
|
||||
textOverflow: "ellipsis",
|
||||
|
||||
fontSizeAdjust: 16,
|
||||
}}
|
||||
>
|
||||
{props.text}
|
||||
</div>
|
||||
);
|
||||
return <div>{props.text}</div>;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import { ActivePipeline } from "../../../core/model/active_pipeline";
|
||||
import { HttpMethod, HttpRepository } from "../../../core/repository/http_repository";
|
||||
import { IProjectModel } from "../model/project_model";
|
||||
|
||||
|
|
8
ui/src/features/assembles/assembles_screen.tsx
Normal file
8
ui/src/features/assembles/assembles_screen.tsx
Normal file
|
@ -0,0 +1,8 @@
|
|||
import * as React from "react";
|
||||
import { MainPage } from "../../core/ui/pages/main_page";
|
||||
|
||||
export interface IAssemblesScreenProps {}
|
||||
export const AssemblesScreenPath = "/assembles";
|
||||
export function AssemblesScreen(props: IAssemblesScreenProps) {
|
||||
return <MainPage page={"Сборки"}></MainPage>;
|
||||
}
|
|
@ -6,6 +6,7 @@ import { useRete } from "rete-react-plugin";
|
|||
import { createEditor } from "./ui/editor/editor";
|
||||
import { SkillTree } from "./ui/skill_tree/skill_tree";
|
||||
import { BehaviorTreeBuilderStore } from "./behavior_tree_builder_store";
|
||||
import { MainPage } from "../../../core/ui/pages/main_page";
|
||||
|
||||
export const behaviorTreeBuilderScreenPath = "behavior/tree/screen/path";
|
||||
|
||||
|
@ -53,56 +54,24 @@ export function BehaviorTreeBuilderScreen() {
|
|||
}, [store, ref]);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div
|
||||
style={{
|
||||
width: "100vw",
|
||||
height: "86px",
|
||||
background: "#041226",
|
||||
}}
|
||||
>
|
||||
<CoreText text="Robossembler studio" type={CoreTextType.header} />
|
||||
</div>
|
||||
<div style={{ display: "flex" }}>
|
||||
<div
|
||||
style={{
|
||||
width: "30vw",
|
||||
height: "70px",
|
||||
background: "#1B2E42",
|
||||
}}
|
||||
></div>
|
||||
<div
|
||||
style={{
|
||||
width: "1782px",
|
||||
height: "70px",
|
||||
background: "rgb(27 45 66)",
|
||||
}}
|
||||
>
|
||||
<Button onClick={() => store.saveBt()}>SAVE</Button>
|
||||
</div>
|
||||
</div>
|
||||
<div style={{ display: "flex" }}>
|
||||
<div
|
||||
style={{
|
||||
width: "30vw",
|
||||
background: "#1B3041",
|
||||
boxShadow: "inset 0px 10px 4px #16283D",
|
||||
}}
|
||||
>
|
||||
<div style={{ overflow: "auto", height: "100%", width: "100%", padding: "10px" }}>
|
||||
<SkillTree dragEnd={store.dragEnd} skills={skills} />
|
||||
</div>
|
||||
</div>
|
||||
<MainPage
|
||||
page={"Навыки"}
|
||||
bodyChildren={
|
||||
<>
|
||||
<div style={{ display: "flex", width: "100%" }}>
|
||||
{/* <SkillTree dragEnd={store.dragEnd} skills={skills} /> */}
|
||||
|
||||
<div
|
||||
ref={ref}
|
||||
style={{
|
||||
width: "1782px",
|
||||
height: String(window.innerHeight - 86 - 70) + "px",
|
||||
background: "#244366",
|
||||
width: "100%",
|
||||
height: window.innerHeight,
|
||||
background: "white",
|
||||
}}
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -16,10 +16,10 @@ interface IRefListerProps {
|
|||
}
|
||||
|
||||
export const RefListener = (props: IRefListerProps) => {
|
||||
const canvasRef = React.useRef<HTMLDataElement>(null);
|
||||
const ref = React.useRef<HTMLDataElement>(null);
|
||||
React.useEffect(() => {
|
||||
if (canvasRef.current) {
|
||||
canvasRef.current.addEventListener("dragend", (e) => {
|
||||
if (ref.current) {
|
||||
ref.current.addEventListener("dragend", (e) => {
|
||||
// @ts-expect-error
|
||||
if (e.target.innerHTML) {
|
||||
// @ts-expect-error
|
||||
|
@ -27,7 +27,7 @@ export const RefListener = (props: IRefListerProps) => {
|
|||
}
|
||||
});
|
||||
}
|
||||
}, [canvasRef, props]);
|
||||
}, [ref, props]);
|
||||
|
||||
return (
|
||||
<div {...props.getNodeProps({ onClick: props.handleExpand })}>
|
||||
|
@ -36,7 +36,7 @@ export const RefListener = (props: IRefListerProps) => {
|
|||
props.handleSelect(e);
|
||||
}}
|
||||
/>
|
||||
<span ref={canvasRef} style={{ color: "white" }} draggable="true">
|
||||
<span ref={ref} style={{ color: "white" }} draggable="true">
|
||||
{props.element.name}
|
||||
</span>
|
||||
</div>
|
||||
|
|
|
@ -1,75 +0,0 @@
|
|||
export const datasetTypes = ["Object Detection - YOLOv8", "Pose Estimation - DOPE"];
|
||||
|
||||
export const datasetFormMockResult = `{
|
||||
"typedataset": \${typedataset:Enum<T>:"ObjectDetection"},
|
||||
"dataset_path": \${ПУТЬ ДАТАСЕТА:string:""},
|
||||
"models":\${models:Array<MODELS>:[]},
|
||||
"models_randomization":{
|
||||
"loc_range_low": [\${LOC_RANGE_LOW_1:number:-1}, \${LOC_RANGE_LOW_2:number:-1},/\${LOC_RANGE_LOW_3:number:0}],
|
||||
"loc_range_high": [\${LOC_RANGE_HIGH_1:number:1}, \${LOC_RANGE_HIGH_2:number:1},/\${LOC_RANGE_HIGH_3:number:2}]
|
||||
},
|
||||
"scene":{
|
||||
"objects": \${OBJECTS_SCENE:Array<OBJECTS_SCENE>:[]},
|
||||
"lights": \${LIGHTS:Array<LIGHTS>:[]},
|
||||
},
|
||||
"camera_position":{
|
||||
"center_shell": [\${CENTER_SHELL_1:number:0}, \${CENTER_SHELL_2:number:0}, \${CENTER_SHELL_3:number:0}],
|
||||
"radius_range": [\${RADIUS_RANGE_1:number:0.4}, \${RADIUS_RANGE_2:number:1.4}],
|
||||
"elevation_range": [\${ELEVATION_RANGE_1:number:10}, \${ELEVATION_RANGE_2:number:90}]
|
||||
},
|
||||
"generation":{
|
||||
"n_cam_pose": \${N_CAM_POSE:number:5},
|
||||
"n_sample_on_pose": \${N_SAMPLE_ON_POSE:number:3},
|
||||
"n_series": \${N_SERIES:number:100},
|
||||
"image_format": \${image_format:Enum<F>:"jpg"},
|
||||
"image_size_wh": [\${IMAGE_SIZE_WH_1:number:640}, \${IMAGE_SIZE_WH_2:number:480}]
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
export const datasetFormMockContext = `
|
||||
ENUM T = "ObjectDetection","PoseEstimation";
|
||||
ENUM L = "POINT","SUN";
|
||||
ENUM F = "JPEG","PNG";
|
||||
ENUM COLLISION_SHAPE = "SHAPE","COLLISION";
|
||||
|
||||
type MODELS = {
|
||||
"id": \${ID:number:1},
|
||||
"name": \${NAME:string:""},
|
||||
"model": \${MODEL:string:"models/1.fbx"}
|
||||
};
|
||||
type OBJECTS_SCENE = {
|
||||
"name": \${NAME:string:""},
|
||||
"collision_shape": \${collision_shape:Enum<COLLISION_SHAPE>:"BOX"},
|
||||
"loc_xyz": [\${LOC_XYZ_1:number:0}, \${LOC_XYZ_2:number:0}, \${LOC_XYZ_3:number:0}],
|
||||
"rot_euler": [\${ROT_EULER_1:number:0},\${ROT_EULER_2:number:0}, \${ROT_EULER_3:number:0}],
|
||||
"material_randomization": {
|
||||
"specular": [\${SPECULAR_1:number:0}, \${SPECULAR_2:number:1}],
|
||||
"roughness": [\${ROUGHNESS_1:number:0}, \${ROUGHNESS_2:number:1}],
|
||||
"metallic": [\${METALLIC_1:number:0}, \${METALLIC_2:number:1}],
|
||||
"base_color": [
|
||||
[
|
||||
\${BASE_COLOR_1:number:0},
|
||||
\${BASE_COLOR_2:number:0},
|
||||
\${BASE_COLOR_3:number:0},
|
||||
\${BASE_COLOR_4:number:1}
|
||||
],
|
||||
[
|
||||
\${BASE_COLOR_5:number:1},
|
||||
\${BASE_COLOR_6:number:1},
|
||||
\${BASE_COLOR_7:number:1},
|
||||
\${BASE_COLOR_8:number:1}
|
||||
]
|
||||
]
|
||||
}
|
||||
};
|
||||
type LIGHTS = {
|
||||
"id": \${ID:number:1},
|
||||
"type": \${type:Enum<L>:"POINT"},
|
||||
"loc_xyz": [\${LOC_XYZ_1:number:5}, \${LOC_XYZ_2:number:5}, \${LOC_XYZ_3:number:5}],
|
||||
"rot_euler": [\${ROT_EULER_1:number:-0.06}, \${ROT_EULER_2:number:0.61}, \${ROT_EULER_3:number:-0.19}],
|
||||
"color_range_low": [\${COLOR_RANGE_LOW_1:number:0.5}, \${COLOR_RANGE_LOW_2:number:0.5}, \${COLOR_RANGE_LOW_3:number:0.5}],
|
||||
"color_range_high":[\${COLOR_RANGE_HIGH_1:number:1}, \${COLOR_RANGE_HIGH_2:number:1}, $\{COLOR_RANGE_HIGH_3:number:1}],
|
||||
"energy_range":[\${ENERGY_RANGE_1:number:400},\${ENERGY_RANGE_2:number:900}]
|
||||
};
|
||||
`;
|
|
@ -1,4 +1,20 @@
|
|||
import { InputBuilderViewModel } from "../../core/ui/form_builder/form_view_model";
|
||||
import { Result } from "../../core/helper/result";
|
||||
import makeAutoObservable from "mobx-store-inheritance";
|
||||
|
||||
export interface IDatasetModel {
|
||||
_id: string;
|
||||
dataSetObjects: string[];
|
||||
processStatus: string;
|
||||
projectId: string;
|
||||
name: string;
|
||||
formBuilder: FormBuilder;
|
||||
unixTime: number;
|
||||
datasetType: string;
|
||||
local_path: string;
|
||||
__v: number;
|
||||
processLogs: string;
|
||||
}
|
||||
|
||||
export interface Dataset {
|
||||
name: string;
|
||||
|
@ -23,3 +39,128 @@ export interface Asset {
|
|||
mesh: string;
|
||||
image: string;
|
||||
}
|
||||
export class FormBuilderValidationModel {
|
||||
public result: string;
|
||||
public context: string;
|
||||
public form: string[];
|
||||
public output: string;
|
||||
constructor(context: string, result: string, form: string[], output: string) {
|
||||
this.context = context;
|
||||
this.result = result;
|
||||
this.form = form;
|
||||
this.output = output;
|
||||
}
|
||||
static empty() {
|
||||
return new FormBuilderValidationModel(datasetFormMockContext, datasetFormMockResult, [], "");
|
||||
}
|
||||
}
|
||||
|
||||
export class DataSetModel {
|
||||
dataSetObjects: string[];
|
||||
datasetType: string;
|
||||
name: string;
|
||||
formBuilder: FormBuilderValidationModel = FormBuilderValidationModel.empty();
|
||||
project?: string;
|
||||
constructor(dataSetObjects: string[], datasetType = datasetTypes[0], datasetName: string) {
|
||||
this.dataSetObjects = dataSetObjects;
|
||||
this.datasetType = datasetType;
|
||||
this.name = datasetName;
|
||||
makeAutoObservable(this);
|
||||
}
|
||||
|
||||
static empty() {
|
||||
return new DataSetModel([], "", "");
|
||||
}
|
||||
|
||||
isValid(): Result<string, void> {
|
||||
if (this.project === undefined) {
|
||||
return Result.error("project is unknow");
|
||||
}
|
||||
if (this.dataSetObjects.isEmpty()) {
|
||||
return Result.error("not selected details");
|
||||
}
|
||||
if (this.datasetType.isEmpty()) {
|
||||
return Result.error("dataset type is empty");
|
||||
}
|
||||
if (this.name.isEmpty()) {
|
||||
return Result.error("dataset name is empty");
|
||||
}
|
||||
return Result.ok();
|
||||
}
|
||||
}
|
||||
|
||||
export const datasetTypes = ["Object Detection - YOLOv8", "Pose Estimation - DOPE"];
|
||||
|
||||
export const datasetFormMockResult = `{
|
||||
"typedataset": \${typedataset:Enum<T>:ObjectDetection},
|
||||
"dataset_path": \${ПУТЬ ДАТАСЕТА:string:none},
|
||||
"models":\${models:Array<MODELS>:[]},
|
||||
"models_randomization":{
|
||||
"loc_range_low": [\${LOC_RANGE_LOW_1:number:-1}, \${LOC_RANGE_LOW_2:number:-1},/\${LOC_RANGE_LOW_3:number:0}],
|
||||
"loc_range_high": [\${LOC_RANGE_HIGH_1:number:1}, \${LOC_RANGE_HIGH_2:number:1},/\${LOC_RANGE_HIGH_3:number:2}]
|
||||
},
|
||||
"scene":{
|
||||
"objects": \${OBJECTS_SCENE:Array<OBJECTS_SCENE>:[]},
|
||||
"lights": \${LIGHTS:Array<LIGHTS>:[]}
|
||||
},
|
||||
"camera_position":{
|
||||
"center_shell": [\${CENTER_SHELL_1:number:0}, \${CENTER_SHELL_2:number:0}, \${CENTER_SHELL_3:number:0}],
|
||||
"radius_range": [\${RADIUS_RANGE_1:number:0.4}, \${RADIUS_RANGE_2:number:1.4}],
|
||||
"elevation_range": [\${ELEVATION_RANGE_1:number:10}, \${ELEVATION_RANGE_2:number:90}]
|
||||
},
|
||||
"generation":{
|
||||
"n_cam_pose": \${N_CAM_POSE:number:5},
|
||||
"n_sample_on_pose": \${N_SAMPLE_ON_POSE:number:3},
|
||||
"n_series": \${N_SERIES:number:100},
|
||||
"image_format": \${image_format:Enum<F>:jpg},
|
||||
"image_size_wh": [\${IMAGE_SIZE_WH_1:number:640}, \${IMAGE_SIZE_WH_2:number:480}]
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
export const datasetFormMockContext = `
|
||||
ENUM T = "ObjectDetection","PoseEstimation";
|
||||
ENUM L = "POINT","SUN";
|
||||
ENUM F = "JPEG","PNG";
|
||||
ENUM COLLISION_SHAPE = "SHAPE","COLLISION";
|
||||
|
||||
type MODELS = {
|
||||
"id": \${ID:number:1},
|
||||
"name": \${NAME:string:none},
|
||||
"model": \${MODEL:string:models/1.fbx}
|
||||
};
|
||||
type OBJECTS_SCENE = {
|
||||
"name": \${NAME:string:default},
|
||||
"collision_shape": \${collision_shape:Enum<COLLISION_SHAPE>:BOX},
|
||||
"loc_xyz": [\${LOC_XYZ_1:number:0}, \${LOC_XYZ_2:number:0}, \${LOC_XYZ_3:number:0}],
|
||||
"rot_euler": [\${ROT_EULER_1:number:0},\${ROT_EULER_2:number:0}, \${ROT_EULER_3:number:0}],
|
||||
"material_randomization": {
|
||||
"specular": [\${SPECULAR_1:number:0}, \${SPECULAR_2:number:1}],
|
||||
"roughness": [\${ROUGHNESS_1:number:0}, \${ROUGHNESS_2:number:1}],
|
||||
"metallic": [\${METALLIC_1:number:0}, \${METALLIC_2:number:1}],
|
||||
"base_color": [
|
||||
[
|
||||
\${BASE_COLOR_1:number:0},
|
||||
\${BASE_COLOR_2:number:0},
|
||||
\${BASE_COLOR_3:number:0},
|
||||
\${BASE_COLOR_4:number:1}
|
||||
],
|
||||
[
|
||||
\${BASE_COLOR_5:number:1},
|
||||
\${BASE_COLOR_6:number:1},
|
||||
\${BASE_COLOR_7:number:1},
|
||||
\${BASE_COLOR_8:number:1}
|
||||
]
|
||||
]
|
||||
}
|
||||
};
|
||||
type LIGHTS = {
|
||||
"id": \${ID:number:1},
|
||||
"type": \${type:Enum<L>:"POINT"},
|
||||
"loc_xyz": [\${LOC_XYZ_1:number:5}, \${LOC_XYZ_2:number:5}, \${LOC_XYZ_3:number:5}],
|
||||
"rot_euler": [\${ROT_EULER_1:number:-0.06}, \${ROT_EULER_2:number:0.61}, \${ROT_EULER_3:number:-0.19}],
|
||||
"color_range_low": [\${COLOR_RANGE_LOW_1:number:0.5}, \${COLOR_RANGE_LOW_2:number:0.5}, \${COLOR_RANGE_LOW_3:number:0.5}],
|
||||
"color_range_high":[\${COLOR_RANGE_HIGH_1:number:1}, \${COLOR_RANGE_HIGH_2:number:1}, $\{COLOR_RANGE_HIGH_3:number:1}],
|
||||
"energy_range":[\${ENERGY_RANGE_1:number:400},\${ENERGY_RANGE_2:number:900}]
|
||||
};
|
||||
`;
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
import { Result } from "../../core/helper/result";
|
||||
import { HttpError, HttpMethod, HttpRepository } from "../../core/repository/http_repository";
|
||||
import { Assets, Dataset } from "./dataset_model";
|
||||
import { DataSetModel, IDatasetModel } from "./dataset_store";
|
||||
import { UUID } from "../all_projects/data/project_repository";
|
||||
import { Assets, DataSetModel, Dataset, IDatasetModel } from "./dataset_model";
|
||||
|
||||
export class DataSetRepository extends HttpRepository {
|
||||
getActiveProjectId(): Promise<Result<HttpError, UUID>> {
|
||||
return this._jsonRequest<UUID>(HttpMethod.GET, "/projects/get/active/project/id");
|
||||
}
|
||||
getAssetsActiveProject = async (): Promise<Result<HttpError, Assets>> => {
|
||||
return this._jsonRequest<Assets>(HttpMethod.GET, "/projects/assets");
|
||||
};
|
||||
|
@ -13,4 +16,13 @@ export class DataSetRepository extends HttpRepository {
|
|||
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");
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
import * as React from "react";
|
||||
import { Drawer, Button, Radio, Card, Checkbox, Input } from "antd";
|
||||
import { FormBuilder } from "../../core/ui/form_builder/form_builder";
|
||||
import { datasetFormMockContext, datasetFormMockResult, datasetTypes } from "./dataset_form_mock";
|
||||
import { DataSetStore } from "./dataset_store";
|
||||
import { observer } from "mobx-react-lite";
|
||||
import { datasetTypes } from "./dataset_model";
|
||||
import { MainPage } from "../../core/ui/pages/main_page";
|
||||
import { CardDataSet, CardDataSetType } from "../../core/ui/card/card_dataset";
|
||||
|
||||
export const DatasetsScreenPath = "/dataset";
|
||||
|
||||
|
@ -18,31 +20,52 @@ export const DataSetScreen: React.FunctionComponent = observer(() => {
|
|||
const [open1, setOpen1] = React.useState(false);
|
||||
return (
|
||||
<>
|
||||
<Button onClick={() => setOpen(true)}>new dataset</Button>
|
||||
{store.datasets?.isEmpty() ? (
|
||||
<div>empty dataset</div>
|
||||
) : (
|
||||
<div>
|
||||
<h1>Datasets</h1>
|
||||
<div>
|
||||
{store.datasets?.map((el, index) => {
|
||||
<MainPage
|
||||
isLoading={false}
|
||||
page="Датасеты"
|
||||
bodyChildren={
|
||||
<div
|
||||
style={{
|
||||
display: "grid",
|
||||
gridTemplateColumns: "repeat(auto-fill, minmax(272px, 1fr))",
|
||||
gridGap: 10,
|
||||
width: "100%",
|
||||
margin: 12,
|
||||
overflow: "auto",
|
||||
height: window.innerHeight,
|
||||
}}
|
||||
>
|
||||
{store.datasets?.map((el) => {
|
||||
console.log(el);
|
||||
return (
|
||||
<Card title={el.name}>
|
||||
<h2>dataset objects:</h2>
|
||||
<div>
|
||||
{el.dataSetObjects.map((el) => (
|
||||
<div>{el}</div>
|
||||
))}
|
||||
</div>
|
||||
<h2>process status</h2>
|
||||
<div>{el.processStatus}</div>
|
||||
<Button>Edit process</Button>
|
||||
</Card>
|
||||
<CardDataSet
|
||||
type={CardDataSetType.COMPLETED}
|
||||
objects={el.dataSetObjects}
|
||||
unixDate={el.unixTime}
|
||||
processStatus={el.processStatus}
|
||||
neuralNetworkAction={el.datasetType.split(" - ").at(0)}
|
||||
neuralNetworkName={el.datasetType.split(" - ").at(1)}
|
||||
id={el._id}
|
||||
onClickButton={(id) => store.runProcess(id)}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
<CardDataSet
|
||||
type={CardDataSetType.EMPTY}
|
||||
onClickEmptyCard={() => {
|
||||
setOpen(true);
|
||||
}}
|
||||
/>
|
||||
|
||||
<Drawer title="Form builder Drawer" onClose={() => setOpen1(false)} open={open1}>
|
||||
<FormBuilder
|
||||
context={store.dataSetModel.formBuilder.context}
|
||||
result={store.dataSetModel.formBuilder.result}
|
||||
onChange={(el) => {
|
||||
if (el) store.dataSetModel.formBuilder = el;
|
||||
}}
|
||||
/>
|
||||
</Drawer>
|
||||
<Drawer title="New Dataset" onClose={() => setOpen(false)} open={open}>
|
||||
<Input placeholder="Dataset name" onChange={(e) => (store.dataSetModel.name = e.target.value)} />
|
||||
<Button onClick={() => setOpen1(true)}>edit dataset settings</Button>
|
||||
|
@ -79,16 +102,37 @@ export const DataSetScreen: React.FunctionComponent = observer(() => {
|
|||
);
|
||||
})}
|
||||
</Drawer>
|
||||
|
||||
<Drawer title="Form builder Drawer" onClose={() => setOpen1(false)} open={open1}>
|
||||
<FormBuilder
|
||||
context={store.dataSetModel.formBuilder.context}
|
||||
result={store.dataSetModel.formBuilder.result}
|
||||
onChange={(el) => {
|
||||
if (el) store.dataSetModel.formBuilder = el;
|
||||
}}
|
||||
</div>
|
||||
}
|
||||
/>
|
||||
</Drawer>
|
||||
</>
|
||||
);
|
||||
});
|
||||
{
|
||||
/* <Button onClick={() => setOpen(true)}>new dataset</Button>
|
||||
{store.datasets?.isEmpty() ? (
|
||||
<div>empty dataset</div>
|
||||
) : (
|
||||
<div>
|
||||
<h1>Datasets</h1>
|
||||
<div>
|
||||
{store.datasets?.map((el, index) => {
|
||||
return (
|
||||
<Card title={el.name}>
|
||||
<h2>dataset objects:</h2>
|
||||
<div>
|
||||
{el.dataSetObjects.map((el) => (
|
||||
<div>{el}</div>
|
||||
))}
|
||||
</div>
|
||||
<h2>process status</h2>
|
||||
<div>{el.processStatus}</div>
|
||||
<Button>Edit process</Button>
|
||||
</Card>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</> */
|
||||
}
|
||||
|
|
|
@ -2,75 +2,46 @@ import makeAutoObservable from "mobx-store-inheritance";
|
|||
import { DataSetRepository } from "./dataset_repository";
|
||||
import { UiErrorState } from "../../core/store/base_store";
|
||||
import { HttpError } from "../../core/repository/http_repository";
|
||||
import { Assets } from "./dataset_model";
|
||||
import { datasetFormMockContext, datasetFormMockResult, datasetTypes } from "./dataset_form_mock";
|
||||
import { Result } from "../../core/helper/result";
|
||||
import { Assets, DataSetModel, IDatasetModel } from "./dataset_model";
|
||||
import { message } from "antd";
|
||||
|
||||
export class FormBuilderValidationModel {
|
||||
public result: string;
|
||||
public context: string;
|
||||
public form: string[];
|
||||
public output: string;
|
||||
constructor(context: string, result: string, form: string[], output: string) {
|
||||
this.context = context;
|
||||
this.result = result;
|
||||
this.form = form;
|
||||
this.output = output;
|
||||
}
|
||||
static empty() {
|
||||
return new FormBuilderValidationModel(datasetFormMockContext, datasetFormMockResult, [], "");
|
||||
}
|
||||
}
|
||||
|
||||
export class DataSetModel {
|
||||
dataSetObjects: string[];
|
||||
datasetType: string;
|
||||
name: string;
|
||||
formBuilder: FormBuilderValidationModel = FormBuilderValidationModel.empty();
|
||||
|
||||
constructor(dataSetObjects: string[], datasetType = datasetTypes[0], datasetName: string) {
|
||||
this.dataSetObjects = dataSetObjects;
|
||||
this.datasetType = datasetType;
|
||||
this.name = datasetName;
|
||||
makeAutoObservable(this);
|
||||
}
|
||||
|
||||
static empty() {
|
||||
return new DataSetModel([], "", "");
|
||||
}
|
||||
|
||||
isValid(): Result<string, void> {
|
||||
if (this.dataSetObjects.isEmpty()) {
|
||||
return Result.error("not selected details");
|
||||
}
|
||||
if (this.datasetType.isEmpty()) {
|
||||
return Result.error("dataset type is empty");
|
||||
}
|
||||
if (this.name.isEmpty()) {
|
||||
return Result.error("dataset name is empty");
|
||||
}
|
||||
return Result.ok();
|
||||
}
|
||||
}
|
||||
import { UUID } from "../all_projects/data/project_repository";
|
||||
|
||||
export class DataSetStore extends UiErrorState<HttpError> {
|
||||
dataSetRepository: DataSetRepository;
|
||||
assets?: Assets;
|
||||
datasets?: IDatasetModel[];
|
||||
activeProject: UUID;
|
||||
dataSetModel = DataSetModel.empty();
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.dataSetRepository = new DataSetRepository();
|
||||
makeAutoObservable(this);
|
||||
}
|
||||
errorHandingStrategy = (error: HttpError) => {};
|
||||
runProcess = async (id: string): Promise<void> => {
|
||||
(await this.dataSetRepository.isRunningProcess()).fold(
|
||||
async (s) => {
|
||||
(await this.dataSetRepository.execDatasetProcess(id)).fold(
|
||||
() => {
|
||||
message.success("процесс запущен");
|
||||
},
|
||||
(e) => message.error(e.message)
|
||||
);
|
||||
},
|
||||
async (e) => message.error(e.message)
|
||||
);
|
||||
};
|
||||
errorHandingStrategy = (error: HttpError) => {
|
||||
message.error(error.message);
|
||||
};
|
||||
|
||||
saveDataset(): void {
|
||||
this.dataSetModel.project = this.activeProject.id;
|
||||
this.dataSetModel.isValid().fold(
|
||||
async () => {
|
||||
(await this.dataSetRepository.saveDataSet(this.dataSetModel)).fold(
|
||||
() => {
|
||||
message.success("save dataset");
|
||||
message.success("датасет сохранен");
|
||||
},
|
||||
(error) => message.error(error.message)
|
||||
);
|
||||
|
@ -78,25 +49,10 @@ export class DataSetStore extends UiErrorState<HttpError> {
|
|||
async (error) => message.error(error)
|
||||
);
|
||||
}
|
||||
|
||||
init = async () => {
|
||||
await this.mapOk("assets", this.dataSetRepository.getAssetsActiveProject());
|
||||
await this.mapOk("datasets", this.dataSetRepository.getDatasetsActiveProject());
|
||||
await this.mapOk("activeProject", this.dataSetRepository.getActiveProjectId());
|
||||
};
|
||||
}
|
||||
export interface IDatasetModel {
|
||||
_id: string;
|
||||
dataSetObjects: string[];
|
||||
processStatus: string;
|
||||
projectId: string;
|
||||
name: string;
|
||||
formBuilder: FormBuilder;
|
||||
local_path: string;
|
||||
__v: number;
|
||||
processLogs: string;
|
||||
}
|
||||
|
||||
export interface FormBuilder {
|
||||
result: string;
|
||||
context: string;
|
||||
form: any[];
|
||||
}
|
||||
|
|
8
ui/src/features/details/details_screen.tsx
Normal file
8
ui/src/features/details/details_screen.tsx
Normal file
|
@ -0,0 +1,8 @@
|
|||
import * as React from "react";
|
||||
import { MainPage } from "../../core/ui/pages/main_page";
|
||||
|
||||
export interface IDetailsScreenProps {}
|
||||
export const DetailsScreenPath = "/detail";
|
||||
export default function DetailsScreen(props: IDetailsScreenProps) {
|
||||
return <MainPage page={"Детали"}></MainPage>;
|
||||
}
|
8
ui/src/features/estimate/estimate_screen.tsx
Normal file
8
ui/src/features/estimate/estimate_screen.tsx
Normal file
|
@ -0,0 +1,8 @@
|
|||
import * as React from "react";
|
||||
import { MainPage } from "../../core/ui/pages/main_page";
|
||||
|
||||
export interface IEstimateScreenProps {}
|
||||
export const EstimateScreenPath = "/estimate";
|
||||
export function EstimateScreen(props: IEstimateScreenProps) {
|
||||
return <MainPage page={"Оценка"}></MainPage>;
|
||||
}
|
|
@ -1,32 +1,27 @@
|
|||
import * as React from "react";
|
||||
import { LoadPage } from "../../core/ui/pages/load_page";
|
||||
import { PipelineInstanceStore } from "./pipeline_instance_store";
|
||||
import { Button } from "antd";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { BehaviorTreeBuilderPath } from "../behavior_tree_builder/presentation/behavior_tree_builder_screen";
|
||||
import { SceneManagerPath } from "../scene_manager/presentation/scene_manager";
|
||||
import { StickObjectsMarkingScreenPath } from "../stick_objects_marking/stick_objects_marking_screen";
|
||||
import { DatasetsScreenPath } from "../dataset/dataset_screen";
|
||||
import { Icon } from "../../core/ui/icons/icons";
|
||||
import { CardDataSet, CardDataSetType } from "../../core/ui/card/card_dataset";
|
||||
import { MainPage } from "../../core/ui/pages/main_page";
|
||||
|
||||
export const PipelineInstanceScreenPath = "/pipeline_instance/";
|
||||
|
||||
export const PipelineInstanceScreen: React.FunctionComponent = () => {
|
||||
const [pipelineInstanceStore] = React.useState(() => new PipelineInstanceStore());
|
||||
React.useEffect(() => {}, [pipelineInstanceStore]);
|
||||
const [store] = React.useState(() => {
|
||||
new PipelineInstanceStore();
|
||||
});
|
||||
React.useEffect(() => {
|
||||
document.body.style.overflow = "hidden";
|
||||
return () => {
|
||||
document.body.style.overflow = "scroll";
|
||||
};
|
||||
}, [store]);
|
||||
const navigate = useNavigate();
|
||||
|
||||
return (
|
||||
<LoadPage
|
||||
needBackButton={true}
|
||||
largeText={"Project instance active"}
|
||||
isError={pipelineInstanceStore.isError}
|
||||
isLoading={pipelineInstanceStore.isLoading}
|
||||
children={
|
||||
<div>
|
||||
<Button onClick={() => navigate(BehaviorTreeBuilderPath)}>Behavior tree</Button>
|
||||
<Button onClick={() => navigate(SceneManagerPath)}>Scene Builder</Button>
|
||||
<Button onClick={() => navigate(StickObjectsMarkingScreenPath)}>Sticky marking</Button>
|
||||
<Button onClick={() => navigate(DatasetsScreenPath)}>Datasets</Button>
|
||||
</div>
|
||||
}
|
||||
/>
|
||||
<>
|
||||
<MainPage page="Датасеты" />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -57,7 +57,6 @@ export const SceneWidget = () => {
|
|||
<h1
|
||||
onClick={(event) => {
|
||||
event.stopPropagation();
|
||||
console.log(201);
|
||||
}}
|
||||
>
|
||||
HYO
|
||||
|
|
|
@ -8,6 +8,7 @@ import { Button } from "antd";
|
|||
import { Form, Input, ResetButton, SubmitButton } from "formik-antd";
|
||||
import { Formik } from "formik";
|
||||
import { CameraViewModel } from "../model/scene_assets";
|
||||
import { MainPage } from "../../../core/ui/pages/main_page";
|
||||
|
||||
export const SceneManagerPath = "/scene/manager/";
|
||||
|
||||
|
@ -33,8 +34,11 @@ export const SceneManger = observer(() => {
|
|||
});
|
||||
|
||||
return (
|
||||
<div>
|
||||
<canvas ref={canvasRef} style={{ position: "absolute", overflow: "hidden" }} />
|
||||
<MainPage
|
||||
page={"Сцена"}
|
||||
bodyChildren={
|
||||
<>
|
||||
<canvas ref={canvasRef} style={{ overflow: "hidden" }} />
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
|
@ -44,8 +48,8 @@ export const SceneManger = observer(() => {
|
|||
position: "absolute",
|
||||
width: "100vw",
|
||||
}}
|
||||
>
|
||||
<div>
|
||||
/>
|
||||
{/* <div>
|
||||
{sceneIcons.map((el) => {
|
||||
return (
|
||||
<div
|
||||
|
@ -70,7 +74,7 @@ export const SceneManger = observer(() => {
|
|||
borderColor: "white",
|
||||
}}
|
||||
>
|
||||
<div style={{ color: "white" }}>Scene manager</div>
|
||||
{/* <div style={{ color: "white" }}>Scene manager</div>
|
||||
{store.isVisibleSaveButton ? (
|
||||
<>
|
||||
<Button onClick={() => store.onTapSave()}>Save</Button>
|
||||
|
@ -160,14 +164,20 @@ export const SceneManger = observer(() => {
|
|||
) : (
|
||||
<Button>Selects an object for magnetism</Button>
|
||||
)}
|
||||
{store.objectForMagnetism ? <>{store.objectForMagnetism}</> : <Button>Selects an object magnet</Button>}
|
||||
{store.objectForMagnetism ? (
|
||||
<>{store.objectForMagnetism}</>
|
||||
) : (
|
||||
<Button>Selects an object magnet</Button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
) : (
|
||||
<></>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)} */}
|
||||
{/* </div> */}
|
||||
</>
|
||||
}
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
|
11
ui/src/features/simulations/simulations_screen.tsx
Normal file
11
ui/src/features/simulations/simulations_screen.tsx
Normal file
|
@ -0,0 +1,11 @@
|
|||
import * as React from "react";
|
||||
import { MainPage } from "../../core/ui/pages/main_page";
|
||||
|
||||
export interface ISimulationScreenProps {}
|
||||
export const SimulationScreenPath = "/simulation";
|
||||
|
||||
export default class SimulationScreen extends React.Component<ISimulationScreenProps> {
|
||||
public render() {
|
||||
return <MainPage page={"Симуляция"}></MainPage>;
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue