progress
This commit is contained in:
parent
7e25cc216a
commit
c628cdb9af
20 changed files with 654 additions and 124 deletions
1
.vscode/settings.json
vendored
1
.vscode/settings.json
vendored
|
@ -1,6 +1,7 @@
|
||||||
{
|
{
|
||||||
"cSpell.words": [
|
"cSpell.words": [
|
||||||
"Ведите",
|
"Ведите",
|
||||||
|
"Навыки",
|
||||||
"typedataset"
|
"typedataset"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import { BehaviorTreesPresentation } from "../../features/behavior_trees/behavior_trees";
|
||||||
import { DatasetsPresentation } from "../../features/datasets/datasets_presentation";
|
import { DatasetsPresentation } from "../../features/datasets/datasets_presentation";
|
||||||
import { ProjectsPresentation } from "../../features/projects/projects_presentation";
|
import { ProjectsPresentation } from "../../features/projects/projects_presentation";
|
||||||
// import { ProjectsPresentation } from "../../features/_projects/projects_presentation";
|
// import { ProjectsPresentation } from "../../features/_projects/projects_presentation";
|
||||||
|
@ -6,4 +7,4 @@ import { Routes } from "../interfaces/router";
|
||||||
|
|
||||||
extensions();
|
extensions();
|
||||||
|
|
||||||
export const httpRoutes: Routes[] = [new ProjectsPresentation(), new DatasetsPresentation()].map((el) => el.call());
|
export const httpRoutes: Routes[] = [new ProjectsPresentation(), new DatasetsPresentation(), new BehaviorTreesPresentation()].map((el) => el.call());
|
||||||
|
|
147
server/src/core/models/skill_model.ts
Normal file
147
server/src/core/models/skill_model.ts
Normal file
|
@ -0,0 +1,147 @@
|
||||||
|
import { IsArray, IsString, ValidateNested } from "class-validator";
|
||||||
|
import { Type } from "class-transformer";
|
||||||
|
|
||||||
|
export interface SkillPoseEstimation {
|
||||||
|
SkillPackage: ISkillPackage;
|
||||||
|
Module: IModule;
|
||||||
|
Launch: ILaunch;
|
||||||
|
ROS2: IRos2;
|
||||||
|
BTAction: IBTAction[];
|
||||||
|
Interface: IInterface;
|
||||||
|
Settings: ISetting[];
|
||||||
|
xxx: IXxx;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IBTAction {
|
||||||
|
name: string;
|
||||||
|
format: string;
|
||||||
|
type: string;
|
||||||
|
param: string[];
|
||||||
|
result: string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IInterface {
|
||||||
|
Input: IPut[];
|
||||||
|
Output: IPut[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IPut {
|
||||||
|
name: string;
|
||||||
|
type: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ILaunch {
|
||||||
|
executable: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IModule {
|
||||||
|
name: string;
|
||||||
|
description: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IRos2 {
|
||||||
|
node_name: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ISetting {
|
||||||
|
name: string;
|
||||||
|
value: number | string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ISkillPackage {
|
||||||
|
name: string;
|
||||||
|
version: string;
|
||||||
|
format: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IXxx {
|
||||||
|
cameraLink: string;
|
||||||
|
topicImage: string;
|
||||||
|
topicCameraInfo: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class SkillPackage implements ISkillPackage {
|
||||||
|
@IsString()
|
||||||
|
name: string;
|
||||||
|
@IsString()
|
||||||
|
version: string;
|
||||||
|
@IsString()
|
||||||
|
format: string;
|
||||||
|
}
|
||||||
|
export class Module implements IModule {
|
||||||
|
@IsString()
|
||||||
|
name: string;
|
||||||
|
@IsString()
|
||||||
|
description: string;
|
||||||
|
}
|
||||||
|
export class BTAction implements IBTAction {
|
||||||
|
@IsString()
|
||||||
|
name: string;
|
||||||
|
@IsString()
|
||||||
|
format: string;
|
||||||
|
@IsString()
|
||||||
|
type: string;
|
||||||
|
@IsArray()
|
||||||
|
param: string[];
|
||||||
|
@IsArray()
|
||||||
|
result: string[];
|
||||||
|
}
|
||||||
|
export class Launch implements ILaunch {
|
||||||
|
@IsString()
|
||||||
|
executable: string;
|
||||||
|
}
|
||||||
|
export class Ros2 implements IRos2 {
|
||||||
|
@IsString()
|
||||||
|
node_name: string;
|
||||||
|
}
|
||||||
|
export class Put implements IPut {
|
||||||
|
@IsString()
|
||||||
|
name: string;
|
||||||
|
@IsString()
|
||||||
|
type: string;
|
||||||
|
}
|
||||||
|
export class Interface implements IInterface {
|
||||||
|
@ValidateNested()
|
||||||
|
@Type(() => Put)
|
||||||
|
Input: IPut[];
|
||||||
|
@ValidateNested()
|
||||||
|
@Type(() => Put)
|
||||||
|
Output: IPut[];
|
||||||
|
}
|
||||||
|
export class Setting implements ISetting {
|
||||||
|
name: string;
|
||||||
|
value: string | number;
|
||||||
|
}
|
||||||
|
export class Xxx implements IXxx {
|
||||||
|
cameraLink: string;
|
||||||
|
topicImage: string;
|
||||||
|
topicCameraInfo: string;
|
||||||
|
}
|
||||||
|
export class SkillModelPoseEstimation implements SkillPoseEstimation {
|
||||||
|
@ValidateNested()
|
||||||
|
@Type(() => SkillPackage)
|
||||||
|
SkillPackage: ISkillPackage;
|
||||||
|
@ValidateNested()
|
||||||
|
@Type(() => Module)
|
||||||
|
Module: IModule;
|
||||||
|
@ValidateNested()
|
||||||
|
@Type(() => Launch)
|
||||||
|
Launch: ILaunch;
|
||||||
|
@ValidateNested()
|
||||||
|
@Type(() => Ros2)
|
||||||
|
ROS2: IRos2;
|
||||||
|
@ValidateNested()
|
||||||
|
@IsArray()
|
||||||
|
@Type(() => BTAction)
|
||||||
|
BTAction: IBTAction[];
|
||||||
|
@ValidateNested()
|
||||||
|
@Type(() => Interface)
|
||||||
|
Interface: IInterface;
|
||||||
|
@ValidateNested()
|
||||||
|
@IsArray()
|
||||||
|
@Type(() => Setting)
|
||||||
|
Settings: ISetting[];
|
||||||
|
@ValidateNested()
|
||||||
|
@Type(() => Xxx)
|
||||||
|
xxx: IXxx;
|
||||||
|
}
|
12
server/src/features/behavior_trees/behavior_trees.ts
Normal file
12
server/src/features/behavior_trees/behavior_trees.ts
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
import { CoreHttpController } from "../../core/controllers/http_controller";
|
||||||
|
import { DatasetValidationModel } from "../datasets/models/dataset_validation_model";
|
||||||
|
import { GetBehaviorTreeSkillsUseCase } from "./get_bt_usecase";
|
||||||
|
export class BehaviorTreesPresentation extends CoreHttpController<DatasetValidationModel> {
|
||||||
|
constructor() {
|
||||||
|
super({
|
||||||
|
url: "behavior/trees",
|
||||||
|
validationModel: DatasetValidationModel,
|
||||||
|
});
|
||||||
|
super.get(new GetBehaviorTreeSkillsUseCase().call);
|
||||||
|
}
|
||||||
|
}
|
154
server/src/features/behavior_trees/get_bt_usecase.ts
Normal file
154
server/src/features/behavior_trees/get_bt_usecase.ts
Normal file
|
@ -0,0 +1,154 @@
|
||||||
|
import { Result } from "../../core/helpers/result";
|
||||||
|
|
||||||
|
export class GetBehaviorTreeSkillsUseCase {
|
||||||
|
call = () => {
|
||||||
|
return Result.ok({
|
||||||
|
skills: [
|
||||||
|
{
|
||||||
|
SkillPackage: {
|
||||||
|
name: "Robossembler",
|
||||||
|
version: "1.0",
|
||||||
|
format: "1",
|
||||||
|
},
|
||||||
|
Module: {
|
||||||
|
name: "PoseEstimation",
|
||||||
|
description: "Pose Estimation skill with DOPE",
|
||||||
|
},
|
||||||
|
Launch: {
|
||||||
|
executable: "pe_dope_lc.py",
|
||||||
|
},
|
||||||
|
ROS2: {
|
||||||
|
node_name: "lc_dope",
|
||||||
|
},
|
||||||
|
BTAction: [
|
||||||
|
{
|
||||||
|
name: "peConfigure",
|
||||||
|
format: "yaml",
|
||||||
|
type: "run",
|
||||||
|
param: ["object_name", "weights_file"],
|
||||||
|
result: ["Pose"],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "peStop",
|
||||||
|
format: "yaml",
|
||||||
|
type: "stop",
|
||||||
|
param: [],
|
||||||
|
result: [],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
Interface: {
|
||||||
|
Input: [
|
||||||
|
{
|
||||||
|
name: "cameraLink",
|
||||||
|
type: "CAMERA",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "object_name",
|
||||||
|
type: "MODEL",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
Output: [
|
||||||
|
{
|
||||||
|
name: "pose_estimation_topic",
|
||||||
|
type: "POSE",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
Settings: [
|
||||||
|
{
|
||||||
|
name: "cameraLink",
|
||||||
|
value: "inner_rgbd_camera",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "pose",
|
||||||
|
value: "",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "publishDelay",
|
||||||
|
value: 0.5,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "tf2_send_pose",
|
||||||
|
value: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "mesh_scale",
|
||||||
|
value: 0.001,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
xxx: {
|
||||||
|
cameraLink: "inner_rgbd_camera",
|
||||||
|
topicImage: "/inner_rgbd_camera/image",
|
||||||
|
topicCameraInfo: "/inner_rgbd_camera/camera_info",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
SkillPackage: {
|
||||||
|
name: "Robossembler",
|
||||||
|
version: "1.0",
|
||||||
|
format: "1",
|
||||||
|
},
|
||||||
|
Module: {
|
||||||
|
name: "ObjectDetection",
|
||||||
|
description: "Object detection skill with YOLOv8",
|
||||||
|
},
|
||||||
|
Launch: {
|
||||||
|
executable: "detection_lifecycle.py",
|
||||||
|
},
|
||||||
|
ROS2: {
|
||||||
|
node_name: "lc_detection",
|
||||||
|
},
|
||||||
|
BTAction: [
|
||||||
|
{
|
||||||
|
name: "odConfigure",
|
||||||
|
format: "yaml",
|
||||||
|
args: ["SettingPath", "server_name", "server_timeout"],
|
||||||
|
result: ["boundBox"],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "odStop",
|
||||||
|
format: "yaml",
|
||||||
|
args: ["server_name", "server_timeout"],
|
||||||
|
result: [],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
Interface: {
|
||||||
|
Input: [
|
||||||
|
{
|
||||||
|
name: "cameraLink",
|
||||||
|
type: "string",
|
||||||
|
group: "STD_USER",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "topicImage",
|
||||||
|
type: "Image",
|
||||||
|
group: "sensor_msgs.msg",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
Output: [
|
||||||
|
{
|
||||||
|
name: "boundBox",
|
||||||
|
type: "BoundBox",
|
||||||
|
group: ".msg",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
Settings: [
|
||||||
|
{
|
||||||
|
name: "publishDelay",
|
||||||
|
value: 0.5,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "server_timeout",
|
||||||
|
value: 1000,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "server_name",
|
||||||
|
value: "/object_detection/change_state",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
183
ui/src/core/model/skill_model.ts
Normal file
183
ui/src/core/model/skill_model.ts
Normal file
|
@ -0,0 +1,183 @@
|
||||||
|
import { IsArray, IsString, ValidateNested } from "class-validator";
|
||||||
|
import { Type } from "class-transformer";
|
||||||
|
import { ISkillView } from "../../features/behavior_tree_builder/presentation/ui/skill_tree/skill_tree";
|
||||||
|
import { v4 } from "uuid";
|
||||||
|
|
||||||
|
export interface ISkillPoseEstimation {
|
||||||
|
SkillPackage: ISkillPackage;
|
||||||
|
Module: IModule;
|
||||||
|
Launch: ILaunch;
|
||||||
|
ROS2: IRos2;
|
||||||
|
BTAction: IBTAction[];
|
||||||
|
Interface: IInterface;
|
||||||
|
Settings: ISetting[];
|
||||||
|
xxx: IXxx;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IBTAction {
|
||||||
|
name: string;
|
||||||
|
format: string;
|
||||||
|
type: string;
|
||||||
|
param: string[];
|
||||||
|
result: string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IInterface {
|
||||||
|
Input: IPut[];
|
||||||
|
Output: IPut[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IPut {
|
||||||
|
name: string;
|
||||||
|
type: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ILaunch {
|
||||||
|
executable: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IModule {
|
||||||
|
name: string;
|
||||||
|
description: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IRos2 {
|
||||||
|
node_name: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ISetting {
|
||||||
|
name: string;
|
||||||
|
value: number | string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ISkillPackage {
|
||||||
|
name: string;
|
||||||
|
version: string;
|
||||||
|
format: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IXxx {
|
||||||
|
cameraLink: string;
|
||||||
|
topicImage: string;
|
||||||
|
topicCameraInfo: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class SkillPackage implements ISkillPackage {
|
||||||
|
@IsString()
|
||||||
|
name: string;
|
||||||
|
@IsString()
|
||||||
|
version: string;
|
||||||
|
@IsString()
|
||||||
|
format: string;
|
||||||
|
}
|
||||||
|
export class Module implements IModule {
|
||||||
|
@IsString()
|
||||||
|
name: string;
|
||||||
|
@IsString()
|
||||||
|
description: string;
|
||||||
|
}
|
||||||
|
export class BTAction implements IBTAction {
|
||||||
|
@IsString()
|
||||||
|
name: string;
|
||||||
|
@IsString()
|
||||||
|
format: string;
|
||||||
|
@IsString()
|
||||||
|
type: string;
|
||||||
|
@IsArray()
|
||||||
|
param: string[];
|
||||||
|
@IsArray()
|
||||||
|
result: string[];
|
||||||
|
}
|
||||||
|
export class Launch implements ILaunch {
|
||||||
|
@IsString()
|
||||||
|
executable: string;
|
||||||
|
}
|
||||||
|
export class Ros2 implements IRos2 {
|
||||||
|
@IsString()
|
||||||
|
node_name: string;
|
||||||
|
}
|
||||||
|
export class Put implements IPut {
|
||||||
|
@IsString()
|
||||||
|
name: string;
|
||||||
|
@IsString()
|
||||||
|
type: string;
|
||||||
|
}
|
||||||
|
export class Interface implements IInterface {
|
||||||
|
@ValidateNested()
|
||||||
|
@Type(() => Put)
|
||||||
|
Input: IPut[];
|
||||||
|
@ValidateNested()
|
||||||
|
@Type(() => Put)
|
||||||
|
Output: IPut[];
|
||||||
|
}
|
||||||
|
export class Setting implements ISetting {
|
||||||
|
name: string;
|
||||||
|
value: string | number;
|
||||||
|
}
|
||||||
|
export class Xxx implements IXxx {
|
||||||
|
cameraLink: string;
|
||||||
|
topicImage: string;
|
||||||
|
topicCameraInfo: string;
|
||||||
|
}
|
||||||
|
export class SkillModelPoseEstimation implements ISkillPoseEstimation {
|
||||||
|
@ValidateNested()
|
||||||
|
@Type(() => SkillPackage)
|
||||||
|
SkillPackage: ISkillPackage;
|
||||||
|
@ValidateNested()
|
||||||
|
@Type(() => Module)
|
||||||
|
Module: IModule;
|
||||||
|
@ValidateNested()
|
||||||
|
@Type(() => Launch)
|
||||||
|
Launch: ILaunch;
|
||||||
|
@ValidateNested()
|
||||||
|
@Type(() => Ros2)
|
||||||
|
ROS2: IRos2;
|
||||||
|
@ValidateNested()
|
||||||
|
@IsArray()
|
||||||
|
@Type(() => BTAction)
|
||||||
|
BTAction: IBTAction[];
|
||||||
|
@ValidateNested()
|
||||||
|
@Type(() => Interface)
|
||||||
|
Interface: IInterface;
|
||||||
|
@ValidateNested()
|
||||||
|
@IsArray()
|
||||||
|
@Type(() => Setting)
|
||||||
|
Settings: ISetting[];
|
||||||
|
@ValidateNested()
|
||||||
|
@Type(() => Xxx)
|
||||||
|
xxx: IXxx;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class Skills {
|
||||||
|
@IsArray()
|
||||||
|
@Type(() => SkillModelPoseEstimation)
|
||||||
|
skills: SkillModelPoseEstimation[];
|
||||||
|
toSkillView(): ISkillView[] {
|
||||||
|
return this.skills.map((el) => {
|
||||||
|
return {
|
||||||
|
name: el.Module.name,
|
||||||
|
children: el.BTAction.map((act) => {
|
||||||
|
// return { name: `${el.Module.name} - ${act.name}` };
|
||||||
|
return { name: act.name, uuid: v4() };
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
getSkillDo(name: string) {
|
||||||
|
return this.skills.reduce((acc, el) => {
|
||||||
|
if (el.BTAction.find((el) => el.name.isEqual(name))) {
|
||||||
|
acc = el.Module.name;
|
||||||
|
}
|
||||||
|
return acc;
|
||||||
|
}, "error");
|
||||||
|
}
|
||||||
|
getSkillsNames() {
|
||||||
|
return this.skills
|
||||||
|
.map((el) => {
|
||||||
|
return el.BTAction.map((act) => {
|
||||||
|
return { name: act.name };
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.flat(1);
|
||||||
|
}
|
||||||
|
}
|
|
@ -21,6 +21,7 @@ import DetailsScreen, { DetailsScreenPath } from "../../features/details/details
|
||||||
import { AssemblesScreen, AssemblesScreenPath } from "../../features/assembles/assembles_screen";
|
import { AssemblesScreen, AssemblesScreenPath } from "../../features/assembles/assembles_screen";
|
||||||
import SimulationScreen, { SimulationScreenPath } from "../../features/simulations/simulations_screen";
|
import SimulationScreen, { SimulationScreenPath } from "../../features/simulations/simulations_screen";
|
||||||
import { EstimateScreen, EstimateScreenPath } from "../../features/estimate/estimate_screen";
|
import { EstimateScreen, EstimateScreenPath } from "../../features/estimate/estimate_screen";
|
||||||
|
import { SkillPath, SkillScreen } from "../../features/skils/skills_screen";
|
||||||
|
|
||||||
const idURL = ":id";
|
const idURL = ":id";
|
||||||
|
|
||||||
|
@ -67,9 +68,12 @@ export const router = createBrowserRouter([
|
||||||
path: SimulationScreenPath,
|
path: SimulationScreenPath,
|
||||||
element: <SimulationScreen />,
|
element: <SimulationScreen />,
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
path: EstimateScreenPath,
|
path: EstimateScreenPath,
|
||||||
element: <EstimateScreen />,
|
element: <EstimateScreen />,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: SkillPath,
|
||||||
|
element: <SkillScreen />,
|
||||||
|
},
|
||||||
]);
|
]);
|
||||||
|
|
|
@ -31,3 +31,6 @@ export function CoreButton(props: IButtonProps) {
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@ import { DetailsScreenPath } from "../../../features/details/details_screen";
|
||||||
import { SimulationScreenPath } from "../../../features/simulations/simulations_screen";
|
import { SimulationScreenPath } from "../../../features/simulations/simulations_screen";
|
||||||
import { EstimateScreenPath } from "../../../features/estimate/estimate_screen";
|
import { EstimateScreenPath } from "../../../features/estimate/estimate_screen";
|
||||||
import { BehaviorTreeBuilderPath } from "../../../features/behavior_tree_builder/presentation/behavior_tree_builder_screen";
|
import { BehaviorTreeBuilderPath } from "../../../features/behavior_tree_builder/presentation/behavior_tree_builder_screen";
|
||||||
|
import { SkillPath as SkillScreenPath } from "../../../features/skils/skills_screen";
|
||||||
export interface IBlockProps {
|
export interface IBlockProps {
|
||||||
name: string;
|
name: string;
|
||||||
isActive: boolean;
|
isActive: boolean;
|
||||||
|
@ -45,6 +46,7 @@ const Block = (props: IBlockProps) => {
|
||||||
export interface IMainPageProps {
|
export interface IMainPageProps {
|
||||||
page: string;
|
page: string;
|
||||||
bodyChildren?: JSX.Element;
|
bodyChildren?: JSX.Element;
|
||||||
|
panelChildren?: JSX.Element;
|
||||||
isLoading?: boolean;
|
isLoading?: boolean;
|
||||||
}
|
}
|
||||||
export const MainPage = (props: IMainPageProps) => {
|
export const MainPage = (props: IMainPageProps) => {
|
||||||
|
@ -53,7 +55,8 @@ export const MainPage = (props: IMainPageProps) => {
|
||||||
{ name: "Сборки", path: AssemblesScreenPath, icon: "Assembly" },
|
{ name: "Сборки", path: AssemblesScreenPath, icon: "Assembly" },
|
||||||
{ name: "Датасеты", path: DatasetsScreenPath, icon: "Datasets" },
|
{ name: "Датасеты", path: DatasetsScreenPath, icon: "Datasets" },
|
||||||
{ name: "Сцена", path: SceneManagerPath, icon: "Layers" },
|
{ name: "Сцена", path: SceneManagerPath, icon: "Layers" },
|
||||||
{ name: "Навыки", path: BehaviorTreeBuilderPath, icon: "Rocket" },
|
{ name: "Навыки", path: SkillScreenPath, icon: "Layers" },
|
||||||
|
{ name: "Поведение", path: BehaviorTreeBuilderPath, icon: "Rocket" },
|
||||||
{ name: "Симуляция", path: SimulationScreenPath, icon: "Simulation" },
|
{ name: "Симуляция", path: SimulationScreenPath, icon: "Simulation" },
|
||||||
{ name: "Оценка", path: EstimateScreenPath, icon: "Grade" },
|
{ name: "Оценка", path: EstimateScreenPath, icon: "Grade" },
|
||||||
];
|
];
|
||||||
|
@ -118,7 +121,9 @@ export const MainPage = (props: IMainPageProps) => {
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
<div style={{ width: 241, height: window.innerHeight, backgroundColor: "#F7F2FA", borderRadius: 16 }}> </div>
|
<div style={{ width: 241, height: window.innerHeight, backgroundColor: "#F7F2FA", borderRadius: 16 }}>
|
||||||
|
{props.panelChildren}{" "}
|
||||||
|
</div>
|
||||||
{props.bodyChildren}
|
{props.bodyChildren}
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
import { Result } from "../../../core/helper/result";
|
||||||
|
import { Skills } from "../../../core/model/skill_model";
|
||||||
|
import { HttpError, HttpMethod, HttpRepository } from "../../../core/repository/http_repository";
|
||||||
|
|
||||||
|
export class BehaviorTreeBuilderRepository extends HttpRepository {
|
||||||
|
getBtSkills = async ():Promise<Result<HttpError, Skills>> => {
|
||||||
|
return await this._jsonToClassInstanceRequest<Skills>(HttpMethod.GET, "/behavior/trees", Skills) as unknown as Promise<Result<HttpError, Skills>>;
|
||||||
|
};
|
||||||
|
}
|
|
@ -3,6 +3,7 @@ import { NodeEditor } from "rete";
|
||||||
import { AreaExtra, Schemes } from "../presentation/ui/editor/editor";
|
import { AreaExtra, Schemes } from "../presentation/ui/editor/editor";
|
||||||
import { Result } from "../../../core/helper/result";
|
import { Result } from "../../../core/helper/result";
|
||||||
import { AreaPlugin } from "rete-area-plugin";
|
import { AreaPlugin } from "rete-area-plugin";
|
||||||
|
import { Skills } from "../../../core/model/skill_model";
|
||||||
|
|
||||||
export interface BtDrawDragAndDropView {
|
export interface BtDrawDragAndDropView {
|
||||||
x: number;
|
x: number;
|
||||||
|
@ -15,21 +16,31 @@ export class BtNodeView extends TypedEvent<BtDrawDragAndDropView> {}
|
||||||
export class ReteObserver extends TypedEvent<any> {}
|
export class ReteObserver extends TypedEvent<any> {}
|
||||||
export class BtBuilderModel {
|
export class BtBuilderModel {
|
||||||
public static result = "";
|
public static result = "";
|
||||||
static fromReteScene(editor: NodeEditor<Schemes>, area: AreaPlugin<Schemes, AreaExtra>): Result<string, string> {
|
static fromReteScene(
|
||||||
|
editor: NodeEditor<Schemes>,
|
||||||
|
area: AreaPlugin<Schemes, AreaExtra>,
|
||||||
|
skills?: Skills
|
||||||
|
): Result<string, string> {
|
||||||
try {
|
try {
|
||||||
|
this.result = "";
|
||||||
this.getFirstSequence(editor).map((sortedSequence) => {
|
this.getFirstSequence(editor).map((sortedSequence) => {
|
||||||
const firstNodeId = sortedSequence.getKeyFromValueIsExists(1) as string;
|
const firstNodeId = sortedSequence.getKeyFromValueIsExists(1) as string;
|
||||||
this.findSequence(firstNodeId, editor, sortedSequence, 2);
|
this.findSequence(firstNodeId, editor, sortedSequence, 2);
|
||||||
this.result += `<${this.getNodeLabelAtId(editor, firstNodeId)} id="${firstNodeId}">`;
|
this.result += `<${this.getNodeLabelAtId(editor, firstNodeId, skills)}>`;
|
||||||
this.toXML(sortedSequence as Map<string, number>, editor, area, firstNodeId);
|
this.toXML(sortedSequence as Map<string, number>, editor, area, firstNodeId, skills);
|
||||||
this.result += `</${this.getNodeLabelAtId(editor, firstNodeId)}>`;
|
this.result += `</${this.getNodeLabelAtId(editor, firstNodeId, skills)}>`;
|
||||||
});
|
});
|
||||||
return Result.ok(this.result);
|
return Result.ok(this.result);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return Result.error("BtBuilderModel fromReteScene error");
|
return Result.error("BtBuilderModel fromReteScene error");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public static getNodeLabelAtId(editor: NodeEditor<Schemes>, id: string) {
|
public static getNodeLabelAtId(editor: NodeEditor<Schemes>, id: string, skills?: Skills) {
|
||||||
|
if (skills?.getSkillsNames().find((el) => el.name.isEqual(editor.getNode(id).label))) {
|
||||||
|
return `Action ID="RbsBtAction" do="${skills.getSkillDo(editor.getNode(id).label)}" command="${
|
||||||
|
editor.getNode(id).label
|
||||||
|
}" server_name="rbs_interface" server_timeout="1000"`;
|
||||||
|
}
|
||||||
return editor.getNode(id).label;
|
return editor.getNode(id).label;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,18 +48,20 @@ export class BtBuilderModel {
|
||||||
sortedSequence: Map<string, number>,
|
sortedSequence: Map<string, number>,
|
||||||
editor: NodeEditor<Schemes>,
|
editor: NodeEditor<Schemes>,
|
||||||
area: AreaPlugin<Schemes, AreaExtra>,
|
area: AreaPlugin<Schemes, AreaExtra>,
|
||||||
activeElementId = ""
|
activeElementId = "",
|
||||||
|
skills?: Skills
|
||||||
) {
|
) {
|
||||||
editor.getConnections().forEach((el) => {
|
editor.getConnections().forEach((el) => {
|
||||||
if (el.source === activeElementId) {
|
if (el.source === activeElementId) {
|
||||||
this.result += `<${this.getNodeLabelAtId(editor, el.target)} id="${el.target}">`;
|
this.result += `<${this.getNodeLabelAtId(editor, el.target, skills)}>`;
|
||||||
this.toXML(sortedSequence, editor, area, el.target);
|
this.toXML(sortedSequence, editor, area, el.target, skills);
|
||||||
this.result += `</${this.getNodeLabelAtId(editor, el.target)}>`;
|
this.result += `</${this.getNodeLabelAtId(editor, el.target)}>`;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public static getBtPriorities(ids: string[]) {}
|
public static getBtPriorities(ids: string[]) {}
|
||||||
|
|
||||||
public static findSequence(
|
public static findSequence(
|
||||||
nodeId: string,
|
nodeId: string,
|
||||||
editor: NodeEditor<Schemes>,
|
editor: NodeEditor<Schemes>,
|
||||||
|
|
|
@ -1,40 +1,27 @@
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import { CoreText, CoreTextType } from "../../../core/ui/text/text";
|
|
||||||
import { Button, Input } from "antd";
|
|
||||||
|
|
||||||
import { useRete } from "rete-react-plugin";
|
import { useRete } from "rete-react-plugin";
|
||||||
import { createEditor } from "./ui/editor/editor";
|
import { createEditor } from "./ui/editor/editor";
|
||||||
import { SkillTree } from "./ui/skill_tree/skill_tree";
|
import { SkillTree } from "./ui/skill_tree/skill_tree";
|
||||||
import { BehaviorTreeBuilderStore } from "./behavior_tree_builder_store";
|
import { BehaviorTreeBuilderStore } from "./behavior_tree_builder_store";
|
||||||
import { MainPage } from "../../../core/ui/pages/main_page";
|
import { MainPage } from "../../../core/ui/pages/main_page";
|
||||||
|
import { CoreButton } from "../../../core/ui/button/button";
|
||||||
|
import { observer } from "mobx-react-lite";
|
||||||
|
|
||||||
export const behaviorTreeBuilderScreenPath = "behavior/tree/screen/path";
|
export const behaviorTreeBuilderScreenPath = "behavior/tree/screen/path";
|
||||||
|
|
||||||
const skills = {
|
|
||||||
name: "",
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
name: "Actions",
|
|
||||||
children: [{ name: "MoveToPose", interface: "Vector3", out: "vo" }],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Control",
|
|
||||||
children: [
|
|
||||||
{ name: "Fallback", interface: "Vector3", out: "vo" },
|
|
||||||
{ name: "Sequence", interface: "Vector3", out: "vo" },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
export const behaviorTreeBuilderStore = new BehaviorTreeBuilderStore();
|
export const behaviorTreeBuilderStore = new BehaviorTreeBuilderStore();
|
||||||
|
|
||||||
export const BehaviorTreeBuilderPath = "/behavior/tree/";
|
export const BehaviorTreeBuilderPath = "/behavior/tree/";
|
||||||
export function BehaviorTreeBuilderScreen() {
|
|
||||||
|
export const BehaviorTreeBuilderScreen = observer(() => {
|
||||||
const store = behaviorTreeBuilderStore;
|
const store = behaviorTreeBuilderStore;
|
||||||
const [ref] = useRete(createEditor);
|
// @ts-expect-error
|
||||||
|
const [ref] = useRete<HTMLDivElement>(createEditor);
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
store.init();
|
store.init();
|
||||||
|
if (ref.current)
|
||||||
store.dragZoneSetOffset(
|
store.dragZoneSetOffset(
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
ref.current.offsetTop,
|
ref.current.offsetTop,
|
||||||
|
@ -45,7 +32,6 @@ export function BehaviorTreeBuilderScreen() {
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
ref.current.clientHeight
|
ref.current.clientHeight
|
||||||
);
|
);
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
store.dispose();
|
store.dispose();
|
||||||
};
|
};
|
||||||
|
@ -54,11 +40,17 @@ export function BehaviorTreeBuilderScreen() {
|
||||||
return (
|
return (
|
||||||
<MainPage
|
<MainPage
|
||||||
page={"Навыки"}
|
page={"Навыки"}
|
||||||
|
panelChildren={
|
||||||
|
<>
|
||||||
|
{store.skills ? <SkillTree skills={store.skillTree} dragEnd={store.dragEnd} /> : null}
|
||||||
|
<div style={{ width: 100, height: 40 }}>
|
||||||
|
<CoreButton onClick={() => store.saveBt()} text="SAVE BT" />
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
}
|
||||||
bodyChildren={
|
bodyChildren={
|
||||||
<>
|
<>
|
||||||
<div style={{ display: "flex", width: "100%" }}>
|
<div style={{ display: "flex", width: "100%" }}>
|
||||||
{/* <SkillTree dragEnd={store.dragEnd} skills={skills} /> */}
|
|
||||||
|
|
||||||
<div
|
<div
|
||||||
ref={ref}
|
ref={ref}
|
||||||
style={{
|
style={{
|
||||||
|
@ -72,4 +64,4 @@ export function BehaviorTreeBuilderScreen() {
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
});
|
||||||
|
|
|
@ -7,6 +7,9 @@ import { NodeEditor } from "rete";
|
||||||
import { AreaExtra, Schemes } from "./ui/editor/editor";
|
import { AreaExtra, Schemes } from "./ui/editor/editor";
|
||||||
import { AreaPlugin } from "rete-area-plugin";
|
import { AreaPlugin } from "rete-area-plugin";
|
||||||
import { NodeBehaviorTree } from "../model/node_behavior_tree";
|
import { NodeBehaviorTree } from "../model/node_behavior_tree";
|
||||||
|
import { BehaviorTreeBuilderRepository } from "../data/behavior_tree_builder_repository";
|
||||||
|
import { Skills } from "../../../core/model/skill_model";
|
||||||
|
import { ISkillView } from "./ui/skill_tree/skill_tree";
|
||||||
|
|
||||||
interface I2DArea {
|
interface I2DArea {
|
||||||
x: number;
|
x: number;
|
||||||
|
@ -20,9 +23,11 @@ export class BehaviorTreeBuilderStore extends UiErrorState<HttpError> {
|
||||||
this.reteNode?.emit("200");
|
this.reteNode?.emit("200");
|
||||||
}
|
}
|
||||||
validateBt() {}
|
validateBt() {}
|
||||||
|
skills?: Skills;
|
||||||
area?: I2DArea;
|
area?: I2DArea;
|
||||||
btNodeView: BtNodeView = new BtNodeView();
|
btNodeView: BtNodeView = new BtNodeView();
|
||||||
reteNode?: ReteObserver;
|
reteNode?: ReteObserver;
|
||||||
|
behaviorTreeBuilderRepository = new BehaviorTreeBuilderRepository();
|
||||||
canRun = true;
|
canRun = true;
|
||||||
nodes: NodeBehaviorTree[] = [
|
nodes: NodeBehaviorTree[] = [
|
||||||
{
|
{
|
||||||
|
@ -32,64 +37,24 @@ export class BehaviorTreeBuilderStore extends UiErrorState<HttpError> {
|
||||||
inputs: ["a"],
|
inputs: ["a"],
|
||||||
position: { x: -488.1303402823156, y: -227.90861570911895 },
|
position: { x: -488.1303402823156, y: -227.90861570911895 },
|
||||||
},
|
},
|
||||||
{
|
|
||||||
label: "Sequence",
|
|
||||||
id: "2",
|
|
||||||
outputs: ["a"],
|
|
||||||
inputs: ["a"],
|
|
||||||
connectTo: "1",
|
|
||||||
position: { x: 119.95735514023244, y: -182.24902817216878 },
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "Sequence",
|
|
||||||
id: "6",
|
|
||||||
outputs: ["a"],
|
|
||||||
inputs: ["a"],
|
|
||||||
connectTo: "2",
|
|
||||||
position: { x: 402.06111561958505, y: -100.97814086372247 },
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "MoveToPose",
|
|
||||||
id: "7",
|
|
||||||
outputs: ["a"],
|
|
||||||
inputs: ["a"],
|
|
||||||
connectTo: "6",
|
|
||||||
position: { x: 932.0688448287292, y: 90.10780461923443 },
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "MoveToPose",
|
|
||||||
id: "8",
|
|
||||||
outputs: ["a"],
|
|
||||||
inputs: ["a"],
|
|
||||||
connectTo: "6",
|
|
||||||
position: { x: 898.1684213039546, y: -119.80545806921208 },
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "MoveToPose",
|
|
||||||
id: "3",
|
|
||||||
outputs: [],
|
|
||||||
inputs: ["a"],
|
|
||||||
connectTo: "1",
|
|
||||||
position: { x: 208.65749743442188, y: 16.256489050033785 },
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "MoveToPose",
|
|
||||||
id: "4",
|
|
||||||
outputs: [],
|
|
||||||
inputs: ["a"],
|
|
||||||
connectTo: "1",
|
|
||||||
position: { x: -50.46426323140673, y: 99.22642447650014 },
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "Sequence",
|
|
||||||
id: "5",
|
|
||||||
outputs: ["a"],
|
|
||||||
inputs: ["a"],
|
|
||||||
connectTo: "1",
|
|
||||||
position: { x: -234.54554662642457, y: 245.4012710608967 },
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
|
];
|
||||||
|
skillTree: ISkillView = {
|
||||||
|
name: "",
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
name: "Actions",
|
||||||
|
children: [],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Control",
|
||||||
|
children: [
|
||||||
|
{ name: "Fallback", interface: "Vector3", out: "vo" },
|
||||||
|
{ name: "Sequence", interface: "Vector3", out: "vo" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
makeAutoObservable(this);
|
makeAutoObservable(this);
|
||||||
|
@ -99,10 +64,9 @@ export class BehaviorTreeBuilderStore extends UiErrorState<HttpError> {
|
||||||
JSON.parse(value) as BtNodeView[];
|
JSON.parse(value) as BtNodeView[];
|
||||||
}
|
}
|
||||||
bt = async (editor: NodeEditor<Schemes>, area: AreaPlugin<Schemes, AreaExtra>) => {
|
bt = async (editor: NodeEditor<Schemes>, area: AreaPlugin<Schemes, AreaExtra>) => {
|
||||||
(await BtBuilderModel.fromReteScene(editor, area)).fold(
|
(await BtBuilderModel.fromReteScene(editor, area, this.skills)).fold(
|
||||||
(s) => {
|
(s) => {
|
||||||
console.log(
|
console.log(xmlFormat(`<?xml version="1.0" encoding="UTF-8"?>
|
||||||
xmlFormat(`<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<root main_tree_to_execute="Main">
|
<root main_tree_to_execute="Main">
|
||||||
<BehaviorTree ID="Main">
|
<BehaviorTree ID="Main">
|
||||||
${s}
|
${s}
|
||||||
|
@ -117,15 +81,12 @@ export class BehaviorTreeBuilderStore extends UiErrorState<HttpError> {
|
||||||
</Action>
|
</Action>
|
||||||
</TreeNodesModel>
|
</TreeNodesModel>
|
||||||
|
|
||||||
</root>`)
|
</root>`));
|
||||||
);
|
|
||||||
},
|
},
|
||||||
(_) => _
|
(_) => _
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
copyBt = () => {
|
|
||||||
this.reteNode?.emit("200");
|
|
||||||
};
|
|
||||||
errorHandingStrategy: (error: HttpError) => void;
|
errorHandingStrategy: (error: HttpError) => void;
|
||||||
|
|
||||||
dragEnd = (e: EventTarget) => {
|
dragEnd = (e: EventTarget) => {
|
||||||
|
@ -155,7 +116,20 @@ export class BehaviorTreeBuilderStore extends UiErrorState<HttpError> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async init(): Promise<any> {}
|
async init(): Promise<any> {
|
||||||
|
(await this.behaviorTreeBuilderRepository.getBtSkills()).fold(
|
||||||
|
(model) => {
|
||||||
|
this.skills = model;
|
||||||
|
this.skillTree.children = this.skillTree.children?.map((el) => {
|
||||||
|
if (el.name === "Actions") {
|
||||||
|
el.children = model.toSkillView();
|
||||||
|
}
|
||||||
|
return el;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
(e) => console.log(e)
|
||||||
|
);
|
||||||
|
}
|
||||||
dragZoneSetOffset(offsetTop: number, offsetWidth: number, width: number, height: number) {
|
dragZoneSetOffset(offsetTop: number, offsetWidth: number, width: number, height: number) {
|
||||||
this.area = {
|
this.area = {
|
||||||
x: offsetTop,
|
x: offsetTop,
|
||||||
|
|
|
@ -93,7 +93,7 @@ export function CustomNode<Scheme extends ClassicScheme>(props: Props<Scheme>) {
|
||||||
const controls = Object.entries(props.data.controls);
|
const controls = Object.entries(props.data.controls);
|
||||||
const selected = props.data.selected || false;
|
const selected = props.data.selected || false;
|
||||||
const { id, label, width, height } = props.data;
|
const { id, label, width, height } = props.data;
|
||||||
|
console.log(label)
|
||||||
sortByIndex(inputs);
|
sortByIndex(inputs);
|
||||||
sortByIndex(outputs);
|
sortByIndex(outputs);
|
||||||
sortByIndex(controls);
|
sortByIndex(controls);
|
||||||
|
|
|
@ -21,6 +21,7 @@ export async function createEditor(container: HTMLElement) {
|
||||||
|
|
||||||
behaviorTreeBuilderStore.btNodeView.on(async (event) => {
|
behaviorTreeBuilderStore.btNodeView.on(async (event) => {
|
||||||
setTimeout(async () => {
|
setTimeout(async () => {
|
||||||
|
console.log(event)
|
||||||
const node = new ClassicPreset.Node(event.name);
|
const node = new ClassicPreset.Node(event.name);
|
||||||
|
|
||||||
const { x, y } = areaContainer.area.pointer;
|
const { x, y } = areaContainer.area.pointer;
|
||||||
|
@ -33,6 +34,7 @@ export async function createEditor(container: HTMLElement) {
|
||||||
});
|
});
|
||||||
|
|
||||||
observer.on(() => {
|
observer.on(() => {
|
||||||
|
console.log(200)
|
||||||
behaviorTreeBuilderStore.bt(editor, areaContainer);
|
behaviorTreeBuilderStore.bt(editor, areaContainer);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ const { RefSocket, RefControl } = Presets.classic;
|
||||||
type NodeExtraData = { width?: number; height?: number };
|
type NodeExtraData = { width?: number; height?: number };
|
||||||
|
|
||||||
export const NodeStyles = styled.div<NodeExtraData & { selected: boolean; styles?: (props: any) => any }>`
|
export const NodeStyles = styled.div<NodeExtraData & { selected: boolean; styles?: (props: any) => any }>`
|
||||||
background: blue;
|
background: red;
|
||||||
border: 2px solid grey;
|
border: 2px solid grey;
|
||||||
|
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
@ -97,7 +97,6 @@ export function SequenceNode<Scheme extends ClassicScheme>(props: Props<Scheme>)
|
||||||
const selected = props.data.selected || false;
|
const selected = props.data.selected || false;
|
||||||
|
|
||||||
const { id, label, width, height } = props.data;
|
const { id, label, width, height } = props.data;
|
||||||
|
|
||||||
sortByIndex(inputs);
|
sortByIndex(inputs);
|
||||||
sortByIndex(outputs);
|
sortByIndex(outputs);
|
||||||
sortByIndex(controls);
|
sortByIndex(controls);
|
||||||
|
|
|
@ -2,8 +2,16 @@ import * as React from "react";
|
||||||
import TreeView, { EventCallback, IBranchProps, INode, LeafProps, flattenTree } from "react-accessible-treeview";
|
import TreeView, { EventCallback, IBranchProps, INode, LeafProps, flattenTree } from "react-accessible-treeview";
|
||||||
import { IFlatMetadata } from "react-accessible-treeview/dist/TreeView/utils";
|
import { IFlatMetadata } from "react-accessible-treeview/dist/TreeView/utils";
|
||||||
import { CallBackEventTarget } from "../../../../../core/extensions/extensions";
|
import { CallBackEventTarget } from "../../../../../core/extensions/extensions";
|
||||||
|
|
||||||
|
export interface ISkillView {
|
||||||
|
name: string;
|
||||||
|
children?: ISkillView[];
|
||||||
|
id?: string;
|
||||||
|
interface?: string;
|
||||||
|
out?: string;
|
||||||
|
}
|
||||||
export interface ISkillTreeProps {
|
export interface ISkillTreeProps {
|
||||||
skills: any;
|
skills: ISkillView;
|
||||||
dragEnd: CallBackEventTarget;
|
dragEnd: CallBackEventTarget;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,12 +24,12 @@ interface IRefListerProps {
|
||||||
}
|
}
|
||||||
|
|
||||||
export const RefListener = (props: IRefListerProps) => {
|
export const RefListener = (props: IRefListerProps) => {
|
||||||
const ref = React.useRef<HTMLDataElement>(null);
|
const ref = React.useRef<HTMLSpanElement>(null);
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
if (ref.current) {
|
if (ref.current) {
|
||||||
ref.current.addEventListener("dragend", (e) => {
|
ref.current.addEventListener("dragend", (e) => {
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
if (e.target.innerHTML) {
|
if (e && e.target && e.target.innerHTML) {
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
props.dragEnd(e);
|
props.dragEnd(e);
|
||||||
}
|
}
|
||||||
|
@ -36,13 +44,13 @@ export const RefListener = (props: IRefListerProps) => {
|
||||||
props.handleSelect(e);
|
props.handleSelect(e);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<span ref={ref} style={{ color: "white" }} draggable="true">
|
<span ref={ref} style={{ color: "black" }} draggable="true">
|
||||||
{props.element.name}
|
{props.element.name}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
export function SkillTree(props: ISkillTreeProps) {
|
export const SkillTree = (props: ISkillTreeProps) => {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<TreeView
|
<TreeView
|
||||||
|
@ -66,4 +74,4 @@ export function SkillTree(props: ISkillTreeProps) {
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
|
|
20
ui/src/features/skils/skills_screen.tsx
Normal file
20
ui/src/features/skils/skills_screen.tsx
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
import { MainPage } from "../../core/ui/pages/main_page";
|
||||||
|
|
||||||
|
export const SkillPath = "/skills";
|
||||||
|
export const SkillScreen = () => {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<MainPage
|
||||||
|
page={"Навыки"}
|
||||||
|
|
||||||
|
bodyChildren={
|
||||||
|
<>
|
||||||
|
<div style={{ display: "flex", width: "100%" }}>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
3
ui/src/features/skils/skills_store.tsx
Normal file
3
ui/src/features/skils/skills_store.tsx
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
export class SkillStore{
|
||||||
|
|
||||||
|
}
|
|
@ -10,7 +10,7 @@ export interface ISocketListerProps {
|
||||||
export const SocketLister = observer((props: ISocketListerProps) => {
|
export const SocketLister = observer((props: ISocketListerProps) => {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
{socketListerStore.socketHasDisconnect ? (
|
{/* {socketListerStore.socketHasDisconnect ? (
|
||||||
<ReloadIcon
|
<ReloadIcon
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
socketListerStore.reconnect();
|
socketListerStore.reconnect();
|
||||||
|
@ -25,7 +25,7 @@ export const SocketLister = observer((props: ISocketListerProps) => {
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<></>
|
<></>
|
||||||
)}
|
)} */}
|
||||||
|
|
||||||
{props.children}
|
{props.children}
|
||||||
</div>
|
</div>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue