add shutdown sequence command

pull/1772/head
gabrielburnworth 2020-04-28 07:18:04 -07:00
parent 66553d143d
commit c9511593a3
10 changed files with 115 additions and 43 deletions

View File

@ -348,9 +348,6 @@ export namespace ToolTips {
For example, you can mark a plant as "planted" during a seeding
sequence or mark a weed as "removed" after removing it.`);
export const REBOOT =
trim(`Power cycle FarmBot's onboard computer.`);
export const SET_SERVO_ANGLE =
trim(`Move a servo to the provided angle. An angle of 90 degrees
corresponds to the servo midpoint (or, for a continuous rotation
@ -362,6 +359,9 @@ export namespace ToolTips {
export const MOVE_TO_HOME =
trim(`Move FarmBot to home for the provided axis.`);
export const ASSERTION =
trim(`Evaluate Lua commands. For power users and software developers.`);
export const FIRMWARE_ACTION =
trim(`FarmBot OS or micro-controller firmware action.`);
@ -740,6 +740,15 @@ export namespace Content {
encoders, stall detection, or endstops enabled for the chosen axis.
Enable endstops, encoders, or stall detection from the Device page for: `);
export const REBOOT_STEP =
trim(`Power cycle FarmBot's onboard computer.`);
export const SHUTDOWN_STEP =
trim(`Power down FarmBot's onboard computer.`);
export const ESTOP_STEP =
trim(`Unlocking a device requires user intervention.`);
export const IN_USE =
trim(`Used in another resource. Protected from deletion.`);

View File

@ -136,6 +136,9 @@
&.reboot-step {
background: $brown;
}
&.shutdown-step {
background: $brown;
}
&.unknown-step {
background: $gray;
}
@ -253,6 +256,9 @@
&.emergency-stop-step {
background: $light_red;
}
&.shutdown-step {
background: $light_brown;
}
&.reboot-step {
background: $light_brown;
}

View File

@ -95,6 +95,11 @@ export function StepButtonCluster(props: StepButtonProps) {
color="brown">
{t("REBOOT")}
</StepButton>,
<StepButton {...commonStepProps}
step={{ kind: "power_off", args: {} }}
color="brown">
{t("SHUTDOWN")}
</StepButton>,
<StepButton {...commonStepProps}
step={{ kind: "emergency_lock", args: {} }}
color="red">

View File

@ -5,59 +5,56 @@ import { render } from "enzyme";
import React from "react";
import { StepParams } from "../../interfaces";
import { fakeSequence } from "../../../__test_support__/fake_state/resources";
import { buildResourceIndex } from "../../../__test_support__/resource_index_builder";
import {
buildResourceIndex,
} from "../../../__test_support__/resource_index_builder";
import { editStep } from "../../../api/crud";
import { Reboot } from "farmbot";
import { Content } from "../../../constants";
const fakeProps = (): StepParams => {
const currentSequence = fakeSequence();
const resources = buildResourceIndex().index;
return {
currentSequence,
currentStep: {
kind: "reboot",
args: {
package: "farmbot_os"
}
},
dispatch: jest.fn(),
index: 1,
resources,
confirmStepDeletion: false,
};
};
const fakeProps = (): StepParams => ({
currentSequence: fakeSequence(),
currentStep: {
kind: "reboot",
args: {
package: "farmbot_os"
}
},
dispatch: jest.fn(),
index: 1,
resources: buildResourceIndex().index,
confirmStepDeletion: false,
});
describe("<TileReboot/>", () => {
it("renders", () => {
const el = render(<TileReboot {...fakeProps()} />);
const verbiage = el.text();
expect(verbiage).toContain("Power cycle FarmBot's onboard computer.");
const block = render(<TileReboot {...fakeProps()} />);
expect(block.text()).toContain(Content.REBOOT_STEP);
});
it("crashes if the step is of the wrong `kind`", () => {
const props = fakeProps();
props.currentStep = { kind: "sync", args: {} };
const boom = () => TileReboot(props);
const p = fakeProps();
p.currentStep = { kind: "sync", args: {} };
const boom = () => TileReboot(p);
expect(boom).toThrowError();
});
it("edits the reboot step", () => {
const props = fakeProps();
const editFn = editTheRebootStep(props);
const p = fakeProps();
const editFn = editTheRebootStep(p);
editFn("arduino_firmware");
expect(props.dispatch).toHaveBeenCalled();
expect(p.dispatch).toHaveBeenCalled();
expect(editStep).toHaveBeenCalledWith({
step: props.currentStep,
index: props.index,
sequence: props.currentSequence,
step: p.currentStep,
index: p.index,
sequence: p.currentSequence,
executor: expect.any(Function),
});
});
it("executes the executor", () => {
const props = fakeProps();
const step = props.currentStep as Reboot;
const p = fakeProps();
const step = p.currentStep as Reboot;
step.args.package = "X";
const fn = rebootExecutor("arduino_firmware");
fn(step);

View File

@ -0,0 +1,29 @@
import * as React from "react";
import { mount } from "enzyme";
import { TileShutdown } from "../tile_shutdown";
import { fakeSequence } from "../../../__test_support__/fake_state/resources";
import { PowerOff } from "farmbot";
import { emptyState } from "../../../resources/reducer";
import { StepParams } from "../../interfaces";
import { Content } from "../../../constants";
describe("<TileShutdown />", () => {
const currentStep: PowerOff = {
kind: "power_off",
args: {},
};
const fakeProps = (): StepParams => ({
currentSequence: fakeSequence(),
currentStep: currentStep,
dispatch: jest.fn(),
index: 0,
resources: emptyState().index,
confirmStepDeletion: false,
});
it("renders step", () => {
const block = mount(<TileShutdown {...fakeProps()} />);
expect(block.text()).toContain(Content.SHUTDOWN_STEP);
});
});

View File

@ -34,6 +34,7 @@ import { TileAssertion } from "./tile_assertion";
import { TileEmergencyStop } from "./tile_emergency_stop";
import { TileReboot } from "./tile_reboot";
import { TileOldMarkAs } from "./tile_old_mark_as";
import { TileShutdown } from "./tile_shutdown";
interface MoveParams {
step: Step;
@ -161,7 +162,8 @@ export function renderCeleryNode(props: StepParams) {
case "reboot": return <TileReboot {...props} />;
case "emergency_lock": return <TileEmergencyStop {...props} />;
case "assertion": return <TileAssertion {...props} />;
case "sync": case "power_off": case "read_status":
case "power_off": return <TileShutdown {...props} />;
case "sync": case "read_status":
case "emergency_unlock": case "install_first_party_farmware":
return <TileSystemAction {...props} />;
case "check_updates": case "factory_reset":

View File

@ -7,6 +7,7 @@ import { TypePart } from "./tile_assertion/type_part";
import { LuaPart } from "./tile_assertion/lua_part";
import { SequencePart } from "./tile_assertion/sequence_part";
import { Assertion } from "farmbot/dist/corpus";
import { ToolTips } from "../../constants";
export interface AssertionStepProps extends StepParams {
currentStep: Assertion;
@ -24,7 +25,7 @@ export function TileAssertion(props: StepParams) {
return <StepWrapper>
<StepHeader
className={CLASS_NAME}
helpText={""}
helpText={ToolTips.ASSERTION}
currentSequence={p.currentSequence}
currentStep={p.currentStep}
dispatch={p.dispatch}

View File

@ -1,6 +1,6 @@
import * as React from "react";
import { StepParams } from "../interfaces";
import { ToolTips } from "../../constants";
import { ToolTips, Content } from "../../constants";
import { StepWrapper, StepHeader, StepContent } from "../step_ui";
import { Col, Row } from "../../ui/index";
import { t } from "../../i18next_wrapper";
@ -21,7 +21,7 @@ export function TileEmergencyStop(props: StepParams) {
<Row>
<Col xs={12}>
<p>
{t("Unlocking a device requires user intervention.")}
{t(Content.ESTOP_STEP)}
</p>
</Col>
</Row>

View File

@ -1,6 +1,6 @@
import * as React from "react";
import { StepParams } from "../interfaces";
import { ToolTips } from "../../constants";
import { Content } from "../../constants";
import { StepWrapper, StepHeader, StepContent } from "../step_ui/index";
import { t } from "../../i18next_wrapper";
import { ALLOWED_PACKAGES, SequenceBodyItem, Reboot } from "farmbot";
@ -44,7 +44,7 @@ export function TileReboot(props: StepParams) {
return <StepWrapper>
<StepHeader
className={className}
helpText={ToolTips.REBOOT}
helpText={Content.RESTART_FARMBOT}
currentSequence={currentSequence}
currentStep={currentStep}
dispatch={dispatch}
@ -52,7 +52,7 @@ export function TileReboot(props: StepParams) {
confirmStepDeletion={props.confirmStepDeletion} />
<StepContent className={className}>
<p>
{t(ToolTips.REBOOT)}
{t(Content.REBOOT_STEP)}
</p>
{/* <StepRadio
choices={Object.keys(PACKAGE_CHOICES())}

View File

@ -0,0 +1,23 @@
import * as React from "react";
import { StepParams } from "../interfaces";
import { Content } from "../../constants";
import { StepWrapper, StepHeader, StepContent } from "../step_ui/index";
import { t } from "../../i18next_wrapper";
export function TileShutdown(props: StepParams) {
const { dispatch, currentStep, index, currentSequence } = props;
const className = "shutdown-step";
return <StepWrapper>
<StepHeader
className={className}
helpText={Content.SHUTDOWN_FARMBOT}
currentSequence={currentSequence}
currentStep={currentStep}
dispatch={dispatch}
index={index}
confirmStepDeletion={props.confirmStepDeletion} />
<StepContent className={className}>
<p>{t(Content.SHUTDOWN_STEP)}</p>
</StepContent>
</StepWrapper>;
}