diff --git a/frontend/constants.ts b/frontend/constants.ts index e1124ad518..db96fe9567 100644 --- a/frontend/constants.ts +++ b/frontend/constants.ts @@ -1306,7 +1306,7 @@ export enum DeviceSetting { // FarmBot farmbotSettings = `FarmBot`, name = `name`, - orderNumber = `FarmBot Order Number`, + orderNumber = `Order Number`, timezone = `timezone`, time_zone = `time zone`, camera = `camera`, diff --git a/frontend/css/farm_designer/farm_designer_panels.scss b/frontend/css/farm_designer/farm_designer_panels.scss index 8af4906016..332c0271b4 100644 --- a/frontend/css/farm_designer/farm_designer_panels.scss +++ b/frontend/css/farm_designer/farm_designer_panels.scss @@ -577,6 +577,10 @@ } } } + .move-to-button { + margin-top: 1rem; + margin-left: 1.5rem; + } } .soil-height-checkbox { @@ -1037,7 +1041,7 @@ padding: 0; margin-left: -1rem; } - button { + button.blue { margin-top: 0.5rem; margin-right: 0.5rem; height: 2.5rem; @@ -1045,6 +1049,9 @@ font-size: 1.5rem; } } + button.gray { + margin-top: 1rem; + } } .tool-direction-input, .gantry-mounted-input { diff --git a/frontend/css/global.scss b/frontend/css/global.scss index a522beed11..efc1ee45c0 100644 --- a/frontend/css/global.scss +++ b/frontend/css/global.scss @@ -1513,6 +1513,7 @@ ul { } textarea { height: 100% !important; + font-family: monospace; } } diff --git a/frontend/farm_events/add_farm_event.tsx b/frontend/farm_events/add_farm_event.tsx index d4a8a52f94..769a114b6f 100644 --- a/frontend/farm_events/add_farm_event.tsx +++ b/frontend/farm_events/add_farm_event.tsx @@ -86,7 +86,6 @@ export class RawAddFarmEvent render() { const farmEvent = this.props.findFarmEventByUuid(this.state.uuid); const panelName = "add-farm-event"; - const executableOptions = this.props.executableOptions.filter(x => !x.heading); return undefined} dispatch={this.props.dispatch} specialStatus={SpecialStatus.DIRTY} - onSave={() => error(executableOptions.length < 1 + onSave={() => error(this.props.executableOptions + .filter(x => !x.heading).length < 1 ? t(Content.MISSING_EXECUTABLE) : t("Please select a sequence or regimen."))} />} diff --git a/frontend/farm_events/edit_fe_form.tsx b/frontend/farm_events/edit_fe_form.tsx index 7bbbf6b047..110b2223a0 100644 --- a/frontend/farm_events/edit_fe_form.tsx +++ b/frontend/farm_events/edit_fe_form.tsx @@ -519,7 +519,7 @@ export const FarmEventForm = (props: FarmEventFormProps) => { - {props.executableOptions.length < 1 && + {props.executableOptions.filter(x => !x.heading).length < 1 && } diff --git a/frontend/photos/images/__tests__/photos_test.tsx b/frontend/photos/images/__tests__/photos_test.tsx index cc8134a95f..fabe04e88e 100644 --- a/frontend/photos/images/__tests__/photos_test.tsx +++ b/frontend/photos/images/__tests__/photos_test.tsx @@ -1,16 +1,19 @@ -const mockDevice = { takePhoto: jest.fn(() => Promise.resolve({})) }; +const mockDevice = { + takePhoto: jest.fn(() => Promise.resolve({})), + moveAbsolute: jest.fn(() => Promise.resolve({})), +}; jest.mock("../../../device", () => ({ getDevice: () => mockDevice })); jest.mock("../../../api/crud", () => ({ destroy: jest.fn() })); import React from "react"; import { mount, shallow } from "enzyme"; -import { Photos, PhotoFooter } from "../photos"; +import { Photos, PhotoFooter, MoveToLocation } from "../photos"; import { JobProgress } from "farmbot"; import { fakeImages } from "../../../__test_support__/fake_state/images"; import { destroy } from "../../../api/crud"; import { clickButton } from "../../../__test_support__/helpers"; -import { PhotosProps, PhotoFooterProps } from "../interfaces"; +import { PhotosProps, PhotoFooterProps, MoveToLocationProps } from "../interfaces"; import { fakeTimeSettings } from "../../../__test_support__/fake_time_settings"; import { success, error } from "../../../toast/toast"; import { Content, ToolTips, Actions } from "../../../constants"; @@ -20,7 +23,7 @@ import { import { fakeImageShowFlags } from "../../../__test_support__/fake_camera_data"; import { mockDispatch } from "../../../__test_support__/fake_dispatch"; -describe("", () => { +describe("", () => { const fakeProps = (): PhotosProps => ({ images: [], currentImage: undefined, @@ -236,6 +239,7 @@ describe("", () => { timeSettings: fakeTimeSettings(), flags: fakeImageShowFlags(), size: { width: 0, height: 0 }, + botOnline: true, }); it("highlights map image", () => { @@ -253,3 +257,16 @@ describe("", () => { }); }); }); + +describe("", () => { + const fakeProps = (): MoveToLocationProps => ({ + imageLocation: { x: 0, y: 0, z: 0 }, + botOnline: true, + }); + + it("moves to location", () => { + const wrapper = mount(); + clickButton(wrapper, 0, "move farmbot to location"); + expect(mockDevice.moveAbsolute).toHaveBeenCalledWith({ x: 0, y: 0, z: 0 }); + }); +}); diff --git a/frontend/photos/images/interfaces.ts b/frontend/photos/images/interfaces.ts index a8d98d5f52..3c0ce40d78 100644 --- a/frontend/photos/images/interfaces.ts +++ b/frontend/photos/images/interfaces.ts @@ -1,4 +1,4 @@ -import { TaggedImage, JobProgress, SyncStatus } from "farmbot"; +import { TaggedImage, JobProgress, SyncStatus, Xyz } from "farmbot"; import { NetworkState } from "../../connectivity/interfaces"; import { TimeSettings } from "../../interfaces"; import { UserEnv } from "../../devices/interfaces"; @@ -111,6 +111,12 @@ export interface PhotoFooterProps { timeSettings: TimeSettings; dispatch: Function; flags: ImageShowFlags; + botOnline: boolean; +} + +export interface MoveToLocationProps { + botOnline: boolean; + imageLocation: Record; } export interface PhotosComponentState { diff --git a/frontend/photos/images/photos.tsx b/frontend/photos/images/photos.tsx index f0e12cc8bf..364e60a2d9 100644 --- a/frontend/photos/images/photos.tsx +++ b/frontend/photos/images/photos.tsx @@ -6,12 +6,13 @@ import { } from "./image_flipper"; import { PhotosProps, PhotoButtonsProps, PhotoFooterProps, PhotosComponentState, + MoveToLocationProps, } from "./interfaces"; import { timeFormatString } from "../../util"; import { destroy } from "../../api/crud"; import { downloadProgress } from "../../settings/fbos_settings/os_update_button"; -import { startCase } from "lodash"; -import { MustBeOnline } from "../../devices/must_be_online"; +import { isNumber, startCase } from "lodash"; +import { isBotOnline, MustBeOnline } from "../../devices/must_be_online"; import { t } from "../../i18next_wrapper"; import { cameraBtnProps } from "../capture_settings/camera_selection"; import { Overlay, Popover } from "@blueprintjs/core"; @@ -19,7 +20,7 @@ import { ImageShowMenu, ImageShowMenuTarget } from "./image_show_menu"; import { setShownMapImages } from "./actions"; import { TaggedImage, Xyz } from "farmbot"; import { MarkedSlider } from "../../ui"; -import { takePhoto } from "../../devices/actions"; +import { moveAbsolute, takePhoto } from "../../devices/actions"; const PhotoButtons = (props: PhotoButtonsProps) => { const imageUploadJobProgress = downloadProgress(props.imageJobs[0]); @@ -99,10 +100,15 @@ export const PhotoFooter = (props: PhotoFooterProps) => {
{image ? ["x", "y", "z"].map((axis: Xyz, index) => -
- - {image.body.meta[axis] ?? "---"} -
) + +
+ + {image.body.meta[axis] ?? "---"} +
+ +
) :
{t("No meta data.")} @@ -111,6 +117,24 @@ export const PhotoFooter = (props: PhotoFooterProps) => {
; }; +export const MoveToLocation = (props: MoveToLocationProps) => + ; + export class Photos extends React.Component { state: PhotosComponentState = { crop: true, rotate: true, fullscreen: false, @@ -193,6 +217,7 @@ export class Photos extends React.Component { flags={this.props.flags} size={this.props.currentImageSize} dispatch={this.props.dispatch} + botOnline={isBotOnline(this.props.syncStatus, this.props.botToMqttStatus)} timeSettings={this.props.timeSettings} /> {this.props.images.length > 1 && - ; export interface EditPointRadiusProps { diff --git a/frontend/points/point_info.tsx b/frontend/points/point_info.tsx index ca8e6f360d..069e267ccc 100644 --- a/frontend/points/point_info.tsx +++ b/frontend/points/point_info.tsx @@ -14,15 +14,18 @@ import { EditPointProperties, updatePoint, PointActions, lookupPointSource, } from "./point_edit_actions"; import { ListItem } from "../plants/plant_panel"; +import { isBotOnlineFromState } from "../devices/must_be_online"; export interface EditPointProps { dispatch: Function; findPoint(id: number): TaggedGenericPointer | undefined; + botOnline: boolean; } export const mapStateToProps = (props: Everything): EditPointProps => ({ dispatch: props.dispatch, findPoint: id => maybeFindGenericPointerById(props.resources.index, id), + botOnline: isBotOnlineFromState(props.bot), }); export class RawEditPoint extends React.Component { @@ -51,6 +54,7 @@ export class RawEditPoint extends React.Component { {this.point ?
    {Object.entries(this.point.body.meta).map(([key, value]) => { @@ -73,12 +77,7 @@ export class RawEditPoint extends React.Component { } })}
- +
: {t("Redirecting")}...} diff --git a/frontend/sequences/step_tiles/tile_assertion.tsx b/frontend/sequences/step_tiles/tile_assertion.tsx index 8d68458125..8b28f6b7a1 100644 --- a/frontend/sequences/step_tiles/tile_assertion.tsx +++ b/frontend/sequences/step_tiles/tile_assertion.tsx @@ -10,7 +10,7 @@ import { ToolTips } from "../../constants"; import { LuaTextArea } from "./tile_lua_support"; export const TileAssertion = (props: StepParams) => { - const [monaco, setMonaco] = React.useState(true); + const [monaco, setMonaco] = React.useState(window.innerWidth > 450); return = { +const ASSERTION_TYPES = (): Record => ({ "continue": { label: t("Continue"), value: "continue" }, "recover": { label: t("Recover and continue"), value: "recover" }, "abort_recover": { label: t("Abort and recover"), value: "abort_recover" }, "abort": { label: t("Abort"), value: "abort" }, -}; +}); export function TypePart(props: StepParams) { const { assertion_type } = props.currentStep.args; @@ -18,7 +18,7 @@ export function TypePart(props: StepParams) { { props.dispatch(editStep({ step: props.currentStep, @@ -29,6 +29,6 @@ export function TypePart(props: StepParams) { } })); }} - list={Object.values(ASSERTION_TYPES)} /> + list={Object.values(ASSERTION_TYPES())} /> ; } diff --git a/frontend/sequences/step_tiles/tile_lua.tsx b/frontend/sequences/step_tiles/tile_lua.tsx index 980438f67e..b82aa49f32 100644 --- a/frontend/sequences/step_tiles/tile_lua.tsx +++ b/frontend/sequences/step_tiles/tile_lua.tsx @@ -8,7 +8,7 @@ import { ToolTips } from "../../constants"; import { LuaTextArea } from "./tile_lua_support"; export const TileLua = (props: StepParams) => { - const [monaco, setMonaco] = React.useState(true); + const [monaco, setMonaco] = React.useState(window.innerWidth > 450); return + list={MESSAGE_STATUSES()} />
- {EACH_CHANNEL.map((chan, inx) => { + {EACH_CHANNEL().map((chan, inx) => { return
; export interface UseCurrentLocationProps { @@ -161,6 +175,7 @@ export const SlotEditRows = (props: SlotEditRowsProps) => slotLocation={props.toolSlot.body} gantryMounted={props.toolSlot.body.gantry_mounted} botPosition={props.botPosition} + botOnline={props.botOnline} onChange={props.updateToolSlot} /> ({ push: jest.fn(), })); -import * as React from "react"; +import React from "react"; import { mount, shallow } from "enzyme"; import { RawEditWeed as EditWeed, EditWeedProps, mapStateToProps, @@ -22,6 +22,7 @@ describe("", () => { const fakeProps = (): EditWeedProps => ({ dispatch: jest.fn(), findPoint: () => undefined, + botOnline: true, }); it("redirects", () => { diff --git a/frontend/weeds/weeds_edit.tsx b/frontend/weeds/weeds_edit.tsx index ace7475781..60f15b24fc 100644 --- a/frontend/weeds/weeds_edit.tsx +++ b/frontend/weeds/weeds_edit.tsx @@ -1,4 +1,4 @@ -import * as React from "react"; +import React from "react"; import { connect } from "react-redux"; import { DesignerPanel, DesignerPanelHeader, DesignerPanelContent, @@ -14,15 +14,18 @@ import { } from "../points/point_edit_actions"; import { Actions } from "../constants"; import { selectPoint } from "../farm_designer/map/actions"; +import { isBotOnlineFromState } from "../devices/must_be_online"; export interface EditWeedProps { dispatch: Function; findPoint(id: number): TaggedWeedPointer | undefined; + botOnline: boolean; } export const mapStateToProps = (props: Everything): EditWeedProps => ({ dispatch: props.dispatch, findPoint: id => maybeFindWeedPointerById(props.resources.index, id), + botOnline: isBotOnlineFromState(props.bot), }); export class RawEditWeed extends React.Component { @@ -54,15 +57,11 @@ export class RawEditWeed extends React.Component { {this.point ?
- +
: {t("Redirecting")}...} diff --git a/frontend/wizard/checks.tsx b/frontend/wizard/checks.tsx index 4f090c3938..e3aa40232e 100644 --- a/frontend/wizard/checks.tsx +++ b/frontend/wizard/checks.tsx @@ -65,7 +65,9 @@ import { ToolTips } from "../constants"; import { WD_KEY_DEFAULTS } from "../photos/remote_env/constants"; import { McuInputBox } from "../settings/hardware_settings/mcu_input_box"; import { LockableButton } from "../settings/hardware_settings/lockable_button"; -import { disabledAxisMap } from "../settings/hardware_settings/axis_tracking_status"; +import { + disabledAxisMap, +} from "../settings/hardware_settings/axis_tracking_status"; const recentErrorLog = ( logs: TaggedLog[],