general code cleanup/refactoring
This commit is contained in:
parent
4a0ed13180
commit
1dab3ccd0b
8 changed files with 104 additions and 82 deletions
|
@ -35,6 +35,7 @@ export default class Dashboard extends Component {
|
||||||
const endpoint = `${DOMAIN}/api/streaming`
|
const endpoint = `${DOMAIN}/api/streaming`
|
||||||
.replace('https', 'wss')
|
.replace('https', 'wss')
|
||||||
.replace('http', 'ws')
|
.replace('http', 'ws')
|
||||||
|
|
||||||
this.client = new StreamingClient(endpoint, this.state.metrics)
|
this.client = new StreamingClient(endpoint, this.state.metrics)
|
||||||
this.client.connect()
|
this.client.connect()
|
||||||
|
|
||||||
|
@ -110,50 +111,62 @@ export default class Dashboard extends Component {
|
||||||
this.setState({ incident: await resp.json() })
|
this.setState({ incident: await resp.json() })
|
||||||
}
|
}
|
||||||
|
|
||||||
render () {
|
renderNotice (services) {
|
||||||
let metrics = null
|
const down = services.filter(([, { status }]) => !status)
|
||||||
|
|
||||||
if (this.state.metrics) {
|
// DegradedNotice should only be shown when there is no ongoing incident,
|
||||||
const allServices = Object.entries(this.state.metrics.status)
|
// and any services are reported as down.
|
||||||
const graphs = this.state.metrics.graph
|
if (!this.state.incident && down.length > 0) {
|
||||||
|
return <DegradedNotice services={objectFromEntries(down)}/>
|
||||||
const services = allServices.map(([name, info]) => (
|
|
||||||
<Service name={name} key={name} graph={graphs[name]} {...info}/>
|
|
||||||
))
|
|
||||||
|
|
||||||
const down = allServices.filter(([, { status }]) => !status)
|
|
||||||
let notice = <Status incident={this.state.incident}/>
|
|
||||||
if (!this.state.incident && down.length > 0) {
|
|
||||||
notice = down.length > 0
|
|
||||||
? <DegradedNotice services={objectFromEntries(down)}/>
|
|
||||||
: null
|
|
||||||
}
|
|
||||||
|
|
||||||
metrics = (
|
|
||||||
<div className="services">
|
|
||||||
{notice}
|
|
||||||
{services}
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return <Status incident={this.state.incident}/>
|
||||||
|
}
|
||||||
|
|
||||||
|
renderServices (services) {
|
||||||
|
const { graph: graphs } = this.state.metrics
|
||||||
|
return services.map(([name, info]) => (
|
||||||
|
<Service name={name} key={name} graph={graphs[name]} {...info}/>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
renderPlaceholders () {
|
||||||
|
return (
|
||||||
|
<React.Fragment>
|
||||||
|
<ServicePlaceholder/>
|
||||||
|
<ServicePlaceholder/>
|
||||||
|
<ServicePlaceholder/>
|
||||||
|
</React.Fragment>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
renderDashboardContent () {
|
||||||
|
if (this.state.error) {
|
||||||
|
return <div className="error">{this.state.error}</div>
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.state.loading) {
|
||||||
|
return this.renderPlaceholders()
|
||||||
|
}
|
||||||
|
|
||||||
|
const allServices = Object.entries(this.state.metrics.status)
|
||||||
|
|
||||||
|
const services = this.renderServices(allServices)
|
||||||
|
const notice = this.renderNotice(allServices)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<React.Fragment>
|
||||||
|
{notice}
|
||||||
|
{services}
|
||||||
|
</React.Fragment>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
render () {
|
||||||
return (
|
return (
|
||||||
<div className="dashboard">
|
<div className="dashboard">
|
||||||
<h1>elstatus</h1>
|
<h1>elstatus</h1>
|
||||||
|
{this.renderDashboardContent()}
|
||||||
{this.state.error ? (
|
|
||||||
<div className="error">
|
|
||||||
{this.state.error}
|
|
||||||
</div>
|
|
||||||
) : null}
|
|
||||||
|
|
||||||
{this.state.loading && !this.state.error ? (
|
|
||||||
<React.Fragment>
|
|
||||||
<ServicePlaceholder/>
|
|
||||||
<ServicePlaceholder/>
|
|
||||||
<ServicePlaceholder/>
|
|
||||||
</React.Fragment>
|
|
||||||
) : metrics}
|
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@ import PropTypes from 'prop-types'
|
||||||
|
|
||||||
import './DegradedNotice.css'
|
import './DegradedNotice.css'
|
||||||
|
|
||||||
const DegradedNotice = ({ services }) => {
|
export default function DegradedNotice ({ services }) {
|
||||||
const keys = Object.keys(services)
|
const keys = Object.keys(services)
|
||||||
const serviceNames = keys.join(', ')
|
const serviceNames = keys.join(', ')
|
||||||
|
|
||||||
|
@ -23,5 +23,3 @@ const DegradedNotice = ({ services }) => {
|
||||||
DegradedNotice.propTypes = {
|
DegradedNotice.propTypes = {
|
||||||
services: PropTypes.object.isRequired,
|
services: PropTypes.object.isRequired,
|
||||||
}
|
}
|
||||||
|
|
||||||
export default DegradedNotice
|
|
||||||
|
|
|
@ -12,7 +12,7 @@ const OUTAGE_TYPES = {
|
||||||
degraded_service: 'Degraded Service',
|
degraded_service: 'Degraded Service',
|
||||||
}
|
}
|
||||||
|
|
||||||
const Incident = ({ incident }) => {
|
export default function Incident ({ incident }) {
|
||||||
const { content, end_date: end, start_date: start, title, type, stages } = incident
|
const { content, end_date: end, start_date: start, title, type, stages } = incident
|
||||||
const ago = ms(Date.now() - start * 1000)
|
const ago = ms(Date.now() - start * 1000)
|
||||||
const agoEnd = end ? ms(Date.now - end * 1000) : null
|
const agoEnd = end ? ms(Date.now - end * 1000) : null
|
||||||
|
@ -51,5 +51,3 @@ Incident.propTypes = {
|
||||||
stages: PropTypes.array,
|
stages: PropTypes.array,
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Incident
|
|
||||||
|
|
|
@ -38,7 +38,7 @@ function getServiceState (status, latency) {
|
||||||
return status ? 'alive' : 'dead'
|
return status ? 'alive' : 'dead'
|
||||||
}
|
}
|
||||||
|
|
||||||
const Service = ({ graph, name, status, latency, description }) => {
|
export default function Service ({ graph, name, status, latency, description }) {
|
||||||
const state = getServiceState(status, latency)
|
const state = getServiceState(status, latency)
|
||||||
|
|
||||||
const title = titles[state]
|
const title = titles[state]
|
||||||
|
@ -81,5 +81,3 @@ Service.propTypes = {
|
||||||
latency: PropTypes.number,
|
latency: PropTypes.number,
|
||||||
description: PropTypes.string.isRequired,
|
description: PropTypes.string.isRequired,
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Service
|
|
||||||
|
|
|
@ -7,3 +7,23 @@
|
||||||
grid-template-columns: 3rem 1fr;
|
grid-template-columns: 3rem 1fr;
|
||||||
grid-gap: 1rem;
|
grid-gap: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.service-placeholder .emoji {
|
||||||
|
width: 3rem !important;
|
||||||
|
height: 3rem !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.service-placeholder .name {
|
||||||
|
width: 100% !important;
|
||||||
|
height: 3rem !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.service-placeholder .text {
|
||||||
|
margin-top: 1rem !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.service-placeholder .graph {
|
||||||
|
width: 100% !important;
|
||||||
|
height: 175px !important;
|
||||||
|
margin-top: 1rem !important;
|
||||||
|
}
|
||||||
|
|
|
@ -5,45 +5,44 @@ import 'react-placeholder/lib/reactPlaceholder.css'
|
||||||
|
|
||||||
import './ServicePlaceholder.css'
|
import './ServicePlaceholder.css'
|
||||||
|
|
||||||
const ServicePlaceholder = () => (
|
export default function ServicePlaceholder () {
|
||||||
<div className="service-placeholder">
|
return (
|
||||||
<div className="title">
|
<div className="service-placeholder">
|
||||||
|
<div className="title">
|
||||||
|
<ReactPlaceholder
|
||||||
|
type="round"
|
||||||
|
ready={false}
|
||||||
|
showLoadingAnimation
|
||||||
|
className="emoji"
|
||||||
|
>
|
||||||
|
{' '}
|
||||||
|
</ReactPlaceholder>
|
||||||
|
<ReactPlaceholder
|
||||||
|
type="rect"
|
||||||
|
ready={false}
|
||||||
|
showLoadingAnimation
|
||||||
|
className="name"
|
||||||
|
>
|
||||||
|
{' '}
|
||||||
|
</ReactPlaceholder>
|
||||||
|
</div>
|
||||||
<ReactPlaceholder
|
<ReactPlaceholder
|
||||||
type="round"
|
type="text"
|
||||||
ready={false}
|
ready={false}
|
||||||
style={{ width: '3rem', height: '3rem' }}
|
rows={1}
|
||||||
className="emoji"
|
|
||||||
showLoadingAnimation
|
showLoadingAnimation
|
||||||
|
className="text"
|
||||||
>
|
>
|
||||||
{' '}
|
{' '}
|
||||||
</ReactPlaceholder>
|
</ReactPlaceholder>
|
||||||
<ReactPlaceholder
|
<ReactPlaceholder
|
||||||
type="rect"
|
type="rect"
|
||||||
ready={false}
|
ready={false}
|
||||||
style={{ width: '100%', height: '3rem' }}
|
|
||||||
showLoadingAnimation
|
showLoadingAnimation
|
||||||
|
className="graph"
|
||||||
>
|
>
|
||||||
{' '}
|
{' '}
|
||||||
</ReactPlaceholder>
|
</ReactPlaceholder>
|
||||||
</div>
|
</div>
|
||||||
<ReactPlaceholder
|
)
|
||||||
type="text"
|
}
|
||||||
ready={false}
|
|
||||||
rows={1}
|
|
||||||
style={{ marginTop: '1rem' }}
|
|
||||||
showLoadingAnimation
|
|
||||||
>
|
|
||||||
{' '}
|
|
||||||
</ReactPlaceholder>
|
|
||||||
<ReactPlaceholder
|
|
||||||
type="rect"
|
|
||||||
ready={false}
|
|
||||||
style={{ width: '100%', height: '175px', marginTop: '1rem' }}
|
|
||||||
showLoadingAnimation
|
|
||||||
>
|
|
||||||
{' '}
|
|
||||||
</ReactPlaceholder>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
|
|
||||||
export default ServicePlaceholder
|
|
||||||
|
|
|
@ -3,7 +3,7 @@ import PropTypes from 'prop-types'
|
||||||
|
|
||||||
import ms from 'ms'
|
import ms from 'ms'
|
||||||
|
|
||||||
const Stage = ({ stage }) => {
|
export default function Stage ({ stage }) {
|
||||||
const { created_at: createdAt, title, content } = stage
|
const { created_at: createdAt, title, content } = stage
|
||||||
const ago = ms(Date.now() - createdAt * 1000)
|
const ago = ms(Date.now() - createdAt * 1000)
|
||||||
|
|
||||||
|
@ -21,7 +21,5 @@ Stage.propTypes = {
|
||||||
created_at: PropTypes.number,
|
created_at: PropTypes.number,
|
||||||
title: PropTypes.string,
|
title: PropTypes.string,
|
||||||
content: PropTypes.string,
|
content: PropTypes.string,
|
||||||
})
|
}),
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Stage
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ import classnames from 'classnames'
|
||||||
import './Status.css'
|
import './Status.css'
|
||||||
import Incident from './Incident'
|
import Incident from './Incident'
|
||||||
|
|
||||||
const Status = ({ incident }) => {
|
export default function Status ({ incident }) {
|
||||||
let view = null
|
let view = null
|
||||||
if (incident) {
|
if (incident) {
|
||||||
view = <Incident incident={incident}/>
|
view = <Incident incident={incident}/>
|
||||||
|
@ -27,5 +27,3 @@ const Status = ({ incident }) => {
|
||||||
Status.propTypes = {
|
Status.propTypes = {
|
||||||
incident: PropTypes.object,
|
incident: PropTypes.object,
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Status
|
|
||||||
|
|
Loading…
Reference in a new issue