FarmBot/Farmbot-Web-App

View on GitHub
frontend/regimens/bulk_scheduler/bulk_scheduler.tsx

Summary

Maintainability
A
0 mins
Test Coverage
import React from "react";
import { BulkEditorProps } from "./interfaces";
import { WeekGrid } from "./week_grid";
import { setTimeOffset, setSequence } from "./actions";
import {
  BlurableInput, Row, Col, FBSelect, DropDownItem, NULL_CHOICE,
} from "../../ui";
import moment from "moment";
import { isString, isUndefined } from "lodash";
import { betterCompact, bail } from "../../util";
import { msToTime, timeToMs } from "./utils";
import { t } from "../../i18next_wrapper";
import { Content } from "../../constants";

const BAD_UUID = "WARNING: Not a sequence UUID.";

export class BulkScheduler extends React.Component<BulkEditorProps, {}> {
  selected = (): DropDownItem => {
    const s = this.props.selectedSequence;
    return (s?.body.id)
      ? { label: s.body.name, value: s.uuid }
      : NULL_CHOICE;
  };

  all = (): DropDownItem[] => {
    return betterCompact(this.props.sequences.map(x => {
      if (x.body.id) {
        return { value: x.uuid, label: x.body.name };
      }
    }));
  };

  commitChange = (uuid: string) => {
    this.props.dispatch(setSequence(uuid));
  };

  onChange = (event: DropDownItem) => {
    const uuid = event.value;
    isString(uuid) ? this.commitChange(uuid) : bail(BAD_UUID);
  };

  SequenceSelectBox = () =>
    <Col xs={6}>
      <div className={"sequence-select-box"}>
        <label>{t("Sequence")}</label>
        <FBSelect onChange={this.onChange}
          selectedItem={this.selected()}
          list={this.all()} />
      </div>
    </Col>;

  TimeSelection = () =>
    <Col xs={6}>
      <div className={"time-selection"}>
        <label>{t("Time")}</label>
        <i className="fa fa-clock-o fb-icon-button" onClick={() =>
          this.props.dispatch(setTimeOffset(timeToMs(
            moment().add(3, "minutes").format("HH:mm"))))} />
        <BlurableInput type="time"
          value={msToTime(this.props.dailyOffsetMs)}
          error={nearOsUpdateTime(
            this.props.dailyOffsetMs,
            this.props.device.body.ota_hour)
            ? t(Content.WITHIN_HOUR_OF_OS_UPDATE)
            : undefined}
          onCommit={({ currentTarget }) => {
            this.props.dispatch(setTimeOffset(timeToMs(currentTarget.value)));
          }} />
      </div>
    </Col>;

  render() {
    const { dispatch, weeks } = this.props;
    return <div className="bulk-scheduler-content">
      <Row>
        <this.SequenceSelectBox />
        <this.TimeSelection />
      </Row>
      <WeekGrid weeks={weeks} dispatch={dispatch} />
    </div>;
  }
}

export const nearOsUpdateTime =
  (dailyOffsetMs: number, otaHour: number | undefined) => {
    if (isUndefined(otaHour)) { return; }
    const otaHourString = otaHour + ":00";
    const oneHourInMs = 60 * 60 * 1000;
    const difference = dailyOffsetMs - timeToMs(otaHourString);
    const spillover = otaHour == 0 && dailyOffsetMs > 23 * 60 * 60 * 1000;
    return Math.abs(difference) < oneHourInMs || spillover;
  };