diff --git a/components/elements/processes/index.tsx b/components/elements/processes/index.tsx new file mode 100644 index 0000000..10968ca --- /dev/null +++ b/components/elements/processes/index.tsx @@ -0,0 +1,80 @@ +import styles from './styles.module.css' +import {useEffect, useState} from "react"; + +export interface ProcessExceptionInterface { + message: string, + file: string, + line: bigint, + code: bigint, + trace: any[], +} + +export interface ProcessProgressInterface { + total: bigint, + progress: bigint, + memory: any[], +} + +export interface ProcessInterface { + id: string, + lock: string|null, + containerUuid: string|null, + pid: bigint|null, + name: string, + options: Record, + arguments: Record, + exception: ProcessExceptionInterface|null, + progress: ProcessProgressInterface|null, + createdAt: string, + updatedAt: string|null, + startedAt: string|null, + pausedAt: string|null, + cancelledAt: string|null + completedAt: string|null +} + +export default function Processes() { + const [processes, setProcesses] = useState([]); + + let refreshProcesses = async () => { + let response = await fetch('http://fmw.sipachev.sv/system-monitoring/processes', { + method: 'GET', + headers: { + 'Content-Type': 'application/json;charset=utf-8', + 'X-Plugin-Token': 'passw0rd' + }, + }); + const processes: ProcessInterface[] = await response.json() + setProcesses(processes) + setTimeout(() => refreshProcesses, 1000) + } + + useEffect(() => { + refreshProcesses() + }, []) + + + return ( +
+ {processes.map((process: ProcessInterface, index: number) => ( +
+
+ {process.name}  +
+
+ {!process.progress && 'N/A'} + {process.progress && + {`${process.progress.progress}`} / {`${process.progress.total}`} - 50% [53Mb] / 20 sec + } +
+
+ {process.completedAt && } + {process.pausedAt && } + {!process.pausedAt && !process.completedAt && !process.cancelledAt && } + {!process.completedAt && !process.cancelledAt && } +
+
+ ))} +
+ ) +} diff --git a/components/elements/processes/styles.module.css b/components/elements/processes/styles.module.css new file mode 100644 index 0000000..0862fe3 --- /dev/null +++ b/components/elements/processes/styles.module.css @@ -0,0 +1,7 @@ +.processes { + display: block; +} +.process { + display: grid; + grid-template-columns: 6fr 4fr 2fr; +} \ No newline at end of file diff --git a/components/elements/tabs/context.ts b/components/elements/tabs/context.ts new file mode 100644 index 0000000..7bb2f3d --- /dev/null +++ b/components/elements/tabs/context.ts @@ -0,0 +1,11 @@ +import React from 'react' + +export interface ContextInterface { + tabCount: number, + tab: number, + setTab: (number: number) => void, +} + +const Context = React.createContext({} as ContextInterface) +export const Provider = Context.Provider +export default Context diff --git a/components/elements/tabs/elements/tab-section/index.tsx b/components/elements/tabs/elements/tab-section/index.tsx new file mode 100644 index 0000000..ebdec66 --- /dev/null +++ b/components/elements/tabs/elements/tab-section/index.tsx @@ -0,0 +1,20 @@ +import React, {PropsWithChildren, useContext} from "react"; +import TabContext, {Mode} from '../../tab-context' +import TabsContext from "../../context"; + +const TabSection = ({children}: PropsWithChildren) => { + const {tab: activeTab} = useContext(TabsContext) + const {tab, mode} = useContext(TabContext) + + if (Mode.SECTIONS !== mode) { + return <> + } + + if (activeTab !== tab) { + return <> + } + + return <>{children} +} + +export default TabSection \ No newline at end of file diff --git a/components/elements/tabs/elements/tab-title/index.tsx b/components/elements/tabs/elements/tab-title/index.tsx new file mode 100644 index 0000000..f008794 --- /dev/null +++ b/components/elements/tabs/elements/tab-title/index.tsx @@ -0,0 +1,20 @@ +import React, {PropsWithChildren, useContext} from "react"; +import TabsContext from '../../context' +import TabContext, {Mode} from '../../tab-context' + +const TabTitle = ({children, className}: PropsWithChildren) => { + const {setTab} = useContext(TabsContext) + const {tab, mode} = useContext(TabContext) + + if (Mode.TABS !== mode) { + return <> + } + + return ( + {setTab(tab)}}> + {children} + + ) +} + +export default TabTitle \ No newline at end of file diff --git a/components/elements/tabs/elements/tab/index.tsx b/components/elements/tabs/elements/tab/index.tsx new file mode 100644 index 0000000..656c374 --- /dev/null +++ b/components/elements/tabs/elements/tab/index.tsx @@ -0,0 +1,20 @@ +import React, {Fragment} from "react"; + +interface Props { + children: React.ReactNode[]; +} + +const Tab = ({children}: Props) => { + return ( + <> + {children.map((child: React.ReactNode, index: number) => { + return ( + {child} + ) + })} + + ) +} + +export default Tab + diff --git a/components/elements/tabs/index.tsx b/components/elements/tabs/index.tsx new file mode 100644 index 0000000..66179c2 --- /dev/null +++ b/components/elements/tabs/index.tsx @@ -0,0 +1,46 @@ +import React, {FC, Fragment, useState} from "react"; +import {Provider} from './context' +import {Mode, Provider as TabProvider} from './tab-context' + +interface ITabs { + children: React.ReactNode[]; + tabsClassName?: string; + sectionsClassName?: string; +} + +const Tabs: FC = ({children, tabsClassName, sectionsClassName}) => { + const [tab, setTab] = useState(0) + const tabCount = children.length + + return ( +
+ +
+ {children.map((child: React.ReactNode, index: number) => { + return ( + + + {child} + + + ) + })} +
+
+ {children.map((child: React.ReactNode, index: number) => { + return ( + + + {child} + + + ) + })} +
+
+
+ ) +} + +export default Tabs + diff --git a/components/elements/tabs/tab-context.ts b/components/elements/tabs/tab-context.ts new file mode 100644 index 0000000..d13bddc --- /dev/null +++ b/components/elements/tabs/tab-context.ts @@ -0,0 +1,15 @@ +import React from 'react' + +export enum Mode { + TABS, + SECTIONS +} + +export interface ContextInterface { + tab: number, + mode: Mode, +} + +const Context = React.createContext({} as ContextInterface) +export const Provider = Context.Provider +export default Context diff --git a/pages/index.tsx b/pages/index.tsx index 55f844b..4a32ab1 100644 --- a/pages/index.tsx +++ b/pages/index.tsx @@ -3,6 +3,11 @@ import styles from '../styles/Home.module.css' import {OptionInterface} from "../components/elements/command/elements/option"; import {ArgumentInterface} from "../components/elements/command/elements/argument"; import Command from "../components/elements/command"; +import Tabs from "../components/elements/tabs"; +import Tab from "../components/elements/tabs/elements/tab"; +import TabTitle from "../components/elements/tabs/elements/tab-title"; +import TabSection from "../components/elements/tabs/elements/tab-section"; +import Processes from "../components/elements/processes"; interface CommandInterface { class: string, @@ -26,12 +31,24 @@ export default function Home({commands}: CommandsInterface) {
-

Tasks

-
- {commands.map((command: CommandInterface, index: number) => ( - - ))} -
+ + + Команды + +
+ {commands.map((command: CommandInterface, index: number) => ( + + ))} +
+
+
+ + Процессы + + + + +
) diff --git a/styles/Home.module.css b/styles/Home.module.css index 7451bb0..e451798 100644 --- a/styles/Home.module.css +++ b/styles/Home.module.css @@ -14,3 +14,22 @@ display: grid; grid-template-columns: 11fr 1fr; } + +.tabPanel { + display: flex; +} + +.tabPanelItem { + flex-grow: 1; + padding: 5px; + cursor: pointer; + border-bottom: solid 2px #cae5fa; +} + +.tabPanelItem:hover { + border-bottom: solid 2px #298df8; +} + +.tabPanelItemActive { + border-bottom: solid 2px #298df8; +} \ No newline at end of file