alexander add env
This commit is contained in:
parent
50d0c4c12b
commit
b5750b12ef
12 changed files with 301 additions and 40 deletions
|
@ -29,6 +29,10 @@ export abstract class CallbackStrategyWithFileUpload {
|
||||||
abstract idValidationExpression: CoreValidation;
|
abstract idValidationExpression: CoreValidation;
|
||||||
abstract call(file: File, id: string): ResponseBase;
|
abstract call(file: File, id: string): ResponseBase;
|
||||||
}
|
}
|
||||||
|
export abstract class CallbackStrategyWithFilesUploads {
|
||||||
|
abstract chuckingFileExpressions: RegExp[];
|
||||||
|
abstract call(files: File[]): ResponseBase;
|
||||||
|
}
|
||||||
|
|
||||||
interface ISubSetFeatureRouter<T> {
|
interface ISubSetFeatureRouter<T> {
|
||||||
method: HttpMethodType;
|
method: HttpMethodType;
|
||||||
|
@ -38,7 +42,8 @@ interface ISubSetFeatureRouter<T> {
|
||||||
| CallbackStrategyWithEmpty
|
| CallbackStrategyWithEmpty
|
||||||
| CallbackStrategyWithIdQuery
|
| CallbackStrategyWithIdQuery
|
||||||
| CallBackStrategyWithQueryPage
|
| CallBackStrategyWithQueryPage
|
||||||
| CallbackStrategyWithFileUpload;
|
| CallbackStrategyWithFileUpload
|
||||||
|
| CallbackStrategyWithFilesUploads;
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class ICoreHttpController {
|
abstract class ICoreHttpController {
|
||||||
|
@ -105,6 +110,7 @@ export class CoreHttpController<V> implements ICoreHttpController {
|
||||||
await this.responseHelper(res, el.fn.call(req["files"]["file"]));
|
await this.responseHelper(res, el.fn.call(req["files"]["file"]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (el.fn instanceof CallBackStrategyWithQueryPage) {
|
if (el.fn instanceof CallBackStrategyWithQueryPage) {
|
||||||
throw Error("needs to be implimed");
|
throw Error("needs to be implimed");
|
||||||
}
|
}
|
||||||
|
@ -112,7 +118,7 @@ export class CoreHttpController<V> implements ICoreHttpController {
|
||||||
await this.responseHelper(res, el.fn.call());
|
await this.responseHelper(res, el.fn.call());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (el.fn instanceof CallbackStrategyWithFileUpload) {
|
if (el.fn instanceof CallbackStrategyWithFileUpload) {
|
||||||
if (req["files"] === undefined) {
|
if (req["files"] === undefined) {
|
||||||
res.status(400).json("need files to form-data request");
|
res.status(400).json("need files to form-data request");
|
||||||
|
@ -143,6 +149,7 @@ export class CoreHttpController<V> implements ICoreHttpController {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.responseHelper(res, el.fn.call(req["files"]["file"], req.query.id));
|
await this.responseHelper(res, el.fn.call(req["files"]["file"], req.query.id));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -0,0 +1,61 @@
|
||||||
|
import { CallbackStrategyWithFilesUploads, ResponseBase } from "../../../core/controllers/http_controller";
|
||||||
|
import { Result } from "../../../core/helpers/result";
|
||||||
|
import { CreateFileUseCase } from "../../../core/usecases/create_file_usecase";
|
||||||
|
import { ReadFileAndParseJsonUseCase } from "../../../core/usecases/read_file_and_parse_json";
|
||||||
|
export interface Parts {
|
||||||
|
name: string;
|
||||||
|
part_path: string;
|
||||||
|
material_path: string;
|
||||||
|
mass: number;
|
||||||
|
inertia: {
|
||||||
|
ixx: number;
|
||||||
|
ixy: number;
|
||||||
|
ixz: number;
|
||||||
|
iyy: number;
|
||||||
|
iyz: number;
|
||||||
|
izz: number;
|
||||||
|
};
|
||||||
|
visual: string;
|
||||||
|
collision: string;
|
||||||
|
type: string;
|
||||||
|
}
|
||||||
|
export class UploadNewEnvScenario {
|
||||||
|
call = async (
|
||||||
|
files: { name: string; file?: Buffer }[],
|
||||||
|
name: string,
|
||||||
|
inertia: number,
|
||||||
|
mass: number,
|
||||||
|
projectPath: string
|
||||||
|
): ResponseBase => {
|
||||||
|
await files.map(
|
||||||
|
async (el) => await new CreateFileUseCase().call(projectPath + `/assets/libs/objects/${name}.${el.name}`, el.file)
|
||||||
|
);
|
||||||
|
// "part_path": "parts/objects/body_down.stl",
|
||||||
|
await new CreateFileUseCase().call(
|
||||||
|
projectPath + `/parts/objects/${name}.${files.find((el) => el.name.isEqual("stl")).name}`,
|
||||||
|
files.find((el) => el.name.isEqual("stl")).file
|
||||||
|
);
|
||||||
|
return (await new ReadFileAndParseJsonUseCase().call<Parts[]>(projectPath + "/assets/parts.json")).map(
|
||||||
|
async (el) => {
|
||||||
|
el.push({
|
||||||
|
name,
|
||||||
|
inertia: {
|
||||||
|
ixx: 0.1,
|
||||||
|
ixy: 0,
|
||||||
|
ixz: 0,
|
||||||
|
iyy: 0.1,
|
||||||
|
iyz: 0,
|
||||||
|
izz: 0.1,
|
||||||
|
},
|
||||||
|
mass,
|
||||||
|
visual: `/assets/libs/objects/${name}.dae`,
|
||||||
|
collision: `/assets/libs/objects/${name}.stl`,
|
||||||
|
type: "env",
|
||||||
|
material_path: "",
|
||||||
|
part_path: `/libs/objects/${name}.stl`,
|
||||||
|
});
|
||||||
|
await new CreateFileUseCase().call(projectPath + "/assets/parts.json", Buffer.from(JSON.stringify(el), "utf8"));
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
}
|
|
@ -1,11 +1,13 @@
|
||||||
import { CrudController } from "../../core/controllers/crud_controller";
|
import { CrudController } from "../../core/controllers/crud_controller";
|
||||||
import { CreateNewProjectInstanceScenario, ProjectValidationModel } from "./domain/create_new_project_scenario";
|
import { SearchManyDataBaseModelUseCase } from "../../core/usecases/search_many_database_model_usecase";
|
||||||
|
import { CreateNewProjectInstanceScenario, ProjectValidationModel } from "./domain/create_new_project_scenario";
|
||||||
import { GetActiveProjectIdScenario } from "./domain/get_active_project_id_scenario";
|
import { GetActiveProjectIdScenario } from "./domain/get_active_project_id_scenario";
|
||||||
import { RobossemblerAssetsNetworkMapperScenario } from "./domain/robossembler_assets_network_mapper_scenario";
|
import { RobossemblerAssetsNetworkMapperScenario } from "./domain/robossembler_assets_network_mapper_scenario";
|
||||||
import { SetActiveProjectScenario } from "./domain/set_active_project_use_scenario";
|
import { SetActiveProjectScenario } from "./domain/set_active_project_use_scenario";
|
||||||
import { UploadCadFileToProjectScenario } from "./domain/upload_file_to_to_project_scenario";
|
import { UploadCadFileToProjectScenario } from "./domain/upload_file_to_to_project_scenario";
|
||||||
import { ProjectDBModel } from "./models/project_model_database_model";
|
import { UploadNewEnvScenario } from "./domain/upload_new_env_scenario";
|
||||||
|
import { IProjectModel, ProjectDBModel } from "./models/project_model_database_model";
|
||||||
|
|
||||||
export class ProjectsPresentation extends CrudController<ProjectValidationModel, typeof ProjectDBModel> {
|
export class ProjectsPresentation extends CrudController<ProjectValidationModel, typeof ProjectDBModel> {
|
||||||
constructor() {
|
constructor() {
|
||||||
super({
|
super({
|
||||||
|
@ -37,6 +39,42 @@ export class ProjectsPresentation extends CrudController<ProjectValidationModel,
|
||||||
subUrl: "assets",
|
subUrl: "assets",
|
||||||
fn: new RobossemblerAssetsNetworkMapperScenario(),
|
fn: new RobossemblerAssetsNetworkMapperScenario(),
|
||||||
});
|
});
|
||||||
|
// this.subRoutes.push({
|
||||||
|
// method: "POST",
|
||||||
|
// subUrl: "upload/env",
|
||||||
|
// fn: new UploadNewEnvScenario(),
|
||||||
|
// });
|
||||||
|
this.router.post("/projects/upload/env", async (req, res) => {
|
||||||
|
try {
|
||||||
|
} catch (error) {}
|
||||||
|
(
|
||||||
|
await new SearchManyDataBaseModelUseCase<IProjectModel>(ProjectDBModel).call(
|
||||||
|
{ isActive: true },
|
||||||
|
"is dont active projects"
|
||||||
|
)
|
||||||
|
).map(async (projectModel) => {
|
||||||
|
const { rootDir } = projectModel[0];
|
||||||
|
const files: { name: string; file?: Buffer }[] = [
|
||||||
|
{ name: "blend" },
|
||||||
|
{ name: "fbx" },
|
||||||
|
{ name: "ply" },
|
||||||
|
{ name: "glb" },
|
||||||
|
{ name: "dae" },
|
||||||
|
{ name: "fbx" },
|
||||||
|
{ name: "png" },
|
||||||
|
{ name: "stl" },
|
||||||
|
];
|
||||||
|
// @ts-ignore
|
||||||
|
const reqFiles = req.files;
|
||||||
|
|
||||||
|
files.forEach((el) => {
|
||||||
|
reqFiles[el.name].data;
|
||||||
|
el.file = reqFiles[el.name].data;
|
||||||
|
});
|
||||||
|
|
||||||
|
await new UploadNewEnvScenario().call(files, req.body.name, req.body.inertia, req.body.mass, rootDir);
|
||||||
|
return res.status(200).json("");
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ export enum HttpMethod {
|
||||||
GET = "GET",
|
GET = "GET",
|
||||||
POST = "POST",
|
POST = "POST",
|
||||||
DELETE = "DELETE",
|
DELETE = "DELETE",
|
||||||
PUT = "PUT"
|
PUT = "PUT",
|
||||||
}
|
}
|
||||||
export class HttpError extends Error {
|
export class HttpError extends Error {
|
||||||
status: number;
|
status: number;
|
||||||
|
@ -20,10 +20,7 @@ export class HttpError extends Error {
|
||||||
}
|
}
|
||||||
export class HttpRepository {
|
export class HttpRepository {
|
||||||
private server = "http://localhost:4001";
|
private server = "http://localhost:4001";
|
||||||
public async _formDataRequest<T>(method: HttpMethod, url: string, data?: any): Promise<Result<HttpError, T>> {
|
public async _formDataRequest<T>(method: HttpMethod, url: string, formData: FormData): Promise<Result<HttpError, T>> {
|
||||||
let formData = new FormData();
|
|
||||||
formData.append("file", data);
|
|
||||||
|
|
||||||
const reqInit = {
|
const reqInit = {
|
||||||
body: formData,
|
body: formData,
|
||||||
method: method,
|
method: method,
|
||||||
|
|
|
@ -56,6 +56,8 @@ export interface IMainPageProps {
|
||||||
maskLoader?: boolean;
|
maskLoader?: boolean;
|
||||||
error?: UiBaseError[];
|
error?: UiBaseError[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export const MainPage = (props: IMainPageProps) => {
|
export const MainPage = (props: IMainPageProps) => {
|
||||||
const blocksNames = [
|
const blocksNames = [
|
||||||
{ name: "Детали", path: DetailsScreenPath, icon: "Setting" },
|
{ name: "Детали", path: DetailsScreenPath, icon: "Setting" },
|
||||||
|
|
|
@ -83,7 +83,5 @@ export function CoreText(props: ITextProps) {
|
||||||
{props.text}
|
{props.text}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
// CREATE COMPONENT , HTML WRITE , JSX->JS TSX -> TS, PROPS , LIFE CYCLE , REACT HOOK, STATE MANAGMENT -> PUBSUB -> Конечный автомат -> ROUTER
|
||||||
|
|
|
@ -15,7 +15,9 @@ export class ProjectHttpRepository extends CoreHttpRepository {
|
||||||
return await this._jsonRequest<UUID>(HttpMethod.POST, "/projects", model);
|
return await this._jsonRequest<UUID>(HttpMethod.POST, "/projects", model);
|
||||||
}
|
}
|
||||||
async setProjectRootFile(file: File, projectId: string) {
|
async setProjectRootFile(file: File, projectId: string) {
|
||||||
return await this._formDataRequest(HttpMethod.POST, `/projects/upload?id=${projectId}`, file);
|
const formData = new FormData();
|
||||||
|
formData.append("file", file);
|
||||||
|
return await this._formDataRequest(HttpMethod.POST, `/projects/upload?id=${projectId}`, formData);
|
||||||
}
|
}
|
||||||
|
|
||||||
async setActivePipeline(id: string) {
|
async setActivePipeline(id: string) {
|
||||||
|
|
|
@ -1,12 +1,19 @@
|
||||||
import { HttpMethod, CoreHttpRepository } from "../../core/repository/http_repository";
|
import { HttpMethod, CoreHttpRepository } from "../../core/repository/http_repository";
|
||||||
|
import { EnvelopmentViewModel } from "./envelopment_view_model";
|
||||||
export interface Parts {
|
export interface Parts {
|
||||||
name: string;
|
name: string;
|
||||||
part_path: string;
|
part_path: string;
|
||||||
material_path: string;
|
material_path: string;
|
||||||
stlUrl: string;
|
stlUrl: string;
|
||||||
image: string;
|
image: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export class DetailsHttpRepository extends CoreHttpRepository {
|
export class DetailsHttpRepository extends CoreHttpRepository {
|
||||||
}
|
uploadNewEnv = (model: EnvelopmentViewModel) => {
|
||||||
|
const formData = new FormData();
|
||||||
|
Object.entries(model).forEach(([k, v]) => {
|
||||||
|
formData.append(k, v);
|
||||||
|
});
|
||||||
|
this._formDataRequest(HttpMethod.POST, "/projects/upload/env", formData);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
|
@ -1,8 +1,11 @@
|
||||||
import { observer } from "mobx-react-lite";
|
import { observer } from "mobx-react-lite";
|
||||||
import { DetailsStore } from "./details_store";
|
import { DetailsStore, DrawersDetailsStore } from "./details_store";
|
||||||
import { MainPage } from "../../core/ui/pages/main_page";
|
import { MainPage } from "../../core/ui/pages/main_page";
|
||||||
import React, { useEffect } from "react";
|
import React from "react";
|
||||||
import { CoreText, CoreTextType } from "../../core/ui/text/text";
|
import { CoreText, CoreTextType } from "../../core/ui/text/text";
|
||||||
|
import { CoreButton } from "../../core/ui/button/button";
|
||||||
|
import { Drawer, Upload } from "antd";
|
||||||
|
import { CoreInput } from "../../core/ui/input/input";
|
||||||
|
|
||||||
export const DetailsScreenPath = "/details";
|
export const DetailsScreenPath = "/details";
|
||||||
|
|
||||||
|
@ -20,6 +23,12 @@ export const DetailsScreen = observer(() => {
|
||||||
bodyChildren={<canvas ref={canvasRef} style={{ overflow: "hidden", width: "100%" }} />}
|
bodyChildren={<canvas ref={canvasRef} style={{ overflow: "hidden", width: "100%" }} />}
|
||||||
panelChildren={
|
panelChildren={
|
||||||
<>
|
<>
|
||||||
|
<CoreButton
|
||||||
|
filled={true}
|
||||||
|
onClick={() => store.editDrawer(DrawersDetailsStore.NewEnvelopment, true)}
|
||||||
|
text="Добавить окружение"
|
||||||
|
style={{ margin: 10 }}
|
||||||
|
/>
|
||||||
{store.detailsViewModel.map((el, i) => (
|
{store.detailsViewModel.map((el, i) => (
|
||||||
<div key={i} onClick={() => store.selectedDetail(el.label)} style={{ margin: 5, cursor: "pointer" }}>
|
<div key={i} onClick={() => store.selectedDetail(el.label)} style={{ margin: 5, cursor: "pointer" }}>
|
||||||
<div style={el.selected ? { width: "100%", background: "#E8DEF8", borderRadius: 100 } : {}}>
|
<div style={el.selected ? { width: "100%", background: "#E8DEF8", borderRadius: 100 } : {}}>
|
||||||
|
@ -31,6 +40,37 @@ export const DetailsScreen = observer(() => {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
|
<Drawer
|
||||||
|
title={store.titleDrawer}
|
||||||
|
destroyOnClose={true}
|
||||||
|
onClose={() => store.editDrawer(DrawersDetailsStore.NewEnvelopment, false)}
|
||||||
|
open={store.drawers.find((el) => el.name === DrawersDetailsStore.NewEnvelopment)?.status}
|
||||||
|
>
|
||||||
|
<CoreInput label="имя" onChange={(text) => store.updateForm({ name: text })} />
|
||||||
|
<Upload onChange={(file) => store.updateForm({ blend: file.file.originFileObj })}>
|
||||||
|
<CoreButton filled={true} text="blend" />
|
||||||
|
</Upload>
|
||||||
|
<Upload onChange={(file) => store.updateForm({ ply: file.file.originFileObj })}>
|
||||||
|
<CoreButton filled={true} text="ply" />
|
||||||
|
</Upload>
|
||||||
|
<Upload onChange={(file) => store.updateForm({ stl: file.file.originFileObj })}>
|
||||||
|
<CoreButton filled={true} text="stl" />
|
||||||
|
</Upload>
|
||||||
|
<Upload onChange={(file) => store.updateForm({ glb: file.file.originFileObj })}>
|
||||||
|
<CoreButton filled={true} text="glb" />
|
||||||
|
</Upload>
|
||||||
|
<Upload onChange={(file) => store.updateForm({ dae: file.file.originFileObj })}>
|
||||||
|
<CoreButton filled={true} text="dae" />
|
||||||
|
</Upload>
|
||||||
|
<Upload onChange={(file) => store.updateForm({ fbx: file.file.originFileObj })}>
|
||||||
|
<CoreButton filled={true} text="fbx" />
|
||||||
|
</Upload>
|
||||||
|
<Upload onChange={(file) => store.updateForm({ png: file.file.originFileObj })}>
|
||||||
|
<CoreButton filled={true} text="png" />
|
||||||
|
</Upload>
|
||||||
|
<div style={{ height: 10 }} />
|
||||||
|
<CoreButton text="Сохранить" onClick={() => store.uploadEnv()} />
|
||||||
|
</Drawer>
|
||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -1,27 +1,32 @@
|
||||||
import makeAutoObservable from "mobx-store-inheritance";
|
import makeAutoObservable from "mobx-store-inheritance";
|
||||||
import { CoreError, UiErrorState } from "../../core/store/base_store";
|
import { CoreError, UiDrawerFormState } from "../../core/store/base_store";
|
||||||
import { NavigateFunction } from "react-router-dom";
|
import { NavigateFunction } from "react-router-dom";
|
||||||
import { DetailsHttpRepository, Parts } from "./details_http_repository";
|
import { DetailsHttpRepository, Parts } from "./details_http_repository";
|
||||||
import { DetailsThreeRepository } from "./details_three_repository";
|
import { DetailsThreeRepository } from "./details_three_repository";
|
||||||
|
import { EnvelopmentViewModel } from "./envelopment_view_model";
|
||||||
|
import { message } from "antd";
|
||||||
|
|
||||||
interface IDetailViewModel {
|
interface IDetailViewModel {
|
||||||
label: string;
|
label: string;
|
||||||
selected: boolean;
|
selected: boolean;
|
||||||
httpUrl: string;
|
httpUrl: string;
|
||||||
}
|
}
|
||||||
|
export enum DrawersDetailsStore {
|
||||||
|
NewEnvelopment = "Новое окружение",
|
||||||
|
}
|
||||||
|
|
||||||
|
export class DetailsStore extends UiDrawerFormState<EnvelopmentViewModel, CoreError> {
|
||||||
export class DetailsStore extends UiErrorState<CoreError> {
|
viewModel: EnvelopmentViewModel = EnvelopmentViewModel.empty();
|
||||||
detailsViewModel: IDetailViewModel[] = [];
|
detailsViewModel: IDetailViewModel[] = [];
|
||||||
parts: Parts[] = [];
|
parts: Parts[] = [];
|
||||||
detailsHttpRepository: DetailsHttpRepository = new DetailsHttpRepository();
|
detailsHttpRepository: DetailsHttpRepository = new DetailsHttpRepository();
|
||||||
detailsThreeRepository?: DetailsThreeRepository;
|
detailsThreeRepository?: DetailsThreeRepository;
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super(DrawersDetailsStore);
|
||||||
makeAutoObservable(this);
|
makeAutoObservable(this);
|
||||||
this.init();
|
this.init();
|
||||||
}
|
}
|
||||||
errorHandingStrategy = (error: CoreError) => { };
|
errorHandingStrategy = (error: CoreError) => {};
|
||||||
init = async (navigate?: NavigateFunction | undefined): Promise<void> => {
|
init = async (navigate?: NavigateFunction | undefined): Promise<void> => {
|
||||||
await this.mapOk("parts", this.detailsHttpRepository.getAssetsActiveProject());
|
await this.mapOk("parts", this.detailsHttpRepository.getAssetsActiveProject());
|
||||||
this.detailsViewModel = this.parts.map((el) => {
|
this.detailsViewModel = this.parts.map((el) => {
|
||||||
|
@ -41,16 +46,24 @@ export class DetailsStore extends UiErrorState<CoreError> {
|
||||||
this.detailsViewModel.map((el) => {
|
this.detailsViewModel.map((el) => {
|
||||||
if (el.label.match(label)) {
|
if (el.label.match(label)) {
|
||||||
el.selected = true;
|
el.selected = true;
|
||||||
this.detailsThreeRepository?.deleteAllObjectsScene()
|
this.detailsThreeRepository?.deleteAllObjectsScene();
|
||||||
this.detailsThreeRepository?.loadHttpAndPreview(el.httpUrl, el.label, () => { })
|
this.detailsThreeRepository?.loadHttpAndPreview(el.httpUrl, el.label, () => {});
|
||||||
return el;
|
return el;
|
||||||
}
|
}
|
||||||
return el
|
return el;
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
loadScene = async (ref: HTMLCanvasElement) => {
|
loadScene = async (ref: HTMLCanvasElement) => {
|
||||||
this.detailsThreeRepository = new DetailsThreeRepository(ref, () => { });
|
this.detailsThreeRepository = new DetailsThreeRepository(ref, () => {});
|
||||||
this.detailsThreeRepository.render();
|
this.detailsThreeRepository.render();
|
||||||
};
|
};
|
||||||
|
uploadEnv = () =>
|
||||||
|
this.viewModel.isValid().fold(
|
||||||
|
async (model) => {
|
||||||
|
await this.detailsHttpRepository.uploadNewEnv(model);
|
||||||
|
await this.init();
|
||||||
|
this.editDrawer(DrawersDetailsStore.NewEnvelopment, false);
|
||||||
|
},
|
||||||
|
async (e) => message.error(e)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
32
ui/src/features/details/envelopment_view_model.ts
Normal file
32
ui/src/features/details/envelopment_view_model.ts
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
import { Result } from "../../core/helper/result";
|
||||||
|
|
||||||
|
export class EnvelopmentViewModel {
|
||||||
|
public name: string;
|
||||||
|
public blend?: File;
|
||||||
|
public ply?: File;
|
||||||
|
public glb?: File;
|
||||||
|
public dae?: File;
|
||||||
|
public stl?: File;
|
||||||
|
public fbx?: File;
|
||||||
|
public png?: File;
|
||||||
|
public mass: number = 0;
|
||||||
|
public inertia = {
|
||||||
|
ixx: 0.1,
|
||||||
|
ixy: 0,
|
||||||
|
ixz: 0,
|
||||||
|
iyy: 0.1,
|
||||||
|
iyz: 0,
|
||||||
|
izz: 0.1,
|
||||||
|
};
|
||||||
|
|
||||||
|
constructor(name: string) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
static empty = () => new EnvelopmentViewModel("");
|
||||||
|
isValid = (): Result<string, EnvelopmentViewModel> => {
|
||||||
|
if (this.name.isEmpty()) {
|
||||||
|
return Result.error("name is empty");
|
||||||
|
}
|
||||||
|
return Result.ok(this);
|
||||||
|
};
|
||||||
|
}
|
|
@ -2,31 +2,95 @@
|
||||||
{
|
{
|
||||||
"name": "body_down",
|
"name": "body_down",
|
||||||
"part_path": "parts/objects/body_down.stl",
|
"part_path": "parts/objects/body_down.stl",
|
||||||
"material_path": ""
|
"material_path": "",
|
||||||
|
"mass": 100,
|
||||||
|
"inertia": {
|
||||||
|
"ixx": 0.1,
|
||||||
|
"ixy": 0,
|
||||||
|
"ixz": 0,
|
||||||
|
"iyy": 0.1,
|
||||||
|
"iyz": 0,
|
||||||
|
"izz": 0.1
|
||||||
|
},
|
||||||
|
"visual": ".dae",
|
||||||
|
"collision": ".stl"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "sol_gear",
|
"name": "sol_gear",
|
||||||
"part_path": "parts/objects/sol_gear.stl",
|
"part_path": "parts/objects/sol_gear.stl",
|
||||||
"material_path": ""
|
"material_path": "",
|
||||||
|
"mass": 100,
|
||||||
|
"inertia": {
|
||||||
|
"ixx": 0.1,
|
||||||
|
"ixy": 0,
|
||||||
|
"ixz": 0,
|
||||||
|
"iyy": 0.1,
|
||||||
|
"iyz": 0,
|
||||||
|
"izz": 0.1
|
||||||
|
},
|
||||||
|
"visual": ".dae",
|
||||||
|
"collision": ".stl"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "output_shaft",
|
"name": "output_shaft",
|
||||||
"part_path": "parts/objects/output_shaft.stl",
|
"part_path": "parts/objects/output_shaft.stl",
|
||||||
"material_path": ""
|
"material_path": "",
|
||||||
|
"mass": 100,
|
||||||
|
"inertia": {
|
||||||
|
"ixx": 0.1,
|
||||||
|
"ixy": 0,
|
||||||
|
"ixz": 0,
|
||||||
|
"iyy": 0.1,
|
||||||
|
"iyz": 0,
|
||||||
|
"izz": 0.1
|
||||||
|
},
|
||||||
|
"visual": ".dae",
|
||||||
|
"collision": ".stl"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "planet_gear",
|
"name": "planet_gear",
|
||||||
"part_path": "parts/objects/planet_gear.stl",
|
"part_path": "parts/objects/planet_gear.stl",
|
||||||
"material_path": ""
|
"material_path": "",
|
||||||
|
"mass": 100,
|
||||||
|
"inertia": {
|
||||||
|
"ixx": 0.1,
|
||||||
|
"ixy": 0,
|
||||||
|
"ixz": 0,
|
||||||
|
"iyy": 0.1,
|
||||||
|
"iyz": 0,
|
||||||
|
"izz": 0.1
|
||||||
|
},
|
||||||
|
"visual": ".dae",
|
||||||
|
"collision": ".stl"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "body_up",
|
"name": "body_up",
|
||||||
"part_path": "parts/objects/body_up.stl",
|
"part_path": "parts/objects/body_up.stl",
|
||||||
"material_path": ""
|
"material_path": "",
|
||||||
|
"inertia": {
|
||||||
|
"ixx": 0.1,
|
||||||
|
"ixy": 0,
|
||||||
|
"ixz": 0,
|
||||||
|
"iyy": 0.1,
|
||||||
|
"iyz": 0,
|
||||||
|
"izz": 0.1
|
||||||
|
},
|
||||||
|
"visual": ".dae",
|
||||||
|
"collision": ".stl"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "bolt",
|
"name": "bolt",
|
||||||
"part_path": "parts/objects/bolt.stl",
|
"part_path": "parts/objects/bolt.stl",
|
||||||
"material_path": ""
|
"material_path": "",
|
||||||
|
"inertia": {
|
||||||
|
"ixx": 0.1,
|
||||||
|
"ixy": 0,
|
||||||
|
"ixz": 0,
|
||||||
|
"iyy": 0.1,
|
||||||
|
"iyz": 0,
|
||||||
|
"izz": 0.1
|
||||||
|
},
|
||||||
|
"visual": ".dae",
|
||||||
|
"collision": ".stl"
|
||||||
}
|
}
|
||||||
]
|
]
|
Loading…
Add table
Add a link
Reference in a new issue