This commit is contained in:
IDONTSUDO 2024-04-11 22:02:57 +03:00
parent c17515d571
commit 0c03906518
25 changed files with 475 additions and 201 deletions

View file

@ -51,4 +51,10 @@ export const ArrayExtensions = () => {
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]);
};
}
};

View file

@ -19,6 +19,7 @@ declare global {
isEmpty(): boolean;
isNotEmpty(): boolean;
hasIncludeElement(element: T): boolean;
repeat(quantity: number): Array<T>;
}
interface Number {
fromArray(): number[];

View file

@ -1,97 +0,0 @@
import { Spin } from "antd";
import { LoadingOutlined } from "@ant-design/icons";
import poseIMG from "../../assets/images/pose_estemation.jpg";
import { Icon } from "../icons/icons";
import { CoreText, CoreTextType } from "../text/text";
import { CoreButton } from "../button/button";
export const enum CardDataSetType {
EMPTY = "EMPTY",
COMPLETED = "COMPLETED",
}
interface ICardDataSetProps {
type: CardDataSetType;
neuralNetworkAction?: string;
neuralNetworkName?: string;
objects?: string[];
unixDate?: number;
processStatus?: string;
onClickButton?: (id: string) => void;
onClickEmptyCard?: Function;
id?: string;
}
export const CardDataSet = (props: ICardDataSetProps) => {
return (
<div
style={{
width: 272,
height: 372,
borderRadius: 12,
border: "1px solid #CAC4D0",
backgroundColor: "rgba(254, 247, 255, 1)",
cursor: "pointer",
}}
onClick={() => {
if (props.type.isEqual(CardDataSetType.EMPTY) && props.onClickEmptyCard) {
props.onClickEmptyCard();
}
}}
>
<div style={{ height: 80 }}>
{props.type.isEqual(CardDataSetType.EMPTY) ? null : (
<div style={{ display: "flex", alignItems: "center", justifyContent: "space-between" }}>
<div style={{ width: 70, marginTop: 11 }}></div>
<div style={{ height: 80, alignContent: "center", marginRight: 40 }}>
<CoreText text={props.neuralNetworkName ?? ""} type={CoreTextType.header} />
<CoreText text={props.neuralNetworkAction ?? ""} type={CoreTextType.medium} />
</div>
<div>
<Icon type="Settings" />
</div>
</div>
)}
</div>
<img alt="pose" style={{ width: "100%" }} src={poseIMG}></img>
<div
style={{
textAlignLast: props.type.isEqual(CardDataSetType.EMPTY) ? "center" : "auto",
marginTop: props.type.isEqual(CardDataSetType.EMPTY) ? 80 : 10,
}}
>
{props.type === CardDataSetType.EMPTY ? (
<Icon type="PlusCircle" />
) : (
<div style={{ margin: 10 }}>
<CoreText text={`Объектов: ${props.objects?.length ?? 0}`} type={CoreTextType.large} />
<CoreText text={Number(props.unixDate).unixFromDate()} type={CoreTextType.medium} color="#49454F" />
<div style={{ height: 40 }} />
<div style={{ width: 240, overflow: "hidden", whiteSpace: "nowrap", height: 40 }}>
<CoreText text={props.objects?.join(", ") ?? ""} type={CoreTextType.medium} color="#49454F" />
</div>
<div style={{ display: "flex", flexDirection: "row", justifyContent: "flex-end", alignItems: "center" }}>
{props.processStatus === "exec" ? (
<Spin indicator={<LoadingOutlined style={{ fontSize: 34, color: "rgba(103, 80, 164, 1)" }} spin />} />
) : null}
<div style={{ width: 20 }} />
{props.processStatus === "new" ? (
<CoreButton
onClick={() => {
if (props.type.isEqual(CardDataSetType.COMPLETED) && props.onClickButton && props.id) {
props.onClickButton(props.id);
}
}}
filled={true}
text="Старт"
/>
) : (
<CoreButton text="Завершено" block={true} />
)}
</div>
</div>
)}
</div>
</div>
);
};

View file

@ -1,9 +1,12 @@
import * as React from "react";
import { Input, Select, Button } from "antd";
import { InputBuilderViewModel, InputType } from "./form_view_model";
import { observer } from "mobx-react-lite";
import { FormBuilderStore } from "./form_builder_store";
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 {
context: string;
@ -28,107 +31,107 @@ export const FormBuilder = observer((props: IFormBuilder) => {
{store.formViewModel?.inputs.map((element) => {
if (element.type.isEqual(InputType.ENUM)) {
const values = element.values as string[];
console.log(element.totalValue);
return (
<>
<div>{element.name}</div>
<Select
defaultValue={element.defaultValue}
style={{ width: 120 }}
onChange={(e) => {
store.changeTotalValue(element.id, e);
}}
options={values?.map((el) => {
return { value: el };
})}
/>
</>
<SelectCore
items={values}
value={element.totalValue ?? element.defaultValue}
onChange={(value) => store.changeTotalValue(element.id, value)}
label={element.name}
style={{ margin: 10 }}
/>
);
}
if (element.type.isEqual(InputType.ARRAY)) {
return (
<div>
<div style={{ fontSize: "large" }}>{element.name}</div>
<div style={{ border: "1px black solid", margin: 10 }}>
<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 ? (
<div>
<div style={{ margin: 10 }}>
{element.totalValue instanceof Array
? element.totalValue?.map((subArray, index) => {
return (
<>
<div style={{ paddingLeft: "10px" }}>
index: {index}
<Button onClick={() => store.deleteTotalValueSubItem(element.id, index)}>
Delete item
</Button>
<div style={{ margin: 10 }}>
<div style={{ display: "flex" }}>
<CoreText text={(element.subType ?? "") + ` ${index}`} type={CoreTextType.medium} />
<Icon
style={{ paddingLeft: 10 }}
type="DeleteCircle"
onClick={() => store.deleteTotalValueSubItem(element.id, index)}
/>
</div>
{subArray.map((subSubArrayItem: InputBuilderViewModel, subIndex: number) => {
if (subSubArrayItem.type.isEqual(InputType.ENUM)) {
return (
<>
<div>{subSubArrayItem.name}</div>
<Select
defaultValue={subSubArrayItem.defaultValue}
style={{ width: 120 }}
onChange={(e) => {
store.changeTotalSubValue(element.id, subIndex, e);
}}
options={subSubArrayItem.values?.map((el) => {
return { value: el };
})}
<SelectCore
items={subSubArrayItem.values?.map((el) => String(el)) ?? []}
value={subSubArrayItem.totalValue ?? subSubArrayItem.defaultValue}
onChange={(value) => store.changeTotalSubValue(element.id, subIndex, value)}
label={element.name}
style={{ margin: 5 }}
/>
</>
);
}
if (subSubArrayItem.type.isEqualMany([InputType.NUMBER, InputType.STRING]))
return (
<div style={{ width: "200px" }}>
<div>{subSubArrayItem.name}</div>
<Input
<div>
<CoreInput
style={{ margin: 5 }}
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>
);
return <>Error</>;
})}
</>
</div>
);
})
: null}
</div>
) : null}
<div
onClick={() => {
store.open(element.id);
}}
>
+
</div>
</div>
);
}
if (element.type.isEqualMany([InputType.NUMBER, InputType.STRING]))
return (
<div style={{ width: "200px" }}>
<div>{element.name}</div>
<Input
<div>
<CoreInput
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>
);
return <>Error</>;
})}
<Button onClick={() => store.saveForm()}>SAVE FORM</Button>
</div>
)}
</div>

View file

@ -4,16 +4,31 @@ import { Result } from "../../helper/result";
export interface IIconsProps {
type: string;
style?: React.CSSProperties;
onClick?: Function;
}
export function Icon(props: IIconsProps) {
const icon = getIconSvg(props.type);
return icon.fold(
(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">
<path
fill-rule="evenodd"
@ -28,6 +43,23 @@ export function Icon(props: IIconsProps) {
}
const getIconSvg = (type: string): Result<undefined, React.JSX.Element> => {
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":
return Result.ok(
<svg width="33" height="33" viewBox="0 0 33 33" fill="none" xmlns="http://www.w3.org/2000/svg">

View 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>
);
};

View 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>
);
};

View 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>
);
};

View file

@ -4,6 +4,7 @@ export enum CoreTextType {
header,
medium,
large,
small,
}
export interface ITextProps {
@ -13,6 +14,22 @@ export interface 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) {
return (
<div