From d94796173e4611e40fb066045d355f04e91de2d7 Mon Sep 17 00:00:00 2001 From: Dunemask Date: Mon, 23 May 2022 00:24:21 +0000 Subject: [PATCH] Microsave --- lib/database/TABLES.md | 15 ++ package.json | 2 +- src/Views.jsx | 6 +- src/ctx/JobContext.jsx | 54 +++++-- src/ctx/StoreContext.jsx | 38 ++++- src/views/About.jsx | 50 ++++--- src/views/Alerting.jsx | 48 +++--- src/views/Catalog.jsx | 25 +++- src/views/Failing.jsx | 66 ++++---- src/views/Jobs.jsx | 59 ++++---- src/views/Settings.jsx | 141 +++++++++-------- src/views/components/CatalogBox.jsx | 86 +++++++++++ src/views/components/CatalogSearch.jsx | 53 ++++--- src/views/components/FailingBox.jsx | 166 +++++++++++++++++++++ src/views/components/MultiOptionDialog.jsx | 32 ++-- src/views/components/SilenceDialog.jsx | 47 ++++++ src/views/components/SilencingBox.jsx | 75 ++++++++++ 17 files changed, 735 insertions(+), 228 deletions(-) create mode 100644 src/views/components/CatalogBox.jsx create mode 100644 src/views/components/FailingBox.jsx create mode 100644 src/views/components/SilenceDialog.jsx create mode 100644 src/views/components/SilencingBox.jsx diff --git a/lib/database/TABLES.md b/lib/database/TABLES.md index 048e05d..8ae0a1d 100644 --- a/lib/database/TABLES.md +++ b/lib/database/TABLES.md @@ -1,3 +1,4 @@ +<<<<<<< HEAD CREATE SEQUENCE test_results_id_seq; CREATE TABLE test_results ( id bigint NOT NULL DEFAULT nextval('test_results_seq') PRIMARY KEY, @@ -16,15 +17,29 @@ weblog_url varchar(255) DEFAULT NULL, ); ALTER SEQUENCE test_results_id_seq OWNED BY test_results.id; +======= + +> > > > > > > b023d8910c89d80573499890a958c0df649849e1 + # Tables PG Database Tables Mapped Out +<<<<<<< HEAD + ## `test_results` | id | test_name | test_class | test_method | test_path | test_type | test_timestamp | test_retry | origin | failed | failed_message | screenshot_url | weblog_url | | int | string | string | string | string | string | timestamp | boolean | string | boolean | string | string | string | | 1 | My Test | My Test Class | My Failing Test Method | My Test Class Path | API | Date.now() | false | Test Suite A | true | Some Failure Messsage | screenshotUrl | weblogUrl | +======= +Table `test_results` +| id | test_name | test_class | test_method | test_path | test_type | test_timestamp | test_retry | origin | failed | failed_message | screenshot_url | weblog_url | +|-----|-----------|------------|-------------|---------------------|---------------|----------------|------------|--------------|---------|------------------------|---------------------|--------------------| +| int | string | string | string | string | string | timestamp | boolean | string | boolean | string | string | string | +| 1 | My Test | My Class | My Method | /path/to/test_class | API/UI/MOBILE | Date.now() | false | Test Suite A | true | I am a test that fails | https://example.com | http://example.com | + +> > > > > > > b023d8910c89d80573499890a958c0df649849e1 - id Automatically Generated - test_name\* Name of test diff --git a/package.json b/package.json index f027423..9e49ce7 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "start:dev": "nodemon dist/app.js", "start:dev:replit": "npm run start:dev & npm run start:react:replit", "start:react": "react-scripts start", - "start:react:replit": "DANGEROUSLY_DISABLE_HOST_CHECK=true npm run start:react", + "start:react:replit": "DANGEROUSLY_DISABLE_HOST_CHECK=true node --max-old-space-size=512 node_modules/.bin/react-scripts start", "test": "node tests/index.js", "test:api": "node tests/api.js", "test:dev": "nodemon tests/index.js" diff --git a/src/Views.jsx b/src/Views.jsx index 7c4e3d1..e3a3227 100644 --- a/src/Views.jsx +++ b/src/Views.jsx @@ -127,7 +127,11 @@ export default function Views() { > {navHeader()} - + diff --git a/src/ctx/JobContext.jsx b/src/ctx/JobContext.jsx index 10a8d73..7109205 100644 --- a/src/ctx/JobContext.jsx +++ b/src/ctx/JobContext.jsx @@ -1,6 +1,15 @@ import React, { useReducer, createContext, useMemo } from "react"; const JobContext = createContext(); +export const jobStatus = { + OK: "o", + QUEUED: "q", + PENDING: "p", + CANCELED: "c", + ACTIVE: "a", + ERROR: "e", +}; + const ACTIONS = { CREATE: "c", UPDATE: "u", @@ -10,6 +19,22 @@ const ACTIONS = { const initialState = { jobs: [], }; +/* +{ + name: "Job1", + test: "someTestName", + status: JOB_STATUS.SUCCESS, + exitcode: 0 +} + +OR +{ + compound: true, + name: "Compound Job", + pipeline: [{}] +} + +*/ const reducer = (state, action) => { // Current Jobs @@ -36,32 +61,35 @@ const reducer = (state, action) => { } }; - - export const JobProvider = ({ children }) => { const [state, dispatch] = useReducer(reducer, initialState); - const jobUpdate = (job, jobId) => dispatch({ type: ACTIONS.UPDATE, jobId, job }); + const jobUpdate = (job, jobId) => + dispatch({ type: ACTIONS.UPDATE, jobId, job }); const jobCreate = (job) => - dispatch({ type: ACTIONS.CREATE, job: { ...job, log: [] } }); + dispatch({ type: ACTIONS.CREATE, job: { ...job, log: [] } }); const jobDelete = (jobId) => dispatch({ type: ACTIONS.DELETE, jobId }); - function retryAll(failing){ - // Query Full Locator - console.log("Would retry all failing tests!"); -} + function retryAll(failing) { + // Query Full Locator + console.log("Would retry all failing tests!"); + } + + function activeJobStates() { + const jobs = { state }; + console.log("Would return all active job states"); + } + + function jobBuilder() {} -function jobBuilder(){ - -} - const context = { state, dispatch, jobUpdate, jobCreate, jobDelete, - retryAll + retryAll, + activeJobStates, }; const contextValue = useMemo(() => context, [state, dispatch]); diff --git a/src/ctx/StoreContext.jsx b/src/ctx/StoreContext.jsx index ff71176..aad6aca 100644 --- a/src/ctx/StoreContext.jsx +++ b/src/ctx/StoreContext.jsx @@ -1,14 +1,50 @@ import React, { useReducer, createContext, useMemo } from "react"; +import { jobStatus } from "./JobContext.jsx"; + const StoreContext = createContext(); const ACTIONS = { UPDATE: "u", }; +const failingMock = new Array(10).fill(0).map((v, i) => ({ + class: `SomeTestClass${i % 2 ? i - 1 : i / 2}`, + name: `TestThatDoesOneThing${i + 1}`, + timestamp: `2022-05-10T16:${2 + i}:33.810Z`, + silencedUntil: i % 4 ? null : `2022-05-10T16:${2 + i}:33.810Z`, + frequency: "1hour", + type: i % 3 ? "api" : "ui", + dailyFails: i + 1, + screenshot: "https://example.com", + recentResults: [1, 0, 0, 1, 0], + isCompound: i % 5 ? false : true, + failedMessage: `Some Test FailureMessage ${i}`, + jobStatus: (() => { + switch (i) { + case 1: + return jobStatus.OK; + case 3: + return jobStatus.ERROR; + case 4: + return jobStatus.PENDING; + case 5: + return jobStatus.ACTIVE; + case 6: + return jobStatus.CANCELED; + case 8: + return jobStatus.QUEUED; + default: + return null; + } + })(), +})); + const initialState = { intervals: [], - failing: [], + catalog: [], + failing: failngMock, regions: [], + catalogSearch: "", focusJob: false, simplifiedControls: false, defaultRegion: "us", // Local Store diff --git a/src/views/About.jsx b/src/views/About.jsx index 98f28bb..0b9266e 100644 --- a/src/views/About.jsx +++ b/src/views/About.jsx @@ -11,22 +11,36 @@ export default function About() {
- Why? - - - Qualiteer was designed to solve the issue of "on call". A state of being in which QA tests will fail, stiring everyone into a frenzy of what is broken in production! 🤯 - Qualiteer gives users power to resolve and reattempt failing tests, run a particular suite of tests, and mute pesky alerts reminding you the navbar's color changed... 🤦‍♂️ - -
- - {"Repository: "} - {repoUrl} - -
-
- Qualiteer -
-
-
- ); + + Why? + + + + Qualiteer was designed to solve the issue of "on call". A state of + being in which QA tests will fail, stiring everyone into a frenzy of + what is broken in production! 🤯 Qualiteer gives users power to + resolve and reattempt failing tests, run a particular suite of tests, + and mute pesky alerts reminding you the navbar's color changed... 🤦‍♂️ + +
+ + + {"Repository: "} + + {repoUrl} + +
+
+ + Qualiteer + +
+ + + ); } diff --git a/src/views/Alerting.jsx b/src/views/Alerting.jsx index 55dce25..1730a57 100644 --- a/src/views/Alerting.jsx +++ b/src/views/Alerting.jsx @@ -1,16 +1,16 @@ import { useState, useContext } from "react"; import StoreContext from "../ctx/StoreContext.jsx"; -import SpeedDial from '@mui/material/SpeedDial'; -import SpeedDialAction from '@mui/material/SpeedDialAction'; -import SpeedDialIcon from '@mui/material/SpeedDialIcon'; +import SpeedDial from "@mui/material/SpeedDial"; +import SpeedDialAction from "@mui/material/SpeedDialAction"; +import SpeedDialIcon from "@mui/material/SpeedDialIcon"; -import Button from '@mui/material/Button'; -import Dialog from '@mui/material/Dialog'; -import DialogActions from '@mui/material/DialogActions'; -import DialogContent from '@mui/material/DialogContent'; -import DialogContentText from '@mui/material/DialogContentText'; -import DialogTitle from '@mui/material/DialogTitle'; +import Button from "@mui/material/Button"; +import Dialog from "@mui/material/Dialog"; +import DialogActions from "@mui/material/DialogActions"; +import DialogContent from "@mui/material/DialogContent"; +import DialogContentText from "@mui/material/DialogContentText"; +import DialogTitle from "@mui/material/DialogTitle"; export default function Alerting() { const { state: store, updateStore } = useContext(StoreContext); @@ -18,29 +18,23 @@ export default function Alerting() { const [alertDialogOpen, setAlertDialogOpen] = useState(false); const quickAlertClick = () => setAlertDialogOpen(!alertDialogOpen); - function silenceAlert(){ - - } + function silenceAlert() {} const handleClose = (confirmed) => () => { - quickAlertClick(); - if(!confirmed) return; - silenceAlert(); - } - + quickAlertClick(); + if (!confirmed) return; + silenceAlert(); + }; + return (
- - Silence Alert - - - - + Silence Alert + } onClick={quickAlertClick} open={false} diff --git a/src/views/Catalog.jsx b/src/views/Catalog.jsx index 69c8d99..15641fb 100644 --- a/src/views/Catalog.jsx +++ b/src/views/Catalog.jsx @@ -1,4 +1,4 @@ -import { useContext } from "react"; +import { useEffect, useContext } from "react"; import StoreContext from "../ctx/StoreContext.jsx"; import JobContext from "../ctx/JobContext.jsx"; @@ -16,14 +16,25 @@ export default function Catalog() { const { state: store, updateStore } = useContext(StoreContext); + const handleSearchChange = (e) => + updateStore({ catalogSearch: e.target.value }); + + const handleSearchClear = () => updateStore({ catalogSearch: "" }); + + useEffect(() => { + return function unmount() { + handleSearchClear(); + }; + }, []); + return (
- - + +
{store.catalogSearch}
); } diff --git a/src/views/Failing.jsx b/src/views/Failing.jsx index e1b7bab..533a9ad 100644 --- a/src/views/Failing.jsx +++ b/src/views/Failing.jsx @@ -2,48 +2,55 @@ import { useState, useContext } from "react"; import StoreContext from "../ctx/StoreContext.jsx"; import JobContext from "../ctx/JobContext.jsx"; -import SpeedDial from '@mui/material/SpeedDial'; -import SpeedDialAction from '@mui/material/SpeedDialAction'; -import SpeedDialIcon from '@mui/material/SpeedDialIcon'; +import SpeedDial from "@mui/material/SpeedDial"; +import SpeedDialAction from "@mui/material/SpeedDialAction"; +import SpeedDialIcon from "@mui/material/SpeedDialIcon"; -import Button from '@mui/material/Button'; -import Dialog from '@mui/material/Dialog'; -import DialogActions from '@mui/material/DialogActions'; -import DialogContent from '@mui/material/DialogContent'; -import DialogContentText from '@mui/material/DialogContentText'; -import DialogTitle from '@mui/material/DialogTitle'; +import Button from "@mui/material/Button"; +import Dialog from "@mui/material/Dialog"; +import DialogActions from "@mui/material/DialogActions"; +import DialogContent from "@mui/material/DialogContent"; +import DialogContentText from "@mui/material/DialogContentText"; +import DialogTitle from "@mui/material/DialogTitle"; -import ReplayIcon from '@mui/icons-material/Replay'; +import ReplayIcon from "@mui/icons-material/Replay"; + +import FailingBox from "./components/FailingBox.jsx"; export default function Failing() { - const { - state: jobState, - retryAll - } = useContext(JobContext); + const { state: jobState, retryAll, activeJobStates } = useContext(JobContext); const { state: store, updateStore } = useContext(StoreContext); + const { failing } = store; + + /* TODO +for(var j of activeJobStates()){ +const failingTest = failing.find((f)=>f.name===j.testName); + if(!failingTest) continue; + failingTest.jobStatus= j.status; + }*/ const [retryAllOpen, setRetryAllOpen] = useState(false); const retryAllClick = () => setRetryAllOpen(!retryAllOpen); - const handleClose = (confirmed) => ()=> { + const handleClose = (confirmed) => () => { retryAllClick(); - if(!confirmed) return; - retryAll(store.failing); - } - + if (!confirmed) return; + retryAll(store.failing); + }; + return (
- + {failing.map((v, i) => ( + + ))} - - Retry all failing tests? - + Retry all failing tests? This will create x jobs and run y tests @@ -56,15 +63,14 @@ export default function Failing() { - - } onClick={retryAllClick} - open={false} + open={false} /> -
); } diff --git a/src/views/Jobs.jsx b/src/views/Jobs.jsx index 0ab6a26..60c24dc 100644 --- a/src/views/Jobs.jsx +++ b/src/views/Jobs.jsx @@ -2,15 +2,14 @@ import { useState, useContext } from "react"; import StoreContext from "../ctx/StoreContext.jsx"; import JobContext from "../ctx/JobContext.jsx"; +import ClickAwayListener from "@mui/material/ClickAwayListener"; +import SpeedDial from "@mui/material/SpeedDial"; +import SpeedDialAction from "@mui/material/SpeedDialAction"; +import SpeedDialIcon from "@mui/material/SpeedDialIcon"; -import ClickAwayListener from '@mui/material/ClickAwayListener'; -import SpeedDial from '@mui/material/SpeedDial'; -import SpeedDialAction from '@mui/material/SpeedDialAction'; -import SpeedDialIcon from '@mui/material/SpeedDialIcon'; - -import PageviewIcon from '@mui/icons-material/Pageview'; -import ViewColumnIcon from '@mui/icons-material/ViewColumn'; -import ViewCarouselIcon from '@mui/icons-material/ViewCarousel'; +import PageviewIcon from "@mui/icons-material/Pageview"; +import ViewColumnIcon from "@mui/icons-material/ViewColumn"; +import ViewCarouselIcon from "@mui/icons-material/ViewCarousel"; export default function Jobs() { const { @@ -26,30 +25,32 @@ export default function Jobs() { const quickOpenClick = () => setQuickOpen(!quickOpen); const quickOpenClose = () => setQuickOpen(false); - + const actions = [ - {name: "Suite", icon: }, {name: "Compound", icon: }, {name: "Manual", icon: } - ] - + { name: "Suite", icon: }, + { name: "Compound", icon: }, + { name: "Manual", icon: }, + ]; + return (
- - } - onClick={quickOpenClick} - open={quickOpen} - > - {actions.map((action) => ( - - ))} - - + + } + onClick={quickOpenClick} + open={quickOpen} + > + {actions.map((action) => ( + + ))} + +
); } diff --git a/src/views/Settings.jsx b/src/views/Settings.jsx index fee6ce2..4861ee6 100644 --- a/src/views/Settings.jsx +++ b/src/views/Settings.jsx @@ -1,76 +1,80 @@ -import { useContext, useState, useEffect } from "react"; +import React, { useContext, useState, useEffect } from "react"; import StoreContext from "../ctx/StoreContext.jsx"; import MultiOptionDialog from "./components/MultiOptionDialog.jsx"; -import * as React from 'react'; -import PropTypes from 'prop-types'; -import Box from '@mui/material/Box'; -import Button from '@mui/material/Button'; -import List from '@mui/material/List'; -import ListItem from '@mui/material/ListItem'; -import ListItemText from '@mui/material/ListItemText'; +import Box from "@mui/material/Box"; +import Button from "@mui/material/Button"; +import List from "@mui/material/List"; +import ListItem from "@mui/material/ListItem"; +import ListItemText from "@mui/material/ListItemText"; import Switch from "@mui/material/Switch"; -import SummarizeIcon from '@mui/icons-material/Summarize'; +import SummarizeIcon from "@mui/icons-material/Summarize"; import Typography from "@mui/material/Typography"; - export default function Settings(props) { - const { state: store, updateStore } = useContext(StoreContext); const { regions } = store; const { pages } = props; -const defaultDialog = {title: "", options: [], current: null, onSelect: null, open: false}; - const [dialog, setDialog] = React.useState(defaultDialog); - - const optionSettings = {region: { - title: "Region", - options: ["us", "au"], - current: store.defaultRegion, - onSelect: (r) => updateStore({defaultRegion: r}) -}, - defaultPage: { - title: "Default Page", - options: ["failing", "alerting"], - current: store.defaultPage, - onSelect: (p) => updateStore({defaultPage: p}) -}} - + const defaultDialog = { + title: "", + options: [], + current: null, + onSelect: null, + open: false, + }; + const [dialog, setDialog] = useState(defaultDialog); + + const optionSettings = { + region: { + title: "Region", + options: [], + current: store.defaultRegion, + onSelect: (r) => updateStore({ defaultRegion: r }), + }, + defaultPage: { + title: "Default Page", + options: pages, + current: store.defaultPage, + onSelect: (p) => updateStore({ defaultPage: p }), + }, + }; + const handleOptionsMenu = (s) => { - setDialog({...s, open:true}); + setDialog({ ...s, open: true }); }; const handleClose = (newValue, onSelect) => { - setDialog({...dialog, open:false}) + setDialog({ ...dialog, open: false }); if (!newValue) return; onSelect(newValue); }; - const handleToggle = (booleanSetting) => ()=> { + const handleToggle = (booleanSetting) => () => { const storeUpdate = {}; storeUpdate[booleanSetting] = !store[booleanSetting]; - updateStore(storeUpdate) - } + updateStore(storeUpdate); + }; - function MultiOptionSubtext(props){ - return( - - {props.value} - - ) + function MultiOptionSubtext(props) { + return ( + + + {props.value} + + + ); } - return ( - + - handleOptionsMenu(optionSettings.defaultPage)} > - - }/> + + } + /> - handleOptionsMenu(optionSettings.region)} + disabled={optionSettings.region.options.length === 0} > - } /> + + } + /> - + - + - + - + - + setOpen(!open); + + function Actions() { + return ( + + + + + + + + + ); + } + + return ( + + + + {`${testClass}#`} + + {testName} + +
+
+ + + + + + + + + {JSON.stringify(catalogTest)} + +
+
+ ); +} diff --git a/src/views/components/CatalogSearch.jsx b/src/views/components/CatalogSearch.jsx index 220f50a..d0e9c26 100644 --- a/src/views/components/CatalogSearch.jsx +++ b/src/views/components/CatalogSearch.jsx @@ -1,31 +1,44 @@ -import * as React from 'react'; -import Paper from '@mui/material/Paper'; -import InputBase from '@mui/material/InputBase'; -import Divider from '@mui/material/Divider'; -import IconButton from '@mui/material/IconButton'; -import MenuIcon from '@mui/icons-material/Menu'; -import SearchIcon from '@mui/icons-material/Search'; -import DirectionsIcon from '@mui/icons-material/Directions'; - import ClearOutlinedIcon from "@mui/icons-material/ClearOutlined"; +import { useEffect, useRef } from "react"; +import Paper from "@mui/material/Paper"; +import InputBase from "@mui/material/InputBase"; +import Divider from "@mui/material/Divider"; +import IconButton from "@mui/material/IconButton"; +import MenuIcon from "@mui/icons-material/Menu"; +import SearchIcon from "@mui/icons-material/Search"; +import DirectionsIcon from "@mui/icons-material/Directions"; +import ClearOutlinedIcon from "@mui/icons-material/ClearOutlined"; + +export default function CatalogSearch(props) { + const { onChange, onClear } = props; + + const searchRef = useRef(null); + + const handleClear = () => { + searchRef.current.children[0].value = null; + searchRef.current.children[0].focus(); + onClear(); + }; -export default function SearchBar(props) { return ( - + - + - - + + ); -} \ No newline at end of file +} diff --git a/src/views/components/FailingBox.jsx b/src/views/components/FailingBox.jsx new file mode 100644 index 0000000..f673013 --- /dev/null +++ b/src/views/components/FailingBox.jsx @@ -0,0 +1,166 @@ +import React, { useState, useContext } from "react"; +import StoreContext from "../../ctx/StoreContext.jsx"; +import JobContext, { jobStatus } from "../../ctx/JobContext.jsx"; + +import Accordion from "@mui/material/Accordion"; +import AccordionDetails from "@mui/material/AccordionDetails"; +import AccordionSummary from "@mui/material/AccordionSummary"; +import Typography from "@mui/material/Typography"; + +import IconButton from "@mui/material/IconButton"; +import DeleteIcon from "@mui/icons-material/Delete"; +import NotificationsIcon from "@mui/icons-material/Notifications"; +import ReplayIcon from "@mui/icons-material/Replay"; +import PhotoCameraIcon from "@mui/icons-material/PhotoCamera"; + +import CheckIcon from "@mui/icons-material/Check"; +import ClearIcon from "@mui/icons-material/Clear"; +import ViewColumnIcon from "@mui/icons-material/ViewColumn"; +import PendingIcon from "@mui/icons-material/Pending"; +import VisibilityIcon from "@mui/icons-material/Visibility"; +import DoNotDisturbIcon from "@mui/icons-material/DoNotDisturb"; + +import Badge from "@mui/material/Badge"; +import Stack from "@mui/material/Stack"; +import Box from "@mui/material/Box"; + +const stopPropagation = (e) => e.stopPropagation() && e.preventDefault(); + +export default function FailingBox(props) { + const { failingTest } = props; + + const { + class: testClass, + name: testName, + timestamp, + silencedUntil, + type, + dailyFails, + screenshot: screenshotUrl, + recentResults, + failedMessage, + isCompound, + jobStatus: testJobStatus, + } = failingTest; + + const { state: jobState, retryTest, retryJobStatus } = useContext(JobContext); + + const { state: store, updateStore } = useContext(StoreContext); + + const [open, setOpen] = useState(false); + + const toggleOpen = () => setOpen(!open); + + function badgeColor() { + if (dailyFails === 1) return "primary"; + else if (dailyFails === 2) return "secondary"; + else if (dailyFails < 6) return "warning"; + return "error"; + } + + function jobIcon() { + switch (testJobStatus) { + case jobStatus.OK: + return ; + case jobStatus.ERROR: + return ; + case jobStatus.PENDING: + return ; + case jobStatus.ACTIVE: + return ; + case jobStatus.CANCELED: + return ; + case jobStatus.QUEUED: + return ; + default: + return ; + } + } + + function Actions() { + return ( + + + + + + + {jobIcon()} + + + + + + + + + + ); + } + + return ( + + + + + {`${testClass}#`} + + {testName}{" "} + +
+ + {recentResults.map( + (v, i) => + (v && ) || ( + + ) + )} + + {isCompound && } +
+ + + + + + + +
+ + {failedMessage} + +
+ ); +} diff --git a/src/views/components/MultiOptionDialog.jsx b/src/views/components/MultiOptionDialog.jsx index 63e1789..c209702 100644 --- a/src/views/components/MultiOptionDialog.jsx +++ b/src/views/components/MultiOptionDialog.jsx @@ -1,24 +1,22 @@ -import {useState, useRef, useEffect} from "react"; - -import Button from "@mui/material/Button" -import DialogTitle from '@mui/material/DialogTitle'; -import DialogContent from '@mui/material/DialogContent'; -import DialogActions from '@mui/material/DialogActions'; -import Dialog from '@mui/material/Dialog'; -import RadioGroup from '@mui/material/RadioGroup'; -import Radio from '@mui/material/Radio'; -import FormControlLabel from '@mui/material/FormControlLabel'; +import { useState, useRef, useEffect } from "react"; +import Button from "@mui/material/Button"; +import DialogTitle from "@mui/material/DialogTitle"; +import DialogContent from "@mui/material/DialogContent"; +import DialogActions from "@mui/material/DialogActions"; +import Dialog from "@mui/material/Dialog"; +import RadioGroup from "@mui/material/RadioGroup"; +import Radio from "@mui/material/Radio"; +import FormControlLabel from "@mui/material/FormControlLabel"; export default function MultiOptionDialog(props) { - const { dialog: dialogProp, onClose, open, ...other } = props; const [value, setValue] = useState(dialogProp.current); const [dialog, setDialog] = useState(dialogProp); - + const radioGroupRef = useRef(null); - useEffect(() => { + useEffect(() => { setDialog(dialogProp); setValue(dialogProp.current); }, [dialogProp, open]); @@ -30,14 +28,14 @@ export default function MultiOptionDialog(props) { const handleCancel = () => onClose(); const handleOk = () => onClose(value, dialog.onSelect); - - const handleChange = (e) =>{ setValue(e.target.value); - } + const handleChange = (e) => { + setValue(e.target.value); + }; return ( { + setSilenceEntry(silence); + }, [silence, open]); + + const { state: store, updateStore } = useContext(StoreContext); + + const upsertSilence = () => { + console.log("Would upsert silence", silenceEntry); + }; + + const handleCancel = () => onClose(); + + const handleOk = () => onClose(silenceEntry); + + return ( + + Silence Alert + + {JSON.stringify(silenceEntry)} + + + + + + + ); +} diff --git a/src/views/components/SilencingBox.jsx b/src/views/components/SilencingBox.jsx new file mode 100644 index 0000000..13b19ce --- /dev/null +++ b/src/views/components/SilencingBox.jsx @@ -0,0 +1,75 @@ +import React, { useState, useContext } from "react"; +import StoreContext from "../../ctx/StoreContext.jsx"; + +import Accordion from "@mui/material/Accordion"; +import AccordionSummary from "@mui/material/AccordionSummary"; +import Typography from "@mui/material/Typography"; + +import IconButton from "@mui/material/IconButton"; +import DeleteIcon from "@mui/icons-material/Delete"; +import NotificationsIcon from "@mui/icons-material/Notifications"; + +import Stack from "@mui/material/Stack"; + +export default function SilencingBox(props) { + const { silenceEntry } = props; + + const { + name: testName, + method: testMethod, + class: testClass, + id: silenceId, + silencedUntil, + } = silenceEntry; + + const { state: store, updateStore } = useContext(StoreContext); + + function Actions() { + return ( + + + + + + + + + ); + } + + return ( + + + + {`Test Name: ${testName}`} +
+ {`Method: ${testMethod}`} +
+ {`Test Class: ${testClass}`} +
+ {`Silenced Until: ${silencedUntil} Remaining Time: 2:50`} +
+ + + + + + + +
+
+ ); +}