// Copyright 2018 Red Hat, Inc // // Licensed under the Apache License, Version 2.0 (the "License"); you may // not use this file except in compliance with the License. You may obtain // a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the // License for the specific language governing permissions and limitations // under the License. import * as moment from 'moment-timezone' import * as React from 'react' import PropTypes from 'prop-types' import { connect } from 'react-redux' import { Checkbox, Icon, Form, FormGroup, FormControl, } from 'patternfly-react' import { PageSection, PageSectionVariants } from '@patternfly/react-core' import { fetchStatusIfNeeded } from '../actions/status' import Pipeline from '../containers/status/Pipeline' import { Fetchable } from '../containers/Fetching' import { removeHash } from '../Misc' class StatusPage extends React.Component { static propTypes = { location: PropTypes.object, tenant: PropTypes.object, preferences: PropTypes.object, timezone: PropTypes.string, remoteData: PropTypes.object, dispatch: PropTypes.func } state = { filter: null, expanded: false, } visibilityListener = () => { if (document[this.visibilityStateProperty] === 'visible') { this.visible = true this.updateData() } else { this.visible = false } } constructor () { super() this.timer = null this.visible = true // Stop refresh when page is not visible if (typeof document.hidden !== 'undefined') { this.visibilityChangeEvent = 'visibilitychange' this.visibilityStateProperty = 'visibilityState' } else if (typeof document.mozHidden !== 'undefined') { this.visibilityChangeEvent = 'mozvisibilitychange' this.visibilityStateProperty = 'mozVisibilityState' } else if (typeof document.msHidden !== 'undefined') { this.visibilityChangeEvent = 'msvisibilitychange' this.visibilityStateProperty = 'msVisibilityState' } else if (typeof document.webkitHidden !== 'undefined') { this.visibilityChangeEvent = 'webkitvisibilitychange' this.visibilityStateProperty = 'webkitVisibilityState' } document.addEventListener( this.visibilityChangeEvent, this.visibilityListener, false) } updateData = (force) => { if (force || (this.visible && this.props.preferences.autoReload)) { this.props.dispatch(fetchStatusIfNeeded(this.props.tenant)) .then(() => {if (this.props.preferences.autoReload && this.visible) { this.timer = setTimeout(this.updateData, 5000) }}) } // Clear any running timer if (this.timer) { clearTimeout(this.timer) this.timer = null } } componentDidMount () { document.title = 'Zuul Status' this.loadState() if (this.props.tenant.name) { this.updateData(true) } window.addEventListener('storage', this.loadState) } componentDidUpdate (prevProps) { if (this.props.tenant.name !== prevProps.tenant.name) { this.updateData(true) } // If the user just enabled auto-reload if (this.props.preferences.autoReload && !prevProps.preferences.autoReload && !this.timer) { this.updateData(true) } } componentWillUnmount () { if (this.timer) { clearTimeout(this.timer) this.timer = null } this.visible = false document.removeEventListener( this.visibilityChangeEvent, this.visibilityListener) } setFilter = (filter) => { // Update form ref value this.filter.value = filter // Store value in location if (filter) { window.location.hash = '#' + filter } else { removeHash() } this.setState({filter: filter}) } handleKeyPress = (e) => { if (e.charCode === 13) { this.setFilter(e.target.value) e.preventDefault() e.target.blur() } } handleCheckBox = (e) => { this.setState({expanded: e.target.checked}) localStorage.setItem('zuul_expand_by_default', e.target.checked) } loadState = () => { const filter = this.props.location.hash ? this.props.location.hash.slice(1) : null let expanded = localStorage.getItem('zuul_expand_by_default') || false if (typeof expanded === 'string') { expanded = (expanded === 'true') } if (filter || expanded) { this.setState({ filter: filter, expanded: expanded }) } } renderStatusHeader (status) { return (

Queue lengths: {status.trigger_event_queue ? status.trigger_event_queue.length : '0' } events,  {status.management_event_queue ? status.management_event_queue.length : '0' } management events.

) } renderStatusFooter (status) { return (

Zuul version: {status.zuul_version}

{status.last_reconfigured ? (

Last reconfigured: {moment.utc(status.last_reconfigured).tz(this.props.timezone).format('llll')}

) : ''}
) } render () { const { remoteData } = this.props const { filter, expanded } = this.state const status = remoteData.status const statusControl = (
this.filter = i} onKeyPress={this.handleKeyPress} /> {filter && ( {this.setFilter('')}} style={{cursor: 'pointer', zIndex: 10, pointerEvents: 'auto'}} >   )}   Expand by default: 
) return (
{status && this.renderStatusHeader(status)} {statusControl}
{status && status.pipelines.map(item => ( ))}
{status && this.renderStatusFooter(status)}
) } } export default connect(state => ({ preferences: state.preferences, tenant: state.tenant, timezone: state.timezone, remoteData: state.status, }))(StatusPage)