diff --git a/client/src/Theme.module.css b/client/src/Theme.module.css index 3937102..39b4024 100644 --- a/client/src/Theme.module.css +++ b/client/src/Theme.module.css @@ -1,3 +1,9 @@ +body { + @mixin light { + background-color: var(--mantine-color-gray-1); + } +} + .container { background-color: light-dark(var(--mantine-color-gray-0), var(--mantine-color-dark-6)); border: rem(1px) solid light-dark(var(--mantine-color-gray-3), var(--mantine-color-dark-4)); diff --git a/client/src/components/Layout/Navbar.module.css b/client/src/components/Layout/Navbar.module.css index 301de69..cbd0254 100644 --- a/client/src/components/Layout/Navbar.module.css +++ b/client/src/components/Layout/Navbar.module.css @@ -1,5 +1,5 @@ .navbar { - background-color: light-dark(var(--mantine-color-gray-0), var(--mantine-color-dark-6)); + background-color: light-dark(var(--mantine-color-gray-2), var(--mantine-color-dark-6)); height: 100%; padding: var(--mantine-spacing-md); padding-top: 0; diff --git a/client/src/components/Logs/Logs.tsx b/client/src/components/Logs/Logs.tsx index cbd85b2..d403ae4 100644 --- a/client/src/components/Logs/Logs.tsx +++ b/client/src/components/Logs/Logs.tsx @@ -1,10 +1,12 @@ -import { Container, Button, Paper, Table, Badge, Tabs, Select, TextInput, Group } from "@mantine/core"; +import { Container, Button, Paper, Table, Badge, Tabs, Select, TextInput, Group, Text, Modal, Box, Code, Title, List, ActionIcon, Indicator } from "@mantine/core"; import { DatePickerInput } from '@mantine/dates'; import Head from "../Common/Head"; import useAPI from "../../hooks/useAPI"; import { ReactElement, useEffect, useState } from "react"; import classes from '../../Theme.module.css'; -import { IconRefresh, IconSearch, IconTrash } from "@tabler/icons-react"; +import { IconDots, IconRefresh, IconSearch, IconTrash } from "@tabler/icons-react"; +import Evaluate from "../Rules/Run/Evaluate"; +import { modals } from "@mantine/modals"; const colors: {[color: string]: string} = { silly: 'indigo', @@ -43,21 +45,62 @@ function Generic( { endpoint, extraTh, extraTd, extraButtons, extraFilters }: Ge const [level, setLevel] = useState('all'); const [limit, setLimit] = useState('50'); const [query, search] = useState(''); + const [viewing, view] = useState(undefined); const { data: logs, fetch, del, loading } = useAPI({ url: `/log/${endpoint}?level=${level}&limit=${limit}${!date[0]?'':`&date=${String(date[0])}${!date[1]?'':`,${String(date[1])}`}`}`, default: [], }); const filtered = (logs||[]).filter(log=>find(query, log)); useEffect(()=>{ fetch() },[ date, level, limit ]); + + const clear = () => + modals.openConfirmModal({ + title: 'Clear log?', + centered: true, + children: ( + + Are you sure you want to empty the {endpoint} log?
+ This action is destructive and cannot be reversed.
+
+ ), + labels: { confirm: 'Reset', cancel: "No, don't clear" }, + confirmProps: { color: 'red' }, + onConfirm: () => del(), + }); + return (<> + (view(undefined))} title="Log Viewer"> + {viewing&& + + + level: {viewing.level} + timestamp: {viewing.timestamp} + message: {viewing.message} + {viewing.schema&&schema: {viewing.schema}} + {viewing.rule&&rule: {viewing.rule}} + + {viewing.stack&& + + Error Stack + {viewing.stack} + } + {viewing.evaluated&&{}} + initActions={(viewing.initActions||[]) as unknown as []} + finalActions={(viewing.finalActions||[]) as unknown as []} + executed + />} + } + -