FarmBot/Farmbot-Web-App

View on GitHub
frontend/sequences/step_tiles/tile_send_message.tsx

Summary

Maintainability
A
1 hr
Test Coverage
import React from "react";
import { FBSelect, DropDownItem, Row, Col } from "../../ui";
import { StepInputBox } from "../inputs/step_input_box";
import { SendMessage } from "farmbot";
import { ChannelName, isMessageType, StepParams } from "../interfaces";
import { editStep } from "../../api/crud";
import { ToolTips } from "../../constants";
import {
  MESSAGE_STATUSES, EACH_CHANNEL, channel, MESSAGE_STATUSES_DDI,
} from "./tile_send_message_support";
import { StepWrapper } from "../step_ui";
import { t } from "../../i18next_wrapper";
import { InputLengthIndicator } from "../inputs/input_length_indicator";

interface TileSendMessageState {
  message: string;
}

export class TileSendMessage
  extends React.Component<StepParams<SendMessage>, TileSendMessageState> {
  state: TileSendMessageState = { message: this.props.currentStep.args.message };

  get currentSelection() {
    return MESSAGE_STATUSES_DDI()[this.props.currentStep.args.message_type];
  }

  get channels() {
    return (this.props.currentStep.body || []).map(x => x.args.channel_name);
  }

  hasChannel = (channelName: ChannelName) => {
    return this.channels.includes(channelName);
  };

  add = (channelName: ChannelName) => (s: SendMessage) => {
    s.body = s.body || [];
    s.body.push(channel(channelName));
  };

  remove = (channelName: ChannelName) => (s: SendMessage) => {
    s.body = (s.body || []).filter(x => x.args.channel_name !== channelName);
  };

  toggle = (n: ChannelName) => () => {
    this.props.dispatch(editStep({
      sequence: this.props.currentSequence,
      step: this.props.currentStep,
      index: this.props.index,
      executor: this.hasChannel(n) ? this.remove(n) : this.add(n)
    }));
  };

  setMsgType = (x: DropDownItem) => {
    this.props.dispatch(editStep({
      sequence: this.props.currentSequence,
      step: this.props.currentStep,
      index: this.props.index,
      executor: (step: SendMessage) => {
        if (isMessageType(x.value)) {
          step.args.message_type = x.value;
        } else {
          throw new Error("message_type must be one of ALLOWED_MESSAGE_TYPES.");
        }
      }
    }));
  };

  updateMessage = (_key: string, buffer: string) =>
    this.setState({ message: buffer });

  render() {
    const { dispatch, index, currentStep, currentSequence } = this.props;
    return <StepWrapper {...this.props}
      className={"send-message-step"}
      helpText={t(ToolTips.SEND_MESSAGE)}>
      <Row>
        <Col xs={12}>
          <label>{t("Message")}</label>
          <InputLengthIndicator field={"message"}
            value={this.state.message} />
          <StepInputBox dispatch={dispatch}
            step={currentStep}
            sequence={currentSequence}
            index={index}
            keyCallback={this.updateMessage}
            field="message" />
          <div className="bottom-content">
            <div className="channel-options">
              <label>{t("type")}</label>
              <FBSelect
                onChange={this.setMsgType}
                selectedItem={this.currentSelection}
                list={MESSAGE_STATUSES()} />
            </div>
            <div className="channel-fields">
              {EACH_CHANNEL().map((chan, inx) => {
                return <fieldset key={inx}>
                  <label htmlFor={chan.name}>
                    {chan.label}
                  </label>
                  <input type="checkbox" name={chan.name}
                    id={chan.name}
                    onChange={this.toggle(chan.name)}
                    checked={
                      this.hasChannel(chan.name) || chan.alwaysOn}
                    disabled={chan.alwaysOn} />
                </fieldset>;
              })}
            </div>
          </div>
        </Col>
      </Row>
    </StepWrapper>;
  }
}