This commit is contained in:
IDONTSUDO 2023-11-10 21:43:57 +03:00
parent 6446da7e76
commit 6f86377685
18 changed files with 274 additions and 107 deletions

View file

@ -1,10 +1,7 @@
import { IsMongoId, IsEnum } from "class-validator";
import { IsMongoId, IsEnum, IsOptional } from "class-validator";
import { Schema, model } from "mongoose";
import { IProcess, StackGenerateType } from "../../core/model/process_model";
import {
TriggerModel,
triggerSchema,
} from "../triggers/trigger_model";
import { TriggerModel, triggerSchema } from "../triggers/trigger_model";
import { schemaProcess } from "../process/process_model";
export const PipelineSchema = new Schema({
@ -19,7 +16,7 @@ export const PipelineSchema = new Schema({
ref: triggerSchema,
autopopulate: true,
default: null,
}
},
}).plugin(require("mongoose-autopopulate"));
export const schemaPipeline = "Pipeline";
@ -37,8 +34,9 @@ export class PipelineModel {
//TODO(IDONTSUDO):NEED OPTION DECORATOR??
public trigger: TriggerModel;
@IsOptional()
public env = null;
@IsEnum(StackGenerateType)
@IsOptional()
public stackGenerateType: StackGenerateType;
}

View file

@ -24,3 +24,4 @@ const socketSubscribers = [
];
new App(httpRoutes, socketSubscribers).listen();

View file

@ -1,13 +1,3 @@
export {};
declare global {
interface Array<T> {
// @strict: The parameter is determined whether the arrays must be exactly the same in content and order of this relationship or simply follow the same requirements.
equals(array: Array<T>, strict: boolean): boolean;
lastElement(): T | undefined;
}
}
export const ArrayExtensions = () => {
if ([].equals === undefined) {
// eslint-disable-next-line no-extend-native
@ -42,4 +32,10 @@ export const ArrayExtensions = () => {
}
};
}
if ([].isEmpty === undefined) {
// eslint-disable-next-line no-extend-native
Array.prototype.isEmpty = function () {
return this.length === 0;
};
}
};

View file

@ -1,6 +1,18 @@
import { ArrayExtensions } from "./array";
import { StringExtensions } from "./string";
export const extensions = () =>{
ArrayExtensions()
declare global {
interface Array<T> {
// @strict: The parameter is determined whether the arrays must be exactly the same in content and order of this relationship or simply follow the same requirements.
equals(array: Array<T>, strict: boolean): boolean;
lastElement(): T | undefined;
isEmpty(): boolean;
}
interface String {
isEmpty(): boolean;
}
}
export const extensions = () => {
ArrayExtensions();
StringExtensions();
};

View file

@ -0,0 +1,8 @@
export const StringExtensions = () => {
if ("".isEmpty === undefined) {
// eslint-disable-next-line no-extend-native
String.prototype.isEmpty = function () {
return this.length === 0;
};
}
};

View file

@ -0,0 +1,3 @@
export interface DatabaseModel {
_id?: string;
}

View file

@ -1,7 +1,8 @@
export interface ITriggerModel {
_id?: string;
import { DatabaseModel } from "./database_model";
export interface ITriggerModel extends DatabaseModel {
type: string;
description:string;
description: string;
value: string[];
}

View file

@ -25,7 +25,7 @@ export const Header: React.FunctionComponent<IHeader> = (props: IHeader) => {
marginTop: "20px",
marginRight: "20px",
display: "contents",
}}
}}
>
{needBackButton ? (
<>

View file

@ -1,50 +1,82 @@
import { Row } from "antd";
import { ReactComponent as AddIcon } from "../../assets/icons/add.svg";
import { observer } from "mobx-react-lite";
import { ReactComponent as DeleteIcon } from "../../assets/icons/delete.svg";
export type CallBackFunction = (a: string) => void;
import { observer } from "mobx-react-lite";
import { v4 } from "uuid";
export type CallBackFunction = (el: ListElement, index: number) => void;
export interface ListElement {
id?: string;
text: string;
color?: string;
}
export enum Icon {
add,
delete,
}
export interface IPropsList {
values: ListElement[];
headers?: string;
onClick?: CallBackFunction;
icon: Icon;
}
export const List: React.FunctionComponent<IPropsList> = observer(
(props) => {
return (
<div>
{props.headers !== undefined ? <>{props.headers}</> : <></>}
{props.values.map((el) => {
return (
<Row
export const List: React.FunctionComponent<IPropsList> = observer((props) => {
props.values.map((el) => {
if (el.id === undefined) {
el.id = v4();
return el
}
return el
});
return (
<div>
{props.headers !== undefined ? <>{props.headers}</> : <></>}
{props.values.map((el, index) => {
return (
<Row
style={{
width: "300px",
backgroundColor: el.color ?? "ActiveBorder",
}}
>
<div
style={{
width: "300px",
backgroundColor: el.color ?? "ActiveBorder",
width: "-webkit-fill-available",
margin: "5px",
marginLeft: "40px",
}}
/>
<div
style={{
marginLeft: "40px",
}}
>
<div
style={{
width: "-webkit-fill-available",
margin: "5px",
marginLeft: "40px",
}}
/>
<div
style={{
marginLeft: "40px",
}}
>
{el.text}
</div>
<div style={{ flexGrow: "1" }}></div>
<AddIcon
{el.text}
</div>
<div style={{ flexGrow: "1" }}></div>
{props.icon === Icon.add ? (
<>
<AddIcon
style={{
width: "50px",
cursor: "pointer",
height: "50px",
marginRight: "40px",
}}
onClick={() => {
if (props.onClick !== undefined) {
props.onClick(el, index);
}
}}
/>
</>
) : (
<DeleteIcon
style={{
width: "50px",
cursor: "pointer",
@ -53,14 +85,14 @@ export const List: React.FunctionComponent<IPropsList> = observer(
}}
onClick={() => {
if (props.onClick !== undefined) {
props.onClick(el.text);
props.onClick(el, index);
}
}}
/>
</Row>
);
})}
</div>
);
}
);
)}
</Row>
);
})}
</div>
);
});

View file

@ -5,8 +5,18 @@ import {
import { ITriggerModel } from "../../../core/model/trigger_model";
import { Result } from "../../../core/helper/result";
import { IProcess } from "../../create_process/model/process_model";
import { PipelineModelDataBase } from "../model/pipiline_model";
export class CreatePipelineRepository extends HttpRepository {
async savePipeline(model: PipelineModelDataBase): Promise<Result<Error, any>> {
try {
return await Result.ok(
this.jsonRequest(HttpMethod.POST, `/pipeline`, model)
);
} catch (error) {
return Result.error(error as Error);
}
}
async getTriggers(page = 1): Promise<Result<Error, ITriggerModel[]>> {
try {
return Result.ok(

View file

@ -1,3 +1,8 @@
export interface IColor {
color:string;
color: string;
}
export interface PipelineModelDataBase {
process: string;
trigger: string;
}

View file

@ -1,9 +1,9 @@
import * as React from "react";
import { Row, Input, Button } from "antd";
import { Row, Button } from "antd";
import { LoadPage } from "../../../core/ui/pages/load_page";
import { createPipelineStore } from "./create_pipeline_store";
import { observer } from "mobx-react-lite";
import { List } from "../../../core/ui/list/list";
import { Icon, List } from "../../../core/ui/list/list";
export const CreatePipelineScreenPath = "/create_pipeline";
@ -20,27 +20,32 @@ export const CreatePipelineScreen: React.FunctionComponent = observer(() => {
<List
headers={"process"}
values={createPipelineStore.processModels.map((el) => {
return { text: el.description };
return { text: el.description, id: el._id };
})}
onClick={(e) => createPipelineStore.addProcess(e)}
onClick={(e) => createPipelineStore.addProcess(e.text, e.id!)}
icon={Icon.add}
/>
<div style={{ flexGrow: "1" }}>
<Input style={{ width: "300px" }} placeholder="description" />
<Button onClick={() => createPipelineStore.createPipeline()}>
Save result
</Button>
<List
headers="new pipeline"
values={createPipelineStore.pipelineViewModel }
values={createPipelineStore.pipelineViewModels}
icon={Icon.delete}
onClick={(_e, index) => {
createPipelineStore.filterPipelineViewModel(index);
}}
/>
</div>
<List
headers="triggers"
values={createPipelineStore.triggersModels.map((el) => {
return { text: el.description };
return { text: el.description, id: el._id };
})}
onClick={(e) => createPipelineStore.addTrigger(e)}
onClick={(e) => createPipelineStore.addTrigger(e.text, e.id!)}
icon={Icon.add}
/>
</Row>
</>

View file

@ -2,26 +2,26 @@ import { makeAutoObservable } from "mobx";
import { CreatePipelineRepository } from "../data/create_pipeline_repository";
import { ITriggerModel } from "../../../core/model/trigger_model";
import { IProcess } from "../../create_process/model/process_model";
// TODO:()rename
enum Direction {
import { message } from "antd";
enum Type {
PROCESS,
TRIGGER,
}
interface CommonView {
export interface UnionView {
text: string;
color: string;
type: Direction;
type: Type;
uuid?: string;
}
export class CreatePipelineStore {
repository: CreatePipelineRepository;
triggersModels: ITriggerModel[] = [];
processModels: IProcess[] = [];
pipelineViewModel: CommonView[] = [];
pipelineViewModels: UnionView[] = [];
isLoading = false;
isError = false;
page = 1;
constructor(repository: CreatePipelineRepository) {
this.repository = repository;
@ -29,40 +29,68 @@ export class CreatePipelineStore {
this.loadTriggers();
this.loadProcess();
}
addProcess(e: string): void {
const lastElement = this.pipelineViewModel.lastElement()
if(lastElement !== undefined){
if(lastElement.type !== Direction.TRIGGER){
// need UI say
return
}
}
this.pipelineViewModel.push({
text: e,
color: "activeborder",
type: Direction.PROCESS,
});
filterPipelineViewModel(index: number): void {
this.pipelineViewModels = this.pipelineViewModels.filter(
(_el, i) => i !== index
);
}
addTrigger(e: string, id: string): void {
const lastElement = this.pipelineViewModels.lastElement();
if (this.pipelineViewModels.length === 2) {
return;
}
if (lastElement !== undefined) {
if (lastElement.type !== Type.PROCESS) {
message.error("Need process");
addTrigger(e: string): void {
const lastElement = this.pipelineViewModel.lastElement()
if(lastElement !== undefined){
if(lastElement.type !== Direction.PROCESS){
// need UI say
return
return;
}
}
this.pipelineViewModel.push({
this.pipelineViewModels.push({
uuid: id,
text: e,
color: "blanchedalmond",
type: Direction.TRIGGER,
type: Type.TRIGGER,
});
}
createPipeline(): void {}
addProcess(e: string, id: string): void {
const lastElement = this.pipelineViewModels.lastElement();
if (this.pipelineViewModels.length === 2) {
return;
}
if (lastElement !== undefined) {
if (lastElement.type !== Type.TRIGGER) {
message.error("Need trigger");
return;
}
}
this.pipelineViewModels.push({
uuid: id,
text: e,
color: "activeborder",
type: Type.PROCESS,
});
}
async createPipeline(): Promise<void> {
if (this.pipelineViewModels.isEmpty()) {
message.error("not found pipelines process");
return;
}
const triggerId = this.pipelineViewModels.find(
(el) => el.type === Type.TRIGGER
)!.uuid as string;
const processId = this.pipelineViewModels.find(
(el) => el.type === Type.PROCESS
)!.uuid as string;
this.repository.savePipeline({
process: processId,
trigger: triggerId,
});
}
async loadProcess() {
this.isLoading = true;
const result = await this.repository.getProcessed();
@ -76,9 +104,10 @@ export class CreatePipelineStore {
);
this.isLoading = false;
}
async loadTriggers() {
this.isLoading = true;
const result = await this.repository.getTriggers(this.page);
const result = await this.repository.getTriggers(1);
result.fold(
(s) => {
this.triggersModels = s;

View file

@ -1,4 +1,6 @@
export interface IProcess {
import { DatabaseModel } from "../../../core/model/database_model";
export interface IProcess extends DatabaseModel {
description: string;
type: EXEC_TYPE | string;
command: string;
@ -17,6 +19,7 @@ export enum IssueType {
ERROR = "ERROR",
}
export const processModelMock: IProcess = {
_id: "",
description: "",
type: EXEC_TYPE.SPAWN,
command: "",

View file

@ -1,5 +1,4 @@
import { makeAutoObservable } from "mobx";
import { v4 as uuidv4 } from "uuid";
import { ProcessRepository } from "../../data/process_repostiory";
import { IProcess } from "../../model/process_model";

View file

@ -0,0 +1,25 @@
import { Result } from "../../core/helper/result";
import { DatabaseModel } from "../../core/model/database_model";
import { ITriggerModel } from "../../core/model/trigger_model";
import {
HttpMethod,
HttpRepository,
} from "../../core/repository/http_repository";
import { IProcess } from "../create_process/model/process_model";
export interface PipelineModel extends DatabaseModel {
process: IProcess;
trigger: ITriggerModel;
}
export class CreateProjectRepository extends HttpRepository {
async getAllPipelines(page = 1): Promise<Result<Error, PipelineModel[]>> {
try {
return Result.ok(
await this.jsonRequest<PipelineModel[]>(HttpMethod.GET, "/pipeline")
);
} catch (error) {
return Result.error(error as Error);
}
}
}

View file

@ -0,0 +1,6 @@
import * as React from "react";
export const createProjectScreenPath = "/create_project";
export const CreateProjectScreen: React.FunctionComponent = () => {
return <></>;
};

View file

@ -0,0 +1,34 @@
import { makeAutoObservable } from "mobx";
import {
CreateProjectRepository,
PipelineModel,
} from "./create_project_repository";
class ProcessStore {
repository: CreateProjectRepository;
isLoading = false;
isError = false;
pipelineModels?: PipelineModel[];
constructor(repository: CreateProjectRepository) {
this.repository = repository;
makeAutoObservable(this);
this.loadPipelines();
}
async loadPipelines() {
this.isLoading = true;
const result = await this.repository.getAllPipelines();
result.fold(
(s) => {
this.pipelineModels = s;
},
(_e) => {
this.isError = true;
}
);
this.isLoading = false;
}
}
export const processStore = new ProcessStore(new CreateProjectRepository());