Skip to content

Commit 11c74d3

Browse files
authored
Merge pull request #23 from opendexnetwork/refactor/components
refactor: loaders, code, menu item, snackbar, labeled row
2 parents eec5694 + df9411b commit 11c74d3

File tree

16 files changed

+192
-118
lines changed

16 files changed

+192
-118
lines changed
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import { Divider, Grid, IconButton, makeStyles } from "@material-ui/core";
2+
import FileCopyOutlinedIcon from "@material-ui/icons/FileCopyOutlined";
3+
import React, { ReactElement } from "react";
4+
import { copyToClipboard } from "../../utils/appUtil";
5+
6+
type LabeledRowProps = {
7+
label: string;
8+
value: string | number;
9+
paddingSpacing?: number;
10+
showCopyIcon?: boolean;
11+
reserveSpaceForCopyIcon?: boolean;
12+
};
13+
14+
const useStyles = makeStyles((theme) => ({
15+
cell: (props: LabeledRowProps) => ({
16+
padding: theme.spacing(props.paddingSpacing ?? 2),
17+
textAlign: "center",
18+
wordWrap: "break-word",
19+
whiteSpace: "pre-wrap",
20+
}),
21+
}));
22+
23+
const LabeledRow = (props: LabeledRowProps): ReactElement => {
24+
const { label, value, showCopyIcon, reserveSpaceForCopyIcon } = props;
25+
const classes = useStyles(props);
26+
27+
return (
28+
<Grid container item justify="space-between" alignItems="center">
29+
<Grid item xs={reserveSpaceForCopyIcon ? 3 : 4} className={classes.cell}>
30+
{label}
31+
</Grid>
32+
<Divider orientation="vertical" flexItem />
33+
<Grid item xs={reserveSpaceForCopyIcon ? 6 : 7} className={classes.cell}>
34+
{value}
35+
</Grid>
36+
{reserveSpaceForCopyIcon && (
37+
<Grid item xs={2} className={classes.cell}>
38+
{showCopyIcon && (
39+
/* IconButton */
40+
<IconButton onClick={() => copyToClipboard(value)}>
41+
<FileCopyOutlinedIcon fontSize="small" />
42+
</IconButton>
43+
)}
44+
</Grid>
45+
)}
46+
</Grid>
47+
);
48+
};
49+
50+
export default LabeledRow;
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import {
2+
IconButton,
3+
makeStyles,
4+
Snackbar as MaterialSnackbar,
5+
SnackbarContent,
6+
} from "@material-ui/core";
7+
import CloseIcon from "@material-ui/icons/Close";
8+
import React, { ReactElement, useEffect, useState } from "react";
9+
import { Subject } from "rxjs";
10+
11+
type SnackbarProps = {
12+
message: string;
13+
openSubject: Subject<boolean>;
14+
type: "error" | "success" | "warning" | "info";
15+
};
16+
17+
const useStyles = makeStyles((theme) => ({
18+
snackbar: {
19+
bottom: theme.spacing(3) * 2,
20+
right: theme.spacing(3) * 2,
21+
},
22+
snackbarContent: (props: SnackbarProps) => ({
23+
backgroundColor: theme.palette[props.type].main,
24+
color: theme.palette[props.type].contrastText,
25+
}),
26+
}));
27+
28+
const Snackbar = (props: SnackbarProps): ReactElement => {
29+
const { message, openSubject } = props;
30+
const [open, setOpen] = useState(false);
31+
const classes = useStyles(props);
32+
33+
useEffect(() => {
34+
const sub = openSubject.subscribe(setOpen);
35+
return () => sub.unsubscribe();
36+
}, [openSubject]);
37+
38+
return (
39+
<MaterialSnackbar
40+
className={classes.snackbar}
41+
open={open}
42+
autoHideDuration={10000}
43+
onClose={() => setOpen(false)}
44+
anchorOrigin={{ vertical: "bottom", horizontal: "right" }}
45+
>
46+
<SnackbarContent
47+
className={classes.snackbarContent}
48+
message={message}
49+
action={
50+
<IconButton onClick={() => setOpen(false)}>
51+
<CloseIcon />
52+
</IconButton>
53+
}
54+
/>
55+
</MaterialSnackbar>
56+
);
57+
};
58+
59+
export default Snackbar;

src/common/components/data-display/loader/PageLoader.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ const useStyles = makeStyles(() =>
1717
},
1818
})
1919
);
20-
const PageCircularProgress = (): ReactElement => {
20+
const PageLoader = (): ReactElement => {
2121
const classes = useStyles();
2222
return (
2323
<Box className={classes.container}>
@@ -26,4 +26,4 @@ const PageCircularProgress = (): ReactElement => {
2626
);
2727
};
2828

29-
export default PageCircularProgress;
29+
export default PageLoader;
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import { makeStyles } from "@material-ui/core";
2+
import React, { ReactElement } from "react";
3+
4+
type CodeProps = {
5+
text: string;
6+
backgroundColor?: "default" | "paper";
7+
};
8+
9+
const useStyles = makeStyles((theme) => ({
10+
code: (props: CodeProps) => ({
11+
backgroundColor:
12+
props.backgroundColor === "default"
13+
? theme.palette.background.default
14+
: theme.palette.background.paper,
15+
padding: `0px ${theme.spacing(1)}px`,
16+
borderRadius: 5,
17+
letterSpacing: 2,
18+
fontFamily: "monospace",
19+
}),
20+
}));
21+
22+
const Code = (props: CodeProps): ReactElement => {
23+
const { text } = props;
24+
const classes = useStyles(props);
25+
26+
return <span className={classes.code}>{text}</span>;
27+
};
28+
29+
export default Code;

src/dashboard/menu/MenuItem.tsx renamed to src/common/components/navigation/MenuItem.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import ListItem from "@material-ui/core/ListItem";
99
import ListItemText from "@material-ui/core/ListItemText";
1010
import React, { ComponentClass, ElementType, ReactElement } from "react";
1111
import { NavLink, useLocation, useRouteMatch } from "react-router-dom";
12-
import { Path } from "../../router/Path";
12+
import { Path } from "../../../router/Path";
1313

1414
export type MenuItemProps = {
1515
path: Path;

src/dashboard/Dashboard.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,9 @@ import { SetupStatusResponse } from "../models/SetupStatusResponse";
2626
import { Status } from "../models/Status";
2727
import { Path } from "../router/Path";
2828
import Console from "./console/Console";
29-
import MenuItem, { MenuItemProps } from "./menu/MenuItem";
29+
import MenuItem, {
30+
MenuItemProps,
31+
} from "../common/components/navigation/MenuItem";
3032
import Overview from "./overview/Overview";
3133
// import SetupWarning from "./SetupWarning";
3234
import Trade from "./trade/Trade";

src/dashboard/console/Console.tsx

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ import {
1313
withStyles,
1414
WithStyles,
1515
} from "@material-ui/core";
16+
import Code from "../../common/components/data-display/text/Code";
17+
import ErrorMessage from "../../common/components/data-display/ErrorMessage";
1618

1719
type PropsType = RouteComponentProps<{ param1: string }> &
1820
WithStyles<typeof styles> & {
@@ -35,13 +37,6 @@ const styles = (theme: Theme) => {
3537
title: {
3638
marginBottom: theme.spacing(2),
3739
},
38-
code: {
39-
backgroundColor: theme.palette.background.paper,
40-
padding: `0px ${theme.spacing(1)}px`,
41-
borderRadius: 5,
42-
letterSpacing: 2,
43-
fontFamily: "monospace",
44-
},
4540
terminalContainer: {
4641
height: "90%",
4742
width: "100%",
@@ -213,11 +208,13 @@ class Console extends Component<PropsType, StateType> {
213208
return (
214209
<div className={classes.wrapper}>
215210
<Typography component="p" variant="body2" className={classes.title}>
216-
Type {<span className={classes.code}>help</span>} to show a list of
217-
available commands
211+
Type {<Code text="help" />} to show a list of available commands
218212
</Typography>
219213
{this.state.error && (
220-
<div>Error: {JSON.stringify(this.state.error)}</div>
214+
<ErrorMessage
215+
mainMessage="Error"
216+
details={JSON.stringify(this.state.error)}
217+
/>
221218
)}
222219
<div className={classes.terminalContainer} ref={this.ref} />
223220
</div>

src/dashboard/overview/Overview.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import Grid from "@material-ui/core/Grid";
33
import React, { ReactElement } from "react";
44
import { RouteComponentProps, withRouter } from "react-router-dom";
55
import api from "../../api";
6-
import PageCircularProgress from "../../common/components/data-display/loader/PageLoader";
6+
import PageLoader from "../../common/components/data-display/loader/PageLoader";
77
import { Status } from "../../models/Status";
88
import DashboardContent, { DashboardContentState } from "../DashboardContent";
99
import OverviewItem from "./OverviewItem";
@@ -74,7 +74,7 @@ class Overview extends DashboardContent<PropsType, StateType> {
7474
></OverviewItem>
7575
))
7676
) : (
77-
<PageCircularProgress />
77+
<PageLoader />
7878
)}
7979
</Grid>
8080
);

src/dashboard/overview/OverviewItem.tsx

Lines changed: 18 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,19 @@ import {
55
Icon,
66
IconButton,
77
makeStyles,
8-
Snackbar,
9-
SnackbarContent,
108
Theme,
119
Tooltip,
1210
} from "@material-ui/core";
1311
import Card from "@material-ui/core/Card";
1412
import CardContent from "@material-ui/core/CardContent";
1513
import Grid from "@material-ui/core/Grid";
1614
import Typography from "@material-ui/core/Typography";
17-
import CloseIcon from "@material-ui/icons/Close";
1815
import GetAppOutlinedIcon from "@material-ui/icons/GetAppOutlined";
1916
import React, { ReactElement, useState } from "react";
17+
import { Subject } from "rxjs";
2018
import api from "../../api";
19+
import Snackbar from "../../common/components/data-display/feedback/Snackbar";
20+
import LabeledRow from "../../common/components/data-display/LabeledRow";
2121
import { formatDateTimeForFilename } from "../../common/utils/dateUtil";
2222
import { isServiceReady } from "../../common/utils/serviceUtil";
2323
import { SERVICES_WITH_ADDITIONAL_INFO } from "../../constants";
@@ -41,10 +41,6 @@ const useStyles = makeStyles((theme: Theme) =>
4141
paddingBottom: 0,
4242
},
4343
},
44-
cardCell: {
45-
padding: theme.spacing(4),
46-
textAlign: "center",
47-
},
4844
statusDot: {
4945
height: 10,
5046
width: 10,
@@ -58,14 +54,6 @@ const useStyles = makeStyles((theme: Theme) =>
5854
inactive: {
5955
backgroundColor: theme.palette.error.light,
6056
},
61-
snackbar: {
62-
bottom: theme.spacing(3) * 2,
63-
right: theme.spacing(3) * 2,
64-
},
65-
snackbarMessage: {
66-
backgroundColor: theme.palette.error.main,
67-
color: theme.palette.error.contrastText,
68-
},
6957
})
7058
);
7159

@@ -88,7 +76,7 @@ const downloadLogs = (serviceName: string, handleError: () => void): void => {
8876
const OverviewItem = (props: OverviewItemProps): ReactElement => {
8977
const { status, opendexdLocked, opendexdNotReady } = props;
9078
const [detailsOpen, setDetailsOpen] = useState(false);
91-
const [errorMsgOpen, setErrorMsgOpen] = useState(false);
79+
const errorMsgOpenSubject = new Subject<boolean>();
9280
const classes = useStyles();
9381

9482
const statusDotClass = `${classes.statusDot} ${
@@ -122,6 +110,7 @@ const OverviewItem = (props: OverviewItemProps): ReactElement => {
122110
>
123111
<Grid container item>
124112
{isDetailsIconVisible(status) && (
113+
/* IconButton */
125114
<Tooltip title="details">
126115
<IconButton size="small" onClick={() => setDetailsOpen(true)}>
127116
<Icon fontSize="small">open_in_full</Icon>
@@ -143,12 +132,15 @@ const OverviewItem = (props: OverviewItemProps): ReactElement => {
143132
</Grid>
144133
<Grid container item justify="flex-end">
145134
{isDownloadLogsEnabled(status) && (
135+
/* TextButton */
146136
<Tooltip title="Download logs">
147137
<Button
148138
size="small"
149139
startIcon={<GetAppOutlinedIcon fontSize="small" />}
150140
onClick={() =>
151-
downloadLogs(status.service, () => setErrorMsgOpen(true))
141+
downloadLogs(status.service, () =>
142+
errorMsgOpenSubject?.next(true)
143+
)
152144
}
153145
>
154146
Logs
@@ -159,15 +151,11 @@ const OverviewItem = (props: OverviewItemProps): ReactElement => {
159151
</Grid>
160152
<Divider />
161153
<CardContent className={classes.cardContent}>
162-
<Grid container item>
163-
<Grid item xs={4} className={classes.cardCell}>
164-
Status
165-
</Grid>
166-
<Divider orientation="vertical" flexItem />
167-
<Grid item xs={7} className={classes.cardCell}>
168-
{props.status.status}
169-
</Grid>
170-
</Grid>
154+
<LabeledRow
155+
label="Status"
156+
value={props.status.status}
157+
paddingSpacing={4}
158+
/>
171159
</CardContent>
172160
</Card>
173161

@@ -179,22 +167,10 @@ const OverviewItem = (props: OverviewItemProps): ReactElement => {
179167
)}
180168

181169
<Snackbar
182-
className={classes.snackbar}
183-
open={errorMsgOpen}
184-
autoHideDuration={10000}
185-
onClose={() => setErrorMsgOpen(false)}
186-
anchorOrigin={{ vertical: "bottom", horizontal: "right" }}
187-
>
188-
<SnackbarContent
189-
className={classes.snackbarMessage}
190-
message={`Could not download the logs for ${status.service}`}
191-
action={
192-
<IconButton onClick={() => setErrorMsgOpen(false)}>
193-
<CloseIcon />
194-
</IconButton>
195-
}
196-
/>
197-
</Snackbar>
170+
message={`Could not download the logs for ${status.service}`}
171+
openSubject={errorMsgOpenSubject}
172+
type="error"
173+
></Snackbar>
198174
</Grid>
199175
);
200176
};

src/dashboard/overview/ServiceDetails.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ const ServiceDetails = (props: ServiceDetailsProps): ReactElement => {
3939
const classes = useStyles();
4040

4141
return (
42+
/* Dialog */
4243
<Dialog
4344
open
4445
onClose={handleClose}
@@ -54,6 +55,7 @@ const ServiceDetails = (props: ServiceDetailsProps): ReactElement => {
5455
wrap="nowrap"
5556
>
5657
<Grid item container xs lg>
58+
{/* IconButton */}
5759
<IconButton onClick={handleClose}>
5860
<CloseIcon />
5961
</IconButton>

0 commit comments

Comments
 (0)