import * as classNames from "classnames"; import { observer } from "mobx-react"; import * as React from "react"; import { Button, Icon, Progress, Segment } from "semantic-ui-react"; import { Duration } from "@common/Duration"; import log from "@common/logger"; import { Section, SectionRun, SectionRunner } from "@common/sprinklersRpc"; import "@client/styles/SectionRunnerView"; interface PausedStateProps { paused: boolean; togglePaused: () => void; } function PausedState({ paused, togglePaused }: PausedStateProps) { const classes = classNames({ "sectionRunner--pausedState": true, "sectionRunner--pausedState-paused": paused, "sectionRunner--pausedState-unpaused": !paused }); return ( ); } class SectionRunView extends React.Component< { run: SectionRun; sections: Section[]; }, { now: number; } > { animationFrameHandle: number | null = null; startTime: number; constructor(p: any) { super(p); const now = performance.now(); this.state = { now }; this.startTime = Date.now() - now; } componentDidMount() { this.requestAnimationFrame(); } componentDidUpdate() { this.requestAnimationFrame(); } componentWillUnmount() { this.cancelAnimationFrame(); } cancelAnimationFrame = () => { if (this.animationFrameHandle != null) { cancelAnimationFrame(this.animationFrameHandle); this.animationFrameHandle = null; } }; requestAnimationFrame = () => { const startTime = this.props.run.startTime; if (startTime != null) { if (this.animationFrameHandle == null) { this.animationFrameHandle = requestAnimationFrame(this.updateNow); } } else { this.cancelAnimationFrame(); } }; updateNow = (now: number) => { this.animationFrameHandle = null; this.setState({ now: this.startTime + now }); this.requestAnimationFrame(); }; render() { const { run, sections } = this.props; const startTime = run.unpauseTime ? run.unpauseTime : run.startTime; const now = this.state.now; const section = sections[run.section]; const duration = Duration.fromSeconds(run.duration); const cancel = run.cancel; let running: boolean = false; // tslint:disable-line:no-unused-variable let paused: boolean = false; let progressBar: React.ReactNode | undefined; if (startTime != null) { let elapsed = run.totalDuration - run.duration; if (run.pauseTime) { paused = true; } else { running = true; elapsed += (now - startTime.valueOf()) / 1000; } const percentage = elapsed / run.totalDuration; progressBar = ( ); } const description = `'${section.name}' for ${duration.toString()}` + (paused ? " (paused)" : "") + (running ? " (running)" : ""); return (
{description}
{progressBar}
); } } @observer export default class SectionRunnerView extends React.Component< { sectionRunner: SectionRunner; sections: Section[]; }, {} > { render() { const { current, queue, paused } = this.props.sectionRunner; const { sections } = this.props; const queueView = queue.map(run => ( )); if (current) { queueView.unshift( ); } if (queueView.length === 0) { queueView.push(No items in queue); } return (

Section Runner Queue

{queueView} ); } togglePaused = () => { const { sectionRunner } = this.props; const paused = !sectionRunner.paused; sectionRunner .setPaused(paused) .then(res => log.info(res, "set section runner paused to " + paused)) .catch(err => log.info({ err }, "error setting section runner paused status") ); }; }