add zero and calibrate to command list

pull/1609/head
gabrielburnworth 2019-12-02 12:53:19 -08:00
parent e8c6257a7f
commit 4f8e344c63
6 changed files with 194 additions and 54 deletions

View File

@ -90,6 +90,22 @@ export function StepButtonCluster(props: StepButtonProps) {
color="blue">
{t("Find Home")}
</StepButton>,
<StepButton{...commonStepProps}
step={{
kind: "zero",
args: { axis: "all" }
}}
color="blue">
{t("Set Zero")}
</StepButton>,
<StepButton{...commonStepProps}
step={{
kind: "calibrate",
args: { axis: "all" }
}}
color="blue">
{t("Calibrate")}
</StepButton>,
<StepButton {...commonStepProps}
step={{
kind: "_if",

View File

@ -1,26 +1,31 @@
import * as React from "react";
import { TileCalibrate } from "../tile_calibrate";
import { TileCalibrate, CalibrateParams } from "../tile_calibrate";
import { mount } from "enzyme";
import { fakeSequence } from "../../../__test_support__/fake_state/resources";
import { Calibrate } from "farmbot";
import { emptyState } from "../../../resources/reducer";
import { StepParams } from "../../interfaces";
import { HardwareFlags } from "../../interfaces";
import {
fakeHardwareFlags
} from "../../../__test_support__/sequence_hardware_settings";
describe("<TileCalibrate/>", () => {
const currentStep: Calibrate = {
kind: "calibrate",
args: {
axis: "all"
}
};
const fakeProps = (): StepParams => ({
const fakeProps = (): CalibrateParams => ({
currentSequence: fakeSequence(),
currentStep: currentStep,
currentStep: { kind: "calibrate", args: { axis: "all" } },
dispatch: jest.fn(),
index: 0,
resources: emptyState().index,
confirmStepDeletion: false,
hardwareFlags: fakeHardwareFlags(),
});
it("errors with incorrect kind", () => {
console.error = jest.fn();
const p = fakeProps();
// tslint:disable-next-line:no-any
p.currentStep.kind = "wrong" as any;
expect(() => mount(<TileCalibrate {...p} />))
.toThrowError("TileCalibrate expects calibrate");
});
it("renders inputs", () => {
@ -33,4 +38,30 @@ describe("<TileCalibrate/>", () => {
expect(labels.at(0).text()).toContain("Calibrate x");
expect(inputs.at(1).props().value).toEqual("x");
});
const CONFLICT_TEXT_BASE = "Hardware setting conflict";
it("doesn't render warning", () => {
const p = fakeProps();
p.currentStep.args.axis = "x";
(p.hardwareFlags as HardwareFlags).findHomeEnabled.x = true;
const wrapper = mount(<TileCalibrate {...p} />);
expect(wrapper.text()).not.toContain(CONFLICT_TEXT_BASE);
});
it("renders warning: all axes", () => {
const p = fakeProps();
p.currentStep.args.axis = "all";
(p.hardwareFlags as HardwareFlags).findHomeEnabled.x = false;
const wrapper = mount(<TileCalibrate {...p} />);
expect(wrapper.text()).toContain(CONFLICT_TEXT_BASE + ": x");
});
it("renders warning: one axis", () => {
const p = fakeProps();
p.currentStep.args.axis = "x";
(p.hardwareFlags as HardwareFlags).findHomeEnabled.x = false;
const wrapper = mount(<TileCalibrate {...p} />);
expect(wrapper.text()).toContain(CONFLICT_TEXT_BASE + ": x");
});
});

View File

@ -2,7 +2,6 @@ import * as React from "react";
import { TileFindHome, FindHomeParams } from "../tile_find_home";
import { mount } from "enzyme";
import { fakeSequence } from "../../../__test_support__/fake_state/resources";
import { FindHome } from "farmbot/dist";
import {
fakeHardwareFlags
} from "../../../__test_support__/sequence_hardware_settings";
@ -10,24 +9,24 @@ import { HardwareFlags } from "../../interfaces";
import { emptyState } from "../../../resources/reducer";
describe("<TileFindHome/>", () => {
const fakeProps = (): FindHomeParams => {
const currentStep: FindHome = {
kind: "find_home",
args: {
speed: 100,
axis: "all"
}
};
return {
currentSequence: fakeSequence(),
currentStep: currentStep,
dispatch: jest.fn(),
index: 0,
resources: emptyState().index,
hardwareFlags: fakeHardwareFlags(),
confirmStepDeletion: false,
};
};
const fakeProps = (): FindHomeParams => ({
currentSequence: fakeSequence(),
currentStep: { kind: "find_home", args: { speed: 100, axis: "all" } },
dispatch: jest.fn(),
index: 0,
resources: emptyState().index,
hardwareFlags: fakeHardwareFlags(),
confirmStepDeletion: false,
});
it("errors with incorrect kind", () => {
console.error = jest.fn();
const p = fakeProps();
// tslint:disable-next-line:no-any
p.currentStep.kind = "wrong" as any;
expect(() => mount(<TileFindHome {...p} />))
.toThrowError("TileFindHome expects find_home");
});
it("renders inputs", () => {
const wrapper = mount(<TileFindHome {...fakeProps()} />);

View File

@ -1,29 +1,93 @@
import * as React from "react";
import { StepParams } from "../interfaces";
import { ToolTips } from "../../constants";
import { StepWrapper, StepHeader, StepContent } from "../step_ui/index";
import { StepParams, HardwareFlags } from "../interfaces";
import { ToolTips, Content } from "../../constants";
import {
StepWrapper, StepHeader, StepContent, conflictsString, StepWarning
} from "../step_ui/index";
import { StepRadio } from "../step_ui/step_radio";
import { t } from "../../i18next_wrapper";
import { Xyz, Calibrate, TaggedSequence } from "farmbot";
import { some } from "lodash";
import { ResourceIndex } from "../../resources/interfaces";
export function TileCalibrate(props: StepParams) {
const { dispatch, currentStep, index, currentSequence } = props;
const className = "calibrate-step";
return <StepWrapper>
<StepHeader
className={className}
helpText={ToolTips.CALIBRATION}
currentSequence={currentSequence}
currentStep={currentStep}
dispatch={dispatch}
index={index}
confirmStepDeletion={props.confirmStepDeletion} />
<StepContent className={className}>
<StepRadio
if (props.currentStep.kind === "calibrate") {
return <InnerTileCalibrate
currentStep={props.currentStep}
currentSequence={props.currentSequence}
dispatch={props.dispatch}
index={props.index}
resources={props.resources}
hardwareFlags={props.hardwareFlags}
confirmStepDeletion={props.confirmStepDeletion} />;
} else {
throw new Error("TileCalibrate expects calibrate");
}
}
export interface CalibrateParams {
currentStep: Calibrate;
currentSequence: TaggedSequence;
dispatch: Function;
index: number;
resources: ResourceIndex;
hardwareFlags: HardwareFlags | undefined;
confirmStepDeletion: boolean;
}
class InnerTileCalibrate extends React.Component<CalibrateParams, {}> {
get settingConflicts(): Record<Xyz, boolean> {
const conflicts = { x: false, y: false, z: false };
if (this.props.hardwareFlags) {
const { axis } = this.props.currentStep.args;
const { findHomeEnabled } = this.props.hardwareFlags;
switch (axis) {
case "x":
case "y":
case "z":
conflicts[axis] = !findHomeEnabled[axis];
break;
case "all":
conflicts.x = !findHomeEnabled.x;
conflicts.y = !findHomeEnabled.y;
conflicts.z = !findHomeEnabled.z;
break;
}
}
return conflicts;
}
get settingConflictWarning() {
return Content.END_DETECTION_DISABLED
+ conflictsString(this.settingConflicts);
}
render() {
const { dispatch, currentStep, index, currentSequence } = this.props;
const className = "calibrate-step";
return <StepWrapper>
<StepHeader
className={className}
helpText={ToolTips.CALIBRATION}
currentSequence={currentSequence}
currentStep={currentStep}
dispatch={dispatch}
index={index}
label={t("Calibrate")} />
</StepContent>
</StepWrapper>;
confirmStepDeletion={this.props.confirmStepDeletion}>
{some(this.settingConflicts) &&
<StepWarning
warning={this.settingConflictWarning}
conflicts={this.settingConflicts} />}
</StepHeader>
<StepContent className={className}>
<StepRadio
currentSequence={currentSequence}
currentStep={currentStep}
dispatch={dispatch}
index={index}
label={t("Calibrate")} />
</StepContent>
</StepWrapper>;
}
}

View File

@ -4,7 +4,7 @@ import * as React from "react";
import { mount } from "enzyme";
import { StepRadio, StepRadioProps } from "../step_radio";
import { fakeSequence } from "../../../__test_support__/fake_state/resources";
import { FindHome } from "farmbot";
import { FindHome, Calibrate, Zero } from "farmbot";
import { overwrite } from "../../../api/crud";
describe("<StepRadio />", () => {
@ -30,7 +30,7 @@ describe("<StepRadio />", () => {
expect(wrapper.text()).toContain("Find");
});
it("handles update", () => {
it("handles update for find_home", () => {
const p = fakeProps();
const wrapper = mount(<StepRadio {...p} />);
wrapper.find("input").last().simulate("change");
@ -41,4 +41,30 @@ describe("<StepRadio />", () => {
expect(overwrite).toHaveBeenCalledWith(p.currentSequence,
expect.objectContaining({ body: [expectedStep] }));
});
it("handles update for calibrate", () => {
const p = fakeProps();
p.currentStep = { kind: "calibrate", args: { axis: "x" } };
const wrapper = mount(<StepRadio {...p} />);
wrapper.find("input").last().simulate("change");
const expectedStep: Calibrate = {
kind: "calibrate",
args: { axis: "all" }
};
expect(overwrite).toHaveBeenCalledWith(p.currentSequence,
expect.objectContaining({ body: [expectedStep] }));
});
it("handles update for zero", () => {
const p = fakeProps();
p.currentStep = { kind: "zero", args: { axis: "x" } };
const wrapper = mount(<StepRadio {...p} />);
wrapper.find("input").last().simulate("change");
const expectedStep: Zero = {
kind: "zero",
args: { axis: "all" }
};
expect(overwrite).toHaveBeenCalledWith(p.currentSequence,
expect.objectContaining({ body: [expectedStep] }));
});
});

View File

@ -19,14 +19,18 @@ const AXIS_CHOICES: ALLOWED_AXIS[] = ["x", "y", "z", "all"];
export function StepRadio(props: StepRadioProps) {
const isSelected = (choice: ALLOWED_AXIS) => {
if (props.currentStep.kind === "find_home") {
if (props.currentStep.kind === "find_home"
|| props.currentStep.kind === "calibrate"
|| props.currentStep.kind === "zero") {
return props.currentStep.args.axis === choice;
}
};
const handleUpdate = (choice: ALLOWED_AXIS) => {
const update = defensiveClone(props.currentStep);
if (update.kind === "find_home") {
if (update.kind === "find_home"
|| update.kind === "calibrate"
|| update.kind === "zero") {
const nextSequence = defensiveClone(props.currentSequence).body;
update.args.axis = choice;
(nextSequence.body || [])[props.index] = update;