Compare commits
No commits in common. "4dadbec6e88206fa8e5990588bc15d96eb284217" and "92fd933c60d1ac337dd1a6df1d111d3f554236f2" have entirely different histories.
4dadbec6e8
...
92fd933c60
@ -1,3 +0,0 @@
|
|||||||
export interface ApproveProcessRequest {
|
|
||||||
id: string
|
|
||||||
}
|
|
@ -37,7 +37,6 @@ export interface ProcessInterface {
|
|||||||
canRepeat: boolean
|
canRepeat: boolean
|
||||||
canStop: boolean
|
canStop: boolean
|
||||||
canKill: boolean
|
canKill: boolean
|
||||||
canApprove: boolean
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum Status {
|
export enum Status {
|
||||||
|
@ -1,10 +0,0 @@
|
|||||||
import {Method, SchemaInterface} from "../../schema-client";
|
|
||||||
|
|
||||||
class ApproveProcessSchema implements SchemaInterface {
|
|
||||||
method = Method.POST
|
|
||||||
url = '/system-monitoring/processes/{id}/approve'
|
|
||||||
contentType = null
|
|
||||||
}
|
|
||||||
|
|
||||||
export let approveProcessSchema = new ApproveProcessSchema()
|
|
||||||
export default approveProcessSchema
|
|
@ -8,9 +8,7 @@ import {CommandInterface} from "./responses/comamnds";
|
|||||||
import commandsSchema from "./schemas/commands";
|
import commandsSchema from "./schemas/commands";
|
||||||
import runCommandsSchema from "./schemas/run-commands";
|
import runCommandsSchema from "./schemas/run-commands";
|
||||||
import {RepeatProcessRequest} from "./requests/repeat-process";
|
import {RepeatProcessRequest} from "./requests/repeat-process";
|
||||||
import {ApproveProcessRequest} from "./requests/approve-process";
|
|
||||||
import repeatProcessSchema from "./schemas/repeat-process";
|
import repeatProcessSchema from "./schemas/repeat-process";
|
||||||
import approveProcessSchema from "./schemas/approve-process";
|
|
||||||
import processOutputSchema from "./schemas/process-output";
|
import processOutputSchema from "./schemas/process-output";
|
||||||
import {ProcessOutputRequest} from "./requests/process-ouput";
|
import {ProcessOutputRequest} from "./requests/process-ouput";
|
||||||
import playProcessSchema from "./schemas/play-process";
|
import playProcessSchema from "./schemas/play-process";
|
||||||
@ -54,14 +52,6 @@ export class SMClient extends SchemaClient {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async approveProcess(data: ApproveProcessRequest): Promise<ResponseInterface> {
|
|
||||||
let { responseData, headers } = await this.send(approveProcessSchema, data)
|
|
||||||
return {
|
|
||||||
data: responseData as ProcessInterface[],
|
|
||||||
headers: headers
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async repeatProcess(data: RepeatProcessRequest): Promise<ResponseInterface> {
|
async repeatProcess(data: RepeatProcessRequest): Promise<ResponseInterface> {
|
||||||
let { responseData, headers } = await this.send(repeatProcessSchema, data)
|
let { responseData, headers } = await this.send(repeatProcessSchema, data)
|
||||||
return {
|
return {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import styles from './styles.module.css'
|
import styles from './styles.module.css'
|
||||||
import {useContext, useEffect, useState} from "react"
|
import {useEffect, useState} from "react"
|
||||||
import DeleteForeverOutlined from "@mui/icons-material/DeleteForeverOutlined"
|
import DeleteForeverOutlined from "@mui/icons-material/DeleteForeverOutlined"
|
||||||
import StopCircleOutlined from "@mui/icons-material/StopCircleOutlined"
|
import StopCircleOutlined from "@mui/icons-material/StopCircleOutlined"
|
||||||
import PauseCircleOutline from "@mui/icons-material/PauseCircleOutline"
|
import PauseCircleOutline from "@mui/icons-material/PauseCircleOutline"
|
||||||
@ -10,7 +10,6 @@ import ErrorOutline from "@mui/icons-material/ErrorOutline"
|
|||||||
import ReplayOutlined from "@mui/icons-material/ReplayOutlined"
|
import ReplayOutlined from "@mui/icons-material/ReplayOutlined"
|
||||||
import RunCircleOutlined from "@mui/icons-material/RunCircleOutlined"
|
import RunCircleOutlined from "@mui/icons-material/RunCircleOutlined"
|
||||||
import FactCheckOutlined from "@mui/icons-material/FactCheckOutlined"
|
import FactCheckOutlined from "@mui/icons-material/FactCheckOutlined"
|
||||||
import ThumbUpAltOutlined from '@mui/icons-material/ThumbUpAltOutlined'
|
|
||||||
import {
|
import {
|
||||||
Box,
|
Box,
|
||||||
TextField,
|
TextField,
|
||||||
@ -31,7 +30,6 @@ import Command from "../commands/elements/command";
|
|||||||
import {CommandInterface} from "../../../api/sm/responses/comamnds";
|
import {CommandInterface} from "../../../api/sm/responses/comamnds";
|
||||||
import Grid from '@mui/material/Grid';
|
import Grid from '@mui/material/Grid';
|
||||||
import {useApi} from "../../../hooks/use-api";
|
import {useApi} from "../../../hooks/use-api";
|
||||||
import Context from "../../../context/token";
|
|
||||||
|
|
||||||
enum Action {
|
enum Action {
|
||||||
Run,
|
Run,
|
||||||
@ -40,11 +38,9 @@ enum Action {
|
|||||||
Kill,
|
Kill,
|
||||||
Play,
|
Play,
|
||||||
Pause,
|
Pause,
|
||||||
Approve,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function Processes() {
|
export default function Processes() {
|
||||||
const {token} = useContext(Context)
|
|
||||||
const [processes, setProcesses] = useState<ProcessInterface[]>([]);
|
const [processes, setProcesses] = useState<ProcessInterface[]>([]);
|
||||||
const [commands, setCommands] = useState<CommandInterface[]>([]);
|
const [commands, setCommands] = useState<CommandInterface[]>([]);
|
||||||
const [page, setPage] = useState<number>(0);
|
const [page, setPage] = useState<number>(0);
|
||||||
@ -120,8 +116,6 @@ export default function Processes() {
|
|||||||
}, [action]);
|
}, [action]);
|
||||||
|
|
||||||
let isFinished = (process: ProcessInterface) => process.cancelledAt || process.completedAt
|
let isFinished = (process: ProcessInterface) => process.cancelledAt || process.completedAt
|
||||||
let isCancelled = (process: ProcessInterface) => process.cancelledAt
|
|
||||||
let isRunning = (process: ProcessInterface) => process.startedAt && !isFinished(process)
|
|
||||||
|
|
||||||
const handleChangePage = (event: any, page: number) => {
|
const handleChangePage = (event: any, page: number) => {
|
||||||
setPage(page);
|
setPage(page);
|
||||||
@ -151,12 +145,6 @@ export default function Processes() {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
if (action === Action.Approve) {
|
|
||||||
await api.approveProcess({
|
|
||||||
id: selectedProcess.id,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
if (action === Action.Repeat) {
|
if (action === Action.Repeat) {
|
||||||
await api.repeatProcess({
|
await api.repeatProcess({
|
||||||
id: selectedProcess.id,
|
id: selectedProcess.id,
|
||||||
@ -225,10 +213,8 @@ export default function Processes() {
|
|||||||
<TableRow key={process.id}>
|
<TableRow key={process.id}>
|
||||||
<TableCell>{process.name}</TableCell>
|
<TableCell>{process.name}</TableCell>
|
||||||
<TableCell>
|
<TableCell>
|
||||||
{!process.progress && !isFinished(process) && isRunning(process) && <LinearProgress/>}
|
{!process.progress && !isFinished(process) && <LinearProgress/>}
|
||||||
{!process.progress && !isFinished(process) && !isRunning(process) && <LinearProgress variant="determinate" value={0}/>}
|
{!process.progress && isFinished(process) && <LinearProgress variant="determinate" value={100}/>}
|
||||||
{!process.progress && isFinished(process) && !isCancelled(process) && <LinearProgress variant="determinate" value={100}/>}
|
|
||||||
{!process.progress && isFinished(process) && isCancelled(process) && <LinearProgress variant="determinate" value={0}/>}
|
|
||||||
{process.progress && <LinearProgress variant="determinate" value={process.progress.percent}/>}
|
{process.progress && <LinearProgress variant="determinate" value={process.progress.percent}/>}
|
||||||
{process.progress && <span>
|
{process.progress && <span>
|
||||||
{`${process.progress.progress}`} / {`${process.progress.total}`} - {process.progress.percent}% [{process.progress.memory}] / {process.progress.remaining}
|
{`${process.progress.progress}`} / {`${process.progress.total}`} - {process.progress.percent}% [{process.progress.memory}] / {process.progress.remaining}
|
||||||
@ -261,9 +247,6 @@ export default function Processes() {
|
|||||||
</IconButton>}
|
</IconButton>}
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell>
|
<TableCell>
|
||||||
{process.canApprove && token?.permissions.indexOf('approve_process') > -1 && <IconButton onClick={() => openDialog(process, Action.Approve)} title={`Approve`} aria-label="Approve">
|
|
||||||
<ThumbUpAltOutlined/>
|
|
||||||
</IconButton>}
|
|
||||||
{process.canRepeat && <IconButton onClick={() => openDialog(process, Action.Repeat)} title={`Repeat`} aria-label="Repeat">
|
{process.canRepeat && <IconButton onClick={() => openDialog(process, Action.Repeat)} title={`Repeat`} aria-label="Repeat">
|
||||||
<ReplayOutlined/>
|
<ReplayOutlined/>
|
||||||
</IconButton>}
|
</IconButton>}
|
||||||
@ -317,13 +300,6 @@ export default function Processes() {
|
|||||||
argumentsParams={selectedProcess.arguments}
|
argumentsParams={selectedProcess.arguments}
|
||||||
callback={callback}/>}
|
callback={callback}/>}
|
||||||
</ConfirmDialog>}
|
</ConfirmDialog>}
|
||||||
{selectedProcess && <ConfirmDialog
|
|
||||||
title={selectedProcess.name}
|
|
||||||
open={Action.Approve === action}
|
|
||||||
agreeCallback={agreeCallback}
|
|
||||||
closeCallback={() => {setAction(null)}}>
|
|
||||||
Approve?
|
|
||||||
</ConfirmDialog>}
|
|
||||||
{selectedProcess && <ConfirmDialog
|
{selectedProcess && <ConfirmDialog
|
||||||
title={`Are you sure?`}
|
title={`Are you sure?`}
|
||||||
open={ !!action && ([Action.Play, Action.Pause, Action.Stop, Action.Kill].indexOf(action) > -1) }
|
open={ !!action && ([Action.Play, Action.Pause, Action.Stop, Action.Kill].indexOf(action) > -1) }
|
||||||
|
@ -1,115 +0,0 @@
|
|||||||
import styles from './styles.module.css'
|
|
||||||
import {Autocomplete, IconButton, TextareaAutosize, TextField} from "@mui/material";
|
|
||||||
import {useContext, useEffect, useState} from "react";
|
|
||||||
import Context from "../../../context/token";
|
|
||||||
import AddCircleOutlineOutlinedIcon from '@mui/icons-material/AddCircleOutlineOutlined';
|
|
||||||
import DeleteForeverOutlined from '@mui/icons-material/DeleteForeverOutlined';
|
|
||||||
import Modal from '@mui/material/Modal';
|
|
||||||
import Fade from '@mui/material/Fade';
|
|
||||||
import Backdrop from '@mui/material/Backdrop';
|
|
||||||
import Box from '@mui/material/Box';
|
|
||||||
import Grid from "@mui/material/Grid";
|
|
||||||
import ConfirmDialog from "../confirm-dialog";
|
|
||||||
|
|
||||||
const style = {
|
|
||||||
position: 'absolute' as 'absolute',
|
|
||||||
top: '50%',
|
|
||||||
left: '50%',
|
|
||||||
transform: 'translate(-50%, -50%)',
|
|
||||||
width: '100%',
|
|
||||||
bgcolor: 'background.paper',
|
|
||||||
border: '2px solid #000',
|
|
||||||
boxShadow: 24,
|
|
||||||
p: 4,
|
|
||||||
};
|
|
||||||
|
|
||||||
export default function Tokens() {
|
|
||||||
const {token, tokens, addToken, deleteToken, switchToken} = useContext(Context)
|
|
||||||
const [showAddForm, setShowAddForm] = useState(false)
|
|
||||||
const [showConfirm, setShowConfirm] = useState(false)
|
|
||||||
|
|
||||||
let variants = tokens.map((token, index) => ({
|
|
||||||
...token,
|
|
||||||
label: token.host
|
|
||||||
}));
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
setShowAddForm(!token)
|
|
||||||
}, [token])
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<Grid container>
|
|
||||||
<Grid item xs={2}>
|
|
||||||
<Autocomplete
|
|
||||||
value={{
|
|
||||||
...token,
|
|
||||||
label: token?.host ?? ''
|
|
||||||
}}
|
|
||||||
onChange={(event: any, newValue: any) => {
|
|
||||||
console.log('newValue', newValue);
|
|
||||||
if (newValue?.id) {
|
|
||||||
switchToken(newValue?.id)
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
disablePortal
|
|
||||||
options={variants}
|
|
||||||
renderInput={(params) => <TextField {...params} label="Tokens"/>}
|
|
||||||
/>
|
|
||||||
</Grid>
|
|
||||||
<Grid item xs={1}>
|
|
||||||
<IconButton onClick={() => setShowAddForm(true)} title={`Add new token`}
|
|
||||||
aria-label="Add new token">
|
|
||||||
<AddCircleOutlineOutlinedIcon/>
|
|
||||||
</IconButton>
|
|
||||||
<IconButton onClick={() => setShowConfirm(true)} title={`Delete current token`}
|
|
||||||
aria-label="Add new token">
|
|
||||||
<DeleteForeverOutlined/>
|
|
||||||
</IconButton>
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
<Modal
|
|
||||||
aria-labelledby="transition-modal-title"
|
|
||||||
aria-describedby="transition-modal-description"
|
|
||||||
open={showAddForm}
|
|
||||||
onClose={() => setShowAddForm(false)}
|
|
||||||
closeAfterTransition
|
|
||||||
slots={{backdrop: Backdrop}}
|
|
||||||
slotProps={{
|
|
||||||
backdrop: {
|
|
||||||
timeout: 500,
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Fade in={showAddForm}>
|
|
||||||
<Box sx={style}>
|
|
||||||
<TextareaAutosize
|
|
||||||
placeholder={`Pass JWT token`}
|
|
||||||
minRows={25}
|
|
||||||
style={{width: '100%'}}
|
|
||||||
onInput={(event: any) => {
|
|
||||||
if (addToken(event.target.value)) {
|
|
||||||
setShowAddForm(false)
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</Box>
|
|
||||||
</Fade>
|
|
||||||
</Modal>
|
|
||||||
<ConfirmDialog
|
|
||||||
title={`Delete curent token`}
|
|
||||||
open={showConfirm}
|
|
||||||
agreeCallback={async () => {
|
|
||||||
let tokenId = token?.id || null
|
|
||||||
if (tokenId) {
|
|
||||||
deleteToken(tokenId)
|
|
||||||
}
|
|
||||||
setShowConfirm(false)
|
|
||||||
}}
|
|
||||||
|
|
||||||
closeCallback={() => {setShowConfirm(false)}}>
|
|
||||||
Confirm?
|
|
||||||
</ConfirmDialog>
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
|
@ -62,22 +62,12 @@ export const grabTokenData = (token: string): TokenData|null => {
|
|||||||
if (!isClient()) {
|
if (!isClient()) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
const parts = token.split('.')
|
const parts = token.split('.')
|
||||||
if (parts.length !== 3) {
|
let payload = 3 === parts.length && parts[1] ? JSON.parse(window.atob(parts[1])) : null
|
||||||
|
let headers = 3 === parts.length && parts[0] ? JSON.parse(window.atob(parts[0])) : null
|
||||||
|
if (!payload || !headers){
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
let payload = JSON.parse(window.atob(parts[1]))
|
|
||||||
if (!payload){
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
let headers = JSON.parse(window.atob(parts[0]))
|
|
||||||
if (!headers){
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
payload,
|
payload,
|
||||||
headers,
|
headers,
|
||||||
|
@ -13,7 +13,7 @@ const grabClient = (token: Token | null, rawToken: string | null): SMClient => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return new SMClient({
|
return new SMClient({
|
||||||
baseUrl: token?.host || 'localhost',
|
baseUrl: 'http://' + (token?.host || 'localhost'),
|
||||||
...authentication
|
...authentication
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import {useState, useEffect} from 'react'
|
import {useState, useEffect} from 'react'
|
||||||
import {cleanToken, grabToken, grabTokenData, grabTokens, selectToken, storeToken} from "../functions/token";
|
import {cleanToken, grabToken, grabTokens, selectToken, storeToken} from "../functions/token";
|
||||||
|
|
||||||
export class Token {
|
export class Token {
|
||||||
id!: string
|
id!: string
|
||||||
@ -39,18 +39,9 @@ export function useToken(): UseTokenInterface {
|
|||||||
setToken(grabToken()?.payload)
|
setToken(grabToken()?.payload)
|
||||||
}
|
}
|
||||||
|
|
||||||
const addToken = (token: string): boolean => {
|
const addToken = (token: string) => {
|
||||||
if (!grabTokenData(token)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
storeToken(token)
|
storeToken(token)
|
||||||
setToken(grabToken()?.payload)
|
setToken(grabToken()?.payload)
|
||||||
setTokens([
|
|
||||||
...tokens,
|
|
||||||
grabToken()?.payload
|
|
||||||
])
|
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return {token, tokens, switchToken, deleteToken, addToken}
|
return {token, tokens, switchToken, deleteToken, addToken}
|
||||||
|
@ -1,12 +1,11 @@
|
|||||||
import Head from 'next/head'
|
import Head from 'next/head'
|
||||||
import styles from '../styles/Home.module.css'
|
import styles from '../styles/Home.module.css'
|
||||||
import Processes from "../components/elements/processes";
|
import Processes from "../components/elements/processes";
|
||||||
import {Tabs, Tab} from '@mui/material';
|
import {Tabs, Tab, MenuItem, Select, InputLabel, TextareaAutosize, Button} from '@mui/material';
|
||||||
import {useContext, useState} from "react";
|
import {useContext, useEffect, useState} from "react";
|
||||||
import Commands from "../components/elements/commands";
|
import Commands from "../components/elements/commands";
|
||||||
import {Provider as TabProvider} from '../context/tab'
|
import {Provider as TabProvider} from '../context/tab'
|
||||||
import Context from "../context/token";
|
import Context from "../context/token";
|
||||||
import Tokens from "../components/elements/tokens";
|
|
||||||
|
|
||||||
|
|
||||||
export enum TabEnum {
|
export enum TabEnum {
|
||||||
@ -15,10 +14,42 @@ export enum TabEnum {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default function Home() {
|
export default function Home() {
|
||||||
let {token} = useContext(Context)
|
let {token, tokens, addToken} = useContext(Context)
|
||||||
const [tab, setTab] = useState<TabEnum>(TabEnum.Processes);
|
const [tab, setTab] = useState<TabEnum>(TabEnum.Processes);
|
||||||
const handleChange = (event: any, tab: number) => setTab(tab)
|
const handleChange = (event: any, tab: number) => setTab(tab)
|
||||||
|
|
||||||
|
// useEffect(() => {
|
||||||
|
// const storedToken = grabToken()
|
||||||
|
// setToken(storedToken)
|
||||||
|
// const storedTokens = grabTokens()
|
||||||
|
// setTokens(storedTokens)
|
||||||
|
// }, [])
|
||||||
|
|
||||||
|
let onTokenInput = (event: any) => {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!token) {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Head>
|
||||||
|
<title>System monitoring</title>
|
||||||
|
<meta name="description" content="System monitoring service"/>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1"/>
|
||||||
|
<link rel="icon" href="/favicon.ico"/>
|
||||||
|
</Head>
|
||||||
|
<main className={styles.main}>
|
||||||
|
<h2>Для дальнейшей работы добавьте JWT токен</h2>
|
||||||
|
<TextareaAutosize
|
||||||
|
minRows={20}
|
||||||
|
style={{ width: '100%' }}
|
||||||
|
onInput={(event: any) => addToken(event.target.value)}
|
||||||
|
/>
|
||||||
|
</main>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Head>
|
<Head>
|
||||||
@ -28,7 +59,29 @@ export default function Home() {
|
|||||||
<link rel="icon" href="/favicon.ico"/>
|
<link rel="icon" href="/favicon.ico"/>
|
||||||
</Head>
|
</Head>
|
||||||
<main className={styles.main}>
|
<main className={styles.main}>
|
||||||
<Tokens />
|
{tokens.length > 0 && <>
|
||||||
|
<InputLabel id="tokens">Tokens</InputLabel>
|
||||||
|
<Select
|
||||||
|
value={token}
|
||||||
|
labelId="tokens"
|
||||||
|
id="demo-simple-select-autowidth"
|
||||||
|
label="Tokens"
|
||||||
|
onChange={(event: any) => {
|
||||||
|
// selectToken(event.target.value)
|
||||||
|
// const storedToken = grabToken()
|
||||||
|
// setToken(storedToken)
|
||||||
|
// if (storedToken) {
|
||||||
|
// smClient.baseUrl = storedToken.payload.host
|
||||||
|
// }
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{tokens.map((token, index) => (
|
||||||
|
<MenuItem key={index} value={index}>{token.host}</MenuItem>
|
||||||
|
))}
|
||||||
|
</Select>
|
||||||
|
</>}
|
||||||
|
|
||||||
|
|
||||||
{token && <>
|
{token && <>
|
||||||
<Tabs
|
<Tabs
|
||||||
value={tab}
|
value={tab}
|
||||||
|
Loading…
Reference in New Issue
Block a user