process
This commit is contained in:
parent
7ff6165882
commit
ae9842d5e1
61 changed files with 929 additions and 433 deletions
|
@ -4,7 +4,7 @@
|
||||||
"description": "",
|
"description": "",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"pretest": "tsc",
|
"test:dev": "NODE_ENV=test_dev tsc-watch --onSuccess 'ts-node ./build/test/test.js'",
|
||||||
"test:unit": "NODE_ENV=unit tsc-watch --onSuccess 'ts-node ./build/test/test.js'",
|
"test:unit": "NODE_ENV=unit tsc-watch --onSuccess 'ts-node ./build/test/test.js'",
|
||||||
"test:e2e": "NODE_ENV=e2e tsc-watch --onSuccess 'ts-node ./build/test/test.js'",
|
"test:e2e": "NODE_ENV=e2e tsc-watch --onSuccess 'ts-node ./build/test/test.js'",
|
||||||
"dev": "NODE_ENV=dev tsc-watch --onSuccess 'ts-node ./build/src/main.js'"
|
"dev": "NODE_ENV=dev tsc-watch --onSuccess 'ts-node ./build/src/main.js'"
|
||||||
|
|
|
@ -85,7 +85,7 @@ export class App extends TypedEvent<ServerStatus> {
|
||||||
this.app.use(cors());
|
this.app.use(cors());
|
||||||
this.app.use(express.json());
|
this.app.use(express.json());
|
||||||
this.app.use(express.urlencoded({ extended: true }));
|
this.app.use(express.urlencoded({ extended: true }));
|
||||||
this.app.use(express.static("public"));
|
this.app.use(express.static(App.staticFilesStoreDir()));
|
||||||
|
|
||||||
this.app.use(
|
this.app.use(
|
||||||
fileUpload({
|
fileUpload({
|
||||||
|
@ -118,6 +118,7 @@ export class App extends TypedEvent<ServerStatus> {
|
||||||
static staticFilesStoreDir = () => {
|
static staticFilesStoreDir = () => {
|
||||||
const dir = dirname(__filename);
|
const dir = dirname(__filename);
|
||||||
const rootDir = dir.slice(0, dir.length - 20);
|
const rootDir = dir.slice(0, dir.length - 20);
|
||||||
|
|
||||||
return rootDir + "public/";
|
return rootDir + "public/";
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,11 +2,11 @@ import { validationModelMiddleware } from "../middlewares/validation_model";
|
||||||
import { Result } from "../helpers/result";
|
import { Result } from "../helpers/result";
|
||||||
import { Router, Request, Response } from "express";
|
import { Router, Request, Response } from "express";
|
||||||
import { IRouteModel, Routes } from "../interfaces/router";
|
import { IRouteModel, Routes } from "../interfaces/router";
|
||||||
|
import { CoreValidation } from "../validations/core_validation";
|
||||||
|
|
||||||
export type HttpMethodType = "GET" | "POST" | "PUT" | "DELETE" | "PATCH" | "PATCH" | "HEAD";
|
export type HttpMethodType = "GET" | "POST" | "PUT" | "DELETE" | "PATCH" | "PATCH" | "HEAD";
|
||||||
|
|
||||||
export type ResponseBase = Promise<Result<any, any>>;
|
export type ResponseBase = Promise<Result<any, any>>;
|
||||||
|
|
||||||
export abstract class CallbackStrategyWithEmpty {
|
export abstract class CallbackStrategyWithEmpty {
|
||||||
abstract call(): ResponseBase;
|
abstract call(): ResponseBase;
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,7 @@ export abstract class CallbackStrategyWithValidationModel<V> {
|
||||||
abstract call(a: V): ResponseBase;
|
abstract call(a: V): ResponseBase;
|
||||||
}
|
}
|
||||||
export abstract class CallbackStrategyWithIdQuery {
|
export abstract class CallbackStrategyWithIdQuery {
|
||||||
abstract idValidationExpression: RegExp | null;
|
abstract idValidationExpression: CoreValidation;
|
||||||
abstract call(id: string): ResponseBase;
|
abstract call(id: string): ResponseBase;
|
||||||
}
|
}
|
||||||
export abstract class CallBackStrategyWithQueryPage {
|
export abstract class CallBackStrategyWithQueryPage {
|
||||||
|
@ -84,7 +84,24 @@ export class CoreHttpController<V> implements ICoreHttpController {
|
||||||
throw Error("needs to be implimed");
|
throw Error("needs to be implimed");
|
||||||
}
|
}
|
||||||
if (el.fn instanceof CallbackStrategyWithIdQuery) {
|
if (el.fn instanceof CallbackStrategyWithIdQuery) {
|
||||||
throw Error("needs to be implimed");
|
if (req.query.id === undefined) {
|
||||||
|
res.status(400).json("request query id is null, need query id ?id={id:String}");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (el.fn.idValidationExpression !== undefined) {
|
||||||
|
if (!el.fn.idValidationExpression.regExp.test(req.query.id)) {
|
||||||
|
res
|
||||||
|
.status(400)
|
||||||
|
.json(
|
||||||
|
`request query id must fall under the pattern: ${el.fn.idValidationExpression.regExp} message: ${el.fn.idValidationExpression.message} `
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
await this.responseHelper(res, el.fn.call(req.query.id));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
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");
|
||||||
|
|
|
@ -20,6 +20,7 @@ declare global {
|
||||||
lastElement(): string;
|
lastElement(): string;
|
||||||
hasPattern(pattern: string): boolean;
|
hasPattern(pattern: string): boolean;
|
||||||
hasNoPattern(pattern: string): boolean;
|
hasNoPattern(pattern: string): boolean;
|
||||||
|
pathNormalize(): string;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
export const extensions = () => {
|
export const extensions = () => {
|
||||||
|
|
|
@ -5,6 +5,11 @@ export const StringExtensions = () => {
|
||||||
return this.length === 0;
|
return this.length === 0;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
if ("".pathNormalize === undefined) {
|
||||||
|
String.prototype.pathNormalize = function () {
|
||||||
|
return this.replace("//", "/");
|
||||||
|
};
|
||||||
|
}
|
||||||
if ("".isNotEmpty === undefined) {
|
if ("".isNotEmpty === undefined) {
|
||||||
// eslint-disable-next-line no-extend-native
|
// eslint-disable-next-line no-extend-native
|
||||||
String.prototype.isNotEmpty = function () {
|
String.prototype.isNotEmpty = function () {
|
||||||
|
@ -27,3 +32,6 @@ export const StringExtensions = () => {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
// python3 /Users/idontsudo/framework/path.py --path /Users/idontsudo/webservice/server/build/public/0a3422cc-f2e3-4abc-87d8-ae13b8b6d26d/ --env /Users/idontsudo/framework/cad_generation/env.json
|
||||||
|
// python3 /Users/idontsudo/framework/path.py --path /Users/idontsudo/webservice/server/build/public/0a3422cc-f2e3-4abc-87d8-ae13b8b6d26d/ --env /Users/idontsudo/framework/cad_generation/env.json
|
||||||
|
// /Users/idontsudo/Desktop/FreeCAD.app/Contents/MacOS/FreeCAD /Users/idontsudo/framework/cad_generation/main.py
|
||||||
|
|
|
@ -17,7 +17,9 @@ export interface WorkerDataExec {
|
||||||
process.on("message", async (message) => {
|
process.on("message", async (message) => {
|
||||||
const workerData = message as WorkerDataExec;
|
const workerData = message as WorkerDataExec;
|
||||||
if (workerData.type == WorkerType.SPAWN) {
|
if (workerData.type == WorkerType.SPAWN) {
|
||||||
const subprocess = cp.spawn(workerData.command, workerData.cliArgs, {
|
// Maybe error
|
||||||
|
// const subprocess = cp.spawn(workerData.command, workerData.cliArgs, {
|
||||||
|
const subprocess = cp.spawn(workerData.command, {
|
||||||
cwd: workerData.execPath,
|
cwd: workerData.execPath,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,6 @@
|
||||||
import { RequestHandler } from "express";
|
import { RequestHandler } from "express";
|
||||||
|
|
||||||
export const validationMiddleware = (
|
export const validationMiddleware = (): RequestHandler => {
|
||||||
type: any,
|
|
||||||
value = "body",
|
|
||||||
skipMissingProperties = false,
|
|
||||||
whitelist = true,
|
|
||||||
forbidNonWhitelisted = true
|
|
||||||
): RequestHandler => {
|
|
||||||
// TODO:(IDONTSUDO) need TOKEN
|
// TODO:(IDONTSUDO) need TOKEN
|
||||||
// return nextTick
|
// return nextTick
|
||||||
return (req, res, next) => {};
|
return (req, res, next) => {};
|
||||||
|
|
|
@ -4,10 +4,15 @@ extensions();
|
||||||
|
|
||||||
export class ExecError extends Error {
|
export class ExecError extends Error {
|
||||||
static isExecError(e: any): ExecError | void {
|
static isExecError(e: any): ExecError | void {
|
||||||
if ("type" in e && "script" in e && "unixTime" in e && "error" in e) {
|
try {
|
||||||
return new ExecError(e.type, e.event, e.data);
|
if (e) {
|
||||||
|
if ("type" in e && "script" in e && "unixTime" in e && "error" in e) {
|
||||||
|
return new ExecError(e.type, e.event, e.data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
}
|
}
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
script: string;
|
script: string;
|
||||||
unixTime: number;
|
unixTime: number;
|
||||||
|
@ -34,10 +39,15 @@ export class SpawnError extends Error {
|
||||||
this.unixTime = Date.now();
|
this.unixTime = Date.now();
|
||||||
}
|
}
|
||||||
static isError(errorType: any): SpawnError | void {
|
static isError(errorType: any): SpawnError | void {
|
||||||
if ("command" in errorType && "error" in errorType && "execPath" in errorType) {
|
try {
|
||||||
return new SpawnError(errorType.command, errorType.execPath, errorType.error);
|
if (errorType) {
|
||||||
|
if ("command" in errorType && "error" in errorType && "execPath" in errorType) {
|
||||||
|
return new SpawnError(errorType.command, errorType.execPath, errorType.error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
}
|
}
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,9 +10,14 @@ export class ExecutorResult {
|
||||||
this.data = data;
|
this.data = data;
|
||||||
}
|
}
|
||||||
static isExecutorResult(value: any): void | ExecutorResult {
|
static isExecutorResult(value: any): void | ExecutorResult {
|
||||||
if ("type" in value && "event" in value && "data" in value) {
|
try {
|
||||||
return new ExecutorResult(value.type, value.event, value.data);
|
if (value) {
|
||||||
|
if ("type" in value && "event" in value && "data" in value) {
|
||||||
|
return new ExecutorResult(value.type, value.event, value.data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
}
|
}
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
131
server/src/core/models/robossembler_assets.ts
Normal file
131
server/src/core/models/robossembler_assets.ts
Normal file
|
@ -0,0 +1,131 @@
|
||||||
|
import { IsEnum, IsNumber, IsOptional, IsString, ValidateNested } from "class-validator";
|
||||||
|
import { Type } from "class-transformer";
|
||||||
|
|
||||||
|
export enum AssetsType {
|
||||||
|
Asset = "asset",
|
||||||
|
Light = "light",
|
||||||
|
}
|
||||||
|
|
||||||
|
export class Gravity {
|
||||||
|
@IsNumber()
|
||||||
|
x: number;
|
||||||
|
@IsNumber()
|
||||||
|
y: number;
|
||||||
|
@IsNumber()
|
||||||
|
z: number;
|
||||||
|
}
|
||||||
|
export class Pose {
|
||||||
|
@IsNumber()
|
||||||
|
x: number;
|
||||||
|
@IsNumber()
|
||||||
|
y: number;
|
||||||
|
@IsNumber()
|
||||||
|
z: number;
|
||||||
|
@IsNumber()
|
||||||
|
roll: number;
|
||||||
|
@IsNumber()
|
||||||
|
pitch: number;
|
||||||
|
@IsNumber()
|
||||||
|
yaw: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class Instance {
|
||||||
|
@IsString()
|
||||||
|
model_name: string;
|
||||||
|
@IsString()
|
||||||
|
model_id: string;
|
||||||
|
@IsString()
|
||||||
|
id: string;
|
||||||
|
@ValidateNested()
|
||||||
|
@Type(() => Pose)
|
||||||
|
pose: Pose;
|
||||||
|
@IsNumber()
|
||||||
|
scale: number;
|
||||||
|
@IsEnum(AssetsType)
|
||||||
|
type: AssetsType;
|
||||||
|
@IsOptional()
|
||||||
|
@IsString()
|
||||||
|
parent?: string;
|
||||||
|
@IsOptional()
|
||||||
|
@IsString()
|
||||||
|
light_type?: string;
|
||||||
|
@IsOptional()
|
||||||
|
@IsString()
|
||||||
|
intencity?: number;
|
||||||
|
@IsOptional()
|
||||||
|
@IsString()
|
||||||
|
diffuse?: number[];
|
||||||
|
@IsOptional()
|
||||||
|
@IsNumber()
|
||||||
|
spot_angle?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class Asset {
|
||||||
|
@IsString()
|
||||||
|
name: string;
|
||||||
|
@IsString()
|
||||||
|
ixx: string;
|
||||||
|
@IsString()
|
||||||
|
ixy: string;
|
||||||
|
@IsString()
|
||||||
|
ixz: string;
|
||||||
|
@IsString()
|
||||||
|
iyy: string;
|
||||||
|
@IsString()
|
||||||
|
izz: string;
|
||||||
|
@IsString()
|
||||||
|
mass: string;
|
||||||
|
@IsString()
|
||||||
|
posX: string;
|
||||||
|
@IsString()
|
||||||
|
posY: string;
|
||||||
|
@IsString()
|
||||||
|
posZ: string;
|
||||||
|
@IsString()
|
||||||
|
eulerX: string;
|
||||||
|
@IsString()
|
||||||
|
eulerY: string;
|
||||||
|
@IsString()
|
||||||
|
eulerZ: string;
|
||||||
|
@IsString()
|
||||||
|
iyz: string;
|
||||||
|
@IsString()
|
||||||
|
meshPath: string;
|
||||||
|
@IsString()
|
||||||
|
friction: string;
|
||||||
|
@IsString()
|
||||||
|
centerMassX: string;
|
||||||
|
@IsString()
|
||||||
|
centerMassY: string;
|
||||||
|
@IsString()
|
||||||
|
centerMassZ: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class Physics {
|
||||||
|
@IsString()
|
||||||
|
engine_name: string;
|
||||||
|
@Type(() => Gravity)
|
||||||
|
gravity: Gravity;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class RobossemblerAssets {
|
||||||
|
@ValidateNested()
|
||||||
|
@Type(() => Asset)
|
||||||
|
assets: Asset[];
|
||||||
|
|
||||||
|
@ValidateNested()
|
||||||
|
@Type(() => Instance)
|
||||||
|
instances: Instance[];
|
||||||
|
|
||||||
|
@IsOptional()
|
||||||
|
@ValidateNested()
|
||||||
|
@Type(() => Physics)
|
||||||
|
physics: Physics;
|
||||||
|
convertLocalPathsToServerPaths(server_address: string): RobossemblerAssets {
|
||||||
|
this.assets = this.assets.map((el) => {
|
||||||
|
el.meshPath = server_address + el.meshPath;
|
||||||
|
return el;
|
||||||
|
});
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
3
server/src/core/models/static_files.ts
Normal file
3
server/src/core/models/static_files.ts
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
export enum StaticFiles {
|
||||||
|
robossembler_assets = "robossembler_assets.json",
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
import { ClassConstructor, plainToInstance } from "class-transformer";
|
||||||
|
import { ReadFileAndParseJsonUseCase } from "../usecases/read_file_and_parse_json";
|
||||||
|
import { Result } from "../helpers/result";
|
||||||
|
import { validate, ValidationError } from "class-validator";
|
||||||
|
const skipMissingProperties = false,
|
||||||
|
whitelist = true,
|
||||||
|
forbidNonWhitelisted = true;
|
||||||
|
|
||||||
|
export class ReadingJsonFileAndConvertingToInstanceClass<T> {
|
||||||
|
model: ClassConstructor<T>;
|
||||||
|
constructor(cls: ClassConstructor<T>) {
|
||||||
|
this.model = cls;
|
||||||
|
}
|
||||||
|
call = async (path: string): Promise<Result<string, T>> => {
|
||||||
|
const result = await new ReadFileAndParseJsonUseCase().call(path);
|
||||||
|
if (result.isFailure()) {
|
||||||
|
return result.forward();
|
||||||
|
}
|
||||||
|
const json = result.value;
|
||||||
|
const model = plainToInstance(this.model, json);
|
||||||
|
const errors = await validate(model as object, { skipMissingProperties, whitelist, forbidNonWhitelisted });
|
||||||
|
if (errors.length > 0) {
|
||||||
|
const message = errors.map((error: ValidationError) => Object.values(error.constraints)).join(", ");
|
||||||
|
return Result.error(message);
|
||||||
|
} else {
|
||||||
|
return Result.ok(model as T);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
|
@ -4,7 +4,7 @@ import {
|
||||||
} from "../../features/project_instance/models/project_instance_database_model";
|
} from "../../features/project_instance/models/project_instance_database_model";
|
||||||
import { pipelineRealTimeService } from "../../features/realtime/realtime_presentation";
|
import { pipelineRealTimeService } from "../../features/realtime/realtime_presentation";
|
||||||
import { App } from "../controllers/app";
|
import { App } from "../controllers/app";
|
||||||
import { CreateFolderUseCase } from "../usecases/crete_folder_usecase";
|
import { CreateFolderUseCase } from "../usecases/create_folder_usecase";
|
||||||
import { SearchDataBaseModelUseCase } from "../usecases/search_database_model_usecase";
|
import { SearchDataBaseModelUseCase } from "../usecases/search_database_model_usecase";
|
||||||
|
|
||||||
export class SetLastActivePipelineToRealTimeServiceScenario {
|
export class SetLastActivePipelineToRealTimeServiceScenario {
|
||||||
|
@ -12,12 +12,11 @@ export class SetLastActivePipelineToRealTimeServiceScenario {
|
||||||
const result = await new SearchDataBaseModelUseCase<IProjectInstanceModel>(ProjectInstanceDbModel).call({
|
const result = await new SearchDataBaseModelUseCase<IProjectInstanceModel>(ProjectInstanceDbModel).call({
|
||||||
isActive: true,
|
isActive: true,
|
||||||
});
|
});
|
||||||
|
await result.map(async (el) => {
|
||||||
if (result.isSuccess()) {
|
const projectModel = el;
|
||||||
const projectModel = result.value;
|
const projectPath = App.staticFilesStoreDir() + projectModel.rootDir + "/";
|
||||||
const projectPath = App.staticFilesStoreDir() + result.value.rootDir + "/";
|
|
||||||
await new CreateFolderUseCase().call(projectPath);
|
await new CreateFolderUseCase().call(projectPath);
|
||||||
pipelineRealTimeService.setPipelineDependency(projectModel.project.pipelines, projectPath, projectModel._id);
|
pipelineRealTimeService.setPipelineDependency(projectModel.project.pipelines, projectPath, projectModel._id);
|
||||||
}
|
});
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,57 +21,61 @@ export class ExecutorProgramService
|
||||||
|
|
||||||
constructor(execPath: string, maxTime: number | null = null) {
|
constructor(execPath: string, maxTime: number | null = null) {
|
||||||
super();
|
super();
|
||||||
this.execPath = execPath;
|
this.execPath = execPath.pathNormalize();
|
||||||
this.maxTime = maxTime;
|
this.maxTime = maxTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async workerExecuted(command: string, workerType: WorkerType, args: Array<string> | undefined = undefined) {
|
private async workerExecuted(command: string, workerType: WorkerType, args: Array<string> | undefined = undefined) {
|
||||||
cluster.setupPrimary({
|
try {
|
||||||
exec: __dirname + "/../helpers/worker_computed.js",
|
cluster.setupPrimary({
|
||||||
});
|
exec: __dirname + "/../helpers/worker_computed.js",
|
||||||
|
});
|
||||||
|
|
||||||
const worker = cluster.fork();
|
const worker = cluster.fork();
|
||||||
|
|
||||||
await delay(300);
|
await delay(300);
|
||||||
|
|
||||||
this.worker = worker;
|
this.worker = worker;
|
||||||
|
|
||||||
const workerDataExec: WorkerDataExec = {
|
const workerDataExec: WorkerDataExec = {
|
||||||
command: command,
|
command: command,
|
||||||
execPath: this.execPath,
|
execPath: this.execPath,
|
||||||
type: workerType,
|
type: workerType,
|
||||||
cliArgs: args,
|
cliArgs: args,
|
||||||
};
|
};
|
||||||
worker.send(workerDataExec);
|
worker.send(workerDataExec);
|
||||||
worker.on("message", (e) => {
|
worker.on("message", (e) => {
|
||||||
const spawnError = SpawnError.isError(e);
|
const spawnError = SpawnError.isError(e);
|
||||||
|
|
||||||
if (spawnError instanceof SpawnError) {
|
if (spawnError instanceof SpawnError) {
|
||||||
this.emit(Result.error(spawnError));
|
this.emit(Result.error(spawnError));
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
const execError = ExecError.isExecError(e);
|
||||||
|
|
||||||
|
if (execError instanceof ExecError) {
|
||||||
|
this.emit(Result.error(execError));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const executorResult = ExecutorResult.isExecutorResult(e);
|
||||||
|
if (executorResult instanceof ExecutorResult) {
|
||||||
|
this.emit(Result.ok(executorResult));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (this.maxTime != null) {
|
||||||
|
setTimeout(() => {
|
||||||
|
this.worker.kill();
|
||||||
|
this.emit(
|
||||||
|
Result.error(
|
||||||
|
WorkerType.EXEC ? new ExecError(command, "timeout err") : new SpawnError(command, "timeout err")
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}, this.maxTime!);
|
||||||
}
|
}
|
||||||
|
} catch (error) {
|
||||||
const executorResult = ExecutorResult.isExecutorResult(e);
|
console.log(error);
|
||||||
|
|
||||||
if (executorResult instanceof ExecutorResult) {
|
|
||||||
this.emit(Result.ok(executorResult));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const execError = ExecError.isExecError(e);
|
|
||||||
|
|
||||||
if (execError instanceof ExecError) {
|
|
||||||
this.emit(Result.error(execError));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
if (this.maxTime != null) {
|
|
||||||
setTimeout(() => {
|
|
||||||
this.worker.kill();
|
|
||||||
this.emit(
|
|
||||||
Result.error(WorkerType.EXEC ? new ExecError(command, "timeout err") : new SpawnError(command, "timeout err"))
|
|
||||||
);
|
|
||||||
}, this.maxTime!);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@ import { ExecError } from "../models/exec_error_model";
|
||||||
import { ExecutorResult } from "../models/executor_result";
|
import { ExecutorResult } from "../models/executor_result";
|
||||||
import { ActivePipeline } from "../models/active_pipeline_model";
|
import { ActivePipeline } from "../models/active_pipeline_model";
|
||||||
import { IPipeline } from "../models/process_model";
|
import { IPipeline } from "../models/process_model";
|
||||||
import { Iteration } from "./stack_service";
|
import { Iteration, StackService } from "./stack_service";
|
||||||
|
|
||||||
export class PipelineRealTimeService extends TypedEvent<ActivePipeline> {
|
export class PipelineRealTimeService extends TypedEvent<ActivePipeline> {
|
||||||
status: ActivePipeline;
|
status: ActivePipeline;
|
||||||
|
@ -65,9 +65,10 @@ export class PipelineRealTimeService extends TypedEvent<ActivePipeline> {
|
||||||
this.status["path"] = path;
|
this.status["path"] = path;
|
||||||
}
|
}
|
||||||
runPipeline(): void {
|
runPipeline(): void {
|
||||||
// const stack = new StackService(this.pipelineModels, this.path);
|
const stack = new StackService(this.pipelineModels, this.status.path);
|
||||||
// this.status["pipelineIsRunning"] = true;
|
|
||||||
// stack.on(this.pipelineSubscriber);
|
this.status["pipelineIsRunning"] = true;
|
||||||
// stack.call();
|
stack.on(this.pipelineSubscriber);
|
||||||
|
stack.call();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@ import { Trigger } from "../../features/triggers/models/trigger_database_model";
|
||||||
|
|
||||||
export interface Iteration {
|
export interface Iteration {
|
||||||
hashes: IHashesCache | null;
|
hashes: IHashesCache | null;
|
||||||
process: IPipeline;
|
pipeline: IPipeline;
|
||||||
result?: ExecError | SpawnError | ExecutorResult;
|
result?: ExecError | SpawnError | ExecutorResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,12 +36,12 @@ export class StackService extends TypedEvent<Iteration[]> implements IStackServi
|
||||||
el = this.commandHandler(el);
|
el = this.commandHandler(el);
|
||||||
this.callStack.push({
|
this.callStack.push({
|
||||||
hashes: null,
|
hashes: null,
|
||||||
process: el,
|
pipeline: el,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private commandHandler(processMetaData: IPipeline) {
|
private commandHandler(processMetaData: IPipeline) {
|
||||||
processMetaData.process.command = processMetaData.process.command.replace("$PATH", this.path);
|
processMetaData.process.command = processMetaData.process.command.replace("$PATH", this.path).pathNormalize();
|
||||||
return processMetaData;
|
return processMetaData;
|
||||||
}
|
}
|
||||||
public async call() {
|
public async call() {
|
||||||
|
@ -52,10 +52,7 @@ export class StackService extends TypedEvent<Iteration[]> implements IStackServi
|
||||||
}
|
}
|
||||||
async execStack(stackNumber: number, stackLayer: Iteration): Promise<void | boolean> {
|
async execStack(stackNumber: number, stackLayer: Iteration): Promise<void | boolean> {
|
||||||
const executorService = new ExecutorProgramService(this.path);
|
const executorService = new ExecutorProgramService(this.path);
|
||||||
executorService.call(stackLayer.process.process.type, stackLayer.process.process.command);
|
executorService.call(stackLayer.pipeline.process.type, stackLayer.pipeline.process.command);
|
||||||
executorService.on((e) => {
|
|
||||||
console.log(e);
|
|
||||||
});
|
|
||||||
const filesChangeNotifierService = new FilesChangeNotifierService(this.path);
|
const filesChangeNotifierService = new FilesChangeNotifierService(this.path);
|
||||||
|
|
||||||
filesChangeNotifierService.call();
|
filesChangeNotifierService.call();
|
||||||
|
@ -73,7 +70,7 @@ export class StackService extends TypedEvent<Iteration[]> implements IStackServi
|
||||||
result.map(async (el) => {
|
result.map(async (el) => {
|
||||||
this.callStack.at(stackNumber).result = el;
|
this.callStack.at(stackNumber).result = el;
|
||||||
this.callStack.at(stackNumber).hashes = filesChangeNotifierService.hashes;
|
this.callStack.at(stackNumber).hashes = filesChangeNotifierService.hashes;
|
||||||
(await this.triggerExec(stackLayer.process.trigger, stackNumber)).map(() => {
|
(await this.triggerExec(stackLayer.pipeline.trigger, stackNumber)).map(() => {
|
||||||
filesChangeNotifierService.cancel();
|
filesChangeNotifierService.cancel();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { App } from "../controllers/app";
|
import { App } from "../controllers/app";
|
||||||
import { FileSystemRepository } from "../repository/file_system_repository";
|
import { FileSystemRepository } from "../repository/file_system_repository";
|
||||||
import { CreateFolderUseCase } from "./crete_folder_usecase";
|
import { CreateFolderUseCase } from "./create_folder_usecase";
|
||||||
|
|
||||||
export class CheckAndCreateStaticFilesFolderUseCase {
|
export class CheckAndCreateStaticFilesFolderUseCase {
|
||||||
fileSystemRepository: FileSystemRepository;
|
fileSystemRepository: FileSystemRepository;
|
||||||
|
|
|
@ -9,7 +9,7 @@ export class CreateFolderUseCase {
|
||||||
call = async (path: string): Promise<Result<Error, string>> => {
|
call = async (path: string): Promise<Result<Error, string>> => {
|
||||||
try {
|
try {
|
||||||
if (await this.fileSystemRepository.dirIsExists(path)) {
|
if (await this.fileSystemRepository.dirIsExists(path)) {
|
||||||
return Result.error(new Error("createFolderUseCase create dir "));
|
return Result.ok("ok");
|
||||||
}
|
}
|
||||||
await this.fileSystemRepository.createDir(path);
|
await this.fileSystemRepository.createDir(path);
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
export class FindPredicateModelAndUpdateDatabaseModelUseCase<D> {
|
||||||
|
databaseModel: D;
|
||||||
|
|
||||||
|
constructor(model) {
|
||||||
|
this.databaseModel = model;
|
||||||
|
}
|
||||||
|
async call(conditions: Partial<D>, update: Partial<D>) {
|
||||||
|
const dbModel = this.databaseModel as any;
|
||||||
|
dbModel.findOneAndUpdate(conditions, update);
|
||||||
|
}
|
||||||
|
}
|
7
server/src/core/usecases/get_server_address_usecase.ts
Normal file
7
server/src/core/usecases/get_server_address_usecase.ts
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
import { Result } from "../helpers/result";
|
||||||
|
|
||||||
|
export class GetServerAddressUseCase {
|
||||||
|
call = (): Result<string, string> => {
|
||||||
|
return Result.ok("http://localhost:4001");
|
||||||
|
};
|
||||||
|
}
|
21
server/src/core/usecases/read_file_and_parse_json.ts
Normal file
21
server/src/core/usecases/read_file_and_parse_json.ts
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
import { Result } from "../helpers/result";
|
||||||
|
import { FileSystemRepository } from "../repository/file_system_repository";
|
||||||
|
|
||||||
|
export class ReadFileAndParseJsonUseCase {
|
||||||
|
fileSystemRepository: FileSystemRepository;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.fileSystemRepository = new FileSystemRepository();
|
||||||
|
}
|
||||||
|
async call<T>(path: string): Promise<Result<string, T>> {
|
||||||
|
try {
|
||||||
|
if (RegExp(path).test("^(.+)/([^/]+)$")) {
|
||||||
|
return Result.error(`ReadFileAndParseJsonUseCase got the bad way: ${path}`);
|
||||||
|
}
|
||||||
|
const file = await this.fileSystemRepository.readFileAsync(path);
|
||||||
|
return Result.ok(JSON.parse(file.toString()));
|
||||||
|
} catch (error) {
|
||||||
|
return Result.error(`ReadFileAndParseJsonUseCase is not json type file parse path:${path}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
4
server/src/core/validations/core_validation.ts
Normal file
4
server/src/core/validations/core_validation.ts
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
export abstract class CoreValidation {
|
||||||
|
abstract regExp: RegExp;
|
||||||
|
abstract message: string;
|
||||||
|
}
|
6
server/src/core/validations/mongo_id_validation.ts
Normal file
6
server/src/core/validations/mongo_id_validation.ts
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
import { CoreValidation } from "./core_validation";
|
||||||
|
|
||||||
|
export class MongoIdValidation extends CoreValidation {
|
||||||
|
regExp = RegExp("^[0-9a-fA-F]{24}$");
|
||||||
|
message = "is do not mongo db object uuid";
|
||||||
|
}
|
|
@ -1,7 +1,7 @@
|
||||||
import { App } from "../../../core/controllers/app";
|
import { App } from "../../../core/controllers/app";
|
||||||
import { Result } from "../../../core/helpers/result";
|
import { Result } from "../../../core/helpers/result";
|
||||||
import { CreateDataBaseModelUseCase } from "../../../core/usecases/create_database_model_usecase";
|
import { CreateDataBaseModelUseCase } from "../../../core/usecases/create_database_model_usecase";
|
||||||
import { CreateFolderUseCase } from "../../../core/usecases/crete_folder_usecase";
|
import { CreateFolderUseCase } from "../../../core/usecases/create_folder_usecase";
|
||||||
import { ProjectInstanceDbModel } from "../models/project_instance_database_model";
|
import { ProjectInstanceDbModel } from "../models/project_instance_database_model";
|
||||||
import { ProjectInstanceValidationModel } from "../models/project_instance_validation_model";
|
import { ProjectInstanceValidationModel } from "../models/project_instance_validation_model";
|
||||||
import { v4 as uuidv4 } from "uuid";
|
import { v4 as uuidv4 } from "uuid";
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
import { CallbackStrategyWithEmpty, ResponseBase } from "../../../core/controllers/http_controller";
|
||||||
|
import { Result } from "../../../core/helpers/result";
|
||||||
|
import { RobossemblerAssets } from "../../../core/models/robossembler_assets";
|
||||||
|
import { StaticFiles } from "../../../core/models/static_files";
|
||||||
|
import { ReadingJsonFileAndConvertingToInstanceClass } from "../../../core/scenarios/read_file_and_json_to_plain_instance_class_scenario";
|
||||||
|
import { GetServerAddressUseCase } from "../../../core/usecases/get_server_address_usecase";
|
||||||
|
import { PipelineStatusUseCase } from "../../realtime/domain/pipeline_status_usecase";
|
||||||
|
|
||||||
|
export class RobossemblerAssetsNetworkMapperScenario extends CallbackStrategyWithEmpty {
|
||||||
|
async call(): ResponseBase {
|
||||||
|
try {
|
||||||
|
const result = await new PipelineStatusUseCase().call();
|
||||||
|
|
||||||
|
return await result.map(async (activeInstanceModel) => {
|
||||||
|
return (
|
||||||
|
await new ReadingJsonFileAndConvertingToInstanceClass(RobossemblerAssets).call(
|
||||||
|
`${activeInstanceModel.path}${StaticFiles.robossembler_assets}`
|
||||||
|
)
|
||||||
|
).map((robossemblerAssets) => {
|
||||||
|
return new GetServerAddressUseCase().call().map((address) => {
|
||||||
|
return Result.ok(
|
||||||
|
robossemblerAssets.convertLocalPathsToServerPaths(`${address}/${activeInstanceModel.projectUUID}`)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
return Result.error(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
import { App } from "../../../core/controllers/app";
|
||||||
|
import { CallbackStrategyWithIdQuery, ResponseBase } from "../../../core/controllers/http_controller";
|
||||||
|
import { Result } from "../../../core/helpers/result";
|
||||||
|
import { CreateFolderUseCase } from "../../../core/usecases/create_folder_usecase";
|
||||||
|
import { FindPredicateModelAndUpdateDatabaseModelUseCase } from "../../../core/usecases/find_and_update_database_model_usecase";
|
||||||
|
import { ReadByIdDataBaseModelUseCase } from "../../../core/usecases/read_by_id_database_model_usecase";
|
||||||
|
import { UpdateDataBaseModelUseCase } from "../../../core/usecases/update_database_model_usecase";
|
||||||
|
import { MongoIdValidation } from "../../../core/validations/mongo_id_validation";
|
||||||
|
import { IProjectInstanceModel, ProjectInstanceDbModel } from "../models/project_instance_database_model";
|
||||||
|
|
||||||
|
export class SetActiveProjectScenario extends CallbackStrategyWithIdQuery {
|
||||||
|
idValidationExpression = new MongoIdValidation();
|
||||||
|
|
||||||
|
async call(id: string): ResponseBase {
|
||||||
|
const result = await new ReadByIdDataBaseModelUseCase<IProjectInstanceModel>(ProjectInstanceDbModel).call(id);
|
||||||
|
|
||||||
|
if (result.isFailure()) {
|
||||||
|
return result.forward();
|
||||||
|
}
|
||||||
|
|
||||||
|
const model = result.value;
|
||||||
|
return (await new CreateFolderUseCase().call(App.staticFilesStoreDir() + model.rootDir)).map(async () => {
|
||||||
|
model.isActive = true;
|
||||||
|
new FindPredicateModelAndUpdateDatabaseModelUseCase(ProjectInstanceDbModel).call({}, {});
|
||||||
|
return (await new UpdateDataBaseModelUseCase(ProjectInstanceDbModel).call(model)).map(() => {
|
||||||
|
return Result.ok(`project ${id} is active`);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,8 @@
|
||||||
import { CrudController } from "../../core/controllers/crud_controller";
|
import { CrudController } from "../../core/controllers/crud_controller";
|
||||||
|
|
||||||
import { CreateNewProjectInstanceScenario } from "./domain/create_new_project_scenario";
|
import { CreateNewProjectInstanceScenario } from "./domain/create_new_project_scenario";
|
||||||
|
import { RobossemblerAssetsNetworkMapperScenario } from "./domain/robossembler_assets_network_mapper_scenario";
|
||||||
|
import { SetActiveProjectScenario } from "./domain/set_active_project_use_scenario";
|
||||||
import { UploadCadFileToProjectScenario } from "./domain/upload_file_to_to_project_scenario";
|
import { UploadCadFileToProjectScenario } from "./domain/upload_file_to_to_project_scenario";
|
||||||
import { ProjectInstanceDbModel } from "./models/project_instance_database_model";
|
import { ProjectInstanceDbModel } from "./models/project_instance_database_model";
|
||||||
import { ProjectInstanceValidationModel } from "./models/project_instance_validation_model";
|
import { ProjectInstanceValidationModel } from "./models/project_instance_validation_model";
|
||||||
|
@ -14,12 +17,25 @@ export class ProjectInstancePresentation extends CrudController<
|
||||||
url: "project_instance",
|
url: "project_instance",
|
||||||
databaseModel: ProjectInstanceDbModel,
|
databaseModel: ProjectInstanceDbModel,
|
||||||
});
|
});
|
||||||
|
|
||||||
super.post(new CreateNewProjectInstanceScenario().call);
|
super.post(new CreateNewProjectInstanceScenario().call);
|
||||||
|
|
||||||
|
this.subRoutes.push({
|
||||||
|
method: "POST",
|
||||||
|
subUrl: "set/active/project",
|
||||||
|
fn: new SetActiveProjectScenario(),
|
||||||
|
});
|
||||||
|
|
||||||
this.subRoutes.push({
|
this.subRoutes.push({
|
||||||
method: "POST",
|
method: "POST",
|
||||||
subUrl: "upload",
|
subUrl: "upload",
|
||||||
fn: new UploadCadFileToProjectScenario(),
|
fn: new UploadCadFileToProjectScenario(),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.subRoutes.push({
|
||||||
|
method: "GET",
|
||||||
|
subUrl: "assets",
|
||||||
|
fn: new RobossemblerAssetsNetworkMapperScenario(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@ export class PipelineStatusUseCase {
|
||||||
if (status.projectUUID !== null) {
|
if (status.projectUUID !== null) {
|
||||||
return Result.ok(status);
|
return Result.ok(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (status.projectUUID === null) {
|
if (status.projectUUID === null) {
|
||||||
return Result.error(new Error("pipelineRealTimeService does not have an active project instance"));
|
return Result.error(new Error("pipelineRealTimeService does not have an active project instance"));
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,39 +1,55 @@
|
||||||
import { App } from "../../../core/controllers/app";
|
import { App } from "../../../core/controllers/app";
|
||||||
import { Result } from "../../../core/helpers/result";
|
import { Result } from "../../../core/helpers/result";
|
||||||
|
import { IPipeline } from "../../../core/models/process_model";
|
||||||
import { ReadByIdDataBaseModelUseCase } from "../../../core/usecases/read_by_id_database_model_usecase";
|
import { ReadByIdDataBaseModelUseCase } from "../../../core/usecases/read_by_id_database_model_usecase";
|
||||||
import { UpdateDataBaseModelUseCase } from "../../../core/usecases/update_database_model_usecase";
|
import { PipelineValidationModel } from "../../pipelines/models/pipeline_validation_model";
|
||||||
import {
|
import {
|
||||||
IProjectInstanceModel,
|
IProjectInstanceModel,
|
||||||
ProjectInstanceDbModel,
|
ProjectInstanceDbModel,
|
||||||
} from "../../project_instance/models/project_instance_database_model";
|
} from "../../project_instance/models/project_instance_database_model";
|
||||||
import { RealTimeValidationModel, pipelineRealTimeService } from "../realtime_presentation";
|
import { pipelineRealTimeService } from "../realtime_presentation";
|
||||||
|
import { PipelineStatusUseCase } from "./pipeline_status_usecase";
|
||||||
|
|
||||||
|
const mongoPipelineModelMapper = (el: PipelineValidationModel): IPipeline => {
|
||||||
|
const mapObj: IPipeline = {
|
||||||
|
process: {
|
||||||
|
type: el.process.type,
|
||||||
|
command: el.process.command,
|
||||||
|
isGenerating: Boolean(el.process.isGenerating),
|
||||||
|
isLocaleCode: Boolean(el.process.isLocaleCode),
|
||||||
|
issueType: el.process.issueType,
|
||||||
|
},
|
||||||
|
trigger: {
|
||||||
|
type: el.trigger.type,
|
||||||
|
value: el.trigger.value.map((el) => String(el)),
|
||||||
|
},
|
||||||
|
env: null,
|
||||||
|
stackGenerateType: el.stackGenerateType,
|
||||||
|
};
|
||||||
|
return mapObj;
|
||||||
|
};
|
||||||
export class RunInstancePipelineUseCase {
|
export class RunInstancePipelineUseCase {
|
||||||
async call(model: RealTimeValidationModel): Promise<Result<Error, any>> {
|
async call(): Promise<Result<Error, any>> {
|
||||||
const { id } = model;
|
const r = await new PipelineStatusUseCase().call();
|
||||||
|
if (r.isFailure()) {
|
||||||
|
return r;
|
||||||
|
}
|
||||||
const readByIdDataBaseModelUseCase = await new ReadByIdDataBaseModelUseCase<IProjectInstanceModel>(
|
const readByIdDataBaseModelUseCase = await new ReadByIdDataBaseModelUseCase<IProjectInstanceModel>(
|
||||||
ProjectInstanceDbModel
|
ProjectInstanceDbModel
|
||||||
).call(id);
|
).call(r.value.projectUUID);
|
||||||
|
|
||||||
if (readByIdDataBaseModelUseCase.isFailure()) {
|
if (readByIdDataBaseModelUseCase.isFailure()) {
|
||||||
return readByIdDataBaseModelUseCase.forward();
|
return readByIdDataBaseModelUseCase.forward();
|
||||||
}
|
}
|
||||||
|
|
||||||
const projectModel = readByIdDataBaseModelUseCase.value;
|
const projectModel = readByIdDataBaseModelUseCase.value;
|
||||||
projectModel.isActive = true;
|
const resultMapper = projectModel.project.pipelines.map((el) => mongoPipelineModelMapper(el));
|
||||||
|
|
||||||
const updateDataBaseModelUseCase = await new UpdateDataBaseModelUseCase<IProjectInstanceModel, any>(
|
|
||||||
ProjectInstanceDbModel
|
|
||||||
).call(projectModel);
|
|
||||||
|
|
||||||
if (updateDataBaseModelUseCase.isFailure()) {
|
|
||||||
return updateDataBaseModelUseCase.forward();
|
|
||||||
}
|
|
||||||
pipelineRealTimeService.setPipelineDependency(
|
pipelineRealTimeService.setPipelineDependency(
|
||||||
projectModel.project.pipelines,
|
resultMapper,
|
||||||
App.staticFilesStoreDir() + projectModel.rootDir + "/",
|
App.staticFilesStoreDir() + projectModel.rootDir + "/",
|
||||||
projectModel._id
|
projectModel._id
|
||||||
);
|
);
|
||||||
|
|
||||||
pipelineRealTimeService.runPipeline();
|
pipelineRealTimeService.runPipeline();
|
||||||
|
|
||||||
return Result.ok({ status: "ok" });
|
return Result.ok({ status: "ok" });
|
||||||
|
|
|
@ -4,7 +4,7 @@ import { delay } from "../../src/core/helpers/delay";
|
||||||
import { assert, dirname__ } from "../test";
|
import { assert, dirname__ } from "../test";
|
||||||
import { mockSimplePipeline } from "../model/mock_pipelines";
|
import { mockSimplePipeline } from "../model/mock_pipelines";
|
||||||
import { FileSystemRepository } from "../../src/core/repository/file_system_repository";
|
import { FileSystemRepository } from "../../src/core/repository/file_system_repository";
|
||||||
import { CreateFolderUseCase } from "../../src/core/usecases/crete_folder_usecase";
|
import { CreateFolderUseCase } from "../../src/core/usecases/create_folder_usecase";
|
||||||
|
|
||||||
abstract class IStackServiceTest {
|
abstract class IStackServiceTest {
|
||||||
abstract test(): Promise<boolean>;
|
abstract test(): Promise<boolean>;
|
||||||
|
|
|
@ -37,19 +37,19 @@ const init = async () => {
|
||||||
|
|
||||||
const unitTest = async () => {
|
const unitTest = async () => {
|
||||||
await init();
|
await init();
|
||||||
// await new ExecutorProgramServiceTest(dirname__).test();
|
await new ExecutorProgramServiceTest(dirname__).test();
|
||||||
// await new FilesChangerTest(dirname__).test();
|
await new FilesChangerTest(dirname__).test();
|
||||||
await new StackServiceTest(dirname__).test();
|
await new StackServiceTest(dirname__).test();
|
||||||
// await new TriggerServiceTest().test();
|
await new TriggerServiceTest().test();
|
||||||
// await new CreateDataBaseModelUseCaseTest().test();
|
await new CreateDataBaseModelUseCaseTest().test();
|
||||||
// await new CreateDataBaseModelUseCaseTest().test();
|
await new CreateDataBaseModelUseCaseTest().test();
|
||||||
// await new DeleteDataBaseModelUseCaseTest().test();
|
await new DeleteDataBaseModelUseCaseTest().test();
|
||||||
// await new ReadDataBaseModelUseCaseTest().test();
|
await new ReadDataBaseModelUseCaseTest().test();
|
||||||
// await new UpdateDataBaseModelUseCaseTest().test();
|
await new UpdateDataBaseModelUseCaseTest().test();
|
||||||
|
|
||||||
// for await (const usecase of tests) {
|
for await (const usecase of tests) {
|
||||||
// testCore.assert(await new usecase().test(), usecase.name);
|
testCore.assert(await new usecase().test(), usecase.name);
|
||||||
// }
|
}
|
||||||
};
|
};
|
||||||
const presentationCrudControllers = [new TriggerPresentation()];
|
const presentationCrudControllers = [new TriggerPresentation()];
|
||||||
const e2eTest = async () => {
|
const e2eTest = async () => {
|
||||||
|
|
|
@ -2,7 +2,8 @@ import { ArrayExtensions } from "./array";
|
||||||
import { MapExtensions } from "./map";
|
import { MapExtensions } from "./map";
|
||||||
import { StringExtensions } from "./string";
|
import { StringExtensions } from "./string";
|
||||||
|
|
||||||
export type CallBackFunction = <T>(value: T) => void;
|
export type CallBackVoidFunction = <T>(value: T) => void;
|
||||||
|
export type CallBackStringVoidFunction = (value: string) => void;
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
interface Array<T> {
|
interface Array<T> {
|
||||||
|
@ -17,7 +18,7 @@ declare global {
|
||||||
isEmpty(): boolean;
|
isEmpty(): boolean;
|
||||||
}
|
}
|
||||||
interface Map<K, V> {
|
interface Map<K, V> {
|
||||||
addValueOrMakeCallback(key: K, value: V, callBack: CallBackFunction): void;
|
addValueOrMakeCallback(key: K, value: V, callBack: CallBackVoidFunction): void;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
export const extensions = () => {
|
export const extensions = () => {
|
||||||
|
|
6
ui/src/core/model/ui_base_error.ts
Normal file
6
ui/src/core/model/ui_base_error.ts
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
export class UiBaseError {
|
||||||
|
text: string;
|
||||||
|
constructor(text: string) {
|
||||||
|
this.text = text;
|
||||||
|
}
|
||||||
|
}
|
|
@ -16,18 +16,32 @@ 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>> {
|
||||||
|
let formData = new FormData();
|
||||||
|
formData.append("file", data);
|
||||||
|
|
||||||
public async jsonRequest<T>(
|
const reqInit = {
|
||||||
method: HttpMethod,
|
body: formData,
|
||||||
url: string,
|
method: method,
|
||||||
data?: any
|
};
|
||||||
): Promise<Result<HttpError, T>> {
|
|
||||||
|
if (data !== undefined) {
|
||||||
|
reqInit["body"] = data;
|
||||||
|
}
|
||||||
|
const response = await fetch(this.server + url, reqInit);
|
||||||
|
if (response.status !== 200) {
|
||||||
|
throw Result.error(new Error(await response.json()));
|
||||||
|
}
|
||||||
|
return Result.ok(response.text as T);
|
||||||
|
}
|
||||||
|
public async jsonRequest<T>(method: HttpMethod, url: string, data?: any): Promise<Result<HttpError, T>> {
|
||||||
try {
|
try {
|
||||||
const reqInit = {
|
const reqInit = {
|
||||||
body: data,
|
body: data,
|
||||||
method: method,
|
method: method,
|
||||||
headers: { "Content-Type": "application/json" },
|
headers: { "Content-Type": "application/json" },
|
||||||
};
|
};
|
||||||
|
console.log(reqInit);
|
||||||
if (data !== undefined) {
|
if (data !== undefined) {
|
||||||
reqInit["body"] = JSON.stringify(data);
|
reqInit["body"] = JSON.stringify(data);
|
||||||
}
|
}
|
||||||
|
@ -37,28 +51,25 @@ export class HttpRepository {
|
||||||
return Result.error(new HttpError(this.server + url, response.status));
|
return Result.error(new HttpError(this.server + url, response.status));
|
||||||
}
|
}
|
||||||
|
|
||||||
return Result.ok(await response.json());
|
return Result.ok(await response.json());
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return Result.error(new HttpError(error, 0));
|
return Result.error(new HttpError(error, 0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async request<T>(
|
public async request<T>(method: HttpMethod, url: string, data?: any): Promise<Result<HttpError, T>> {
|
||||||
method: HttpMethod,
|
|
||||||
url: string,
|
|
||||||
data?: any
|
|
||||||
): Promise<T> {
|
|
||||||
const reqInit = {
|
const reqInit = {
|
||||||
body: data,
|
body: data,
|
||||||
method: method,
|
method: method,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (data !== undefined) {
|
if (data !== undefined) {
|
||||||
reqInit["body"] = data;
|
reqInit["body"] = data;
|
||||||
}
|
}
|
||||||
const response = await fetch(this.server + url, reqInit);
|
const response = await fetch(this.server + url, reqInit);
|
||||||
if (response.status !== 200) {
|
if (response.status !== 200) {
|
||||||
throw new Error(await response.json());
|
throw Result.error(new Error(await response.json()));
|
||||||
}
|
}
|
||||||
return response.json();
|
return Result.ok(response.text as T);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,18 +21,17 @@ import {
|
||||||
CreateProcessScreen,
|
CreateProcessScreen,
|
||||||
CreateProcessScreenPath,
|
CreateProcessScreenPath,
|
||||||
} from "../../features/create_process/presentation/create_process_screen";
|
} from "../../features/create_process/presentation/create_process_screen";
|
||||||
import { ProjectRepository } from "../../features/all_projects/data/project_repository";
|
|
||||||
import {
|
import {
|
||||||
CreateProjectInstancePath,
|
CreateProjectInstancePath,
|
||||||
CreateProjectInstanceScreen,
|
CreateProjectInstanceScreen,
|
||||||
} from "../../features/create_project_instance/create_project_instance";
|
} from "../../features/create_project_instance/create_project_instance";
|
||||||
|
import { SceneManger, SceneManagerPath } from "../../features/scene_manager/scene_manager";
|
||||||
|
|
||||||
const idURL = ":id";
|
const idURL = ":id";
|
||||||
|
|
||||||
export const router = createBrowserRouter([
|
export const router = createBrowserRouter([
|
||||||
{
|
{
|
||||||
path: AllProjectScreenPath,
|
path: AllProjectScreenPath,
|
||||||
loader: new ProjectRepository().loader,
|
|
||||||
element: <AllProjectScreen />,
|
element: <AllProjectScreen />,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -63,4 +62,8 @@ export const router = createBrowserRouter([
|
||||||
path: CreateProjectInstancePath + idURL,
|
path: CreateProjectInstancePath + idURL,
|
||||||
element: <CreateProjectInstanceScreen />,
|
element: <CreateProjectInstanceScreen />,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: SceneManagerPath + idURL,
|
||||||
|
element: <SceneManger />,
|
||||||
|
},
|
||||||
]);
|
]);
|
||||||
|
|
|
@ -1,22 +1,49 @@
|
||||||
// TODO(IDONTSUDO): нужно переписать все запросы под BaseStore
|
// TODO(IDONTSUDO): нужно переписать все запросы под BaseStore
|
||||||
|
|
||||||
import { Result } from "../helper/result";
|
import { Result } from "../helper/result";
|
||||||
|
import { UiBaseError } from "../model/ui_base_error";
|
||||||
|
import { HttpError } from "../repository/http_repository";
|
||||||
|
|
||||||
export class BaseStore {
|
export type CoreError = HttpError | Error;
|
||||||
|
|
||||||
|
export abstract class UiLoader {
|
||||||
isLoading = false;
|
isLoading = false;
|
||||||
isError = false;
|
|
||||||
|
|
||||||
async loadingHelper<T>(callBack: Promise<Result<any, T>>) {
|
async loadingHelper<T>(callBack: Promise<Result<any, T>>) {
|
||||||
this.isLoading = true;
|
this.isLoading = true;
|
||||||
|
|
||||||
const result = await callBack;
|
const result = await callBack;
|
||||||
if (result.isFailure()) {
|
if (result.isFailure()) {
|
||||||
this.isError = true;
|
|
||||||
this.isLoading = false;
|
this.isLoading = false;
|
||||||
|
this.errorHandingStrategy(result.error);
|
||||||
return result.forward();
|
return result.forward();
|
||||||
}
|
}
|
||||||
|
|
||||||
this.isLoading = false;
|
this.isLoading = false;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
abstract errorHandingStrategy: (error?: any) => void;
|
||||||
|
|
||||||
|
mapOk = async <T>(property: string, callBack: Promise<Result<CoreError, T>>) => {
|
||||||
|
return (
|
||||||
|
(await this.loadingHelper(callBack))
|
||||||
|
// eslint-disable-next-line array-callback-return
|
||||||
|
.map((el) => {
|
||||||
|
// @ts-ignore
|
||||||
|
this[property] = el;
|
||||||
|
})
|
||||||
|
);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
export class SimpleErrorState extends UiLoader {
|
||||||
|
errorHandingStrategy = () => {
|
||||||
|
this.isError = true;
|
||||||
|
};
|
||||||
|
isError = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
export abstract class UiErrorState<T> extends UiLoader {
|
||||||
|
abstract errorHandingStrategy: (error: T) => void;
|
||||||
|
abstract init(): Promise<any>;
|
||||||
|
dispose() {}
|
||||||
|
errors: UiBaseError[] = [];
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,27 +1,16 @@
|
||||||
import { redirect } from "react-router-dom";
|
import { ActivePipeline } from "../../../core/model/active_pipeline";
|
||||||
import { ActivePipeline } from "../../../core/model/active_pipiline";
|
import { HttpMethod, HttpRepository } from "../../../core/repository/http_repository";
|
||||||
import {
|
|
||||||
HttpMethod,
|
|
||||||
HttpRepository,
|
|
||||||
} from "../../../core/repository/http_repository";
|
|
||||||
import { PipelineInstanceScreenPath } from "../../pipeline_instance_main_screen/pipeline_instance_screen";
|
|
||||||
import { IProjectModel } from "../model/project_model";
|
import { IProjectModel } from "../model/project_model";
|
||||||
|
|
||||||
export class ProjectRepository extends HttpRepository {
|
export class ProjectRepository extends HttpRepository {
|
||||||
async getAllProject() {
|
async getAllProject() {
|
||||||
return this.jsonRequest<IProjectModel[]>(HttpMethod.GET, "/project");
|
return this.jsonRequest<IProjectModel[]>(HttpMethod.GET, "/project_instance");
|
||||||
}
|
}
|
||||||
|
|
||||||
async getActivePipeline() {
|
async getActivePipeline() {
|
||||||
return this.jsonRequest<ActivePipeline>(HttpMethod.GET, "/realtime");
|
return this.jsonRequest<ActivePipeline>(HttpMethod.GET, "/realtime");
|
||||||
}
|
}
|
||||||
loader = async () => {
|
async setActivePipeline(id: string) {
|
||||||
const result = await this.getActivePipeline();
|
return this.jsonRequest(HttpMethod.POST, `/project_instance/set/active/project?id=${id}`);
|
||||||
|
}
|
||||||
// if (result.isSuccess() && result.value.projectUUID !== null) {
|
|
||||||
// return redirect(PipelineInstanceScreenPath + result.value.projectUUID);
|
|
||||||
// }
|
|
||||||
|
|
||||||
return null;
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,13 +4,18 @@ import { ProjectRepository } from "../data/project_repository";
|
||||||
import { LoadPage } from "../../../core/ui/pages/load_page";
|
import { LoadPage } from "../../../core/ui/pages/load_page";
|
||||||
import { observer } from "mobx-react-lite";
|
import { observer } from "mobx-react-lite";
|
||||||
import { SelectProjectScreenPath } from "../../select_project/presentation/select_project";
|
import { SelectProjectScreenPath } from "../../select_project/presentation/select_project";
|
||||||
|
import { useNavigate } from "react-router-dom";
|
||||||
|
import { Button } from "antd";
|
||||||
|
import { PipelineInstanceScreenPath } from "../../pipeline_instance_main_screen/pipeline_instance_screen";
|
||||||
|
|
||||||
export const AllProjectScreenPath = "/";
|
export const AllProjectScreenPath = "/";
|
||||||
|
|
||||||
export const AllProjectScreen: React.FunctionComponent = observer(() => {
|
export const AllProjectScreen: React.FunctionComponent = observer(() => {
|
||||||
const [allProjectStore] = React.useState(
|
const [allProjectStore] = React.useState(() => new AllProjectStore(new ProjectRepository()));
|
||||||
() => new AllProjectStore(new ProjectRepository())
|
const navigate = useNavigate();
|
||||||
);
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
allProjectStore.init();
|
||||||
|
}, [allProjectStore]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
@ -23,8 +28,33 @@ export const AllProjectScreen: React.FunctionComponent = observer(() => {
|
||||||
isLoading={allProjectStore.isLoading}
|
isLoading={allProjectStore.isLoading}
|
||||||
children={
|
children={
|
||||||
<div>
|
<div>
|
||||||
|
<h1>Projects</h1>
|
||||||
|
<h5 style={{ backgroundColor: "ButtonShadow" }}>
|
||||||
|
<Button
|
||||||
|
onClick={() => {
|
||||||
|
navigate(PipelineInstanceScreenPath + allProjectStore.activePipeline?.projectUUID ?? "");
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Project main panel
|
||||||
|
</Button>
|
||||||
|
{allProjectStore.activePipeline?.projectUUID ?? "loading"}
|
||||||
|
</h5>
|
||||||
{allProjectStore.projectsModels?.map((el) => {
|
{allProjectStore.projectsModels?.map((el) => {
|
||||||
return <div>{el.description}</div>;
|
return (
|
||||||
|
<div style={{ margin: "10px", backgroundColor: "Highlight" }}>
|
||||||
|
<Button
|
||||||
|
onClick={() => {
|
||||||
|
allProjectStore.setPipelineActive(el._id ?? "").then(() => {
|
||||||
|
allProjectStore.init();
|
||||||
|
navigate(PipelineInstanceScreenPath + el._id ?? "");
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
set active project
|
||||||
|
</Button>
|
||||||
|
<div style={{ margin: "10px", display: "contents" }}> {el.description}</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,24 +1,62 @@
|
||||||
import makeAutoObservable from "mobx-store-inheritance";
|
import makeAutoObservable from "mobx-store-inheritance";
|
||||||
import { ProjectRepository } from "../data/project_repository";
|
import { ProjectRepository } from "../data/project_repository";
|
||||||
import { IProjectModel } from "../model/project_model";
|
import { IProjectModel } from "../model/project_model";
|
||||||
import { BaseStore } from "../../../core/store/base_store";
|
import { SimpleErrorState } from "../../../core/store/base_store";
|
||||||
|
import { ActivePipeline } from "../../../core/model/active_pipeline";
|
||||||
|
|
||||||
export class AllProjectStore extends BaseStore {
|
interface IProjectView {
|
||||||
|
isActive: boolean;
|
||||||
|
description: string;
|
||||||
|
id: string;
|
||||||
|
}
|
||||||
|
export class ProjectView {
|
||||||
|
isActive: boolean;
|
||||||
|
description: string;
|
||||||
|
id: string;
|
||||||
|
constructor(view: IProjectView) {
|
||||||
|
this.isActive = view.isActive;
|
||||||
|
this.description = view.description;
|
||||||
|
this.id = view.id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export class AllProjectStore extends SimpleErrorState {
|
||||||
projectsModels?: IProjectModel[];
|
projectsModels?: IProjectModel[];
|
||||||
repository: ProjectRepository;
|
repository: ProjectRepository;
|
||||||
redirect = false;
|
activePipeline?: ActivePipeline;
|
||||||
constructor(repository: ProjectRepository) {
|
constructor(repository: ProjectRepository) {
|
||||||
super();
|
super();
|
||||||
this.repository = repository;
|
this.repository = repository;
|
||||||
makeAutoObservable(this);
|
makeAutoObservable(this);
|
||||||
}
|
}
|
||||||
|
async getProjects(): Promise<void> {
|
||||||
async getProjects() {
|
await this.mapOk<IProjectModel[]>("projectsModels", this.repository.getAllProject());
|
||||||
const result = await this.loadingHelper(this.repository.getAllProject());
|
|
||||||
if (result.isSuccess()) {
|
|
||||||
this.projectsModels = result.value;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async getActiveProject(): Promise<void> {
|
||||||
|
await this.mapOk<ActivePipeline>("activePipeline", this.repository.getActivePipeline());
|
||||||
|
}
|
||||||
|
async foo(): Promise<void> {
|
||||||
|
this.isLoading = true;
|
||||||
|
const result = await this.repository.getActivePipeline();
|
||||||
|
result.fold(
|
||||||
|
(success) => {
|
||||||
|
this.activePipeline = success;
|
||||||
|
this.isLoading = false;
|
||||||
|
},
|
||||||
|
(_error) => {
|
||||||
|
this.isError = true;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
async init() {
|
||||||
|
await Promise.all([this.getProjects(), this.getActiveProject()]);
|
||||||
|
await this.projectViewGenerate();
|
||||||
|
}
|
||||||
|
projectViewGenerate() {
|
||||||
|
this.projectsModels = this.projectsModels?.filter((el) => el._id === this.activePipeline?.projectUUID);
|
||||||
|
}
|
||||||
|
async setPipelineActive(id: string) {
|
||||||
|
await this.loadingHelper(this.repository.setActivePipeline(id));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,9 +29,7 @@ export const CreatePipelineScreen: React.FunctionComponent = observer(() => {
|
||||||
icon={Icon.add}
|
icon={Icon.add}
|
||||||
/>
|
/>
|
||||||
<div style={{ flexGrow: "1" }}>
|
<div style={{ flexGrow: "1" }}>
|
||||||
<Button onClick={() => createPipelineStore.createPipeline()}>
|
<Button onClick={() => createPipelineStore.createPipeline()}>Save result</Button>
|
||||||
Save result
|
|
||||||
</Button>
|
|
||||||
<List
|
<List
|
||||||
headers="new pipeline"
|
headers="new pipeline"
|
||||||
values={createPipelineStore.pipelineViewModels}
|
values={createPipelineStore.pipelineViewModels}
|
||||||
|
|
|
@ -3,7 +3,7 @@ import { CreatePipelineRepository } from "../data/create_pipeline_repository";
|
||||||
import { ITriggerModel } from "../../../core/model/trigger_model";
|
import { ITriggerModel } from "../../../core/model/trigger_model";
|
||||||
import { IProcess } from "../../create_process/model/process_model";
|
import { IProcess } from "../../create_process/model/process_model";
|
||||||
import { message } from "antd";
|
import { message } from "antd";
|
||||||
import { BaseStore } from "../../../core/store/base_store";
|
import { SimpleErrorState } from "../../../core/store/base_store";
|
||||||
|
|
||||||
enum Type {
|
enum Type {
|
||||||
PROCESS,
|
PROCESS,
|
||||||
|
@ -16,7 +16,7 @@ export interface UnionView {
|
||||||
uuid?: string;
|
uuid?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class CreatePipelineStore extends BaseStore {
|
export class CreatePipelineStore extends SimpleErrorState {
|
||||||
repository: CreatePipelineRepository;
|
repository: CreatePipelineRepository;
|
||||||
triggersModels: ITriggerModel[] = [];
|
triggersModels: ITriggerModel[] = [];
|
||||||
processModels: IProcess[] = [];
|
processModels: IProcess[] = [];
|
||||||
|
@ -34,9 +34,7 @@ export class CreatePipelineStore extends BaseStore {
|
||||||
}
|
}
|
||||||
|
|
||||||
filterPipelineViewModel(index: number): void {
|
filterPipelineViewModel(index: number): void {
|
||||||
this.pipelineViewModels = this.pipelineViewModels.filter(
|
this.pipelineViewModels = this.pipelineViewModels.filter((_el, i) => i !== index);
|
||||||
(_el, i) => i !== index
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
addTrigger(e: string, id: string): void {
|
addTrigger(e: string, id: string): void {
|
||||||
const lastElement = this.pipelineViewModels.lastElement();
|
const lastElement = this.pipelineViewModels.lastElement();
|
||||||
|
@ -82,12 +80,8 @@ export class CreatePipelineStore extends BaseStore {
|
||||||
message.error("not found pipelines process");
|
message.error("not found pipelines process");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const triggerId = this.pipelineViewModels.find(
|
const triggerId = this.pipelineViewModels.find((el) => el.type === Type.TRIGGER)!.uuid as string;
|
||||||
(el) => el.type === Type.TRIGGER
|
const processId = this.pipelineViewModels.find((el) => el.type === Type.PROCESS)!.uuid as string;
|
||||||
)!.uuid as string;
|
|
||||||
const processId = this.pipelineViewModels.find(
|
|
||||||
(el) => el.type === Type.PROCESS
|
|
||||||
)!.uuid as string;
|
|
||||||
|
|
||||||
this.repository.savePipeline({
|
this.repository.savePipeline({
|
||||||
process: processId,
|
process: processId,
|
||||||
|
@ -96,33 +90,11 @@ export class CreatePipelineStore extends BaseStore {
|
||||||
}
|
}
|
||||||
|
|
||||||
async loadProcess() {
|
async loadProcess() {
|
||||||
this.isLoading = true;
|
this.mapOk("processModels", this.repository.getProcessed());
|
||||||
const result = await this.repository.getProcessed();
|
|
||||||
result.fold(
|
|
||||||
(s) => {
|
|
||||||
this.processModels = s;
|
|
||||||
},
|
|
||||||
(_e) => {
|
|
||||||
this.isError = true;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
this.isLoading = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async loadTriggers() {
|
async loadTriggers() {
|
||||||
this.isLoading = true;
|
this.mapOk("triggersModels", this.repository.getTriggers());
|
||||||
const result = await this.repository.getTriggers(1);
|
|
||||||
result.fold(
|
|
||||||
(s) => {
|
|
||||||
this.triggersModels = s;
|
|
||||||
},
|
|
||||||
(_e) => {
|
|
||||||
this.isError = true;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
this.isLoading = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
export const createPipelineStore = new CreatePipelineStore(
|
export const createPipelineStore = new CreatePipelineStore(new CreatePipelineRepository());
|
||||||
new CreatePipelineRepository()
|
|
||||||
);
|
|
||||||
|
|
|
@ -8,8 +8,8 @@ class ProcessStore {
|
||||||
this.repository = repository;
|
this.repository = repository;
|
||||||
makeAutoObservable(this);
|
makeAutoObservable(this);
|
||||||
}
|
}
|
||||||
async saveResult(model:IProcess) {
|
async saveResult(model: IProcess) {
|
||||||
await this.repository.save(model)
|
await this.repository.save(model);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,17 +1,23 @@
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import { LoadPage } from "../../core/ui/pages/load_page";
|
import { LoadPage as MainPage } from "../../core/ui/pages/load_page";
|
||||||
import { createProjectStore } from "./create_project_store";
|
|
||||||
import { observer } from "mobx-react-lite";
|
import { observer } from "mobx-react-lite";
|
||||||
import { Col, Row, Input, Button } from "antd";
|
import { Col, Row, Input, Button } from "antd";
|
||||||
import { ReactComponent as AddIcon } from "../../core/assets/icons/add.svg";
|
import { ReactComponent as AddIcon } from "../../core/assets/icons/add.svg";
|
||||||
import { CreatePipelineScreenPath } from "../create_pipeline/presentation/create_pipeline_screen";
|
import { CreatePipelineScreenPath } from "../create_pipeline/presentation/create_pipeline_screen";
|
||||||
|
import { CreateProjectStore } from "./create_project_store";
|
||||||
|
import { CreateProjectRepository } from "./create_project_repository";
|
||||||
|
|
||||||
export const CreateProjectScreenPath = "/create_project";
|
export const CreateProjectScreenPath = "/create_project";
|
||||||
|
|
||||||
export const CreateProjectScreen: React.FunctionComponent = observer(() => {
|
export const CreateProjectScreen: React.FunctionComponent = observer(() => {
|
||||||
|
const [createProjectStore] = React.useState(() => new CreateProjectStore(new CreateProjectRepository()));
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
createProjectStore.init();
|
||||||
|
}, [createProjectStore]);
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<LoadPage
|
<MainPage
|
||||||
path={CreatePipelineScreenPath}
|
path={CreatePipelineScreenPath}
|
||||||
largeText={"Create project"}
|
largeText={"Create project"}
|
||||||
minText={"add new pipelines?"}
|
minText={"add new pipelines?"}
|
||||||
|
@ -48,21 +54,14 @@ export const CreateProjectScreen: React.FunctionComponent = observer(() => {
|
||||||
})}
|
})}
|
||||||
</Col>
|
</Col>
|
||||||
<Col>
|
<Col>
|
||||||
|
|
||||||
<Row>
|
<Row>
|
||||||
<Input
|
<Input
|
||||||
style={{ width: "250px" }}
|
style={{ width: "250px" }}
|
||||||
onChange={(e) =>
|
onChange={(e) => createProjectStore.setDescriptionToNewProject(e.target.value)}
|
||||||
createProjectStore.setDescriptionToNewProject(
|
|
||||||
e.target.value
|
|
||||||
)
|
|
||||||
}
|
|
||||||
placeholder="project description"
|
placeholder="project description"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Button onClick={() => createProjectStore.saveProject()}>
|
<Button onClick={() => createProjectStore.saveProject()}>save</Button>
|
||||||
save
|
|
||||||
</Button>
|
|
||||||
</Row>
|
</Row>
|
||||||
|
|
||||||
{createProjectStore.newProjectViews.map((el, index) => {
|
{createProjectStore.newProjectViews.map((el, index) => {
|
||||||
|
@ -87,4 +86,3 @@ export const CreateProjectScreen: React.FunctionComponent = observer(() => {
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,12 +1,9 @@
|
||||||
import makeAutoObservable from "mobx-store-inheritance";
|
import makeAutoObservable from "mobx-store-inheritance";
|
||||||
import {
|
import { CreateProjectRepository, PipelineModel } from "./create_project_repository";
|
||||||
CreateProjectRepository,
|
|
||||||
PipelineModel,
|
|
||||||
} from "./create_project_repository";
|
|
||||||
import { message } from "antd";
|
import { message } from "antd";
|
||||||
import { BaseStore } from "../../core/store/base_store";
|
import { SimpleErrorState } from "../../core/store/base_store";
|
||||||
|
|
||||||
class CreateProjectStore extends BaseStore {
|
export class CreateProjectStore extends SimpleErrorState {
|
||||||
repository: CreateProjectRepository;
|
repository: CreateProjectRepository;
|
||||||
|
|
||||||
pipelineModels?: PipelineModel[];
|
pipelineModels?: PipelineModel[];
|
||||||
|
@ -17,25 +14,16 @@ class CreateProjectStore extends BaseStore {
|
||||||
super();
|
super();
|
||||||
this.repository = repository;
|
this.repository = repository;
|
||||||
makeAutoObservable(this);
|
makeAutoObservable(this);
|
||||||
this.loadPipelines();
|
|
||||||
}
|
}
|
||||||
|
async init() {
|
||||||
|
await this.loadPipelines();
|
||||||
|
}
|
||||||
async addPipeline(model: PipelineModel) {
|
async addPipeline(model: PipelineModel) {
|
||||||
this.newProjectViews.push(model);
|
this.newProjectViews.push(model);
|
||||||
}
|
}
|
||||||
|
|
||||||
async loadPipelines() {
|
async loadPipelines() {
|
||||||
this.isLoading = true;
|
this.mapOk("pipelineModels", this.repository.getAllPipelines());
|
||||||
const result = await this.repository.getAllPipelines();
|
|
||||||
result.fold(
|
|
||||||
(s) => {
|
|
||||||
this.pipelineModels = s;
|
|
||||||
},
|
|
||||||
(_e) => {
|
|
||||||
this.isError = true;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
this.isLoading = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
setDescriptionToNewProject(value: string): void {
|
setDescriptionToNewProject(value: string): void {
|
||||||
|
@ -71,7 +59,3 @@ class CreateProjectStore extends BaseStore {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const createProjectStore = new CreateProjectStore(
|
|
||||||
new CreateProjectRepository()
|
|
||||||
);
|
|
||||||
|
|
|
@ -12,16 +12,17 @@ export const CreateProjectInstanceScreen = observer(() => {
|
||||||
() => new CreateProjectInstanceStore(new CreateProjectInstanceRepository())
|
() => new CreateProjectInstanceStore(new CreateProjectInstanceRepository())
|
||||||
);
|
);
|
||||||
const id = useParams().id;
|
const id = useParams().id;
|
||||||
createProjectInstanceStore.getProjectById(id as string)
|
React.useEffect(() => {}, [id, createProjectInstanceStore]);
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Upload
|
<Upload
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
console.log(e);
|
createProjectInstanceStore.file = e.file.originFileObj;
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Button>Upload root entity</Button>
|
<Button>Upload root entity</Button>
|
||||||
</Upload>
|
</Upload>
|
||||||
|
<Button onClick={() => createProjectInstanceStore.saveInstance()}>Save</Button>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,10 +1,13 @@
|
||||||
import {
|
import { HttpMethod, HttpRepository } from "../../core/repository/http_repository";
|
||||||
HttpMethod,
|
|
||||||
HttpRepository,
|
|
||||||
} from "../../core/repository/http_repository";
|
|
||||||
|
|
||||||
|
// this.subRoutes.push({
|
||||||
|
// method: "POST",
|
||||||
|
// subUrl: "upload
|
||||||
export class CreateProjectInstanceRepository extends HttpRepository {
|
export class CreateProjectInstanceRepository extends HttpRepository {
|
||||||
async getProjectInstance(id: string) {
|
async setProjectRootFile() {
|
||||||
return await this.jsonRequest(HttpMethod.GET, "");
|
return await this.formDataRequest(HttpMethod.POST, "/project_instance/upload/");
|
||||||
}
|
}
|
||||||
|
// async getProjectInstance(id: string) {
|
||||||
|
// return await this.jsonRequest(HttpMethod.GET, "");
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,18 +1,23 @@
|
||||||
import makeAutoObservable from "mobx-store-inheritance";
|
import makeAutoObservable from "mobx-store-inheritance";
|
||||||
import { BaseStore } from "../../core/store/base_store";
|
import { SimpleErrorState } from "../../core/store/base_store";
|
||||||
import { CreateProjectInstanceRepository } from "./create_project_instance_repository";
|
import { CreateProjectInstanceRepository } from "./create_project_instance_repository";
|
||||||
|
import { message } from "antd";
|
||||||
|
import { HttpMethod } from "../../core/repository/http_repository";
|
||||||
|
|
||||||
export class CreateProjectInstanceStore extends BaseStore {
|
export class CreateProjectInstanceStore extends SimpleErrorState {
|
||||||
|
file?: File;
|
||||||
|
|
||||||
|
saveInstance(): void {
|
||||||
|
if (this.file === undefined) {
|
||||||
|
message.error("Need upload file");
|
||||||
|
} else {
|
||||||
|
// this.repository.formDataRequest(HttpMethod.POST, "", this.file);
|
||||||
|
}
|
||||||
|
}
|
||||||
constructor(repository: CreateProjectInstanceRepository) {
|
constructor(repository: CreateProjectInstanceRepository) {
|
||||||
super();
|
super();
|
||||||
this.repository = repository;
|
this.repository = repository;
|
||||||
makeAutoObservable(this);
|
makeAutoObservable(this);
|
||||||
}
|
}
|
||||||
repository: CreateProjectInstanceRepository;
|
repository: CreateProjectInstanceRepository;
|
||||||
async getProjectById(id: string) {
|
|
||||||
const result = await this.loadingHelper(this.repository.getProjectInstance(id))
|
|
||||||
if(result.isSuccess()){
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,36 +2,40 @@ import * as React from "react";
|
||||||
import Editor from "@monaco-editor/react";
|
import Editor from "@monaco-editor/react";
|
||||||
import { Button } from "antd";
|
import { Button } from "antd";
|
||||||
import { observer } from "mobx-react-lite";
|
import { observer } from "mobx-react-lite";
|
||||||
import { triggerStore } from "../trigger_store";
|
import { CallBackStringVoidFunction } from "../../../../core/extensions/extensions";
|
||||||
|
|
||||||
export const CodeTriggerForm: React.FunctionComponent = observer(() => {
|
interface ICodeTriggerFormProps {
|
||||||
return (
|
codeTriggerValue: string;
|
||||||
<>
|
clearTriggerCode: VoidFunction;
|
||||||
<div style={{ width: "100%", backgroundColor: "black", height: "1px" }} />
|
saveCode: VoidFunction;
|
||||||
|
writeNewTrigger: CallBackStringVoidFunction;
|
||||||
|
}
|
||||||
|
|
||||||
<Editor
|
export const CodeTriggerForm: React.FunctionComponent<ICodeTriggerFormProps> = observer(
|
||||||
height="40vh"
|
(props: ICodeTriggerFormProps) => {
|
||||||
defaultLanguage="javascript"
|
return (
|
||||||
value={triggerStore.codeTriggerValue}
|
<>
|
||||||
onChange={(v) => {
|
<div style={{ width: "100%", backgroundColor: "black", height: "1px" }} />
|
||||||
triggerStore.writeNewTrigger(v);
|
|
||||||
}}
|
|
||||||
onValidate={(_m) => {}}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<div style={{ width: "100%", backgroundColor: "black", height: "1px" }} />
|
<Editor
|
||||||
<div style={{ height: "10px" }} />
|
height="40vh"
|
||||||
|
defaultLanguage="javascript"
|
||||||
|
value={props.codeTriggerValue}
|
||||||
|
onChange={(v) => {
|
||||||
|
props.writeNewTrigger(v ?? "");
|
||||||
|
}}
|
||||||
|
onValidate={(_m) => {}}
|
||||||
|
/>
|
||||||
|
|
||||||
<Button
|
<div style={{ width: "100%", backgroundColor: "black", height: "1px" }} />
|
||||||
onClick={() => triggerStore.saveCode()}
|
<div style={{ height: "10px" }} />
|
||||||
style={{ marginLeft: "10px", marginRight: "10px" }}
|
|
||||||
>
|
|
||||||
Save code
|
|
||||||
</Button>
|
|
||||||
|
|
||||||
<Button onClick={() => triggerStore.clearTriggerCode()}>
|
<Button onClick={() => props.saveCode()} style={{ marginLeft: "10px", marginRight: "10px" }}>
|
||||||
Reset code
|
Save code
|
||||||
</Button>
|
</Button>
|
||||||
</>
|
|
||||||
);
|
<Button onClick={() => props.clearTriggerCode()}>Reset code</Button>
|
||||||
});
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
|
@ -3,50 +3,49 @@ import { Formik } from "formik";
|
||||||
import { SubmitButton, Input, ResetButton, Form, FormItem } from "formik-antd";
|
import { SubmitButton, Input, ResetButton, Form, FormItem } from "formik-antd";
|
||||||
import { Row, Col } from "antd";
|
import { Row, Col } from "antd";
|
||||||
import { observer } from "mobx-react-lite";
|
import { observer } from "mobx-react-lite";
|
||||||
import { triggerStore } from "../trigger_store";
|
|
||||||
import { TriggerType } from "../../../../core/model/trigger_model";
|
import { TriggerType } from "../../../../core/model/trigger_model";
|
||||||
import { validateRequired } from "../../../../core/helper/validate";
|
import { validateRequired } from "../../../../core/helper/validate";
|
||||||
|
export interface IFileTriggerFormProps {
|
||||||
export const FileTriggerForm: React.FunctionComponent = observer(() => {
|
pushTrigger: (value: string, type: TriggerType) => void;
|
||||||
return (
|
}
|
||||||
<>
|
export const FileTriggerForm: React.FunctionComponent<IFileTriggerFormProps> = observer(
|
||||||
<div style={{ marginTop: 80 }}>
|
(props: IFileTriggerFormProps) => {
|
||||||
<Formik
|
return (
|
||||||
initialValues={{
|
<>
|
||||||
value: "",
|
<div style={{ marginTop: 80 }}>
|
||||||
}}
|
<Formik
|
||||||
onSubmit={(values, actions) => {
|
initialValues={{
|
||||||
triggerStore.pushTrigger(values.value, TriggerType.FILE);
|
value: "",
|
||||||
actions.setSubmitting(false);
|
}}
|
||||||
actions.resetForm();
|
onSubmit={(values, actions) => {
|
||||||
}}
|
props.pushTrigger(values.value, TriggerType.FILE);
|
||||||
validate={(values) => {
|
actions.setSubmitting(false);
|
||||||
if (values.value.length === 0) {
|
actions.resetForm();
|
||||||
return false;
|
}}
|
||||||
}
|
validate={(values) => {
|
||||||
return {};
|
if (values.value.length === 0) {
|
||||||
}}
|
return false;
|
||||||
render={() => (
|
}
|
||||||
<Form>
|
return {};
|
||||||
<div style={{ background: "white", flex: 1, padding: 40 }}>
|
}}
|
||||||
<FormItem
|
render={() => (
|
||||||
name="value"
|
<Form>
|
||||||
required={true}
|
<div style={{ background: "white", flex: 1, padding: 40 }}>
|
||||||
validate={validateRequired}
|
<FormItem name="value" required={true} validate={validateRequired}>
|
||||||
>
|
<Input name="value" placeholder="regExp file" />
|
||||||
<Input name="value" placeholder="regExp file" />
|
</FormItem>
|
||||||
</FormItem>
|
<Row style={{ marginTop: 60 }}>
|
||||||
<Row style={{ marginTop: 60 }}>
|
<Col offset={8}>
|
||||||
<Col offset={8}>
|
<ResetButton>Reset</ResetButton>
|
||||||
<ResetButton>Reset</ResetButton>
|
<SubmitButton>Submit</SubmitButton>
|
||||||
<SubmitButton>Submit</SubmitButton>
|
</Col>
|
||||||
</Col>
|
</Row>
|
||||||
</Row>
|
</div>
|
||||||
</div>
|
</Form>
|
||||||
</Form>
|
)}
|
||||||
)}
|
/>
|
||||||
/>
|
</div>
|
||||||
</div>
|
</>
|
||||||
</>
|
);
|
||||||
);
|
}
|
||||||
});
|
);
|
||||||
|
|
|
@ -2,35 +2,20 @@ import * as React from "react";
|
||||||
import { Button, Col, Row, Switch, Typography, Input } from "antd";
|
import { Button, Col, Row, Switch, Typography, Input } from "antd";
|
||||||
import { CodeTriggerForm } from "./components/code_trigger_form";
|
import { CodeTriggerForm } from "./components/code_trigger_form";
|
||||||
import { observer } from "mobx-react-lite";
|
import { observer } from "mobx-react-lite";
|
||||||
import { triggerStore } from "./trigger_store";
|
|
||||||
import { FileTriggerForm } from "./components/file_trigger_form";
|
import { FileTriggerForm } from "./components/file_trigger_form";
|
||||||
import { ReactComponent as DeleteIcon } from "../../../core/assets/icons/delete.svg";
|
import { ReactComponent as DeleteIcon } from "../../../core/assets/icons/delete.svg";
|
||||||
import { Loader } from "../../../core/ui/loader/loader";
|
import { Loader } from "../../../core/ui/loader/loader";
|
||||||
|
import { TriggerRepository } from "../data/trigger_repository";
|
||||||
|
import { TriggerStore } from "./trigger_store";
|
||||||
|
import { TriggerViewModel } from "../model/trigger_form_view_model";
|
||||||
|
import { CallBackStringVoidFunction } from "../../../core/extensions/extensions";
|
||||||
|
|
||||||
const { Title } = Typography;
|
const { Title } = Typography;
|
||||||
|
|
||||||
const Header = observer(() => {
|
const Bottom = observer((props: { triggers: TriggerViewModel[]; callBack: CallBackStringVoidFunction }) => {
|
||||||
return (
|
|
||||||
<Row style={{ justifyItems: "center", alignItems: "center" }}>
|
|
||||||
<div style={{ height: "37px" }}>
|
|
||||||
<Switch
|
|
||||||
checked={triggerStore.getTriggerType()}
|
|
||||||
onChange={() => triggerStore.setTriggerType()}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<Title level={2}>
|
|
||||||
Trigger editor: {triggerStore.getTriggerDescription()}
|
|
||||||
</Title>
|
|
||||||
<div style={{ width: "10px" }}></div>
|
|
||||||
<Button onClick={() => triggerStore.saveResult()}>Save result</Button>
|
|
||||||
</Row>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
const Bottom = observer(() => {
|
|
||||||
return (
|
return (
|
||||||
<Col>
|
<Col>
|
||||||
{triggerStore.triggers.map((el) => {
|
{props.triggers.map((el) => {
|
||||||
return (
|
return (
|
||||||
<Row
|
<Row
|
||||||
style={{
|
style={{
|
||||||
|
@ -38,40 +23,50 @@ const Bottom = observer(() => {
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{el.value}
|
{el.value}
|
||||||
<DeleteIcon onClick={() => triggerStore.deleteItem(el.id)} />
|
<DeleteIcon onClick={() => props.callBack(el.id)} />
|
||||||
</Row>
|
</Row>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</Col>
|
</Col>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
export const CreateTriggerScreenPath = '/create/trigger'
|
export const CreateTriggerScreenPath = "/create/trigger";
|
||||||
|
|
||||||
export const TriggerScreen: React.FunctionComponent = observer(() => {
|
export const TriggerScreen: React.FunctionComponent = observer(() => {
|
||||||
|
const [triggerStore] = React.useState(() => new TriggerStore(new TriggerRepository()));
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<main>
|
<main>
|
||||||
{!triggerStore.isLoading ? (
|
{!triggerStore.isLoading ? (
|
||||||
<>
|
<>
|
||||||
<Header />,
|
<Row style={{ justifyItems: "center", alignItems: "center" }}>
|
||||||
<Input
|
<div style={{ height: "37px" }}>
|
||||||
placeholder="trigger description"
|
<Switch checked={triggerStore.getTriggerType()} onChange={() => triggerStore.setTriggerType()} />
|
||||||
onChange={() => triggerStore.changeTriggerDescription}
|
</div>
|
||||||
/>
|
<Title level={2}>Trigger editor: {triggerStore.getTriggerDescription()}</Title>
|
||||||
|
<div style={{ width: "10px" }}></div>
|
||||||
|
<Button onClick={() => triggerStore.saveResult()}>Save result</Button>
|
||||||
|
</Row>
|
||||||
|
<Input placeholder="trigger description" onChange={() => triggerStore.changeTriggerDescription} />
|
||||||
{triggerStore.getTriggerType() ? (
|
{triggerStore.getTriggerType() ? (
|
||||||
<>
|
<>
|
||||||
<FileTriggerForm />
|
<FileTriggerForm pushTrigger={triggerStore.pushTrigger} />
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
<CodeTriggerForm />
|
<CodeTriggerForm
|
||||||
|
codeTriggerValue={triggerStore.codeTriggerValue}
|
||||||
|
clearTriggerCode={triggerStore.clearTriggerCode}
|
||||||
|
saveCode={triggerStore.saveCode}
|
||||||
|
writeNewTrigger={triggerStore.writeNewTrigger}
|
||||||
|
/>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
<Bottom />
|
<Bottom triggers={triggerStore.triggers} callBack={triggerStore.deleteItem} />
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
|
<Loader />
|
||||||
<Loader/>
|
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</main>
|
</main>
|
||||||
|
|
|
@ -3,9 +3,9 @@ import { v4 as uuidv4 } from "uuid";
|
||||||
import { TriggerType } from "../../../core/model/trigger_model";
|
import { TriggerType } from "../../../core/model/trigger_model";
|
||||||
import { TriggerRepository } from "../data/trigger_repository";
|
import { TriggerRepository } from "../data/trigger_repository";
|
||||||
import { TriggerViewModel } from "../model/trigger_form_view_model";
|
import { TriggerViewModel } from "../model/trigger_form_view_model";
|
||||||
import { BaseStore } from "../../../core/store/base_store";
|
import { SimpleErrorState } from "../../../core/store/base_store";
|
||||||
|
|
||||||
class TriggerStore extends BaseStore {
|
export class TriggerStore extends SimpleErrorState {
|
||||||
constructor(repository: TriggerRepository) {
|
constructor(repository: TriggerRepository) {
|
||||||
super();
|
super();
|
||||||
this.triggerType = TriggerType.FILE;
|
this.triggerType = TriggerType.FILE;
|
||||||
|
@ -39,9 +39,7 @@ class TriggerStore extends BaseStore {
|
||||||
this.triggerType = TriggerType.FILE;
|
this.triggerType = TriggerType.FILE;
|
||||||
};
|
};
|
||||||
getTriggerDescription = (): string => {
|
getTriggerDescription = (): string => {
|
||||||
return this.triggerType === TriggerType.FILE
|
return this.triggerType === TriggerType.FILE ? TriggerType.FILE : TriggerType.PROCESS;
|
||||||
? TriggerType.FILE
|
|
||||||
: TriggerType.PROCESS;
|
|
||||||
};
|
};
|
||||||
pushTrigger = (value: string, type: TriggerType): void => {
|
pushTrigger = (value: string, type: TriggerType): void => {
|
||||||
this.triggers.push({
|
this.triggers.push({
|
||||||
|
@ -72,16 +70,15 @@ class TriggerStore extends BaseStore {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
async saveResult(): Promise<void> {
|
async saveResult(): Promise<void> {
|
||||||
this.isLoading = true;
|
await this.loadingHelper(
|
||||||
await this.repository.save({
|
this.repository.save({
|
||||||
type: this.getTriggerDescription(),
|
type: this.getTriggerDescription(),
|
||||||
description: this.triggerDescription,
|
description: this.triggerDescription,
|
||||||
value: this.triggers.map((el) => {
|
value: this.triggers.map((el) => {
|
||||||
return el.value;
|
return el.value;
|
||||||
}),
|
}),
|
||||||
});
|
})
|
||||||
this.isLoading = false;
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const triggerStore = new TriggerStore(new TriggerRepository());
|
export const triggerStore = new TriggerStore(new TriggerRepository());
|
||||||
|
|
68
ui/src/features/p.tsx
Normal file
68
ui/src/features/p.tsx
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
export {};
|
||||||
|
// import React from "react";
|
||||||
|
// import { CoreError, UiErrorState } from "../core/store/base_store";
|
||||||
|
// import { SelectProjectStore } from "./select_project/presentation/select_project_store";
|
||||||
|
|
||||||
|
// export declare type ClassConstructor<T> = {
|
||||||
|
// new (...args: any[]): T;
|
||||||
|
// };
|
||||||
|
// interface MobxReactComponentProps<T extends UiErrorState<CoreError>, ClassConstructor> {
|
||||||
|
// store: ClassConstructor;
|
||||||
|
// children: (element: T) => React.ReactElement;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// class UiStateErrorComponent<T extends UiErrorState<CoreError>, K> extends React.Component<
|
||||||
|
// MobxReactComponentProps<T, K>,
|
||||||
|
// { store: T | undefined }
|
||||||
|
// > {
|
||||||
|
// async componentDidMount(): Promise<void> {
|
||||||
|
// const store = this.props.store as ClassConstructor<T>;
|
||||||
|
// console.log(store);
|
||||||
|
// const s = new store();
|
||||||
|
// this.setState({ store: s });
|
||||||
|
// if (this.state !== null) {
|
||||||
|
// await this.state.store?.init();
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// componentWillUnmount(): void {
|
||||||
|
// if (this.state.store !== undefined) {
|
||||||
|
// this.state.store.dispose();
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// render() {
|
||||||
|
// if (this.state !== null) {
|
||||||
|
// if (this.state.store?.isLoading) {
|
||||||
|
// return <>Loading</>;
|
||||||
|
// }
|
||||||
|
// if (this.state.store !== undefined) {
|
||||||
|
// return this.props.children(this.state.store);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// return (
|
||||||
|
// <div>
|
||||||
|
// <>{this.props.children}</>
|
||||||
|
// </div>
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// export const ExampleScreen: React.FC = () => {
|
||||||
|
// return (
|
||||||
|
// <div>
|
||||||
|
// <UiStateErrorComponent<SelectProjectStore, {}> store={SelectProjectStore}>
|
||||||
|
// {(store) => {
|
||||||
|
// console.log(store);
|
||||||
|
// return (
|
||||||
|
// <div>
|
||||||
|
// {store.projects.map((el) => {
|
||||||
|
// return <>{el}</>;
|
||||||
|
// })}
|
||||||
|
// </div>
|
||||||
|
// );
|
||||||
|
// }}
|
||||||
|
// </UiStateErrorComponent>
|
||||||
|
// </div>
|
||||||
|
// );
|
||||||
|
// };
|
|
@ -4,13 +4,12 @@ import { PipelineInstanceStore } from "./pipeline_instance_store";
|
||||||
|
|
||||||
export const PipelineInstanceScreenPath = "/pipeline_instance/";
|
export const PipelineInstanceScreenPath = "/pipeline_instance/";
|
||||||
export const PipelineInstanceScreen: React.FunctionComponent = () => {
|
export const PipelineInstanceScreen: React.FunctionComponent = () => {
|
||||||
const [pipelineInstanceStore] = React.useState(
|
const [pipelineInstanceStore] = React.useState(() => new PipelineInstanceStore());
|
||||||
() => new PipelineInstanceStore()
|
React.useEffect(() => {}, [pipelineInstanceStore]);
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<LoadPage
|
<LoadPage
|
||||||
needBackButton={false}
|
needBackButton={true}
|
||||||
|
largeText={"Project instance active"}
|
||||||
isError={pipelineInstanceStore.isError}
|
isError={pipelineInstanceStore.isError}
|
||||||
isLoading={pipelineInstanceStore.isLoading}
|
isLoading={pipelineInstanceStore.isLoading}
|
||||||
children={<div></div>}
|
children={<div></div>}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import makeAutoObservable from "mobx-store-inheritance";
|
import makeAutoObservable from "mobx-store-inheritance";
|
||||||
import { BaseStore } from "../../core/store/base_store";
|
import { SimpleErrorState } from "../../core/store/base_store";
|
||||||
|
|
||||||
export class PipelineInstanceStore extends BaseStore {
|
export class PipelineInstanceStore extends SimpleErrorState {
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
makeAutoObservable(this);
|
makeAutoObservable(this);
|
||||||
|
|
|
@ -2,6 +2,7 @@ import * as React from "react";
|
||||||
import { SceneMangerStore, StaticAssetItemModel } from "./scene_manager_store";
|
import { SceneMangerStore, StaticAssetItemModel } from "./scene_manager_store";
|
||||||
import { observer } from "mobx-react-lite";
|
import { observer } from "mobx-react-lite";
|
||||||
import { StaticAssetModelView } from "./components/static_asset_item_view";
|
import { StaticAssetModelView } from "./components/static_asset_item_view";
|
||||||
|
import { useParams } from "react-router-dom";
|
||||||
|
|
||||||
// const useKeyLister = (fn: Function) => {
|
// const useKeyLister = (fn: Function) => {
|
||||||
// const pressed = new Map();
|
// const pressed = new Map();
|
||||||
|
@ -26,21 +27,25 @@ import { StaticAssetModelView } from "./components/static_asset_item_view";
|
||||||
|
|
||||||
// return [];
|
// return [];
|
||||||
// };
|
// };
|
||||||
|
export const SceneManagerPath = "/scene/manager/";
|
||||||
export const SceneManger = observer(() => {
|
export const SceneManger = observer(() => {
|
||||||
const canvasRef = React.useRef<HTMLCanvasElement>(null);
|
const canvasRef = React.useRef<HTMLCanvasElement>(null);
|
||||||
|
|
||||||
const [sceneMangerStore] = React.useState(() => new SceneMangerStore());
|
const [sceneMangerStore] = React.useState(() => new SceneMangerStore());
|
||||||
|
const id = useParams().id as string;
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
sceneMangerStore.loadGl(canvasRef.current!);
|
if (id) {
|
||||||
|
sceneMangerStore.loadScene(id, canvasRef.current!);
|
||||||
|
}
|
||||||
return () => {
|
return () => {
|
||||||
sceneMangerStore.dispose();
|
sceneMangerStore.dispose();
|
||||||
};
|
};
|
||||||
});
|
}, [id, sceneMangerStore]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
|
<div>{sceneMangerStore.errors.isNotEmpty() ? <>{sceneMangerStore.errors[0].text}</> : <></>}</div>
|
||||||
<div style={{ position: "absolute" }}>
|
<div style={{ position: "absolute" }}>
|
||||||
{sceneMangerStore.sceneItems.map((el) => {
|
{sceneMangerStore.sceneItems.map((el) => {
|
||||||
if (el instanceof StaticAssetItemModel) {
|
if (el instanceof StaticAssetItemModel) {
|
||||||
|
|
|
@ -1,8 +1,11 @@
|
||||||
/* eslint-disable array-callback-return */
|
/* eslint-disable array-callback-return */
|
||||||
import { makeAutoObservable } from "mobx";
|
import makeAutoObservable from "mobx-store-inheritance";
|
||||||
import { CoreThereRepository } from "../../core/repository/core_there_repository";
|
import { CoreThereRepository } from "../../core/repository/core_there_repository";
|
||||||
import { v4 as uuidv4 } from "uuid";
|
import { v4 as uuidv4 } from "uuid";
|
||||||
import { Vector2 } from "three";
|
import { Vector2 } from "three";
|
||||||
|
import { HttpError, HttpMethod, HttpRepository } from "../../core/repository/http_repository";
|
||||||
|
import { UiErrorState } from "../../core/store/base_store";
|
||||||
|
import { UiBaseError } from "../../core/model/ui_base_error";
|
||||||
|
|
||||||
export class BaseSceneItemModel {
|
export class BaseSceneItemModel {
|
||||||
id: string;
|
id: string;
|
||||||
|
@ -24,12 +27,35 @@ export class StaticAssetItemModel extends BaseSceneItemModel {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class SceneMangerStore {
|
export enum RobossemblerFiles {
|
||||||
|
robossemblerAssets = "robossembler_assets.json",
|
||||||
|
}
|
||||||
|
|
||||||
|
export class SceneMangerStore extends UiErrorState<HttpError> {
|
||||||
|
async init(): Promise<any> {}
|
||||||
|
errorHandingStrategy = (error: HttpError) => {
|
||||||
|
if (error.status === 404) {
|
||||||
|
this.errors.push(new UiBaseError(`${RobossemblerFiles.robossemblerAssets} not found to project`));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
async loadScene(sceneId: string, canvasRef: HTMLCanvasElement) {
|
||||||
|
(
|
||||||
|
await this.loadingHelper(
|
||||||
|
this.httpRepository.jsonRequest(HttpMethod.GET, "/" + sceneId + "/" + RobossemblerFiles.robossemblerAssets)
|
||||||
|
)
|
||||||
|
).map((el) => {
|
||||||
|
this.loadGl(canvasRef);
|
||||||
|
});
|
||||||
|
}
|
||||||
coreThereRepository: null | CoreThereRepository = null;
|
coreThereRepository: null | CoreThereRepository = null;
|
||||||
|
httpRepository: HttpRepository;
|
||||||
sceneItems: BaseSceneItemModel[] = [];
|
sceneItems: BaseSceneItemModel[] = [];
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
|
super();
|
||||||
makeAutoObservable(this);
|
makeAutoObservable(this);
|
||||||
|
this.httpRepository = new HttpRepository();
|
||||||
}
|
}
|
||||||
|
|
||||||
loadGl(canvasRef: HTMLCanvasElement): void {
|
loadGl(canvasRef: HTMLCanvasElement): void {
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
import { Result } from "../../../core/helper/result";
|
import { Result } from "../../../core/helper/result";
|
||||||
import {
|
import { HttpMethod, HttpRepository } from "../../../core/repository/http_repository";
|
||||||
HttpMethod,
|
|
||||||
HttpRepository,
|
|
||||||
} from "../../../core/repository/http_repository";
|
|
||||||
import { IProjectModel } from "../model/project_model";
|
import { IProjectModel } from "../model/project_model";
|
||||||
|
|
||||||
export class SelectProjectRepository extends HttpRepository {
|
export class SelectProjectRepository extends HttpRepository {
|
||||||
|
async setActiveProject(id: string) {
|
||||||
|
return await this.jsonRequest(HttpMethod.POST, `/project?${id}`);
|
||||||
|
}
|
||||||
async getAllProjects(page = 1): Promise<Result<Error, IProjectModel[]>> {
|
async getAllProjects(page = 1): Promise<Result<Error, IProjectModel[]>> {
|
||||||
return await this.jsonRequest(HttpMethod.GET, `/project?${page}`);
|
return await this.jsonRequest(HttpMethod.GET, `/project?${page}`);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,16 +3,16 @@ import { observer } from "mobx-react-lite";
|
||||||
import { LoadPage } from "../../../core/ui/pages/load_page";
|
import { LoadPage } from "../../../core/ui/pages/load_page";
|
||||||
import { CreateProjectScreenPath } from "../../create_project/create_project_screen";
|
import { CreateProjectScreenPath } from "../../create_project/create_project_screen";
|
||||||
import { SelectProjectStore } from "./select_project_store";
|
import { SelectProjectStore } from "./select_project_store";
|
||||||
import { SelectProjectRepository } from "../data/select_project_repository";
|
|
||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
import { CreateProjectInstancePath } from "../../create_project_instance/create_project_instance";
|
import { CreateProjectInstancePath } from "../../create_project_instance/create_project_instance";
|
||||||
import { Button } from "antd";
|
import { Button } from "antd";
|
||||||
export const SelectProjectScreenPath = "/select_project";
|
export const SelectProjectScreenPath = "/select_project";
|
||||||
|
|
||||||
export const SelectProjectScreen: React.FunctionComponent = observer(() => {
|
export const SelectProjectScreen: React.FunctionComponent = observer(() => {
|
||||||
const [selectProjectStore] = React.useState(
|
const [selectProjectStore] = React.useState(() => new SelectProjectStore());
|
||||||
() => new SelectProjectStore(new SelectProjectRepository())
|
React.useEffect(() => {
|
||||||
);
|
selectProjectStore.init();
|
||||||
|
}, [selectProjectStore]);
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -22,17 +22,13 @@ export const SelectProjectScreen: React.FunctionComponent = observer(() => {
|
||||||
largeText={"Select project"}
|
largeText={"Select project"}
|
||||||
minText={"add new project?"}
|
minText={"add new project?"}
|
||||||
isLoading={selectProjectStore.isLoading}
|
isLoading={selectProjectStore.isLoading}
|
||||||
isError={selectProjectStore.isError}
|
isError={selectProjectStore.errors.isNotEmpty()}
|
||||||
children={selectProjectStore.projects.map((el) => {
|
children={selectProjectStore.projects.map((el) => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div>{el.description}</div>
|
<div>{el.description}</div>
|
||||||
<div>
|
<div>
|
||||||
<Button
|
<Button onClick={() => navigate(CreateProjectInstancePath + el._id)}>create instance</Button>
|
||||||
onClick={() => navigate(CreateProjectInstancePath + el._id)}
|
|
||||||
>
|
|
||||||
create instance
|
|
||||||
</Button>
|
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,33 +1,31 @@
|
||||||
import makeAutoObservable from "mobx-store-inheritance";
|
import makeAutoObservable from "mobx-store-inheritance";
|
||||||
import { SelectProjectRepository } from "../data/select_project_repository";
|
import { SelectProjectRepository } from "../data/select_project_repository";
|
||||||
import { IProjectModel } from "../model/project_model";
|
import { IProjectModel } from "../model/project_model";
|
||||||
import { BaseStore } from "../../../core/store/base_store";
|
import { CoreError, UiErrorState } from "../../../core/store/base_store";
|
||||||
|
|
||||||
|
export class SelectProjectStore extends UiErrorState<CoreError> {
|
||||||
|
errorHandingStrategy = (error: CoreError) => {
|
||||||
|
console.log(error);
|
||||||
|
};
|
||||||
|
|
||||||
export class SelectProjectStore extends BaseStore {
|
|
||||||
repository: SelectProjectRepository;
|
repository: SelectProjectRepository;
|
||||||
|
errors = [];
|
||||||
page = 1;
|
page = 1;
|
||||||
projects: IProjectModel[] = [];
|
projects: IProjectModel[] = [];
|
||||||
|
|
||||||
constructor(repository: SelectProjectRepository) {
|
constructor() {
|
||||||
super()
|
super();
|
||||||
this.repository = repository;
|
|
||||||
|
this.repository = new SelectProjectRepository();
|
||||||
makeAutoObservable(this);
|
makeAutoObservable(this);
|
||||||
this.getPipelines();
|
|
||||||
}
|
}
|
||||||
|
async setActiveProject(id: string): Promise<void> {
|
||||||
|
this.loadingHelper(this.repository.setActiveProject(id));
|
||||||
|
}
|
||||||
async getPipelines(): Promise<void> {
|
async getPipelines(): Promise<void> {
|
||||||
this.isLoading = true;
|
await this.mapOk("projects", this.repository.getAllProjects(this.page));
|
||||||
const result = await this.repository.getAllProjects(this.page);
|
}
|
||||||
result.fold(
|
async init() {
|
||||||
(s) => {
|
await this.getPipelines();
|
||||||
this.projects = s;
|
|
||||||
},
|
|
||||||
(_e) => {
|
|
||||||
this.isError = true;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
this.isLoading = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,21 +2,19 @@ import React from "react";
|
||||||
import ReactDOM from "react-dom/client";
|
import ReactDOM from "react-dom/client";
|
||||||
|
|
||||||
import "antd/dist/antd.min.css";
|
import "antd/dist/antd.min.css";
|
||||||
import { RouterProvider } from "react-router-dom";
|
|
||||||
|
|
||||||
import { router } from "./core/routers/routers";
|
|
||||||
import { SocketLister } from "./features/socket_lister/socket_lister";
|
|
||||||
import { extensions } from "./core/extensions/extensions";
|
import { extensions } from "./core/extensions/extensions";
|
||||||
import { SceneManger } from "./features/scene_manager/scene_manager";
|
import { SocketLister } from "./features/socket_lister/socket_lister";
|
||||||
|
import { RouterProvider } from "react-router-dom";
|
||||||
|
import { router } from "./core/routers/routers";
|
||||||
|
|
||||||
extensions();
|
extensions();
|
||||||
const root = ReactDOM.createRoot(document.getElementById("root") as HTMLElement);
|
const root = ReactDOM.createRoot(document.getElementById("root") as HTMLElement);
|
||||||
|
|
||||||
root.render(
|
root.render(
|
||||||
<>
|
<>
|
||||||
{/* <SocketLister>
|
<SocketLister>
|
||||||
<RouterProvider router={router} />
|
<RouterProvider router={router} />
|
||||||
</SocketLister> */}
|
</SocketLister>
|
||||||
<SceneManger />
|
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue