tools panel updates
parent
b1c2b36a37
commit
ec878e0dae
|
@ -640,6 +640,9 @@
|
|||
|
||||
.add-tool-panel-content,
|
||||
.edit-tool-panel-content {
|
||||
max-height: calc(100vh - 14rem);
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
button {
|
||||
display: block;
|
||||
margin-left: auto;
|
||||
|
@ -687,6 +690,7 @@
|
|||
}
|
||||
}
|
||||
button {
|
||||
margin-bottom: 2rem;
|
||||
.fa-plus {
|
||||
margin-right: 0.5rem;
|
||||
}
|
||||
|
|
|
@ -26,9 +26,6 @@ const NO_TMC = ["arduino", "farmduino", "farmduino_k14"];
|
|||
export const isTMCBoard = (firmwareHardware: FirmwareHardware | undefined) =>
|
||||
!firmwareHardware || !NO_TMC.includes(firmwareHardware);
|
||||
|
||||
export const isExpressBoard = (firmwareHardware: FirmwareHardware | undefined) =>
|
||||
!!(firmwareHardware && EXPRESS_BOARDS.includes(firmwareHardware));
|
||||
|
||||
export const hasButtons = (firmwareHardware: FirmwareHardware | undefined) =>
|
||||
!firmwareHardware || !NO_BUTTONS.includes(firmwareHardware);
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@ import { Color } from "../../../../../ui/index";
|
|||
import {
|
||||
fakeMapTransformProps,
|
||||
} from "../../../../../__test_support__/map_transform_props";
|
||||
import { svgMount } from "../../../../../__test_support__/svg_mount";
|
||||
|
||||
describe("<BotFigure/>", () => {
|
||||
const fakeProps = (): BotFigureProps => ({
|
||||
|
@ -35,7 +36,7 @@ describe("<BotFigure/>", () => {
|
|||
p.mapTransformProps.quadrant = quadrant;
|
||||
p.mapTransformProps.xySwap = xySwap;
|
||||
p.figureName = figureName;
|
||||
const result = shallow<BotFigure>(<BotFigure {...p} />);
|
||||
const result = svgMount(<BotFigure {...p} />);
|
||||
|
||||
const expectedGantryProps = expect.objectContaining({
|
||||
id: "gantry",
|
||||
|
@ -65,7 +66,7 @@ describe("<BotFigure/>", () => {
|
|||
const p = fakeProps();
|
||||
p.mapTransformProps.quadrant = 2;
|
||||
p.position = { x: 100, y: 200, z: 0 };
|
||||
const result = shallow<BotFigure>(<BotFigure {...p} />);
|
||||
const result = svgMount(<BotFigure {...p} />);
|
||||
const gantry = result.find("#gantry");
|
||||
expect(gantry.length).toEqual(1);
|
||||
expect(gantry.props().x).toEqual(90);
|
||||
|
@ -77,7 +78,7 @@ describe("<BotFigure/>", () => {
|
|||
it("changes color on e-stop", () => {
|
||||
const p = fakeProps();
|
||||
p.eStopStatus = true;
|
||||
const wrapper = shallow<BotFigure>(<BotFigure {...p} />);
|
||||
const wrapper = svgMount(<BotFigure {...p} />);
|
||||
expect(wrapper.find("#gantry").props().fill).toEqual(Color.virtualRed);
|
||||
});
|
||||
|
||||
|
@ -118,7 +119,7 @@ describe("<BotFigure/>", () => {
|
|||
it("shows mounted tool", () => {
|
||||
const p = fakeProps();
|
||||
p.mountedToolName = "Seeder";
|
||||
const wrapper = shallow<BotFigure>(<BotFigure {...p} />);
|
||||
const wrapper = svgMount(<BotFigure {...p} />);
|
||||
expect(wrapper.find("#UTM-wrapper").find("#mounted-tool").length)
|
||||
.toEqual(1);
|
||||
});
|
||||
|
|
|
@ -303,7 +303,6 @@ describe("<ToolSlotSVG />", () => {
|
|||
const fakeProps = (): ToolSlotSVGProps => ({
|
||||
toolSlot: fakeToolSlot(),
|
||||
toolName: "seeder",
|
||||
renderRotation: false,
|
||||
xySwap: false,
|
||||
quadrant: 2,
|
||||
});
|
||||
|
|
|
@ -341,13 +341,12 @@ const SeedTrough = (props: ToolGraphicProps) => {
|
|||
export interface ToolSlotSVGProps {
|
||||
toolSlot: TaggedToolSlotPointer;
|
||||
toolName: string | undefined;
|
||||
renderRotation: boolean;
|
||||
xySwap?: boolean;
|
||||
quadrant?: BotOriginQuadrant;
|
||||
}
|
||||
|
||||
export const ToolSlotSVG = (props: ToolSlotSVGProps) => {
|
||||
const xySwap = props.renderRotation ? !!props.xySwap : false;
|
||||
const xySwap = !!props.xySwap;
|
||||
const toolProps = {
|
||||
x: 0, y: 0,
|
||||
hovered: false,
|
||||
|
@ -355,13 +354,11 @@ export const ToolSlotSVG = (props: ToolSlotSVGProps) => {
|
|||
uuid: props.toolSlot.uuid,
|
||||
xySwap,
|
||||
};
|
||||
const pulloutDirection = props.renderRotation
|
||||
? props.toolSlot.body.pullout_direction
|
||||
: ToolPulloutDirection.POSITIVE_X;
|
||||
const quadrant = props.renderRotation && props.quadrant ? props.quadrant : 2;
|
||||
const viewBox = props.renderRotation ? "-25 0 50 1" : "-25 0 50 1";
|
||||
const pulloutDirection = props.toolSlot.body.pullout_direction
|
||||
|| ToolPulloutDirection.POSITIVE_X;
|
||||
const quadrant = props.quadrant || 2;
|
||||
return props.toolSlot.body.gantry_mounted
|
||||
? <svg width="3rem" height="3rem" viewBox={viewBox}>
|
||||
? <svg width="3rem" height="3rem" viewBox={"-25 0 50 1"}>
|
||||
<GantryToolSlot x={0} y={0} xySwap={xySwap} />
|
||||
{props.toolSlot.body.tool_id &&
|
||||
<Tool tool={reduceToolName(props.toolName)} toolProps={toolProps} />}
|
||||
|
@ -369,7 +366,7 @@ export const ToolSlotSVG = (props: ToolSlotSVGProps) => {
|
|||
: <svg width="3rem" height="3rem" viewBox={`-50 0 100 1`}>
|
||||
{props.toolSlot.body.pullout_direction &&
|
||||
<ToolbaySlot
|
||||
id={props.toolSlot.body.id}
|
||||
id={-(props.toolSlot.body.id || 1)}
|
||||
x={0}
|
||||
y={0}
|
||||
pulloutDirection={pulloutDirection}
|
||||
|
|
|
@ -51,7 +51,7 @@ export const ToolSlotPoint = (props: TSPProps) => {
|
|||
onClick={() => history.push(`/app/designer/tool-slots/${id}`)}>
|
||||
{pullout_direction && !gantry_mounted &&
|
||||
<ToolbaySlot
|
||||
id={-(id || 1)}
|
||||
id={id}
|
||||
x={qx}
|
||||
y={qy}
|
||||
pulloutDirection={pullout_direction}
|
||||
|
|
|
@ -21,7 +21,8 @@ import { init, save, edit, destroy } from "../../../api/crud";
|
|||
import { history } from "../../../history";
|
||||
import { SpecialStatus } from "farmbot";
|
||||
import { ToolPulloutDirection } from "farmbot/dist/resources/api_resources";
|
||||
import { AddToolSlotProps, mapStateToPropsAdd } from "../map_to_props_add_edit";
|
||||
import { mapStateToPropsAdd } from "../state_to_props";
|
||||
import { AddToolSlotProps } from "../interfaces";
|
||||
|
||||
describe("<AddToolSlot />", () => {
|
||||
const fakeProps = (): AddToolSlotProps => ({
|
||||
|
@ -39,7 +40,7 @@ describe("<AddToolSlot />", () => {
|
|||
it("renders", () => {
|
||||
const wrapper = mount(<AddToolSlot {...fakeProps()} />);
|
||||
["add new slot", "x (mm)", "y (mm)", "z (mm)", "tool or seed container",
|
||||
"change direction", "gantry-mounted",
|
||||
"direction", "gantry-mounted",
|
||||
].map(string => expect(wrapper.text().toLowerCase()).toContain(string));
|
||||
expect(init).toHaveBeenCalledWith("Point", {
|
||||
pointer_type: "ToolSlot", name: "Slot", radius: 0, meta: {},
|
||||
|
|
|
@ -4,14 +4,13 @@ jest.mock("../../../history", () => ({ history: { push: jest.fn() } }));
|
|||
|
||||
import * as React from "react";
|
||||
import { mount, shallow } from "enzyme";
|
||||
import {
|
||||
RawAddTool as AddTool, AddToolProps, mapStateToProps,
|
||||
} from "../add_tool";
|
||||
import { RawAddTool as AddTool, mapStateToProps } from "../add_tool";
|
||||
import { fakeState } from "../../../__test_support__/fake_state";
|
||||
import { SaveBtn } from "../../../ui";
|
||||
import { initSave } from "../../../api/crud";
|
||||
import { history } from "../../../history";
|
||||
import { FirmwareHardware } from "farmbot";
|
||||
import { AddToolProps } from "../interfaces";
|
||||
|
||||
describe("<AddTool />", () => {
|
||||
const fakeProps = (): AddToolProps => ({
|
||||
|
@ -90,6 +89,22 @@ describe("<AddTool />", () => {
|
|||
wrapper.find("input").last().simulate("change");
|
||||
expect(wrapper.state().toAdd).toEqual(["Seed Trough 2"]);
|
||||
});
|
||||
|
||||
it("disables when all already added", () => {
|
||||
const p = fakeProps();
|
||||
p.firmwareHardware = "express_k10";
|
||||
p.existingToolNames = ["Seed Trough 1", "Seed Trough 2"];
|
||||
const wrapper = mount<AddTool>(<AddTool {...p} />);
|
||||
expect(wrapper.find("button").last().hasClass("pseudo-disabled"))
|
||||
.toBeTruthy();
|
||||
});
|
||||
|
||||
it("hides when none firmware is selected", () => {
|
||||
const p = fakeProps();
|
||||
p.firmwareHardware = "none";
|
||||
const wrapper = mount<AddTool>(<AddTool {...p} />);
|
||||
expect(wrapper.find(".add-stock-tools").props().hidden).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
describe("mapStateToProps()", () => {
|
||||
|
|
|
@ -18,10 +18,9 @@ import {
|
|||
buildResourceIndex,
|
||||
} from "../../../__test_support__/resource_index_builder";
|
||||
import { destroy, edit, save } from "../../../api/crud";
|
||||
import {
|
||||
EditToolSlotProps, mapStateToPropsEdit,
|
||||
} from "../map_to_props_add_edit";
|
||||
import { mapStateToPropsEdit } from "../state_to_props";
|
||||
import { SlotEditRows } from "../tool_slot_edit_components";
|
||||
import { EditToolSlotProps } from "../interfaces";
|
||||
|
||||
describe("<EditToolSlot />", () => {
|
||||
const fakeProps = (): EditToolSlotProps => ({
|
||||
|
@ -46,7 +45,7 @@ describe("<EditToolSlot />", () => {
|
|||
p.findToolSlot = () => fakeToolSlot();
|
||||
const wrapper = mount(<EditToolSlot {...p} />);
|
||||
["edit slot", "x (mm)", "y (mm)", "z (mm)", "tool or seed container",
|
||||
"change direction", "gantry-mounted",
|
||||
"direction", "gantry-mounted",
|
||||
].map(string => expect(wrapper.text().toLowerCase()).toContain(string));
|
||||
});
|
||||
|
||||
|
|
|
@ -13,9 +13,11 @@ jest.mock("../../../history", () => ({
|
|||
import * as React from "react";
|
||||
import { mount, shallow } from "enzyme";
|
||||
import {
|
||||
RawEditTool as EditTool, EditToolProps, mapStateToProps, isActive,
|
||||
RawEditTool as EditTool, mapStateToProps, isActive,
|
||||
} from "../edit_tool";
|
||||
import { fakeTool, fakeToolSlot } from "../../../__test_support__/fake_state/resources";
|
||||
import {
|
||||
fakeTool, fakeToolSlot,
|
||||
} from "../../../__test_support__/fake_state/resources";
|
||||
import { fakeState } from "../../../__test_support__/fake_state";
|
||||
import {
|
||||
buildResourceIndex, fakeDevice,
|
||||
|
@ -24,6 +26,7 @@ import { SaveBtn } from "../../../ui";
|
|||
import { history } from "../../../history";
|
||||
import { edit, destroy } from "../../../api/crud";
|
||||
import { clickButton } from "../../../__test_support__/helpers";
|
||||
import { EditToolProps } from "../interfaces";
|
||||
|
||||
describe("<EditTool />", () => {
|
||||
beforeEach(() => {
|
||||
|
|
|
@ -14,22 +14,20 @@ jest.mock("../../../device", () => ({ getDevice: () => mockDevice }));
|
|||
import * as React from "react";
|
||||
import { mount, shallow } from "enzyme";
|
||||
import {
|
||||
RawTools as Tools, ToolsProps, mapStateToProps,
|
||||
RawTools as Tools,
|
||||
ToolSlotInventoryItem, ToolSlotInventoryItemProps,
|
||||
} from "../index";
|
||||
import {
|
||||
fakeTool, fakeToolSlot, fakeSensor,
|
||||
} from "../../../__test_support__/fake_state/resources";
|
||||
import { history } from "../../../history";
|
||||
import { fakeState } from "../../../__test_support__/fake_state";
|
||||
import {
|
||||
buildResourceIndex, fakeDevice,
|
||||
} from "../../../__test_support__/resource_index_builder";
|
||||
import { fakeDevice } from "../../../__test_support__/resource_index_builder";
|
||||
import { bot } from "../../../__test_support__/fake_state/bot";
|
||||
import { error } from "../../../toast/toast";
|
||||
import { Content, Actions } from "../../../constants";
|
||||
import { edit, save } from "../../../api/crud";
|
||||
import { ToolSelection } from "../tool_slot_edit_components";
|
||||
import { ToolsProps } from "../interfaces";
|
||||
|
||||
describe("<Tools />", () => {
|
||||
const fakeProps = (): ToolsProps => ({
|
||||
|
@ -43,6 +41,8 @@ describe("<Tools />", () => {
|
|||
hoveredToolSlot: undefined,
|
||||
firmwareHardware: undefined,
|
||||
isActive: jest.fn(),
|
||||
xySwap: false,
|
||||
quadrant: 2,
|
||||
});
|
||||
|
||||
it("renders with no tools", () => {
|
||||
|
@ -225,6 +225,8 @@ describe("<ToolSlotInventoryItem />", () => {
|
|||
hovered: false,
|
||||
dispatch: jest.fn(),
|
||||
isActive: jest.fn(),
|
||||
xySwap: false,
|
||||
quadrant: 2,
|
||||
});
|
||||
|
||||
it("changes tool", () => {
|
||||
|
@ -242,14 +244,3 @@ describe("<ToolSlotInventoryItem />", () => {
|
|||
expect(e.stopPropagation).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe("mapStateToProps()", () => {
|
||||
it("returns props", () => {
|
||||
const state = fakeState();
|
||||
const tool = fakeTool();
|
||||
tool.body.id = 1;
|
||||
state.resources = buildResourceIndex([tool, fakeDevice()]);
|
||||
const props = mapStateToProps(state);
|
||||
expect(props.findTool(tool.body.id)).toEqual(tool);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
import { fakeState } from "../../../__test_support__/fake_state";
|
||||
import {
|
||||
fakeWebAppConfig, fakeTool,
|
||||
} from "../../../__test_support__/fake_state/resources";
|
||||
import {
|
||||
buildResourceIndex, fakeDevice,
|
||||
} from "../../../__test_support__/resource_index_builder";
|
||||
import { mapStateToProps } from "../state_to_props";
|
||||
|
||||
describe("mapStateToProps()", () => {
|
||||
it("returns props", () => {
|
||||
const state = fakeState();
|
||||
const webAppConfig = fakeWebAppConfig();
|
||||
webAppConfig.body.bot_origin_quadrant = 1;
|
||||
state.resources = buildResourceIndex([fakeDevice(), webAppConfig]);
|
||||
const props = mapStateToProps(state);
|
||||
expect(props.quadrant).toEqual(1);
|
||||
});
|
||||
|
||||
it("returns props: incorrect quadrant", () => {
|
||||
const state = fakeState();
|
||||
const tool = fakeTool();
|
||||
tool.body.id = 1;
|
||||
const webAppConfig = fakeWebAppConfig();
|
||||
webAppConfig.body.bot_origin_quadrant = 10;
|
||||
state.resources = buildResourceIndex([tool, fakeDevice(), webAppConfig]);
|
||||
const props = mapStateToProps(state);
|
||||
expect(props.findTool(tool.body.id)).toEqual(tool);
|
||||
expect(props.quadrant).toEqual(2);
|
||||
});
|
||||
});
|
|
@ -7,8 +7,11 @@ import {
|
|||
SlotLocationInputRow, SlotLocationInputRowProps,
|
||||
ToolSelection, ToolSelectionProps, SlotEditRows, SlotEditRowsProps,
|
||||
} from "../tool_slot_edit_components";
|
||||
import { fakeTool, fakeToolSlot } from "../../../__test_support__/fake_state/resources";
|
||||
import {
|
||||
fakeTool, fakeToolSlot,
|
||||
} from "../../../__test_support__/fake_state/resources";
|
||||
import { FBSelect, NULL_CHOICE } from "../../../ui";
|
||||
import { ToolPulloutDirection } from "farmbot/dist/resources/api_resources";
|
||||
|
||||
describe("<GantryMountedInput />", () => {
|
||||
const fakeProps = (): GantryMountedInputProps => ({
|
||||
|
@ -35,9 +38,18 @@ describe("<SlotDirectionInputRow />", () => {
|
|||
onChange: jest.fn(),
|
||||
});
|
||||
|
||||
it("renders", () => {
|
||||
const wrapper = mount(<SlotDirectionInputRow {...fakeProps()} />);
|
||||
expect(wrapper.text().toLowerCase()).toContain("change direction");
|
||||
it.each<[ToolPulloutDirection, string]>([
|
||||
[ToolPulloutDirection.NONE, "fa-dot-circle-o"],
|
||||
[ToolPulloutDirection.POSITIVE_X, "fa-arrow-circle-right"],
|
||||
[ToolPulloutDirection.NEGATIVE_X, "fa-arrow-circle-left"],
|
||||
[ToolPulloutDirection.POSITIVE_Y, "fa-arrow-circle-up"],
|
||||
[ToolPulloutDirection.NEGATIVE_Y, "fa-arrow-circle-down"],
|
||||
])("renders: direction %s", (toolPulloutDirection, expected) => {
|
||||
const p = fakeProps();
|
||||
p.toolPulloutDirection = toolPulloutDirection;
|
||||
const wrapper = mount(<SlotDirectionInputRow {...p} />);
|
||||
expect(wrapper.text().toLowerCase()).toContain("direction");
|
||||
expect(wrapper.find("i").first().hasClass(expected)).toBeTruthy();
|
||||
});
|
||||
|
||||
it("changes value by click", () => {
|
||||
|
@ -47,6 +59,14 @@ describe("<SlotDirectionInputRow />", () => {
|
|||
expect(p.onChange).toHaveBeenCalledWith({ pullout_direction: 1 });
|
||||
});
|
||||
|
||||
it("changes value by click: handles rollover", () => {
|
||||
const p = fakeProps();
|
||||
p.toolPulloutDirection = ToolPulloutDirection.NEGATIVE_Y;
|
||||
const wrapper = shallow(<SlotDirectionInputRow {...p} />);
|
||||
wrapper.find("i").first().simulate("click");
|
||||
expect(p.onChange).toHaveBeenCalledWith({ pullout_direction: 0 });
|
||||
});
|
||||
|
||||
it("changes value by selection", () => {
|
||||
const p = fakeProps();
|
||||
const wrapper = shallow(<SlotDirectionInputRow {...p} />);
|
||||
|
@ -72,7 +92,8 @@ describe("<ToolSelection />", () => {
|
|||
|
||||
it("handles missing tool data", () => {
|
||||
const p = fakeProps();
|
||||
p.filterSelectedTool = true;
|
||||
p.filterActiveTools = false;
|
||||
p.filterSelectedTool = false;
|
||||
const tool = fakeTool();
|
||||
tool.body.name = undefined;
|
||||
tool.body.id = undefined;
|
||||
|
@ -111,7 +132,7 @@ describe("<ToolInputRow />", () => {
|
|||
tools: [],
|
||||
selectedTool: undefined,
|
||||
onChange: jest.fn(),
|
||||
isExpress: false,
|
||||
noUTM: false,
|
||||
isActive: jest.fn(),
|
||||
});
|
||||
|
||||
|
@ -129,7 +150,7 @@ describe("<ToolInputRow />", () => {
|
|||
|
||||
it("renders for express bots", () => {
|
||||
const p = fakeProps();
|
||||
p.isExpress = true;
|
||||
p.noUTM = true;
|
||||
const wrapper = mount(<ToolInputRow {...p} />);
|
||||
expect(wrapper.text().toLowerCase()).toContain("seed container");
|
||||
});
|
||||
|
@ -196,7 +217,7 @@ describe("<SlotEditRows />", () => {
|
|||
tool: undefined,
|
||||
botPosition: { x: undefined, y: undefined, z: undefined },
|
||||
updateToolSlot: jest.fn(),
|
||||
isExpress: false,
|
||||
noUTM: false,
|
||||
xySwap: false,
|
||||
quadrant: 2,
|
||||
isActive: () => false,
|
||||
|
|
|
@ -6,7 +6,7 @@ import {
|
|||
import { Everything } from "../../interfaces";
|
||||
import { t } from "../../i18next_wrapper";
|
||||
import { SaveBtn } from "../../ui";
|
||||
import { SpecialStatus, FirmwareHardware } from "farmbot";
|
||||
import { SpecialStatus } from "farmbot";
|
||||
import { initSave } from "../../api/crud";
|
||||
import { Panel } from "../panel_header";
|
||||
import { history } from "../../history";
|
||||
|
@ -17,17 +17,7 @@ import {
|
|||
} from "../../devices/components/firmware_hardware_support";
|
||||
import { getFbosConfig } from "../../resources/getters";
|
||||
import { ToolSVG } from "../map/layers/tool_slots/tool_graphics";
|
||||
|
||||
export interface AddToolProps {
|
||||
dispatch: Function;
|
||||
existingToolNames: string[];
|
||||
firmwareHardware: FirmwareHardware | undefined;
|
||||
}
|
||||
|
||||
export interface AddToolState {
|
||||
toolName: string;
|
||||
toAdd: string[];
|
||||
}
|
||||
import { AddToolProps, AddToolState } from "./interfaces";
|
||||
|
||||
export const mapStateToProps = (props: Everything): AddToolProps => ({
|
||||
dispatch: props.dispatch,
|
||||
|
@ -107,8 +97,10 @@ export class RawAddTool extends React.Component<AddToolProps, AddToolState> {
|
|||
</div>;
|
||||
}
|
||||
|
||||
AddStockTools = () =>
|
||||
<div className="add-stock-tools">
|
||||
AddStockTools = () => {
|
||||
const add = this.state.toAdd.filter(this.filterExisting);
|
||||
return <div className="add-stock-tools"
|
||||
hidden={this.props.firmwareHardware == "none"}>
|
||||
<label>{t("stock names")}</label>
|
||||
<ul>
|
||||
{this.stockToolNames().map(n =>
|
||||
|
@ -118,17 +110,17 @@ export class RawAddTool extends React.Component<AddToolProps, AddToolState> {
|
|||
</li>)}
|
||||
</ul>
|
||||
<button
|
||||
className="fb-button green"
|
||||
title={t("add selected stock names")}
|
||||
className={`fb-button green ${add.length > 0 ? "" : "pseudo-disabled"}`}
|
||||
title={add.length > 0 ? t("Add selected") : t("None to add")}
|
||||
onClick={() => {
|
||||
this.state.toAdd.filter(this.filterExisting)
|
||||
.map(n => this.newTool(n));
|
||||
add.map(n => this.newTool(n));
|
||||
history.push("/app/designer/tools");
|
||||
}}>
|
||||
<i className="fa fa-plus" />
|
||||
{t("selected")}
|
||||
</button>
|
||||
</div>
|
||||
</div>;
|
||||
}
|
||||
|
||||
render() {
|
||||
const panelName = "add-tool";
|
||||
|
|
|
@ -11,15 +11,9 @@ import { Panel } from "../panel_header";
|
|||
import { ToolPulloutDirection } from "farmbot/dist/resources/api_resources";
|
||||
import { history } from "../../history";
|
||||
import { SlotEditRows } from "./tool_slot_edit_components";
|
||||
import { UUID } from "../../resources/interfaces";
|
||||
import {
|
||||
isExpressBoard,
|
||||
} from "../../devices/components/firmware_hardware_support";
|
||||
import { AddToolSlotProps, mapStateToPropsAdd } from "./map_to_props_add_edit";
|
||||
|
||||
export interface AddToolSlotState {
|
||||
uuid: UUID | undefined;
|
||||
}
|
||||
import { hasUTM } from "../../devices/components/firmware_hardware_support";
|
||||
import { mapStateToPropsAdd } from "./state_to_props";
|
||||
import { AddToolSlotState, AddToolSlotProps } from "./interfaces";
|
||||
|
||||
export class RawAddToolSlot
|
||||
extends React.Component<AddToolSlotProps, AddToolSlotState> {
|
||||
|
@ -30,7 +24,7 @@ export class RawAddToolSlot
|
|||
pointer_type: "ToolSlot", name: t("Slot"), radius: 0, meta: {},
|
||||
x: 0, y: 0, z: 0, tool_id: undefined,
|
||||
pullout_direction: ToolPulloutDirection.NONE,
|
||||
gantry_mounted: isExpressBoard(this.props.firmwareHardware) ? true : false,
|
||||
gantry_mounted: !hasUTM(this.props.firmwareHardware) ? true : false,
|
||||
});
|
||||
this.setState({ uuid: action.payload.uuid });
|
||||
this.props.dispatch(action);
|
||||
|
@ -74,7 +68,7 @@ export class RawAddToolSlot
|
|||
<DesignerPanelContent panelName={panelName}>
|
||||
{this.toolSlot
|
||||
? <SlotEditRows
|
||||
isExpress={isExpressBoard(this.props.firmwareHardware)}
|
||||
noUTM={!hasUTM(this.props.firmwareHardware)}
|
||||
toolSlot={this.toolSlot}
|
||||
tools={this.props.tools}
|
||||
tool={this.tool}
|
||||
|
|
|
@ -16,22 +16,12 @@ import { history } from "../../history";
|
|||
import { Panel } from "../panel_header";
|
||||
import { ToolSVG } from "../map/layers/tool_slots/tool_graphics";
|
||||
import { error } from "../../toast/toast";
|
||||
import { EditToolProps, EditToolState } from "./interfaces";
|
||||
|
||||
export const isActive = (toolSlots: TaggedToolSlotPointer[]) =>
|
||||
(toolId: number | undefined) =>
|
||||
!!(toolId && toolSlots.map(x => x.body.tool_id).includes(toolId));
|
||||
|
||||
export interface EditToolProps {
|
||||
findTool(id: string): TaggedTool | undefined;
|
||||
dispatch: Function;
|
||||
mountedToolId: number | undefined;
|
||||
isActive(id: number | undefined): boolean;
|
||||
}
|
||||
|
||||
export interface EditToolState {
|
||||
toolName: string;
|
||||
}
|
||||
|
||||
export const mapStateToProps = (props: Everything): EditToolProps => ({
|
||||
findTool: (id: string) =>
|
||||
maybeFindToolById(props.resources.index, parseInt(id)),
|
||||
|
|
|
@ -11,10 +11,9 @@ import { history } from "../../history";
|
|||
import { Panel } from "../panel_header";
|
||||
import { SlotEditRows } from "./tool_slot_edit_components";
|
||||
import { moveAbs } from "../../devices/actions";
|
||||
import {
|
||||
isExpressBoard,
|
||||
} from "../../devices/components/firmware_hardware_support";
|
||||
import { EditToolSlotProps, mapStateToPropsEdit } from "./map_to_props_add_edit";
|
||||
import { hasUTM } from "../../devices/components/firmware_hardware_support";
|
||||
import { mapStateToPropsEdit } from "./state_to_props";
|
||||
import { EditToolSlotProps } from "./interfaces";
|
||||
|
||||
export class RawEditToolSlot extends React.Component<EditToolSlotProps> {
|
||||
|
||||
|
@ -44,7 +43,7 @@ export class RawEditToolSlot extends React.Component<EditToolSlotProps> {
|
|||
{toolSlot
|
||||
? <div className={"edit-tool-slot-content-wrapper"}>
|
||||
<SlotEditRows
|
||||
isExpress={isExpressBoard(this.props.firmwareHardware)}
|
||||
noUTM={!hasUTM(this.props.firmwareHardware)}
|
||||
toolSlot={toolSlot}
|
||||
tools={this.props.tools}
|
||||
tool={this.tool}
|
||||
|
|
|
@ -3,21 +3,12 @@ import { connect } from "react-redux";
|
|||
import {
|
||||
DesignerPanel, DesignerPanelTop, DesignerPanelContent,
|
||||
} from "../designer_panel";
|
||||
import { Everything } from "../../interfaces";
|
||||
import { DesignerNavTabs, Panel, TAB_COLOR } from "../panel_header";
|
||||
import {
|
||||
EmptyStateWrapper, EmptyStateGraphic,
|
||||
} from "../../ui/empty_state_wrapper";
|
||||
import { t } from "../../i18next_wrapper";
|
||||
import {
|
||||
TaggedTool, TaggedToolSlotPointer, TaggedDevice, TaggedSensor,
|
||||
FirmwareHardware,
|
||||
} from "farmbot";
|
||||
import {
|
||||
selectAllTools, selectAllToolSlotPointers, getDeviceAccountSettings,
|
||||
maybeFindToolById,
|
||||
selectAllSensors,
|
||||
} from "../../resources/selectors";
|
||||
import { TaggedTool, TaggedToolSlotPointer, TaggedSensor } from "farmbot";
|
||||
import { Content } from "../../constants";
|
||||
import { history } from "../../history";
|
||||
import { Row, Col, Help } from "../../ui";
|
||||
|
@ -26,47 +17,15 @@ import { Link } from "../../link";
|
|||
import { edit, save } from "../../api/crud";
|
||||
import { readPin } from "../../devices/actions";
|
||||
import { isBotOnlineFromState } from "../../devices/must_be_online";
|
||||
import { BotState } from "../../devices/interfaces";
|
||||
import {
|
||||
setToolHover, ToolSlotSVG, ToolSVG,
|
||||
} from "../map/layers/tool_slots/tool_graphics";
|
||||
import { ToolSelection } from "./tool_slot_edit_components";
|
||||
import { error } from "../../toast/toast";
|
||||
import {
|
||||
isExpressBoard, getFwHardwareValue,
|
||||
} from "../../devices/components/firmware_hardware_support";
|
||||
import { getFbosConfig } from "../../resources/getters";
|
||||
import { isActive } from "./edit_tool";
|
||||
|
||||
export interface ToolsProps {
|
||||
tools: TaggedTool[];
|
||||
toolSlots: TaggedToolSlotPointer[];
|
||||
dispatch: Function;
|
||||
findTool(id: number): TaggedTool | undefined;
|
||||
device: TaggedDevice;
|
||||
sensors: TaggedSensor[];
|
||||
bot: BotState;
|
||||
hoveredToolSlot: string | undefined;
|
||||
firmwareHardware: FirmwareHardware | undefined;
|
||||
isActive(id: number | undefined): boolean;
|
||||
}
|
||||
|
||||
export interface ToolsState {
|
||||
searchTerm: string;
|
||||
}
|
||||
|
||||
export const mapStateToProps = (props: Everything): ToolsProps => ({
|
||||
tools: selectAllTools(props.resources.index),
|
||||
toolSlots: selectAllToolSlotPointers(props.resources.index),
|
||||
dispatch: props.dispatch,
|
||||
findTool: (id: number) => maybeFindToolById(props.resources.index, id),
|
||||
device: getDeviceAccountSettings(props.resources.index),
|
||||
sensors: selectAllSensors(props.resources.index),
|
||||
bot: props.bot,
|
||||
hoveredToolSlot: props.resources.consumers.farm_designer.hoveredToolSlot,
|
||||
firmwareHardware: getFwHardwareValue(getFbosConfig(props.resources.index)),
|
||||
isActive: isActive(selectAllToolSlotPointers(props.resources.index)),
|
||||
});
|
||||
import { hasUTM } from "../../devices/components/firmware_hardware_support";
|
||||
import { ToolsProps, ToolsState } from "./interfaces";
|
||||
import { mapStateToProps } from "./state_to_props";
|
||||
import { BotOriginQuadrant } from "../interfaces";
|
||||
|
||||
const toolStatus = (value: number | undefined): string => {
|
||||
switch (value) {
|
||||
|
@ -112,7 +71,7 @@ export class RawTools extends React.Component<ToolsProps, ToolsState> {
|
|||
|
||||
get botOnline() { return isBotOnlineFromState(this.props.bot); }
|
||||
|
||||
get isExpress() { return isExpressBoard(this.props.firmwareHardware); }
|
||||
get noUTM() { return !hasUTM(this.props.firmwareHardware); }
|
||||
|
||||
MountedToolInfo = () =>
|
||||
<div className="mounted-tool">
|
||||
|
@ -165,7 +124,9 @@ export class RawTools extends React.Component<ToolsProps, ToolsState> {
|
|||
dispatch={this.props.dispatch}
|
||||
toolSlot={toolSlot}
|
||||
isActive={this.props.isActive}
|
||||
tools={this.props.tools} />)}
|
||||
tools={this.props.tools}
|
||||
xySwap={this.props.xySwap}
|
||||
quadrant={this.props.quadrant} />)}
|
||||
</div>
|
||||
|
||||
Tools = () =>
|
||||
|
@ -192,16 +153,16 @@ export class RawTools extends React.Component<ToolsProps, ToolsState> {
|
|||
|
||||
get strings() {
|
||||
return {
|
||||
placeholder: this.isExpress
|
||||
placeholder: this.noUTM
|
||||
? t("Search your seed containers...")
|
||||
: t("Search your tools..."),
|
||||
titleText: this.isExpress
|
||||
titleText: this.noUTM
|
||||
? t("Add a seed container")
|
||||
: t("Add a tool or seed container"),
|
||||
emptyStateText: this.isExpress
|
||||
emptyStateText: this.noUTM
|
||||
? Content.NO_SEED_CONTAINERS
|
||||
: Content.NO_TOOLS,
|
||||
tools: this.isExpress
|
||||
tools: this.noUTM
|
||||
? t("seed containers")
|
||||
: t("tools and seed containers"),
|
||||
toolSlots: t("slots"),
|
||||
|
@ -228,8 +189,7 @@ export class RawTools extends React.Component<ToolsProps, ToolsState> {
|
|||
title={this.strings.titleText}
|
||||
text={this.strings.emptyStateText}
|
||||
colorScheme={"tools"}>
|
||||
{!this.isExpress &&
|
||||
<this.MountedToolInfo />}
|
||||
{!this.noUTM && <this.MountedToolInfo />}
|
||||
<this.ToolSlots />
|
||||
<this.Tools />
|
||||
</EmptyStateWrapper>
|
||||
|
@ -244,6 +204,8 @@ export interface ToolSlotInventoryItemProps {
|
|||
hovered: boolean;
|
||||
dispatch: Function;
|
||||
isActive(id: number | undefined): boolean;
|
||||
xySwap: boolean;
|
||||
quadrant: BotOriginQuadrant;
|
||||
}
|
||||
|
||||
export const ToolSlotInventoryItem = (props: ToolSlotInventoryItemProps) => {
|
||||
|
@ -260,7 +222,7 @@ export const ToolSlotInventoryItem = (props: ToolSlotInventoryItemProps) => {
|
|||
<ToolSlotSVG
|
||||
toolSlot={props.toolSlot}
|
||||
toolName={tool_id ? toolName : "Empty"}
|
||||
renderRotation={false} />
|
||||
xySwap={props.xySwap} quadrant={props.quadrant} />
|
||||
</Col>
|
||||
<Col xs={6}>
|
||||
<div className={"tool-selection-wrapper"}
|
||||
|
|
|
@ -0,0 +1,71 @@
|
|||
import { UUID } from "../../resources/interfaces";
|
||||
import {
|
||||
FirmwareHardware, TaggedTool, TaggedToolSlotPointer,
|
||||
TaggedDevice, TaggedSensor,
|
||||
} from "farmbot";
|
||||
import { BotOriginQuadrant } from "../interfaces";
|
||||
import { BotState, BotPosition } from "../../devices/interfaces";
|
||||
|
||||
export interface AddToolSlotState {
|
||||
uuid: UUID | undefined;
|
||||
}
|
||||
|
||||
export interface AddToolProps {
|
||||
dispatch: Function;
|
||||
existingToolNames: string[];
|
||||
firmwareHardware: FirmwareHardware | undefined;
|
||||
}
|
||||
|
||||
export interface AddToolState {
|
||||
toolName: string;
|
||||
toAdd: string[];
|
||||
}
|
||||
|
||||
export interface EditToolProps {
|
||||
findTool(id: string): TaggedTool | undefined;
|
||||
dispatch: Function;
|
||||
mountedToolId: number | undefined;
|
||||
isActive(id: number | undefined): boolean;
|
||||
}
|
||||
|
||||
export interface EditToolState {
|
||||
toolName: string;
|
||||
}
|
||||
|
||||
export interface ToolsProps {
|
||||
tools: TaggedTool[];
|
||||
toolSlots: TaggedToolSlotPointer[];
|
||||
dispatch: Function;
|
||||
findTool(id: number): TaggedTool | undefined;
|
||||
device: TaggedDevice;
|
||||
sensors: TaggedSensor[];
|
||||
bot: BotState;
|
||||
hoveredToolSlot: string | undefined;
|
||||
firmwareHardware: FirmwareHardware | undefined;
|
||||
xySwap: boolean;
|
||||
quadrant: BotOriginQuadrant;
|
||||
isActive(id: number | undefined): boolean;
|
||||
}
|
||||
|
||||
export interface ToolsState {
|
||||
searchTerm: string;
|
||||
}
|
||||
|
||||
export interface AddEditToolSlotPropsBase {
|
||||
tools: TaggedTool[];
|
||||
dispatch: Function;
|
||||
botPosition: BotPosition;
|
||||
findTool(id: number): TaggedTool | undefined;
|
||||
firmwareHardware: FirmwareHardware | undefined;
|
||||
xySwap: boolean;
|
||||
quadrant: BotOriginQuadrant;
|
||||
isActive(id: number | undefined): boolean;
|
||||
}
|
||||
|
||||
export interface AddToolSlotProps extends AddEditToolSlotPropsBase {
|
||||
findToolSlot(uuid: UUID | undefined): TaggedToolSlotPointer | undefined;
|
||||
}
|
||||
|
||||
export interface EditToolSlotProps extends AddEditToolSlotPropsBase {
|
||||
findToolSlot(id: string): TaggedToolSlotPointer | undefined;
|
||||
}
|
|
@ -1,10 +1,10 @@
|
|||
import { Everything } from "../../interfaces";
|
||||
import { TaggedTool, TaggedToolSlotPointer, FirmwareHardware } from "farmbot";
|
||||
import {
|
||||
selectAllTools, maybeFindToolById, maybeGetToolSlot, maybeFindToolSlotById,
|
||||
selectAllToolSlotPointers,
|
||||
getDeviceAccountSettings,
|
||||
selectAllSensors,
|
||||
} from "../../resources/selectors";
|
||||
import { BotPosition } from "../../devices/interfaces";
|
||||
import { validBotLocationData } from "../../util";
|
||||
import { UUID } from "../../resources/interfaces";
|
||||
import {
|
||||
|
@ -13,21 +13,35 @@ import {
|
|||
import { getFbosConfig } from "../../resources/getters";
|
||||
import { getWebAppConfigValue } from "../../config_storage/actions";
|
||||
import { BooleanSetting, NumericSetting } from "../../session_keys";
|
||||
import { BotOriginQuadrant, isBotOriginQuadrant } from "../interfaces";
|
||||
import { isBotOriginQuadrant } from "../interfaces";
|
||||
import { isActive } from "./edit_tool";
|
||||
import {
|
||||
AddEditToolSlotPropsBase, AddToolSlotProps, EditToolSlotProps, ToolsProps,
|
||||
} from "./interfaces";
|
||||
|
||||
export interface AddEditToolSlotPropsBase {
|
||||
tools: TaggedTool[];
|
||||
dispatch: Function;
|
||||
botPosition: BotPosition;
|
||||
findTool(id: number): TaggedTool | undefined;
|
||||
firmwareHardware: FirmwareHardware | undefined;
|
||||
xySwap: boolean;
|
||||
quadrant: BotOriginQuadrant;
|
||||
isActive(id: number | undefined): boolean;
|
||||
}
|
||||
export const mapStateToProps = (props: Everything): ToolsProps => {
|
||||
const getWebAppConfig = getWebAppConfigValue(() => props);
|
||||
const xySwap = !!getWebAppConfig(BooleanSetting.xy_swap);
|
||||
const rawQuadrant = getWebAppConfig(NumericSetting.bot_origin_quadrant);
|
||||
const quadrant = isBotOriginQuadrant(rawQuadrant) ? rawQuadrant : 2;
|
||||
return {
|
||||
tools: selectAllTools(props.resources.index),
|
||||
toolSlots: selectAllToolSlotPointers(props.resources.index),
|
||||
dispatch: props.dispatch,
|
||||
findTool: (id: number) => maybeFindToolById(props.resources.index, id),
|
||||
device: getDeviceAccountSettings(props.resources.index),
|
||||
sensors: selectAllSensors(props.resources.index),
|
||||
bot: props.bot,
|
||||
hoveredToolSlot: props.resources.consumers.farm_designer.hoveredToolSlot,
|
||||
firmwareHardware: getFwHardwareValue(getFbosConfig(props.resources.index)),
|
||||
isActive: isActive(selectAllToolSlotPointers(props.resources.index)),
|
||||
xySwap,
|
||||
quadrant,
|
||||
};
|
||||
};
|
||||
|
||||
export const mapStateToPropsBase = (props: Everything): AddEditToolSlotPropsBase => {
|
||||
export const mapStateToPropsAddEditBase = (props: Everything):
|
||||
AddEditToolSlotPropsBase => {
|
||||
const getWebAppConfig = getWebAppConfigValue(() => props);
|
||||
const xySwap = !!getWebAppConfig(BooleanSetting.xy_swap);
|
||||
const rawQuadrant = getWebAppConfig(NumericSetting.bot_origin_quadrant);
|
||||
|
@ -44,24 +58,16 @@ export const mapStateToPropsBase = (props: Everything): AddEditToolSlotPropsBase
|
|||
};
|
||||
};
|
||||
|
||||
export interface AddToolSlotProps extends AddEditToolSlotPropsBase {
|
||||
findToolSlot(uuid: UUID | undefined): TaggedToolSlotPointer | undefined;
|
||||
}
|
||||
|
||||
export const mapStateToPropsAdd = (props: Everything): AddToolSlotProps => {
|
||||
const mapStateToProps = mapStateToPropsBase(props) as AddToolSlotProps;
|
||||
mapStateToProps.findToolSlot = (uuid: UUID | undefined) =>
|
||||
const stateToProps = mapStateToPropsAddEditBase(props) as AddToolSlotProps;
|
||||
stateToProps.findToolSlot = (uuid: UUID | undefined) =>
|
||||
maybeGetToolSlot(props.resources.index, uuid);
|
||||
return mapStateToProps;
|
||||
return stateToProps;
|
||||
};
|
||||
|
||||
export interface EditToolSlotProps extends AddEditToolSlotPropsBase {
|
||||
findToolSlot(id: string): TaggedToolSlotPointer | undefined;
|
||||
}
|
||||
|
||||
export const mapStateToPropsEdit = (props: Everything): EditToolSlotProps => {
|
||||
const mapStateToProps = mapStateToPropsBase(props) as EditToolSlotProps;
|
||||
mapStateToProps.findToolSlot = (id: string) =>
|
||||
const stateToProps = mapStateToPropsAddEditBase(props) as EditToolSlotProps;
|
||||
stateToProps.findToolSlot = (id: string) =>
|
||||
maybeFindToolSlotById(props.resources.index, parseInt(id));
|
||||
return mapStateToProps;
|
||||
return stateToProps;
|
||||
};
|
|
@ -8,8 +8,8 @@ import { BotPosition } from "../../devices/interfaces";
|
|||
import { ToolPulloutDirection } from "farmbot/dist/resources/api_resources";
|
||||
import { Popover } from "@blueprintjs/core";
|
||||
import { ToolSlotSVG } from "../map/layers/tool_slots/tool_graphics";
|
||||
import { BotOriginQuadrant } from "../interfaces";
|
||||
import { isNumber } from "lodash";
|
||||
import { BotOriginQuadrant } from "../interfaces";
|
||||
|
||||
export interface GantryMountedInputProps {
|
||||
gantryMounted: boolean;
|
||||
|
@ -32,7 +32,7 @@ export interface SlotDirectionInputRowProps {
|
|||
export const SlotDirectionInputRow = (props: SlotDirectionInputRowProps) =>
|
||||
<fieldset className="tool-slot-direction-input">
|
||||
<label>
|
||||
{t("Change direction")}
|
||||
{t("Direction")}
|
||||
</label>
|
||||
<i className={"direction-icon "
|
||||
+ directionIconClass(props.toolPulloutDirection)}
|
||||
|
@ -81,7 +81,7 @@ export interface ToolInputRowProps {
|
|||
tools: TaggedTool[];
|
||||
selectedTool: TaggedTool | undefined;
|
||||
onChange(update: { tool_id: number }): void;
|
||||
isExpress: boolean;
|
||||
noUTM: boolean;
|
||||
isActive(id: number | undefined): boolean;
|
||||
}
|
||||
|
||||
|
@ -90,7 +90,7 @@ export const ToolInputRow = (props: ToolInputRowProps) =>
|
|||
<Row>
|
||||
<Col xs={12}>
|
||||
<label>
|
||||
{props.isExpress
|
||||
{props.noUTM
|
||||
? t("Seed Container")
|
||||
: t("Tool or Seed Container")}
|
||||
</label>
|
||||
|
@ -155,7 +155,7 @@ export interface SlotEditRowsProps {
|
|||
tool: TaggedTool | undefined;
|
||||
botPosition: BotPosition;
|
||||
updateToolSlot(update: Partial<TaggedToolSlotPointer["body"]>): void;
|
||||
isExpress: boolean;
|
||||
noUTM: boolean;
|
||||
xySwap: boolean;
|
||||
quadrant: BotOriginQuadrant;
|
||||
isActive(id: number | undefined): boolean;
|
||||
|
@ -165,14 +165,14 @@ export const SlotEditRows = (props: SlotEditRowsProps) =>
|
|||
<div className="tool-slot-edit-rows">
|
||||
<ToolSlotSVG toolSlot={props.toolSlot}
|
||||
toolName={props.tool ? props.tool.body.name : "Empty"}
|
||||
renderRotation={true} xySwap={props.xySwap} quadrant={props.quadrant} />
|
||||
xySwap={props.xySwap} quadrant={props.quadrant} />
|
||||
<SlotLocationInputRow
|
||||
slotLocation={props.toolSlot.body}
|
||||
gantryMounted={props.toolSlot.body.gantry_mounted}
|
||||
botPosition={props.botPosition}
|
||||
onChange={props.updateToolSlot} />
|
||||
<ToolInputRow
|
||||
isExpress={props.isExpress}
|
||||
noUTM={props.noUTM}
|
||||
tools={props.tools}
|
||||
selectedTool={props.tool}
|
||||
isActive={props.isActive}
|
||||
|
@ -181,7 +181,7 @@ export const SlotEditRows = (props: SlotEditRowsProps) =>
|
|||
<SlotDirectionInputRow
|
||||
toolPulloutDirection={props.toolSlot.body.pullout_direction}
|
||||
onChange={props.updateToolSlot} />}
|
||||
{!props.isExpress &&
|
||||
{!props.noUTM &&
|
||||
<GantryMountedInput
|
||||
gantryMounted={props.toolSlot.body.gantry_mounted}
|
||||
onChange={props.updateToolSlot} />}
|
||||
|
|
Loading…
Reference in New Issue