progress
This commit is contained in:
parent
c17515d571
commit
0c03906518
25 changed files with 475 additions and 201 deletions
31
.vscode/settings.json
vendored
31
.vscode/settings.json
vendored
|
@ -1,32 +1,3 @@
|
||||||
{
|
{
|
||||||
"files.exclude": {
|
"cSpell.words": ["Ведите"]
|
||||||
"**/.git": false,
|
|
||||||
"**/.svn": false,
|
|
||||||
"**/.hg": false,
|
|
||||||
"**/CVS": false,
|
|
||||||
"**/__pycache__": false,
|
|
||||||
"*.DS_Store": false,
|
|
||||||
"*.DS_Store.*": false,
|
|
||||||
"*.git": false,
|
|
||||||
"*.git.*": false,
|
|
||||||
"*.vscode": false,
|
|
||||||
"*.vscode.*": false,
|
|
||||||
"*server.*": false,
|
|
||||||
"*ui": false,
|
|
||||||
"*ui.*": false
|
|
||||||
},
|
|
||||||
"cSpell.words": [
|
|
||||||
"запущен",
|
|
||||||
"процесс",
|
|
||||||
"antd",
|
|
||||||
"Collada",
|
|
||||||
"Contolls",
|
|
||||||
"fileupload",
|
|
||||||
"lerp",
|
|
||||||
"metadatas",
|
|
||||||
"Skils",
|
|
||||||
"undici",
|
|
||||||
"uuidv"
|
|
||||||
],
|
|
||||||
"editor.rulers": [100]
|
|
||||||
}
|
}
|
||||||
|
|
2
p.ts
2
p.ts
|
@ -1,2 +0,0 @@
|
||||||
console.log([1, 2, 3, 4, 5, 6].reduce((element, acc) => (acc += element)));
|
|
||||||
console.log(["1", "2", "3", "4", "5", "6"].reduce((element, acc) => (acc += element)));
|
|
|
@ -13,7 +13,6 @@ export class ReadingJsonFileAndConvertingToInstanceClassScenario<T> {
|
||||||
}
|
}
|
||||||
call = async (path: string): Promise<Result<string, T>> => {
|
call = async (path: string): Promise<Result<string, T>> => {
|
||||||
try {
|
try {
|
||||||
console.log(path);
|
|
||||||
const result = await new ReadFileAndParseJsonUseCase().call(path);
|
const result = await new ReadFileAndParseJsonUseCase().call(path);
|
||||||
if (result.isFailure()) {
|
if (result.isFailure()) {
|
||||||
return result.forward();
|
return result.forward();
|
||||||
|
|
|
@ -8,7 +8,6 @@ export class CreateFolderUseCase {
|
||||||
}
|
}
|
||||||
call = async (path: string): Promise<Result<Error, string>> => {
|
call = async (path: string): Promise<Result<Error, string>> => {
|
||||||
try {
|
try {
|
||||||
console.log(path);
|
|
||||||
if (await this.fileSystemRepository.dirIsExists(path)) {
|
if (await this.fileSystemRepository.dirIsExists(path)) {
|
||||||
return Result.ok("ok");
|
return Result.ok("ok");
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,7 +31,6 @@ export class ExecProcessUseCase {
|
||||||
try {
|
try {
|
||||||
executorProgramService.execPath = path;
|
executorProgramService.execPath = path;
|
||||||
executorProgramService.on((event) => {
|
executorProgramService.on((event) => {
|
||||||
console.log(event);
|
|
||||||
if (watcher) watcher.emit(event);
|
if (watcher) watcher.emit(event);
|
||||||
});
|
});
|
||||||
executorProgramService.call(EXEC_TYPE.EXEC, command);
|
executorProgramService.call(EXEC_TYPE.EXEC, command);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { CrudController } from "../../core/controllers/crud_controller";
|
import { CrudController } from "../../core/controllers/crud_controller";
|
||||||
import { IsHaveActiveProcessUseCase, KillLastProcessUseCase } from "../../core/usecases/exec_process_usecase";
|
import { IsHaveActiveProcessUseCase, KillLastProcessUseCase } from "../../core/usecases/exec_process_usecase";
|
||||||
import { CreateDataSetScenario } from "./domain/create_dataset_scanario";
|
import { CreateDataSetScenario } from "./domain/create_dataset_scenario";
|
||||||
import { ExecDatasetProcessScenario } from "./domain/exec_process_scenario";
|
import { ExecDatasetProcessScenario } from "./domain/exec_process_scenario";
|
||||||
import { GetDatasetActiveProjectScenario } from "./domain/get_dataset_active_project_scenario";
|
import { GetDatasetActiveProjectScenario } from "./domain/get_dataset_active_project_scenario";
|
||||||
import { DatasetDBModel } from "./models/dataset_database_model";
|
import { DatasetDBModel } from "./models/dataset_database_model";
|
||||||
|
|
|
@ -4,11 +4,10 @@ import { Result } from "../../../core/helpers/result";
|
||||||
import { TypedEvent } from "../../../core/helpers/typed_event";
|
import { TypedEvent } from "../../../core/helpers/typed_event";
|
||||||
import { EXEC_EVENT, ExecError, SpawnError } from "../../../core/models/exec_error_model";
|
import { EXEC_EVENT, ExecError, SpawnError } from "../../../core/models/exec_error_model";
|
||||||
import { ExecutorResult } from "../../../core/models/executor_result";
|
import { ExecutorResult } from "../../../core/models/executor_result";
|
||||||
import { ExecProcessUseCase } from "../../../core/usecases/exec_process_usecase";
|
|
||||||
import { SearchDataBaseModelUseCase } from "../../../core/usecases/search_database_model_usecase";
|
import { SearchDataBaseModelUseCase } from "../../../core/usecases/search_database_model_usecase";
|
||||||
import { IProjectModel, ProjectDBModel } from "../../_projects/models/project_database_model";
|
import { IProjectModel, ProjectDBModel } from "../../_projects/models/project_database_model";
|
||||||
import { DatasetDBModel } from "../models/dataset_database_model";
|
import { DatasetDBModel } from "../models/dataset_database_model";
|
||||||
import { DatasetValidationModel } from "../models/dataset_validation_model";
|
import { DatasetValidationModel, ProcessStatus } from "../models/dataset_validation_model";
|
||||||
|
|
||||||
export class ProcessWatcherAndDatabaseUpdateService extends TypedEvent<Result<ExecError | SpawnError, ExecutorResult>> {
|
export class ProcessWatcherAndDatabaseUpdateService extends TypedEvent<Result<ExecError | SpawnError, ExecutorResult>> {
|
||||||
databaseId: ObjectId;
|
databaseId: ObjectId;
|
||||||
|
@ -25,7 +24,7 @@ export class ProcessWatcherAndDatabaseUpdateService extends TypedEvent<Result<Ex
|
||||||
const dbModel = await DatasetDBModel.findById(this.databaseId);
|
const dbModel = await DatasetDBModel.findById(this.databaseId);
|
||||||
if (dbModel !== null) {
|
if (dbModel !== null) {
|
||||||
dbModel.local_path;
|
dbModel.local_path;
|
||||||
dbModel.processStatus = "end";
|
dbModel.processStatus = ProcessStatus.END;
|
||||||
dbModel.processLogs = success.data;
|
dbModel.processLogs = success.data;
|
||||||
await dbModel.save();
|
await dbModel.save();
|
||||||
}
|
}
|
||||||
|
@ -34,7 +33,7 @@ export class ProcessWatcherAndDatabaseUpdateService extends TypedEvent<Result<Ex
|
||||||
async (error) => {
|
async (error) => {
|
||||||
const dbModel = await DatasetDBModel.findById(this.databaseId);
|
const dbModel = await DatasetDBModel.findById(this.databaseId);
|
||||||
if (dbModel !== null) {
|
if (dbModel !== null) {
|
||||||
dbModel.processStatus = "error";
|
dbModel.processStatus = ProcessStatus.ERROR;
|
||||||
dbModel.processLogs = error.message;
|
dbModel.processLogs = error.message;
|
||||||
await dbModel.save();
|
await dbModel.save();
|
||||||
}
|
}
|
||||||
|
@ -48,7 +47,7 @@ export class CreateDataSetScenario extends CallbackStrategyWithValidationModel<D
|
||||||
return (
|
return (
|
||||||
await new SearchDataBaseModelUseCase<IProjectModel>(ProjectDBModel).call({ isActive: true }, "no active projects")
|
await new SearchDataBaseModelUseCase<IProjectModel>(ProjectDBModel).call({ isActive: true }, "no active projects")
|
||||||
).map(async (project) => {
|
).map(async (project) => {
|
||||||
model.processStatus = "new";
|
model.processStatus = ProcessStatus.NEW;
|
||||||
model.local_path = project.rootDir;
|
model.local_path = project.rootDir;
|
||||||
model.projectId = project._id;
|
model.projectId = project._id;
|
||||||
const d = new DatasetDBModel();
|
const d = new DatasetDBModel();
|
|
@ -5,7 +5,7 @@ import { ReadByIdDataBaseModelUseCase } from "../../../core/usecases/read_by_id_
|
||||||
import { MongoIdValidation } from "../../../core/validations/mongo_id_validation";
|
import { MongoIdValidation } from "../../../core/validations/mongo_id_validation";
|
||||||
import { DatasetDBModel } from "../models/dataset_database_model";
|
import { DatasetDBModel } from "../models/dataset_database_model";
|
||||||
import { IDatasetModel } from "../models/dataset_validation_model";
|
import { IDatasetModel } from "../models/dataset_validation_model";
|
||||||
import { ProcessWatcherAndDatabaseUpdateService } from "./create_dataset_scanario";
|
import { ProcessWatcherAndDatabaseUpdateService } from "./create_dataset_scenario";
|
||||||
|
|
||||||
export class ExecDatasetProcessScenario extends CallbackStrategyWithIdQuery {
|
export class ExecDatasetProcessScenario extends CallbackStrategyWithIdQuery {
|
||||||
idValidationExpression = new MongoIdValidation();
|
idValidationExpression = new MongoIdValidation();
|
||||||
|
|
|
@ -10,14 +10,18 @@ export class FormBuilderValidationModel {
|
||||||
@IsArray()
|
@IsArray()
|
||||||
public form: [];
|
public form: [];
|
||||||
}
|
}
|
||||||
|
export enum ProcessStatus {
|
||||||
|
END = "END",
|
||||||
|
ERROR = "ERROR",
|
||||||
|
NEW = "NEW",
|
||||||
|
}
|
||||||
export interface IDatasetModel {
|
export interface IDatasetModel {
|
||||||
name: string;
|
name: string;
|
||||||
local_path: string;
|
local_path: string;
|
||||||
dataSetObjects: string[];
|
dataSetObjects: string[];
|
||||||
formBuilder: FormBuilderValidationModel;
|
formBuilder: FormBuilderValidationModel;
|
||||||
processLogs: string;
|
processLogs: string;
|
||||||
processStatus: string;
|
processStatus: ProcessStatus;
|
||||||
project?: IProjectModel;
|
project?: IProjectModel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,7 +34,7 @@ export class DatasetValidationModel implements IDatasetModel {
|
||||||
@Type(() => FormBuilderValidationModel)
|
@Type(() => FormBuilderValidationModel)
|
||||||
public formBuilder: FormBuilderValidationModel;
|
public formBuilder: FormBuilderValidationModel;
|
||||||
public local_path: string;
|
public local_path: string;
|
||||||
public processStatus: string;
|
public processStatus: ProcessStatus;
|
||||||
public projectId: string;
|
public projectId: string;
|
||||||
public processLogs: string;
|
public processLogs: string;
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,5 +20,10 @@
|
||||||
<style>
|
<style>
|
||||||
@import url('https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&display=swap')
|
@import url('https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&display=swap')
|
||||||
</style>
|
</style>
|
||||||
|
<style>
|
||||||
|
[contenteditable]:focus {
|
||||||
|
outline: 0px solid transparent;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
</html>
|
</html>
|
|
@ -51,4 +51,10 @@ export const ArrayExtensions = () => {
|
||||||
return this.indexOf(element) !== -1;
|
return this.indexOf(element) !== -1;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
if ([].repeat === undefined) {
|
||||||
|
// eslint-disable-next-line no-extend-native
|
||||||
|
Array.prototype.repeat = function (quantity) {
|
||||||
|
return Array(quantity).fill(this[0]);
|
||||||
|
};
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -19,6 +19,7 @@ declare global {
|
||||||
isEmpty(): boolean;
|
isEmpty(): boolean;
|
||||||
isNotEmpty(): boolean;
|
isNotEmpty(): boolean;
|
||||||
hasIncludeElement(element: T): boolean;
|
hasIncludeElement(element: T): boolean;
|
||||||
|
repeat(quantity: number): Array<T>;
|
||||||
}
|
}
|
||||||
interface Number {
|
interface Number {
|
||||||
fromArray(): number[];
|
fromArray(): number[];
|
||||||
|
|
|
@ -1,9 +1,12 @@
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import { Input, Select, Button } from "antd";
|
|
||||||
import { InputBuilderViewModel, InputType } from "./form_view_model";
|
import { InputBuilderViewModel, InputType } from "./form_view_model";
|
||||||
import { observer } from "mobx-react-lite";
|
import { observer } from "mobx-react-lite";
|
||||||
import { FormBuilderStore } from "./form_builder_store";
|
import { FormBuilderStore } from "./form_builder_store";
|
||||||
import { FormBuilderValidationModel } from "../../../features/dataset/dataset_model";
|
import { FormBuilderValidationModel } from "../../../features/dataset/dataset_model";
|
||||||
|
import { SelectCore } from "../select/select";
|
||||||
|
import { CoreInput } from "../input/input";
|
||||||
|
import { Icon } from "../icons/icons";
|
||||||
|
import { CoreText, CoreTextType } from "../text/text";
|
||||||
|
|
||||||
export interface IFormBuilder {
|
export interface IFormBuilder {
|
||||||
context: string;
|
context: string;
|
||||||
|
@ -28,107 +31,107 @@ export const FormBuilder = observer((props: IFormBuilder) => {
|
||||||
{store.formViewModel?.inputs.map((element) => {
|
{store.formViewModel?.inputs.map((element) => {
|
||||||
if (element.type.isEqual(InputType.ENUM)) {
|
if (element.type.isEqual(InputType.ENUM)) {
|
||||||
const values = element.values as string[];
|
const values = element.values as string[];
|
||||||
|
console.log(element.totalValue);
|
||||||
return (
|
return (
|
||||||
<>
|
<SelectCore
|
||||||
<div>{element.name}</div>
|
items={values}
|
||||||
|
value={element.totalValue ?? element.defaultValue}
|
||||||
<Select
|
onChange={(value) => store.changeTotalValue(element.id, value)}
|
||||||
defaultValue={element.defaultValue}
|
label={element.name}
|
||||||
style={{ width: 120 }}
|
style={{ margin: 10 }}
|
||||||
onChange={(e) => {
|
/>
|
||||||
store.changeTotalValue(element.id, e);
|
|
||||||
}}
|
|
||||||
options={values?.map((el) => {
|
|
||||||
return { value: el };
|
|
||||||
})}
|
|
||||||
/>
|
|
||||||
</>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (element.type.isEqual(InputType.ARRAY)) {
|
if (element.type.isEqual(InputType.ARRAY)) {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div style={{ border: "1px black solid", margin: 10 }}>
|
||||||
<div style={{ fontSize: "large" }}>{element.name}</div>
|
<div
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
margin: 10,
|
||||||
|
alignItems: "center",
|
||||||
|
paddingRight: 10,
|
||||||
|
}}
|
||||||
|
onClick={() => {
|
||||||
|
store.open(element.id);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<CoreText text={element.name} type={CoreTextType.large} />
|
||||||
|
<Icon type="PlusCircle" style={{ width: 22 }} />
|
||||||
|
</div>
|
||||||
|
|
||||||
{element.isOpen ? (
|
{element.isOpen ? (
|
||||||
<div>
|
<div style={{ margin: 10 }}>
|
||||||
{element.totalValue instanceof Array
|
{element.totalValue instanceof Array
|
||||||
? element.totalValue?.map((subArray, index) => {
|
? element.totalValue?.map((subArray, index) => {
|
||||||
return (
|
return (
|
||||||
<>
|
<div style={{ margin: 10 }}>
|
||||||
<div style={{ paddingLeft: "10px" }}>
|
<div style={{ display: "flex" }}>
|
||||||
index: {index}
|
<CoreText text={(element.subType ?? "") + ` ${index}`} type={CoreTextType.medium} />
|
||||||
<Button onClick={() => store.deleteTotalValueSubItem(element.id, index)}>
|
<Icon
|
||||||
Delete item
|
style={{ paddingLeft: 10 }}
|
||||||
</Button>
|
type="DeleteCircle"
|
||||||
|
onClick={() => store.deleteTotalValueSubItem(element.id, index)}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{subArray.map((subSubArrayItem: InputBuilderViewModel, subIndex: number) => {
|
{subArray.map((subSubArrayItem: InputBuilderViewModel, subIndex: number) => {
|
||||||
if (subSubArrayItem.type.isEqual(InputType.ENUM)) {
|
if (subSubArrayItem.type.isEqual(InputType.ENUM)) {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div>{subSubArrayItem.name}</div>
|
<SelectCore
|
||||||
|
items={subSubArrayItem.values?.map((el) => String(el)) ?? []}
|
||||||
<Select
|
value={subSubArrayItem.totalValue ?? subSubArrayItem.defaultValue}
|
||||||
defaultValue={subSubArrayItem.defaultValue}
|
onChange={(value) => store.changeTotalSubValue(element.id, subIndex, value)}
|
||||||
style={{ width: 120 }}
|
label={element.name}
|
||||||
onChange={(e) => {
|
style={{ margin: 5 }}
|
||||||
store.changeTotalSubValue(element.id, subIndex, e);
|
|
||||||
}}
|
|
||||||
options={subSubArrayItem.values?.map((el) => {
|
|
||||||
return { value: el };
|
|
||||||
})}
|
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (subSubArrayItem.type.isEqualMany([InputType.NUMBER, InputType.STRING]))
|
if (subSubArrayItem.type.isEqualMany([InputType.NUMBER, InputType.STRING]))
|
||||||
return (
|
return (
|
||||||
<div style={{ width: "200px" }}>
|
<div>
|
||||||
<div>{subSubArrayItem.name}</div>
|
<CoreInput
|
||||||
<Input
|
style={{ margin: 5 }}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
store.changeTotalSubValue(element.id, subIndex, e.target.value);
|
store.changeTotalSubValue(element.id, subIndex, e);
|
||||||
}}
|
}}
|
||||||
defaultValue={subSubArrayItem.defaultValue}
|
value={subSubArrayItem.defaultValue}
|
||||||
|
label={subSubArrayItem.name}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
return <>Error</>;
|
return <>Error</>;
|
||||||
})}
|
})}
|
||||||
</>
|
</div>
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
: null}
|
: null}
|
||||||
</div>
|
</div>
|
||||||
) : null}
|
) : null}
|
||||||
<div
|
|
||||||
onClick={() => {
|
|
||||||
store.open(element.id);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
+
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (element.type.isEqualMany([InputType.NUMBER, InputType.STRING]))
|
if (element.type.isEqualMany([InputType.NUMBER, InputType.STRING]))
|
||||||
return (
|
return (
|
||||||
<div style={{ width: "200px" }}>
|
<div>
|
||||||
<div>{element.name}</div>
|
<CoreInput
|
||||||
<Input
|
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
store.changeTotalValue(element.id, e.target.value);
|
store.changeTotalValue(element.id, e);
|
||||||
}}
|
}}
|
||||||
defaultValue={element.defaultValue}
|
value={element.defaultValue}
|
||||||
|
label={element.name}
|
||||||
|
style={{ margin: 10 }}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
return <>Error</>;
|
return <>Error</>;
|
||||||
})}
|
})}
|
||||||
<Button onClick={() => store.saveForm()}>SAVE FORM</Button>
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -4,16 +4,31 @@ import { Result } from "../../helper/result";
|
||||||
export interface IIconsProps {
|
export interface IIconsProps {
|
||||||
type: string;
|
type: string;
|
||||||
style?: React.CSSProperties;
|
style?: React.CSSProperties;
|
||||||
|
onClick?: Function;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function Icon(props: IIconsProps) {
|
export function Icon(props: IIconsProps) {
|
||||||
const icon = getIconSvg(props.type);
|
const icon = getIconSvg(props.type);
|
||||||
return icon.fold(
|
return icon.fold(
|
||||||
(node) => {
|
(node) => {
|
||||||
return <div style={props.style}>{node}</div>;
|
return (
|
||||||
|
<div
|
||||||
|
onClick={() => {
|
||||||
|
if (props.onClick) props.onClick();
|
||||||
|
}}
|
||||||
|
style={props.style}
|
||||||
|
>
|
||||||
|
{node}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
},
|
},
|
||||||
() => (
|
() => (
|
||||||
<div style={props.style}>
|
<div
|
||||||
|
onClick={() => {
|
||||||
|
if (props.onClick) props.onClick();
|
||||||
|
}}
|
||||||
|
style={props.style}
|
||||||
|
>
|
||||||
<svg width="12" height="12" viewBox="0 0 12 12" fill="none" xmlns="http://www.w3.org/2000/svg">
|
<svg width="12" height="12" viewBox="0 0 12 12" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
<path
|
<path
|
||||||
fill-rule="evenodd"
|
fill-rule="evenodd"
|
||||||
|
@ -28,6 +43,23 @@ export function Icon(props: IIconsProps) {
|
||||||
}
|
}
|
||||||
const getIconSvg = (type: string): Result<undefined, React.JSX.Element> => {
|
const getIconSvg = (type: string): Result<undefined, React.JSX.Element> => {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
|
case "DeleteCircle":
|
||||||
|
return Result.ok(
|
||||||
|
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path
|
||||||
|
fill-rule="evenodd"
|
||||||
|
clip-rule="evenodd"
|
||||||
|
d="M10 0C4.47 0 0 4.47 0 10C0 15.53 4.47 20 10 20C15.53 20 20 15.53 20 10C20 4.47 15.53 0 10 0ZM10 18C5.59 18 2 14.41 2 10C2 5.59 5.59 2 10 2C14.41 2 18 5.59 18 10C18 14.41 14.41 18 10 18ZM10 8.59L13.59 5L15 6.41L11.41 10L15 13.59L13.59 15L10 11.41L6.41 15L5 13.59L8.59 10L5 6.41L6.41 5L10 8.59Z"
|
||||||
|
fill="#49454F"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
case "Check":
|
||||||
|
return Result.ok(
|
||||||
|
<svg width="12" height="10" viewBox="0 0 12 10" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M4 9.4L0 5.4L1.4 4L4 6.6L10.6 0L12 1.4L4 9.4Z" fill="white" />
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
case "PlusCircle":
|
case "PlusCircle":
|
||||||
return Result.ok(
|
return Result.ok(
|
||||||
<svg width="33" height="33" viewBox="0 0 33 33" fill="none" xmlns="http://www.w3.org/2000/svg">
|
<svg width="33" height="33" viewBox="0 0 33 33" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
|
38
ui/src/core/ui/input/input.tsx
Normal file
38
ui/src/core/ui/input/input.tsx
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
import { CoreText, CoreTextType } from "../text/text";
|
||||||
|
|
||||||
|
interface IInputProps {
|
||||||
|
label: string;
|
||||||
|
value?: string;
|
||||||
|
onChange?: (value: string) => void;
|
||||||
|
style?: React.CSSProperties;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const CoreInput = (props: IInputProps) => {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
style={Object.assign(
|
||||||
|
{
|
||||||
|
backgroundColor: "rgba(230, 224, 233, 1)",
|
||||||
|
height: 58,
|
||||||
|
borderRadius: " 4px 4px 0px 0px",
|
||||||
|
borderBottom: "solid 1px black",
|
||||||
|
padding: "10px 10px 10px 10px",
|
||||||
|
},
|
||||||
|
props.style
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<CoreText type={CoreTextType.small} text={props.label} />
|
||||||
|
|
||||||
|
<div
|
||||||
|
onChange={(event) => {
|
||||||
|
console.log(event);
|
||||||
|
}}
|
||||||
|
onInput={(e) => {
|
||||||
|
if (props.onChange && e.currentTarget.textContent) props.onChange(e.currentTarget.textContent);
|
||||||
|
}}
|
||||||
|
style={{ fontSize: 16, fontFamily: "Roboto", color: "#1D1B20", height: 24 }}
|
||||||
|
contentEditable="true"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
67
ui/src/core/ui/select/select.tsx
Normal file
67
ui/src/core/ui/select/select.tsx
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
import React from "react";
|
||||||
|
import { CoreText, CoreTextType } from "../text/text";
|
||||||
|
|
||||||
|
interface ISelectCoreProps {
|
||||||
|
items: string[];
|
||||||
|
value: string;
|
||||||
|
label: string;
|
||||||
|
onChange: (value: string) => void;
|
||||||
|
style?: React.CSSProperties;
|
||||||
|
}
|
||||||
|
export const SelectCore = (props: ISelectCoreProps) => {
|
||||||
|
const ref = React.useRef<HTMLDivElement>(null);
|
||||||
|
const [cursorIsCorses, setCursorIsCorses] = React.useState(false);
|
||||||
|
const [value, setValue] = React.useState(props.value);
|
||||||
|
React.useEffect(() => {
|
||||||
|
ref.current?.addEventListener("mousemove", () => {
|
||||||
|
setCursorIsCorses(true);
|
||||||
|
});
|
||||||
|
ref.current?.addEventListener("mouseleave", () => {
|
||||||
|
setCursorIsCorses(false);
|
||||||
|
});
|
||||||
|
}, [ref, setCursorIsCorses]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div ref={ref} style={props.style}>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
backgroundColor: "rgba(230, 224, 233, 1)",
|
||||||
|
height: 58,
|
||||||
|
borderRadius: "4px 4px 0px 0px",
|
||||||
|
borderBottom: "solid 1px black",
|
||||||
|
padding: "10px 10px 10px 10px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<CoreText type={CoreTextType.small} text={props.label} />
|
||||||
|
<div style={{ fontSize: 16, fontFamily: "Roboto", color: "#1D1B20", height: 24 }}>{value}</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
backgroundColor: "rgba(243, 237, 247, 1)",
|
||||||
|
boxShadow: "0px 1px 2px rgba(0, 0, 0, 0.3), 0px 2px 6px 2px rgba(0, 0, 0, 0.15)",
|
||||||
|
borderRadius: 4,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{cursorIsCorses
|
||||||
|
? props.items.map((el) => (
|
||||||
|
<div
|
||||||
|
onClick={() => {
|
||||||
|
setValue(el);
|
||||||
|
props.onChange(el);
|
||||||
|
}}
|
||||||
|
style={{
|
||||||
|
height: 48,
|
||||||
|
textAlign: "center",
|
||||||
|
alignContent: "center",
|
||||||
|
cursor: "pointer",
|
||||||
|
borderBottom: "1px solid",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{el}
|
||||||
|
</div>
|
||||||
|
))
|
||||||
|
: null}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
19
ui/src/core/ui/switch/switch.tsx
Normal file
19
ui/src/core/ui/switch/switch.tsx
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
import { Icon } from "../icons/icons";
|
||||||
|
|
||||||
|
interface ISwitchProps {
|
||||||
|
isSelected: boolean;
|
||||||
|
id: string;
|
||||||
|
onChange: (status: boolean, id: string) => void;
|
||||||
|
}
|
||||||
|
export const CoreSwitch = (props: ISwitchProps) => {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
style={{ height: 40, width: 40, borderRadius: 2, alignContent: "center", cursor: "pointer" }}
|
||||||
|
onClick={() => props.onChange(props.isSelected, props.id)}
|
||||||
|
>
|
||||||
|
<div style={{ backgroundColor: "rgba(104, 80, 164, 1)", width: 20, height: 20, textAlign: "center" }}>
|
||||||
|
{props.isSelected ? <Icon type={"Check"} /> : null}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
|
@ -4,6 +4,7 @@ export enum CoreTextType {
|
||||||
header,
|
header,
|
||||||
medium,
|
medium,
|
||||||
large,
|
large,
|
||||||
|
small,
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ITextProps {
|
export interface ITextProps {
|
||||||
|
@ -13,6 +14,22 @@ export interface ITextProps {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function CoreText(props: ITextProps) {
|
export function CoreText(props: ITextProps) {
|
||||||
|
if (props.type === CoreTextType.small) {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
color: props.color ?? "rgba(73, 69, 79, 1)",
|
||||||
|
fontSize: 12,
|
||||||
|
fontFamily: "Roboto",
|
||||||
|
fontWeight: 400,
|
||||||
|
fontSizeAdjust: 14,
|
||||||
|
textOverflow: "ellipsis",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{props.text}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
if (props.type === CoreTextType.large) {
|
if (props.type === CoreTextType.large) {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
|
|
|
@ -34,8 +34,6 @@ export function BehaviorTreeBuilderScreen() {
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
store.init();
|
store.init();
|
||||||
// @ts-expect-error
|
|
||||||
console.log(ref.current.clientHeight);
|
|
||||||
|
|
||||||
store.dragZoneSetOffset(
|
store.dragZoneSetOffset(
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
|
|
|
@ -1,9 +1,17 @@
|
||||||
import { Spin } from "antd";
|
import { Spin } from "antd";
|
||||||
import { LoadingOutlined } from "@ant-design/icons";
|
import { LoadingOutlined } from "@ant-design/icons";
|
||||||
import poseIMG from "../../assets/images/pose_estemation.jpg";
|
import poseIMG from "../../core/assets/images/pose_estemation.jpg";
|
||||||
import { Icon } from "../icons/icons";
|
import { Icon } from "../../core/ui/icons/icons";
|
||||||
import { CoreText, CoreTextType } from "../text/text";
|
import { CoreText, CoreTextType } from "../../core/ui/text/text";
|
||||||
import { CoreButton } from "../button/button";
|
import { CoreButton } from "../../core/ui/button/button";
|
||||||
|
import type { MenuProps } from "antd";
|
||||||
|
import { Dropdown } from "antd";
|
||||||
|
import { ProcessStatus } from "./dataset_model";
|
||||||
|
|
||||||
|
interface IMenuItem {
|
||||||
|
onClick: Function;
|
||||||
|
name: string;
|
||||||
|
}
|
||||||
|
|
||||||
export const enum CardDataSetType {
|
export const enum CardDataSetType {
|
||||||
EMPTY = "EMPTY",
|
EMPTY = "EMPTY",
|
||||||
|
@ -19,10 +27,22 @@ interface ICardDataSetProps {
|
||||||
processStatus?: string;
|
processStatus?: string;
|
||||||
onClickButton?: (id: string) => void;
|
onClickButton?: (id: string) => void;
|
||||||
onClickEmptyCard?: Function;
|
onClickEmptyCard?: Function;
|
||||||
|
onEdit?: Function;
|
||||||
|
onDelete?: Function;
|
||||||
id?: string;
|
id?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const CardDataSet = (props: ICardDataSetProps) => {
|
export const CardDataSet = (props: ICardDataSetProps) => {
|
||||||
|
const menu: IMenuItem[] = [
|
||||||
|
{ onClick: () => props.onEdit?.call(props.id), name: "Редактировать" },
|
||||||
|
{ onClick: () => props.onDelete?.call(props.id), name: "Удалить" },
|
||||||
|
];
|
||||||
|
const items: MenuProps["items"] = menu.map((el, index) => {
|
||||||
|
return {
|
||||||
|
key: String(index),
|
||||||
|
label: <CoreText text={el.name} type={CoreTextType.medium} />,
|
||||||
|
};
|
||||||
|
});
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
|
@ -48,7 +68,11 @@ export const CardDataSet = (props: ICardDataSetProps) => {
|
||||||
<CoreText text={props.neuralNetworkAction ?? ""} type={CoreTextType.medium} />
|
<CoreText text={props.neuralNetworkAction ?? ""} type={CoreTextType.medium} />
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<Icon type="Settings" />
|
<Dropdown overlayStyle={{ backgroundColor: "rgba(243, 237, 247, 1)" }} menu={{ items }}>
|
||||||
|
<div>
|
||||||
|
<Icon type="Settings" />
|
||||||
|
</div>
|
||||||
|
</Dropdown>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
@ -75,7 +99,7 @@ export const CardDataSet = (props: ICardDataSetProps) => {
|
||||||
<Spin indicator={<LoadingOutlined style={{ fontSize: 34, color: "rgba(103, 80, 164, 1)" }} spin />} />
|
<Spin indicator={<LoadingOutlined style={{ fontSize: 34, color: "rgba(103, 80, 164, 1)" }} spin />} />
|
||||||
) : null}
|
) : null}
|
||||||
<div style={{ width: 20 }} />
|
<div style={{ width: 20 }} />
|
||||||
{props.processStatus === "new" ? (
|
{props.processStatus === ProcessStatus.NEW ? (
|
||||||
<CoreButton
|
<CoreButton
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
if (props.type.isEqual(CardDataSetType.COMPLETED) && props.onClickButton && props.id) {
|
if (props.type.isEqual(CardDataSetType.COMPLETED) && props.onClickButton && props.id) {
|
||||||
|
@ -85,9 +109,19 @@ export const CardDataSet = (props: ICardDataSetProps) => {
|
||||||
filled={true}
|
filled={true}
|
||||||
text="Старт"
|
text="Старт"
|
||||||
/>
|
/>
|
||||||
) : (
|
) : null}
|
||||||
<CoreButton text="Завершено" block={true} />
|
|
||||||
)}
|
{props.processStatus === ProcessStatus.ERROR ? (
|
||||||
|
<CoreButton
|
||||||
|
onClick={() => {
|
||||||
|
if (props.type.isEqual(CardDataSetType.COMPLETED) && props.onClickButton && props.id) {
|
||||||
|
props.onClickButton(props.id);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
filled={true}
|
||||||
|
text="Ошибка"
|
||||||
|
/>
|
||||||
|
) : null}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
|
@ -1,11 +1,16 @@
|
||||||
import { InputBuilderViewModel } from "../../core/ui/form_builder/form_view_model";
|
import { InputBuilderViewModel } from "../../core/ui/form_builder/form_view_model";
|
||||||
import { Result } from "../../core/helper/result";
|
import { Result } from "../../core/helper/result";
|
||||||
import makeAutoObservable from "mobx-store-inheritance";
|
import makeAutoObservable from "mobx-store-inheritance";
|
||||||
|
export enum ProcessStatus {
|
||||||
|
END = "END",
|
||||||
|
ERROR = "ERROR",
|
||||||
|
NEW = "NEW",
|
||||||
|
}
|
||||||
|
|
||||||
export interface IDatasetModel {
|
export interface IDatasetModel {
|
||||||
_id: string;
|
_id: string;
|
||||||
dataSetObjects: string[];
|
dataSetObjects: string[];
|
||||||
processStatus: string;
|
processStatus: ProcessStatus;
|
||||||
projectId: string;
|
projectId: string;
|
||||||
name: string;
|
name: string;
|
||||||
formBuilder: FormBuilder;
|
formBuilder: FormBuilder;
|
||||||
|
@ -77,13 +82,13 @@ export class DataSetModel {
|
||||||
return Result.error("project is unknow");
|
return Result.error("project is unknow");
|
||||||
}
|
}
|
||||||
if (this.dataSetObjects.isEmpty()) {
|
if (this.dataSetObjects.isEmpty()) {
|
||||||
return Result.error("not selected details");
|
return Result.error("Не выделены детали");
|
||||||
}
|
}
|
||||||
if (this.datasetType.isEmpty()) {
|
if (this.datasetType.isEmpty()) {
|
||||||
return Result.error("dataset type is empty");
|
return Result.error("Навык датасета не выбран");
|
||||||
}
|
}
|
||||||
if (this.name.isEmpty()) {
|
if (this.name.isEmpty()) {
|
||||||
return Result.error("dataset name is empty");
|
return Result.error("ВВедите имя датасета");
|
||||||
}
|
}
|
||||||
return Result.ok();
|
return Result.ok();
|
||||||
}
|
}
|
||||||
|
@ -93,8 +98,6 @@ export const datasetTypes = ["Object Detection - YOLOv8", "Pose Estimation - DOP
|
||||||
|
|
||||||
export const datasetFormMockResult = `{
|
export const datasetFormMockResult = `{
|
||||||
"typedataset": \${typedataset:Enum<T>:ObjectDetection},
|
"typedataset": \${typedataset:Enum<T>:ObjectDetection},
|
||||||
"dataset_path": \${ПУТЬ ДАТАСЕТА:string:none},
|
|
||||||
"models":\${models:Array<MODELS>:[]},
|
|
||||||
"models_randomization":{
|
"models_randomization":{
|
||||||
"loc_range_low": [\${LOC_RANGE_LOW_1:number:-1}, \${LOC_RANGE_LOW_2:number:-1},/\${LOC_RANGE_LOW_3:number:0}],
|
"loc_range_low": [\${LOC_RANGE_LOW_1:number:-1}, \${LOC_RANGE_LOW_2:number:-1},/\${LOC_RANGE_LOW_3:number:0}],
|
||||||
"loc_range_high": [\${LOC_RANGE_HIGH_1:number:1}, \${LOC_RANGE_HIGH_2:number:1},/\${LOC_RANGE_HIGH_3:number:2}]
|
"loc_range_high": [\${LOC_RANGE_HIGH_1:number:1}, \${LOC_RANGE_HIGH_2:number:1},/\${LOC_RANGE_HIGH_3:number:2}]
|
||||||
|
@ -123,12 +126,7 @@ ENUM T = "ObjectDetection","PoseEstimation";
|
||||||
ENUM L = "POINT","SUN";
|
ENUM L = "POINT","SUN";
|
||||||
ENUM F = "JPEG","PNG";
|
ENUM F = "JPEG","PNG";
|
||||||
ENUM COLLISION_SHAPE = "SHAPE","COLLISION";
|
ENUM COLLISION_SHAPE = "SHAPE","COLLISION";
|
||||||
|
|
||||||
type MODELS = {
|
|
||||||
"id": \${ID:number:1},
|
|
||||||
"name": \${NAME:string:none},
|
|
||||||
"model": \${MODEL:string:models/1.fbx}
|
|
||||||
};
|
|
||||||
type OBJECTS_SCENE = {
|
type OBJECTS_SCENE = {
|
||||||
"name": \${NAME:string:default},
|
"name": \${NAME:string:default},
|
||||||
"collision_shape": \${collision_shape:Enum<COLLISION_SHAPE>:BOX},
|
"collision_shape": \${collision_shape:Enum<COLLISION_SHAPE>:BOX},
|
||||||
|
|
|
@ -1,11 +1,15 @@
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import { Drawer, Button, Radio, Card, Checkbox, Input } from "antd";
|
import { Drawer } from "antd";
|
||||||
import { FormBuilder } from "../../core/ui/form_builder/form_builder";
|
import { FormBuilder } from "../../core/ui/form_builder/form_builder";
|
||||||
import { DataSetStore } from "./dataset_store";
|
import { DataSetStore, DrawersDataset } from "./dataset_store";
|
||||||
import { observer } from "mobx-react-lite";
|
import { observer } from "mobx-react-lite";
|
||||||
import { datasetTypes } from "./dataset_model";
|
|
||||||
import { MainPage } from "../../core/ui/pages/main_page";
|
import { MainPage } from "../../core/ui/pages/main_page";
|
||||||
import { CardDataSet, CardDataSetType } from "../../core/ui/card/card_dataset";
|
import { CardDataSet, CardDataSetType } from "./card_dataset";
|
||||||
|
import { CoreInput } from "../../core/ui/input/input";
|
||||||
|
import { CoreButton } from "../../core/ui/button/button";
|
||||||
|
import { ListItem } from "./list_item";
|
||||||
|
import { datasetTypes } from "./dataset_model";
|
||||||
|
import { CoreText, CoreTextType } from "../../core/ui/text/text";
|
||||||
|
|
||||||
export const DatasetsScreenPath = "/dataset";
|
export const DatasetsScreenPath = "/dataset";
|
||||||
|
|
||||||
|
@ -15,9 +19,6 @@ export const DataSetScreen: React.FunctionComponent = observer(() => {
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
store.init();
|
store.init();
|
||||||
}, [store]);
|
}, [store]);
|
||||||
|
|
||||||
const [open, setOpen] = React.useState(false);
|
|
||||||
const [open1, setOpen1] = React.useState(false);
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<MainPage
|
<MainPage
|
||||||
|
@ -36,7 +37,6 @@ export const DataSetScreen: React.FunctionComponent = observer(() => {
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{store.datasets?.map((el) => {
|
{store.datasets?.map((el) => {
|
||||||
console.log(el);
|
|
||||||
return (
|
return (
|
||||||
<CardDataSet
|
<CardDataSet
|
||||||
type={CardDataSetType.COMPLETED}
|
type={CardDataSetType.COMPLETED}
|
||||||
|
@ -46,18 +46,23 @@ export const DataSetScreen: React.FunctionComponent = observer(() => {
|
||||||
neuralNetworkAction={el.datasetType.split(" - ").at(0)}
|
neuralNetworkAction={el.datasetType.split(" - ").at(0)}
|
||||||
neuralNetworkName={el.datasetType.split(" - ").at(1)}
|
neuralNetworkName={el.datasetType.split(" - ").at(1)}
|
||||||
id={el._id}
|
id={el._id}
|
||||||
onClickButton={(id) => store.runProcess(id)}
|
onClickButton={(id: string) => store.runProcess(id)}
|
||||||
|
onDelete={(id: string) => store.deleteDataset(id)}
|
||||||
|
onEdit={(id: string) => store.editDataset(id)}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
<CardDataSet
|
<CardDataSet
|
||||||
type={CardDataSetType.EMPTY}
|
type={CardDataSetType.EMPTY}
|
||||||
onClickEmptyCard={() => {
|
onClickEmptyCard={() => {
|
||||||
setOpen(true);
|
store.editDrawer(DrawersDataset.NewDataset, true);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
<Drawer
|
||||||
<Drawer title="Form builder Drawer" onClose={() => setOpen1(false)} open={open1}>
|
title={DrawersDataset.FormBuilderDrawer}
|
||||||
|
onClose={() => store.editDrawer(DrawersDataset.FormBuilderDrawer, false)}
|
||||||
|
open={store.drawers.find((el) => el.name === DrawersDataset.FormBuilderDrawer)?.status ?? false}
|
||||||
|
>
|
||||||
<FormBuilder
|
<FormBuilder
|
||||||
context={store.dataSetModel.formBuilder.context}
|
context={store.dataSetModel.formBuilder.context}
|
||||||
result={store.dataSetModel.formBuilder.result}
|
result={store.dataSetModel.formBuilder.result}
|
||||||
|
@ -65,42 +70,69 @@ export const DataSetScreen: React.FunctionComponent = observer(() => {
|
||||||
if (el) store.dataSetModel.formBuilder = el;
|
if (el) store.dataSetModel.formBuilder = el;
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
<div style={{ display: "flex" }}>
|
||||||
|
<CoreButton text="Сохранить" filled={true} />
|
||||||
|
<div style={{ width: 10 }} />
|
||||||
|
<CoreButton text="Отмена" onClick={() => store.editDrawer(DrawersDataset.FormBuilderDrawer, false)} />
|
||||||
|
</div>
|
||||||
</Drawer>
|
</Drawer>
|
||||||
<Drawer title="New Dataset" onClose={() => setOpen(false)} open={open}>
|
<Drawer
|
||||||
<Input placeholder="Dataset name" onChange={(e) => (store.dataSetModel.name = e.target.value)} />
|
title={DrawersDataset.NewDataset}
|
||||||
<Button onClick={() => setOpen1(true)}>edit dataset settings</Button>
|
onClose={() => store.editDrawer(DrawersDataset.NewDataset, false)}
|
||||||
<Button onClick={() => store.saveDataset()}>save dataset</Button>
|
open={store.drawers.find((el) => el.name === DrawersDataset.NewDataset)?.status}
|
||||||
|
>
|
||||||
<Radio.Group
|
<div
|
||||||
value={store.dataSetModel.datasetType}
|
style={{ display: "flex", flexDirection: "column", justifyContent: "space-between", height: "100%" }}
|
||||||
onChange={(e) => {
|
|
||||||
store.dataSetModel.datasetType = e.target.value;
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
{datasetTypes.map((el) => (
|
<div>
|
||||||
<>
|
<CoreInput label={"Имя датасета"} onChange={(e) => store.setNewDatasetName(e)} />
|
||||||
<Radio.Button value={el}>{el}</Radio.Button>
|
<div>
|
||||||
</>
|
<CoreText type={CoreTextType.header} text="Тип навыка" />
|
||||||
))}
|
{datasetTypes.map((el) => {
|
||||||
</Radio.Group>
|
return (
|
||||||
|
<div
|
||||||
|
onClick={() => store.setSkillSelected(el)}
|
||||||
|
style={{
|
||||||
|
backgroundColor: store.skillIsSelected(el) ? "rgb(103 80 164)" : "rgba(254, 247, 255, 1)",
|
||||||
|
borderRadius: 25,
|
||||||
|
color: store.skillIsSelected(el) ? "white" : "",
|
||||||
|
margin: 10,
|
||||||
|
padding: 10,
|
||||||
|
cursor: "pointer",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{el}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
<div style={{ width: 180, marginTop: 10, marginBottom: 30 }}>
|
||||||
|
<CoreButton
|
||||||
|
onClick={() => store.editDrawer(DrawersDataset.FormBuilderDrawer, true)}
|
||||||
|
text="Настройки датасета"
|
||||||
|
filled={true}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
{store.assets?.assets?.map((el) => {
|
||||||
|
return (
|
||||||
|
<ListItem
|
||||||
|
status={store.assetStatus(el.name)}
|
||||||
|
name={el.name}
|
||||||
|
imgURL={el.image}
|
||||||
|
onChange={() => {
|
||||||
|
store.datasetCheckBox(el);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
|
||||||
{store.assets?.assets.map((el) => {
|
<div style={{ display: "flex" }}>
|
||||||
return (
|
<CoreButton text="Сохранить" filled={true} onClick={() => store.saveDataset()} />
|
||||||
<>
|
<div style={{ width: 10 }} />
|
||||||
<Checkbox
|
<CoreButton text="Отмена" onClick={() => store.editDrawer(DrawersDataset.NewDataset, false)} />
|
||||||
onChange={() => {
|
</div>
|
||||||
store.dataSetModel.dataSetObjects.push(el.name);
|
</div>
|
||||||
}}
|
|
||||||
defaultChecked={store.dataSetModel.dataSetObjects.includes(el.name)}
|
|
||||||
>
|
|
||||||
include?
|
|
||||||
</Checkbox>
|
|
||||||
<Card title={el.name} style={{ width: 300 }}>
|
|
||||||
<img src={el.image} alt="error" />
|
|
||||||
</Card>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</Drawer>
|
</Drawer>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
@ -108,31 +140,3 @@ export const DataSetScreen: React.FunctionComponent = observer(() => {
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
{
|
|
||||||
/* <Button onClick={() => setOpen(true)}>new dataset</Button>
|
|
||||||
{store.datasets?.isEmpty() ? (
|
|
||||||
<div>empty dataset</div>
|
|
||||||
) : (
|
|
||||||
<div>
|
|
||||||
<h1>Datasets</h1>
|
|
||||||
<div>
|
|
||||||
{store.datasets?.map((el, index) => {
|
|
||||||
return (
|
|
||||||
<Card title={el.name}>
|
|
||||||
<h2>dataset objects:</h2>
|
|
||||||
<div>
|
|
||||||
{el.dataSetObjects.map((el) => (
|
|
||||||
<div>{el}</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
<h2>process status</h2>
|
|
||||||
<div>{el.processStatus}</div>
|
|
||||||
<Button>Edit process</Button>
|
|
||||||
</Card>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</> */
|
|
||||||
}
|
|
||||||
|
|
|
@ -2,28 +2,80 @@ import makeAutoObservable from "mobx-store-inheritance";
|
||||||
import { DataSetRepository } from "./dataset_repository";
|
import { DataSetRepository } from "./dataset_repository";
|
||||||
import { UiErrorState } from "../../core/store/base_store";
|
import { UiErrorState } from "../../core/store/base_store";
|
||||||
import { HttpError } from "../../core/repository/http_repository";
|
import { HttpError } from "../../core/repository/http_repository";
|
||||||
import { Assets, DataSetModel, IDatasetModel } from "./dataset_model";
|
import { Asset, Assets, DataSetModel, IDatasetModel } from "./dataset_model";
|
||||||
import { message } from "antd";
|
import { message } from "antd";
|
||||||
import { UUID } from "../all_projects/data/project_repository";
|
import { UUID } from "../all_projects/data/project_repository";
|
||||||
|
|
||||||
|
export enum DrawersDataset {
|
||||||
|
NewDataset = "Новый датасет",
|
||||||
|
FormBuilderDrawer = "Редактировать датасет",
|
||||||
|
}
|
||||||
|
export interface Drawer {
|
||||||
|
name: string;
|
||||||
|
status: boolean;
|
||||||
|
}
|
||||||
export class DataSetStore extends UiErrorState<HttpError> {
|
export class DataSetStore extends UiErrorState<HttpError> {
|
||||||
dataSetRepository: DataSetRepository;
|
dataSetRepository: DataSetRepository;
|
||||||
assets?: Assets;
|
assets?: Assets;
|
||||||
datasets?: IDatasetModel[];
|
datasets?: IDatasetModel[];
|
||||||
activeProject: UUID;
|
activeProject: UUID;
|
||||||
dataSetModel = DataSetModel.empty();
|
dataSetModel = DataSetModel.empty();
|
||||||
|
drawers: Drawer[];
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
this.dataSetRepository = new DataSetRepository();
|
this.dataSetRepository = new DataSetRepository();
|
||||||
|
this.drawers = Object.entries(DrawersDataset).map((k, v) => {
|
||||||
|
return {
|
||||||
|
name: k.at(1) ?? "",
|
||||||
|
status: false,
|
||||||
|
};
|
||||||
|
});
|
||||||
makeAutoObservable(this);
|
makeAutoObservable(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setNewDatasetName(e: string): void {
|
||||||
|
this.dataSetModel.name = e;
|
||||||
|
}
|
||||||
|
|
||||||
|
setSkillSelected(el: string): void {
|
||||||
|
this.dataSetModel.datasetType = el;
|
||||||
|
}
|
||||||
|
|
||||||
|
skillIsSelected(el: string): boolean {
|
||||||
|
return el === this.dataSetModel.datasetType;
|
||||||
|
}
|
||||||
|
|
||||||
|
assetStatus(name: string): boolean {
|
||||||
|
return this.dataSetModel.dataSetObjects.includes(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
datasetCheckBox(asset: Asset): void {
|
||||||
|
if (this.assetStatus(asset.name)) {
|
||||||
|
this.dataSetModel.dataSetObjects = this.dataSetModel.dataSetObjects.filter((el) => !el.isEqual(asset.name));
|
||||||
|
} else {
|
||||||
|
this.dataSetModel.dataSetObjects.push(asset.name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
editDrawer(drawerName: DrawersDataset, status: boolean): void {
|
||||||
|
this.drawers = this.drawers.map((el) => {
|
||||||
|
if (el.name === drawerName) {
|
||||||
|
el.status = status;
|
||||||
|
}
|
||||||
|
return el;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
editDataset(id: string) {}
|
||||||
|
|
||||||
|
deleteDataset(id: string) {}
|
||||||
|
|
||||||
runProcess = async (id: string): Promise<void> => {
|
runProcess = async (id: string): Promise<void> => {
|
||||||
(await this.dataSetRepository.isRunningProcess()).fold(
|
(await this.dataSetRepository.isRunningProcess()).fold(
|
||||||
async (s) => {
|
async (s) => {
|
||||||
(await this.dataSetRepository.execDatasetProcess(id)).fold(
|
(await this.dataSetRepository.execDatasetProcess(id)).fold(
|
||||||
() => {
|
() => {
|
||||||
message.success("процесс запущен");
|
message.success("Процесс запущен");
|
||||||
},
|
},
|
||||||
(e) => message.error(e.message)
|
(e) => message.error(e.message)
|
||||||
);
|
);
|
||||||
|
@ -41,7 +93,7 @@ export class DataSetStore extends UiErrorState<HttpError> {
|
||||||
async () => {
|
async () => {
|
||||||
(await this.dataSetRepository.saveDataSet(this.dataSetModel)).fold(
|
(await this.dataSetRepository.saveDataSet(this.dataSetModel)).fold(
|
||||||
() => {
|
() => {
|
||||||
message.success("датасет сохранен");
|
message.success("Датасет сохранен");
|
||||||
},
|
},
|
||||||
(error) => message.error(error.message)
|
(error) => message.error(error.message)
|
||||||
);
|
);
|
||||||
|
|
31
ui/src/features/dataset/list_item.tsx
Normal file
31
ui/src/features/dataset/list_item.tsx
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
import { CoreSwitch } from "../../core/ui/switch/switch";
|
||||||
|
import { CoreText, CoreTextType } from "../../core/ui/text/text";
|
||||||
|
|
||||||
|
export interface IListItemProps {
|
||||||
|
name: string;
|
||||||
|
imgURL: string;
|
||||||
|
status: boolean;
|
||||||
|
onChange: (status: boolean, id: string) => void;
|
||||||
|
}
|
||||||
|
export const ListItem = (props: IListItemProps) => {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
backgroundColor: "rgba(254, 247, 255, 1)",
|
||||||
|
border: "1px #6750a4 solid",
|
||||||
|
width: "100%",
|
||||||
|
height: 110,
|
||||||
|
display: "flex",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
alignItems: "center",
|
||||||
|
borderRadius: 12,
|
||||||
|
marginTop: 10,
|
||||||
|
marginBottom: 10,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<img style={{ height: 50, margin: 10 }} src={props.imgURL} alt="" />
|
||||||
|
<CoreText text={props.name} type={CoreTextType.large} />
|
||||||
|
<CoreSwitch isSelected={props.status} id={props.name} onChange={props.onChange} />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
|
@ -2,7 +2,7 @@ import * as React from "react";
|
||||||
import { PipelineInstanceStore } from "./pipeline_instance_store";
|
import { PipelineInstanceStore } from "./pipeline_instance_store";
|
||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
import { Icon } from "../../core/ui/icons/icons";
|
import { Icon } from "../../core/ui/icons/icons";
|
||||||
import { CardDataSet, CardDataSetType } from "../../core/ui/card/card_dataset";
|
import { CardDataSet, CardDataSetType } from "../dataset/card_dataset";
|
||||||
import { MainPage } from "../../core/ui/pages/main_page";
|
import { MainPage } from "../../core/ui/pages/main_page";
|
||||||
|
|
||||||
export const PipelineInstanceScreenPath = "/pipeline_instance/";
|
export const PipelineInstanceScreenPath = "/pipeline_instance/";
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue