From 29a14e3997e337eb90825982c3fdfcb5f45e9be5 Mon Sep 17 00:00:00 2001 From: Gabriel Burnworth Date: Sat, 20 Jan 2018 06:46:44 -0800 Subject: [PATCH 1/3] Misc bug fixes and refactoring (#627) * allow external docs links * match upgrade path test cases * style updates: prefer return < over ( * refactor util * import refactor * fix sequence step scroll * refactor mocked paths * remove unnecessary prop * zoom level checks * misc fixes * sync and estop button fixes * don't sync WebAppConfigs --- config/application.rb | 4 +- spec/lib/session_token_spec.rb | 4 +- webpack/__tests__/app_test.tsx | 9 +- webpack/__tests__/routes_test.tsx | 10 +- webpack/__tests__/util_test.ts | 301 ----------- .../account/components/change_password.tsx | 2 +- webpack/account/components/delete_account.tsx | 2 +- webpack/account/components/settings.tsx | 4 +- webpack/account/index.tsx | 2 +- webpack/api/crud.ts | 4 +- webpack/api/maybe_start_tracking.ts | 3 +- webpack/app.tsx | 7 +- .../__tests__/data_consistency_test.ts | 4 +- webpack/connectivity/auto_sync.ts | 4 +- webpack/controls/axis_display_group.tsx | 2 +- webpack/controls/axis_input_box_group.tsx | 2 +- webpack/controls/controls.tsx | 2 +- webpack/controls/move.tsx | 212 ++++---- webpack/controls/peripherals/index.tsx | 6 +- webpack/controls/toggle_button.tsx | 14 +- webpack/controls/webcam/edit.tsx | 46 +- webpack/controls/webcam/show.tsx | 69 ++- webpack/devices/__tests__/actions_test.ts | 14 +- .../devices/__tests__/must_be_online_test.tsx | 14 +- .../__tests__/e_stop_button_test.tsx | 29 ++ .../__tests__/farmbot_os_settings_test.tsx | 12 +- .../__tests__/rpi_gpio_diagram_test.tsx | 2 +- .../components/boolean_mcu_input_group.tsx | 58 +-- webpack/devices/components/e_stop_btn.tsx | 4 +- .../__tests__/os_update_button_test.tsx | 9 + .../components/fbos_settings/board_type.tsx | 3 +- .../fbos_settings/camera_selection.tsx | 3 +- .../fbos_settings/os_update_button.tsx | 4 +- .../devices/components/hardware_settings.tsx | 105 ++-- .../__tests__/encoder_type_test.tsx | 6 +- .../hardware_settings/encoder_type.tsx | 3 +- .../components/numeric_mcu_input_group.tsx | 3 +- webpack/devices/components/pin_bindings.tsx | 6 +- .../components/pin_guard_input_group.tsx | 3 +- .../connectivity/__tests__/diagram_test.tsx | 2 +- webpack/devices/connectivity/diagram.tsx | 2 +- webpack/devices/devices.tsx | 3 +- webpack/devices/interfaces.ts | 1 - webpack/devices/must_be_online.tsx | 6 +- webpack/devices/reducer.ts | 4 +- .../devices/timezones/timezone_selector.tsx | 3 +- webpack/extras/fallback_widget.tsx | 20 +- .../farm_designer/__tests__/actions_test.ts | 33 +- .../farm_events/add_farm_event.tsx | 40 +- .../farm_events/edit_fe_form.tsx | 174 +++---- .../farm_events/event_time_picker.tsx | 2 +- .../farm_events/farm_event_repeat_form.tsx | 5 +- .../farm_designer/farm_events/farm_events.tsx | 82 ++- .../map_state_to_props_add_edit.ts | 2 +- .../map/__tests__/drag_helpers_test.tsx | 2 +- .../map/__tests__/garden_map_test.tsx | 32 +- .../farm_designer/map/__tests__/zoom_test.ts | 12 + webpack/farm_designer/map/drag_helpers.tsx | 16 +- webpack/farm_designer/map/garden_map.tsx | 16 +- .../farm_designer/map/garden_map_legend.tsx | 132 +++-- webpack/farm_designer/map/garden_plant.tsx | 2 +- webpack/farm_designer/map/grid.tsx | 2 +- .../map/layers/__tests__/plant_layer_test.tsx | 13 +- .../layers/__tests__/tool_slot_layer_test.tsx | 14 +- webpack/farm_designer/map/layers/index.ts | 7 + .../map/layers/tool_slot_layer.tsx | 4 +- webpack/farm_designer/map/map_background.tsx | 2 +- .../farm_designer/map/target_coordinate.tsx | 9 +- webpack/farm_designer/map/tool_slot_point.tsx | 2 +- webpack/farm_designer/map/util.ts | 5 +- .../__tests__/bot_figure_test.tsx | 2 +- .../map/virtual_farmbot/bot_figure.tsx | 2 +- webpack/farm_designer/map/zoom.ts | 14 +- .../plants/__tests__/add_plant_test.tsx | 9 +- .../plants/__tests__/crop_info_test.tsx | 9 +- .../plants/__tests__/move_to_test.tsx | 9 +- .../plants/__tests__/select_plants_test.tsx | 9 +- webpack/farm_designer/plants/add_plant.tsx | 2 +- .../farm_designer/plants/edit_plant_info.tsx | 2 +- webpack/farm_designer/reducer.ts | 5 +- .../camera_calibration/camera_calibration.tsx | 102 ++-- webpack/farmware/farmware_panel.tsx | 172 +++--- webpack/farmware/images/image_flipper.tsx | 32 +- webpack/farmware/images/photos.tsx | 85 ++- webpack/farmware/weed_detector/config.tsx | 13 +- .../farmware/weed_detector/farmbot_picker.tsx | 2 +- .../weed_detector/image_workspace.tsx | 168 +++--- webpack/farmware/weed_detector/selectors.ts | 2 +- webpack/farmware/weed_detector/title.tsx | 74 ++- .../__tests__/create_account_test.tsx | 4 +- webpack/front_page/front_page.tsx | 48 +- webpack/hotkeys.tsx | 54 +- webpack/logs/components/logs_table.tsx | 2 +- webpack/logs/index.tsx | 2 +- webpack/nav/index.tsx | 84 ++- webpack/nav/mobile_menu.tsx | 20 +- webpack/nav/nav_links.tsx | 32 +- webpack/nav/sync_button.tsx | 12 +- webpack/nav/ticker_list.tsx | 72 ++- webpack/password_reset/password_reset.tsx | 80 ++- webpack/regimens/bulk_scheduler/index.tsx | 6 +- webpack/regimens/editor/active_editor.tsx | 12 +- webpack/regimens/editor/index.tsx | 10 +- .../regimens/editor/regimen_name_input.tsx | 29 +- webpack/regimens/list/add_button.tsx | 18 +- webpack/regimens/list/index.tsx | 68 ++- webpack/resources/__tests__/selectors_test.ts | 74 +-- .../sequences/__tests__/locals_list_test.tsx | 8 +- .../sequence_editor_middle_inactive_test.tsx | 4 +- .../__tests__/sequence_editor_middle_test.tsx | 4 +- .../sequences/__tests__/sequences_test.tsx | 4 +- webpack/sequences/actions.ts | 2 +- webpack/sequences/inputs/input_default.tsx | 2 +- webpack/sequences/interfaces.ts | 4 +- webpack/sequences/locals_list.tsx | 14 +- .../sequence_editor_middle_active.tsx | 97 ++-- webpack/sequences/sequences_list.tsx | 72 ++- webpack/sequences/step_button_cluster.tsx | 4 +- webpack/sequences/step_tiles/index.tsx | 4 +- webpack/sequences/step_tiles/tile_execute.tsx | 3 +- webpack/sequences/step_tiles/tile_if/else.tsx | 3 +- webpack/sequences/step_tiles/tile_if/if.tsx | 6 +- .../sequences/step_tiles/tile_if/index.tsx | 3 +- webpack/sequences/step_tiles/tile_if/then.tsx | 3 +- .../step_tiles/tile_move_absolute.tsx | 8 +- .../format_selected_dropdown.ts | 3 +- .../step_tiles/tile_move_absolute/index.ts | 7 + .../tile_move_absolute/input_box.tsx | 2 +- .../step_tiles/tile_move_absolute/select.tsx | 3 +- .../sequences/step_tiles/tile_read_pin.tsx | 3 +- .../step_tiles/tile_send_message.tsx | 3 +- .../sequences/step_tiles/tile_write_pin.tsx | 3 +- webpack/session.ts | 10 +- webpack/tools/components/tool_form.tsx | 6 +- webpack/tools/components/tool_list.tsx | 2 +- webpack/tools/components/toolbay_form.tsx | 6 +- webpack/tools/components/toolbay_list.tsx | 2 +- webpack/tools/index.tsx | 2 +- webpack/tools/interfaces.ts | 2 +- webpack/tools/state_to_props.ts | 3 +- webpack/ui/color_picker.tsx | 2 +- webpack/ui/filter_search.tsx | 42 +- webpack/ui/index.ts | 5 + webpack/ui/new_fb_select.tsx | 8 +- webpack/util.ts | 488 ------------------ webpack/util/__tests__/errors_test.ts | 14 + webpack/util/__tests__/integer_clamp_test.ts | 21 + webpack/util/__tests__/move_test.ts | 19 + webpack/util/__tests__/page_test.ts | 7 + webpack/util/__tests__/progress_test.ts | 23 + webpack/util/__tests__/util_test.ts | 156 ++++++ webpack/util/__tests__/version_test.ts | 54 ++ webpack/util/errors.ts | 41 ++ webpack/util/index.ts | 7 + webpack/util/integer_clamp.ts | 37 ++ webpack/util/move.ts | 39 ++ webpack/util/page.ts | 60 +++ webpack/util/progress.ts | 22 + webpack/util/util.ts | 215 ++++++++ webpack/util/version.ts | 49 ++ 160 files changed, 2261 insertions(+), 2330 deletions(-) delete mode 100644 webpack/__tests__/util_test.ts create mode 100644 webpack/devices/components/__tests__/e_stop_button_test.tsx create mode 100644 webpack/farm_designer/map/layers/index.ts create mode 100644 webpack/sequences/step_tiles/tile_move_absolute/index.ts delete mode 100644 webpack/util.ts create mode 100644 webpack/util/__tests__/errors_test.ts create mode 100644 webpack/util/__tests__/integer_clamp_test.ts create mode 100644 webpack/util/__tests__/move_test.ts create mode 100644 webpack/util/__tests__/page_test.ts create mode 100644 webpack/util/__tests__/progress_test.ts create mode 100644 webpack/util/__tests__/util_test.ts create mode 100644 webpack/util/__tests__/version_test.ts create mode 100644 webpack/util/errors.ts create mode 100644 webpack/util/index.ts create mode 100644 webpack/util/integer_clamp.ts create mode 100644 webpack/util/move.ts create mode 100644 webpack/util/page.ts create mode 100644 webpack/util/progress.ts create mode 100644 webpack/util/util.ts create mode 100644 webpack/util/version.ts diff --git a/config/application.rb b/config/application.rb index 971351309..9a998d03d 100755 --- a/config/application.rb +++ b/config/application.rb @@ -53,7 +53,6 @@ module FarmBot default_src: %w(https: 'self'), base_uri: %w('self'), block_all_mixed_content: false, # :( Some webcam feeds use http:// - child_src: %w('self'), connect_src: ALL_LOCAL_URIS + [ENV["MQTT_HOST"], "api.github.com", "raw.githubusercontent.com", @@ -68,7 +67,7 @@ module FarmBot fonts.gstatic.com ), form_action: %w('self'), - frame_ancestors: %w(*), # We need "*" to support webcam users. + frame_src: %w(*), # We need "*" to support webcam users. img_src: %w(* data:), # We need "*" to support webcam users. manifest_src: %w('self'), media_src: %w(), @@ -78,6 +77,7 @@ module FarmBot allow-forms allow-same-origin allow-modals + allow-popups ), plugin_types: %w(), script_src: %w( diff --git a/spec/lib/session_token_spec.rb b/spec/lib/session_token_spec.rb index cca5aaf0d..b93407af7 100644 --- a/spec/lib/session_token_spec.rb +++ b/spec/lib/session_token_spec.rb @@ -47,9 +47,9 @@ describe SessionToken do expect(test_case["0.0.0"]).to eq(CalculateUpgrade::OLD_OS_URL) expect(test_case["5.0.5"]).to eq(CalculateUpgrade::OLD_OS_URL) expect(test_case["5.0.6"]).to eq(CalculateUpgrade::OLD_OS_URL) - expect(test_case["5.0.7"]).to eq(CalculateUpgrade::MID_OS_URL) expect(test_case["5.0.8"]).to eq(CalculateUpgrade::MID_OS_URL) - expect(test_case["5.1.0"]).to eq(CalculateUpgrade::OS_RELEASE) + expect(test_case["5.0.9"]).to eq(CalculateUpgrade::MID_OS_URL) + expect(test_case["6.0.1"]).to eq(CalculateUpgrade::OS_RELEASE) end it "doesn't honor expired tokens" do diff --git a/webpack/__tests__/app_test.tsx b/webpack/__tests__/app_test.tsx index 6387bf654..9c002de67 100644 --- a/webpack/__tests__/app_test.tsx +++ b/webpack/__tests__/app_test.tsx @@ -6,6 +6,11 @@ jest.mock("react-redux", () => ({ connect: jest.fn() })); +let mockPath = ""; +jest.mock("../history", () => ({ + getPathArray: jest.fn(() => { return mockPath.split("/"); }) +})); + import * as React from "react"; import { App, AppProps } from "../app"; import { mount } from "enzyme"; @@ -29,9 +34,7 @@ describe(": Controls Pop-Up", () => { function controlsPopUp(page: string, exists: boolean) { it(`doesn't render controls pop-up on ${page} page`, () => { - Object.defineProperty(location, "pathname", { - value: "/app/" + page, configurable: true - }); + mockPath = "/app/" + page; const wrapper = mount(); if (exists) { expect(wrapper.html()).toContain("controls-popup"); diff --git a/webpack/__tests__/routes_test.tsx b/webpack/__tests__/routes_test.tsx index 9a336dc3b..b44cb3441 100644 --- a/webpack/__tests__/routes_test.tsx +++ b/webpack/__tests__/routes_test.tsx @@ -2,13 +2,11 @@ jest.mock("fastclick", () => ({ attach: jest.fn(), })); -import { auth } from "../__test_support__/fake_state/token"; -const mockAuth = auth; +let mockAuth: AuthState | undefined = undefined; const mockClear = jest.fn(); jest.mock("../session", () => ({ Session: { - fetchStoredToken: jest.fn(() => mockAuth) - .mockImplementationOnce(() => { }), + fetchStoredToken: jest.fn(() => mockAuth), deprecatedGetNum: () => undefined, deprecatedGetBool: () => undefined, getAll: () => undefined, @@ -20,6 +18,8 @@ import * as React from "react"; import { shallow } from "enzyme"; import { RootComponent } from "../routes"; import { store } from "../redux/store"; +import { AuthState } from "../auth/interfaces"; +import { auth } from "../__test_support__/fake_state/token"; describe("", () => { beforeEach(function () { @@ -27,6 +27,7 @@ describe("", () => { }); it("clears session when not authorized", () => { + mockAuth = undefined; Object.defineProperty(location, "pathname", { value: "/app/account" }); @@ -35,6 +36,7 @@ describe("", () => { }); it("authorized", () => { + mockAuth = auth; Object.defineProperty(location, "pathname", { value: "/app/account" }); diff --git a/webpack/__tests__/util_test.ts b/webpack/__tests__/util_test.ts deleted file mode 100644 index 56da9fe2d..000000000 --- a/webpack/__tests__/util_test.ts +++ /dev/null @@ -1,301 +0,0 @@ -import { - prettyPrintApiErrors, - defensiveClone, - getParam, - betterCompact, - safeStringFetch, - oneOf, - semverCompare, - SemverResult, - trim, - bitArray, - withTimeout, - minFwVersionCheck, - move, - shortRevision, - clampUnsignedInteger, - isUndefined, - IntegerSize, - Progress, - colors, - randomColor -} from "../util"; -import { times } from "lodash"; -describe("util", () => { - describe("safeStringFetch", () => { - const data = { - // tslint:disable-next-line:no-null-keyword - "null": null, - "undefined": undefined, - "number": 0, - "string": "hello", - "boolean": false, - "other": () => { "not allowed!"; } - }; - - it("fetches null", () => { - expect(safeStringFetch(data, "null")).toEqual(""); - }); - - it("fetches undefined", () => { - expect(safeStringFetch(data, "undefined")).toEqual(""); - }); - - it("fetches number", () => { - expect(safeStringFetch(data, "number")).toEqual("0"); - }); - - it("fetches string", () => { - expect(safeStringFetch(data, "string")).toEqual("hello"); - }); - - it("fetches boolean", () => { - expect(safeStringFetch(data, "boolean")).toEqual("false"); - }); - - it("handles others with exception", () => { - expect(() => safeStringFetch(data, "other")).toThrow(); - }); - }); - - describe("betterCompact", () => { - it("removes falsy values", () => { - const before = [{}, {}, undefined]; - const after = betterCompact(before); - expect(after.length).toBe(2); - expect(after).not.toContain(undefined); - }); - }); - - describe("defensiveClone", () => { - it("deep clones any serializable object", () => { - const origin = { a: "b", c: 2, d: [{ e: { f: "g" } }] }; - const child = defensiveClone(origin); - origin.a = "--"; - origin.c = 0; - origin.d[0].e.f = "--"; - expect(child).not.toBe(origin); - expect(child.a).toEqual("b"); - expect(child.c).toEqual(2); - expect(child.d[0].e.f).toEqual("g"); - }); - }); - - describe("getParam", () => { - it("gets params", () => { - Object.defineProperty(window.location, "search", { - writable: true, - value: "?foo=bar&baz=wow" - }); - expect(getParam("foo")).toEqual("bar"); - expect(getParam("baz")).toEqual("wow"); - expect(getParam("blah")).toEqual(""); - }); - }); - - describe("prettyPrintApiErrors", () => { - it("handles properly formatted API error messages", () => { - const result = prettyPrintApiErrors({ - response: { - data: { - email: "can't be blank" - } - } - }); - expect(result).toEqual("Email: can't be blank"); - }); - }); - - describe("oneOf()", () => { - it("determines matches", () => { - expect(oneOf(["foo"], "foobar")).toBeTruthy(); - expect(oneOf(["foo", "baz"], "foo bar baz")).toBeTruthy(); - }); - - it("determines non-matches", () => { - expect(oneOf(["foo"], "QMMADSDASDASD")).toBeFalsy(); - expect(oneOf(["foo", "baz"], "nothing to see here.")).toBeFalsy(); - }); - }); - - describe("semver compare", () => { - it("knows when RIGHT_IS_GREATER", () => { - expect(semverCompare("3.1.6", "4.0.0")) - .toBe(SemverResult.RIGHT_IS_GREATER); - - expect(semverCompare("2.1.6", "4.1.0")) - .toBe(SemverResult.RIGHT_IS_GREATER); - - expect(semverCompare("4.1.6", "5.1.9")) - .toBe(SemverResult.RIGHT_IS_GREATER); - - expect(semverCompare("1.1.9", "2.0.2")) - .toBe(SemverResult.RIGHT_IS_GREATER); - - expect(semverCompare("", "1.0.0")) - .toBe(SemverResult.RIGHT_IS_GREATER); - }); - - it("knows when LEFT_IS_GREATER", () => { - expect(semverCompare("4.0.0", "3.1.6")) - .toBe(SemverResult.LEFT_IS_GREATER); - - expect(semverCompare("4.1.0", "2.1.6")) - .toBe(SemverResult.LEFT_IS_GREATER); - - expect(semverCompare("5.1.9", "4.1.6")) - .toBe(SemverResult.LEFT_IS_GREATER); - - expect(semverCompare("2.0.2", "1.1.9")) - .toBe(SemverResult.LEFT_IS_GREATER); - - expect(semverCompare("1.0.0", "")) - .toBe(SemverResult.LEFT_IS_GREATER); - expect(semverCompare("1.0.0", "x.y.z")) - .toBe(SemverResult.LEFT_IS_GREATER); - expect(semverCompare("x.y.z", "1.0.0")) - .toBe(SemverResult.RIGHT_IS_GREATER); - }); - }); -}); - -describe("trim()", () => { - it("formats whitespace", () => { - const string = `foo - bar`; - const formattedString = trim(string); - expect(formattedString).toEqual("foo bar"); - }); -}); - -describe("bitArray", () => { - it("converts flags to numbers", () => { - expect(bitArray(true)).toBe(0b1); - expect(bitArray(true, false)).toBe(0b10); - expect(bitArray(false, true)).toBe(0b01); - expect(bitArray(true, true)).toBe(0b11); - }); -}); - -describe("withTimeout()", () => { - it("rejects promises that do not meet a particular deadline", (done) => { - const p = new Promise(res => setTimeout(() => res("Done"), 10)); - withTimeout(1, p).then(fail, (y) => { - expect(y).toContain("Timed out"); - done(); - }); - }); - - it("resolves promises that meet a particular deadline", (done) => { - withTimeout(10, new Promise(res => setTimeout(() => res("Done"), 1))) - .then(y => { - expect(y).toContain("Done"); - done(); - }, fail); - }); -}); - -describe("minFwVersionCheck()", () => { - it("firmware version meets or exceeds minimum", () => { - expect(minFwVersionCheck("1.0.1R", "1.0.1")).toBeTruthy(); - expect(minFwVersionCheck("1.0.2F", "1.0.1")).toBeTruthy(); - }); - - it("firmware version doesn't meet minimum", () => { - expect(minFwVersionCheck("1.0.0R", "1.0.1")).toBeFalsy(); - expect(minFwVersionCheck(undefined, "1.0.1")).toBeFalsy(); - expect(minFwVersionCheck("1.0.0", "1.0.1")).toBeFalsy(); - }); -}); - -describe("move()", () => { - it("shuffles array elems", () => { - const fixture = [0, 1, 2]; - const case1 = move(fixture, 0, 2); - expect(case1[0]).toEqual(1); - expect(case1[1]).toEqual(2); - expect(case1[2]).toEqual(0); - - const case2 = move(fixture, 1, 0); - expect(case2[0]).toEqual(1); - expect(case2[1]).toEqual(0); - expect(case2[2]).toEqual(2); - - const case3 = move(fixture, 0, 0); - expect(case3).toEqual(fixture); - }); -}); - -describe("shortRevision()", () => { - it("none", () => { - globalConfig.SHORT_REVISION = ""; - const short = shortRevision(); - expect(short).toEqual("NONE"); - }); - - it("slices", () => { - globalConfig.SHORT_REVISION = "0123456789"; - const short = shortRevision(); - expect(short).toEqual("01234567"); - }); -}); - -describe("clampUnsignedInteger()", () => { - function clampTest( - input: string, - output: number | undefined, - message: string, - size: IntegerSize) { - it(`${size}: ${message}`, () => { - const result = clampUnsignedInteger(input, size); - expect(result.outcome).toEqual(message); - expect(result.result).toEqual(output); - }); - } - clampTest("nope", undefined, "malformed", "short"); - clampTest("100000", 32000, "high", "short"); - clampTest("-100000", 0, "low", "short"); - clampTest("1000", 1000, "ok", "short"); - clampTest("1000000", 1000000, "ok", "long"); - clampTest("-1000000", 0, "low", "long"); -}); - -describe("isUndefined()", () => { - it("undefined", () => { - const result = isUndefined(undefined); - expect(result).toBeTruthy(); - }); - - it("defined", () => { - const result = isUndefined({}); - expect(result).toBeFalsy(); - }); -}); - -describe("Progress", () => { - it("increments", () => { - const cb = jest.fn(); - const counter = new Progress(3, cb); - counter.inc(); - expect(cb).toHaveBeenCalledWith(counter); - counter.inc(); - counter.inc(); // Now we're done. - cb.mockClear(); - counter.inc(); - expect(cb).not.toHaveBeenCalled(); - }); - - it("force finishes", () => { - const cb = jest.fn(); - const counter = new Progress(3, cb); - counter.finish(); - expect(cb).toHaveBeenCalled(); - expect(counter.isDone).toBeTruthy(); - }); -}); - -describe("randomColor()", () => { - it("only picks valid colors", () => { - times(colors.length * 1.5, () => expect(colors).toContain(randomColor())); - }); -}); diff --git a/webpack/account/components/change_password.tsx b/webpack/account/components/change_password.tsx index 01862cdb1..85fbaaa42 100644 --- a/webpack/account/components/change_password.tsx +++ b/webpack/account/components/change_password.tsx @@ -6,7 +6,7 @@ import { WidgetHeader, WidgetBody, SaveBtn -} from "../../ui"; +} from "../../ui/index"; import { SpecialStatus } from "../../resources/tagged_resources"; import Axios from "axios"; import { API } from "../../api/index"; diff --git a/webpack/account/components/delete_account.tsx b/webpack/account/components/delete_account.tsx index 18b6c9b0e..298492bcf 100644 --- a/webpack/account/components/delete_account.tsx +++ b/webpack/account/components/delete_account.tsx @@ -7,7 +7,7 @@ import { WidgetBody, Col, Row -} from "../../ui"; +} from "../../ui/index"; import { DeleteAccountProps, DeleteAccountState } from "../interfaces"; import { Content } from "../../constants"; diff --git a/webpack/account/components/settings.tsx b/webpack/account/components/settings.tsx index bde674c10..1cbe85d72 100644 --- a/webpack/account/components/settings.tsx +++ b/webpack/account/components/settings.tsx @@ -1,6 +1,8 @@ import * as React from "react"; import { t } from "i18next"; -import { BlurableInput, Widget, WidgetHeader, WidgetBody, SaveBtn } from "../../ui"; +import { + BlurableInput, Widget, WidgetHeader, WidgetBody, SaveBtn +} from "../../ui/index"; import { SettingsPropTypes } from "../interfaces"; export class Settings extends React.Component { diff --git a/webpack/account/index.tsx b/webpack/account/index.tsx index 8e53ea753..1bded44f8 100644 --- a/webpack/account/index.tsx +++ b/webpack/account/index.tsx @@ -3,7 +3,7 @@ import { t } from "i18next"; import { connect } from "react-redux"; import { Settings, DeleteAccount, ChangePassword } from "./components"; import { Props } from "./interfaces"; -import { Page, Row, Col } from "../ui"; +import { Page, Row, Col } from "../ui/index"; import { mapStateToProps } from "./state_to_props"; import { User } from "../auth/interfaces"; import { edit, save } from "../api/crud"; diff --git a/webpack/api/crud.ts b/webpack/api/crud.ts index eb63fcfa8..1f032f2d9 100644 --- a/webpack/api/crud.ts +++ b/webpack/api/crud.ts @@ -8,7 +8,9 @@ import { import { GetState, ReduxAction } from "../redux/interfaces"; import { API } from "./index"; import axios from "axios"; -import { updateOK, updateNO, destroyOK, destroyNO, GeneralizedError } from "../resources/actions"; +import { + updateOK, updateNO, destroyOK, destroyNO, GeneralizedError +} from "../resources/actions"; import { UnsafeError } from "../interfaces"; import { findByUuid } from "../resources/reducer"; import { generateUuid } from "../resources/util"; diff --git a/webpack/api/maybe_start_tracking.ts b/webpack/api/maybe_start_tracking.ts index 480b35a84..49e893553 100644 --- a/webpack/api/maybe_start_tracking.ts +++ b/webpack/api/maybe_start_tracking.ts @@ -5,7 +5,8 @@ const BLACKLIST: ResourceName[] = [ "Log", "Image", "WebcamFeed", - "User" + "User", + "WebAppConfig", ]; export function maybeStartTracking(uuid: string) { diff --git a/webpack/app.tsx b/webpack/app.tsx index 6d7057465..d0f1443e6 100644 --- a/webpack/app.tsx +++ b/webpack/app.tsx @@ -20,6 +20,7 @@ import { Content } from "./constants"; import { catchErrors } from "./util"; import { Session } from "./session"; import { BooleanSetting } from "./session_keys"; +import { getPathArray } from "./history"; /** Remove 300ms delay on touch devices - https://github.com/ftlabs/fastclick */ const fastClick = require("fastclick"); @@ -99,7 +100,7 @@ export class App extends React.Component { render() { const syncLoaded = this.isLoaded; - const currentPath = window.location.pathname; + const currentPage = getPathArray()[2]; return
{ /> {!syncLoaded && } {syncLoaded && this.props.children} - {!currentPath.startsWith("/app/controls") && - !currentPath.startsWith("/app/account") && - !currentPath.startsWith("/app/regimens") && + {!(["controls", "account", "regimens"].includes(currentPage)) && { import { getDevice } from "../../device"; import { store } from "../../redux/store"; import { Actions } from "../../constants"; -import { startTracking, outstandingRequests, stopTracking, cleanUUID } from "../data_consistency"; +import { + startTracking, outstandingRequests, stopTracking, cleanUUID +} from "../data_consistency"; const unprocessedUuid = "~UU.ID~"; const niceUuid = cleanUUID(unprocessedUuid); diff --git a/webpack/connectivity/auto_sync.ts b/webpack/connectivity/auto_sync.ts index a2d0bb1d5..88e49ad61 100644 --- a/webpack/connectivity/auto_sync.ts +++ b/webpack/connectivity/auto_sync.ts @@ -1,6 +1,8 @@ import { GetState } from "../redux/interfaces"; import { maybeDetermineUuid } from "../resources/selectors"; -import { ResourceName, TaggedResource, SpecialStatus } from "../resources/tagged_resources"; +import { + ResourceName, TaggedResource, SpecialStatus +} from "../resources/tagged_resources"; import { overwrite, init } from "../api/crud"; import { handleInbound } from "./auto_sync_handle_inbound"; import { SyncPayload, MqttDataResult, Reason, UpdateMqttData } from "./interfaces"; diff --git a/webpack/controls/axis_display_group.tsx b/webpack/controls/axis_display_group.tsx index a1a6bc746..5b2ce5561 100644 --- a/webpack/controls/axis_display_group.tsx +++ b/webpack/controls/axis_display_group.tsx @@ -1,6 +1,6 @@ import * as React from "react"; import { t } from "i18next"; -import { Row, Col } from "../ui"; +import { Row, Col } from "../ui/index"; import { AxisDisplayGroupProps } from "./interfaces"; import { isNumber } from "lodash"; diff --git a/webpack/controls/axis_input_box_group.tsx b/webpack/controls/axis_input_box_group.tsx index e07ce22c7..a672d2f77 100644 --- a/webpack/controls/axis_input_box_group.tsx +++ b/webpack/controls/axis_input_box_group.tsx @@ -1,7 +1,7 @@ import * as React from "react"; import { AxisInputBox } from "./axis_input_box"; import { t } from "i18next"; -import { Row, Col } from "../ui"; +import { Row, Col } from "../ui/index"; import { AxisInputBoxGroupProps, AxisInputBoxGroupState, diff --git a/webpack/controls/controls.tsx b/webpack/controls/controls.tsx index 4a681c7e4..9551774cb 100644 --- a/webpack/controls/controls.tsx +++ b/webpack/controls/controls.tsx @@ -1,7 +1,7 @@ import * as React from "react"; import { connect } from "react-redux"; import { Peripherals } from "./peripherals"; -import { Row, Page, Col } from "../ui"; +import { Row, Page, Col } from "../ui/index"; import { mapStateToProps } from "./state_to_props"; import { WebcamPanel } from "./webcam"; import { Props, MoveProps } from "./interfaces"; diff --git a/webpack/controls/move.tsx b/webpack/controls/move.tsx index 92b1f5c2a..819d20f02 100644 --- a/webpack/controls/move.tsx +++ b/webpack/controls/move.tsx @@ -4,7 +4,7 @@ import { changeStepSize, moveAbs } from "../devices/actions"; import { EStopButton } from "../devices/components/e_stop_btn"; import { JogButtons } from "./jog_buttons"; import { AxisInputBoxGroup } from "./axis_input_box_group"; -import { Row, Col, Widget, WidgetBody, WidgetHeader } from "../ui"; +import { Row, Col, Widget, WidgetBody, WidgetHeader } from "../ui/index"; import { StepSizeSelector } from "./step_size_selector"; import { MustBeOnline } from "../devices/must_be_online"; import { ToolTips } from "../constants"; @@ -52,113 +52,111 @@ export class Move extends React.Component { ? "Scaled Encoder (mm)" : "Scaled Encoder (steps)"; - return ( - - - - -
- -
- -
-
- -
-
- -
- -
- -
-
- -
-
-
- -
- - - + +
; } } diff --git a/webpack/controls/peripherals/index.tsx b/webpack/controls/peripherals/index.tsx index 04e1eb863..5776c7d65 100644 --- a/webpack/controls/peripherals/index.tsx +++ b/webpack/controls/peripherals/index.tsx @@ -3,10 +3,12 @@ import { t } from "i18next"; import { error } from "farmbot-toastr"; import { PeripheralList } from "./peripheral_list"; import { PeripheralForm } from "./peripheral_form"; -import { Widget, WidgetBody, WidgetHeader, SaveBtn } from "../../ui"; +import { Widget, WidgetBody, WidgetHeader, SaveBtn } from "../../ui/index"; import { PeripheralsProps } from "../../devices/interfaces"; import { PeripheralState } from "./interfaces"; -import { TaggedPeripheral, getArrayStatus, SpecialStatus } from "../../resources/tagged_resources"; +import { + TaggedPeripheral, getArrayStatus, SpecialStatus +} from "../../resources/tagged_resources"; import { saveAll, init } from "../../api/crud"; import { ToolTips } from "../../constants"; import * as _ from "lodash"; diff --git a/webpack/controls/toggle_button.tsx b/webpack/controls/toggle_button.tsx index 9a8c7f8e7..d8d43339f 100644 --- a/webpack/controls/toggle_button.tsx +++ b/webpack/controls/toggle_button.tsx @@ -42,13 +42,11 @@ export class ToggleButton extends React.Component { render() { const cb = () => !this.props.disabled && this.props.toggleAction(); - return ( - - ); + return ; } } diff --git a/webpack/controls/webcam/edit.tsx b/webpack/controls/webcam/edit.tsx index 7b5bb26c7..67c552ad2 100644 --- a/webpack/controls/webcam/edit.tsx +++ b/webpack/controls/webcam/edit.tsx @@ -27,28 +27,26 @@ export function Edit(props: WebcamPanelProps) { const unsaved = props .feeds .filter(x => x.specialStatus === SpecialStatus.DIRTY); - return ( - - - - - - -
- {rows} -
-
- ); + return + + + + + +
+ {rows} +
+
; } diff --git a/webpack/controls/webcam/show.tsx b/webpack/controls/webcam/show.tsx index 9522fb468..eab98d947 100644 --- a/webpack/controls/webcam/show.tsx +++ b/webpack/controls/webcam/show.tsx @@ -1,11 +1,10 @@ import * as React from "react"; -import { Widget, WidgetHeader } from "../../ui/index"; +import { Widget, WidgetHeader, FallbackImg } from "../../ui/index"; import { t } from "i18next"; import { ToolTips } from "../../constants"; import { WebcamPanelProps } from "./interfaces"; import { PLACEHOLDER_FARMBOT } from "../../farmware/images/image_flipper"; import { Flipper } from "./flipper"; -import { FallbackImg } from "../../ui/fallback_img"; import { sortedFeeds } from "./edit"; type State = { @@ -54,41 +53,39 @@ export class Show extends React.Component { const title = flipper.current.name || "Webcam Feeds"; const msg = this.getMessage(flipper.current.url); const imageClass = msg.length > 0 ? "no-flipper-image-container" : ""; - return ( - - - - - -
-
-
-

{msg}

- -
- - + return + + + + +
+
+
+

{msg}

+
+ +
- - ); +
+
; } } diff --git a/webpack/devices/__tests__/actions_test.ts b/webpack/devices/__tests__/actions_test.ts index a37e7b8ca..8927463c1 100644 --- a/webpack/devices/__tests__/actions_test.ts +++ b/webpack/devices/__tests__/actions_test.ts @@ -29,16 +29,10 @@ jest.mock("farmbot-toastr", () => ({ error: mockError })); +let mockGetRelease: Promise<{}> = Promise.resolve({}); jest.mock("axios", () => ({ default: { - get: jest.fn(() => { return Promise.reject("error"); }) - .mockImplementationOnce(() => { return Promise.resolve(); }) - .mockImplementationOnce(() => { - return Promise.resolve({ data: { tag_name: "v1.0.0" } }); - }) - .mockImplementationOnce(() => { - return Promise.resolve({ data: { tag_name: "v1.0.0-beta" } }); - }) + get: jest.fn(() => { return mockGetRelease; }) } })); @@ -260,6 +254,7 @@ describe("fetchReleases()", () => { }); it("fetches latest OS release version", async () => { + mockGetRelease = Promise.resolve({ data: { tag_name: "v1.0.0" } }); const dispatch = jest.fn(); await actions.fetchReleases("url")(dispatch, jest.fn()); expect(axios.get).toHaveBeenCalledWith("url"); @@ -271,6 +266,7 @@ describe("fetchReleases()", () => { }); it("fetches latest beta OS release version", async () => { + mockGetRelease = Promise.resolve({ data: { tag_name: "v1.0.0-beta" } }); const dispatch = jest.fn(); await actions.fetchReleases("url", { beta: true })(dispatch, jest.fn()); expect(axios.get).toHaveBeenCalledWith("url"); @@ -282,6 +278,7 @@ describe("fetchReleases()", () => { }); it("fails to fetches latest OS release version", async () => { + mockGetRelease = Promise.reject("error"); const dispatch = jest.fn(); await actions.fetchReleases("url")(dispatch, jest.fn()); await expect(axios.get).toHaveBeenCalledWith("url"); @@ -294,6 +291,7 @@ describe("fetchReleases()", () => { }); it("fails to fetches latest beta OS release version", async () => { + mockGetRelease = Promise.reject("error"); const dispatch = jest.fn(); await actions.fetchReleases("url", { beta: true })(dispatch, jest.fn()); await expect(axios.get).toHaveBeenCalledWith("url"); diff --git a/webpack/devices/__tests__/must_be_online_test.tsx b/webpack/devices/__tests__/must_be_online_test.tsx index 40e50fb6c..e50264176 100644 --- a/webpack/devices/__tests__/must_be_online_test.tsx +++ b/webpack/devices/__tests__/must_be_online_test.tsx @@ -1,6 +1,6 @@ import * as React from "react"; import { shallow } from "enzyme"; -import { MustBeOnline } from "../must_be_online"; +import { MustBeOnline, isBotUp } from "../must_be_online"; describe("", function () { it("Covers content when status is 'unknown'", function () { @@ -29,3 +29,15 @@ describe("", function () { expect(overlay.hasClass("banner")).toBeFalsy(); }); }); + +describe("isBotUp()", () => { + it("is up", () => { + expect(isBotUp("synced")).toBeTruthy(); + }); + + it("is not up", () => { + expect(isBotUp("unknown")).toBeFalsy(); + expect(isBotUp("maintenance")).toBeFalsy(); + expect(isBotUp(undefined)).toBeFalsy(); + }); +}); diff --git a/webpack/devices/components/__tests__/e_stop_button_test.tsx b/webpack/devices/components/__tests__/e_stop_button_test.tsx new file mode 100644 index 000000000..27b06ddc2 --- /dev/null +++ b/webpack/devices/components/__tests__/e_stop_button_test.tsx @@ -0,0 +1,29 @@ +import * as React from "react"; +import { mount } from "enzyme"; +import { EStopButton } from "../e_stop_btn"; +import { bot } from "../../../__test_support__/fake_state/bot"; +import { taggedUser } from "../../../__test_support__/user"; + +describe("", () => { + it("renders", () => { + bot.hardware.informational_settings.sync_status = "synced"; + const wrapper = mount(); + expect(wrapper.text()).toEqual("E-STOP"); + expect(wrapper.find("button").hasClass("red")).toBeTruthy(); + }); + + it("grayed out", () => { + bot.hardware.informational_settings.sync_status = undefined; + const wrapper = mount(); + expect(wrapper.text()).toEqual("E-STOP"); + expect(wrapper.find("button").hasClass("gray")).toBeTruthy(); + }); + + it("locked", () => { + bot.hardware.informational_settings.sync_status = "synced"; + bot.hardware.informational_settings.locked = true; + const wrapper = mount(); + expect(wrapper.text()).toEqual("UNLOCK"); + expect(wrapper.find("button").hasClass("yellow")).toBeTruthy(); + }); +}); diff --git a/webpack/devices/components/__tests__/farmbot_os_settings_test.tsx b/webpack/devices/components/__tests__/farmbot_os_settings_test.tsx index 87b7ae9ee..7c62134b2 100644 --- a/webpack/devices/components/__tests__/farmbot_os_settings_test.tsx +++ b/webpack/devices/components/__tests__/farmbot_os_settings_test.tsx @@ -1,10 +1,7 @@ +let mockReleaseNoteData = {}; jest.mock("axios", () => ({ default: { - get: jest.fn(() => { return Promise.resolve({ data: "notes" }); }) - .mockImplementationOnce(() => { return Promise.resolve(); }) - .mockImplementationOnce(() => { - return Promise.resolve({ data: "intro\n\n# v6\n\n* note" }); - }) + get: jest.fn(() => { return Promise.resolve(mockReleaseNoteData); }) } })); @@ -12,9 +9,7 @@ import * as React from "react"; import { FarmbotOsSettings } from "../farmbot_os_settings"; import { mount } from "enzyme"; import { bot } from "../../../__test_support__/fake_state/bot"; -import { fakeState } from "../../../__test_support__/fake_state"; import { fakeResource } from "../../../__test_support__/fake_resource"; -import { AuthState } from "../../../auth/interfaces"; import { FbosDetails } from "../fbos_settings/farmbot_os_row"; import { FarmbotOsProps } from "../../interfaces"; import axios from "axios"; @@ -25,7 +20,6 @@ describe("", () => { account: fakeResource("Device", { id: 0, name: "", tz_offset_hrs: 0 }), dispatch: jest.fn(), bot: bot, - auth: fakeState().auth as AuthState, botToMqttStatus: "up" }; } @@ -39,6 +33,7 @@ describe("", () => { }); it("fetches OS release notes", async () => { + mockReleaseNoteData = { data: "intro\n\n# v6\n\n* note" }; const osSettings = await mount(); await expect(axios.get).toHaveBeenCalledWith( expect.stringContaining("RELEASE_NOTES.md")); @@ -47,6 +42,7 @@ describe("", () => { }); it("doesn't fetch OS release notes", async () => { + mockReleaseNoteData = { data: "empty notes" }; const osSettings = await mount(); await expect(axios.get).toHaveBeenCalledWith( expect.stringContaining("RELEASE_NOTES.md")); diff --git a/webpack/devices/components/__tests__/rpi_gpio_diagram_test.tsx b/webpack/devices/components/__tests__/rpi_gpio_diagram_test.tsx index d8976a128..9c89c15c6 100644 --- a/webpack/devices/components/__tests__/rpi_gpio_diagram_test.tsx +++ b/webpack/devices/components/__tests__/rpi_gpio_diagram_test.tsx @@ -1,7 +1,7 @@ import * as React from "react"; import { mount } from "enzyme"; import { RpiGpioDiagram, RpiGpioDiagramProps } from "../rpi_gpio_diagram"; -import { Color } from "../../../ui/colors"; +import { Color } from "../../../ui/index"; describe("", () => { function fakeProps(): RpiGpioDiagramProps { diff --git a/webpack/devices/components/boolean_mcu_input_group.tsx b/webpack/devices/components/boolean_mcu_input_group.tsx index d651b8c40..8bd888c44 100644 --- a/webpack/devices/components/boolean_mcu_input_group.tsx +++ b/webpack/devices/components/boolean_mcu_input_group.tsx @@ -23,34 +23,32 @@ export function BooleanMCUInputGroup(props: BooleanMCUInputGroupProps) { const { mcu_params } = bot.hardware; - return ( - - - - - - - settingToggle(x, bot, displayAlert)} /> - - - settingToggle(y, bot, displayAlert)} /> - - - settingToggle(z, bot, displayAlert)} /> - - - ); + return + + + + + + settingToggle(x, bot, displayAlert)} /> + + + settingToggle(y, bot, displayAlert)} /> + + + settingToggle(z, bot, displayAlert)} /> + + ; } diff --git a/webpack/devices/components/e_stop_btn.tsx b/webpack/devices/components/e_stop_btn.tsx index 444c31cb8..18409f826 100644 --- a/webpack/devices/components/e_stop_btn.tsx +++ b/webpack/devices/components/e_stop_btn.tsx @@ -2,13 +2,15 @@ import * as React from "react"; import { t } from "i18next"; import { emergencyLock, emergencyUnlock } from "../actions"; import { EStopButtonProps } from "../interfaces"; +import { isBotUp } from "../must_be_online"; export class EStopButton extends React.Component { render() { const i = this.props.bot.hardware.informational_settings; const isLocked = !!i.locked; const toggleEmergencyLock = isLocked ? emergencyUnlock : emergencyLock; - const emergencyLockStatusColor = isLocked ? "yellow" : "red"; + const color = isLocked ? "yellow" : "red"; + const emergencyLockStatusColor = isBotUp(i.sync_status) ? color : "gray"; const emergencyLockStatusText = isLocked ? "UNLOCK" : "E-STOP"; if (this.props.user) { diff --git a/webpack/devices/components/fbos_settings/__tests__/os_update_button_test.tsx b/webpack/devices/components/fbos_settings/__tests__/os_update_button_test.tsx index 87fee2c29..e5c79c07f 100644 --- a/webpack/devices/components/fbos_settings/__tests__/os_update_button_test.tsx +++ b/webpack/devices/components/fbos_settings/__tests__/os_update_button_test.tsx @@ -27,6 +27,15 @@ describe("", () => { const osUpdateButton = buttons.find("button").last(); expect(osUpdateButton.text()).toBe("Can't Connect to release server"); }); + it("renders buttons: no beta releases", () => { + bot.hardware.configuration.beta_opt_in = true; + const buttons = mount(); + expect(buttons.find("button").length).toBe(1); + const autoUpdate = buttons.find("button").first(); + expect(autoUpdate.hasClass("yellow")).toBeTruthy(); + const osUpdateButton = buttons.find("button").last(); + expect(osUpdateButton.text()).toBe("No beta releases available"); + }); it("up to date", () => { bot.hardware.informational_settings.controller_version = "3.1.6"; const buttons = mount(); diff --git a/webpack/devices/components/fbos_settings/board_type.tsx b/webpack/devices/components/fbos_settings/board_type.tsx index 148edbb81..6b3c618fe 100644 --- a/webpack/devices/components/fbos_settings/board_type.tsx +++ b/webpack/devices/components/fbos_settings/board_type.tsx @@ -1,7 +1,6 @@ import * as React from "react"; -import { Row, Col, DropDownItem } from "../../../ui/index"; +import { Row, Col, DropDownItem, FBSelect } from "../../../ui/index"; import { t } from "i18next"; -import { FBSelect } from "../../../ui/new_fb_select"; import { getDevice } from "../../../device"; import { info, error } from "farmbot-toastr"; import { FirmwareHardware } from "farmbot"; diff --git a/webpack/devices/components/fbos_settings/camera_selection.tsx b/webpack/devices/components/fbos_settings/camera_selection.tsx index 5014b02b8..f6473d775 100644 --- a/webpack/devices/components/fbos_settings/camera_selection.tsx +++ b/webpack/devices/components/fbos_settings/camera_selection.tsx @@ -1,12 +1,11 @@ import * as React from "react"; -import { DropDownItem, Row, Col } from "../../../ui/index"; +import { DropDownItem, Row, Col, FBSelect } from "../../../ui/index"; import { t } from "i18next"; import { CameraSelectionProps, CameraSelectionState } from "../../interfaces"; import { info, success, error } from "farmbot-toastr/dist"; import { getDevice } from "../../../device"; -import { FBSelect } from "../../../ui/new_fb_select"; import { ColWidth } from "../farmbot_os_settings"; const CAMERA_CHOICES = [ diff --git a/webpack/devices/components/fbos_settings/os_update_button.tsx b/webpack/devices/components/fbos_settings/os_update_button.tsx index a617f5b42..d654651a4 100644 --- a/webpack/devices/components/fbos_settings/os_update_button.tsx +++ b/webpack/devices/components/fbos_settings/os_update_button.tsx @@ -28,7 +28,9 @@ export let OsUpdateButton = ({ bot }: BotProp) => { buttonColor = "green"; } } else { - buttonStr = "Can't Connect to release server"; + buttonStr = beta_opt_in + ? "No beta releases available" + : "Can't Connect to release server"; } const osUpdateJob = (bot.hardware.jobs || {})["FBOS_OTA"]; diff --git a/webpack/devices/components/hardware_settings.tsx b/webpack/devices/components/hardware_settings.tsx index e80b4238a..4e441ede6 100644 --- a/webpack/devices/components/hardware_settings.tsx +++ b/webpack/devices/components/hardware_settings.tsx @@ -1,9 +1,8 @@ import * as React from "react"; import { MCUFactoryReset, bulkToggleControlPanel } from "../actions"; -import { Widget, WidgetHeader, WidgetBody } from "../../ui/index"; +import { Widget, WidgetHeader, WidgetBody, SaveBtn } from "../../ui/index"; import { HardwareSettingsProps } from "../interfaces"; import { MustBeOnline } from "../must_be_online"; -import { SaveBtn } from "../../ui/save_button"; import { ToolTips } from "../../constants"; import { DangerZone } from "./hardware_settings/danger_zone"; import { PinGuard } from "./hardware_settings/pin_guard"; @@ -21,59 +20,57 @@ export class HardwareSettings extends render() { const { bot, dispatch } = this.props; const { sync_status } = this.props.bot.hardware.informational_settings; - return ( - - - - - - - - - -
- -
- - - - - -
-
-
- ); + +
+ +
+ + + + + +
+ + ; } } diff --git a/webpack/devices/components/hardware_settings/__tests__/encoder_type_test.tsx b/webpack/devices/components/hardware_settings/__tests__/encoder_type_test.tsx index 5d837065b..d93c1a02b 100644 --- a/webpack/devices/components/hardware_settings/__tests__/encoder_type_test.tsx +++ b/webpack/devices/components/hardware_settings/__tests__/encoder_type_test.tsx @@ -1,7 +1,9 @@ import * as React from "react"; -import { EncoderType, EncoderTypeProps, LOOKUP, findByType, isEncoderValue } from "../encoder_type"; +import { + EncoderType, EncoderTypeProps, LOOKUP, findByType, isEncoderValue +} from "../encoder_type"; import { shallow } from "enzyme"; -import { FBSelect } from "../../../../ui/new_fb_select"; +import { FBSelect } from "../../../../ui/index"; import { Encoder } from "farmbot"; describe("", () => { diff --git a/webpack/devices/components/hardware_settings/encoder_type.tsx b/webpack/devices/components/hardware_settings/encoder_type.tsx index b65e076a6..591318f30 100644 --- a/webpack/devices/components/hardware_settings/encoder_type.tsx +++ b/webpack/devices/components/hardware_settings/encoder_type.tsx @@ -1,8 +1,7 @@ import * as React from "react"; import { McuParams, Encoder, McuParamName } from "farmbot/dist"; import { t } from "i18next"; -import { FBSelect } from "../../../ui/new_fb_select"; -import { DropDownItem } from "../../../ui/fb_select"; +import { FBSelect, DropDownItem } from "../../../ui/index"; export interface EncoderTypeProps { hardware: McuParams; diff --git a/webpack/devices/components/numeric_mcu_input_group.tsx b/webpack/devices/components/numeric_mcu_input_group.tsx index 61e940f6f..b5169ec11 100644 --- a/webpack/devices/components/numeric_mcu_input_group.tsx +++ b/webpack/devices/components/numeric_mcu_input_group.tsx @@ -2,8 +2,7 @@ import * as React from "react"; import { McuInputBox } from "./mcu_input_box"; import { SpacePanelToolTip } from "./space_panel_tool_tip"; import { NumericMCUInputGroupProps } from "./interfaces"; -import { Row } from "../../ui/row"; -import { Col } from "../../ui/index"; +import { Row, Col } from "../../ui/index"; export function NumericMCUInputGroup(props: NumericMCUInputGroupProps) { diff --git a/webpack/devices/components/pin_bindings.tsx b/webpack/devices/components/pin_bindings.tsx index 788b519f7..f2b88758d 100644 --- a/webpack/devices/components/pin_bindings.tsx +++ b/webpack/devices/components/pin_bindings.tsx @@ -2,9 +2,11 @@ import * as React from "react"; import { t } from "i18next"; import * as _ from "lodash"; import { - Widget, WidgetBody, WidgetHeader, Row, Col, BlurableInput, DropDownItem + Widget, WidgetBody, WidgetHeader, + Row, Col, + BlurableInput, + FBSelect, DropDownItem } from "../../ui/index"; -import { FBSelect } from "../../ui/new_fb_select"; import { ToolTips } from "../../constants"; import { BotState } from "../interfaces"; import { registerGpioPin, unregisterGpioPin } from "../actions"; diff --git a/webpack/devices/components/pin_guard_input_group.tsx b/webpack/devices/components/pin_guard_input_group.tsx index 013ba38d3..73da8f89f 100644 --- a/webpack/devices/components/pin_guard_input_group.tsx +++ b/webpack/devices/components/pin_guard_input_group.tsx @@ -1,8 +1,7 @@ import * as React from "react"; import { McuInputBox } from "./mcu_input_box"; import { PinGuardMCUInputGroupProps } from "./interfaces"; -import { Row } from "../../ui/row"; -import { Col } from "../../ui/index"; +import { Row, Col } from "../../ui/index"; import { settingToggle } from "../actions"; import { ToggleButton } from "../../controls/toggle_button"; import { isUndefined } from "util"; diff --git a/webpack/devices/connectivity/__tests__/diagram_test.tsx b/webpack/devices/connectivity/__tests__/diagram_test.tsx index 80cee6d42..b518e8376 100644 --- a/webpack/devices/connectivity/__tests__/diagram_test.tsx +++ b/webpack/devices/connectivity/__tests__/diagram_test.tsx @@ -11,7 +11,7 @@ import { DiagramNodes, getConnectionColor } from "../diagram"; -import { Color } from "../../../ui/colors"; +import { Color } from "../../../ui/index"; describe("", () => { function fakeProps(): ConnectivityDiagramProps { diff --git a/webpack/devices/connectivity/diagram.tsx b/webpack/devices/connectivity/diagram.tsx index 50c9e74b7..450a2bcfb 100644 --- a/webpack/devices/connectivity/diagram.tsx +++ b/webpack/devices/connectivity/diagram.tsx @@ -1,7 +1,7 @@ import * as React from "react"; import { StatusRowProps } from "./connectivity_row"; import { CowardlyDictionary } from "../../util"; -import { Color } from "../../ui/colors"; +import { Color } from "../../ui/index"; export interface ConnectivityDiagramProps { rowData: StatusRowProps[]; diff --git a/webpack/devices/devices.tsx b/webpack/devices/devices.tsx index c4fd10dd6..a9ec6610a 100644 --- a/webpack/devices/devices.tsx +++ b/webpack/devices/devices.tsx @@ -2,7 +2,7 @@ import * as React from "react"; import { connect } from "react-redux"; import { HardwareSettings } from "./components/hardware_settings"; import { FarmbotOsSettings } from "./components/farmbot_os_settings"; -import { Page, Col, Row } from "../ui"; +import { Page, Col, Row } from "../ui/index"; import { mapStateToProps } from "./state_to_props"; import { Props } from "./interfaces"; import { ConnectivityPanel } from "./connectivity/index"; @@ -60,7 +60,6 @@ export class Devices extends React.Component { account={this.props.deviceAccount} dispatch={this.props.dispatch} bot={this.props.bot} - auth={this.props.auth} botToMqttStatus={botToMqttStatus} /> {children}
; diff --git a/webpack/devices/reducer.ts b/webpack/devices/reducer.ts index caecca2b4..74e3ea10f 100644 --- a/webpack/devices/reducer.ts +++ b/webpack/devices/reducer.ts @@ -4,7 +4,9 @@ import { Actions } from "../constants"; import { EncoderDisplay } from "../controls/interfaces"; import { EXPECTED_MAJOR, EXPECTED_MINOR } from "./actions"; import { BooleanSetting } from "../session_keys"; -import { maybeNegateStatus, maybeNegateConsistency } from "../connectivity/maybe_negate_status"; +import { + maybeNegateStatus, maybeNegateConsistency +} from "../connectivity/maybe_negate_status"; import { EdgeStatus } from "../connectivity/interfaces"; import { ReduxAction } from "../redux/interfaces"; import { connectivityReducer } from "../connectivity/reducer"; diff --git a/webpack/devices/timezones/timezone_selector.tsx b/webpack/devices/timezones/timezone_selector.tsx index 15b5c40b6..090d7042e 100644 --- a/webpack/devices/timezones/timezone_selector.tsx +++ b/webpack/devices/timezones/timezone_selector.tsx @@ -1,8 +1,7 @@ import * as React from "react"; -import { DropDownItem } from "../../ui/fb_select"; +import { FBSelect, DropDownItem } from "../../ui/index"; import { list } from "./tz_list"; import { inferTimezone } from "./guess_timezone"; -import { FBSelect } from "../../ui/new_fb_select"; import * as _ from "lodash"; const CHOICES: DropDownItem[] = list.map(x => ({ label: x, value: x })); diff --git a/webpack/extras/fallback_widget.tsx b/webpack/extras/fallback_widget.tsx index 9fa445690..fec74c650 100644 --- a/webpack/extras/fallback_widget.tsx +++ b/webpack/extras/fallback_widget.tsx @@ -1,6 +1,6 @@ import * as React from "react"; import { t } from "i18next"; -import { Widget, WidgetHeader } from "../ui"; +import { Widget, WidgetHeader } from "../ui/index"; /* * Widget to display if the desired widget fails to load. @@ -25,15 +25,13 @@ export class FallbackWidget extends React.Component { render() { - return ( - - -
- {t("Widget load failed.")} -
-
- ); + return + +
+ {t("Widget load failed.")} +
+
; } } diff --git a/webpack/farm_designer/__tests__/actions_test.ts b/webpack/farm_designer/__tests__/actions_test.ts index f42211149..186598931 100644 --- a/webpack/farm_designer/__tests__/actions_test.ts +++ b/webpack/farm_designer/__tests__/actions_test.ts @@ -1,18 +1,10 @@ const mockHistory = jest.fn(); +let mockPath = "/app/designer/plants"; jest.mock("../../history", () => ({ history: { push: mockHistory }, - getPathArray: jest.fn() - .mockImplementationOnce(() => { - return "/app/designer/plants".split("/"); - }) - .mockImplementationOnce(() => { - return "/app/designer/plants/1/edit".split("/"); - }) - .mockImplementationOnce(() => { - return "/app/designer/plants/1".split("/"); - }) + getPathArray: jest.fn(() => { return mockPath.split("/"); }) })); jest.mock("../../api/crud", () => ({ @@ -60,16 +52,27 @@ describe("movePlant", () => { movePlantTest("too low", { x: -10000, y: -10000 }, { x: 0, y: 0 }); }); -describe("close plant", () => { - it("closes plant info", () => { +describe("closePlantInfo()", () => { + it("no plant info open", () => { + mockPath = "/app/designer/plants"; const dispatch = jest.fn(); - closePlantInfo(dispatch)(); // no plant info open + closePlantInfo(dispatch)(); expect(mockHistory).not.toHaveBeenCalled(); expect(dispatch).not.toHaveBeenCalled(); - closePlantInfo(dispatch)(); // plant edit open + }); + + it("plant edit open", () => { + mockPath = "/app/designer/plants/1/edit"; + const dispatch = jest.fn(); + closePlantInfo(dispatch)(); expect(mockHistory).not.toHaveBeenCalled(); expect(dispatch).not.toHaveBeenCalled(); - closePlantInfo(dispatch)(); // plant info open + }); + + it("plant info open", () => { + mockPath = "/app/designer/plants/1"; + const dispatch = jest.fn(); + closePlantInfo(dispatch)(); expect(mockHistory).toHaveBeenCalledWith("/app/designer/plants"); expect(dispatch).toHaveBeenCalledWith({ payload: undefined, type: "SELECT_PLANT" diff --git a/webpack/farm_designer/farm_events/add_farm_event.tsx b/webpack/farm_designer/farm_events/add_farm_event.tsx index 9b68f8092..437a8b4f5 100644 --- a/webpack/farm_designer/farm_events/add_farm_event.tsx +++ b/webpack/farm_designer/farm_events/add_farm_event.tsx @@ -87,18 +87,16 @@ export class AddFarmEvent } placeholderTemplate(children: JSXChildren) { - return ( -
-
-

{t("No Executables")}

-
-
- -
+ return
+
+

{t("No Executables")}

- ); +
+ +
+
; } render() { @@ -108,17 +106,15 @@ export class AddFarmEvent // to mapStateToProps instead of juggling arrays. const fe = uuid && this.props.farmEvents.filter(x => x.uuid === uuid)[0]; if (fe) { - return ( - - ); + return ; } else { return this .placeholderTemplate(((this.executable) ? this.loading : this.none)()); diff --git a/webpack/farm_designer/farm_events/edit_fe_form.tsx b/webpack/farm_designer/farm_events/edit_fe_form.tsx index 088c3a182..8878b306a 100644 --- a/webpack/farm_designer/farm_events/edit_fe_form.tsx +++ b/webpack/farm_designer/farm_events/edit_fe_form.tsx @@ -4,29 +4,17 @@ import * as _ from "lodash"; import { t } from "i18next"; import { success, error } from "farmbot-toastr"; import { TaggedFarmEvent, SpecialStatus } from "../../resources/tagged_resources"; -import { - TimeUnit, - ExecutableQuery, - ExecutableType -} from "../interfaces"; -import { - formatTime, - formatDate -} from "./map_state_to_props_add_edit"; +import { TimeUnit, ExecutableQuery, ExecutableType } from "../interfaces"; +import { formatTime, formatDate } from "./map_state_to_props_add_edit"; import { BackArrow, BlurableInput, - Col, - Row, - SaveBtn + Col, Row, + SaveBtn, + FBSelect, + DropDownItem } from "../../ui/index"; -import { FBSelect } from "../../ui/new_fb_select"; -import { - destroy, - save, - edit -} from "../../api/crud"; -import { DropDownItem } from "../../ui/fb_select"; +import { destroy, save, edit } from "../../api/crud"; import { history } from "../../history"; // TIL: https://stackoverflow.com/a/24900248/1064917 import { betterMerge } from "../../util"; @@ -227,81 +215,79 @@ export class EditFEForm extends React.Component { const fe = this.props.farmEvent; const repeats = this.fieldGet("timeUnit") !== NEVER; const allowRepeat = (!this.isReg && repeats); - return ( -
-
-

- { - if (!this.props.farmEvent.body.id) { - // Throw out unsaved farmevents. - this.props.dispatch(destroyOK(this.props.farmEvent)); - return; - } - }} /> - {this.props.title} -

-
-
- - - - - - - - - - - - -
+ return
+
+

+ { + if (!this.props.farmEvent.body.id) { + // Throw out unsaved farmevents. + this.props.dispatch(destroyOK(this.props.farmEvent)); + return; + } + }} /> + {this.props.title} +

- ); +
+ + + + + + + + + + + + +
+
; } } diff --git a/webpack/farm_designer/farm_events/event_time_picker.tsx b/webpack/farm_designer/farm_events/event_time_picker.tsx index 4d8358884..0202b2843 100644 --- a/webpack/farm_designer/farm_events/event_time_picker.tsx +++ b/webpack/farm_designer/farm_events/event_time_picker.tsx @@ -1,5 +1,5 @@ import * as React from "react"; -import { BlurableInput } from "../../ui/blurable_input"; +import { BlurableInput } from "../../ui/index"; import * as moment from "moment"; interface Props { diff --git a/webpack/farm_designer/farm_events/farm_event_repeat_form.tsx b/webpack/farm_designer/farm_events/farm_event_repeat_form.tsx index fb0b39b60..080651525 100644 --- a/webpack/farm_designer/farm_events/farm_event_repeat_form.tsx +++ b/webpack/farm_designer/farm_events/farm_event_repeat_form.tsx @@ -1,7 +1,8 @@ import * as React from "react"; import { t } from "i18next"; -import { Row, Col, BlurableInput, DropDownItem } from "../../ui/index"; -import { FBSelect } from "../../ui/new_fb_select"; +import { + Row, Col, BlurableInput, FBSelect, DropDownItem +} from "../../ui/index"; import { repeatOptions } from "./map_state_to_props_add_edit"; import { keyBy } from "lodash"; import { TimeUnit } from "../interfaces"; diff --git a/webpack/farm_designer/farm_events/farm_events.tsx b/webpack/farm_designer/farm_events/farm_events.tsx index 42b4351a6..4969e7ffe 100644 --- a/webpack/farm_designer/farm_events/farm_events.tsx +++ b/webpack/farm_designer/farm_events/farm_events.tsx @@ -2,7 +2,7 @@ import * as React from "react"; import { Link } from "react-router"; import { connect } from "react-redux"; import { t } from "i18next"; -import { Row } from "../../ui"; +import { Row } from "../../ui/index"; import { mapStateToProps } from "./map_state_to_props"; import { FarmEventProps, CalendarOccurrence } from "../interfaces"; import * as _ from "lodash"; @@ -25,22 +25,20 @@ export class PureFarmEvents extends React.Component { ?

{occur.heading}

:

; - return ( -

-
- {occur.timeStr} -
-
- {heading} - {subHeading} -
- - - + return
+
+ {occur.timeStr}
- ); +
+ {heading} + {subHeading} +
+ + + +
; }); } @@ -48,21 +46,19 @@ export class PureFarmEvents extends React.Component { return this.props.calendarRows.filter((day) => { return day.year == year; }).map(item => { - return ( -
-
-
- {item.month} -
-
- {item.day} -
+ return
+
+
+ {item.month}
-
- {this.innerRows(item.items)} +
+ {item.day}
- ); +
+ {this.innerRows(item.items)} +
+
; }); } @@ -117,24 +113,22 @@ export class PureFarmEvents extends React.Component { render() { - return ( -
-
-
- - {t("Designer")} - - - {t("Plants")} - - - {t("Farm Events")} - -
+ return
+
+
+ + {t("Designer")} + + + {t("Plants")} + + + {t("Farm Events")} +
- {this.props.timezoneIsSet ? this.normalContent() : this.tzwarning()}
- ); + {this.props.timezoneIsSet ? this.normalContent() : this.tzwarning()} +
; } } diff --git a/webpack/farm_designer/farm_events/map_state_to_props_add_edit.ts b/webpack/farm_designer/farm_events/map_state_to_props_add_edit.ts index 93bba126d..39b6ea178 100644 --- a/webpack/farm_designer/farm_events/map_state_to_props_add_edit.ts +++ b/webpack/farm_designer/farm_events/map_state_to_props_add_edit.ts @@ -22,7 +22,7 @@ import { TaggedSequence, TaggedRegimen } from "../../resources/tagged_resources"; -import { DropDownItem } from "../../ui/fb_select"; +import { DropDownItem } from "../../ui/index"; export let formatTime = (input: string, timeOffset: number) => { const iso = new Date(input).toISOString(); diff --git a/webpack/farm_designer/map/__tests__/drag_helpers_test.tsx b/webpack/farm_designer/map/__tests__/drag_helpers_test.tsx index aef85eeb2..f735dc81d 100644 --- a/webpack/farm_designer/map/__tests__/drag_helpers_test.tsx +++ b/webpack/farm_designer/map/__tests__/drag_helpers_test.tsx @@ -3,7 +3,7 @@ import { DragHelpers } from "../drag_helpers"; import { shallow } from "enzyme"; import { DragHelpersProps } from "../interfaces"; import { fakePlant } from "../../../__test_support__/fake_state/resources"; -import { Color } from "../../../ui/colors"; +import { Color } from "../../../ui/index"; describe("", () => { function fakeProps(): DragHelpersProps { diff --git a/webpack/farm_designer/map/__tests__/garden_map_test.tsx b/webpack/farm_designer/map/__tests__/garden_map_test.tsx index 1a9492dcf..b285db771 100644 --- a/webpack/farm_designer/map/__tests__/garden_map_test.tsx +++ b/webpack/farm_designer/map/__tests__/garden_map_test.tsx @@ -13,6 +13,11 @@ jest.mock("../../../api/crud", () => ({ save: () => "save resource", })); +let mockPath = ""; +jest.mock("../../../history", () => ({ + getPathArray: jest.fn(() => { return mockPath.split("/"); }) +})); + import * as React from "react"; import { GardenMap } from "../garden_map"; import { shallow } from "enzyme"; @@ -91,10 +96,7 @@ describe("", () => { const dispatch = jest.fn(); p.dispatch = dispatch; const wrapper = shallow(); - Object.defineProperty(location, "pathname", { - value: "/app/designer/plants/crop_search/strawberry/add", - configurable: true - }); + mockPath = "/app/designer/plants/crop_search/strawberry/add"; wrapper.find("#drop-area-svg").simulate("click", { preventDefault: jest.fn() }); @@ -105,10 +107,7 @@ describe("", () => { it("doesn't drop plant: error", () => { const wrapper = shallow(); - Object.defineProperty(location, "pathname", { - value: "/app/designer/plants/crop_search/aplant/add", - configurable: true - }); + mockPath = "/app/designer/plants/crop_search/aplant/add"; Object.defineProperty(document, "querySelector", { value: () => { }, configurable: true }); @@ -121,10 +120,7 @@ describe("", () => { it("doesn't drop plant: outside planting area", () => { const wrapper = shallow(); - Object.defineProperty(location, "pathname", { - value: "/app/designer/plants/crop_search/aplant/add", - configurable: true - }); + mockPath = "/app/designer/plants/crop_search/aplant/add"; wrapper.find("#drop-area-svg").simulate("click", { preventDefault: jest.fn(), pageX: -100, pageY: -100 }); @@ -135,9 +131,7 @@ describe("", () => { it("starts drag and sets activeSpread", async () => { const wrapper = shallow(); expect(wrapper.state()).toEqual({}); - Object.defineProperty(location, "pathname", { - value: "/app/designer/plants/1/edit/" - }); + mockPath = "/app/designer/plants/1/edit/"; await wrapper.find("#drop-area-svg").simulate("mouseDown"); expect(wrapper.state()).toEqual({ activeDragSpread: 1000, @@ -165,9 +159,7 @@ describe("", () => { }); it("drags: editing", () => { - Object.defineProperty(location, "pathname", { - value: "/app/designer/plants/1/edit", configurable: true - }); + mockPath = "/app/designer/plants/1/edit"; const p = fakeProps(); const wrapper = shallow(); expect(wrapper.state()).toEqual({}); @@ -188,9 +180,7 @@ describe("", () => { }); it("drags: selecting", () => { - Object.defineProperty(location, "pathname", { - value: "/app/designer/plants/select", configurable: true - }); + mockPath = "/app/designer/plants/select"; const p = fakeProps(); const wrapper = shallow(); expect(wrapper.state()).toEqual({}); diff --git a/webpack/farm_designer/map/__tests__/zoom_test.ts b/webpack/farm_designer/map/__tests__/zoom_test.ts index f389dd6cb..d91126dd5 100644 --- a/webpack/farm_designer/map/__tests__/zoom_test.ts +++ b/webpack/farm_designer/map/__tests__/zoom_test.ts @@ -37,12 +37,24 @@ describe("zoom utilities", () => { expect(ZoomUtils.atMinZoom()).toBeFalsy(); }); + it("beyond max zoom", () => { + mockZoomValue = 999; + const result = ZoomUtils.getZoomLevelIndex(); + expect(result).toEqual(ZoomUtils.maxZoomIndex); + }); + it("at min zoom", () => { mockZoomValue = ZoomUtils.minZoomLevel; expect(ZoomUtils.atMaxZoom()).toBeFalsy(); expect(ZoomUtils.atMinZoom()).toBeTruthy(); }); + it("beyond min zoom", () => { + mockZoomValue = -999; + const result = ZoomUtils.getZoomLevelIndex(); + expect(result).toEqual(0); + }); + it("at unknown zoom", () => { mockZoomValue = undefined; const defaultZoom = ZoomUtils.calcZoomLevel(ZoomUtils.getZoomLevelIndex()); diff --git a/webpack/farm_designer/map/drag_helpers.tsx b/webpack/farm_designer/map/drag_helpers.tsx index 84a18098d..15f25e847 100644 --- a/webpack/farm_designer/map/drag_helpers.tsx +++ b/webpack/farm_designer/map/drag_helpers.tsx @@ -3,7 +3,7 @@ import { DragHelpersProps } from "./interfaces"; import { round, getXYFromQuadrant, getMapSize } from "./util"; import { isUndefined } from "util"; import { BotPosition } from "../../devices/interfaces"; -import { Color } from "../../ui/colors"; +import { Color } from "../../ui/index"; enum Alignment { NONE = "not aligned", @@ -87,10 +87,9 @@ export function DragHelpers(props: DragHelpersProps) { {[0, 90, 180, 270].map(rotation => { - return ( - ); + return ; })} } {!dragging && // Non-active plants @@ -105,10 +104,9 @@ export function DragHelpers(props: DragHelpersProps) { {rotationArray(getAlignment(activeDragXY, gardenCoord)).map(rotation => { - return ( - ); + return ; })} } ; diff --git a/webpack/farm_designer/map/garden_map.tsx b/webpack/farm_designer/map/garden_map.tsx index df43d1967..ae41386f9 100644 --- a/webpack/farm_designer/map/garden_map.tsx +++ b/webpack/farm_designer/map/garden_map.tsx @@ -18,14 +18,16 @@ import { import { findBySlug } from "../search_selectors"; import { Grid } from "./grid"; import { MapBackground } from "./map_background"; -import { PlantLayer } from "./layers/plant_layer"; -import { PointLayer } from "./layers/point_layer"; -import { SpreadLayer } from "./layers/spread_layer"; -import { ToolSlotLayer } from "./layers/tool_slot_layer"; -import { HoveredPlantLayer } from "./layers/hovered_plant_layer"; -import { FarmBotLayer } from "./layers/farmbot_layer"; +import { + PlantLayer, + SpreadLayer, + PointLayer, + ToolSlotLayer, + FarmBotLayer, + HoveredPlantLayer, + DragHelperLayer +} from "./layers"; import { cachedCrop } from "../../open_farm/icons"; -import { DragHelperLayer } from "./layers/drag_helper_layer"; import { AxisNumberProperty } from "./interfaces"; import { SelectionBox, SelectionBoxData } from "./selection_box"; import { Actions } from "../../constants"; diff --git a/webpack/farm_designer/map/garden_map_legend.tsx b/webpack/farm_designer/map/garden_map_legend.tsx index 40ab067cd..a79378fb2 100644 --- a/webpack/farm_designer/map/garden_map_legend.tsx +++ b/webpack/farm_designer/map/garden_map_legend.tsx @@ -23,76 +23,74 @@ export function GardenMapLegend(props: GardenMapLegendProps) { const minusBtnClass = atMinZoom() ? "disabled" : ""; const menuClass = legendMenuOpen ? "active" : ""; - return ( + return
-
- - {t("Menu")} - - + className={"menu-pullout " + menuClass} + onClick={toggle("legend_menu_open")}> + + {t("Menu")} + + +
+
+
+ +
-
-
- - -
-
- - - - -
-
- -
-
-
-
-
-
-
-
- +
+ + + + +
+
+ +
+
+
+
+
+
+ +
- ); +
; } diff --git a/webpack/farm_designer/map/garden_plant.tsx b/webpack/farm_designer/map/garden_plant.tsx index 18dbc3de8..7aef0664e 100644 --- a/webpack/farm_designer/map/garden_plant.tsx +++ b/webpack/farm_designer/map/garden_plant.tsx @@ -5,7 +5,7 @@ import { round, getXYFromQuadrant } from "./util"; import { DragHelpers } from "./drag_helpers"; import { Session } from "../../session"; import { BooleanSetting } from "../../session_keys"; -import { Color } from "../../ui/colors"; +import { Color } from "../../ui/index"; export class GardenPlant extends React.Component> { diff --git a/webpack/farm_designer/map/grid.tsx b/webpack/farm_designer/map/grid.tsx index f7ba0cc01..a591eb588 100644 --- a/webpack/farm_designer/map/grid.tsx +++ b/webpack/farm_designer/map/grid.tsx @@ -2,7 +2,7 @@ import * as React from "react"; import { GridProps } from "./interfaces"; import { getXYFromQuadrant } from "./util"; import * as _ from "lodash"; -import { Color } from "../../ui/colors"; +import { Color } from "../../ui/index"; export function Grid(props: GridProps) { const { quadrant, gridSize } = props.mapTransformProps; diff --git a/webpack/farm_designer/map/layers/__tests__/plant_layer_test.tsx b/webpack/farm_designer/map/layers/__tests__/plant_layer_test.tsx index d9cc26799..41f9291b2 100644 --- a/webpack/farm_designer/map/layers/__tests__/plant_layer_test.tsx +++ b/webpack/farm_designer/map/layers/__tests__/plant_layer_test.tsx @@ -1,7 +1,6 @@ +let mockPath = "/app/designer/plants"; jest.mock("../../../../history", () => ({ - getPathArray: jest - .fn(() => { return "/app/designer/plants/select".split("/"); }) - .mockImplementationOnce(() => { return "/app/designer/plants".split("/"); }) + getPathArray: jest.fn(() => { return mockPath.split("/"); }) })); jest.mock("../../../../session", () => { @@ -59,7 +58,15 @@ describe("", () => { expect(wrapper.html()).toEqual(""); }); + it("is in clickable mode", () => { + mockPath = "/app/designer/plants"; + const p = fakeProps(); + const wrapper = shallow(); + expect(wrapper.find("Link").props().style).toEqual({}); + }); + it("is in non-clickable mode", () => { + mockPath = "/app/designer/plants/select"; const p = fakeProps(); const wrapper = shallow(); expect(wrapper.find("Link").props().style) diff --git a/webpack/farm_designer/map/layers/__tests__/tool_slot_layer_test.tsx b/webpack/farm_designer/map/layers/__tests__/tool_slot_layer_test.tsx index b7839bb6a..2eb6199a8 100644 --- a/webpack/farm_designer/map/layers/__tests__/tool_slot_layer_test.tsx +++ b/webpack/farm_designer/map/layers/__tests__/tool_slot_layer_test.tsx @@ -1,11 +1,10 @@ const mockHistory = jest.fn(); +let mockPath = "/app/designer/plants"; jest.mock("../../../../history", () => ({ history: { push: mockHistory }, - getPathArray: jest - .fn(() => { return "/app/designer/plants/select".split("/"); }) - .mockImplementationOnce(() => { return "/app/designer/plants".split("/"); }) + getPathArray: jest.fn(() => { return mockPath.split("/"); }) })); import * as React from "react"; @@ -53,9 +52,7 @@ describe("", () => { }); it("navigates to tools page", async () => { - Object.defineProperty(location, "pathname", { - value: "/app/designer/plants", configurable: true - }); + mockPath = "/app/designer/plants"; const p = fakeProps(); const wrapper = shallow(); const tools = wrapper.find("g").first(); @@ -64,9 +61,7 @@ describe("", () => { }); it("doesn't navigate to tools page", async () => { - Object.defineProperty(location, "pathname", { - value: "/app/designer/plants/1", configurable: true - }); + mockPath = "/app/designer/plants/1"; const p = fakeProps(); const wrapper = shallow(); const tools = wrapper.find("g").first(); @@ -76,6 +71,7 @@ describe("", () => { }); it("is in non-clickable mode", () => { + mockPath = "/app/designer/plants/select"; const p = fakeProps(); const wrapper = shallow(); expect(wrapper.find("g").props().style) diff --git a/webpack/farm_designer/map/layers/index.ts b/webpack/farm_designer/map/layers/index.ts new file mode 100644 index 000000000..cb12b962e --- /dev/null +++ b/webpack/farm_designer/map/layers/index.ts @@ -0,0 +1,7 @@ +export * from "./drag_helper_layer"; +export * from "./farmbot_layer"; +export * from "./hovered_plant_layer"; +export * from "./plant_layer"; +export * from "./point_layer"; +export * from "./spread_layer"; +export * from "./tool_slot_layer"; diff --git a/webpack/farm_designer/map/layers/tool_slot_layer.tsx b/webpack/farm_designer/map/layers/tool_slot_layer.tsx index 6b2f7130f..414ea0898 100644 --- a/webpack/farm_designer/map/layers/tool_slot_layer.tsx +++ b/webpack/farm_designer/map/layers/tool_slot_layer.tsx @@ -2,7 +2,7 @@ import * as React from "react"; import { SlotWithTool } from "../../../resources/interfaces"; import { ToolSlotPoint } from "../tool_slot_point"; import { MapTransformProps } from "../interfaces"; -import { history } from "../../../history"; +import { history, getPathArray } from "../../../history"; import { getMode, Mode } from "../garden_map"; export interface ToolSlotLayerProps { @@ -13,7 +13,7 @@ export interface ToolSlotLayerProps { } export function ToolSlotLayer(props: ToolSlotLayerProps) { - const pathArray = location.pathname.split("/"); + const pathArray = getPathArray(); const canClickTool = !(pathArray[3] === "plants" && pathArray.length > 4); function goToToolsPage() { if (canClickTool) { diff --git a/webpack/farm_designer/map/map_background.tsx b/webpack/farm_designer/map/map_background.tsx index 20fea0c25..49da4e5cf 100644 --- a/webpack/farm_designer/map/map_background.tsx +++ b/webpack/farm_designer/map/map_background.tsx @@ -1,6 +1,6 @@ import * as React from "react"; import { MapBackgroundProps } from "./interfaces"; -import { Color } from "../../ui/colors"; +import { Color } from "../../ui/index"; export function MapBackground(props: MapBackgroundProps) { const { mapTransformProps, plantAreaOffset } = props; diff --git a/webpack/farm_designer/map/target_coordinate.tsx b/webpack/farm_designer/map/target_coordinate.tsx index d5f0165b9..04b7960f6 100644 --- a/webpack/farm_designer/map/target_coordinate.tsx +++ b/webpack/farm_designer/map/target_coordinate.tsx @@ -3,7 +3,7 @@ import { MapTransformProps } from "./interfaces"; import { getXYFromQuadrant, round } from "./util"; import { BotPosition } from "../../devices/interfaces"; import { isNumber } from "lodash"; -import { Color } from "../../ui/colors"; +import { Color } from "../../ui/index"; export interface TargetCoordinateProps { chosenLocation: BotPosition; @@ -27,10 +27,9 @@ export function TargetCoordinate(props: TargetCoordinateProps) { {[45, 135, 225, 315].map(rotation => { - return ( - ); + return ; })} ; } else { diff --git a/webpack/farm_designer/map/tool_slot_point.tsx b/webpack/farm_designer/map/tool_slot_point.tsx index eab237b35..6c3e21cf9 100644 --- a/webpack/farm_designer/map/tool_slot_point.tsx +++ b/webpack/farm_designer/map/tool_slot_point.tsx @@ -3,7 +3,7 @@ import { SlotWithTool } from "../../resources/interfaces"; import { getXYFromQuadrant } from "./util"; import { MapTransformProps } from "./interfaces"; import * as _ from "lodash"; -import { Color } from "../../ui/colors"; +import { Color } from "../../ui/index"; export interface TSPProps { slot: SlotWithTool; diff --git a/webpack/farm_designer/map/util.ts b/webpack/farm_designer/map/util.ts index 889cc4dbe..dcd06597f 100644 --- a/webpack/farm_designer/map/util.ts +++ b/webpack/farm_designer/map/util.ts @@ -1,7 +1,4 @@ -import { - BotOriginQuadrant, - isBotOriginQuadrant -} from "../interfaces"; +import { BotOriginQuadrant, isBotOriginQuadrant } from "../interfaces"; import { McuParams } from "farmbot"; import { StepsPerMmXY } from "../../devices/interfaces"; import { CheckedAxisLength, AxisNumberProperty, BotSize } from "./interfaces"; diff --git a/webpack/farm_designer/map/virtual_farmbot/__tests__/bot_figure_test.tsx b/webpack/farm_designer/map/virtual_farmbot/__tests__/bot_figure_test.tsx index 2c585480b..1272b79ae 100644 --- a/webpack/farm_designer/map/virtual_farmbot/__tests__/bot_figure_test.tsx +++ b/webpack/farm_designer/map/virtual_farmbot/__tests__/bot_figure_test.tsx @@ -2,7 +2,7 @@ import * as React from "react"; import { shallow } from "enzyme"; import { BotOriginQuadrant } from "../../../interfaces"; import { BotFigure, BotFigureProps } from "../bot_figure"; -import { Color } from "../../../../ui/colors"; +import { Color } from "../../../../ui/index"; describe("", () => { function fakeProps(): BotFigureProps { diff --git a/webpack/farm_designer/map/virtual_farmbot/bot_figure.tsx b/webpack/farm_designer/map/virtual_farmbot/bot_figure.tsx index c98b8e335..62d49ef5e 100644 --- a/webpack/farm_designer/map/virtual_farmbot/bot_figure.tsx +++ b/webpack/farm_designer/map/virtual_farmbot/bot_figure.tsx @@ -2,7 +2,7 @@ import * as React from "react"; import { AxisNumberProperty, MapTransformProps } from "../interfaces"; import { getMapSize, getXYFromQuadrant } from "../util"; import { BotPosition } from "../../../devices/interfaces"; -import { Color } from "../../../ui/colors"; +import { Color } from "../../../ui/index"; export interface BotFigureProps { name: string; diff --git a/webpack/farm_designer/map/zoom.ts b/webpack/farm_designer/map/zoom.ts index ed11653e1..ace6c10e6 100644 --- a/webpack/farm_designer/map/zoom.ts +++ b/webpack/farm_designer/map/zoom.ts @@ -1,6 +1,6 @@ import { Session } from "../../session"; import { NumericSetting } from "../../session_keys"; -import { findIndex, isNumber } from "lodash"; +import { findIndex, isNumber, clamp } from "lodash"; /** * Map Zoom Level utilities @@ -16,11 +16,13 @@ const zoomLevels = const foundIndex = findIndex(zoomLevels, (x) => x === 1); const zoomLevel1Index = foundIndex === -1 ? 9 : foundIndex; const zoomLevelsCount = zoomLevels.length; +export const maxZoomIndex = zoomLevelsCount - 1; +const clampZoom = (index: number): number => clamp(index, 0, maxZoomIndex); export const maxZoomLevel = zoomLevelsCount - zoomLevel1Index; export const minZoomLevel = 1 - zoomLevel1Index; export function atMaxZoom(): boolean { - return getZoomLevelIndex() >= (zoomLevelsCount - 1); + return getZoomLevelIndex() >= maxZoomIndex; } export function atMinZoom(): boolean { @@ -30,9 +32,9 @@ export function atMinZoom(): boolean { /* Load the index of a saved zoom level. */ export function getZoomLevelIndex(): number { const savedValue = Session.deprecatedGetNum(NumericSetting.zoom_level); - return isNumber(savedValue) - ? savedValue + zoomLevel1Index - 1 - : zoomLevel1Index; + if (!isNumber(savedValue)) { return zoomLevel1Index; } + const zoomLevelIndex = savedValue + zoomLevel1Index - 1; + return clampZoom(zoomLevelIndex); } /* Save a zoom level index. */ @@ -43,5 +45,5 @@ export function saveZoomLevelIndex(index: number) { /* Calculate map zoom level from a zoom level index. */ export function calcZoomLevel(index: number): number { - return zoomLevels[index]; + return zoomLevels[clampZoom(index)]; } diff --git a/webpack/farm_designer/plants/__tests__/add_plant_test.tsx b/webpack/farm_designer/plants/__tests__/add_plant_test.tsx index 458863229..425553260 100644 --- a/webpack/farm_designer/plants/__tests__/add_plant_test.tsx +++ b/webpack/farm_designer/plants/__tests__/add_plant_test.tsx @@ -2,6 +2,11 @@ jest.mock("react-redux", () => ({ connect: jest.fn() })); +let mockPath = ""; +jest.mock("../../../history", () => ({ + getPathArray: jest.fn(() => { return mockPath.split("/"); }) +})); + import * as React from "react"; import { mount } from "enzyme"; import { AddPlant, AddPlantProps } from "../add_plant"; @@ -24,9 +29,7 @@ describe("", () => { } }] }; - Object.defineProperty(location, "pathname", { - value: "/app/designer/plants/crop_search/mint/add" - }); + mockPath = "/app/designer/plants/crop_search/mint/add"; const wrapper = mount(); expect(wrapper.text()).toContain("Mint"); expect(wrapper.text()).toContain("Done"); diff --git a/webpack/farm_designer/plants/__tests__/crop_info_test.tsx b/webpack/farm_designer/plants/__tests__/crop_info_test.tsx index 6c8cc9935..f060a3bad 100644 --- a/webpack/farm_designer/plants/__tests__/crop_info_test.tsx +++ b/webpack/farm_designer/plants/__tests__/crop_info_test.tsx @@ -2,6 +2,11 @@ jest.mock("react-redux", () => ({ connect: jest.fn() })); +let mockPath = ""; +jest.mock("../../../history", () => ({ + getPathArray: jest.fn(() => { return mockPath.split("/"); }) +})); + jest.mock("../../search_selectors", () => ({ findBySlug: () => { return { @@ -26,9 +31,7 @@ import { shallow } from "enzyme"; describe("", () => { it("renders", () => { - Object.defineProperty(location, "pathname", { - value: "/app/designer/plants/crop_search/mint" - }); + mockPath = "/app/designer/plants/crop_search/mint"; const wrapper = shallow( ({ getDevice: () => (mockDevice) })); +let mockPath = ""; +jest.mock("../../../history", () => ({ + getPathArray: jest.fn(() => { return mockPath.split("/"); }) +})); + import * as React from "react"; import { mount } from "enzyme"; import { MoveTo, MoveToProps } from "../move_to"; @@ -17,9 +22,7 @@ import { MoveTo, MoveToProps } from "../move_to"; describe("", () => { beforeEach(function () { jest.clearAllMocks(); - Object.defineProperty(location, "pathname", { - value: "/app/designer/plants/move_to" - }); + mockPath = "/app/designer/plants/move_to"; }); function fakeProps(): MoveToProps { diff --git a/webpack/farm_designer/plants/__tests__/select_plants_test.tsx b/webpack/farm_designer/plants/__tests__/select_plants_test.tsx index 5d462b53f..357536101 100644 --- a/webpack/farm_designer/plants/__tests__/select_plants_test.tsx +++ b/webpack/farm_designer/plants/__tests__/select_plants_test.tsx @@ -2,6 +2,11 @@ jest.mock("react-redux", () => ({ connect: jest.fn() })); +let mockPath = ""; +jest.mock("../../../history", () => ({ + getPathArray: jest.fn(() => { return mockPath.split("/"); }) +})); + import * as React from "react"; import { mount, shallow } from "enzyme"; import { SelectPlants, SelectPlantsProps } from "../select_plants"; @@ -11,9 +16,7 @@ import { Actions } from "../../../constants"; describe("", () => { beforeEach(function () { jest.clearAllMocks(); - Object.defineProperty(location, "pathname", { - value: "/app/designer/plants/select" - }); + mockPath = "/app/designer/plants/select"; }); function fakeProps(): SelectPlantsProps { diff --git a/webpack/farm_designer/plants/add_plant.tsx b/webpack/farm_designer/plants/add_plant.tsx index 9289b14ed..8d83d308a 100644 --- a/webpack/farm_designer/plants/add_plant.tsx +++ b/webpack/farm_designer/plants/add_plant.tsx @@ -1,5 +1,5 @@ import * as React from "react"; -import { BackArrow } from "../../ui"; +import { BackArrow } from "../../ui/index"; import { Everything } from "../../interfaces"; import { connect } from "react-redux"; import { t } from "i18next"; diff --git a/webpack/farm_designer/plants/edit_plant_info.tsx b/webpack/farm_designer/plants/edit_plant_info.tsx index f3509e61f..fd9eab5f8 100644 --- a/webpack/farm_designer/plants/edit_plant_info.tsx +++ b/webpack/farm_designer/plants/edit_plant_info.tsx @@ -1,7 +1,7 @@ import * as React from "react"; import { connect } from "react-redux"; import { t } from "i18next"; -import { BackArrow } from "../../ui"; +import { BackArrow } from "../../ui/index"; import { TaggedPlantPointer } from "../../resources/tagged_resources"; import { mapStateToProps, formatPlantInfo } from "./map_state_to_props"; import { PlantInfoBase } from "./plant_info_base"; diff --git a/webpack/farm_designer/reducer.ts b/webpack/farm_designer/reducer.ts index 96532c4ac..00440efa4 100644 --- a/webpack/farm_designer/reducer.ts +++ b/webpack/farm_designer/reducer.ts @@ -1,9 +1,6 @@ import { CropLiveSearchResult } from "./interfaces"; import { generateReducer } from "../redux/generate_reducer"; -import { - DesignerState, - HoveredPlantPayl -} from "./interfaces"; +import { DesignerState, HoveredPlantPayl } from "./interfaces"; import { cloneDeep } from "lodash"; import { TaggedResource } from "../resources/tagged_resources"; import { Actions } from "../constants"; diff --git a/webpack/farmware/camera_calibration/camera_calibration.tsx b/webpack/farmware/camera_calibration/camera_calibration.tsx index 016b53171..f0c923ed3 100644 --- a/webpack/farmware/camera_calibration/camera_calibration.tsx +++ b/webpack/farmware/camera_calibration/camera_calibration.tsx @@ -16,57 +16,55 @@ export class CameraCalibration extends React.Component { render() { const classname = "weed-detector-widget"; - return ( - - - - - - - { this.props.dispatch(scanImage(id)); }} - onFlip={(uuid) => this.props.dispatch(selectImage(uuid))} - images={this.props.images} - currentImage={this.props.currentImage} - onChange={(key, value) => { - const MAPPING: Record = { - "iteration": "CAMERA_CALIBRATION_iteration", - "morph": "CAMERA_CALIBRATION_morph", - "blur": "CAMERA_CALIBRATION_blur", - "H_HI": "CAMERA_CALIBRATION_H_HI", - "H_LO": "CAMERA_CALIBRATION_H_LO", - "S_HI": "CAMERA_CALIBRATION_S_HI", - "S_LO": "CAMERA_CALIBRATION_S_LO", - "V_HI": "CAMERA_CALIBRATION_V_HI", - "V_LO": "CAMERA_CALIBRATION_V_LO" - }; - envSave(MAPPING[key], value); - }} - iteration={this.props.iteration} - morph={this.props.morph} - blur={this.props.blur} - H_LO={this.props.H_LO} - S_LO={this.props.S_LO} - V_LO={this.props.V_LO} - H_HI={this.props.H_HI} - S_HI={this.props.S_HI} - V_HI={this.props.V_HI} - invertHue={!!envGet( - "CAMERA_CALIBRATION_invert_hue_selection", - this.props.env)} /> - - - - - - ); + return + + + + + + { this.props.dispatch(scanImage(id)); }} + onFlip={(uuid) => this.props.dispatch(selectImage(uuid))} + images={this.props.images} + currentImage={this.props.currentImage} + onChange={(key, value) => { + const MAPPING: Record = { + "iteration": "CAMERA_CALIBRATION_iteration", + "morph": "CAMERA_CALIBRATION_morph", + "blur": "CAMERA_CALIBRATION_blur", + "H_HI": "CAMERA_CALIBRATION_H_HI", + "H_LO": "CAMERA_CALIBRATION_H_LO", + "S_HI": "CAMERA_CALIBRATION_S_HI", + "S_LO": "CAMERA_CALIBRATION_S_LO", + "V_HI": "CAMERA_CALIBRATION_V_HI", + "V_LO": "CAMERA_CALIBRATION_V_LO" + }; + envSave(MAPPING[key], value); + }} + iteration={this.props.iteration} + morph={this.props.morph} + blur={this.props.blur} + H_LO={this.props.H_LO} + S_LO={this.props.S_LO} + V_LO={this.props.V_LO} + H_HI={this.props.H_HI} + S_HI={this.props.S_HI} + V_HI={this.props.V_HI} + invertHue={!!envGet( + "CAMERA_CALIBRATION_invert_hue_selection", + this.props.env)} /> + + + + + ; } } diff --git a/webpack/farmware/farmware_panel.tsx b/webpack/farmware/farmware_panel.tsx index 51d2ffd40..df9417784 100644 --- a/webpack/farmware/farmware_panel.tsx +++ b/webpack/farmware/farmware_panel.tsx @@ -8,15 +8,11 @@ import { import { MustBeOnline } from "../devices/must_be_online"; import { ToolTips, Content } from "../constants"; import { - Widget, - WidgetHeader, - WidgetBody, - Row, - Col, - DropDownItem -} from "../ui"; + Widget, WidgetHeader, WidgetBody, + Row, Col, + FBSelect, DropDownItem +} from "../ui/index"; import { betterCompact } from "../util"; -import { FBSelect } from "../ui/new_fb_select"; import { Popover, Position } from "@blueprintjs/core"; import { getFirstPartyFarmwareList } from "./actions"; @@ -155,88 +151,86 @@ export class FarmwarePanel extends React.Component> { } render() { - return ( - - - - - - - - - - -
- - { - this.setState({ packageUrl: e.currentTarget.value }); - }} /> - - - - -
-
- -
- - { - const selectedFarmware = x.value; - if (_.isString(selectedFarmware)) { - this.setState({ selectedFarmware }); - } else { - throw new Error(`Bad farmware name: ${x.value}`); - } - }} - placeholder="Installed Farmware Packages" /> - - - - - - -
-
- + return + + + + + + + + + +
- {this.fwDescription(this.state.selectedFarmware)} + { + this.setState({ packageUrl: e.currentTarget.value }); + }} /> - - - - - ); + + + +
+
+ +
+ + { + const selectedFarmware = x.value; + if (_.isString(selectedFarmware)) { + this.setState({ selectedFarmware }); + } else { + throw new Error(`Bad farmware name: ${x.value}`); + } + }} + placeholder="Installed Farmware Packages" /> + + + + + + +
+
+ + + {this.fwDescription(this.state.selectedFarmware)} + + +
+
+
; } } diff --git a/webpack/farmware/images/image_flipper.tsx b/webpack/farmware/images/image_flipper.tsx index 68d4618f7..f390fac6e 100644 --- a/webpack/farmware/images/image_flipper.tsx +++ b/webpack/farmware/images/image_flipper.tsx @@ -63,22 +63,20 @@ export class ImageFlipper extends render() { const image = this.imageJSX(); const multipleImages = this.props.images.length > 1; - return ( -
- {image} - - -
- ); + return
+ {image} + + +
; } } diff --git a/webpack/farmware/images/photos.tsx b/webpack/farmware/images/photos.tsx index c47f23bf7..b8ac546dc 100644 --- a/webpack/farmware/images/photos.tsx +++ b/webpack/farmware/images/photos.tsx @@ -3,13 +3,12 @@ import * as _ from "lodash"; import * as moment from "moment"; import { t } from "i18next"; import { success, error } from "farmbot-toastr"; -import { Widget, WidgetHeader, WidgetBody } from "../../ui/index"; +import { Widget, WidgetHeader, WidgetBody, WidgetFooter } from "../../ui/index"; import { ImageFlipper } from "./image_flipper"; import { PhotosProps } from "./interfaces"; import { getDevice } from "../../device"; import { ToolTips } from "../../constants"; import { selectImage } from "./actions"; -import { WidgetFooter } from "../../ui/widget_footer"; import { safeStringFetch } from "../../util"; import { destroy } from "../../api/crud"; @@ -26,12 +25,10 @@ interface MetaInfoProps { function MetaInfo({ obj, attr, label }: MetaInfoProps) { const top = label || _.startCase(attr.split("_").join()); const bottom = safeStringFetch(obj, attr); - return ( -
- - {bottom || "unknown"} -
- ); + return
+ + {bottom || "unknown"} +
; } export class Photos extends React.Component { @@ -66,43 +63,43 @@ export class Photos extends React.Component { render() { const image = this.props.currentImage; const created_at = image - ? moment(image.body.created_at).utcOffset(this.props.timeOffset).format("MMMM Do, YYYY h:mma") + ? moment(image.body.created_at) + .utcOffset(this.props.timeOffset) + .format("MMMM Do, YYYY h:mma") : ""; - return ( - - - - - - - { this.props.dispatch(selectImage(id)); }} - currentImage={this.props.currentImage} - images={this.props.images} /> - - - {/** Separated from for stylistic purposes. */} - {image ? -
- - - {created_at} - -
- : ""} -
- {this.metaDatas()} + return + + + + + + { this.props.dispatch(selectImage(id)); }} + currentImage={this.props.currentImage} + images={this.props.images} /> + + + {/** Separated from for stylistic purposes. */} + {image ? +
+ + + {created_at} +
-
-
- ); + : ""} +
+ {this.metaDatas()} +
+ + ; } } diff --git a/webpack/farmware/weed_detector/config.tsx b/webpack/farmware/weed_detector/config.tsx index 5fa954f39..3ce7287bd 100644 --- a/webpack/farmware/weed_detector/config.tsx +++ b/webpack/farmware/weed_detector/config.tsx @@ -1,12 +1,15 @@ import * as React from "react"; import { t } from "i18next"; -import { DropDownItem } from "../../ui/fb_select"; -import { Row, Col, NULL_CHOICE } from "../../ui/index"; -import { FBSelect } from "../../ui/new_fb_select"; +import { + BlurableInput, + Row, Col, + FBSelect, NULL_CHOICE, DropDownItem +} from "../../ui/index"; import { SettingsMenuProps } from "./interfaces"; import * as _ from "lodash"; -import { BlurableInput } from "../../ui/blurable_input"; -import { SPECIAL_VALUE_DDI, CALIBRATION_DROPDOWNS, ORIGIN_DROPDOWNS } from "./constants"; +import { + SPECIAL_VALUE_DDI, CALIBRATION_DROPDOWNS, ORIGIN_DROPDOWNS +} from "./constants"; import { WD_ENV } from "./remote_env/interfaces"; import { envGet } from "./remote_env/selectors"; import { SPECIAL_VALUES } from "./remote_env/constants"; diff --git a/webpack/farmware/weed_detector/farmbot_picker.tsx b/webpack/farmware/weed_detector/farmbot_picker.tsx index ab42cfcdb..130cd818d 100644 --- a/webpack/farmware/weed_detector/farmbot_picker.tsx +++ b/webpack/farmware/weed_detector/farmbot_picker.tsx @@ -2,7 +2,7 @@ import * as React from "react"; import { Hue, Saturation } from "react-color/lib/components/common"; import { FarmbotPickerProps } from "./interfaces"; import * as _ from "lodash"; -import { Color } from "../../ui/colors"; +import { Color } from "../../ui/index"; /** Wrapper class around `react-color`'s `` and ``. * Add an extra white box feature for showing user weed detection settings. diff --git a/webpack/farmware/weed_detector/image_workspace.tsx b/webpack/farmware/weed_detector/image_workspace.tsx index 0a744c83a..35ff7eb8e 100644 --- a/webpack/farmware/weed_detector/image_workspace.tsx +++ b/webpack/farmware/weed_detector/image_workspace.tsx @@ -76,92 +76,90 @@ export class ImageWorkspace extends React.Component { render() { const { H_LO, H_HI, S_LO, S_HI, V_LO, V_HI } = this.props; - return ( -
- - -

- {t("Color Range")} -

- - - - - - - - - - -
- - -

- {t("Processing Parameters")} -

- + return
+ + +

+ {t("Color Range")} +

+ + + + + + + + + + +
+ + +

+ {t("Processing Parameters")} +

+ - - - - + + + + - - - - - - - - -
- - - - - - -
- ); + + + + + + + + +
+ + + + + + +
; } } diff --git a/webpack/farmware/weed_detector/selectors.ts b/webpack/farmware/weed_detector/selectors.ts index 5b693bd9a..9527d473f 100644 --- a/webpack/farmware/weed_detector/selectors.ts +++ b/webpack/farmware/weed_detector/selectors.ts @@ -1,4 +1,4 @@ -import { DropDownItem, NULL_CHOICE } from "../../ui/fb_select"; +import { DropDownItem, NULL_CHOICE } from "../../ui/index"; import { SPECIAL_VALUE_DDI } from "./constants"; import { WD_ENV } from "./remote_env/interfaces"; import { envGet } from "./remote_env/selectors"; diff --git a/webpack/farmware/weed_detector/title.tsx b/webpack/farmware/weed_detector/title.tsx index 9b6739b43..92e57f408 100644 --- a/webpack/farmware/weed_detector/title.tsx +++ b/webpack/farmware/weed_detector/title.tsx @@ -5,7 +5,7 @@ import { WidgetHeader } from "../../ui/index"; import { WD_ENV } from "./remote_env/interfaces"; import { envSave } from "./remote_env/actions"; import { Popover, PopoverInteractionKind } from "@blueprintjs/core"; -import { DocSlug } from "../../ui/doc_link"; +import { DocSlug } from "../../ui/index"; type ClickHandler = React.EventHandler>; @@ -32,41 +32,39 @@ export function TitleBar({ help, docs }: Props) { - return ( - - - - - - - - ); + return + + + + + + ; } diff --git a/webpack/front_page/__tests__/create_account_test.tsx b/webpack/front_page/__tests__/create_account_test.tsx index 47ff3d335..c7173bb48 100644 --- a/webpack/front_page/__tests__/create_account_test.tsx +++ b/webpack/front_page/__tests__/create_account_test.tsx @@ -17,7 +17,9 @@ jest.mock("../resend_verification", () => { }); import * as React from "react"; -import { FormField, sendEmail, DidRegister, MustRegister, CreateAccount } from "../create_account"; +import { + FormField, sendEmail, DidRegister, MustRegister, CreateAccount +} from "../create_account"; import { shallow } from "enzyme"; import { BlurableInput } from "../../ui/index"; import { success, error } from "farmbot-toastr"; diff --git a/webpack/front_page/front_page.tsx b/webpack/front_page/front_page.tsx index a8a359135..4d59f239f 100644 --- a/webpack/front_page/front_page.tsx +++ b/webpack/front_page/front_page.tsx @@ -144,32 +144,30 @@ export class FrontPage extends React.Component<{}, Partial> { const TOS_URL = globalConfig.TOS_URL; if (TOS_URL) { const PRV_URL = globalConfig.PRIV_URL; - return ( -
-
- - -
- + return
+
+ +
- ); + +
; } } diff --git a/webpack/hotkeys.tsx b/webpack/hotkeys.tsx index 6bfd24f0c..1f917935a 100644 --- a/webpack/hotkeys.tsx +++ b/webpack/hotkeys.tsx @@ -34,35 +34,31 @@ export class HotKeys extends React.Component> { state: State = { guideOpen: false }; render() { - return ( -
- -
-

{t("Hotkeys")}

- - { - this.hotkeys(this.props.dispatch, "") - .map(hotkey => { - return ( - - - - - - {hotkey.combo} - - - ); - }) - } -
-
-
- ); + return
+ +
+

{t("Hotkeys")}

+ + { + this.hotkeys(this.props.dispatch, "") + .map(hotkey => { + return + + + + + {hotkey.combo} + + ; + }) + } +
+
+
; } toggle = (property: keyof State) => () => diff --git a/webpack/logs/components/logs_table.tsx b/webpack/logs/components/logs_table.tsx index 0c173f1e8..83885f791 100644 --- a/webpack/logs/components/logs_table.tsx +++ b/webpack/logs/components/logs_table.tsx @@ -68,7 +68,7 @@ const filterByVerbosity = (state: LogsState, logs: TaggedLog[]) => { }) .filter((log: TaggedLog) => { const type = (log.body.meta || {}).type; - const verbosity = log.body.meta.verbosity; + const { verbosity } = log.body.meta; const filterLevel = state[type as keyof LogsState]; const displayLog = verbosity ? verbosity <= filterLevel diff --git a/webpack/logs/index.tsx b/webpack/logs/index.tsx index 46eb42e1a..e45a1cebf 100644 --- a/webpack/logs/index.tsx +++ b/webpack/logs/index.tsx @@ -1,7 +1,7 @@ import * as React from "react"; import * as moment from "moment"; import { connect } from "react-redux"; -import { Col, Row, Page, ToolTip } from "../ui"; +import { Col, Row, Page, ToolTip } from "../ui/index"; import { mapStateToProps } from "./state_to_props"; import { t } from "i18next"; import { Popover, Position } from "@blueprintjs/core"; diff --git a/webpack/nav/index.tsx b/webpack/nav/index.tsx index 1babdd0c6..a7fb3656f 100644 --- a/webpack/nav/index.tsx +++ b/webpack/nav/index.tsx @@ -3,7 +3,7 @@ import { t } from "i18next"; import { NavBarProps, NavBarState } from "./interfaces"; import { EStopButton } from "../devices/components/e_stop_btn"; import { Session } from "../session"; -import { Row, Col } from "../ui"; +import { Row, Col } from "../ui/index"; import { getPathArray } from "../history"; import { updatePageInfo } from "../util"; import { SyncButton } from "./sync_button"; @@ -61,49 +61,47 @@ export class NavBar extends React.Component> { const { mobileMenuOpen, tickerListOpen, accountMenuOpen } = this.state; const { logs, timeOffset } = this.props; - return ( -
- +
; } } diff --git a/webpack/nav/mobile_menu.tsx b/webpack/nav/mobile_menu.tsx index 7c42fc971..c9e9e2d91 100644 --- a/webpack/nav/mobile_menu.tsx +++ b/webpack/nav/mobile_menu.tsx @@ -8,15 +8,13 @@ const classes = [Classes.CARD, Classes.ELEVATION_4, "mobile-menu"]; export let MobileMenu = (props: MobileMenuProps) => { const isActive = props.mobileMenuOpen ? "active" : "inactive"; - return ( -
- -
- {NavLinks({ close: props.close })} -
-
-
- ); + return
+ +
+ {NavLinks({ close: props.close })} +
+
+
; }; diff --git a/webpack/nav/nav_links.tsx b/webpack/nav/nav_links.tsx index c8a09e186..d1bf98217 100644 --- a/webpack/nav/nav_links.tsx +++ b/webpack/nav/nav_links.tsx @@ -16,23 +16,19 @@ export const links = [ export const NavLinks = (props: NavLinksProps) => { const currPageSlug = getPathArray()[2]; - return ( -
-
- {links.map(link => { - const isActive = (currPageSlug === link.slug) ? "active" : ""; - return ( - - - {link.name} - - ); - })} -
+ return
+
+ {links.map(link => { + const isActive = (currPageSlug === link.slug) ? "active" : ""; + return + + {link.name} + ; + })}
- ); +
; }; diff --git a/webpack/nav/sync_button.tsx b/webpack/nav/sync_button.tsx index a2686ec63..a6a604fd8 100644 --- a/webpack/nav/sync_button.tsx +++ b/webpack/nav/sync_button.tsx @@ -31,11 +31,9 @@ export function SyncButton({ user, bot, dispatch, consistent }: NavButtonProps) sync_status = sync_status || "unknown"; const color = consistent ? (COLOR_MAPPING[sync_status] || "red") : "gray"; const text = TEXT_MAPPING[sync_status] || "DISCONNECTED"; - return ( - - ); + return ; } diff --git a/webpack/nav/ticker_list.tsx b/webpack/nav/ticker_list.tsx index 79adee8f3..2ff39d988 100644 --- a/webpack/nav/ticker_list.tsx +++ b/webpack/nav/ticker_list.tsx @@ -48,46 +48,42 @@ const getfirstTickerLog = (logs: Log[]): Log => { const Ticker = (log: Log, index: number, timeOffset: number) => { const time = formatLogTime(log.created_at, timeOffset); const type = (log.meta || {}).type; - return ( - // TODO: Should utilize log's `uuid` instead of index. -
-
- - -
- ); + // TODO: Should utilize log's `uuid` instead of index. + return
+
+ + +
; }; export let TickerList = (props: TickerListProps) => { - return ( -
-
- {Ticker(getfirstTickerLog(props.logs), -1, props.timeOffset)} -
- - {props - .logs - .filter((log, index) => index !== 0) - .filter((log) => logFilter(log)) - .map((log: Log, index: number) => Ticker(log, index, props.timeOffset))} - - - -
- -
- -
+ return
+
+ {Ticker(getfirstTickerLog(props.logs), -1, props.timeOffset)}
- ); + + {props + .logs + .filter((log, index) => index !== 0) + .filter((log) => logFilter(log)) + .map((log: Log, index: number) => Ticker(log, index, props.timeOffset))} + + + +
+ +
+ +
+
; }; diff --git a/webpack/password_reset/password_reset.tsx b/webpack/password_reset/password_reset.tsx index 1e4767096..ff0261cb1 100644 --- a/webpack/password_reset/password_reset.tsx +++ b/webpack/password_reset/password_reset.tsx @@ -66,47 +66,45 @@ export class PasswordReset extends React.Component { borderBottom: "none" }; - return ( -
-
-

- {t("Reset your password")} -

-
- - - - - -
- - - - - - - - - -
-
-
- -
-
+ return
+
+

+ {t("Reset your password")} +

+
+ + + + + +
+ + + + + + + + + +
+
+
+ +
- ); +
; } } diff --git a/webpack/regimens/bulk_scheduler/index.tsx b/webpack/regimens/bulk_scheduler/index.tsx index 69a4553d3..c4cb0fade 100644 --- a/webpack/regimens/bulk_scheduler/index.tsx +++ b/webpack/regimens/bulk_scheduler/index.tsx @@ -3,14 +3,14 @@ import { BulkEditorProps } from "./interfaces"; import { AddButton } from "./add_button"; import { WeekGrid } from "./week_grid"; import { commitBulkEditor, setTimeOffset, setSequence } from "./actions"; -import { ToolTip, Row, Col, DropDownItem } from "../../ui/index"; -import { BlurableInput } from "../../ui/blurable_input"; +import { + BlurableInput, ToolTip, Row, Col, FBSelect, DropDownItem, NULL_CHOICE +} from "../../ui/index"; import { duration } from "moment"; import { t } from "i18next"; import { ToolTips } from "../../constants"; import * as _ from "lodash"; import { betterCompact } from "../../util"; -import { NULL_CHOICE, FBSelect } from "../../ui/new_fb_select"; export class BulkSchedulerWidget extends React.Component { selected = (): DropDownItem => { diff --git a/webpack/regimens/editor/active_editor.tsx b/webpack/regimens/editor/active_editor.tsx index 544768760..65cea4a91 100644 --- a/webpack/regimens/editor/active_editor.tsx +++ b/webpack/regimens/editor/active_editor.tsx @@ -25,13 +25,11 @@ export function ActiveEditor(props: ActiveEditorProps) { const { item, regimen } = row; const click = () => props.dispatch(removeRegimenItem(item, regimen)); const klass = `${row.color} regimen-event`; - return ( -
- {row.name} - {row.hhmm} - -
- ); + return
+ {row.name} + {row.hhmm} + +
; })}
; })} diff --git a/webpack/regimens/editor/index.tsx b/webpack/regimens/editor/index.tsx index ab8496983..6548c7cef 100644 --- a/webpack/regimens/editor/index.tsx +++ b/webpack/regimens/editor/index.tsx @@ -12,12 +12,10 @@ import { ToolTips } from "../../constants"; function MiddleSection({ regimen, dispatch, calendar }: MiddleSectionProps) { if (regimen && isTaggedRegimen(regimen) && calendar) { - return ( - - ); + return ; } else { return ; } diff --git a/webpack/regimens/editor/regimen_name_input.tsx b/webpack/regimens/editor/regimen_name_input.tsx index 144ef3e2f..b2c0a2c60 100644 --- a/webpack/regimens/editor/regimen_name_input.tsx +++ b/webpack/regimens/editor/regimen_name_input.tsx @@ -1,8 +1,7 @@ import * as React from "react"; import { RegimenProps } from "../interfaces"; import { t } from "i18next"; -import { ColorPicker } from "../../ui"; -import { Row, Col } from "../../ui/index"; +import { Row, Col, ColorPicker } from "../../ui/index"; import { editRegimen } from "../actions"; export function write({ dispatch, regimen }: RegimenProps): @@ -18,18 +17,16 @@ export function write({ dispatch, regimen }: RegimenProps): export function RegimenNameInput({ regimen, dispatch }: RegimenProps) { const value = (regimen && regimen.body.name) || ""; - return ( - - - - - dispatch(editRegimen(regimen, { color }))} /> - - ); + return + + + + dispatch(editRegimen(regimen, { color }))} /> + ; } diff --git a/webpack/regimens/list/add_button.tsx b/webpack/regimens/list/add_button.tsx index cb17db647..d4c95760a 100644 --- a/webpack/regimens/list/add_button.tsx +++ b/webpack/regimens/list/add_button.tsx @@ -22,14 +22,12 @@ export function AddRegimen(props: AddRegimenProps) { const classes = "fb-button green add " + props.className; let { length } = props; const { dispatch } = props; - return ( - - ); + return ; } diff --git a/webpack/regimens/list/index.tsx b/webpack/regimens/list/index.tsx index 28ec5d903..a1f3757fa 100644 --- a/webpack/regimens/list/index.tsx +++ b/webpack/regimens/list/index.tsx @@ -32,26 +32,22 @@ export class RegimensList extends rows = () => { const searchTerm = this.state.searchTerm.toLowerCase(); - return ( - - {sortResourcesById(this.props.regimens) - .filter(regimen => regimen - .body - .name - .toLowerCase() - .includes(searchTerm)) - .map((regimen, index) => { - return ( - - ); - })} - - ); + return + {sortResourcesById(this.props.regimens) + .filter(regimen => regimen + .body + .name + .toLowerCase() + .includes(searchTerm)) + .map((regimen, index) => { + return ; + })} + ; } onChange = (e: React.SyntheticEvent) => { @@ -61,22 +57,20 @@ export class RegimensList extends render() { const { dispatch, regimens } = this.props; - return ( -
-

- {t("Regimens")} -

- - - - -
- {this.rows()} -
-
-
- ); + return
+

+ {t("Regimens")} +

+ + + + +
+ {this.rows()} +
+
+
; } } diff --git a/webpack/resources/__tests__/selectors_test.ts b/webpack/resources/__tests__/selectors_test.ts index 60f911f02..640e69a7f 100644 --- a/webpack/resources/__tests__/selectors_test.ts +++ b/webpack/resources/__tests__/selectors_test.ts @@ -1,27 +1,5 @@ import { buildResourceIndex } from "../../__test_support__/resource_index_builder"; -import { - findSlotByToolId, - getFeeds, - selectAllLogs, - findResourceById, - isKind, - groupPointsByType, - findPointerByTypeAndId, - findToolSlot, - findPlant, - selectCurrentToolSlot, - getSequenceByUUID, - toArray, - findAllById, - toolsInUse, - hasId, - findFarmEventById, - maybeFindToolById, - findToolById, - findSequenceById, - findRegimenById, - maybeFindPlantById -} from "../selectors"; +import * as Selector from "../selectors"; import { resourceReducer, emptyState } from "../reducer"; import { TaggedTool, TaggedToolSlotPointer, SpecialStatus } from "../tagged_resources"; import { createOK } from "../actions"; @@ -65,7 +43,7 @@ describe("findSlotByToolId", () => { it("returns undefined when not found", () => { const state = resourceReducer(buildResourceIndex(), createOK(fakeTool)); expect(state.index.byKindAndId["Tool." + fakeTool.body.id]); - const result = findSlotByToolId(state.index, TOOL_ID); + const result = Selector.findSlotByToolId(state.index, TOOL_ID); expect(result).toBeFalsy(); }); @@ -73,7 +51,7 @@ describe("findSlotByToolId", () => { const initialState = buildResourceIndex(); const state = [createOK(fakeTool), createOK(fakeSlot)] .reduce(resourceReducer, initialState); - const result = findSlotByToolId(state.index, TOOL_ID); + const result = Selector.findSlotByToolId(state.index, TOOL_ID); expect(result).toBeTruthy(); if (result) { expect(result.kind).toBe("Point"); } }); @@ -81,7 +59,7 @@ describe("findSlotByToolId", () => { describe("getFeeds", () => { it("returns empty array", () => { - expect(getFeeds(emptyState().index).length).toBe(0); + expect(Selector.getFeeds(emptyState().index).length).toBe(0); }); it("finds the only WebcamFeed", () => { @@ -93,13 +71,13 @@ describe("getFeeds", () => { data: feed } }].reduce(resourceReducer, emptyState()); - expect(getFeeds(state.index)[0].body).toEqual(feed); + expect(Selector.getFeeds(state.index)[0].body).toEqual(feed); }); }); describe("selectAllLogs", () => { it("stays truthful to its name by finding all logs", () => { - const results = selectAllLogs(fakeIndex); + const results = Selector.selectAllLogs(fakeIndex); expect(results.length).toBeGreaterThan(0); const kinds = _(results).map("kind").uniq().value(); expect(kinds.length).toEqual(1); @@ -109,32 +87,32 @@ describe("selectAllLogs", () => { describe("findResourceById()", () => { it("returns UUID", () => { - const uuid = findResourceById(fakeIndex, "Sequence", 23); + const uuid = Selector.findResourceById(fakeIndex, "Sequence", 23); expect(uuid).toContain("Sequence.23"); }); it("throws error", () => { const findUuid = () => - findResourceById(fakeIndex, "Sequence", NaN); + Selector.findResourceById(fakeIndex, "Sequence", NaN); expect(findUuid).toThrow("UUID not found for id NaN"); }); }); describe("isKind()", () => { it("is", () => { - const ret = isKind("Sequence")(fakeSequence()); + const ret = Selector.isKind("Sequence")(fakeSequence()); expect(ret).toBeTruthy(); }); it("isn't", () => { - const ret = isKind("Tool")(fakeSequence()); + const ret = Selector.isKind("Tool")(fakeSequence()); expect(ret).toBeFalsy(); }); }); describe("groupPointsByType()", () => { it("returns points", () => { - const points = groupPointsByType(fakeIndex); + const points = Selector.groupPointsByType(fakeIndex); const expectedKeys = ["Plant", "GenericPointer", "ToolSlot"]; expect(expectedKeys.every(key => key in points)).toBeTruthy(); }); @@ -142,14 +120,14 @@ describe("groupPointsByType()", () => { describe("findPointerByTypeAndId()", () => { it("throws error", () => { - const find = () => findPointerByTypeAndId(fakeIndex, "Other", 0); + const find = () => Selector.findPointerByTypeAndId(fakeIndex, "Other", 0); expect(find).toThrow("Tried to fetch bad point Other 0"); }); }); describe("findToolSlot()", () => { it("throws error", () => { - const find = () => findToolSlot(fakeIndex, "bad"); + const find = () => Selector.findToolSlot(fakeIndex, "bad"); expect(find).toThrow("ToolSlotPointer not found: bad"); }); }); @@ -157,7 +135,7 @@ describe("findToolSlot()", () => { describe("findPlant()", () => { it("throws error", () => { console.warn = jest.fn(); - const find = () => findPlant(fakeIndex, "bad"); + const find = () => Selector.findPlant(fakeIndex, "bad"); expect(find).toThrowError(); expect(console.warn).toBeCalled(); }); @@ -165,7 +143,7 @@ describe("findPlant()", () => { describe("selectCurrentToolSlot()", () => { it("throws error", () => { - const find = () => selectCurrentToolSlot(fakeIndex, "bad"); + const find = () => Selector.selectCurrentToolSlot(fakeIndex, "bad"); expect(find).toThrowError(); }); }); @@ -173,7 +151,7 @@ describe("selectCurrentToolSlot()", () => { describe("getSequenceByUUID()", () => { it("throws error", () => { console.warn = jest.fn(); - const find = () => getSequenceByUUID(fakeIndex, "bad"); + const find = () => Selector.getSequenceByUUID(fakeIndex, "bad"); expect(find).toThrow("BAD Sequence UUID"); expect(console.warn).toBeCalled(); }); @@ -181,70 +159,70 @@ describe("getSequenceByUUID()", () => { describe("toArray()", () => { it("returns array", () => { - const array = toArray(fakeIndex); + const array = Selector.toArray(fakeIndex); expect(array.length).toEqual(fakeIndex.all.length); }); }); describe("findAllById()", () => { it("returns", () => { - const result = findAllById(fakeIndex, [23], "Sequence"); + const result = Selector.findAllById(fakeIndex, [23], "Sequence"); expect(result.length).toEqual(1); }); }); describe("toolsInUse()", () => { it("returns tools", () => { - const activeTools = toolsInUse(fakeIndex); + const activeTools = Selector.toolsInUse(fakeIndex); expect(activeTools.length).toBeGreaterThan(0); }); }); describe("hasId()", () => { it("has", () => { - const result = hasId(fakeIndex, "Sequence", 23); + const result = Selector.hasId(fakeIndex, "Sequence", 23); expect(result).toBeTruthy(); }); }); describe("findFarmEventById()", () => { it("throws error", () => { - const find = () => findFarmEventById(fakeIndex, 0); + const find = () => Selector.findFarmEventById(fakeIndex, 0); expect(find).toThrow("Bad farm_event id: 0"); }); }); describe("maybeFindToolById()", () => { it("not found", () => { - const result = maybeFindToolById(fakeIndex, 0); + const result = Selector.maybeFindToolById(fakeIndex, 0); expect(result).toBeUndefined(); }); }); describe("findToolById()", () => { it("throws error", () => { - const find = () => findToolById(fakeIndex, 0); + const find = () => Selector.findToolById(fakeIndex, 0); expect(find).toThrow("Bad tool id: 0"); }); }); describe("findSequenceById()", () => { it("throws error", () => { - const find = () => findSequenceById(fakeIndex, 0); + const find = () => Selector.findSequenceById(fakeIndex, 0); expect(find).toThrow("Bad sequence id: 0"); }); }); describe("findRegimenById()", () => { it("throws error", () => { - const find = () => findRegimenById(fakeIndex, 0); + const find = () => Selector.findRegimenById(fakeIndex, 0); expect(find).toThrow("Bad regimen id: 0"); }); }); describe("maybeFindPlantById()", () => { it("not found", () => { - const result = maybeFindPlantById(fakeIndex, 0); + const result = Selector.maybeFindPlantById(fakeIndex, 0); expect(result).toBeUndefined(); }); }); diff --git a/webpack/sequences/__tests__/locals_list_test.tsx b/webpack/sequences/__tests__/locals_list_test.tsx index a9d6ca58c..395f1e2f4 100644 --- a/webpack/sequences/__tests__/locals_list_test.tsx +++ b/webpack/sequences/__tests__/locals_list_test.tsx @@ -24,10 +24,10 @@ import { overwrite } from "../../api/crud"; import { defensiveClone } from "../../util"; import { shallow } from "enzyme"; import { buildResourceIndex } from "../../__test_support__/resource_index_builder"; -import { FBSelect } from "../../ui/new_fb_select"; -import { InputBox } from "../step_tiles/tile_move_absolute/input_box"; -import { generateList } from "../step_tiles/tile_move_absolute/generate_list"; -import { handleSelect } from "../step_tiles/tile_move_absolute/handle_select"; +import { FBSelect } from "../../ui/index"; +import { + InputBox, generateList, handleSelect +} from "../step_tiles/tile_move_absolute/index"; const coord: Coordinate = { kind: "coordinate", args: { x: 1, y: 2, z: 3 } }; const tool: Tool = { kind: "tool", args: { tool_id: 4 } }; diff --git a/webpack/sequences/__tests__/sequence_editor_middle_inactive_test.tsx b/webpack/sequences/__tests__/sequence_editor_middle_inactive_test.tsx index d79d51f81..3fa863a32 100644 --- a/webpack/sequences/__tests__/sequence_editor_middle_inactive_test.tsx +++ b/webpack/sequences/__tests__/sequence_editor_middle_inactive_test.tsx @@ -1,5 +1,7 @@ import * as React from "react"; -import { SequenceEditorMiddleInactive, IMAGE_PATH } from "../sequence_editor_middle_inactive"; +import { + SequenceEditorMiddleInactive, IMAGE_PATH +} from "../sequence_editor_middle_inactive"; import { shallow } from "enzyme"; import { Content } from "../../constants"; diff --git a/webpack/sequences/__tests__/sequence_editor_middle_test.tsx b/webpack/sequences/__tests__/sequence_editor_middle_test.tsx index ccc58356f..0060dcd1f 100644 --- a/webpack/sequences/__tests__/sequence_editor_middle_test.tsx +++ b/webpack/sequences/__tests__/sequence_editor_middle_test.tsx @@ -2,7 +2,9 @@ import * as React from "react"; import { SequenceEditorMiddle } from "../sequence_editor_middle"; import { mount } from "enzyme"; import { SequenceEditorMiddleProps } from "../interfaces"; -import { FAKE_RESOURCES, buildResourceIndex } from "../../__test_support__/resource_index_builder"; +import { + FAKE_RESOURCES, buildResourceIndex +} from "../../__test_support__/resource_index_builder"; import { fakeSequence } from "../../__test_support__/fake_state/resources"; describe("", () => { diff --git a/webpack/sequences/__tests__/sequences_test.tsx b/webpack/sequences/__tests__/sequences_test.tsx index 70e529b1a..75dca51c9 100644 --- a/webpack/sequences/__tests__/sequences_test.tsx +++ b/webpack/sequences/__tests__/sequences_test.tsx @@ -6,7 +6,9 @@ import * as React from "react"; import { Sequences } from "../sequences"; import { shallow } from "enzyme"; import { Props } from "../interfaces"; -import { FAKE_RESOURCES, buildResourceIndex } from "../../__test_support__/resource_index_builder"; +import { + FAKE_RESOURCES, buildResourceIndex +} from "../../__test_support__/resource_index_builder"; import { fakeSequence } from "../../__test_support__/fake_state/resources"; import { auth } from "../../__test_support__/fake_state/token"; import { ToolTips } from "../../constants"; diff --git a/webpack/sequences/actions.ts b/webpack/sequences/actions.ts index 375c8d159..d4633d040 100644 --- a/webpack/sequences/actions.ts +++ b/webpack/sequences/actions.ts @@ -1,6 +1,6 @@ import { CeleryNode as Step, SequenceBodyItem } from "farmbot"; import { ChangeStepSelect, SelectSequence } from "./interfaces"; -import { DropDownItem } from "../ui"; +import { DropDownItem } from "../ui/index"; import { GetState } from "../redux/interfaces"; import { edit, init, overwrite } from "../api/crud"; import { TaggedSequence } from "../resources/tagged_resources"; diff --git a/webpack/sequences/inputs/input_default.tsx b/webpack/sequences/inputs/input_default.tsx index 7b7c79c56..c8e5bdfcd 100644 --- a/webpack/sequences/inputs/input_default.tsx +++ b/webpack/sequences/inputs/input_default.tsx @@ -2,7 +2,7 @@ import * as React from "react"; import { updateStep } from "../step_tiles/index"; import { isString, isNumber } from "lodash"; import { StepInputProps } from "../interfaces"; -import { BlurableInput } from "../../ui"; +import { BlurableInput } from "../../ui/index"; import { Dictionary } from "farmbot/dist"; export function InputDefault({ diff --git a/webpack/sequences/interfaces.ts b/webpack/sequences/interfaces.ts index 2f1d0caca..f40d8ce41 100644 --- a/webpack/sequences/interfaces.ts +++ b/webpack/sequences/interfaces.ts @@ -7,9 +7,7 @@ import { SyncStatus } from "farmbot"; import { StepMoveDataXfer, StepSpliceDataXfer } from "../draggable/interfaces"; -import { - TaggedSequence -} from "../resources/tagged_resources"; +import { TaggedSequence } from "../resources/tagged_resources"; import { ResourceIndex } from "../resources/interfaces"; import { JSXChildren } from "../util"; diff --git a/webpack/sequences/locals_list.tsx b/webpack/sequences/locals_list.tsx index 8647571eb..015d4dcac 100644 --- a/webpack/sequences/locals_list.tsx +++ b/webpack/sequences/locals_list.tsx @@ -5,18 +5,14 @@ import { Vector3 } from "farmbot"; import { ResourceIndex } from "../resources/interfaces"; -import { LocationData } from "./step_tiles/tile_move_absolute/interfaces"; +import { + LocationData, InputBox, generateList, formatSelectedDropdown, handleSelect +} from "./step_tiles/tile_move_absolute/index"; import { overwrite } from "../api/crud"; import { TaggedSequence } from "../resources/tagged_resources"; import { defensiveClone } from "../util"; -import { Row } from "../ui/row"; -import { Col } from "../ui/index"; -import { InputBox } from "./step_tiles/tile_move_absolute/input_box"; +import { Row, Col, FBSelect } from "../ui/index"; import { t } from "i18next"; -import { generateList } from "./step_tiles/tile_move_absolute/generate_list"; -import { formatSelectedDropdown } from "./step_tiles/tile_move_absolute/format_selected_dropdown"; -import { handleSelect } from "./step_tiles/tile_move_absolute/handle_select"; -import { FBSelect } from "../ui/new_fb_select"; import { isNaN } from "lodash"; type LocalVariable = ParameterDeclaration | VariableDeclaration; @@ -171,7 +167,7 @@ export const ParentVariableForm =
; - } + }; /** List of local variable declarations for a sequence. If no variables are * found, shows nothing. */ diff --git a/webpack/sequences/sequence_editor_middle_active.tsx b/webpack/sequences/sequence_editor_middle_active.tsx index 9b33048ac..565fa162b 100644 --- a/webpack/sequences/sequence_editor_middle_active.tsx +++ b/webpack/sequences/sequence_editor_middle_active.tsx @@ -3,9 +3,8 @@ import { ActiveMiddleProps } from "./interfaces"; import { execSequence } from "../devices/actions"; import { editCurrentSequence } from "./actions"; import { splice, move } from "./step_tiles/index"; -import { ColorPicker } from "../ui"; import { t } from "i18next"; -import { BlurableInput, Row, Col, SaveBtn } from "../ui"; +import { BlurableInput, Row, Col, SaveBtn, ColorPicker } from "../ui/index"; import { DropArea } from "../draggable/drop_area"; import { stepGet } from "../draggable/actions"; import { copySequence } from "./actions"; @@ -48,57 +47,55 @@ export class SequenceEditorMiddleActive extends render() { const { dispatch, sequence } = this.props; - return ( -
-
-
- { dispatch(save(sequence.uuid)); }} /> - execSequence(sequence.body)} /> - - -
- - - { - dispatch(edit(sequence, { name: e.currentTarget.value })); - }} /> - - editCurrentSequence(dispatch, sequence, { color })} /> - - {/* +
+
+ { dispatch(save(sequence.uuid)); }} /> + execSequence(sequence.body)} /> + + +
+ + + { + dispatch(edit(sequence, { name: e.currentTarget.value })); + }} /> + + editCurrentSequence(dispatch, sequence, { color })} /> + + {/* */} -
-
-
- - - - onDrop(dispatch, sequence)(Infinity, key)}> - {t("DRAG COMMAND HERE")} - - - -
+
- ); +
+ + + + onDrop(dispatch, sequence)(Infinity, key)}> + {t("DRAG COMMAND HERE")} + + + +
+
; } } diff --git a/webpack/sequences/sequences_list.tsx b/webpack/sequences/sequences_list.tsx index d20984928..b303c3e0e 100644 --- a/webpack/sequences/sequences_list.tsx +++ b/webpack/sequences/sequences_list.tsx @@ -4,11 +4,7 @@ import { t } from "i18next"; import { push } from "../history"; import { selectSequence } from "./actions"; import { SequencesListProps, SequencesListState } from "./interfaces"; -import { - sortResourcesById, - urlFriendly, - lastUrlChunk -} from "../util"; +import { sortResourcesById, urlFriendly, lastUrlChunk } from "../util"; import { Row, Col, ToolTip } from "../ui/index"; import { TaggedSequence, SpecialStatus } from "../resources/tagged_resources"; import { init } from "../api/crud"; @@ -94,39 +90,37 @@ export class SequencesList extends const { sequences, dispatch } = this.props; const searchTerm = this.state.searchTerm.toLowerCase(); - return ( -
-

- {t("Sequences")} -

- - - - - -
- { - sortResourcesById(sequences) - .filter(seq => seq - .body - .name - .toLowerCase() - .includes(searchTerm)) - .map(sequenceList(dispatch)) - } -
- -
-
- ); + return
+

+ {t("Sequences")} +

+ + + + + +
+ { + sortResourcesById(sequences) + .filter(seq => seq + .body + .name + .toLowerCase() + .includes(searchTerm)) + .map(sequenceList(dispatch)) + } +
+ +
+
; } } diff --git a/webpack/sequences/step_button_cluster.tsx b/webpack/sequences/step_button_cluster.tsx index cfd8bf75e..167c02cb3 100644 --- a/webpack/sequences/step_button_cluster.tsx +++ b/webpack/sequences/step_button_cluster.tsx @@ -2,7 +2,7 @@ import * as React from "react"; import { StepButton } from "./step_buttons/index"; import { t } from "i18next"; import { Farmbot } from "farmbot"; -import { smoothScrollToBottom } from "../util"; +import { scrollToBottom } from "../util"; import { Row, ToolTip } from "../ui/index"; import { TaggedSequence } from "../resources/tagged_resources"; import { ToolTips } from "../constants"; @@ -157,7 +157,7 @@ export function StepButtonCluster({ dispatch, current }: StepButtonProps) { ALL_THE_BUTTONS.map(function (el, inx) { return
{ smoothScrollToBottom(); }}> + () => { scrollToBottom("sequenceDiv"); }}> {el}
; }) diff --git a/webpack/sequences/step_tiles/index.tsx b/webpack/sequences/step_tiles/index.tsx index d698133e0..7277be404 100644 --- a/webpack/sequences/step_tiles/index.tsx +++ b/webpack/sequences/step_tiles/index.tsx @@ -14,7 +14,9 @@ import { TileWritePin } from "./tile_write_pin"; import { TileExecuteScript } from "./tile_execute_script"; import { TileTakePhoto } from "./tile_take_photo"; import * as _ from "lodash"; -import { CeleryNode, LegalSequenceKind, LegalArgString, If, Execute, Nothing } from "farmbot"; +import { + CeleryNode, LegalSequenceKind, LegalArgString, If, Execute, Nothing +} from "farmbot"; import { TaggedSequence } from "../../resources/tagged_resources"; import { overwrite } from "../../api/crud"; import { TileFindHome } from "./tile_find_home"; diff --git a/webpack/sequences/step_tiles/tile_execute.tsx b/webpack/sequences/step_tiles/tile_execute.tsx index 0457e0bb4..84556993c 100644 --- a/webpack/sequences/step_tiles/tile_execute.tsx +++ b/webpack/sequences/step_tiles/tile_execute.tsx @@ -2,13 +2,12 @@ import * as _ from "lodash"; import * as React from "react"; import { StepParams } from "../interfaces"; import { t } from "i18next"; -import { DropDownItem, Row, Col } from "../../ui"; +import { Row, Col, FBSelect, DropDownItem } from "../../ui/index"; import { selectAllSequences, findSequenceById } from "../../resources/selectors"; import { Execute } from "farmbot/dist"; import { TaggedSequence } from "../../resources/tagged_resources"; import { ResourceIndex } from "../../resources/interfaces"; import { editStep } from "../../api/crud"; -import { FBSelect } from "../../ui/new_fb_select"; import { ToolTips } from "../../constants"; import { StepWrapper, StepHeader, StepContent } from "../step_ui/index"; diff --git a/webpack/sequences/step_tiles/tile_if/else.tsx b/webpack/sequences/step_tiles/tile_if/else.tsx index 211c576e1..8f51b20f9 100644 --- a/webpack/sequences/step_tiles/tile_if/else.tsx +++ b/webpack/sequences/step_tiles/tile_if/else.tsx @@ -1,8 +1,7 @@ import * as React from "react"; import { IfParams, seqDropDown, IfBlockDropDownHandler } from "./index"; import { t } from "i18next"; -import { FBSelect } from "../../../ui/new_fb_select"; -import { Row, Col } from "../../../ui/index"; +import { Row, Col, FBSelect } from "../../../ui/index"; export function Else(props: IfParams) { const { onChange, selectedItem } = IfBlockDropDownHandler(props, "_else"); diff --git a/webpack/sequences/step_tiles/tile_if/if.tsx b/webpack/sequences/step_tiles/tile_if/if.tsx index bc96c67fe..3f9307b42 100644 --- a/webpack/sequences/step_tiles/tile_if/if.tsx +++ b/webpack/sequences/step_tiles/tile_if/if.tsx @@ -3,11 +3,11 @@ import * as React from "react"; import { IfParams, LHSOptions, operatorOptions } from "./index"; import { t } from "i18next"; import { StepInputBox } from "../../inputs/step_input_box"; -import { FBSelect, NULL_CHOICE } from "../../../ui/new_fb_select"; -import { DropDownItem } from "../../../ui/fb_select"; import { defensiveClone } from "../../../util"; import { overwrite } from "../../../api/crud"; -import { Col, Row } from "../../../ui/index"; +import { + Col, Row, FBSelect, DropDownItem, NULL_CHOICE +} from "../../../ui/index"; import { ALLOWED_OPS } from "farmbot/dist"; const IS_UNDEFINED: ALLOWED_OPS = "is_undefined"; diff --git a/webpack/sequences/step_tiles/tile_if/index.tsx b/webpack/sequences/step_tiles/tile_if/index.tsx index ee253b1ac..1ea1c4d25 100644 --- a/webpack/sequences/step_tiles/tile_if/index.tsx +++ b/webpack/sequences/step_tiles/tile_if/index.tsx @@ -1,7 +1,7 @@ import * as _ from "lodash"; import * as React from "react"; import { t } from "i18next"; -import { DropDownItem } from "../../../ui"; +import { DropDownItem, NULL_CHOICE } from "../../../ui/index"; import { TaggedSequence } from "../../../resources/tagged_resources"; import { If, Execute, Nothing } from "farmbot/dist"; import { ResourceIndex } from "../../../resources/interfaces"; @@ -12,7 +12,6 @@ import { Then } from "./then"; import { Else } from "./else"; import { defensiveClone } from "../../../util"; import { overwrite } from "../../../api/crud"; -import { NULL_CHOICE } from "../../../ui/fb_select"; import { range } from "lodash"; import { ToolTips } from "../../../constants"; import { StepWrapper, StepHeader, StepContent } from "../../step_ui/index"; diff --git a/webpack/sequences/step_tiles/tile_if/then.tsx b/webpack/sequences/step_tiles/tile_if/then.tsx index 00a778bb0..4d7749dec 100644 --- a/webpack/sequences/step_tiles/tile_if/then.tsx +++ b/webpack/sequences/step_tiles/tile_if/then.tsx @@ -1,8 +1,7 @@ import * as React from "react"; import { IfParams, seqDropDown, IfBlockDropDownHandler } from "./index"; import { t } from "i18next"; -import { FBSelect } from "../../../ui/new_fb_select"; -import { Row, Col } from "../../../ui/index"; +import { Row, Col, FBSelect } from "../../../ui/index"; export function Then(props: IfParams) { const { onChange, selectedItem } = IfBlockDropDownHandler(props, "_then"); diff --git a/webpack/sequences/step_tiles/tile_move_absolute.tsx b/webpack/sequences/step_tiles/tile_move_absolute.tsx index 59b3d0818..2e8a672eb 100644 --- a/webpack/sequences/step_tiles/tile_move_absolute.tsx +++ b/webpack/sequences/step_tiles/tile_move_absolute.tsx @@ -12,10 +12,7 @@ import { Identifier, MoveAbsolute } from "farmbot"; -import { - Row, - Col -} from "../../ui"; +import { Row, Col } from "../../ui/index"; import { isTaggedSequence, TaggedTool, @@ -29,8 +26,7 @@ import { import { defensiveClone, betterMerge } from "../../util"; import { overwrite } from "../../api/crud"; import { Xyz } from "../../devices/interfaces"; -import { TileMoveAbsSelect } from "./tile_move_absolute/select"; -import { InputBox } from "./tile_move_absolute/input_box"; +import { TileMoveAbsSelect, InputBox } from "./tile_move_absolute/index"; import { ToolTips } from "../../constants"; import { extractParent } from "../locals_list"; import { StepWrapper, StepHeader, StepContent } from "../step_ui/index"; diff --git a/webpack/sequences/step_tiles/tile_move_absolute/format_selected_dropdown.ts b/webpack/sequences/step_tiles/tile_move_absolute/format_selected_dropdown.ts index 97b7df3d4..c8d9f2580 100644 --- a/webpack/sequences/step_tiles/tile_move_absolute/format_selected_dropdown.ts +++ b/webpack/sequences/step_tiles/tile_move_absolute/format_selected_dropdown.ts @@ -1,13 +1,12 @@ import { ResourceIndex } from "../../../resources/interfaces"; import { LocationData } from "./interfaces"; -import { NULL_CHOICE } from "../../../ui/index"; +import { NULL_CHOICE, DropDownItem } from "../../../ui/index"; import { dropDownName, PARENT_DDI } from "./generate_list"; import { findToolById, findPointerByTypeAndId, findToolBySlotId } from "../../../resources/selectors"; -import { DropDownItem } from "../../../ui/fb_select"; import { Point, Tool } from "farmbot/dist"; export function formatSelectedDropdown(ri: ResourceIndex, ld: LocationData): DropDownItem { diff --git a/webpack/sequences/step_tiles/tile_move_absolute/index.ts b/webpack/sequences/step_tiles/tile_move_absolute/index.ts new file mode 100644 index 000000000..82c892d0a --- /dev/null +++ b/webpack/sequences/step_tiles/tile_move_absolute/index.ts @@ -0,0 +1,7 @@ +export * from "./generate_list"; +export * from "./interfaces"; +export * from "./variables_support"; +export * from "./input_box"; +export * from "./handle_select"; +export * from "./format_selected_dropdown"; +export * from "./select"; diff --git a/webpack/sequences/step_tiles/tile_move_absolute/input_box.tsx b/webpack/sequences/step_tiles/tile_move_absolute/input_box.tsx index 923f78e70..9c0501342 100644 --- a/webpack/sequences/step_tiles/tile_move_absolute/input_box.tsx +++ b/webpack/sequences/step_tiles/tile_move_absolute/input_box.tsx @@ -1,5 +1,5 @@ import * as React from "react"; -import { BlurableInput } from "../../../ui/blurable_input"; +import { BlurableInput } from "../../../ui/index"; import { InputBoxProps } from "./interfaces"; export function InputBox(p: InputBoxProps) { diff --git a/webpack/sequences/step_tiles/tile_move_absolute/select.tsx b/webpack/sequences/step_tiles/tile_move_absolute/select.tsx index 4e5624f69..4f10944d1 100644 --- a/webpack/sequences/step_tiles/tile_move_absolute/select.tsx +++ b/webpack/sequences/step_tiles/tile_move_absolute/select.tsx @@ -1,10 +1,9 @@ import * as React from "react"; -import { FBSelect } from "../../../ui/new_fb_select"; import { generateList/*, PARENT_DDI*/ } from "./generate_list"; import { handleSelect } from "./handle_select"; import { formatSelectedDropdown } from "./format_selected_dropdown"; import { TileMoveAbsProps } from "./interfaces"; -import { DropDownItem } from "../../../ui/index"; +import { FBSelect, DropDownItem } from "../../../ui/index"; interface TileMoveAbsSelectProps extends TileMoveAbsProps { additionalItems?: DropDownItem[]; diff --git a/webpack/sequences/step_tiles/tile_read_pin.tsx b/webpack/sequences/step_tiles/tile_read_pin.tsx index 4b5631ce8..31eac1c20 100644 --- a/webpack/sequences/step_tiles/tile_read_pin.tsx +++ b/webpack/sequences/step_tiles/tile_read_pin.tsx @@ -3,10 +3,9 @@ import { t } from "i18next"; import { StepInputBox } from "../inputs/step_input_box"; import { StepParams } from "../interfaces"; import { ToolTips } from "../../constants"; -import { FBSelect } from "../../ui/new_fb_select"; import { setPinMode, PIN_MODES, currentModeSelection } from "./tile_pin_support"; import { StepWrapper, StepHeader, StepContent } from "../step_ui/index"; -import { Row, Col } from "../../ui/index"; +import { Row, Col, FBSelect } from "../../ui/index"; export function TileReadPin(props: StepParams) { const { dispatch, currentStep, index, currentSequence } = props; diff --git a/webpack/sequences/step_tiles/tile_send_message.tsx b/webpack/sequences/step_tiles/tile_send_message.tsx index d4d62d2ba..480940437 100644 --- a/webpack/sequences/step_tiles/tile_send_message.tsx +++ b/webpack/sequences/step_tiles/tile_send_message.tsx @@ -1,5 +1,5 @@ import * as React from "react"; -import { DropDownItem, Row, Col } from "../../ui"; +import { FBSelect, DropDownItem, Row, Col } from "../../ui/index"; import { t } from "i18next"; import { StepInputBox } from "../inputs/step_input_box"; import { SendMessage, ALLOWED_CHANNEL_NAMES } from "farmbot"; @@ -8,7 +8,6 @@ import { StepParams } from "../interfaces"; import { TaggedSequence } from "../../resources/tagged_resources"; import { ResourceIndex } from "../../resources/interfaces"; import { editStep } from "../../api/crud"; -import { FBSelect } from "../../ui/new_fb_select"; import { ToolTips } from "../../constants"; import { MESSAGE_STATUSES, diff --git a/webpack/sequences/step_tiles/tile_write_pin.tsx b/webpack/sequences/step_tiles/tile_write_pin.tsx index f01579127..bf160dd2a 100644 --- a/webpack/sequences/step_tiles/tile_write_pin.tsx +++ b/webpack/sequences/step_tiles/tile_write_pin.tsx @@ -3,13 +3,12 @@ import { t } from "i18next"; import { StepInputBox } from "../inputs/step_input_box"; import { StepParams } from "../interfaces"; import { ToolTips } from "../../constants"; -import { FBSelect } from "../../ui/new_fb_select"; import { setPinMode, PIN_MODES, setPinValue, currentValueSelection, PIN_VALUES, currentModeSelection } from "./tile_pin_support"; import { StepWrapper, StepHeader, StepContent } from "../step_ui/index"; -import { Row, Col } from "../../ui/index"; +import { Row, Col, FBSelect } from "../../ui/index"; export function TileWritePin(props: StepParams) { const { dispatch, currentStep, index, currentSequence } = props; diff --git a/webpack/session.ts b/webpack/session.ts index dedd35587..b4ff19d10 100644 --- a/webpack/session.ts +++ b/webpack/session.ts @@ -2,7 +2,7 @@ import { AuthState } from "./auth/interfaces"; import { box } from "boxed_value"; import { BooleanConfigKey, NumberConfigKey } from "./config_storage/web_app_configs"; import { BooleanSetting, NumericSetting } from "./session_keys"; -import { getBoolViaRedux, setBoolViaRedux, getNumViaRedux, setNumViaRedux } from "./config/legacy_shims"; +import * as LegacyShim from "./config/legacy_shims"; /** The `Session` namespace is a wrapper for `localStorage`. * Use this to avoid direct access of `localStorage` where possible. @@ -47,12 +47,12 @@ export namespace Session { /** @deprecated Don't use this anymore. This is a legacy articfact of when we * used localStorage to store API settings. */ export function deprecatedGetBool(key: BooleanConfigKey): boolean | undefined { - return getBoolViaRedux(key); + return LegacyShim.getBoolViaRedux(key); } /** Store a boolean value in `localStorage` */ export function setBool(key: BooleanConfigKey, val: boolean): boolean { - return setBoolViaRedux(key, val); + return LegacyShim.setBoolViaRedux(key, val); } export function invertBool(key: BooleanConfigKey): boolean { @@ -62,12 +62,12 @@ export namespace Session { /** Extract numeric settings from `localStorage`. Returns `undefined` when * none are found. */ export function deprecatedGetNum(key: NumberConfigKey): number | undefined { - return getNumViaRedux(key); + return LegacyShim.getNumViaRedux(key); } /** Set a numeric value in `localStorage`. */ export function deprecatedSetNum(key: NumberConfigKey, val: number): void { - setNumViaRedux(key, val); + LegacyShim.setNumViaRedux(key, val); } } diff --git a/webpack/tools/components/tool_form.tsx b/webpack/tools/components/tool_form.tsx index 9803a4294..2e22e45da 100644 --- a/webpack/tools/components/tool_form.tsx +++ b/webpack/tools/components/tool_form.tsx @@ -9,8 +9,10 @@ import { WidgetHeader, BlurableInput, SaveBtn -} from "../../ui"; -import { TaggedTool, getArrayStatus, SpecialStatus } from "../../resources/tagged_resources"; +} from "../../ui/index"; +import { + TaggedTool, getArrayStatus, SpecialStatus +} from "../../resources/tagged_resources"; import { edit, destroy, init, saveAll } from "../../api/crud"; import { ToolTips } from "../../constants"; diff --git a/webpack/tools/components/tool_list.tsx b/webpack/tools/components/tool_list.tsx index 0d8f16d68..03a304532 100644 --- a/webpack/tools/components/tool_list.tsx +++ b/webpack/tools/components/tool_list.tsx @@ -1,5 +1,5 @@ import * as React from "react"; -import { Row, Col, Widget, WidgetBody, WidgetHeader } from "../../ui"; +import { Row, Col, Widget, WidgetBody, WidgetHeader } from "../../ui/index"; import { t } from "i18next"; import { ToolListProps } from "../interfaces"; import { TaggedTool } from "../../resources/tagged_resources"; diff --git a/webpack/tools/components/toolbay_form.tsx b/webpack/tools/components/toolbay_form.tsx index fb1a6f579..f144ad432 100644 --- a/webpack/tools/components/toolbay_form.tsx +++ b/webpack/tools/components/toolbay_form.tsx @@ -7,14 +7,14 @@ import { Col, Row, BlurableInput, - SaveBtn -} from "../../ui"; + SaveBtn, + FBSelect +} from "../../ui/index"; import { t } from "i18next"; import { TaggedToolSlotPointer, getArrayStatus, SpecialStatus } from "../../resources/tagged_resources"; import { edit, destroy, saveAll, init } from "../../api/crud"; -import { FBSelect } from "../../ui/new_fb_select"; import { ToolBayHeader } from "./toolbay_header"; import { ToolTips } from "../../constants"; import * as _ from "lodash"; diff --git a/webpack/tools/components/toolbay_list.tsx b/webpack/tools/components/toolbay_list.tsx index 416f19398..99e370e11 100644 --- a/webpack/tools/components/toolbay_list.tsx +++ b/webpack/tools/components/toolbay_list.tsx @@ -1,6 +1,6 @@ import * as React from "react"; import { t } from "i18next"; -import { Row, Col, Widget, WidgetBody, WidgetHeader } from "../../ui"; +import { Row, Col, Widget, WidgetBody, WidgetHeader } from "../../ui/index"; import { ToolBayListProps } from "../interfaces"; import { TaggedToolSlotPointer } from "../../resources/tagged_resources"; import { ToolBayHeader } from "./toolbay_header"; diff --git a/webpack/tools/index.tsx b/webpack/tools/index.tsx index d1560662a..c514ad173 100644 --- a/webpack/tools/index.tsx +++ b/webpack/tools/index.tsx @@ -1,7 +1,7 @@ import * as React from "react"; import { connect } from "react-redux"; import { ToolsState, Props } from "./interfaces"; -import { Col, Row, Page } from "../ui"; +import { Col, Row, Page } from "../ui/index"; import { ToolBayList, ToolBayForm, ToolList, ToolForm } from "./components"; import { mapStateToProps } from "./state_to_props"; import { catchErrors } from "../util"; diff --git a/webpack/tools/interfaces.ts b/webpack/tools/interfaces.ts index d29c3607b..3cb26c5f4 100644 --- a/webpack/tools/interfaces.ts +++ b/webpack/tools/interfaces.ts @@ -1,4 +1,4 @@ -import { DropDownItem } from "../ui/fb_select"; +import { DropDownItem } from "../ui/index"; import { TaggedTool, TaggedToolSlotPointer, diff --git a/webpack/tools/state_to_props.ts b/webpack/tools/state_to_props.ts index ac9ec122d..41ed7ac6b 100644 --- a/webpack/tools/state_to_props.ts +++ b/webpack/tools/state_to_props.ts @@ -1,7 +1,6 @@ import { Everything } from "../interfaces"; import { Props } from "./interfaces"; import * as _ from "lodash"; -import { NULL_CHOICE } from "../ui/fb_select"; import { selectAllToolSlotPointers, selectAllTools, @@ -13,7 +12,7 @@ import { TaggedToolSlotPointer } from "../resources/tagged_resources"; import { edit } from "../api/crud"; -import { DropDownItem } from "../ui/index"; +import { DropDownItem, NULL_CHOICE } from "../ui/index"; import { BotPosition } from "../devices/interfaces"; export function mapStateToProps(props: Everything): Props { diff --git a/webpack/ui/color_picker.tsx b/webpack/ui/color_picker.tsx index e2775586b..126edbead 100644 --- a/webpack/ui/color_picker.tsx +++ b/webpack/ui/color_picker.tsx @@ -1,6 +1,6 @@ import * as React from "react"; import { Popover, Position } from "@blueprintjs/core"; -import { Saucer } from "../ui"; +import { Saucer } from "../ui/index"; import { Color } from "../interfaces"; import { colors } from "../util"; diff --git a/webpack/ui/filter_search.tsx b/webpack/ui/filter_search.tsx index 50767b5e0..5195bba11 100644 --- a/webpack/ui/filter_search.tsx +++ b/webpack/ui/filter_search.tsx @@ -2,9 +2,7 @@ import * as React from "react"; import { t } from "i18next"; import { Button, Classes, MenuItem } from "@blueprintjs/core"; import { ISelectItemRendererProps, Select } from "@blueprintjs/labs"; - -import { DropDownItem } from "./fb_select"; -import { NULL_CHOICE } from "./new_fb_select"; +import { DropDownItem, NULL_CHOICE } from "./fb_select"; const SelectComponent = Select.ofType(); @@ -47,20 +45,18 @@ export class FilterSearch extends React.Component> { render() { const { item, minimal, ...flags } = this.state; - return ( - } - onItemSelect={this.handleValueChange} - popoverProps={{ popoverClassName: minimal ? Classes.MINIMAL : "" }}> -