You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

202 lines
6.7 KiB

import { observer } from "mobx-react";
import { createViewModel, IViewModel } from "mobx-utils";
import * as React from "react";
import { RouteComponentProps } from "react-router";
import { Button, CheckboxProps, Form, Input, InputOnChangeData, Menu, Modal, Segment } from "semantic-ui-react";
import { ProgramSequenceView, ScheduleView } from "@app/components";
import * as rp from "@app/routePaths";
import { AppState, injectState } from "@app/state";
import log from "@common/logger";
import { Program, SprinklersDevice } from "@common/sprinklersRpc";
@observer
class ProgramPage extends React.Component<{
appState: AppState,
} & RouteComponentProps<{ deviceId: string, programId: number }>, {
programView: Program & IViewModel<Program> | undefined,
}> {
private device!: SprinklersDevice;
private program!: Program;
constructor(p: any) {
super(p);
this.state = {
programView: undefined,
};
}
get isEditing(): boolean {
return this.state.programView != null;
}
renderName(program: Program) {
const { name } = program;
if (this.isEditing) {
return (
<Menu.Item header>
<Form>
<Form.Group inline>
<Form.Field inline>
<label><h4>Program</h4></label>
<Input
placeholder="Program Name"
type="text"
value={name}
onChange={this.onNameChange}
/>
</Form.Field>
({program.id})
</Form.Group>
</Form>
</Menu.Item>
);
} else {
return <Menu.Item header as="h4">Program {name} ({program.id})</Menu.Item>;
}
}
renderActions(program: Program) {
const { running } = program;
const editing = this.isEditing;
let editButtons;
if (editing) {
editButtons = (
<React.Fragment>
<Button primary onClick={this.save}>
Save
</Button>
<Button negative onClick={this.cancelEditing}>
Cancel
</Button>
</React.Fragment>
);
} else {
editButtons = (
<Button primary onClick={this.startEditing}>
Edit
</Button>
);
}
return (
<Modal.Actions>
<Button positive={!running} negative={running} onClick={this.cancelOrRun}>
{running ? "Cancel" : "Run"}
</Button>
{editButtons}
<Button onClick={this.close}>
Close
</Button>
</Modal.Actions>
);
}
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;
}
this.program = device.programs[programId];
const { programView } = this.state;
const program = programView || this.program;
const editing = programView != null;
const { running, enabled, schedule, sequence } = program;
return (
<Modal open onClose={this.close} className="programEditor">
<Modal.Header>{this.renderName(program)}</Modal.Header>
<Modal.Content>
<Form>
<Form.Group>
<Form.Checkbox
toggle
label="Enabled"
checked={enabled}
readOnly={!editing}
onChange={this.onEnabledChange}
/>
<Form.Checkbox toggle label="Running" checked={running} readOnly={!editing}/>
</Form.Group>
<Form.Field>
<label><h4>Sequence</h4></label>
<ProgramSequenceView sequence={sequence} sections={this.device.sections} editing={editing}/>
</Form.Field>
<Form.Field>
<label><h4>Schedule</h4></label>
<ScheduleView schedule={schedule}/>
</Form.Field>
</Form>
</Modal.Content>
{this.renderActions(program)}
</Modal>
);
}
private cancelOrRun = () => {
if (!this.program) {
return;
}
this.program.running ? this.program.cancel() : this.program.run();
}
private startEditing = () => {
let { programView } = this.state;
if (programView) { // stop editing, so save
programView.submit();
programView = undefined;
} else { // start editing
programView = createViewModel(this.program);
}
this.setState({ programView });
}
private save = () => {
let { programView } = this.state;
if (programView) { // stop editing, so save
programView.submit();
programView = undefined;
}
this.setState({ programView });
this.program.update()
.then((data) => {
log.info({ data }, "Program updated");
}, (err) => {
log.error({ err }, "error updating Program");
});
}
private cancelEditing = () => {
let { programView } = this.state;
if (programView) {
programView = undefined; // stop editing
}
this.setState({ programView });
}
private close = () => {
const { deviceId } = this.props.match.params;
this.props.history.push({ pathname: rp.device(deviceId) });
}
private onNameChange = (e: any, p: InputOnChangeData) => {
const { programView } = this.state;
if (programView) {
programView.name = p.value;
}
}
private onEnabledChange = (e: any, p: CheckboxProps) => {
const { programView } = this.state;
if (programView) {
programView.enabled = p.checked!;
}
}
}
const DecoratedProgramPage = injectState(observer(ProgramPage));
export default DecoratedProgramPage;