check server availability
parent
ad254682f0
commit
677de87434
|
@ -0,0 +1,341 @@
|
|||
{
|
||||
"breakpoints":{
|
||||
"keys":[
|
||||
"xs",
|
||||
"sm",
|
||||
"md",
|
||||
"lg",
|
||||
"xl"
|
||||
],
|
||||
"values":{
|
||||
"xs":0,
|
||||
"sm":600,
|
||||
"md":960,
|
||||
"lg":1280,
|
||||
"xl":1920
|
||||
}
|
||||
},
|
||||
"direction":"ltr",
|
||||
"mixins":{
|
||||
"toolbar":{
|
||||
"minHeight":56,
|
||||
"@media (min-width:0px) and (orientation: landscape)":{
|
||||
"minHeight":48
|
||||
},
|
||||
"@media (min-width:600px)":{
|
||||
"minHeight":64
|
||||
}
|
||||
}
|
||||
},
|
||||
"overrides":{
|
||||
"MuiBackdrop":{
|
||||
"root":{
|
||||
"backgroundColor":"#4A4A4A1A"
|
||||
}
|
||||
},
|
||||
"MuiMenu":{
|
||||
"paper":{
|
||||
"boxShadow":"0px 3px 11px 0px #E8EAFC, 0 3px 3px -2px #B2B2B21A, 0 1px 8px 0 #9A9A9A1A"
|
||||
}
|
||||
},
|
||||
"MuiSelect":{
|
||||
"icon":{
|
||||
"color":"#B9B9B9"
|
||||
}
|
||||
},
|
||||
"MuiListItem":{
|
||||
"root":{
|
||||
"&$selected":{
|
||||
"backgroundColor":"#F3F5FF !important",
|
||||
"&:focus":{
|
||||
"backgroundColor":"#F3F5FF"
|
||||
}
|
||||
}
|
||||
},
|
||||
"button":{
|
||||
"&:hover, &:focus":{
|
||||
"backgroundColor":"#F3F5FF"
|
||||
}
|
||||
}
|
||||
},
|
||||
"MuiTouchRipple":{
|
||||
"child":{
|
||||
"backgroundColor":"white"
|
||||
}
|
||||
},
|
||||
"MuiTableRow":{
|
||||
"root":{
|
||||
"height":56
|
||||
}
|
||||
},
|
||||
"MuiTableCell":{
|
||||
"root":{
|
||||
"borderBottom":"1px solid rgba(224, 224, 224, .5)",
|
||||
"paddingLeft":24
|
||||
},
|
||||
"head":{
|
||||
"fontSize":"0.95rem"
|
||||
},
|
||||
"body":{
|
||||
"fontSize":"0.95rem"
|
||||
}
|
||||
},
|
||||
"PrivateSwitchBase":{
|
||||
"root":{
|
||||
"marginLeft":10
|
||||
}
|
||||
}
|
||||
},
|
||||
"palette":{
|
||||
"common":{
|
||||
"black":"#000",
|
||||
"white":"#fff"
|
||||
},
|
||||
"type":"light",
|
||||
"primary":{
|
||||
"main":"#536DFE",
|
||||
"light":"#798dfe",
|
||||
"dark":"#072cfe",
|
||||
"contrastText":"#fff"
|
||||
},
|
||||
"secondary":{
|
||||
"main":"#FF5C93",
|
||||
"light":"#ff82ac",
|
||||
"dark":"#ff0f60",
|
||||
"contrastText":"#FFFFFF"
|
||||
},
|
||||
"error":{
|
||||
"light":"#e57373",
|
||||
"main":"#f44336",
|
||||
"dark":"#d32f2f",
|
||||
"contrastText":"#fff"
|
||||
},
|
||||
"warning":{
|
||||
"main":"#FFC260",
|
||||
"light":"#ffd186",
|
||||
"dark":"#ffa513",
|
||||
"contrastText":"rgba(0, 0, 0, 0.87)"
|
||||
},
|
||||
"info":{
|
||||
"main":"#9013FE",
|
||||
"light":"#a239fe",
|
||||
"dark":"#6801c4",
|
||||
"contrastText":"#fff"
|
||||
},
|
||||
"success":{
|
||||
"main":"#3CD4A0",
|
||||
"light":"#5bdbaf",
|
||||
"dark":"#23a075",
|
||||
"contrastText":"rgba(0, 0, 0, 0.87)"
|
||||
},
|
||||
"grey":{
|
||||
"50":"#fafafa",
|
||||
"100":"#f5f5f5",
|
||||
"200":"#eeeeee",
|
||||
"300":"#e0e0e0",
|
||||
"400":"#bdbdbd",
|
||||
"500":"#9e9e9e",
|
||||
"600":"#757575",
|
||||
"700":"#616161",
|
||||
"800":"#424242",
|
||||
"900":"#212121",
|
||||
"A100":"#d5d5d5",
|
||||
"A200":"#aaaaaa",
|
||||
"A400":"#303030",
|
||||
"A700":"#616161"
|
||||
},
|
||||
"contrastThreshold":3,
|
||||
"tonalOffset":0.2,
|
||||
"text":{
|
||||
"primary":"#4A4A4A",
|
||||
"secondary":"#6E6E6E",
|
||||
"disabled":"rgba(0, 0, 0, 0.38)",
|
||||
"hint":"#B9B9B9"
|
||||
},
|
||||
"divider":"rgba(0, 0, 0, 0.12)",
|
||||
"background":{
|
||||
"paper":"#fff",
|
||||
"default":"#F6F7FF",
|
||||
"light":"#F3F5FF"
|
||||
},
|
||||
"action":{
|
||||
"active":"rgba(0, 0, 0, 0.54)",
|
||||
"hover":"rgba(0, 0, 0, 0.04)",
|
||||
"hoverOpacity":0.04,
|
||||
"selected":"rgba(0, 0, 0, 0.08)",
|
||||
"selectedOpacity":0.08,
|
||||
"disabled":"rgba(0, 0, 0, 0.26)",
|
||||
"disabledBackground":"rgba(0, 0, 0, 0.12)",
|
||||
"disabledOpacity":0.38,
|
||||
"focus":"rgba(0, 0, 0, 0.12)",
|
||||
"focusOpacity":0.12,
|
||||
"activatedOpacity":0.12
|
||||
}
|
||||
},
|
||||
"props":{
|
||||
|
||||
},
|
||||
"shadows":[
|
||||
"none",
|
||||
"0px 2px 1px -1px rgba(0,0,0,0.2),0px 1px 1px 0px rgba(0,0,0,0.14),0px 1px 3px 0px rgba(0,0,0,0.12)",
|
||||
"0px 3px 1px -2px rgba(0,0,0,0.2),0px 2px 2px 0px rgba(0,0,0,0.14),0px 1px 5px 0px rgba(0,0,0,0.12)",
|
||||
"0px 3px 3px -2px rgba(0,0,0,0.2),0px 3px 4px 0px rgba(0,0,0,0.14),0px 1px 8px 0px rgba(0,0,0,0.12)",
|
||||
"0px 2px 4px -1px rgba(0,0,0,0.2),0px 4px 5px 0px rgba(0,0,0,0.14),0px 1px 10px 0px rgba(0,0,0,0.12)",
|
||||
"0px 3px 5px -1px rgba(0,0,0,0.2),0px 5px 8px 0px rgba(0,0,0,0.14),0px 1px 14px 0px rgba(0,0,0,0.12)",
|
||||
"0px 3px 5px -1px rgba(0,0,0,0.2),0px 6px 10px 0px rgba(0,0,0,0.14),0px 1px 18px 0px rgba(0,0,0,0.12)",
|
||||
"0px 4px 5px -2px rgba(0,0,0,0.2),0px 7px 10px 1px rgba(0,0,0,0.14),0px 2px 16px 1px rgba(0,0,0,0.12)",
|
||||
"0px 5px 5px -3px rgba(0,0,0,0.2),0px 8px 10px 1px rgba(0,0,0,0.14),0px 3px 14px 2px rgba(0,0,0,0.12)",
|
||||
"0px 5px 6px -3px rgba(0,0,0,0.2),0px 9px 12px 1px rgba(0,0,0,0.14),0px 3px 16px 2px rgba(0,0,0,0.12)",
|
||||
"0px 6px 6px -3px rgba(0,0,0,0.2),0px 10px 14px 1px rgba(0,0,0,0.14),0px 4px 18px 3px rgba(0,0,0,0.12)",
|
||||
"0px 6px 7px -4px rgba(0,0,0,0.2),0px 11px 15px 1px rgba(0,0,0,0.14),0px 4px 20px 3px rgba(0,0,0,0.12)",
|
||||
"0px 7px 8px -4px rgba(0,0,0,0.2),0px 12px 17px 2px rgba(0,0,0,0.14),0px 5px 22px 4px rgba(0,0,0,0.12)",
|
||||
"0px 7px 8px -4px rgba(0,0,0,0.2),0px 13px 19px 2px rgba(0,0,0,0.14),0px 5px 24px 4px rgba(0,0,0,0.12)",
|
||||
"0px 7px 9px -4px rgba(0,0,0,0.2),0px 14px 21px 2px rgba(0,0,0,0.14),0px 5px 26px 4px rgba(0,0,0,0.12)",
|
||||
"0px 8px 9px -5px rgba(0,0,0,0.2),0px 15px 22px 2px rgba(0,0,0,0.14),0px 6px 28px 5px rgba(0,0,0,0.12)",
|
||||
"0px 8px 10px -5px rgba(0,0,0,0.2),0px 16px 24px 2px rgba(0,0,0,0.14),0px 6px 30px 5px rgba(0,0,0,0.12)",
|
||||
"0px 8px 11px -5px rgba(0,0,0,0.2),0px 17px 26px 2px rgba(0,0,0,0.14),0px 6px 32px 5px rgba(0,0,0,0.12)",
|
||||
"0px 9px 11px -5px rgba(0,0,0,0.2),0px 18px 28px 2px rgba(0,0,0,0.14),0px 7px 34px 6px rgba(0,0,0,0.12)",
|
||||
"0px 9px 12px -6px rgba(0,0,0,0.2),0px 19px 29px 2px rgba(0,0,0,0.14),0px 7px 36px 6px rgba(0,0,0,0.12)",
|
||||
"0px 10px 13px -6px rgba(0,0,0,0.2),0px 20px 31px 3px rgba(0,0,0,0.14),0px 8px 38px 7px rgba(0,0,0,0.12)",
|
||||
"0px 10px 13px -6px rgba(0,0,0,0.2),0px 21px 33px 3px rgba(0,0,0,0.14),0px 8px 40px 7px rgba(0,0,0,0.12)",
|
||||
"0px 10px 14px -6px rgba(0,0,0,0.2),0px 22px 35px 3px rgba(0,0,0,0.14),0px 8px 42px 7px rgba(0,0,0,0.12)",
|
||||
"0px 11px 14px -7px rgba(0,0,0,0.2),0px 23px 36px 3px rgba(0,0,0,0.14),0px 9px 44px 8px rgba(0,0,0,0.12)",
|
||||
"0px 11px 15px -7px rgba(0,0,0,0.2),0px 24px 38px 3px rgba(0,0,0,0.14),0px 9px 46px 8px rgba(0,0,0,0.12)"
|
||||
],
|
||||
"typography":{
|
||||
"htmlFontSize":16,
|
||||
"fontFamily":"\\""Roboto\\"", \\""Helvetica\\"", \\""Arial\\"", sans-serif",
|
||||
"fontSize":14,
|
||||
"fontWeightLight":300,
|
||||
"fontWeightRegular":400,
|
||||
"fontWeightMedium":500,
|
||||
"fontWeightBold":700,
|
||||
"h1":{
|
||||
"fontFamily":"\\""Roboto\\"", \\""Helvetica\\"", \\""Arial\\"", sans-serif",
|
||||
"fontWeight":300,
|
||||
"fontSize":"3rem",
|
||||
"lineHeight":1.167,
|
||||
"letterSpacing":"-0.01562em"
|
||||
},
|
||||
"h2":{
|
||||
"fontFamily":"\\""Roboto\\"", \\""Helvetica\\"", \\""Arial\\"", sans-serif",
|
||||
"fontWeight":300,
|
||||
"fontSize":"2rem",
|
||||
"lineHeight":1.2,
|
||||
"letterSpacing":"-0.00833em"
|
||||
},
|
||||
"h3":{
|
||||
"fontFamily":"\\""Roboto\\"", \\""Helvetica\\"", \\""Arial\\"", sans-serif",
|
||||
"fontWeight":400,
|
||||
"fontSize":"1.64rem",
|
||||
"lineHeight":1.167,
|
||||
"letterSpacing":"0em"
|
||||
},
|
||||
"h4":{
|
||||
"fontFamily":"\\""Roboto\\"", \\""Helvetica\\"", \\""Arial\\"", sans-serif",
|
||||
"fontWeight":400,
|
||||
"fontSize":"1.5rem",
|
||||
"lineHeight":1.235,
|
||||
"letterSpacing":"0.00735em"
|
||||
},
|
||||
"h5":{
|
||||
"fontFamily":"\\""Roboto\\"", \\""Helvetica\\"", \\""Arial\\"", sans-serif",
|
||||
"fontWeight":400,
|
||||
"fontSize":"1.285rem",
|
||||
"lineHeight":1.334,
|
||||
"letterSpacing":"0em"
|
||||
},
|
||||
"h6":{
|
||||
"fontFamily":"\\""Roboto\\"", \\""Helvetica\\"", \\""Arial\\"", sans-serif",
|
||||
"fontWeight":500,
|
||||
"fontSize":"1.142rem",
|
||||
"lineHeight":1.6,
|
||||
"letterSpacing":"0.0075em"
|
||||
},
|
||||
"subtitle1":{
|
||||
"fontFamily":"\\""Roboto\\"", \\""Helvetica\\"", \\""Arial\\"", sans-serif",
|
||||
"fontWeight":400,
|
||||
"fontSize":"1rem",
|
||||
"lineHeight":1.75,
|
||||
"letterSpacing":"0.00938em"
|
||||
},
|
||||
"subtitle2":{
|
||||
"fontFamily":"\\""Roboto\\"", \\""Helvetica\\"", \\""Arial\\"", sans-serif",
|
||||
"fontWeight":500,
|
||||
"fontSize":"0.875rem",
|
||||
"lineHeight":1.57,
|
||||
"letterSpacing":"0.00714em"
|
||||
},
|
||||
"body1":{
|
||||
"fontFamily":"\\""Roboto\\"", \\""Helvetica\\"", \\""Arial\\"", sans-serif",
|
||||
"fontWeight":400,
|
||||
"fontSize":"1rem",
|
||||
"lineHeight":1.5,
|
||||
"letterSpacing":"0.00938em"
|
||||
},
|
||||
"body2":{
|
||||
"fontFamily":"\\""Roboto\\"", \\""Helvetica\\"", \\""Arial\\"", sans-serif",
|
||||
"fontWeight":400,
|
||||
"fontSize":"0.875rem",
|
||||
"lineHeight":1.43,
|
||||
"letterSpacing":"0.01071em"
|
||||
},
|
||||
"button":{
|
||||
"fontFamily":"\\""Roboto\\"", \\""Helvetica\\"", \\""Arial\\"", sans-serif",
|
||||
"fontWeight":500,
|
||||
"fontSize":"0.875rem",
|
||||
"lineHeight":1.75,
|
||||
"letterSpacing":"0.02857em",
|
||||
"textTransform":"uppercase"
|
||||
},
|
||||
"caption":{
|
||||
"fontFamily":"\\""Roboto\\"", \\""Helvetica\\"", \\""Arial\\"", sans-serif",
|
||||
"fontWeight":400,
|
||||
"fontSize":"0.75rem",
|
||||
"lineHeight":1.66,
|
||||
"letterSpacing":"0.03333em"
|
||||
},
|
||||
"overline":{
|
||||
"fontFamily":"\\""Roboto\\"", \\""Helvetica\\"", \\""Arial\\"", sans-serif",
|
||||
"fontWeight":400,
|
||||
"fontSize":"0.75rem",
|
||||
"lineHeight":2.66,
|
||||
"letterSpacing":"0.08333em",
|
||||
"textTransform":"uppercase"
|
||||
}
|
||||
},
|
||||
"shape":{
|
||||
"borderRadius":4
|
||||
},
|
||||
"transitions":{
|
||||
"easing":{
|
||||
"easeInOut":"cubic-bezier(0.4, 0, 0.2, 1)",
|
||||
"easeOut":"cubic-bezier(0.0, 0, 0.2, 1)",
|
||||
"easeIn":"cubic-bezier(0.4, 0, 1, 1)",
|
||||
"sharp":"cubic-bezier(0.4, 0, 0.6, 1)"
|
||||
},
|
||||
"duration":{
|
||||
"shortest":150,
|
||||
"shorter":200,
|
||||
"short":250,
|
||||
"standard":300,
|
||||
"complex":375,
|
||||
"enteringScreen":225,
|
||||
"leavingScreen":195
|
||||
}
|
||||
},
|
||||
"zIndex":{
|
||||
"mobileStepper":1000,
|
||||
"speedDial":1050,
|
||||
"appBar":1100,
|
||||
"drawer":1200,
|
||||
"modal":1300,
|
||||
"snackbar":1400,
|
||||
"tooltip":1500
|
||||
},
|
||||
"customShadows":{
|
||||
"widget":"0px 3px 11px 0px #E8EAFC, 0 3px 3px -2px #B2B2B21A, 0 1px 8px 0 #9A9A9A1A",
|
||||
"widgetDark":"0px 3px 18px 0px #4558A3B3, 0 3px 3px -2px #B2B2B21A, 0 1px 8px 0 #9A9A9A1A",
|
||||
"widgetWide":"0px 12px 33px 0px #E8EAFC, 0 3px 3px -2px #B2B2B21A, 0 1px 8px 0 #9A9A9A1A"
|
||||
}
|
||||
}
|
|
@ -7,6 +7,7 @@ import Layout from "./Layout/Layout";
|
|||
// pages
|
||||
import Error from "../pages/error";
|
||||
import Login from "../pages/login";
|
||||
import ServerNotAvailable from "../features/server/availability/components/ServerNotAvailable";
|
||||
|
||||
// context
|
||||
import { useUserState } from "../contexts/UserContext";
|
||||
|
@ -26,7 +27,10 @@ export default function App() {
|
|||
return (
|
||||
<BrowserRouter basename={process.env.PUBLIC_URL || ""}>
|
||||
<Switch>
|
||||
<Route exact path="/" render={() => <Redirect to="/dashboard" />} />
|
||||
<PrivateRoute
|
||||
path="/server-not-available"
|
||||
component={ServerNotAvailable}
|
||||
/>
|
||||
<PublicRoute path="/login" component={Login} />
|
||||
<PrivateRoute path="/" component={Layout} />
|
||||
<Route component={Error} />
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import React from "react";
|
||||
import { withRouter } from "react-router-dom";
|
||||
import ServerAvailabilityProvider from "../../features/server/providers/ServerAvailabilityProvider";
|
||||
|
||||
// components
|
||||
import Header from "../Header/Header";
|
||||
|
@ -13,13 +14,13 @@ function Layout(props) {
|
|||
var classes = useStyles();
|
||||
|
||||
return (
|
||||
<div className={classes.root}>
|
||||
<>
|
||||
<ServerAvailabilityProvider>
|
||||
<div className={classes.root}>
|
||||
<Header history={props.history} />
|
||||
<Sidebar />
|
||||
<Content />
|
||||
</>
|
||||
</div>
|
||||
</div>
|
||||
</ServerAvailabilityProvider>
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
import useServerApi from "./useServerApi";
|
||||
|
||||
export { useServerApi };
|
|
@ -0,0 +1,26 @@
|
|||
import { useCallback } from "react";
|
||||
import useHttpRequest from "../../../hooks/useHttpRequest";
|
||||
import { get } from "../../../utils/axios";
|
||||
|
||||
const cdn = process.env.REACT_APP_CDN_URL;
|
||||
const endpoints = {
|
||||
ping: `${cdn}/health/ping`
|
||||
};
|
||||
|
||||
const useServerApi = () => {
|
||||
const { exec } = useHttpRequest();
|
||||
|
||||
const checkHealth = useCallback(
|
||||
(options) => {
|
||||
const promise = exec(() => get(endpoints.ping), options);
|
||||
return promise;
|
||||
},
|
||||
[exec]
|
||||
);
|
||||
|
||||
return {
|
||||
checkHealth
|
||||
};
|
||||
};
|
||||
|
||||
export default useServerApi;
|
|
@ -0,0 +1,50 @@
|
|||
import React from "react";
|
||||
import { Grid, Paper, Typography, Button } from "@material-ui/core";
|
||||
import { Link } from "react-router-dom";
|
||||
import useStyles from "../styles";
|
||||
import classnames from "classnames";
|
||||
import ServerIsDown from "../../../../images/ServerIsDown.gif";
|
||||
|
||||
const ServerNotAvailable = () => {
|
||||
const classes = useStyles();
|
||||
|
||||
return (
|
||||
<Grid container className={classes.container}>
|
||||
<Paper classes={{ root: classes.paperRoot }}>
|
||||
<div className={classes.imageFrame}>
|
||||
<img
|
||||
className={classes.image}
|
||||
src={ServerIsDown}
|
||||
alt="server is down"
|
||||
/>
|
||||
</div>
|
||||
<Typography
|
||||
variant="h5"
|
||||
className={classnames(classes.textRow, classes.safetyText)}
|
||||
>
|
||||
{"Oops. Looks like the server is currently unavailable."}
|
||||
</Typography>
|
||||
<Typography
|
||||
variant="h6"
|
||||
color="text"
|
||||
colorBrightness="secondary"
|
||||
className={classnames(classes.textRow, classes.safetyText)}
|
||||
>
|
||||
{"Try again in a few seconds"}
|
||||
</Typography>
|
||||
<Button
|
||||
variant="contained"
|
||||
// color="primary"
|
||||
component={Link}
|
||||
to="/"
|
||||
size="large"
|
||||
className={classes.button}
|
||||
>
|
||||
Retry
|
||||
</Button>
|
||||
</Paper>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
|
||||
export default ServerNotAvailable;
|
|
@ -0,0 +1,49 @@
|
|||
import { makeStyles } from "@material-ui/styles";
|
||||
|
||||
export default makeStyles((theme) => ({
|
||||
container: {
|
||||
height: "100vh",
|
||||
width: "100vw",
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
backgroundColor: theme.palette.error.dark,
|
||||
position: "absolute",
|
||||
top: 0,
|
||||
left: 0
|
||||
},
|
||||
imageFrame: {
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
marginBottom: theme.spacing(2)
|
||||
},
|
||||
image: {
|
||||
width: 200,
|
||||
marginRight: theme.spacing(2)
|
||||
},
|
||||
paperRoot: {
|
||||
backgroundColor: theme.palette.common.black,
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
alignItems: "center",
|
||||
paddingTop: theme.spacing(2),
|
||||
paddingBottom: theme.spacing(2),
|
||||
paddingLeft: theme.spacing(2),
|
||||
paddingRight: theme.spacing(2),
|
||||
maxWidth: 404
|
||||
},
|
||||
textRow: {
|
||||
marginBottom: theme.spacing(4),
|
||||
textAlign: "center"
|
||||
},
|
||||
safetyText: {
|
||||
fontWeight: 300,
|
||||
color: theme.palette.text.hint
|
||||
},
|
||||
button: {
|
||||
backgroundColor: theme.palette.error.dark,
|
||||
textTransform: "none",
|
||||
fontSize: 22
|
||||
}
|
||||
}));
|
|
@ -0,0 +1,26 @@
|
|||
import React, { useState, useEffect } from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import { Redirect } from "react-router-dom";
|
||||
import { useServerApi } from "../api";
|
||||
|
||||
const ServerAvailabilityProvider = ({ children }) => {
|
||||
const [ok, setOk] = useState(null);
|
||||
const { checkHealth } = useServerApi();
|
||||
|
||||
useEffect(() => {
|
||||
checkHealth({
|
||||
onCompleted: () => setOk(true),
|
||||
onError: () => setOk(false)
|
||||
});
|
||||
}, [checkHealth]);
|
||||
|
||||
if (ok === null) return <span>Checking server health...</span>;
|
||||
if (ok === false) return <Redirect to="/server-not-available" />;
|
||||
return <>{children}</>;
|
||||
};
|
||||
|
||||
ServerAvailabilityProvider.propTypes = {
|
||||
children: PropTypes.node
|
||||
};
|
||||
|
||||
export default ServerAvailabilityProvider;
|
Binary file not shown.
After Width: | Height: | Size: 120 KiB |
Loading…
Reference in New Issue