resource_update -> update_resource (fe)
parent
1014eece5f
commit
281813369e
|
@ -346,7 +346,7 @@ export namespace ToolTips {
|
|||
trim(`The Mark As step allows FarmBot to programmatically edit the
|
||||
properties of the UTM, plants, and weeds from within a sequence.
|
||||
For example, you can mark a plant as "planted" during a seeding
|
||||
sequence or delete a weed after removing it.`);
|
||||
sequence or mark a weed as "removed" after removing it.`);
|
||||
|
||||
export const REBOOT =
|
||||
trim(`Power cycle FarmBot's onboard computer.`);
|
||||
|
|
|
@ -106,7 +106,7 @@
|
|||
&.take-photo-step {
|
||||
background: $brown;
|
||||
}
|
||||
&.resource-update-step {
|
||||
&.update-resource-step {
|
||||
background: $brown;
|
||||
}
|
||||
&.set-servo-angle-step {
|
||||
|
@ -226,7 +226,7 @@
|
|||
&.take-photo-step a {
|
||||
color: $dark_brown;
|
||||
}
|
||||
&.resource-update-step {
|
||||
&.update-resource-step {
|
||||
background: $light_brown;
|
||||
}
|
||||
&.set-servo-angle-step {
|
||||
|
|
|
@ -81,6 +81,7 @@ export enum Feature {
|
|||
ota_update_hour = "ota_update_hour",
|
||||
rpi_led_control = "rpi_led_control",
|
||||
sensors = "sensors",
|
||||
update_resource = "update_resource",
|
||||
use_update_channel = "use_update_channel",
|
||||
variables = "variables",
|
||||
}
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
jest.mock("../../history", () => ({ push: jest.fn() }));
|
||||
|
||||
jest.mock("../../api/crud", () => ({
|
||||
destroy: jest.fn(),
|
||||
save: jest.fn(),
|
||||
|
@ -55,6 +57,7 @@ import { DropAreaProps } from "../../draggable/interfaces";
|
|||
import { Actions } from "../../constants";
|
||||
import { setWebAppConfigValue } from "../../config_storage/actions";
|
||||
import { BooleanSetting } from "../../session_keys";
|
||||
import { push } from "../../history";
|
||||
|
||||
describe("<SequenceEditorMiddleActive/>", () => {
|
||||
const fakeProps = (): ActiveMiddleProps => {
|
||||
|
@ -73,10 +76,13 @@ describe("<SequenceEditorMiddleActive/>", () => {
|
|||
};
|
||||
};
|
||||
|
||||
it("saves", () => {
|
||||
const wrapper = mount(<SequenceEditorMiddleActive {...fakeProps()} />);
|
||||
clickButton(wrapper, 0, "Save * ");
|
||||
it("saves", async () => {
|
||||
const p = fakeProps();
|
||||
p.dispatch = () => Promise.resolve();
|
||||
const wrapper = mount(<SequenceEditorMiddleActive {...p} />);
|
||||
await clickButton(wrapper, 0, "Save * ");
|
||||
expect(save).toHaveBeenCalledWith(expect.stringContaining("Sequence"));
|
||||
expect(push).toHaveBeenCalledWith("/app/sequences/fake");
|
||||
});
|
||||
|
||||
it("tests", () => {
|
||||
|
|
|
@ -66,32 +66,45 @@ interface NewVarProps {
|
|||
newVarLabel?: string;
|
||||
}
|
||||
|
||||
const nothingVar =
|
||||
({ identifierLabel: label, allowedVariableNodes }: NewVarProps): VariableWithAValue =>
|
||||
createVariableNode(allowedVariableNodes)(label, NOTHING_SELECTED);
|
||||
const nothingVar = ({
|
||||
identifierLabel: label, allowedVariableNodes
|
||||
}: NewVarProps): VariableWithAValue =>
|
||||
createVariableNode(allowedVariableNodes)(label, NOTHING_SELECTED);
|
||||
|
||||
const toolVar = (value: string | number) =>
|
||||
({ identifierLabel: label, allowedVariableNodes }: NewVarProps): VariableWithAValue =>
|
||||
createVariableNode(allowedVariableNodes)(label, {
|
||||
kind: "tool",
|
||||
args: { tool_id: parseInt("" + value) }
|
||||
});
|
||||
const toolVar = (value: string | number) => ({
|
||||
identifierLabel: label, allowedVariableNodes
|
||||
}: NewVarProps): VariableWithAValue =>
|
||||
createVariableNode(allowedVariableNodes)(label, {
|
||||
kind: "tool",
|
||||
args: { tool_id: parseInt("" + value) }
|
||||
});
|
||||
|
||||
const pointVar = (
|
||||
pointer_type: "Plant" | "GenericPointer" | "Weed",
|
||||
value: string | number,
|
||||
) => ({ identifierLabel: label, allowedVariableNodes }: NewVarProps): VariableWithAValue =>
|
||||
) => ({
|
||||
identifierLabel: label, allowedVariableNodes
|
||||
}: NewVarProps): VariableWithAValue =>
|
||||
createVariableNode(allowedVariableNodes)(label, {
|
||||
kind: "point",
|
||||
args: { pointer_type, pointer_id: parseInt("" + value) }
|
||||
});
|
||||
|
||||
const manualEntry = (value: string | number) =>
|
||||
({ identifierLabel: label, allowedVariableNodes }: NewVarProps): VariableWithAValue =>
|
||||
createVariableNode(allowedVariableNodes)(label, {
|
||||
kind: "coordinate",
|
||||
args: value ? JSON.parse("" + value) : { x: 0, y: 0, z: 0 }
|
||||
});
|
||||
const groupVar = (value: string | number) => ({
|
||||
identifierLabel: label, allowedVariableNodes
|
||||
}: NewVarProps): VariableWithAValue =>
|
||||
createVariableNode(allowedVariableNodes)(label, {
|
||||
kind: "point_group",
|
||||
args: { point_group_id: parseInt("" + value) }
|
||||
});
|
||||
|
||||
const manualEntry = (value: string | number) => ({
|
||||
identifierLabel: label, allowedVariableNodes
|
||||
}: NewVarProps): VariableWithAValue =>
|
||||
createVariableNode(allowedVariableNodes)(label, {
|
||||
kind: "coordinate",
|
||||
args: value ? JSON.parse("" + value) : { x: 0, y: 0, z: 0 }
|
||||
});
|
||||
|
||||
/**
|
||||
* Create a parameter declaration or a parameter application containing an
|
||||
|
@ -129,15 +142,7 @@ const createNewVariable = (props: NewVarProps): VariableNode | undefined => {
|
|||
case "Tool": return toolVar(ddi.value)(props);
|
||||
case "parameter": return newParameter(props);
|
||||
case "Coordinate": return manualEntry(ddi.value)(props);
|
||||
case "PointGroup":
|
||||
const point_group_id = parseInt("" + ddi.value, 10);
|
||||
return {
|
||||
kind: "parameter_application",
|
||||
args: {
|
||||
label: props.identifierLabel,
|
||||
data_value: { kind: "point_group", args: { point_group_id } }
|
||||
}
|
||||
};
|
||||
case "PointGroup": return groupVar(ddi.value)(props);
|
||||
}
|
||||
console.error("WARNING: Don't know how to handle " + (ddi.headingId || "NA"));
|
||||
return undefined;
|
||||
|
|
|
@ -12,7 +12,7 @@ import { save, edit, destroy } from "../api/crud";
|
|||
import { TestButton } from "./test_button";
|
||||
import { AllSteps } from "./all_steps";
|
||||
import { LocalsList, localListCallback } from "./locals_list/locals_list";
|
||||
import { betterCompact } from "../util";
|
||||
import { betterCompact, urlFriendly } from "../util";
|
||||
import { AllowedVariableNodes } from "./locals_list/locals_list_support";
|
||||
import { ResourceIndex } from "../resources/interfaces";
|
||||
import { ShouldDisplay } from "../devices/interfaces";
|
||||
|
@ -135,7 +135,8 @@ const SequenceBtnGroup = ({
|
|||
}: SequenceBtnGroupProps) =>
|
||||
<div className="button-group">
|
||||
<SaveBtn status={sequence.specialStatus}
|
||||
onClick={() => dispatch(save(sequence.uuid))} />
|
||||
onClick={() => dispatch(save(sequence.uuid)).then(() =>
|
||||
push(`/app/sequences/${urlFriendly(sequence.body.name)}`))} />
|
||||
<TestButton
|
||||
syncStatus={syncStatus}
|
||||
sequence={sequence}
|
||||
|
|
|
@ -179,16 +179,19 @@ export function StepButtonCluster(props: StepButtonProps) {
|
|||
{t("ASSERTION")}
|
||||
</StepButton>);
|
||||
|
||||
shouldDisplay(Feature.mark_as_step) && ALL_THE_BUTTONS.push(<StepButton
|
||||
shouldDisplay(Feature.update_resource) && ALL_THE_BUTTONS.push(<StepButton
|
||||
{...commonStepProps}
|
||||
step={{
|
||||
kind: "resource_update",
|
||||
kind: "update_resource",
|
||||
args: {
|
||||
resource_type: "Device",
|
||||
resource_id: 0,
|
||||
label: "mounted_tool_id",
|
||||
value: 0
|
||||
}
|
||||
resource: {
|
||||
kind: "resource",
|
||||
args: { resource_id: 0, resource_type: "Device" }
|
||||
}
|
||||
},
|
||||
body: [
|
||||
{ kind: "pair", args: { label: "mounted_tool_id", value: 0 } },
|
||||
],
|
||||
}}
|
||||
color="brown">
|
||||
{t("Mark As...")}
|
||||
|
|
|
@ -147,17 +147,32 @@ describe("renderCeleryNode()", () => {
|
|||
node: { kind: "wait", args: { milliseconds: 100 } },
|
||||
expected: "milliseconds"
|
||||
},
|
||||
{
|
||||
node: {
|
||||
kind: "update_resource",
|
||||
args: {
|
||||
resource: {
|
||||
kind: "resource",
|
||||
args: { resource_id: 23, resource_type: "Plant" }
|
||||
},
|
||||
body: [
|
||||
{ kind: "pair", args: { label: "plant_stage", value: "planted" } },
|
||||
]
|
||||
}
|
||||
},
|
||||
expected: "markplant 23 as"
|
||||
},
|
||||
{
|
||||
node: {
|
||||
kind: "resource_update",
|
||||
args: {
|
||||
resource_id: 23,
|
||||
resource_type: "Plant",
|
||||
label: "x",
|
||||
value: 300
|
||||
label: "plant_stage",
|
||||
value: "planted",
|
||||
}
|
||||
},
|
||||
expected: "MarkPlantasx = 300"
|
||||
expected: "mark plant 23 plant_stage as plantedthis step has been deprecated."
|
||||
},
|
||||
{
|
||||
node: { kind: "set_servo_angle", args: { pin_number: 4, pin_value: 90 } },
|
||||
|
|
|
@ -0,0 +1,106 @@
|
|||
const mockEditStep = jest.fn();
|
||||
jest.mock("../../../api/crud", () => ({
|
||||
editStep: mockEditStep
|
||||
}));
|
||||
|
||||
import * as React from "react";
|
||||
import { mount } from "enzyme";
|
||||
import { TileOldMarkAs } from "../tile_old_mark_as";
|
||||
import { fakeSequence } from "../../../__test_support__/fake_state/resources";
|
||||
import { emptyState } from "../../../resources/reducer";
|
||||
import { StepParams } from "../../interfaces";
|
||||
import { editStep } from "../../../api/crud";
|
||||
import { SequenceBodyItem } from "farmbot";
|
||||
import { cloneDeep } from "lodash";
|
||||
|
||||
describe("<TileOldMarkAs />", () => {
|
||||
const currentStep = {
|
||||
kind: "resource_update",
|
||||
args: {
|
||||
resource_type: "Device",
|
||||
resource_id: 0,
|
||||
label: "mounted_tool_id",
|
||||
value: 0,
|
||||
}
|
||||
} as unknown as SequenceBodyItem;
|
||||
|
||||
const fakeProps = (): StepParams => ({
|
||||
currentSequence: fakeSequence(),
|
||||
currentStep: currentStep,
|
||||
dispatch: jest.fn(),
|
||||
index: 0,
|
||||
resources: emptyState().index,
|
||||
confirmStepDeletion: false,
|
||||
});
|
||||
|
||||
it("renders deprecation notice", () => {
|
||||
const block = mount(<TileOldMarkAs {...fakeProps()} />);
|
||||
expect(block.text()).toContain("deprecated");
|
||||
expect(block.text()).not.toContain("convert");
|
||||
});
|
||||
|
||||
it("renders deprecation notice and convert button", () => {
|
||||
const p = fakeProps();
|
||||
p.shouldDisplay = () => true;
|
||||
const block = mount(<TileOldMarkAs {...p} />);
|
||||
expect(block.text()).toContain("deprecated");
|
||||
expect(block.text()).toContain("convert");
|
||||
});
|
||||
|
||||
it("converts set mounted tool step", () => {
|
||||
const p = fakeProps();
|
||||
p.shouldDisplay = () => true;
|
||||
const block = mount(<TileOldMarkAs {...p} />);
|
||||
expect(block.text()).toContain("deprecated");
|
||||
expect(block.text()).toContain("convert");
|
||||
block.find("button").last().simulate("click");
|
||||
expect(editStep).toHaveBeenCalled();
|
||||
const step = cloneDeep(p.currentStep);
|
||||
mockEditStep.mock.calls[0][0].executor(step);
|
||||
expect(step).toEqual({
|
||||
kind: "update_resource",
|
||||
args: {
|
||||
resource: {
|
||||
kind: "resource",
|
||||
args: { resource_type: "Device", resource_id: 0 }
|
||||
}
|
||||
},
|
||||
body: [{
|
||||
kind: "pair", args: { label: "mounted_tool_id", value: 0 }
|
||||
}],
|
||||
});
|
||||
});
|
||||
|
||||
it("converts remove weed step", () => {
|
||||
const p = fakeProps();
|
||||
p.currentStep = {
|
||||
kind: "resource_update",
|
||||
args: {
|
||||
resource_type: "Weed",
|
||||
resource_id: 123,
|
||||
label: "discarded_at",
|
||||
value: "?",
|
||||
}
|
||||
} as unknown as SequenceBodyItem;
|
||||
p.shouldDisplay = () => true;
|
||||
const block = mount(<TileOldMarkAs {...p} />);
|
||||
expect(block.text()).toContain("deprecated");
|
||||
expect(block.text()).toContain("convert");
|
||||
block.find("button").last().simulate("click");
|
||||
expect(editStep).toHaveBeenCalled();
|
||||
const step = cloneDeep(p.currentStep);
|
||||
mockEditStep.mock.calls[0][0].executor(step);
|
||||
expect(step).toEqual({
|
||||
kind: "update_resource",
|
||||
args: {
|
||||
resource: {
|
||||
kind: "resource",
|
||||
args: { resource_type: "Weed", resource_id: 123 }
|
||||
}
|
||||
},
|
||||
body: [{
|
||||
kind: "pair", args: { label: "plant_stage", value: "removed" }
|
||||
}],
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,7 +1,7 @@
|
|||
import * as React from "react";
|
||||
import {
|
||||
CeleryNode, LegalArgString, If, Execute, Nothing,
|
||||
SequenceBodyItem as Step, TaggedSequence,
|
||||
SequenceBodyItem as Step, TaggedSequence, LegalSequenceKind,
|
||||
} from "farmbot";
|
||||
import { FLOAT_NUMERIC_FIELDS, NUMERIC_FIELDS } from "../interfaces";
|
||||
import { ExecuteBlock } from "./tile_execute";
|
||||
|
@ -33,6 +33,7 @@ import { t } from "../../i18next_wrapper";
|
|||
import { TileAssertion } from "./tile_assertion";
|
||||
import { TileEmergencyStop } from "./tile_emergency_stop";
|
||||
import { TileReboot } from "./tile_reboot";
|
||||
import { TileOldMarkAs } from "./tile_old_mark_as";
|
||||
|
||||
interface MoveParams {
|
||||
step: Step;
|
||||
|
@ -149,7 +150,9 @@ export function renderCeleryNode(props: StepParams) {
|
|||
case "take_photo": return <TileTakePhoto {...props} />;
|
||||
case "wait": return <TileWait {...props} />;
|
||||
case "write_pin": return <TileWritePin {...props} />;
|
||||
case "resource_update": return <MarkAs {...props} />;
|
||||
case "update_resource": return <MarkAs {...props} />;
|
||||
case "resource_update" as LegalSequenceKind:
|
||||
return <TileOldMarkAs {...props} />;
|
||||
case "set_servo_angle": return <TileSetServoAngle {...props} />;
|
||||
case "toggle_pin": return <TileTogglePin {...props} />;
|
||||
case "zero": return <TileSetZero {...props} />;
|
||||
|
|
|
@ -4,7 +4,7 @@ import { StepWrapper, StepHeader, StepContent } from "../step_ui/index";
|
|||
import { ToolTips } from "../../constants";
|
||||
import * as React from "react";
|
||||
import { unpackStep } from "./mark_as/unpack_step";
|
||||
import { ResourceUpdate } from "farmbot";
|
||||
import { UpdateResource } from "farmbot";
|
||||
import { resourceList } from "./mark_as/resource_list";
|
||||
import { actionList } from "./mark_as/action_list";
|
||||
import { commitStepChanges } from "./mark_as/commit_step_changes";
|
||||
|
@ -15,7 +15,7 @@ const NONE = (): DropDownItem => ({ label: t("Select one"), value: 0 });
|
|||
|
||||
export class MarkAs extends React.Component<StepParams, MarkAsState> {
|
||||
state: MarkAsState = { nextResource: undefined };
|
||||
className = "resource-update-step";
|
||||
className = "update-resource-step";
|
||||
|
||||
commitSelection = (nextAction: DropDownItem) => {
|
||||
this.props.dispatch(commitStepChanges({
|
||||
|
@ -23,13 +23,13 @@ export class MarkAs extends React.Component<StepParams, MarkAsState> {
|
|||
nextAction,
|
||||
nextResource: this.state.nextResource,
|
||||
sequence: this.props.currentSequence,
|
||||
step: this.props.currentStep as ResourceUpdate,
|
||||
step: this.props.currentStep as UpdateResource,
|
||||
}));
|
||||
this.setState({ nextResource: undefined });
|
||||
};
|
||||
|
||||
render() {
|
||||
const step = this.props.currentStep as ResourceUpdate;
|
||||
const step = this.props.currentStep as UpdateResource;
|
||||
const { rightSide, leftSide } =
|
||||
unpackStep({ step, resourceIndex: this.props.resources });
|
||||
return <StepWrapper>
|
||||
|
@ -54,7 +54,8 @@ export class MarkAs extends React.Component<StepParams, MarkAsState> {
|
|||
<Col xs={6}>
|
||||
<label>{t("as")}</label>
|
||||
<FBSelect
|
||||
list={actionList(this.state.nextResource, step, this.props.resources)}
|
||||
list={actionList(this.state.nextResource?.headingId,
|
||||
step, this.props.resources)}
|
||||
onChange={this.commitSelection}
|
||||
key={JSON.stringify(rightSide) + JSON.stringify(this.state)}
|
||||
selectedItem={this.state.nextResource ? NONE() : rightSide} />
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { actionList } from "../action_list";
|
||||
import { resourceUpdate, markAsResourceFixture } from "../assertion_support";
|
||||
import { updateResource, markAsResourceFixture } from "../test_support";
|
||||
import {
|
||||
buildResourceIndex,
|
||||
} from "../../../../__test_support__/resource_index_builder";
|
||||
|
@ -7,7 +7,10 @@ import { PLANT_OPTIONS } from "../constants";
|
|||
|
||||
describe("actionList()", () => {
|
||||
it("uses args.resource_type if DropDownItem is undefined", () => {
|
||||
const step = resourceUpdate({ resource_type: "Plant" });
|
||||
const step = updateResource({
|
||||
kind: "resource",
|
||||
args: { resource_type: "Plant", resource_id: 0 }
|
||||
});
|
||||
const { index } = markAsResourceFixture();
|
||||
const result = actionList(undefined, step, index);
|
||||
expect(result).toEqual(PLANT_OPTIONS());
|
||||
|
@ -15,9 +18,9 @@ describe("actionList()", () => {
|
|||
|
||||
it("provides a list of tool mount actions", () => {
|
||||
const ddi = { label: "test case", value: 1, headingId: "Device" };
|
||||
const step = resourceUpdate({});
|
||||
const step = updateResource();
|
||||
const { index } = markAsResourceFixture();
|
||||
const result = actionList(ddi, step, index);
|
||||
const result = actionList(ddi.headingId, step, index);
|
||||
expect(result.length).toBe(3);
|
||||
const labels = result.map(x => x.label);
|
||||
expect(labels).toContain("Not Mounted");
|
||||
|
@ -27,9 +30,9 @@ describe("actionList()", () => {
|
|||
|
||||
it("provides a list of generic pointer actions", () => {
|
||||
const ddi = { label: "test case", value: 1, headingId: "GenericPointer" };
|
||||
const step = resourceUpdate({});
|
||||
const step = updateResource();
|
||||
const { index } = markAsResourceFixture();
|
||||
const result = actionList(ddi, step, index);
|
||||
const result = actionList(ddi.headingId, step, index);
|
||||
expect(result.length).toBe(1);
|
||||
const labels = result.map(x => x.label);
|
||||
expect(labels).toContain("Removed");
|
||||
|
@ -37,19 +40,26 @@ describe("actionList()", () => {
|
|||
|
||||
it("provides a list of weed pointer actions", () => {
|
||||
const ddi = { label: "test case", value: 1, headingId: "Weed" };
|
||||
const step = resourceUpdate({});
|
||||
const step = updateResource();
|
||||
const { index } = markAsResourceFixture();
|
||||
const result = actionList(ddi, step, index);
|
||||
const result = actionList(ddi.headingId, step, index);
|
||||
expect(result.length).toBe(1);
|
||||
const labels = result.map(x => x.label);
|
||||
expect(labels).toContain("Removed");
|
||||
});
|
||||
|
||||
it("returns an empty list for all other options", () => {
|
||||
it("returns an empty list for identifiers", () => {
|
||||
const ddi = { label: "test case", value: 1, headingId: "USB Cables" };
|
||||
const step = resourceUpdate({});
|
||||
const step = updateResource();
|
||||
const { index } = buildResourceIndex([]);
|
||||
const result = actionList(ddi, step, index);
|
||||
const result = actionList(ddi.headingId, step, index);
|
||||
expect(result.length).toBe(0);
|
||||
});
|
||||
|
||||
it("returns an empty list for all other options", () => {
|
||||
const step = updateResource({ kind: "identifier", args: { label: "var" } });
|
||||
const { index } = buildResourceIndex([]);
|
||||
const result = actionList("Other", step, index);
|
||||
expect(result.length).toBe(0);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { fakeMarkAsProps } from "../assertion_support";
|
||||
import { fakeMarkAsProps } from "../test_support";
|
||||
import { commitStepChanges } from "../commit_step_changes";
|
||||
import { ResourceUpdate, TaggedSequence } from "farmbot";
|
||||
import { UpdateResource, TaggedSequence } from "farmbot";
|
||||
import { Actions } from "../../../../constants";
|
||||
import { unpackUUID } from "../../../../util";
|
||||
|
||||
|
@ -10,7 +10,7 @@ describe("commitSelection", () => {
|
|||
const results = commitStepChanges({
|
||||
nextAction: { label: "X", value: "some_action" },
|
||||
nextResource: undefined,
|
||||
step: p.currentStep as ResourceUpdate,
|
||||
step: p.currentStep as UpdateResource,
|
||||
index: p.index,
|
||||
sequence: p.currentSequence
|
||||
});
|
||||
|
@ -19,7 +19,7 @@ describe("commitSelection", () => {
|
|||
expect(unpackUUID(payload.uuid).kind).toBe("Sequence");
|
||||
const s = payload.update as TaggedSequence["body"];
|
||||
expect(s.kind).toBe("sequence");
|
||||
const step = (s.body || [])[0] as ResourceUpdate;
|
||||
expect(step.args.value).toBe("some_action");
|
||||
const step = (s.body || [])[0] as UpdateResource;
|
||||
expect(step.body?.[0].args.value).toBe("some_action");
|
||||
});
|
||||
});
|
||||
|
|
|
@ -7,7 +7,7 @@ import * as React from "react";
|
|||
import { shallow, mount } from "enzyme";
|
||||
import { MarkAs } from "../../mark_as";
|
||||
import { FBSelect } from "../../../../ui";
|
||||
import { fakeMarkAsProps } from "../assertion_support";
|
||||
import { fakeMarkAsProps } from "../test_support";
|
||||
import { commitStepChanges } from "../commit_step_changes";
|
||||
|
||||
describe("<MarkAs/>", () => {
|
||||
|
|
|
@ -1,36 +1,45 @@
|
|||
import { resourceUpdate } from "../assertion_support";
|
||||
import { updateResource } from "../test_support";
|
||||
import { packStep } from "../pack_step";
|
||||
import { TOP_HALF } from "../constants";
|
||||
import { Resource, Identifier } from "farmbot";
|
||||
|
||||
describe("packStep()", () => {
|
||||
const plant = resourceUpdate({ resource_type: "Plant", resource_id: 6 });
|
||||
|
||||
it("serializes 'discard' actions", () => {
|
||||
const actionDDI = { value: "removed", label: "Removed" };
|
||||
const { args } = packStep(plant, undefined, actionDDI);
|
||||
expect(args.label).toEqual("discarded_at");
|
||||
expect(args.value).toEqual("{{ Time.now }}");
|
||||
expect(args.resource_id).toEqual(6);
|
||||
expect(args.resource_type).toEqual("Plant");
|
||||
const plant = updateResource({
|
||||
kind: "resource",
|
||||
args: { resource_type: "Plant", resource_id: 6 }
|
||||
});
|
||||
|
||||
it("serializes 'plant_stage' actions", () => {
|
||||
const actionDDI = { value: "harvested", label: "harvested" };
|
||||
const { args } = packStep(plant, undefined, actionDDI);
|
||||
expect(args.label).toEqual("plant_stage");
|
||||
expect(args.value).toEqual("harvested");
|
||||
expect(args.resource_id).toEqual(6);
|
||||
expect(args.resource_type).toEqual("Plant");
|
||||
const { args, body } = packStep(plant, undefined, actionDDI);
|
||||
expect(body?.[0].args.label).toEqual("plant_stage");
|
||||
expect(body?.[0].args.value).toEqual("harvested");
|
||||
expect((args.resource as Resource).args.resource_id).toEqual(6);
|
||||
expect((args.resource as Resource).args.resource_type).toEqual("Plant");
|
||||
});
|
||||
|
||||
it("serializes 'mounted_tool_id' actions", () => {
|
||||
const resourceDDI = TOP_HALF[0];
|
||||
const actionDDI = { value: 23, label: "Mounted to can opener" };
|
||||
const device = resourceUpdate({ resource_type: "Device", resource_id: 7 });
|
||||
const { args } = packStep(device, resourceDDI, actionDDI);
|
||||
expect(args.label).toEqual("mounted_tool_id");
|
||||
expect(args.resource_type).toEqual("Device");
|
||||
expect(args.resource_id).toEqual(0);
|
||||
expect(args.value).toEqual(23);
|
||||
const device = updateResource({
|
||||
kind: "resource",
|
||||
args: { resource_type: "Device", resource_id: 7 }
|
||||
});
|
||||
const { args, body } = packStep(device, resourceDDI, actionDDI);
|
||||
expect(body?.[0].args.label).toEqual("mounted_tool_id");
|
||||
expect((args.resource as Resource).args.resource_type).toEqual("Device");
|
||||
expect((args.resource as Resource).args.resource_id).toEqual(0);
|
||||
expect(body?.[0].args.value).toEqual(23);
|
||||
});
|
||||
|
||||
it("serializes 'plant_stage' actions: identifier", () => {
|
||||
const actionDDI = { value: "harvested", label: "harvested" };
|
||||
const identifier = updateResource({
|
||||
kind: "identifier", args: { label: "var" }
|
||||
});
|
||||
const { args, body } = packStep(identifier, undefined, actionDDI);
|
||||
expect(body?.[0].args.label).toEqual("plant_stage");
|
||||
expect(body?.[0].args.value).toEqual("harvested");
|
||||
expect((args.resource as Identifier).args.label).toEqual("var");
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { resourceList } from "../resource_list";
|
||||
import { markAsResourceFixture } from "../assertion_support";
|
||||
import { markAsResourceFixture } from "../test_support";
|
||||
|
||||
describe("resourceList()", () => {
|
||||
it("lists defaults, plus saved points", () => {
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
import { fakeResourceIndex } from "../../../locals_list/test_helpers";
|
||||
import { resourceUpdate } from "../assertion_support";
|
||||
import { updateResource } from "../test_support";
|
||||
import { unpackStep, TOOL_MOUNT, DISMOUNTED } from "../unpack_step";
|
||||
import {
|
||||
selectAllPlantPointers,
|
||||
selectAllTools,
|
||||
selectAllGenericPointers,
|
||||
selectAllWeedPointers,
|
||||
} from "../../../../resources/selectors";
|
||||
import { DropDownPair } from "../interfaces";
|
||||
import { fakeTool } from "../../../../__test_support__/fake_state/resources";
|
||||
import { fakeTool, fakeWeed } from "../../../../__test_support__/fake_state/resources";
|
||||
import {
|
||||
buildResourceIndex,
|
||||
} from "../../../../__test_support__/resource_index_builder";
|
||||
|
@ -25,7 +25,7 @@ describe("unpackStep()", () => {
|
|||
|
||||
it("unpacks empty tool_ids", () => {
|
||||
const result = unpackStep({
|
||||
step: resourceUpdate({ label: "mounted_tool_id", value: 0 }),
|
||||
step: updateResource(undefined, { label: "mounted_tool_id", value: 0 }),
|
||||
resourceIndex: fakeResourceIndex()
|
||||
});
|
||||
expect(result).toEqual(DISMOUNTED());
|
||||
|
@ -37,7 +37,8 @@ describe("unpackStep()", () => {
|
|||
expect(body).toBeTruthy();
|
||||
|
||||
const result = unpackStep({
|
||||
step: resourceUpdate({ label: "mounted_tool_id", value: body.id || NaN }),
|
||||
step: updateResource(undefined,
|
||||
{ label: "mounted_tool_id", value: body.id || NaN }),
|
||||
resourceIndex
|
||||
});
|
||||
const actionLabel = "Mounted to: Generic Tool";
|
||||
|
@ -54,7 +55,8 @@ describe("unpackStep()", () => {
|
|||
expect(body).toBeTruthy();
|
||||
|
||||
const result = unpackStep({
|
||||
step: resourceUpdate({ label: "mounted_tool_id", value: body.id || NaN }),
|
||||
step: updateResource(undefined,
|
||||
{ label: "mounted_tool_id", value: body.id || NaN }),
|
||||
resourceIndex
|
||||
});
|
||||
const actionLabel = "Mounted to: Untitled Tool";
|
||||
|
@ -64,7 +66,8 @@ describe("unpackStep()", () => {
|
|||
|
||||
it("unpacks invalid tool_ids (that may have been valid previously)", () => {
|
||||
const result = unpackStep({
|
||||
step: resourceUpdate({ label: "mounted_tool_id", value: Infinity }),
|
||||
step: updateResource(undefined,
|
||||
{ label: "mounted_tool_id", value: Infinity }),
|
||||
resourceIndex: fakeResourceIndex()
|
||||
});
|
||||
const actionLabel = "Mounted to: an unknown tool";
|
||||
|
@ -72,49 +75,70 @@ describe("unpackStep()", () => {
|
|||
assertGoodness(result, actionLabel, "mounted", label, value);
|
||||
});
|
||||
|
||||
it("unpacks discarded_at operations", () => {
|
||||
const resourceIndex = fakeResourceIndex();
|
||||
const { body } = selectAllGenericPointers(resourceIndex)[0];
|
||||
expect(body.pointer_type).toBe("GenericPointer");
|
||||
|
||||
const result = unpackStep({
|
||||
step: resourceUpdate({
|
||||
resource_type: "GenericPointer",
|
||||
resource_id: body.id || -1,
|
||||
label: "discarded_at",
|
||||
value: "non-configurable"
|
||||
}), resourceIndex
|
||||
});
|
||||
assertGoodness(result,
|
||||
"Removed",
|
||||
"removed",
|
||||
`${body.name} (${body.x}, ${body.y}, ${body.z})`,
|
||||
body.id || NaN);
|
||||
});
|
||||
|
||||
it("unpacks plant_stage operations", () => {
|
||||
it("unpacks plant_stage operations: plants", () => {
|
||||
const resourceIndex = fakeResourceIndex();
|
||||
const plant = selectAllPlantPointers(resourceIndex)[1];
|
||||
expect(plant).toBeTruthy();
|
||||
|
||||
const result = unpackStep({
|
||||
step: resourceUpdate({
|
||||
resource_type: "Plant",
|
||||
resource_id: plant.body.id || -1,
|
||||
label: "plant_stage",
|
||||
value: "wilting"
|
||||
}), resourceIndex
|
||||
step: updateResource({
|
||||
kind: "resource",
|
||||
args: { resource_type: "Plant", resource_id: plant.body.id || -1 }
|
||||
},
|
||||
{ label: "plant_stage", value: "wilting" }),
|
||||
resourceIndex
|
||||
});
|
||||
const { body } = plant;
|
||||
const plantName = `${body.name} (${body.x}, ${body.y}, ${body.z})`;
|
||||
assertGoodness(result, "wilting", "wilting", plantName, body.id || NaN);
|
||||
});
|
||||
|
||||
it("unpacks unknown resource_update steps", () => {
|
||||
it("unpacks plant_stage operations: weeds", () => {
|
||||
const resourceIndex = fakeResourceIndex([fakeWeed()]);
|
||||
const weed = selectAllWeedPointers(resourceIndex)[1];
|
||||
expect(weed).toBeTruthy();
|
||||
|
||||
const result = unpackStep({
|
||||
step: resourceUpdate({}),
|
||||
step: updateResource({
|
||||
kind: "resource",
|
||||
args: { resource_type: "Weed", resource_id: weed.body.id || -1 }
|
||||
},
|
||||
{ label: "plant_stage", value: "removed" }),
|
||||
resourceIndex
|
||||
});
|
||||
const { body } = weed;
|
||||
const plantName = `${body.name} (${body.x}, ${body.y}, ${body.z})`;
|
||||
assertGoodness(result, "Removed", "removed", plantName, body.id || NaN);
|
||||
});
|
||||
|
||||
it("unpacks plant_stage operations: identifier", () => {
|
||||
const resourceIndex = fakeResourceIndex();
|
||||
const result = unpackStep({
|
||||
step: updateResource(
|
||||
{ kind: "identifier", args: { label: "var" } },
|
||||
{ label: "plant_stage", value: "removed" }),
|
||||
resourceIndex
|
||||
});
|
||||
assertGoodness(result, "Removed", "removed", "var", "var");
|
||||
});
|
||||
|
||||
it("unpacks unknown resource update_resource steps", () => {
|
||||
const result = unpackStep({
|
||||
step: updateResource(),
|
||||
resourceIndex: fakeResourceIndex()
|
||||
});
|
||||
assertGoodness(result, "some_attr = some_value", "some_value", "Other", 1);
|
||||
assertGoodness(result,
|
||||
"some_value", "some_value",
|
||||
"Other 1 some_attr", "some_attr");
|
||||
});
|
||||
|
||||
it("unpacks unknown identifier update_resource steps", () => {
|
||||
const result = unpackStep({
|
||||
step: updateResource({ kind: "identifier", args: { label: "var" } }),
|
||||
resourceIndex: fakeResourceIndex()
|
||||
});
|
||||
assertGoodness(result,
|
||||
"some_value", "some_value",
|
||||
"variable 0 some_attr", "some_attr");
|
||||
});
|
||||
});
|
||||
|
|
|
@ -2,7 +2,7 @@ import { Dictionary } from "farmbot";
|
|||
import { DropDownItem } from "../../../ui";
|
||||
import { ListBuilder } from "./interfaces";
|
||||
import { ResourceIndex } from "../../../resources/interfaces";
|
||||
import { ResourceUpdate } from "farmbot";
|
||||
import { UpdateResource } from "farmbot";
|
||||
import { selectAllTools } from "../../../resources/selectors";
|
||||
import {
|
||||
MOUNTED_TO,
|
||||
|
@ -27,16 +27,19 @@ const DEFAULT = "Default";
|
|||
const ACTION_LIST: Dictionary<ListBuilder> = {
|
||||
"Device": (i) => [DISMOUNT(), ...allToolsAsDDI(i)],
|
||||
"Plant": () => PLANT_OPTIONS(),
|
||||
"GenericPointer": () => POINT_OPTIONS,
|
||||
"Weed": () => POINT_OPTIONS,
|
||||
"GenericPointer": () => POINT_OPTIONS(),
|
||||
"Weed": () => POINT_OPTIONS(),
|
||||
[DEFAULT]: () => []
|
||||
};
|
||||
|
||||
const getList =
|
||||
(t = DEFAULT): ListBuilder => (ACTION_LIST[t] || ACTION_LIST[DEFAULT]);
|
||||
const getList = (t: string): ListBuilder =>
|
||||
(ACTION_LIST[t] || ACTION_LIST[DEFAULT]);
|
||||
|
||||
export const actionList = (d: DropDownItem | undefined,
|
||||
r: ResourceUpdate,
|
||||
export const actionList = (d: string | undefined,
|
||||
r: UpdateResource,
|
||||
i: ResourceIndex): DropDownItem[] => {
|
||||
return getList(d ? d.headingId : r.args.resource_type)(i);
|
||||
const resourceType = r.args.resource.kind == "identifier"
|
||||
? DEFAULT
|
||||
: r.args.resource.args.resource_type;
|
||||
return getList(d || resourceType)(i);
|
||||
};
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { ResourceUpdate } from "farmbot";
|
||||
import { UpdateResource } from "farmbot";
|
||||
import { editStep } from "../../../api/crud";
|
||||
import { packStep } from "./pack_step";
|
||||
import { MarkAsEditProps } from "./interfaces";
|
||||
|
@ -11,8 +11,10 @@ export const commitStepChanges = (p: MarkAsEditProps) => {
|
|||
step,
|
||||
index,
|
||||
sequence,
|
||||
executor(c: ResourceUpdate) {
|
||||
c.args = packStep(step, nextResource, nextAction).args;
|
||||
executor(c: UpdateResource) {
|
||||
const { args, body } = packStep(step, nextResource, nextAction);
|
||||
c.args = args;
|
||||
c.body = body;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
|
|
@ -8,7 +8,7 @@ export const DISMOUNT = (): DropDownItem =>
|
|||
({ label: t("Not Mounted"), value: 0 });
|
||||
|
||||
/** Legal "actions" for "Mark As.." block when marking Point resources */
|
||||
export const POINT_OPTIONS: DropDownItem[] = [
|
||||
export const POINT_OPTIONS = (): DropDownItem[] => [
|
||||
{ label: t("Removed"), value: "removed" },
|
||||
];
|
||||
|
||||
|
|
|
@ -1,25 +1,29 @@
|
|||
import { ResourceIndex } from "../../../resources/interfaces";
|
||||
import { DropDownItem } from "../../../ui";
|
||||
import { ResourceUpdate, TaggedSequence } from "farmbot";
|
||||
import { UpdateResource, TaggedSequence, Resource, Identifier } from "farmbot";
|
||||
|
||||
/** Function that converts resources into dropdown selections based on
|
||||
* use-case specific rules */
|
||||
export type ListBuilder = (i: ResourceIndex) => DropDownItem[];
|
||||
|
||||
/** Shape of step.args when step.kind = "resource_update" */
|
||||
export type ResourceUpdateArgs = Partial<ResourceUpdate["args"]>;
|
||||
|
||||
/** Input data for calls to commitStepChanges() */
|
||||
export interface MarkAsEditProps {
|
||||
nextAction: DropDownItem;
|
||||
nextResource: DropDownItem | undefined;
|
||||
step: ResourceUpdate;
|
||||
step: UpdateResource;
|
||||
index: number;
|
||||
sequence: TaggedSequence
|
||||
}
|
||||
|
||||
export interface StepWithResourceIndex {
|
||||
step: ResourceUpdate;
|
||||
export interface PackedStepWithResourceIndex {
|
||||
step: UpdateResource;
|
||||
resourceIndex: ResourceIndex;
|
||||
}
|
||||
|
||||
export interface UnpackedStepWithResourceIndex {
|
||||
resource: Resource | Identifier;
|
||||
field: string;
|
||||
value: string | number | boolean;
|
||||
resourceIndex: ResourceIndex;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { ResourceUpdate, resource_type as RESOURCE_TYPE } from "farmbot";
|
||||
import { UpdateResource, Resource, Identifier, resource_type } from "farmbot";
|
||||
import { DropDownItem } from "../../../ui";
|
||||
|
||||
/**
|
||||
|
@ -8,43 +8,54 @@ import { DropDownItem } from "../../../ui";
|
|||
* local changes as well as a copy of older data from the API.
|
||||
*
|
||||
* PROBLEM: You need to take the component's local state plus the
|
||||
* shape of the "resource_update" ("Mark As..") block and merge them
|
||||
* shape of the "update_resource" ("Mark As..") block and merge them
|
||||
* together so that you can render the form in the editor.
|
||||
*
|
||||
* SOLUTION: Use the celery node + pieces of the component's state (resourceDDI,
|
||||
* actionDDI) to properly populate dropdown menus and determine the
|
||||
* shape of the new "resource_update" step when it is saved.
|
||||
* shape of the new "update_resource" step when it is saved.
|
||||
* */
|
||||
export const packStep =
|
||||
(csNode: ResourceUpdate,
|
||||
resourceDDI: DropDownItem | undefined,
|
||||
actionDDI: DropDownItem): ResourceUpdate => {
|
||||
const resource_type = (resourceDDI ?
|
||||
resourceDDI.headingId : csNode.args.resource_type) as RESOURCE_TYPE;
|
||||
const resource_id = (resourceDDI ?
|
||||
resourceDDI.value : csNode.args.resource_id) as number;
|
||||
switch (resource_type) {
|
||||
export const packStep = (
|
||||
csNode: UpdateResource,
|
||||
resourceDDI: DropDownItem | undefined,
|
||||
actionDDI: DropDownItem,
|
||||
): UpdateResource => {
|
||||
const resource = resourceDDI?.headingId
|
||||
? resourceNode(resourceDDI.headingId, resourceDDI.value)
|
||||
: csNode.args.resource;
|
||||
if (resource.kind == "identifier") {
|
||||
return updateResource(resource, "plant_stage", actionDDI.value);
|
||||
} else {
|
||||
switch (resource.args.resource_type) {
|
||||
case "Device":
|
||||
/* Scenario I: Changing tool mount */
|
||||
return {
|
||||
kind: "resource_update",
|
||||
args: {
|
||||
resource_id,
|
||||
resource_type,
|
||||
label: "mounted_tool_id",
|
||||
value: actionDDI.value
|
||||
}
|
||||
};
|
||||
|
||||
return updateResource(resource, "mounted_tool_id", actionDDI.value);
|
||||
default:
|
||||
/* Scenario II: Changing a point */
|
||||
const label = "" +
|
||||
(actionDDI.value == "removed" ? "discarded_at" : "plant_stage");
|
||||
const value = "" +
|
||||
(label === "discarded_at" ? "{{ Time.now }}" : actionDDI.value);
|
||||
return {
|
||||
kind: "resource_update",
|
||||
args: { resource_id, resource_type, label, value }
|
||||
};
|
||||
return updateResource(resource, "plant_stage", actionDDI.value);
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
const resourceNode = (type: string, id: string | number): Resource => ({
|
||||
kind: "resource",
|
||||
args: {
|
||||
resource_type: type as resource_type,
|
||||
resource_id: parseInt("" + id),
|
||||
}
|
||||
});
|
||||
|
||||
const updateResource = (
|
||||
resource: Resource | Identifier,
|
||||
field: string,
|
||||
value: string | number,
|
||||
): UpdateResource => ({
|
||||
kind: "update_resource",
|
||||
args: { resource },
|
||||
body: [{
|
||||
kind: "pair", args: {
|
||||
label: field,
|
||||
value: value,
|
||||
}
|
||||
}]
|
||||
});
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
import { ResourceUpdate, TaggedSequence, resource_type } from "farmbot";
|
||||
import {
|
||||
UpdateResource, TaggedSequence, resource_type, Pair, Resource, Identifier,
|
||||
} from "farmbot";
|
||||
import {
|
||||
buildResourceIndex,
|
||||
} from "../../../__test_support__/resource_index_builder";
|
||||
|
@ -11,18 +13,26 @@ import {
|
|||
} from "../../../__test_support__/fake_state/resources";
|
||||
import { betterMerge } from "../../../util";
|
||||
import { MarkAs } from "../mark_as";
|
||||
import { ResourceUpdateArgs } from "./interfaces";
|
||||
|
||||
export function resourceUpdate(i: ResourceUpdateArgs): ResourceUpdate {
|
||||
export function updateResource(
|
||||
resource?: Resource | Identifier, pairArgs?: Pair["args"]): UpdateResource {
|
||||
return {
|
||||
kind: "resource_update",
|
||||
kind: "update_resource",
|
||||
args: {
|
||||
resource_type: "Other" as resource_type,
|
||||
resource_id: 1,
|
||||
label: "some_attr",
|
||||
value: "some_value",
|
||||
...i
|
||||
}
|
||||
resource: resource || {
|
||||
kind: "resource", args: {
|
||||
resource_type: "Other" as resource_type,
|
||||
resource_id: 1,
|
||||
}
|
||||
},
|
||||
},
|
||||
body: [{
|
||||
kind: "pair", args: {
|
||||
label: "some_attr",
|
||||
value: "some_value",
|
||||
...pairArgs,
|
||||
}
|
||||
}],
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -38,13 +48,14 @@ export const markAsResourceFixture = () => buildResourceIndex([
|
|||
export function fakeMarkAsProps() {
|
||||
const steps: TaggedSequence["body"]["body"] = [
|
||||
{
|
||||
kind: "resource_update",
|
||||
kind: "update_resource",
|
||||
args: {
|
||||
resource_type: "Device",
|
||||
resource_id: 0,
|
||||
label: "mounted_tool_id",
|
||||
value: 0
|
||||
}
|
||||
resource: {
|
||||
kind: "resource",
|
||||
args: { resource_id: 0, resource_type: "Device" }
|
||||
}
|
||||
},
|
||||
body: [{ kind: "pair", args: { label: "mounted_tool_id", value: 0 } }],
|
||||
},
|
||||
];
|
||||
const currentSequence: TaggedSequence =
|
|
@ -1,12 +1,17 @@
|
|||
import { DropDownItem } from "../../../ui";
|
||||
import {
|
||||
findToolById, findPointerByTypeAndId,
|
||||
findToolById,
|
||||
findPointerByTypeAndId,
|
||||
} from "../../../resources/selectors";
|
||||
import { point2ddi } from "./resource_list";
|
||||
import { MOUNTED_TO } from "./constants";
|
||||
import { DropDownPair, StepWithResourceIndex } from "./interfaces";
|
||||
import {
|
||||
DropDownPair, PackedStepWithResourceIndex, UnpackedStepWithResourceIndex,
|
||||
} from "./interfaces";
|
||||
import { t } from "../../../i18next_wrapper";
|
||||
import { PLANT_STAGE_DDI_LOOKUP } from "../../../farm_designer/plants/edit_plant_status";
|
||||
import {
|
||||
PLANT_STAGE_DDI_LOOKUP,
|
||||
} from "../../../farm_designer/plants/edit_plant_status";
|
||||
|
||||
export const TOOL_MOUNT = (): DropDownItem => ({
|
||||
label: t("Tool Mount"), value: "tool_mount"
|
||||
|
@ -17,14 +22,13 @@ export const DISMOUNTED = (): DropDownPair => ({
|
|||
rightSide: NOT_IN_USE()
|
||||
});
|
||||
const DEFAULT_TOOL_NAME = () => t("Untitled Tool");
|
||||
const REMOVED_ACTION = () => ({ label: t("Removed"), value: "removed" });
|
||||
|
||||
const mountedTo = (toolName = DEFAULT_TOOL_NAME()): DropDownItem =>
|
||||
({ label: `${MOUNTED_TO()} ${toolName}`, value: "mounted" });
|
||||
|
||||
/** The user wants to change the `mounted_tool_id` of their Device. */
|
||||
function mountTool(i: StepWithResourceIndex): DropDownPair {
|
||||
const { value } = i.step.args;
|
||||
function mountTool(i: UnpackedStepWithResourceIndex): DropDownPair {
|
||||
const { value } = i;
|
||||
if (typeof value === "number" && value > 0) {
|
||||
try { // Good tool id
|
||||
const tool = findToolById(i.resourceIndex, value as number);
|
||||
|
@ -41,33 +45,34 @@ function mountTool(i: StepWithResourceIndex): DropDownPair {
|
|||
/** When we can't properly guess the correct way to to render the screen,
|
||||
* possibly for legacy reasons or because the user wrote their CeleryScript by
|
||||
* hand. */
|
||||
function unknownOption(i: StepWithResourceIndex): DropDownPair {
|
||||
const { resource_type, resource_id, label, value } = i.step.args;
|
||||
|
||||
function unknownOption(i: UnpackedStepWithResourceIndex): DropDownPair {
|
||||
const { resource } = i;
|
||||
const resource_type =
|
||||
resource.kind == "resource" ? resource.args.resource_type : "variable";
|
||||
const resource_id =
|
||||
resource.kind == "resource" ? resource.args.resource_id : 0;
|
||||
const { field, value } = i;
|
||||
const leftLabel = `${resource_type} ${resource_id} ${field}`;
|
||||
return {
|
||||
leftSide: { label: resource_type, value: resource_id },
|
||||
rightSide: { label: `${label} = ${value}`, value: "" + value }
|
||||
};
|
||||
}
|
||||
|
||||
/** The user wants to mark a the `discarded_at` attribute of a Point. */
|
||||
function discardPoint(i: StepWithResourceIndex): DropDownPair {
|
||||
const { resource_id, resource_type } = i.step.args;
|
||||
const pointerBody =
|
||||
findPointerByTypeAndId(i.resourceIndex, resource_type, resource_id).body;
|
||||
return {
|
||||
leftSide: point2ddi(pointerBody),
|
||||
rightSide: REMOVED_ACTION(),
|
||||
leftSide: { label: leftLabel, value: field },
|
||||
rightSide: { label: "" + value, value: "" + value }
|
||||
};
|
||||
}
|
||||
|
||||
/** The user wants to mark a the `plant_stage` attribute of a Plant resource. */
|
||||
function plantStage(i: StepWithResourceIndex): DropDownPair {
|
||||
const { resource_id, resource_type, value } = i.step.args;
|
||||
const pointerBody =
|
||||
findPointerByTypeAndId(i.resourceIndex, resource_type, resource_id).body;
|
||||
function plantStage(i: UnpackedStepWithResourceIndex): DropDownPair {
|
||||
const { resource } = i;
|
||||
const resource_type =
|
||||
resource.kind == "resource" ? resource.args.resource_type : "";
|
||||
const resource_id =
|
||||
resource.kind == "resource" ? resource.args.resource_id : 0;
|
||||
const { value } = i;
|
||||
const leftSide = resource.kind == "resource"
|
||||
? point2ddi(findPointerByTypeAndId(
|
||||
i.resourceIndex, resource_type, resource_id).body)
|
||||
: { label: "" + resource.args.label, value: "" + resource.args.label };
|
||||
return {
|
||||
leftSide: point2ddi(pointerBody),
|
||||
leftSide,
|
||||
rightSide: PLANT_STAGE_DDI_LOOKUP()["" + value]
|
||||
|| { label: "" + value, value: "" + value },
|
||||
};
|
||||
|
@ -76,12 +81,14 @@ function plantStage(i: StepWithResourceIndex): DropDownPair {
|
|||
/** We can guess how the "Mark As.." UI will be rendered (left and right side
|
||||
* drop downs) based on the shape of the current step. There are several
|
||||
* strategies and this function will dispatch the appropriate one. */
|
||||
export function unpackStep(i: StepWithResourceIndex): DropDownPair {
|
||||
const { label } = i.step.args;
|
||||
switch (label) {
|
||||
case "mounted_tool_id": return mountTool(i);
|
||||
case "discarded_at": return discardPoint(i);
|
||||
case "plant_stage": return plantStage(i);
|
||||
default: return unknownOption(i);
|
||||
export function unpackStep(p: PackedStepWithResourceIndex): DropDownPair {
|
||||
const { resource } = p.step.args;
|
||||
const { label, value } = p.step.body?.[0]?.args || { label: "", value: "" };
|
||||
const field = label;
|
||||
const unpacked = { resourceIndex: p.resourceIndex, resource, field, value };
|
||||
switch (field) {
|
||||
case "mounted_tool_id": return mountTool(unpacked);
|
||||
case "plant_stage": return plantStage(unpacked);
|
||||
default: return unknownOption(unpacked);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
import * as React from "react";
|
||||
import { SequenceBodyItem as Step, SequenceBodyItem } from "farmbot";
|
||||
import {
|
||||
SequenceBodyItem as Step, SequenceBodyItem, LegalSequenceKind,
|
||||
} from "farmbot";
|
||||
import { StepTitleBarProps } from "../interfaces";
|
||||
import { BlurableInput } from "../../ui/index";
|
||||
import { updateStepTitle } from "./index";
|
||||
|
@ -19,7 +21,8 @@ function translate(input: Step): string {
|
|||
"read_pin": t("Read Sensor"),
|
||||
"send_message": t("Send Message"),
|
||||
"take_photo": t("Take a Photo"),
|
||||
"resource_update": t("Mark As"),
|
||||
"update_resource": t("Mark As"),
|
||||
["resource_update" as LegalSequenceKind]: t("Deprecated Mark As"),
|
||||
"assertion": t("Assertion"),
|
||||
"set_servo_angle": t("Control Servo"),
|
||||
"wait": t("Wait"),
|
||||
|
|
|
@ -0,0 +1,61 @@
|
|||
import * as React from "react";
|
||||
import { StepParams } from "../interfaces";
|
||||
import { ToolTips } from "../../constants";
|
||||
import { StepWrapper, StepHeader, StepContent } from "../step_ui/index";
|
||||
import { editStep } from "../../api/crud";
|
||||
import { SequenceBodyItem, LegalArgString } from "farmbot";
|
||||
import { Feature } from "../../devices/interfaces";
|
||||
import { trim } from "../../util";
|
||||
|
||||
const convertOldMarkAs = (oldStep: SequenceBodyItem) =>
|
||||
(step: SequenceBodyItem) => {
|
||||
const stepArgs = oldStep.args as Record<LegalArgString, string>;
|
||||
step.kind = "update_resource";
|
||||
step.args = {
|
||||
resource: {
|
||||
kind: "resource", args: {
|
||||
resource_type: stepArgs.resource_type,
|
||||
resource_id: stepArgs.resource_id,
|
||||
}
|
||||
}
|
||||
};
|
||||
const field = stepArgs.label;
|
||||
step.body = [{
|
||||
kind: "pair", args: {
|
||||
label: field == "discarded_at" ? "plant_stage" : field,
|
||||
value: field == "discarded_at" ? "removed" : stepArgs.value,
|
||||
}
|
||||
}];
|
||||
};
|
||||
|
||||
export function TileOldMarkAs(props: StepParams) {
|
||||
const { dispatch, currentStep, index, currentSequence } = props;
|
||||
const oldStepArgs = currentStep.args as Record<LegalArgString, string>;
|
||||
const className = "update-resource-step";
|
||||
return <StepWrapper>
|
||||
<StepHeader
|
||||
className={className}
|
||||
helpText={ToolTips.MARK_AS}
|
||||
currentSequence={currentSequence}
|
||||
currentStep={currentStep}
|
||||
dispatch={dispatch}
|
||||
index={index}
|
||||
confirmStepDeletion={props.confirmStepDeletion} />
|
||||
<StepContent className={className}>
|
||||
<p>{trim(`Mark ${oldStepArgs.resource_type} ${oldStepArgs.resource_id}
|
||||
${oldStepArgs.label} as ${oldStepArgs.value}`)}</p>
|
||||
<hr />
|
||||
<p>{"This step has been deprecated."}</p>
|
||||
{props.shouldDisplay?.(Feature.update_resource) &&
|
||||
<button className="fb-button yellow" style={{ float: "none" }}
|
||||
onClick={() => props.dispatch(editStep({
|
||||
step: props.currentStep,
|
||||
sequence: props.currentSequence,
|
||||
index: props.index,
|
||||
executor: convertOldMarkAs(props.currentStep),
|
||||
}))}>
|
||||
{"convert"}
|
||||
</button>}
|
||||
</StepContent>
|
||||
</StepWrapper>;
|
||||
}
|
|
@ -45,7 +45,7 @@
|
|||
"coveralls": "3.0.11",
|
||||
"enzyme": "3.11.0",
|
||||
"enzyme-adapter-react-16": "1.15.2",
|
||||
"farmbot": "9.2.3",
|
||||
"farmbot": "10.0.0-rc1",
|
||||
"i18next": "19.4.1",
|
||||
"install": "0.13.0",
|
||||
"lodash": "4.17.15",
|
||||
|
|
Loading…
Reference in New Issue