Alex Mikhalev
7 years ago
12 changed files with 258 additions and 89 deletions
@ -0,0 +1,19 @@
@@ -0,0 +1,19 @@
|
||||
import * as React from "react"; |
||||
|
||||
import { Duration } from "@common/Duration"; |
||||
import { ProgramItem, Section} from "@common/sprinklersRpc"; |
||||
|
||||
export default function ProgramSequenceView({ sequence, sections }: { |
||||
sequence: ProgramItem[], sections: Section[], |
||||
}) { |
||||
const sequenceItems = sequence.map((item, index) => { |
||||
const section = sections[item.section]; |
||||
const duration = Duration.fromSeconds(item.duration); |
||||
return ( |
||||
<li key={index}> |
||||
<em>"{section.name}"</em> for {duration.toString()} |
||||
</li> |
||||
); |
||||
}); |
||||
return <ul>{sequenceItems}</ul>; |
||||
} |
@ -0,0 +1,38 @@
@@ -0,0 +1,38 @@
|
||||
import { observer } from "mobx-react"; |
||||
import * as moment from "moment"; |
||||
import * as React from "react"; |
||||
|
||||
import { DateOfYear, Schedule, TimeOfDay, Weekday } from "@common/sprinklersRpc"; |
||||
|
||||
function timeToString(time: TimeOfDay) { |
||||
return moment(time).format("LTS"); |
||||
} |
||||
|
||||
function formatDateOfYear(day: DateOfYear | null, prefix: React.ReactNode) { |
||||
if (day == null) { |
||||
return null; |
||||
} |
||||
const format = (day.year === 0) ? "M/D" : "l"; |
||||
return <React.Fragment>{prefix}{moment(day).format(format)}</React.Fragment>; |
||||
} |
||||
|
||||
@observer |
||||
export default class ScheduleView extends React.Component<{ schedule: Schedule }> { |
||||
render() { |
||||
const { schedule } = this.props; |
||||
const times = schedule.times.map((time, i) => timeToString(time)) |
||||
.join(", "); |
||||
const weekdays = schedule.weekdays.map((weekday) => |
||||
Weekday[weekday]).join(", "); |
||||
const from = formatDateOfYear(schedule.from, <b>From </b>); |
||||
const to = formatDateOfYear(schedule.to, <b>To </b>); |
||||
return ( |
||||
<div> |
||||
<b>At</b> {times} <br/> |
||||
<b>On</b> {weekdays} <br/> |
||||
{from} <br/> |
||||
{to} |
||||
</div> |
||||
); |
||||
} |
||||
} |
@ -0,0 +1,69 @@
@@ -0,0 +1,69 @@
|
||||
import { observer } from "mobx-react"; |
||||
import * as React from "react"; |
||||
import { Button, Menu, Segment} from "semantic-ui-react"; |
||||
|
||||
import { ProgramSequenceView, ScheduleView } from "@app/components"; |
||||
import { AppState, injectState } from "@app/state"; |
||||
import { Program, SprinklersDevice } from "@common/sprinklersRpc"; |
||||
import { RouteComponentProps } from "react-router"; |
||||
import { Link } from "react-router-dom"; |
||||
|
||||
@observer |
||||
class ProgramDetailView extends React.Component { |
||||
|
||||
} |
||||
|
||||
@observer |
||||
class ProgramPage extends React.Component<{ |
||||
appState: AppState, |
||||
} & RouteComponentProps<{ deviceId: string, programId: number }>> { |
||||
device!: SprinklersDevice; |
||||
|
||||
render() { |
||||
const { deviceId, programId } = this.props.match.params; |
||||
const device = this.device = this.props.appState.sprinklersRpc.getDevice(deviceId); |
||||
// TODO: check programId
|
||||
if (device.programs.length <= programId || !device.programs[programId]) { |
||||
return null; |
||||
} |
||||
const program = device.programs[programId]; |
||||
|
||||
const programRows = this.renderRows(program, programId); |
||||
return ( |
||||
<div> |
||||
<Menu attached="top"> |
||||
<Menu.Item header>Program {program.name} ({program.id})</Menu.Item> |
||||
<Menu.Menu position="right"> |
||||
<Menu.Item> |
||||
<Button as={Link} to={"/devices/" + deviceId}> |
||||
Back |
||||
</Button> |
||||
</Menu.Item> |
||||
</Menu.Menu> |
||||
</Menu> |
||||
<Segment attached="bottom"> |
||||
{programRows} |
||||
</Segment> |
||||
</div> |
||||
); |
||||
} |
||||
|
||||
private renderRows = (program: Program, i: number): JSX.Element | null => { |
||||
const { name, running, enabled, schedule, sequence } = program; |
||||
const cancelOrRun = () => running ? program.cancel() : program.run(); |
||||
return ( |
||||
<React.Fragment key={i}> |
||||
<b>Enabled: </b>{enabled ? "Enabled" : "Not enabled"}<br/> |
||||
<b>Running: </b>{running ? "Running" : "Not running"}<br/> |
||||
<Button size="small" onClick={cancelOrRun}> |
||||
{running ? "Cancel" : "Run"} |
||||
</Button> |
||||
<h4>Sequence: </h4> <ProgramSequenceView sequence={sequence} sections={this.device.sections}/> |
||||
<h4>Schedule: </h4> <ScheduleView schedule={schedule}/> |
||||
</React.Fragment> |
||||
); |
||||
} |
||||
} |
||||
|
||||
const DecoratedProgramPage = injectState(observer(ProgramPage)); |
||||
export default DecoratedProgramPage; |
@ -0,0 +1,23 @@
@@ -0,0 +1,23 @@
|
||||
export interface RouteParams { |
||||
deviceId: string; |
||||
programId: string; |
||||
} |
||||
|
||||
export const routerRouteParams: RouteParams = { |
||||
deviceId: ":deviceId", |
||||
programId: ":programId", |
||||
}; |
||||
|
||||
export const home = "/"; |
||||
export const messagesTest = "/messagesTest"; |
||||
|
||||
export const login = "/login"; |
||||
export const logout = "/logout"; |
||||
|
||||
export function device(deviceId?: string | number): string { |
||||
return `/devices/${deviceId || ""}`; |
||||
} |
||||
|
||||
export function program(deviceId: string | number, programId?: string | number): string { |
||||
return `${device(deviceId)}/programs/${programId}`; |
||||
} |
Loading…
Reference in new issue