Show next run time for programs
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
parent
89562b11b0
commit
f6d6ef7c0c
@ -105,16 +105,17 @@ class ProgramSequenceItem extends React.Component<{
|
||||
|
||||
const ProgramSequenceItemD = SortableElement(ProgramSequenceItem);
|
||||
|
||||
// tslint:disable: no-shadowed-variable
|
||||
const ProgramSequenceList = SortableContainer(
|
||||
observer(
|
||||
(props: {
|
||||
function ProgramSequenceList(props: {
|
||||
className: string;
|
||||
list: ProgramItem[];
|
||||
sections: Section[];
|
||||
editing: boolean;
|
||||
onChange: ItemChangeHandler;
|
||||
onRemove: ItemRemoveHandler;
|
||||
}) => {
|
||||
}) {
|
||||
const { className, list, sections, ...rest } = props;
|
||||
const listItems = list.map((item, index) => {
|
||||
const key = `item-${index}`;
|
||||
@ -132,7 +133,6 @@ const ProgramSequenceList = SortableContainer(
|
||||
return <ul className={className}>{listItems}</ul>;
|
||||
}
|
||||
),
|
||||
{ withRef: true }
|
||||
);
|
||||
|
||||
@observer
|
||||
|
@ -8,6 +8,7 @@ import { ProgramSequenceView, ScheduleView } from "@client/components";
|
||||
import * as route from "@client/routePaths";
|
||||
import { ISprinklersDevice } from "@common/httpApi";
|
||||
import { Program, SprinklersDevice } from "@common/sprinklersRpc";
|
||||
import moment = require("moment");
|
||||
|
||||
@observer
|
||||
class ProgramRows extends React.Component<{
|
||||
@ -69,6 +70,12 @@ class ProgramRows extends React.Component<{
|
||||
<h4>Sequence: </h4>{" "}
|
||||
<ProgramSequenceView sequence={sequence} sections={sections} />
|
||||
<ScheduleView schedule={schedule} label={<h4>Schedule: </h4>} />
|
||||
<h4 className="program--nextRun">Next run: </h4>
|
||||
{
|
||||
program.nextRun
|
||||
? <time title={moment(program.nextRun).toString()}>{moment(program.nextRun).fromNow()}</time>
|
||||
: <time title="never">never</time>
|
||||
}
|
||||
</Form>
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
|
@ -20,8 +20,9 @@ import { AppState, injectState } from "@client/state";
|
||||
import { ISprinklersDevice } from "@common/httpApi";
|
||||
import log from "@common/logger";
|
||||
import { Program, SprinklersDevice } from "@common/sprinklersRpc";
|
||||
import { action } from "mobx";
|
||||
import classNames = require("classnames");
|
||||
import { action } from "mobx";
|
||||
import * as moment from "moment";
|
||||
|
||||
interface ProgramPageProps
|
||||
extends RouteComponentProps<{ deviceId: string; programId: string }> {
|
||||
@ -186,7 +187,6 @@ class ProgramPage extends React.Component<ProgramPageProps> {
|
||||
toggle
|
||||
label="Enabled"
|
||||
checked={enabled}
|
||||
readOnly={!editing}
|
||||
onChange={this.onEnabledChange}
|
||||
/>
|
||||
<Form.Checkbox
|
||||
@ -211,6 +211,16 @@ class ProgramPage extends React.Component<ProgramPageProps> {
|
||||
editing={editing}
|
||||
label={<h4>Schedule</h4>}
|
||||
/>
|
||||
{ !editing && (
|
||||
<h4 className="program--nextRun">Next run: </h4>)
|
||||
}
|
||||
{
|
||||
!editing && (
|
||||
program.nextRun
|
||||
? <time title={moment(program.nextRun).toString()}>{moment(program.nextRun).fromNow()}</time>
|
||||
: <time title="never">never</time>
|
||||
)
|
||||
}
|
||||
</Form>
|
||||
</Modal.Content>
|
||||
{this.renderActions(program)}
|
||||
@ -243,6 +253,10 @@ class ProgramPage extends React.Component<ProgramPageProps> {
|
||||
},
|
||||
err => {
|
||||
log.error({ err }, "error updating Program");
|
||||
this.props.appState.uiStore.addMessage({
|
||||
error: true,
|
||||
content: `Error updating program: ${err}`,
|
||||
});
|
||||
}
|
||||
);
|
||||
this.stopEditing();
|
||||
@ -268,11 +282,28 @@ class ProgramPage extends React.Component<ProgramPageProps> {
|
||||
|
||||
@action.bound
|
||||
private onEnabledChange(e: any, p: CheckboxProps) {
|
||||
if (this.programView) {
|
||||
this.programView.enabled = p.checked!;
|
||||
if (p.checked !== undefined && this.program) {
|
||||
this.program.enabled = p.checked;
|
||||
this.program.update().then(
|
||||
data => {
|
||||
log.info({ data }, "Program updated");
|
||||
this.props.appState.uiStore.addMessage({
|
||||
success: true,
|
||||
content: `Program ${this.program!.name} ${this.program!.enabled ? "enabled" : "disabled"}`,
|
||||
timeout: 2000,
|
||||
});
|
||||
},
|
||||
err => {
|
||||
log.error({ err }, "error updating Program");
|
||||
this.props.appState.uiStore.addMessage({
|
||||
error: true,
|
||||
content: `Error updating program: ${err}`,
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const DecoratedProgramPage = injectState(withRouter(observer(ProgramPage)));
|
||||
const DecoratedProgramPage = injectState(withRouter(ProgramPage));
|
||||
export default DecoratedProgramPage;
|
||||
|
@ -78,6 +78,11 @@ $connected-color: #13d213;
|
||||
color: green;
|
||||
}
|
||||
|
||||
.program--nextRun {
|
||||
display: inline-block;
|
||||
padding-right: 0.5em;
|
||||
}
|
||||
|
||||
.ui.modal.programEditor {
|
||||
&.editing > .content {
|
||||
min-height: 80vh;
|
||||
|
@ -32,6 +32,8 @@ export class Program {
|
||||
sequence: ProgramItem[] = [];
|
||||
@observable
|
||||
running: boolean = false;
|
||||
@observable
|
||||
nextRun: Date | null = null;
|
||||
|
||||
constructor(device: SprinklersDevice, id: number, data?: Partial<Program>) {
|
||||
this.device = device;
|
||||
@ -60,7 +62,8 @@ export class Program {
|
||||
enabled: this.enabled,
|
||||
running: this.running,
|
||||
schedule: this.schedule.clone(),
|
||||
sequence: this.sequence.slice()
|
||||
sequence: this.sequence.slice(),
|
||||
nextRun: this.nextRun,
|
||||
});
|
||||
}
|
||||
|
||||
@ -68,7 +71,7 @@ export class Program {
|
||||
return (
|
||||
`Program{name="${this.name}", enabled=${this.enabled}, schedule=${
|
||||
this.schedule
|
||||
}, ` + `sequence=${this.sequence}, running=${this.running}}`
|
||||
}, ` + `sequence=${this.sequence}, running=${this.running}, nextRun=${this.nextRun}}`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -7,6 +7,8 @@ export class MqttProgram extends s.Program {
|
||||
onMessage(payload: string, topic: string | undefined) {
|
||||
if (topic === "running") {
|
||||
this.running = payload === "true";
|
||||
} else if (topic === "nextRun") {
|
||||
this.nextRun = (payload.length > 0) ? new Date(Number(payload) * 1000.0) : null;
|
||||
} else if (topic == null) {
|
||||
this.updateFromJSON(JSON.parse(payload));
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { createSimpleSchema, ModelSchema, object, primitive } from "serializr";
|
||||
import { createSimpleSchema, ModelSchema, object, primitive, date } from "serializr";
|
||||
import * as s from "..";
|
||||
import list from "./list";
|
||||
|
||||
@ -85,7 +85,8 @@ export const program: ModelSchema<s.Program> = {
|
||||
enabled: primitive(),
|
||||
schedule: object(schedule),
|
||||
sequence: list(object(programItem)),
|
||||
running: primitive()
|
||||
running: primitive(),
|
||||
nextRun: date(),
|
||||
}
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user