progress
This commit is contained in:
parent
6f86377685
commit
8ecb036b1d
36 changed files with 498 additions and 212 deletions
1
.vscode/settings.json
vendored
1
.vscode/settings.json
vendored
|
@ -16,6 +16,7 @@
|
||||||
"*ui.*": false
|
"*ui.*": false
|
||||||
},
|
},
|
||||||
"cSpell.words": [
|
"cSpell.words": [
|
||||||
|
"antd",
|
||||||
"uuidv"
|
"uuidv"
|
||||||
]
|
]
|
||||||
}
|
}
|
|
@ -49,6 +49,6 @@
|
||||||
"spark-md5": "^3.0.2",
|
"spark-md5": "^3.0.2",
|
||||||
"ts-md5": "^1.3.1",
|
"ts-md5": "^1.3.1",
|
||||||
"tsc-watch": "^6.0.4",
|
"tsc-watch": "^6.0.4",
|
||||||
"typedi": "^0.10.0"
|
"uuid": "^9.0.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
import express from "express";
|
import express from "express";
|
||||||
import { Routes } from "../interfaces/router";
|
import { Routes } from "../interfaces/router";
|
||||||
import cors from "cors";
|
import cors from "cors";
|
||||||
import locator from "../di/register_di";
|
|
||||||
import { DevEnv, UnitTestEnv } from "../di/env";
|
|
||||||
import mongoose from "mongoose";
|
import mongoose from "mongoose";
|
||||||
import { Server } from "socket.io";
|
import { Server } from "socket.io";
|
||||||
import { createServer } from "http";
|
import { createServer } from "http";
|
||||||
import { TypedEvent } from "../helper/typed_event";
|
|
||||||
import { SocketSubscriber } from "./socket_controller";
|
import { SocketSubscriber } from "./socket_controller";
|
||||||
|
import { dirname } from "path";
|
||||||
|
import { CreateFolderUseCase } from "../usecases/crete_folder_usecase";
|
||||||
|
import { dirIsExists } from "../repository/fs";
|
||||||
|
|
||||||
export class App {
|
export class App {
|
||||||
public app: express.Application;
|
public app: express.Application;
|
||||||
|
@ -59,6 +59,7 @@ export class App {
|
||||||
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"));
|
||||||
}
|
}
|
||||||
|
|
||||||
private initializeRoutes(routes: Routes[]) {
|
private initializeRoutes(routes: Routes[]) {
|
||||||
|
@ -72,6 +73,7 @@ export class App {
|
||||||
// ? new DevEnv(this.computedFolder)
|
// ? new DevEnv(this.computedFolder)
|
||||||
// : new UnitTestEnv(this.computedFolder)
|
// : new UnitTestEnv(this.computedFolder)
|
||||||
// );
|
// );
|
||||||
|
await this.appStartController();
|
||||||
|
|
||||||
mongoose
|
mongoose
|
||||||
.connect("mongodb://127.0.0.1:27017/test")
|
.connect("mongodb://127.0.0.1:27017/test")
|
||||||
|
@ -80,4 +82,27 @@ export class App {
|
||||||
console.log("ERROR:", e);
|
console.log("ERROR:", e);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async appStartController() {
|
||||||
|
console.log(App.staticFilesStoreDir());
|
||||||
|
if (await dirIsExists(App.staticFilesStoreDir())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const createFolderUseCase = await new CreateFolderUseCase().call(
|
||||||
|
App.staticFilesStoreDir()
|
||||||
|
);
|
||||||
|
|
||||||
|
createFolderUseCase.fold(
|
||||||
|
(_s) => {},
|
||||||
|
(e) => {
|
||||||
|
// TODO:(IDONTSUDO) need logger
|
||||||
|
console.log(e);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
static staticFilesStoreDir = () => {
|
||||||
|
const dir = dirname(__filename);
|
||||||
|
const rootDir = dir.slice(0, dir.length - 20);
|
||||||
|
return rootDir + "public/";
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,17 +18,25 @@ export class CrudController<V, D> extends CoreHttpController<V> {
|
||||||
this.init();
|
this.init();
|
||||||
}
|
}
|
||||||
init() {
|
init() {
|
||||||
this.routes["POST"] = new CreateDataBaseModelUseCase<D>(
|
if (this.routes["POST"] === null) {
|
||||||
this.dataBaseModel
|
this.routes["POST"] = new CreateDataBaseModelUseCase<D>(
|
||||||
).call;
|
this.dataBaseModel
|
||||||
this.routes["GET"] = new PaginationDataBaseModelUseCase<D>(
|
).call;
|
||||||
this.dataBaseModel
|
}
|
||||||
).call;
|
if (this.routes["GET"] === null) {
|
||||||
this.routes["DELETE"] = new DeleteDataBaseModelUseCase<D>(
|
this.routes["GET"] = new PaginationDataBaseModelUseCase<D>(
|
||||||
this.dataBaseModel
|
this.dataBaseModel
|
||||||
).call;
|
).call;
|
||||||
this.routes["PUT"] = new UpdateDataBaseModelUseCase<V, D>(
|
}
|
||||||
this.dataBaseModel
|
if (this.routes["DELETE"] === null) {
|
||||||
).call;
|
this.routes["DELETE"] = new DeleteDataBaseModelUseCase<D>(
|
||||||
|
this.dataBaseModel
|
||||||
|
).call;
|
||||||
|
}
|
||||||
|
if (this.routes["PUT"] === null) {
|
||||||
|
this.routes["PUT"] = new UpdateDataBaseModelUseCase<V, D>(
|
||||||
|
this.dataBaseModel
|
||||||
|
).call;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,7 +68,7 @@ export class CoreHttpController<V> implements ICoreHttpController {
|
||||||
public delete(usecase: CallBackFunction<V>) {
|
public delete(usecase: CallBackFunction<V>) {
|
||||||
this.routes["DELETE"] = usecase;
|
this.routes["DELETE"] = usecase;
|
||||||
}
|
}
|
||||||
private async requestResponseController<T>(
|
public async requestResponseController<T>(
|
||||||
req: Request,
|
req: Request,
|
||||||
res: Response,
|
res: Response,
|
||||||
usecase: CallBackFunction<T>
|
usecase: CallBackFunction<T>
|
||||||
|
|
29
server/src/core/repository/fs.ts
Normal file
29
server/src/core/repository/fs.ts
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
import * as fs from "fs";
|
||||||
|
import { promisify } from "node:util";
|
||||||
|
|
||||||
|
export const readFileAsync = promisify(fs.readFile);
|
||||||
|
export const readdir = promisify(fs.readdir);
|
||||||
|
export const stat = promisify(fs.stat);
|
||||||
|
export const lsStat = promisify(fs.lstat);
|
||||||
|
export const createDir = promisify(fs.mkdir);
|
||||||
|
export const dirIsExists = promisify(fs.exists);
|
||||||
|
|
||||||
|
export function readDirRecursive(path: string, filesToDir: string[] = []) {
|
||||||
|
const files = fs.readdirSync(path);
|
||||||
|
files.forEach((file) => {
|
||||||
|
let filePath = "";
|
||||||
|
if (path[path.length - 1] !== "/") {
|
||||||
|
filePath = `${path}/${file}`;
|
||||||
|
} else {
|
||||||
|
filePath = `${path}${file}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
const stats = fs.statSync(filePath);
|
||||||
|
if (stats.isDirectory()) {
|
||||||
|
readDirRecursive(filePath, filesToDir);
|
||||||
|
} else {
|
||||||
|
filesToDir.push(file);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return filesToDir;
|
||||||
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
import * as fs from "fs";
|
import * as fs from "fs";
|
||||||
import { resolve } from "node:path";
|
import { resolve } from "node:path";
|
||||||
import { promisify } from "node:util";
|
|
||||||
import { createHash } from "node:crypto";
|
import { createHash } from "node:crypto";
|
||||||
import "reflect-metadata";
|
import "reflect-metadata";
|
||||||
import { BinaryLike } from "crypto";
|
import { BinaryLike } from "crypto";
|
||||||
|
@ -10,11 +10,9 @@ import {
|
||||||
} from "../model/meta_data_file_manager_model";
|
} from "../model/meta_data_file_manager_model";
|
||||||
import { Result } from "../helper/result";
|
import { Result } from "../helper/result";
|
||||||
import { TypedEvent } from "../helper/typed_event";
|
import { TypedEvent } from "../helper/typed_event";
|
||||||
|
import { lsStat, readFileAsync, readdir, stat } from "../repository/fs";
|
||||||
|
|
||||||
|
|
||||||
const readFileAsync = promisify(fs.readFile);
|
|
||||||
const readdir = promisify(fs.readdir);
|
|
||||||
const stat = promisify(fs.stat);
|
|
||||||
const lsStat = promisify(fs.lstat);
|
|
||||||
|
|
||||||
function joinBuffers(buffers: Array<Buffer>, delimiter = " ") {
|
function joinBuffers(buffers: Array<Buffer>, delimiter = " ") {
|
||||||
const d = Buffer.from(delimiter);
|
const d = Buffer.from(delimiter);
|
||||||
|
@ -34,6 +32,7 @@ async function readFileAtBuffer(path: string): Promise<Buffer> {
|
||||||
}
|
}
|
||||||
return await readFileAsync(path);
|
return await readFileAsync(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
function md5(content: Buffer | BinaryLike): Promise<string> {
|
function md5(content: Buffer | BinaryLike): Promise<string> {
|
||||||
return new Promise((resolve, _reject) => {
|
return new Promise((resolve, _reject) => {
|
||||||
return resolve(createHash("md5").update(content).digest("hex"));
|
return resolve(createHash("md5").update(content).digest("hex"));
|
||||||
|
@ -47,6 +46,8 @@ export interface IHashesCache {
|
||||||
export abstract class IFilesChangeNotifierService {
|
export abstract class IFilesChangeNotifierService {
|
||||||
abstract directory: string;
|
abstract directory: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export class FilesChangeNotifierService
|
export class FilesChangeNotifierService
|
||||||
extends TypedEvent<Result<Error, IHashesCache>>
|
extends TypedEvent<Result<Error, IHashesCache>>
|
||||||
implements IFilesChangeNotifierService
|
implements IFilesChangeNotifierService
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
import { TypedEvent } from "../helper/typed_event";
|
import { TypedEvent } from "../helper/typed_event";
|
||||||
import { ExecError } from "../model/exec_error_model";
|
import { ExecError } from "../model/exec_error_model";
|
||||||
import { ExecutorResult } from "../model/executor_result";
|
import { ExecutorResult } from "../model/executor_result";
|
||||||
import { IPipelineMeta } from "../model/pipiline_meta";
|
import { IPipelineMeta } from "../model/pipeline_meta";
|
||||||
import { IPipeline } from "../model/process_model";
|
import { IPipeline } from "../model/process_model";
|
||||||
import { Iteration, StackService } from "./stack_service";
|
import { Iteration, StackService } from "./stack_service";
|
||||||
|
|
||||||
|
|
||||||
export class PipelineRealTimeService extends TypedEvent<IPipelineMeta> {
|
export class PipelineRealTimeService extends TypedEvent<IPipelineMeta> {
|
||||||
status: IPipelineMeta;
|
status: IPipelineMeta;
|
||||||
pipelineModels?: IPipeline[];
|
pipelineModels?: IPipeline[];
|
||||||
|
@ -13,7 +12,7 @@ export class PipelineRealTimeService extends TypedEvent<IPipelineMeta> {
|
||||||
super();
|
super();
|
||||||
this.init();
|
this.init();
|
||||||
}
|
}
|
||||||
init() {
|
private init(): void {
|
||||||
this.status = {
|
this.status = {
|
||||||
pipelineIsRunning: false,
|
pipelineIsRunning: false,
|
||||||
projectUUID: null,
|
projectUUID: null,
|
||||||
|
|
17
server/src/core/usecases/crete_folder_usecase.ts
Normal file
17
server/src/core/usecases/crete_folder_usecase.ts
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
import { Result } from "../helper/result";
|
||||||
|
import { dirIsExists, createDir } from "../repository/fs";
|
||||||
|
|
||||||
|
export class CreateFolderUseCase {
|
||||||
|
call = async (path: string): Promise<Result<Error, string>> => {
|
||||||
|
try {
|
||||||
|
if (await dirIsExists(path)) {
|
||||||
|
return Result.error(new Error("createFolderUseCase create dir "));
|
||||||
|
}
|
||||||
|
await createDir(path);
|
||||||
|
|
||||||
|
return Result.ok("ok");
|
||||||
|
} catch (error) {
|
||||||
|
return Result.error(error as Error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
33
server/src/features/projects/create_new_project_scenario.ts
Normal file
33
server/src/features/projects/create_new_project_scenario.ts
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
import { App } from "../../core/controllers/app";
|
||||||
|
import { Result } from "../../core/helper/result";
|
||||||
|
import { CreateDataBaseModelUseCase } from "../../core/usecases/create_database_model_usecase";
|
||||||
|
import { CreateFolderUseCase } from "../../core/usecases/crete_folder_usecase";
|
||||||
|
import { ProjectDBModel, ProjectValidationModel } from "./projects_model";
|
||||||
|
import { v4 as uuidv4 } from "uuid";
|
||||||
|
|
||||||
|
export class CreateNewProjectScenario {
|
||||||
|
call = async (model: ProjectValidationModel): Promise<Result<Error, any>> => {
|
||||||
|
try {
|
||||||
|
const folderName = uuidv4() + "/";
|
||||||
|
const createFolderUseCase = await new CreateFolderUseCase().call(
|
||||||
|
App.staticFilesStoreDir() + folderName
|
||||||
|
);
|
||||||
|
if (createFolderUseCase.isFailure()) {
|
||||||
|
return createFolderUseCase.forward();
|
||||||
|
}
|
||||||
|
|
||||||
|
model.rootDir = folderName;
|
||||||
|
const createDataBaseModelUseCase = await new CreateDataBaseModelUseCase(
|
||||||
|
ProjectDBModel
|
||||||
|
).call(model);
|
||||||
|
|
||||||
|
if (createDataBaseModelUseCase.isFailure()) {
|
||||||
|
return createDataBaseModelUseCase.forward();
|
||||||
|
}
|
||||||
|
|
||||||
|
return Result.ok({ status: "ok" });
|
||||||
|
} catch (error) {
|
||||||
|
return Result.error(error as Error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
|
@ -1,8 +1,9 @@
|
||||||
import { Schema, model } from "mongoose";
|
import { Schema, model } from "mongoose";
|
||||||
import { PipelineModel, schemaPipeline } from "../pipelines/pipeline_model";
|
import { PipelineModel, schemaPipeline } from "../pipelines/pipeline_model";
|
||||||
import { IsMongoId, IsString } from "class-validator";
|
import { IsArray, IsOptional, IsString } from "class-validator";
|
||||||
|
|
||||||
export interface IProjectModel {
|
export interface IProjectModel {
|
||||||
|
_id: string;
|
||||||
pipelines: [PipelineModel];
|
pipelines: [PipelineModel];
|
||||||
rootDir: string;
|
rootDir: string;
|
||||||
description: string;
|
description: string;
|
||||||
|
@ -27,13 +28,11 @@ const schema = "Projects";
|
||||||
|
|
||||||
export const ProjectDBModel = model<IProjectModel>(schema, ProjectSchema);
|
export const ProjectDBModel = model<IProjectModel>(schema, ProjectSchema);
|
||||||
|
|
||||||
export class ProjectModel implements IProjectModel {
|
export class ProjectValidationModel {
|
||||||
@IsMongoId()
|
@IsArray()
|
||||||
public pipelines: [PipelineModel];
|
public pipelines: [string];
|
||||||
|
|
||||||
@IsString()
|
|
||||||
public rootDir: string;
|
|
||||||
|
|
||||||
@IsString()
|
@IsString()
|
||||||
public description: string;
|
public description: string;
|
||||||
|
@IsOptional()
|
||||||
|
public rootDir: string;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,16 +1,17 @@
|
||||||
// import { TriggerDBModel, TriggerModel } from "./trigger_model";
|
|
||||||
import { CrudController } from "../../core/controllers/crud_controller";
|
import { CrudController } from "../../core/controllers/crud_controller";
|
||||||
import { ProjectDBModel, ProjectModel } from "./projects_model";
|
import { CreateNewProjectScenario } from "./create_new_project_scenario";
|
||||||
|
import { ProjectDBModel, ProjectValidationModel } from "./projects_model";
|
||||||
|
|
||||||
export class ProjectsPresentation extends CrudController<
|
export class ProjectsPresentation extends CrudController<
|
||||||
ProjectModel,
|
ProjectValidationModel,
|
||||||
typeof ProjectDBModel
|
typeof ProjectDBModel
|
||||||
> {
|
> {
|
||||||
constructor() {
|
constructor() {
|
||||||
super({
|
super({
|
||||||
url: "project",
|
url: "project",
|
||||||
validationModel: ProjectModel,
|
validationModel: ProjectValidationModel,
|
||||||
databaseModel: ProjectDBModel,
|
databaseModel: ProjectDBModel,
|
||||||
});
|
});
|
||||||
|
super.post(new CreateNewProjectScenario().call);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,29 +1,24 @@
|
||||||
|
import { IsString } from "class-validator";
|
||||||
import { CoreHttpController } from "../../core/controllers/http_controller";
|
import { CoreHttpController } from "../../core/controllers/http_controller";
|
||||||
import { Result } from "../../core/helper/result";
|
import { PipelineRealTimeService } from "../../core/services/pipeline_real_time_service";
|
||||||
import { IPipelineMeta } from "../../core/model/pipiline_meta";
|
import { RunInstancePipelineUseCase } from "./usecases/run_instance_pipeline_usecase";
|
||||||
import {
|
import { PipelineStatusUseCase } from "./usecases/pipeline_status_usecase";
|
||||||
PipelineRealTimeService,
|
|
||||||
} from "../../core/services/pipeline_real_time_service";
|
|
||||||
|
|
||||||
export const pipelineRealTimeService = new PipelineRealTimeService();
|
export const pipelineRealTimeService = new PipelineRealTimeService();
|
||||||
|
|
||||||
class PipelineStatusUseCase {
|
export class RealTimeValidationModel {
|
||||||
async call(): Promise<Result<Error, IPipelineMeta>> {
|
@IsString()
|
||||||
try {
|
public id: string;
|
||||||
return Result.ok(pipelineRealTimeService.status);
|
|
||||||
} catch (error) {
|
|
||||||
return Result.error(error as Error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class RealTimePresentation extends CoreHttpController<void> {
|
export class RealTimePresentation extends CoreHttpController<RealTimeValidationModel> {
|
||||||
constructor() {
|
constructor() {
|
||||||
super({
|
super({
|
||||||
validationModel: null,
|
validationModel: RealTimeValidationModel,
|
||||||
url: "realtime",
|
url: "realtime",
|
||||||
databaseModel: null,
|
databaseModel: null,
|
||||||
});
|
});
|
||||||
|
super.post(new RunInstancePipelineUseCase().call);
|
||||||
super.get(new PipelineStatusUseCase().call);
|
super.get(new PipelineStatusUseCase().call);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
import { Result } from "../../../core/helper/result";
|
||||||
|
import { IPipelineMeta } from "../../../core/model/pipeline_meta";
|
||||||
|
import { pipelineRealTimeService } from "../realtime_presentation";
|
||||||
|
|
||||||
|
export class PipelineStatusUseCase {
|
||||||
|
async call(): Promise<Result<Error, IPipelineMeta>> {
|
||||||
|
try {
|
||||||
|
return Result.ok(pipelineRealTimeService.status);
|
||||||
|
} catch (error) {
|
||||||
|
return Result.error(error as Error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
import { Result } from "../../../core/helper/result";
|
||||||
|
import { ReadByIdDataBaseModelUseCase } from "../../../core/usecases/read_by_id_database_model_usecase";
|
||||||
|
import { IProjectModel, ProjectDBModel } from "../../projects/projects_model";
|
||||||
|
import {
|
||||||
|
RealTimeValidationModel,
|
||||||
|
pipelineRealTimeService,
|
||||||
|
} from "../realtime_presentation";
|
||||||
|
|
||||||
|
export class RunInstancePipelineUseCase {
|
||||||
|
async call(model: RealTimeValidationModel): Promise<Result<Error, any>> {
|
||||||
|
const id = model.id;
|
||||||
|
const readByIdDataBaseModelUseCase =
|
||||||
|
await new ReadByIdDataBaseModelUseCase<IProjectModel>(
|
||||||
|
ProjectDBModel
|
||||||
|
).call(id);
|
||||||
|
if (readByIdDataBaseModelUseCase.isFailure()) {
|
||||||
|
return readByIdDataBaseModelUseCase.forward();
|
||||||
|
}
|
||||||
|
|
||||||
|
const projectModel = readByIdDataBaseModelUseCase.value;
|
||||||
|
|
||||||
|
pipelineRealTimeService.runPipeline(
|
||||||
|
projectModel.pipelines,
|
||||||
|
projectModel.rootDir,
|
||||||
|
projectModel._id
|
||||||
|
);
|
||||||
|
|
||||||
|
return Result.ok({ status: "ok" });
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,11 +1,11 @@
|
||||||
import "reflect-metadata";
|
import "reflect-metadata";
|
||||||
import { App } from "./core/controllers/app";
|
import { App } from "./core/controllers/app";
|
||||||
|
import { SocketSubscriber } from "./core/controllers/socket_controller";
|
||||||
import { Routes } from "./core/interfaces/router";
|
import { Routes } from "./core/interfaces/router";
|
||||||
import { TriggerPresentation } from "./features/triggers/triggers_presentation";
|
import { TriggerPresentation } from "./features/triggers/triggers_presentation";
|
||||||
import { ProjectsPresentation } from "./features/projects/projects_presentation";
|
import { ProjectsPresentation } from "./features/projects/projects_presentation";
|
||||||
import { PipelinePresentation } from "./features/pipelines/pipeline_presentation";
|
import { PipelinePresentation } from "./features/pipelines/pipeline_presentation";
|
||||||
import { ProcessPresentation } from "./features/process/process_presentation";
|
import { ProcessPresentation } from "./features/process/process_presentation";
|
||||||
import { SocketSubscriber } from "./core/controllers/socket_controller";
|
|
||||||
import {
|
import {
|
||||||
RealTimePresentation,
|
RealTimePresentation,
|
||||||
pipelineRealTimeService,
|
pipelineRealTimeService,
|
||||||
|
|
|
@ -5,7 +5,6 @@ import { dirname__ } from "../test";
|
||||||
export class PipelineRealTimeServiceTest extends PipelineRealTimeService {
|
export class PipelineRealTimeServiceTest extends PipelineRealTimeService {
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
this.init();
|
|
||||||
}
|
}
|
||||||
async test() {
|
async test() {
|
||||||
this.runPipeline(mockSimplePipeline, dirname__, "");
|
this.runPipeline(mockSimplePipeline, dirname__, "");
|
||||||
|
|
|
@ -1,33 +1,14 @@
|
||||||
import { rmSync } from "fs";
|
import { rmSync } from "fs";
|
||||||
import * as fs from "fs";
|
|
||||||
import { StackService } from "../../src/core/services/stack_service";
|
import { StackService } from "../../src/core/services/stack_service";
|
||||||
import { delay } from "../../src/core/helper/delay";
|
import { delay } from "../../src/core/helper/delay";
|
||||||
import { assert, dirname__ } from "../test";
|
import { assert, dirname__ } from "../test";
|
||||||
import { mockSimplePipeline } from "../model/mock_pipelines";
|
import { mockSimplePipeline } from "../model/mock_pipelines";
|
||||||
|
import { readDirRecursive } from "../../src/core/repository/fs";
|
||||||
|
|
||||||
abstract class IStackServiceTest {
|
abstract class IStackServiceTest {
|
||||||
abstract test(): Promise<boolean>;
|
abstract test(): Promise<boolean>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function readDirRecursive(path: string, filesToDir: string[] = []) {
|
|
||||||
const files = fs.readdirSync(path);
|
|
||||||
files.forEach((file) => {
|
|
||||||
let filePath = "";
|
|
||||||
if (path[path.length - 1] !== "/") {
|
|
||||||
filePath = `${path}/${file}`;
|
|
||||||
} else {
|
|
||||||
filePath = `${path}${file}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
const stats = fs.statSync(filePath);
|
|
||||||
if (stats.isDirectory()) {
|
|
||||||
readDirRecursive(filePath, filesToDir);
|
|
||||||
} else {
|
|
||||||
filesToDir.push(file);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return filesToDir;
|
|
||||||
}
|
|
||||||
|
|
||||||
class SimpleTestStackServiceTest
|
class SimpleTestStackServiceTest
|
||||||
extends StackService
|
extends StackService
|
||||||
|
|
|
@ -14,7 +14,6 @@ import { UpdateDataBaseModelUseCaseTest } from "./usecases/update_database_model
|
||||||
import { PaginationDataBaseModelUseCaseTest } from "./usecases/pagination_database_model_usecase_test";
|
import { PaginationDataBaseModelUseCaseTest } from "./usecases/pagination_database_model_usecase_test";
|
||||||
// import { PipelineRealTimeServiceTest } from "./services/pipeline_real_time_service_test";
|
// import { PipelineRealTimeServiceTest } from "./services/pipeline_real_time_service_test";
|
||||||
|
|
||||||
|
|
||||||
const testCore = TestCore.instance;
|
const testCore = TestCore.instance;
|
||||||
|
|
||||||
export const dirname__: string = dirname(__filename);
|
export const dirname__: string = dirname(__filename);
|
||||||
|
@ -24,30 +23,36 @@ const env = new UnitTestEnv(dirname__);
|
||||||
|
|
||||||
locator(env);
|
locator(env);
|
||||||
|
|
||||||
const tests = [CreateDataBaseModelUseCaseTest, DeleteDataBaseModelUseCaseTest,ReadDataBaseModelUseCaseTest,UpdateDataBaseModelUseCaseTest, PaginationDataBaseModelUseCaseTest]
|
const tests = [
|
||||||
const init = async () =>{
|
CreateDataBaseModelUseCaseTest,
|
||||||
await mongoose.connect('mongodb://127.0.0.1:27017/test')
|
DeleteDataBaseModelUseCaseTest,
|
||||||
}
|
ReadDataBaseModelUseCaseTest,
|
||||||
|
UpdateDataBaseModelUseCaseTest,
|
||||||
|
PaginationDataBaseModelUseCaseTest,
|
||||||
|
];
|
||||||
|
const init = async () => {
|
||||||
|
await mongoose.connect("mongodb://127.0.0.1:27017/test");
|
||||||
|
};
|
||||||
|
|
||||||
const test = async () =>{
|
const test = async () => {
|
||||||
// await new ExecutorProgramServiceTest(dirname__).test();
|
await new ExecutorProgramServiceTest(dirname__).test();
|
||||||
// await new FilesChangerTest(dirname__).test();
|
await new FilesChangerTest(dirname__).test();
|
||||||
await new StackServiceTest(dirname__ + "/context/").test();
|
await new StackServiceTest(dirname__ + "/context/").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();
|
||||||
// await new PipelineRealTimeServiceTest().test()
|
// await new PipelineRealTimeServiceTest().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 main = async () => {
|
const main = async () => {
|
||||||
await init()
|
await init();
|
||||||
await test()
|
await test();
|
||||||
await testCore.testResult();
|
await testCore.testResult();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { CreateDataBaseModelUseCase } from "../../src/core/usecases/create_database_model_usecase";
|
import { CreateDataBaseModelUseCase } from "../../src/core/usecases/create_database_model_usecase";
|
||||||
import { ReadByIdDataBaseModelUseCase } from "../../src/core/usecases/read_database_model_usecase";
|
import { ReadByIdDataBaseModelUseCase } from "../../src/core/usecases/read_by_id_database_model_usecase";
|
||||||
import { ITestModel, TestDBModel } from "../model/test_db_mongo_model";
|
import { ITestModel, TestDBModel } from "../model/test_db_mongo_model";
|
||||||
|
|
||||||
export class ReadDataBaseModelUseCaseTest {
|
export class ReadDataBaseModelUseCaseTest {
|
||||||
|
|
|
@ -1,32 +1,64 @@
|
||||||
|
import { Result } from "../helper/result";
|
||||||
|
|
||||||
export enum HttpMethod {
|
export enum HttpMethod {
|
||||||
GET = 'GET',
|
GET = "GET",
|
||||||
POST = 'POST'
|
POST = "POST",
|
||||||
|
}
|
||||||
|
export class HttpError extends Error {
|
||||||
|
status: number;
|
||||||
|
error: any;
|
||||||
|
constructor(error: any, status: number) {
|
||||||
|
super(error);
|
||||||
|
this.error = error;
|
||||||
|
this.status = status;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class HttpRepository {
|
export class HttpRepository {
|
||||||
|
private server = "http://localhost:4001";
|
||||||
|
|
||||||
private server = 'http://localhost:4001'
|
public async jsonRequest<T>(
|
||||||
|
method: HttpMethod,
|
||||||
|
url: string,
|
||||||
|
data?: any
|
||||||
|
): Promise<Result<HttpError, T>> {
|
||||||
|
try {
|
||||||
|
const reqInit = {
|
||||||
|
body: data,
|
||||||
|
method: method,
|
||||||
|
headers: { "Content-Type": "application/json" },
|
||||||
|
};
|
||||||
|
if (data !== undefined) {
|
||||||
|
reqInit["body"] = JSON.stringify(data);
|
||||||
|
}
|
||||||
|
const response = await fetch(this.server + url, reqInit);
|
||||||
|
|
||||||
public async jsonRequest<T>(method: HttpMethod, url: string, data?: any): Promise<T> {
|
if (response.status !== 200) {
|
||||||
const reqInit = {
|
return Result.error(new HttpError(this.server + url, response.status));
|
||||||
'body': data,
|
}
|
||||||
'method': method,
|
|
||||||
'headers': { 'Content-Type': 'application/json' },
|
return Result.ok(await response.json());
|
||||||
}
|
} catch (error) {
|
||||||
if (data !== undefined) {
|
return Result.error(new HttpError(error, 0));
|
||||||
reqInit['body'] = JSON.stringify(data)
|
|
||||||
}
|
|
||||||
return (await fetch(this.server + url, reqInit)).json()
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public async request<T>(method: HttpMethod, url: string, data?: any): Promise<T> {
|
public async request<T>(
|
||||||
const reqInit = {
|
method: HttpMethod,
|
||||||
'body': data,
|
url: string,
|
||||||
'method': method,
|
data?: any
|
||||||
}
|
): Promise<T> {
|
||||||
if (data !== undefined) {
|
const reqInit = {
|
||||||
reqInit['body'] = data
|
body: data,
|
||||||
}
|
method: method,
|
||||||
return (await fetch(this.server + url, reqInit)).json()
|
};
|
||||||
|
if (data !== undefined) {
|
||||||
|
reqInit["body"] = data;
|
||||||
}
|
}
|
||||||
|
const response = await fetch(this.server + url, reqInit);
|
||||||
|
if (response.status !== 200) {
|
||||||
|
throw new Error(await response.json());
|
||||||
|
}
|
||||||
|
return response.json();
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -7,7 +7,7 @@ export class SocketRepository {
|
||||||
const socket = io(this.serverURL);
|
const socket = io(this.serverURL);
|
||||||
this.socket = socket;
|
this.socket = socket;
|
||||||
socket.connect();
|
socket.connect();
|
||||||
socket.on('mock', (d) =>{
|
socket.on('realtime', (d) =>{
|
||||||
console.log(d)
|
console.log(d)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@ import {
|
||||||
CreatePipelineScreen,
|
CreatePipelineScreen,
|
||||||
CreatePipelineScreenPath,
|
CreatePipelineScreenPath,
|
||||||
} from "../../features/create_pipeline/presentation/create_pipeline_screen";
|
} from "../../features/create_pipeline/presentation/create_pipeline_screen";
|
||||||
|
import { CreateProjectScreen, CreateProjectScreenPath } from "../../features/create_project/create_project_screen";
|
||||||
|
|
||||||
export const router = createBrowserRouter([
|
export const router = createBrowserRouter([
|
||||||
{
|
{
|
||||||
|
@ -33,4 +34,8 @@ export const router = createBrowserRouter([
|
||||||
path: CreatePipelineScreenPath,
|
path: CreatePipelineScreenPath,
|
||||||
element: <CreatePipelineScreen />,
|
element: <CreatePipelineScreen />,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: CreateProjectScreenPath,
|
||||||
|
element: <CreateProjectScreen />,
|
||||||
|
},
|
||||||
]);
|
]);
|
||||||
|
|
|
@ -12,38 +12,39 @@ interface ILoadPage extends IHeader {
|
||||||
children?: JSX.Element | JSX.Element[];
|
children?: JSX.Element | JSX.Element[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export const LoadPage: React.FunctionComponent<ILoadPage> = observer((
|
export const LoadPage: React.FunctionComponent<ILoadPage> = observer(
|
||||||
props: ILoadPage
|
(props: ILoadPage) => {
|
||||||
) => {
|
return (
|
||||||
return (
|
<>
|
||||||
<>
|
<Header
|
||||||
<Header
|
path={props.path}
|
||||||
path={props.path}
|
largeText={props.largeText}
|
||||||
largeText={props.largeText}
|
minText={props.minText}
|
||||||
minText={props.minText}
|
/>
|
||||||
/>
|
{props.isError ? (
|
||||||
{props.isError ? (
|
<>
|
||||||
<>
|
<ErrorIcon
|
||||||
<ErrorIcon
|
style={{
|
||||||
style={{
|
height: "100px",
|
||||||
height: "100px",
|
width: "-webkit-fill-available",
|
||||||
width: "-webkit-fill-available",
|
}}
|
||||||
}}
|
/>
|
||||||
/>
|
<Title style={{ textAlign: "center" }} level={3} type="danger">
|
||||||
<Title style={{ textAlign: "center" }} level={3} type="danger">
|
not expected error
|
||||||
not expected error
|
</Title>
|
||||||
</Title>
|
</>
|
||||||
</>
|
) : (
|
||||||
) : (
|
<>
|
||||||
<></>
|
{props.isLoading ? (
|
||||||
)}
|
<div style={{ marginTop: "50px" }}>
|
||||||
{props.isLoading ? (
|
<Loader />
|
||||||
<div style={{'marginTop':'50px'}}>
|
</div>
|
||||||
<Loader />
|
) : (
|
||||||
</div>
|
<>{props.children}</>
|
||||||
) : (
|
)}
|
||||||
<>{props.children}</>
|
</>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
});
|
}
|
||||||
|
);
|
||||||
|
|
|
@ -9,8 +9,8 @@ export const AllProjectScreen: React.FunctionComponent = () => {
|
||||||
<>
|
<>
|
||||||
<Header
|
<Header
|
||||||
path={SelectProjectScreenPath}
|
path={SelectProjectScreenPath}
|
||||||
largeText={"All Projects"}
|
largeText={"Projects"}
|
||||||
minText={"create new pipiline?"}
|
minText={"select instance project?"}
|
||||||
needBackButton={true}
|
needBackButton={true}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
|
|
|
@ -5,35 +5,22 @@ import {
|
||||||
import { ITriggerModel } from "../../../core/model/trigger_model";
|
import { ITriggerModel } from "../../../core/model/trigger_model";
|
||||||
import { Result } from "../../../core/helper/result";
|
import { Result } from "../../../core/helper/result";
|
||||||
import { IProcess } from "../../create_process/model/process_model";
|
import { IProcess } from "../../create_process/model/process_model";
|
||||||
import { PipelineModelDataBase } from "../model/pipiline_model";
|
import { PipelineModelDataBase } from "../model/pipeline_model";
|
||||||
|
|
||||||
export class CreatePipelineRepository extends HttpRepository {
|
export class CreatePipelineRepository extends HttpRepository {
|
||||||
async savePipeline(model: PipelineModelDataBase): Promise<Result<Error, any>> {
|
async savePipeline(
|
||||||
try {
|
model: PipelineModelDataBase
|
||||||
return await Result.ok(
|
): Promise<Result<Error, any>> {
|
||||||
this.jsonRequest(HttpMethod.POST, `/pipeline`, model)
|
return await this.jsonRequest(HttpMethod.POST, `/pipeline`, model);
|
||||||
);
|
|
||||||
} catch (error) {
|
|
||||||
return Result.error(error as Error);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
async getTriggers(page = 1): Promise<Result<Error, ITriggerModel[]>> {
|
async getTriggers(page = 1): Promise<Result<Error, ITriggerModel[]>> {
|
||||||
try {
|
return await this.jsonRequest(HttpMethod.GET, `/trigger?${page}`);
|
||||||
return Result.ok(
|
|
||||||
await this.jsonRequest(HttpMethod.GET, `/trigger?${page}`)
|
|
||||||
);
|
|
||||||
} catch (error) {
|
|
||||||
return Result.error(error as Error);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async getProcessed(page = 1): Promise<Result<Error, IProcess[]>> {
|
async getProcessed(page = 1): Promise<Result<Error, IProcess[]>> {
|
||||||
try {
|
return await this.jsonRequest<IProcess[]>(
|
||||||
return Result.ok(
|
HttpMethod.GET,
|
||||||
await this.jsonRequest<IProcess[]>(HttpMethod.GET, `/process?${page}`)
|
`/process?${page}`
|
||||||
);
|
);
|
||||||
} catch (error) {
|
|
||||||
return Result.error(error as Error);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ import {
|
||||||
HttpRepository,
|
HttpRepository,
|
||||||
} from "../../core/repository/http_repository";
|
} from "../../core/repository/http_repository";
|
||||||
import { IProcess } from "../create_process/model/process_model";
|
import { IProcess } from "../create_process/model/process_model";
|
||||||
|
import { ICreateProjectViewModel } from "./project_model";
|
||||||
|
|
||||||
export interface PipelineModel extends DatabaseModel {
|
export interface PipelineModel extends DatabaseModel {
|
||||||
process: IProcess;
|
process: IProcess;
|
||||||
|
@ -14,12 +15,11 @@ export interface PipelineModel extends DatabaseModel {
|
||||||
|
|
||||||
export class CreateProjectRepository extends HttpRepository {
|
export class CreateProjectRepository extends HttpRepository {
|
||||||
async getAllPipelines(page = 1): Promise<Result<Error, PipelineModel[]>> {
|
async getAllPipelines(page = 1): Promise<Result<Error, PipelineModel[]>> {
|
||||||
try {
|
return await this.jsonRequest<PipelineModel[]>(HttpMethod.GET, "/pipeline");
|
||||||
return Result.ok(
|
}
|
||||||
await this.jsonRequest<PipelineModel[]>(HttpMethod.GET, "/pipeline")
|
async saveProject(
|
||||||
);
|
model: ICreateProjectViewModel
|
||||||
} catch (error) {
|
): Promise<Result<Error, void>> {
|
||||||
return Result.error(error as Error);
|
return await this.jsonRequest<void>(HttpMethod.POST, "/project", model);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,89 @@
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
export const createProjectScreenPath = "/create_project";
|
import { LoadPage } from "../../core/ui/pages/load_page";
|
||||||
|
import { createProjectStore } from "./create_project_store";
|
||||||
|
import { observer } from "mobx-react-lite";
|
||||||
|
import { Col, Row, Input, Button } from "antd";
|
||||||
|
import { ReactComponent as AddIcon } from "../../core/assets/icons/add.svg";
|
||||||
|
import { CreatePipelineScreenPath } from "../create_pipeline/presentation/create_pipeline_screen";
|
||||||
|
|
||||||
export const CreateProjectScreen: React.FunctionComponent = () => {
|
export const CreateProjectScreenPath = "/create_project";
|
||||||
return <></>;
|
|
||||||
};
|
export const CreateProjectScreen: React.FunctionComponent = observer(() => {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<LoadPage
|
||||||
|
path={CreatePipelineScreenPath}
|
||||||
|
largeText={"Create project"}
|
||||||
|
minText={"add new pipelines?"}
|
||||||
|
isLoading={createProjectStore.isLoading}
|
||||||
|
isError={createProjectStore.isError}
|
||||||
|
children={
|
||||||
|
<Row>
|
||||||
|
<Col>
|
||||||
|
<>Pipelines</>
|
||||||
|
{createProjectStore.pipelineModels?.map((el) => {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
backgroundColor: "ActiveBorder",
|
||||||
|
margin: "10px",
|
||||||
|
width: "400px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div>{el.process.description}</div>
|
||||||
|
<div>{el.trigger.description}</div>
|
||||||
|
<AddIcon
|
||||||
|
style={{
|
||||||
|
width: "50px",
|
||||||
|
cursor: "pointer",
|
||||||
|
height: "50px",
|
||||||
|
marginRight: "40px",
|
||||||
|
}}
|
||||||
|
onClick={() => {
|
||||||
|
createProjectStore.addPipeline(el);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</Col>
|
||||||
|
<Col>
|
||||||
|
|
||||||
|
<Row>
|
||||||
|
<Input
|
||||||
|
style={{ width: "250px" }}
|
||||||
|
onChange={(e) =>
|
||||||
|
createProjectStore.setDescriptionToNewProject(
|
||||||
|
e.target.value
|
||||||
|
)
|
||||||
|
}
|
||||||
|
placeholder="project description"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Button onClick={() => createProjectStore.saveProject()}>
|
||||||
|
save
|
||||||
|
</Button>
|
||||||
|
</Row>
|
||||||
|
|
||||||
|
{createProjectStore.newProjectViews.map((el, index) => {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
backgroundColor: "ActiveBorder",
|
||||||
|
margin: "10px",
|
||||||
|
width: "400px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div>{el.process.description}</div>
|
||||||
|
<div>{el.trigger.description}</div>
|
||||||
|
<div>{index + 1}</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
|
@ -3,12 +3,15 @@ import {
|
||||||
CreateProjectRepository,
|
CreateProjectRepository,
|
||||||
PipelineModel,
|
PipelineModel,
|
||||||
} from "./create_project_repository";
|
} from "./create_project_repository";
|
||||||
|
import { message } from "antd";
|
||||||
|
|
||||||
class ProcessStore {
|
class CreateProjectStore {
|
||||||
repository: CreateProjectRepository;
|
repository: CreateProjectRepository;
|
||||||
isLoading = false;
|
isLoading = false;
|
||||||
isError = false;
|
isError = false;
|
||||||
pipelineModels?: PipelineModel[];
|
pipelineModels?: PipelineModel[];
|
||||||
|
newProjectDescription: string = "";
|
||||||
|
newProjectViews: PipelineModel[] = [];
|
||||||
|
|
||||||
constructor(repository: CreateProjectRepository) {
|
constructor(repository: CreateProjectRepository) {
|
||||||
this.repository = repository;
|
this.repository = repository;
|
||||||
|
@ -16,6 +19,10 @@ class ProcessStore {
|
||||||
this.loadPipelines();
|
this.loadPipelines();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async addPipeline(model: PipelineModel) {
|
||||||
|
this.newProjectViews.push(model);
|
||||||
|
}
|
||||||
|
|
||||||
async loadPipelines() {
|
async loadPipelines() {
|
||||||
this.isLoading = true;
|
this.isLoading = true;
|
||||||
const result = await this.repository.getAllPipelines();
|
const result = await this.repository.getAllPipelines();
|
||||||
|
@ -29,6 +36,42 @@ class ProcessStore {
|
||||||
);
|
);
|
||||||
this.isLoading = false;
|
this.isLoading = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setDescriptionToNewProject(value: string): void {
|
||||||
|
this.newProjectDescription = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
async saveProject(): Promise<void> {
|
||||||
|
if (this.newProjectDescription.isEmpty()) {
|
||||||
|
message.error("project description is not empty");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (this.newProjectViews.isEmpty()) {
|
||||||
|
message.error("project view is not empty");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.isLoading = true;
|
||||||
|
const result = await this.repository.saveProject({
|
||||||
|
description: this.newProjectDescription,
|
||||||
|
pipelines: this.newProjectViews.map((el) => el._id ?? ""),
|
||||||
|
});
|
||||||
|
|
||||||
|
this.newProjectDescription = "";
|
||||||
|
this.newProjectViews = [];
|
||||||
|
this.isLoading = false;
|
||||||
|
|
||||||
|
result.fold(
|
||||||
|
(_s) => {
|
||||||
|
message.success("save");
|
||||||
|
},
|
||||||
|
(_e) => {
|
||||||
|
this.isError = true;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const processStore = new ProcessStore(new CreateProjectRepository());
|
export const createProjectStore = new CreateProjectStore(
|
||||||
|
new CreateProjectRepository()
|
||||||
|
);
|
||||||
|
|
||||||
|
|
5
ui/src/features/create_project/project_model.ts
Normal file
5
ui/src/features/create_project/project_model.ts
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
export interface ICreateProjectViewModel {
|
||||||
|
pipelines: string[];
|
||||||
|
|
||||||
|
description: string;
|
||||||
|
}
|
|
@ -7,12 +7,6 @@ import { IProjectModel } from "../model/project_model";
|
||||||
|
|
||||||
export class SelectProjectRepository extends HttpRepository {
|
export class SelectProjectRepository extends HttpRepository {
|
||||||
async getAllProjects(page = 1): Promise<Result<Error, IProjectModel[]>> {
|
async getAllProjects(page = 1): Promise<Result<Error, IProjectModel[]>> {
|
||||||
try {
|
return await this.jsonRequest(HttpMethod.GET, `/project?${page}`);
|
||||||
return Result.ok(
|
|
||||||
await this.jsonRequest(HttpMethod.GET, `/project?${page}`)
|
|
||||||
);
|
|
||||||
} catch (error) {
|
|
||||||
return Result.error(error as Error);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,8 @@
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import { selectProjectStore } from "./select_project_store";
|
import { selectProjectStore } from "./select_project_store";
|
||||||
import { Loader } from "../../../core/ui/loader/loader";
|
|
||||||
import { observer } from "mobx-react-lite";
|
import { observer } from "mobx-react-lite";
|
||||||
import { Header } from "../../../core/ui/header/header";
|
|
||||||
import { CreatePipelineScreenPath } from "../../create_pipeline/presentation/create_pipeline_screen";
|
|
||||||
import { LoadPage } from "../../../core/ui/pages/load_page";
|
import { LoadPage } from "../../../core/ui/pages/load_page";
|
||||||
|
import { CreateProjectScreenPath } from "../../create_project/create_project_screen";
|
||||||
|
|
||||||
export const SelectProjectScreenPath = "/select_project";
|
export const SelectProjectScreenPath = "/select_project";
|
||||||
|
|
||||||
|
@ -12,7 +10,7 @@ export const SelectProjectScreen: React.FunctionComponent = observer(() => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<LoadPage
|
<LoadPage
|
||||||
path={CreatePipelineScreenPath}
|
path={CreateProjectScreenPath}
|
||||||
largeText={"Select project"}
|
largeText={"Select project"}
|
||||||
minText={"add new project?"}
|
minText={"add new project?"}
|
||||||
isLoading={selectProjectStore.isLoading}
|
isLoading={selectProjectStore.isLoading}
|
||||||
|
|
|
@ -8,7 +8,9 @@ class SocketListerStore {
|
||||||
constructor(repository: SocketRepository) {
|
constructor(repository: SocketRepository) {
|
||||||
this.repository = repository;
|
this.repository = repository;
|
||||||
makeAutoObservable(this);
|
makeAutoObservable(this);
|
||||||
|
repository.connect()
|
||||||
}
|
}
|
||||||
|
|
||||||
async reconnect() {
|
async reconnect() {
|
||||||
await this.repository.connect()
|
await this.repository.connect()
|
||||||
this.socketDisconnect = false
|
this.socketDisconnect = false
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue