Fix dark theme styles

This commit is contained in:
Ken Hibino 2021-01-12 16:41:14 -08:00
parent b15fa59cf9
commit e7cfbc6bf7
13 changed files with 307 additions and 215 deletions

View File

@ -19,7 +19,6 @@
"@types/react-router-dom": "5.1.6", "@types/react-router-dom": "5.1.6",
"@types/react-syntax-highlighter": "13.5.0", "@types/react-syntax-highlighter": "13.5.0",
"@types/recharts": "1.8.16", "@types/recharts": "1.8.16",
"@types/styled-components": "5.1.4",
"axios": "0.20.0", "axios": "0.20.0",
"clsx": "1.1.1", "clsx": "1.1.1",
"lodash.uniqby": "4.7.0", "lodash.uniqby": "4.7.0",
@ -31,7 +30,6 @@
"react-scripts": "3.4.3", "react-scripts": "3.4.3",
"react-syntax-highlighter": "15.3.0", "react-syntax-highlighter": "15.3.0",
"recharts": "1.8.5", "recharts": "1.8.5",
"styled-components": "5.2.0",
"typescript": "~3.7.2" "typescript": "~3.7.2"
}, },
"scripts": { "scripts": {

View File

@ -2,7 +2,7 @@ import React, { useState } from "react";
import { connect, ConnectedProps } from "react-redux"; import { connect, ConnectedProps } from "react-redux";
import clsx from "clsx"; import clsx from "clsx";
import { BrowserRouter as Router, Switch, Route } from "react-router-dom"; import { BrowserRouter as Router, Switch, Route } from "react-router-dom";
import { makeStyles, ThemeProvider } from "@material-ui/core/styles"; import { makeStyles, Theme, ThemeProvider } from "@material-ui/core/styles";
import AppBar from "@material-ui/core/AppBar"; import AppBar from "@material-ui/core/AppBar";
import Drawer from "@material-ui/core/Drawer"; import Drawer from "@material-ui/core/Drawer";
import Toolbar from "@material-ui/core/Toolbar"; import Toolbar from "@material-ui/core/Toolbar";
@ -39,7 +39,11 @@ import PageNotFoundView from "./views/PageNotFoundView";
const drawerWidth = 220; const drawerWidth = 220;
const useStyles = makeStyles((theme) => ({ // FIXME: For some reason, the following code does not work:
// makeStyles(theme => ({ /* use theme here */}));
// Using closure to work around this problem.
const useStyles = (theme: Theme) =>
makeStyles({
root: { root: {
display: "flex", display: "flex",
}, },
@ -66,7 +70,6 @@ const useStyles = makeStyles((theme) => ({
}, },
title: { title: {
flexGrow: 1, flexGrow: 1,
color: theme.palette.grey[800],
}, },
drawerPaper: { drawerPaper: {
position: "relative", position: "relative",
@ -105,7 +108,7 @@ const useStyles = makeStyles((theme) => ({
flex: 1, flex: 1,
height: "100vh", height: "100vh",
overflow: "hidden", overflow: "hidden",
background: "#ffffff", background: theme.palette.background.paper,
}, },
contentWrapper: { contentWrapper: {
height: "100%", height: "100%",
@ -123,7 +126,7 @@ const useStyles = makeStyles((theme) => ({
borderTopRightRadius: "24px", borderTopRightRadius: "24px",
borderBottomRightRadius: "24px", borderBottomRightRadius: "24px",
}, },
})); });
function mapStateToProps(state: AppState) { function mapStateToProps(state: AppState) {
return { return {
@ -143,10 +146,10 @@ function SlideUpTransition(props: TransitionProps) {
} }
function App(props: ConnectedProps<typeof connector>) { function App(props: ConnectedProps<typeof connector>) {
const classes = useStyles(); const theme = makeTheme(props.isDarkTheme);
const classes = useStyles(theme)();
const [open, setOpen] = useState(true); const [open, setOpen] = useState(true);
const toggleDrawer = () => setOpen(!open); const toggleDrawer = () => setOpen(!open);
const theme = makeTheme(props.isDarkTheme);
return ( return (
<ThemeProvider theme={theme}> <ThemeProvider theme={theme}>
<Router> <Router>
@ -169,9 +172,9 @@ function App(props: ConnectedProps<typeof connector>) {
<Typography <Typography
component="h1" component="h1"
variant="h6" variant="h6"
color="inherit"
noWrap noWrap
className={classes.title} className={classes.title}
color="textPrimary"
> >
Asynq Monitoring Asynq Monitoring
</Typography> </Typography>

View File

@ -41,11 +41,14 @@ import { ActiveTaskExtended } from "../reducers/tasksReducer";
import { uuidPrefix } from "../utils"; import { uuidPrefix } from "../utils";
import { TableColumn } from "../types/table"; import { TableColumn } from "../types/table";
const useStyles = makeStyles({ const useStyles = makeStyles((theme) => ({
table: { table: {
minWidth: 650, minWidth: 650,
}, },
}); stickyHeaderCell: {
background: theme.palette.background.paper,
},
}));
function mapStateToProps(state: AppState) { function mapStateToProps(state: AppState) {
return { return {
@ -168,7 +171,10 @@ function ActiveTasksTable(props: Props & ReduxProps) {
> >
<TableHead> <TableHead>
<TableRow> <TableRow>
<TableCell padding="checkbox"> <TableCell
padding="checkbox"
classes={{ stickyHeader: classes.stickyHeaderCell }}
>
<Checkbox <Checkbox
indeterminate={numSelected > 0 && numSelected < rowCount} indeterminate={numSelected > 0 && numSelected < rowCount}
checked={rowCount > 0 && numSelected === rowCount} checked={rowCount > 0 && numSelected === rowCount}
@ -179,7 +185,11 @@ function ActiveTasksTable(props: Props & ReduxProps) {
/> />
</TableCell> </TableCell>
{columns.map((col) => ( {columns.map((col) => (
<TableCell key={col.key} align={col.align}> <TableCell
key={col.key}
align={col.align}
classes={{ stickyHeader: classes.stickyHeaderCell }}
>
{col.label} {col.label}
</TableCell> </TableCell>
))} ))}

View File

@ -46,11 +46,14 @@ import { usePolling } from "../hooks";
import { ArchivedTaskExtended } from "../reducers/tasksReducer"; import { ArchivedTaskExtended } from "../reducers/tasksReducer";
import { TableColumn } from "../types/table"; import { TableColumn } from "../types/table";
const useStyles = makeStyles({ const useStyles = makeStyles((theme) => ({
table: { table: {
minWidth: 650, minWidth: 650,
}, },
}); stickyHeaderCell: {
background: theme.palette.background.paper,
},
}));
const useRowStyles = makeStyles({ const useRowStyles = makeStyles({
root: { root: {
@ -214,7 +217,10 @@ function ArchivedTasksTable(props: Props & ReduxProps) {
> >
<TableHead> <TableHead>
<TableRow> <TableRow>
<TableCell padding="checkbox"> <TableCell
padding="checkbox"
classes={{ stickyHeader: classes.stickyHeaderCell }}
>
<Checkbox <Checkbox
indeterminate={numSelected > 0 && numSelected < rowCount} indeterminate={numSelected > 0 && numSelected < rowCount}
checked={rowCount > 0 && numSelected === rowCount} checked={rowCount > 0 && numSelected === rowCount}
@ -225,7 +231,11 @@ function ArchivedTasksTable(props: Props & ReduxProps) {
/> />
</TableCell> </TableCell>
{columns.map((col) => ( {columns.map((col) => (
<TableCell key={col.key} align={col.align}> <TableCell
key={col.key}
align={col.align}
classes={{ stickyHeader: classes.stickyHeaderCell }}
>
{col.label} {col.label}
</TableCell> </TableCell>
))} ))}

View File

@ -32,11 +32,14 @@ import { usePolling } from "../hooks";
import { uuidPrefix } from "../utils"; import { uuidPrefix } from "../utils";
import { TableColumn } from "../types/table"; import { TableColumn } from "../types/table";
const useStyles = makeStyles({ const useStyles = makeStyles((theme) => ({
table: { table: {
minWidth: 650, minWidth: 650,
}, },
}); stickyHeaderCell: {
background: theme.palette.background.paper,
},
}));
function mapStateToProps(state: AppState) { function mapStateToProps(state: AppState) {
return { return {
@ -110,7 +113,11 @@ function PendingTasksTable(props: Props & ReduxProps) {
<TableHead> <TableHead>
<TableRow> <TableRow>
{columns.map((col) => ( {columns.map((col) => (
<TableCell key={col.key} align={col.align}> <TableCell
key={col.key}
align={col.align}
classes={{ stickyHeader: classes.stickyHeaderCell }}
>
{col.label} {col.label}
</TableCell> </TableCell>
))} ))}

View File

@ -27,6 +27,7 @@ const useStyles = makeStyles((theme) => ({
}, },
linkCell: { linkCell: {
textDecoration: "none", textDecoration: "none",
color: theme.palette.text.primary,
}, },
footerCell: { footerCell: {
fontWeight: 600, fontWeight: 600,
@ -40,7 +41,7 @@ const useStyles = makeStyles((theme) => ({
position: "sticky", position: "sticky",
zIndex: 1, zIndex: 1,
left: 0, left: 0,
background: theme.palette.common.white, background: theme.palette.background.paper,
}, },
actionIconsContainer: { actionIconsContainer: {
display: "flex", display: "flex",
@ -211,7 +212,10 @@ export default function QueuesOverviewTable(props: Props) {
scope="row" scope="row"
className={clsx(classes.boldCell, classes.fixedCell)} className={clsx(classes.boldCell, classes.fixedCell)}
> >
<Link to={queueDetailsPath(q.queue)}> <Link
to={queueDetailsPath(q.queue)}
className={classes.linkCell}
>
{q.queue} {q.queue}
{q.paused ? " (paused)" : ""} {q.paused ? " (paused)" : ""}
</Link> </Link>

View File

@ -50,11 +50,14 @@ import { RetryTaskExtended } from "../reducers/tasksReducer";
import clsx from "clsx"; import clsx from "clsx";
import { TableColumn } from "../types/table"; import { TableColumn } from "../types/table";
const useStyles = makeStyles({ const useStyles = makeStyles((theme) => ({
table: { table: {
minWidth: 650, minWidth: 650,
}, },
}); stickyHeaderCell: {
background: theme.palette.background.paper,
},
}));
function mapStateToProps(state: AppState) { function mapStateToProps(state: AppState) {
return { return {
@ -229,7 +232,10 @@ function RetryTasksTable(props: Props & ReduxProps) {
> >
<TableHead> <TableHead>
<TableRow> <TableRow>
<TableCell padding="checkbox"> <TableCell
padding="checkbox"
classes={{ stickyHeader: classes.stickyHeaderCell }}
>
<Checkbox <Checkbox
indeterminate={numSelected > 0 && numSelected < rowCount} indeterminate={numSelected > 0 && numSelected < rowCount}
checked={rowCount > 0 && numSelected === rowCount} checked={rowCount > 0 && numSelected === rowCount}
@ -240,7 +246,11 @@ function RetryTasksTable(props: Props & ReduxProps) {
/> />
</TableCell> </TableCell>
{columns.map((col) => ( {columns.map((col) => (
<TableCell key={col.label} align={col.align}> <TableCell
key={col.label}
align={col.align}
classes={{ stickyHeader: classes.stickyHeaderCell }}
>
{col.label} {col.label}
</TableCell> </TableCell>
))} ))}

View File

@ -50,11 +50,14 @@ import { usePolling } from "../hooks";
import { ScheduledTaskExtended } from "../reducers/tasksReducer"; import { ScheduledTaskExtended } from "../reducers/tasksReducer";
import { TableColumn } from "../types/table"; import { TableColumn } from "../types/table";
const useStyles = makeStyles({ const useStyles = makeStyles((theme) => ({
table: { table: {
minWidth: 650, minWidth: 650,
}, },
}); stickyHeaderCell: {
background: theme.palette.background.paper,
},
}));
function mapStateToProps(state: AppState) { function mapStateToProps(state: AppState) {
return { return {
@ -226,7 +229,10 @@ function ScheduledTasksTable(props: Props & ReduxProps) {
> >
<TableHead> <TableHead>
<TableRow> <TableRow>
<TableCell padding="checkbox"> <TableCell
padding="checkbox"
classes={{ stickyHeader: classes.stickyHeaderCell }}
>
<Checkbox <Checkbox
indeterminate={numSelected > 0 && numSelected < rowCount} indeterminate={numSelected > 0 && numSelected < rowCount}
checked={rowCount > 0 && numSelected === rowCount} checked={rowCount > 0 && numSelected === rowCount}
@ -237,7 +243,11 @@ function ScheduledTasksTable(props: Props & ReduxProps) {
/> />
</TableCell> </TableCell>
{columns.map((col) => ( {columns.map((col) => (
<TableCell key={col.label} align={col.align}> <TableCell
key={col.label}
align={col.align}
classes={{ stickyHeader: classes.stickyHeaderCell }}
>
{col.label} {col.label}
</TableCell> </TableCell>
))} ))}

View File

@ -1,7 +1,7 @@
import React, { useState } from "react"; import React, { useState } from "react";
import { Link } from "react-router-dom"; import { Link } from "react-router-dom";
import clsx from "clsx"; import clsx from "clsx";
import { makeStyles } from "@material-ui/core/styles"; import { makeStyles, useTheme, Theme } from "@material-ui/core/styles";
import Grid from "@material-ui/core/Grid"; import Grid from "@material-ui/core/Grid";
import Box from "@material-ui/core/Box"; import Box from "@material-ui/core/Box";
import Collapse from "@material-ui/core/Collapse"; import Collapse from "@material-ui/core/Collapse";
@ -19,7 +19,8 @@ import KeyboardArrowUpIcon from "@material-ui/icons/KeyboardArrowUp";
import Alert from "@material-ui/lab/Alert"; import Alert from "@material-ui/lab/Alert";
import AlertTitle from "@material-ui/lab/AlertTitle"; import AlertTitle from "@material-ui/lab/AlertTitle";
import SyntaxHighlighter from "react-syntax-highlighter"; import SyntaxHighlighter from "react-syntax-highlighter";
import syntaxHighlightStyle from "react-syntax-highlighter/dist/esm/styles/hljs/github"; import syntaxHighlightStyleDark from "react-syntax-highlighter/dist/esm/styles/hljs/atom-one-dark";
import syntaxHighlightStyleLight from "react-syntax-highlighter/dist/esm/styles/hljs/atom-one-light";
import { ServerInfo } from "../api"; import { ServerInfo } from "../api";
import { SortDirection, SortableTableColumn } from "../types/table"; import { SortDirection, SortableTableColumn } from "../types/table";
import { timeAgo, uuidPrefix } from "../utils"; import { timeAgo, uuidPrefix } from "../utils";
@ -34,7 +35,7 @@ const useStyles = makeStyles((theme) => ({
position: "sticky", position: "sticky",
zIndex: 1, zIndex: 1,
left: 0, left: 0,
background: theme.palette.common.white, background: theme.palette.background.paper,
}, },
})); }));
@ -208,10 +209,15 @@ const useRowStyles = makeStyles((theme) => ({
noBorder: { noBorder: {
border: "none", border: "none",
}, },
link: {
color: theme.palette.text.primary,
},
})); }));
function Row(props: RowProps) { function Row(props: RowProps) {
const classes = useRowStyles(); const classes = useRowStyles();
const theme = useTheme<Theme>();
const isDarkTheme = theme.palette.type === "dark";
const { server } = props; const { server } = props;
const [open, setOpen] = useState<boolean>(false); const [open, setOpen] = useState<boolean>(false);
const qnames = Object.keys(server.queue_priorities); const qnames = Object.keys(server.queue_priorities);
@ -226,7 +232,9 @@ function Row(props: RowProps) {
<TableCell> <TableCell>
{qnames.map((qname, idx) => ( {qnames.map((qname, idx) => (
<span key={qname}> <span key={qname}>
<Link to={queueDetailsPath(qname)}>{qname}</Link> <Link to={queueDetailsPath(qname)} className={classes.link}>
{qname}
</Link>
{idx === qnames.length - 1 ? "" : ", "} {idx === qnames.length - 1 ? "" : ", "}
</span> </span>
))} ))}
@ -276,7 +284,11 @@ function Row(props: RowProps) {
<TableCell> <TableCell>
<SyntaxHighlighter <SyntaxHighlighter
language="json" language="json"
style={syntaxHighlightStyle} style={
isDarkTheme
? syntaxHighlightStyleDark
: syntaxHighlightStyleLight
}
customStyle={{ margin: 0 }} customStyle={{ margin: 0 }}
> >
{JSON.stringify(worker.task.payload)} {JSON.stringify(worker.task.payload)}
@ -308,7 +320,12 @@ function Row(props: RowProps) {
{qnames.map((qname) => ( {qnames.map((qname) => (
<TableRow key={qname}> <TableRow key={qname}>
<TableCell> <TableCell>
<Link to={queueDetailsPath(qname)}>{qname}</Link> <Link
to={queueDetailsPath(qname)}
className={classes.link}
>
{qname}
</Link>
</TableCell> </TableCell>
<TableCell align="right"> <TableCell align="right">
{server.queue_priorities[qname]} {server.queue_priorities[qname]}

View File

@ -1,9 +1,10 @@
import React from "react"; import React from "react";
import { connect, ConnectedProps } from "react-redux"; import { connect, ConnectedProps } from "react-redux";
import styled from "styled-components";
import { makeStyles } from "@material-ui/core/styles"; import { makeStyles } from "@material-ui/core/styles";
import Tabs from "@material-ui/core/Tabs"; import Tabs from "@material-ui/core/Tabs";
import Tab from "@material-ui/core/Tab"; import Tab from "@material-ui/core/Tab";
import Typography from "@material-ui/core/Typography";
import Paper from "@material-ui/core/Paper";
import ActiveTasksTable from "./ActiveTasksTable"; import ActiveTasksTable from "./ActiveTasksTable";
import PendingTasksTable from "./PendingTasksTable"; import PendingTasksTable from "./PendingTasksTable";
import ScheduledTasksTable from "./ScheduledTasksTable"; import ScheduledTasksTable from "./ScheduledTasksTable";
@ -11,8 +12,6 @@ import RetryTasksTable from "./RetryTasksTable";
import ArchivedTasksTable from "./ArchivedTasksTable"; import ArchivedTasksTable from "./ArchivedTasksTable";
import { useHistory } from "react-router-dom"; import { useHistory } from "react-router-dom";
import { queueDetailsPath } from "../paths"; import { queueDetailsPath } from "../paths";
import { Typography } from "@material-ui/core";
import Paper from "@material-ui/core/Paper/Paper";
import { QueueInfo } from "../reducers/queuesReducer"; import { QueueInfo } from "../reducers/queuesReducer";
import { AppState } from "../store"; import { AppState } from "../store";
@ -22,24 +21,20 @@ interface TabPanelProps {
value: string; // tab panel will be shown if selected value equals to the value value: string; // tab panel will be shown if selected value equals to the value
} }
const TabPanelRoot = styled.div`
flex: 1;
overflow-y: scroll;
`;
function TabPanel(props: TabPanelProps) { function TabPanel(props: TabPanelProps) {
const { children, value, selected, ...other } = props; const { children, value, selected, ...other } = props;
return ( return (
<TabPanelRoot <div
role="tabpanel" role="tabpanel"
hidden={value !== selected} hidden={value !== selected}
id={`scrollable-auto-tabpanel-${selected}`} id={`scrollable-auto-tabpanel-${selected}`}
aria-labelledby={`scrollable-auto-tab-${selected}`} aria-labelledby={`scrollable-auto-tab-${selected}`}
style={{ flex: 1, overflowY: "scroll" }}
{...other} {...other}
> >
{value === selected && children} {value === selected && children}
</TabPanelRoot> </div>
); );
} }
@ -50,67 +45,13 @@ function a11yProps(value: string) {
}; };
} }
const Container = styled.div` const usePanelHeadingStyles = makeStyles((theme) => ({
display: flex;
width: 100%;
height: 100%;
`;
const TaskCount = styled.div`
font-size: 2rem;
font-weight: 600;
margin: 0;
`;
const Heading = styled.div`
opacity: 0.7;
font-size: 1.7rem;
font-weight: 500;
background: #f5f7f9;
padding-left: 28px;
padding-top: 28px;
padding-bottom: 28px;
`;
const PanelContainer = styled.div`
padding: 24px;
background: #ffffff;
`;
const TabsContainer = styled.div`
background: #f5f7f9;
`;
const useStyles = makeStyles((theme) => ({
paper: { paper: {
padding: theme.spacing(2), padding: theme.spacing(2),
marginBottom: theme.spacing(2), marginBottom: theme.spacing(2),
display: "flex", display: "flex",
justifyContent: "space-between", justifyContent: "space-between",
}, },
heading: {
padingLeft: theme.spacing(2),
},
tabsRoot: {
paddingLeft: theme.spacing(2),
background: theme.palette.background.default,
},
tabsIndicator: {
right: "auto",
left: "0",
},
tabroot: {
width: "204px",
textAlign: "left",
padding: theme.spacing(2),
},
tabwrapper: {
alignItems: "flex-start",
},
tabSelected: {
background: theme.palette.common.white,
boxShadow: theme.shadows[1],
},
})); }));
function PanelHeading(props: { function PanelHeading(props: {
@ -119,9 +60,9 @@ function PanelHeading(props: {
failed: number; failed: number;
paused: boolean; paused: boolean;
}) { }) {
const classes = useStyles(); const classes = usePanelHeadingStyles();
return ( return (
<Paper className={classes.paper}> <Paper variant="outlined" className={classes.paper}>
<div> <div>
<Typography variant="overline" display="block"> <Typography variant="overline" display="block">
Queue Name Queue Name
@ -183,15 +124,66 @@ interface Props {
selected: string; selected: string;
} }
const useStyles = makeStyles((theme) => ({
container: {
display: "flex",
width: "100%",
height: "100%",
},
heading: {
opacity: 0.7,
fontSize: "1.7rem",
fontWeight: 500,
backgroundColor: theme.palette.background.paper,
paddingLeft: "28px", // TODO: maybe use theme.spacing(3),
paddingTop: "28px",
paddingBottom: "28px",
color: theme.palette.text.primary,
},
tabsContainer: {
background: theme.palette.background.paper,
},
tabsRoot: {
paddingLeft: theme.spacing(2),
background: theme.palette.background.paper,
},
tabsIndicator: {
right: "auto",
left: "0",
},
tabroot: {
width: "204px",
textAlign: "left",
padding: theme.spacing(2),
},
tabwrapper: {
alignItems: "flex-start",
color: theme.palette.text.primary,
},
tabSelected: {
background: theme.palette.action.selected,
boxShadow: theme.shadows[1],
},
panelContainer: {
padding: "24px",
background: theme.palette.background.paper,
},
taskCount: {
fontSize: "2rem",
fontWeight: 600,
margin: 0,
},
}));
function TasksTable(props: Props & ReduxProps) { function TasksTable(props: Props & ReduxProps) {
const { currentStats } = props; const { currentStats } = props;
const classes = useStyles(); const classes = useStyles();
const history = useHistory(); const history = useHistory();
return ( return (
<Container> <div className={classes.container}>
<TabsContainer> <div className={classes.tabsContainer}>
<Heading>Tasks</Heading> <div className={classes.heading}>Tasks</div>
<Tabs <Tabs
value={props.selected} value={props.selected}
onChange={(_, value: string) => onChange={(_, value: string) =>
@ -204,7 +196,9 @@ function TasksTable(props: Props & ReduxProps) {
<Tab <Tab
value="active" value="active"
label="Active" label="Active"
icon={<TaskCount>{currentStats.active}</TaskCount>} icon={
<div className={classes.taskCount}>{currentStats.active}</div>
}
classes={{ classes={{
root: classes.tabroot, root: classes.tabroot,
wrapper: classes.tabwrapper, wrapper: classes.tabwrapper,
@ -215,7 +209,9 @@ function TasksTable(props: Props & ReduxProps) {
<Tab <Tab
value="pending" value="pending"
label="Pending" label="Pending"
icon={<TaskCount>{currentStats.pending}</TaskCount>} icon={
<div className={classes.taskCount}>{currentStats.pending}</div>
}
classes={{ classes={{
root: classes.tabroot, root: classes.tabroot,
wrapper: classes.tabwrapper, wrapper: classes.tabwrapper,
@ -226,7 +222,9 @@ function TasksTable(props: Props & ReduxProps) {
<Tab <Tab
value="scheduled" value="scheduled"
label="Scheduled" label="Scheduled"
icon={<TaskCount>{currentStats.scheduled}</TaskCount>} icon={
<div className={classes.taskCount}>{currentStats.scheduled}</div>
}
classes={{ classes={{
root: classes.tabroot, root: classes.tabroot,
wrapper: classes.tabwrapper, wrapper: classes.tabwrapper,
@ -237,7 +235,7 @@ function TasksTable(props: Props & ReduxProps) {
<Tab <Tab
value="retry" value="retry"
label="Retry" label="Retry"
icon={<TaskCount>{currentStats.retry}</TaskCount>} icon={<div className={classes.taskCount}>{currentStats.retry}</div>}
classes={{ classes={{
root: classes.tabroot, root: classes.tabroot,
wrapper: classes.tabwrapper, wrapper: classes.tabwrapper,
@ -248,7 +246,9 @@ function TasksTable(props: Props & ReduxProps) {
<Tab <Tab
value="archived" value="archived"
label="Archived" label="Archived"
icon={<TaskCount>{currentStats.archived}</TaskCount>} icon={
<div className={classes.taskCount}>{currentStats.archived}</div>
}
classes={{ classes={{
root: classes.tabroot, root: classes.tabroot,
wrapper: classes.tabwrapper, wrapper: classes.tabwrapper,
@ -257,9 +257,9 @@ function TasksTable(props: Props & ReduxProps) {
{...a11yProps("archived")} {...a11yProps("archived")}
/> />
</Tabs> </Tabs>
</TabsContainer> </div>
<TabPanel value="active" selected={props.selected}> <TabPanel value="active" selected={props.selected}>
<PanelContainer> <div className={classes.panelContainer}>
<PanelHeading <PanelHeading
queue={props.queue} queue={props.queue}
processed={currentStats.processed} processed={currentStats.processed}
@ -267,10 +267,10 @@ function TasksTable(props: Props & ReduxProps) {
paused={currentStats.paused} paused={currentStats.paused}
/> />
<ActiveTasksTable queue={props.queue} /> <ActiveTasksTable queue={props.queue} />
</PanelContainer> </div>
</TabPanel> </TabPanel>
<TabPanel value="pending" selected={props.selected}> <TabPanel value="pending" selected={props.selected}>
<PanelContainer> <div className={classes.panelContainer}>
<PanelHeading <PanelHeading
queue={props.queue} queue={props.queue}
processed={currentStats.processed} processed={currentStats.processed}
@ -281,10 +281,10 @@ function TasksTable(props: Props & ReduxProps) {
queue={props.queue} queue={props.queue}
totalTaskCount={currentStats.pending} totalTaskCount={currentStats.pending}
/> />
</PanelContainer> </div>
</TabPanel> </TabPanel>
<TabPanel value="scheduled" selected={props.selected}> <TabPanel value="scheduled" selected={props.selected}>
<PanelContainer> <div className={classes.panelContainer}>
<PanelHeading <PanelHeading
queue={props.queue} queue={props.queue}
processed={currentStats.processed} processed={currentStats.processed}
@ -295,10 +295,10 @@ function TasksTable(props: Props & ReduxProps) {
queue={props.queue} queue={props.queue}
totalTaskCount={currentStats.scheduled} totalTaskCount={currentStats.scheduled}
/> />
</PanelContainer> </div>
</TabPanel> </TabPanel>
<TabPanel value="retry" selected={props.selected}> <TabPanel value="retry" selected={props.selected}>
<PanelContainer> <div className={classes.panelContainer}>
<PanelHeading <PanelHeading
queue={props.queue} queue={props.queue}
processed={currentStats.processed} processed={currentStats.processed}
@ -309,10 +309,10 @@ function TasksTable(props: Props & ReduxProps) {
queue={props.queue} queue={props.queue}
totalTaskCount={currentStats.retry} totalTaskCount={currentStats.retry}
/> />
</PanelContainer> </div>
</TabPanel> </TabPanel>
<TabPanel value="archived" selected={props.selected}> <TabPanel value="archived" selected={props.selected}>
<PanelContainer> <div className={classes.panelContainer}>
<PanelHeading <PanelHeading
queue={props.queue} queue={props.queue}
processed={currentStats.processed} processed={currentStats.processed}
@ -323,9 +323,9 @@ function TasksTable(props: Props & ReduxProps) {
queue={props.queue} queue={props.queue}
totalTaskCount={currentStats.archived} totalTaskCount={currentStats.archived}
/> />
</PanelContainer> </div>
</TabPanel> </TabPanel>
</Container> </div>
); );
} }

View File

@ -1,4 +1,8 @@
import {POLL_INTERVAL_CHANGE, SettingsActionTypes, TOGGLE_DARK_THEME,} from '../actions/settingsActions'; import {
POLL_INTERVAL_CHANGE,
SettingsActionTypes,
TOGGLE_DARK_THEME,
} from "../actions/settingsActions";
interface SettingsState { interface SettingsState {
pollInterval: number; pollInterval: number;
@ -7,18 +11,21 @@ interface SettingsState {
const initialState: SettingsState = { const initialState: SettingsState = {
pollInterval: 8, pollInterval: 8,
isDarkTheme: false, isDarkTheme: true,
}; };
function settingsReducer( function settingsReducer(
state = initialState, action: SettingsActionTypes): SettingsState { state = initialState,
action: SettingsActionTypes
): SettingsState {
switch (action.type) { switch (action.type) {
case POLL_INTERVAL_CHANGE: case POLL_INTERVAL_CHANGE:
return {...state, pollInterval: action.value}; return { ...state, pollInterval: action.value };
case TOGGLE_DARK_THEME: case TOGGLE_DARK_THEME:
return { return {
...state, isDarkTheme: !state.isDarkTheme ...state,
} isDarkTheme: !state.isDarkTheme,
};
default: default:
return state; return state;
} }

View File

@ -9,7 +9,8 @@ import CardContent from "@material-ui/core/CardContent";
import Alert from "@material-ui/lab/Alert"; import Alert from "@material-ui/lab/Alert";
import AlertTitle from "@material-ui/lab/AlertTitle"; import AlertTitle from "@material-ui/lab/AlertTitle";
import SyntaxHighlighter from "react-syntax-highlighter"; import SyntaxHighlighter from "react-syntax-highlighter";
import syntaxHighlightStyle from "react-syntax-highlighter/dist/esm/styles/hljs/github"; import syntaxHighlightStyleDark from "react-syntax-highlighter/dist/esm/styles/hljs/atom-one-dark";
import syntaxHighlightStyleLight from "react-syntax-highlighter/dist/esm/styles/hljs/atom-one-light";
import { getRedisInfoAsync } from "../actions/redisInfoActions"; import { getRedisInfoAsync } from "../actions/redisInfoActions";
import { usePolling } from "../hooks"; import { usePolling } from "../hooks";
import { AppState } from "../store"; import { AppState } from "../store";
@ -30,6 +31,7 @@ function mapStateToProps(state: AppState) {
redisAddress: state.redis.address, redisAddress: state.redis.address,
redisInfoRaw: state.redis.rawData, redisInfoRaw: state.redis.rawData,
pollInterval: state.settings.pollInterval, pollInterval: state.settings.pollInterval,
isDarkTheme: state.settings.isDarkTheme,
}; };
} }
@ -38,7 +40,13 @@ type Props = ConnectedProps<typeof connector>;
function RedisInfoView(props: Props) { function RedisInfoView(props: Props) {
const classes = useStyles(); const classes = useStyles();
const { pollInterval, getRedisInfoAsync, redisInfo, redisInfoRaw } = props; const {
pollInterval,
getRedisInfoAsync,
redisInfo,
redisInfoRaw,
isDarkTheme,
} = props;
usePolling(getRedisInfoAsync, pollInterval); usePolling(getRedisInfoAsync, pollInterval);
@ -56,7 +64,9 @@ function RedisInfoView(props: Props) {
{props.error === "" ? ( {props.error === "" ? (
<> <>
<Grid item xs={12}> <Grid item xs={12}>
<Typography variant="h5">Redis Info</Typography> <Typography variant="h5" color="textPrimary">
Redis Info
</Typography>
<Typography variant="subtitle1" color="textSecondary"> <Typography variant="subtitle1" color="textSecondary">
Connected to: {props.redisAddress} Connected to: {props.redisAddress}
</Typography> </Typography>
@ -153,7 +163,11 @@ function RedisInfoView(props: Props) {
</Typography> </Typography>
<SyntaxHighlighter <SyntaxHighlighter
language="yaml" language="yaml"
style={syntaxHighlightStyle} style={
isDarkTheme
? syntaxHighlightStyleDark
: syntaxHighlightStyleLight
}
> >
{redisInfoRaw} {redisInfoRaw}
</SyntaxHighlighter> </SyntaxHighlighter>

View File

@ -60,7 +60,9 @@ function SettingsView(props: PropsFromRedux) {
<Container maxWidth="lg" className={classes.container}> <Container maxWidth="lg" className={classes.container}>
<Grid container spacing={3}> <Grid container spacing={3}>
<Grid item xs={12}> <Grid item xs={12}>
<Typography variant="h5">Settings</Typography> <Typography variant="h5" color="textPrimary">
Settings
</Typography>
</Grid> </Grid>
<Grid item xs={5}> <Grid item xs={5}>
<Paper className={classes.paper} variant="outlined"> <Paper className={classes.paper} variant="outlined">