general code cleanup/refactoring

This commit is contained in:
slice 2018-07-18 17:48:16 -07:00
parent 4a0ed13180
commit 1dab3ccd0b
No known key found for this signature in database
GPG Key ID: 1508C19D7436A26D
8 changed files with 104 additions and 82 deletions

View File

@ -35,6 +35,7 @@ export default class Dashboard extends Component {
const endpoint = `${DOMAIN}/api/streaming`
.replace('https', 'wss')
.replace('http', 'ws')
this.client = new StreamingClient(endpoint, this.state.metrics)
this.client.connect()
@ -110,50 +111,62 @@ export default class Dashboard extends Component {
this.setState({ incident: await resp.json() })
}
render () {
let metrics = null
renderNotice (services) {
const down = services.filter(([, { status }]) => !status)
if (this.state.metrics) {
const allServices = Object.entries(this.state.metrics.status)
const graphs = this.state.metrics.graph
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>
)
// DegradedNotice should only be shown when there is no ongoing incident,
// and any services are reported as down.
if (!this.state.incident && down.length > 0) {
return <DegradedNotice services={objectFromEntries(down)}/>
}
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 (
<div className="dashboard">
<h1>elstatus</h1>
{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}
{this.renderDashboardContent()}
</div>
)
}

View File

@ -3,7 +3,7 @@ import PropTypes from 'prop-types'
import './DegradedNotice.css'
const DegradedNotice = ({ services }) => {
export default function DegradedNotice ({ services }) {
const keys = Object.keys(services)
const serviceNames = keys.join(', ')
@ -23,5 +23,3 @@ const DegradedNotice = ({ services }) => {
DegradedNotice.propTypes = {
services: PropTypes.object.isRequired,
}
export default DegradedNotice

View File

@ -12,7 +12,7 @@ const OUTAGE_TYPES = {
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 ago = ms(Date.now() - start * 1000)
const agoEnd = end ? ms(Date.now - end * 1000) : null
@ -51,5 +51,3 @@ Incident.propTypes = {
stages: PropTypes.array,
}),
}
export default Incident

View File

@ -38,7 +38,7 @@ function getServiceState (status, latency) {
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 title = titles[state]
@ -81,5 +81,3 @@ Service.propTypes = {
latency: PropTypes.number,
description: PropTypes.string.isRequired,
}
export default Service

View File

@ -7,3 +7,23 @@
grid-template-columns: 3rem 1fr;
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;
}

View File

@ -5,45 +5,44 @@ import 'react-placeholder/lib/reactPlaceholder.css'
import './ServicePlaceholder.css'
const ServicePlaceholder = () => (
<div className="service-placeholder">
<div className="title">
export default function ServicePlaceholder () {
return (
<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
type="round"
type="text"
ready={false}
style={{ width: '3rem', height: '3rem' }}
className="emoji"
rows={1}
showLoadingAnimation
className="text"
>
{' '}
</ReactPlaceholder>
<ReactPlaceholder
type="rect"
ready={false}
style={{ width: '100%', height: '3rem' }}
showLoadingAnimation
className="graph"
>
{' '}
</ReactPlaceholder>
</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
)
}

View File

@ -3,7 +3,7 @@ import PropTypes from 'prop-types'
import ms from 'ms'
const Stage = ({ stage }) => {
export default function Stage ({ stage }) {
const { created_at: createdAt, title, content } = stage
const ago = ms(Date.now() - createdAt * 1000)
@ -21,7 +21,5 @@ Stage.propTypes = {
created_at: PropTypes.number,
title: PropTypes.string,
content: PropTypes.string,
})
}),
}
export default Stage

View File

@ -5,7 +5,7 @@ import classnames from 'classnames'
import './Status.css'
import Incident from './Incident'
const Status = ({ incident }) => {
export default function Status ({ incident }) {
let view = null
if (incident) {
view = <Incident incident={incident}/>
@ -27,5 +27,3 @@ const Status = ({ incident }) => {
Status.propTypes = {
incident: PropTypes.object,
}
export default Status