From e24fa8ac10924a76d8ff5a9ca46411f7774d8a7b Mon Sep 17 00:00:00 2001 From: gabrielburnworth Date: Fri, 15 Dec 2023 15:06:24 -0800 Subject: [PATCH 1/4] upgrade deps --- Gemfile.lock | 33 ++++++++--------- frontend/__test_support__/fake_html_events.ts | 2 +- .../api/__tests__/crud_data_tracking_test.ts | 2 +- .../connect_device/connect_device_test.ts | 2 +- frontend/connectivity/__tests__/index_test.ts | 3 +- .../connectivity/__tests__/ping_mqtt_test.ts | 2 +- frontend/devices/__tests__/actions_test.ts | 2 +- frontend/folders/__tests__/actions_test.ts | 2 +- frontend/folders/actions.ts | 2 +- .../point_groups/__tests__/actions_test.ts | 2 +- frontend/redux/interfaces.ts | 2 ++ frontend/redux/middlewares.ts | 2 +- .../redux/revert_to_english_middleware.ts | 3 +- frontend/resources/__tests__/in_use_test.ts | 2 +- frontend/ui/__tests__/markdown_test.tsx | 13 ++++--- frontend/ui/markdown-it-emoji.d.ts | 1 + frontend/ui/markdown.tsx | 23 ++++++------ package.json | 36 +++++++++---------- 18 files changed, 72 insertions(+), 62 deletions(-) create mode 100644 frontend/ui/markdown-it-emoji.d.ts diff --git a/Gemfile.lock b/Gemfile.lock index 2ead3bdfbe..88e57cf222 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -71,7 +71,7 @@ GEM minitest (>= 5.1) tzinfo (~> 2.0) zeitwerk (~> 2.3) - addressable (2.8.5) + addressable (2.8.6) public_suffix (>= 2.0.2, < 6.0) amq-protocol (2.3.2) bcrypt (3.1.20) @@ -114,10 +114,10 @@ GEM docile (1.4.0) e2mmap (0.1.0) erubi (1.12.0) - factory_bot (6.2.1) + factory_bot (6.4.2) activesupport (>= 5.0.0) - factory_bot_rails (6.2.0) - factory_bot (~> 6.2.0) + factory_bot_rails (6.4.2) + factory_bot (~> 6.4) railties (>= 5.0.0) faker (3.2.2) i18n (>= 1.8.11, < 2) @@ -161,11 +161,11 @@ GEM google-apis-core (>= 0.11.0, < 2.a) google-apis-storage_v1 (0.29.0) google-apis-core (>= 0.11.0, < 2.a) - google-cloud-core (1.6.0) - google-cloud-env (~> 1.0) + google-cloud-core (1.6.1) + google-cloud-env (>= 1.0, < 3.a) google-cloud-errors (~> 1.0) - google-cloud-env (1.6.0) - faraday (>= 0.17.3, < 3.0) + google-cloud-env (2.1.0) + faraday (>= 1.0, < 3.a) google-cloud-errors (1.3.1) google-cloud-storage (1.45.0) addressable (~> 2.8) @@ -175,13 +175,14 @@ GEM google-cloud-core (~> 1.6) googleauth (>= 0.16.2, < 2.a) mini_mime (~> 1.0) - googleauth (1.8.1) - faraday (>= 0.17.3, < 3.a) + googleauth (1.9.1) + faraday (>= 1.0, < 3.a) + google-cloud-env (~> 2.1) jwt (>= 1.4, < 3.0) multi_json (~> 1.11) os (>= 0.9, < 2.0) signet (>= 0.16, < 2.a) - hashdiff (1.0.1) + hashdiff (1.1.0) hashie (4.1.0) httpclient (2.8.3) i18n (1.14.1) @@ -221,7 +222,7 @@ GEM multipart-post (2.3.0) mutations (0.9.1) activesupport - net-imap (0.4.5) + net-imap (0.4.8) date net-protocol net-pop (0.1.2) @@ -230,7 +231,7 @@ GEM timeout net-smtp (0.4.0) net-protocol - nio4r (2.6.1) + nio4r (2.7.0) nokogiri (1.15.5-x86_64-linux) racc (~> 1.4) orm_adapter (0.5.0) @@ -306,7 +307,7 @@ GEM railties (>= 5.2) retriable (3.1.2) rexml (3.2.6) - rollbar (3.4.1) + rollbar (3.4.2) rspec (3.12.0) rspec-core (~> 3.12.0) rspec-expectations (~> 3.12.0) @@ -335,7 +336,7 @@ GEM activerecord (>= 4.0.0) railties (>= 4.0.0) secure_headers (6.5.0) - set (1.0.3) + set (1.0.4) signet (0.18.0) addressable (~> 2.8) faraday (>= 0.17.5, < 3.a) @@ -432,4 +433,4 @@ RUBY VERSION ruby 3.1.4p223 BUNDLED WITH - 2.4.22 + 2.5.0 diff --git a/frontend/__test_support__/fake_html_events.ts b/frontend/__test_support__/fake_html_events.ts index a4a660f6c7..dd3fa91a56 100644 --- a/frontend/__test_support__/fake_html_events.ts +++ b/frontend/__test_support__/fake_html_events.ts @@ -1,4 +1,4 @@ -import { DeepPartial } from "redux"; +import { DeepPartial } from "../redux/interfaces"; type DomEvent = React.SyntheticEvent; export const inputEvent = (value: string, name?: string): DomEvent => { diff --git a/frontend/api/__tests__/crud_data_tracking_test.ts b/frontend/api/__tests__/crud_data_tracking_test.ts index 72f6104437..3f046e80b5 100644 --- a/frontend/api/__tests__/crud_data_tracking_test.ts +++ b/frontend/api/__tests__/crud_data_tracking_test.ts @@ -17,7 +17,7 @@ import { destroy, saveAll, initSave, initSaveGetId } from "../crud"; import { buildResourceIndex } from "../../__test_support__/resource_index_builder"; import { createStore, applyMiddleware } from "redux"; import { resourceReducer } from "../../resources/reducer"; -import thunk from "redux-thunk"; +import { thunk } from "redux-thunk"; import { ReduxAction } from "../../redux/interfaces"; import { maybeStartTracking } from "../maybe_start_tracking"; import { API } from "../api"; diff --git a/frontend/connectivity/__tests__/connect_device/connect_device_test.ts b/frontend/connectivity/__tests__/connect_device/connect_device_test.ts index fc10c21d5f..ac7be397d4 100644 --- a/frontend/connectivity/__tests__/connect_device/connect_device_test.ts +++ b/frontend/connectivity/__tests__/connect_device/connect_device_test.ts @@ -6,7 +6,7 @@ jest.mock("../../../device", () => { import { fetchNewDevice } from "../../../device"; import { connectDevice } from "../../connect_device"; -import { DeepPartial } from "redux"; +import { DeepPartial } from "../../../redux/interfaces"; import { AuthState } from "../../../auth/interfaces"; import { fakeState } from "../../../__test_support__/fake_state"; diff --git a/frontend/connectivity/__tests__/index_test.ts b/frontend/connectivity/__tests__/index_test.ts index 52fcdd6435..d1eefe1564 100644 --- a/frontend/connectivity/__tests__/index_test.ts +++ b/frontend/connectivity/__tests__/index_test.ts @@ -26,11 +26,10 @@ import { networkUptimeThrottleStats, } from "../index"; import { networkUp, networkDown } from "../actions"; -import { GetState } from "../../redux/interfaces"; +import { GetState, DeepPartial } from "../../redux/interfaces"; import { autoSync, routeMqttData } from "../auto_sync"; import { handleInbound } from "../auto_sync_handle_inbound"; import { store } from "../../redux/store"; -import { DeepPartial } from "redux"; import { Everything } from "../../interfaces"; import { Actions } from "../../constants"; diff --git a/frontend/connectivity/__tests__/ping_mqtt_test.ts b/frontend/connectivity/__tests__/ping_mqtt_test.ts index 872f881f72..296328a462 100644 --- a/frontend/connectivity/__tests__/ping_mqtt_test.ts +++ b/frontend/connectivity/__tests__/ping_mqtt_test.ts @@ -14,7 +14,7 @@ import { import { Farmbot } from "farmbot"; import { FarmBotInternalConfig } from "farmbot/dist/config"; import { pingNO } from "../index"; -import { DeepPartial } from "redux"; +import { DeepPartial } from "../../redux/interfaces"; const state: Partial = { LAST_PING_IN: 123, diff --git a/frontend/devices/__tests__/actions_test.ts b/frontend/devices/__tests__/actions_test.ts index 8eb76ad323..ede05d510a 100644 --- a/frontend/devices/__tests__/actions_test.ts +++ b/frontend/devices/__tests__/actions_test.ts @@ -55,7 +55,7 @@ import { buildResourceIndex } from "../../__test_support__/resource_index_builde import axios from "axios"; import { success, error, warning, info } from "../../toast/toast"; import { edit, save } from "../../api/crud"; -import { DeepPartial } from "redux"; +import { DeepPartial } from "../../redux/interfaces"; import { Farmbot } from "farmbot"; import { goToFbosSettings } from "../../settings/maybe_highlight"; diff --git a/frontend/folders/__tests__/actions_test.ts b/frontend/folders/__tests__/actions_test.ts index 56eeae7013..c2ad506eba 100644 --- a/frontend/folders/__tests__/actions_test.ts +++ b/frontend/folders/__tests__/actions_test.ts @@ -21,7 +21,7 @@ import { sequenceEditMaybeSave, } from "../actions"; import { store } from "../../redux/store"; -import { DeepPartial } from "redux"; +import { DeepPartial } from "../../redux/interfaces"; import { Everything } from "../../interfaces"; import { buildResourceIndex } from "../../__test_support__/resource_index_builder"; import { newTaggedResource } from "../../sync/actions"; diff --git a/frontend/folders/actions.ts b/frontend/folders/actions.ts index 86f9ddcf00..6e6911c4d3 100644 --- a/frontend/folders/actions.ts +++ b/frontend/folders/actions.ts @@ -2,7 +2,7 @@ import { Color, SpecialStatus, TaggedSequence } from "farmbot"; import { store } from "../redux/store"; import { initSave, destroy, edit, save, init } from "../api/crud"; import { Folder } from "farmbot/dist/resources/api_resources"; -import { DeepPartial } from "redux"; +import { DeepPartial } from "../redux/interfaces"; import { findFolderById } from "../resources/selectors_by_id"; import { Actions } from "../constants"; import { t } from "../i18next_wrapper"; diff --git a/frontend/point_groups/__tests__/actions_test.ts b/frontend/point_groups/__tests__/actions_test.ts index 4f787b1064..cf4780cca7 100644 --- a/frontend/point_groups/__tests__/actions_test.ts +++ b/frontend/point_groups/__tests__/actions_test.ts @@ -21,7 +21,7 @@ import { import { fakePoint, fakePlant, fakeToolSlot, fakePointGroup, } from "../../__test_support__/fake_state/resources"; -import { DeepPartial } from "redux"; +import { DeepPartial } from "../../redux/interfaces"; import { Everything } from "../../interfaces"; import { DEFAULT_CRITERIA } from "../criteria/interfaces"; import { cloneDeep } from "lodash"; diff --git a/frontend/redux/interfaces.ts b/frontend/redux/interfaces.ts index 6c10ca58af..2dac90bf49 100644 --- a/frontend/redux/interfaces.ts +++ b/frontend/redux/interfaces.ts @@ -20,3 +20,5 @@ export interface Thunk { export type EnvName = "test" | "production" | "development" | "*"; export type Reducers = Reducer, AnyAction>; + +export type DeepPartial = { [K in keyof T]?: DeepPartial } diff --git a/frontend/redux/middlewares.ts b/frontend/redux/middlewares.ts index 56ed860b5c..c0a73b683c 100644 --- a/frontend/redux/middlewares.ts +++ b/frontend/redux/middlewares.ts @@ -1,4 +1,4 @@ -import thunk from "redux-thunk"; +import { thunk } from "redux-thunk"; import { Store, Middleware, applyMiddleware, compose, StoreEnhancer } from "redux"; import { EnvName, ReduxAction } from "./interfaces"; import { stateFetchMiddlewareConfig } from "./state_fetch_middleware"; diff --git a/frontend/redux/revert_to_english_middleware.ts b/frontend/redux/revert_to_english_middleware.ts index d709148409..0092d48ad5 100644 --- a/frontend/redux/revert_to_english_middleware.ts +++ b/frontend/redux/revert_to_english_middleware.ts @@ -1,10 +1,11 @@ -import { Middleware, DeepPartial } from "redux"; +import { Middleware } from "redux"; import { MiddlewareConfig } from "./middlewares"; import { ResourceName, TaggedWebAppConfig } from "farmbot"; import { Actions } from "../constants"; import { revertToEnglish } from "../revert_to_english"; import { SyncResponse } from "../sync/actions"; import { arrayUnwrap } from "../resources/util"; +import { DeepPartial } from "./interfaces"; const WEB_APP_CONFIG: ResourceName = "WebAppConfig"; diff --git a/frontend/resources/__tests__/in_use_test.ts b/frontend/resources/__tests__/in_use_test.ts index eabaa8edcb..8e07c11535 100644 --- a/frontend/resources/__tests__/in_use_test.ts +++ b/frontend/resources/__tests__/in_use_test.ts @@ -4,7 +4,7 @@ import { buildResourceIndex, } from "../../__test_support__/resource_index_builder"; import { EVERY_USAGE_KIND, UsageIndex, resourceUsageList } from "../in_use"; -import { DeepPartial } from "redux"; +import { DeepPartial } from "../../redux/interfaces"; import { fakeSequence, fakeFarmEvent, diff --git a/frontend/ui/__tests__/markdown_test.tsx b/frontend/ui/__tests__/markdown_test.tsx index bdbdf41a65..86116f058d 100644 --- a/frontend/ui/__tests__/markdown_test.tsx +++ b/frontend/ui/__tests__/markdown_test.tsx @@ -1,3 +1,6 @@ +/* eslint-disable @typescript-eslint/no-unsafe-argument */ +/* eslint-disable @typescript-eslint/no-explicit-any */ +import { Token } from "markdown-it"; import { Markdown, md_for_tests } from "../markdown"; import { mount } from "enzyme"; @@ -16,13 +19,14 @@ describe("", () => { describe("link_open_for_tests()", () => { const fakeTokens = () => [ { attrPush: jest.fn(), attrIndex: () => 0, attrs: [["", ""]] }, - ]; + ] as unknown as Token[]; it("adds new attribute", () => { const tokens = fakeTokens(); tokens[0].attrIndex = () => -1; const renderToken = jest.fn(); - md_for_tests.renderer.rules.link_open(tokens, 0, {}, {}, { renderToken }); + md_for_tests.renderer.rules.link_open?.(tokens, 0, {}, {}, + { renderToken } as any); expect(tokens[0].attrPush).toHaveBeenCalledWith(["target", "_blank"]); expect(renderToken).toHaveBeenCalledWith(tokens, 0, {}); }); @@ -30,8 +34,9 @@ describe("link_open_for_tests()", () => { it("updates attribute", () => { const tokens = fakeTokens(); const renderToken = jest.fn(); - md_for_tests.renderer.rules.link_open(tokens, 0, {}, {}, { renderToken }); - expect(tokens[0].attrs[0][1]).toEqual("_blank"); + md_for_tests.renderer.rules.link_open?.(tokens, 0, {}, {}, + { renderToken } as any); + expect(tokens[0].attrs?.[0][1]).toEqual("_blank"); expect(renderToken).toHaveBeenCalledWith(tokens, 0, {}); }); }); diff --git a/frontend/ui/markdown-it-emoji.d.ts b/frontend/ui/markdown-it-emoji.d.ts new file mode 100644 index 0000000000..e1a0be37e4 --- /dev/null +++ b/frontend/ui/markdown-it-emoji.d.ts @@ -0,0 +1 @@ +declare module "markdown-it-emoji"; diff --git a/frontend/ui/markdown.tsx b/frontend/ui/markdown.tsx index 868d4804ab..64295576fb 100644 --- a/frontend/ui/markdown.tsx +++ b/frontend/ui/markdown.tsx @@ -1,12 +1,15 @@ import React from "react"; -const emoji = require("markdown-it-emoji"); -const md = require("markdown-it")({ +import { full as emoji } from "markdown-it-emoji"; +import markdownit from "markdown-it"; + +const md = markdownit({ breaks: true, linkify: true, typographer: true, -}); +}) + .use(emoji as markdownit.PluginSimple); -const md_with_html = require("markdown-it")({ +const md_with_html = markdownit({ /** Enable HTML tags in source */ html: true, /** Convert '\n' in paragraphs into
*/ @@ -15,10 +18,8 @@ const md_with_html = require("markdown-it")({ linkify: true, /** Enable some language-neutral replacement + quotes beautification */ typographer: true, -}); - -md.use(emoji); -md_with_html.use(emoji); +}) + .use(emoji as markdownit.PluginSimple); const defaultRenderer = md.renderer.rules.link_open || // eslint-disable-next-line @typescript-eslint/no-explicit-any @@ -40,15 +41,15 @@ md.renderer.rules.link_open = export const md_for_tests = md; interface MarkdownProps { - children?: React.ReactNode; + children?: string; html?: boolean; className?: string; } export function Markdown(props: MarkdownProps) { const result = props.html - ? md_with_html.render(props.children) - : md.render(props.children); + ? md_with_html.render("" + props.children) + : md.render("" + props.children); return diff --git a/package.json b/package.json index 4549a8f5a2..43972ffa2e 100644 --- a/package.json +++ b/package.json @@ -31,32 +31,32 @@ "author": "farmbot.io", "license": "MIT", "dependencies": { - "@blueprintjs/core": "5.7.1", - "@blueprintjs/select": "5.0.19", + "@blueprintjs/core": "5.7.2", + "@blueprintjs/select": "5.0.20", "@monaco-editor/react": "4.6.0", "@parcel/transformer-sass": "2.10.3", "@parcel/transformer-typescript-tsc": "2.10.3", "@types/lodash": "4.14.202", "@types/markdown-it": "13.0.7", - "@types/node": "20.9.3", + "@types/node": "20.10.4", "@types/promise-timeout": "1.3.3", - "@types/react": "18.2.38", + "@types/react": "18.2.45", "@types/react-color": "3.0.10", - "@types/react-dom": "18.2.16", + "@types/react-dom": "18.2.17", "@types/ws": "8.5.10", "axios": "1.6.2", "bowser": "2.11.0", "browser-speech": "1.1.1", "events": "3.3.0", "farmbot": "15.8.5", - "i18next": "23.7.6", + "i18next": "23.7.11", "lodash": "4.17.21", - "markdown-it": "13.0.2", - "markdown-it-emoji": "2.0.2", + "markdown-it": "14.0.0", + "markdown-it-emoji": "3.0.0", "moment": "2.29.4", - "monaco-editor": "0.44.0", + "monaco-editor": "0.45.0", "mqtt": "5.1.4", - "npm": "10.2.4", + "npm": "10.2.5", "parcel": "2.10.3", "process": "0.11.10", "promise-timeout": "1.3.0", @@ -68,24 +68,24 @@ "react-redux": "8.1.3", "redux": "4.2.1", "redux-immutable-state-invariant": "2.1.0", - "redux-thunk": "2.4.2", + "redux-thunk": "3.1.0", "takeme": "0.12.0", - "typescript": "5.3.2", + "typescript": "5.3.3", "url": "0.11.3", "xterm": "5.3.0" }, "devDependencies": { "@types/enzyme": "3.10.12", - "@types/jest": "29.5.9", - "@types/readable-stream": "4.0.8", - "@typescript-eslint/eslint-plugin": "6.12.0", - "@typescript-eslint/parser": "6.12.0", + "@types/jest": "29.5.11", + "@types/readable-stream": "4.0.10", + "@typescript-eslint/eslint-plugin": "6.14.0", + "@typescript-eslint/parser": "6.14.0", "@wojtekmaj/enzyme-adapter-react-17": "0.8.0", "coveralls": "3.1.1", "enzyme": "3.11.0", - "eslint": "8.54.0", + "eslint": "8.55.0", "eslint-plugin-eslint-comments": "3.2.0", - "eslint-plugin-import": "2.29.0", + "eslint-plugin-import": "2.29.1", "eslint-plugin-jest": "27.6.0", "eslint-plugin-no-null": "1.0.2", "eslint-plugin-promise": "6.1.1", From e21df02561a9735b7c3fd09b499f5fc2b8485d81 Mon Sep 17 00:00:00 2001 From: gabrielburnworth Date: Fri, 15 Dec 2023 16:22:29 -0800 Subject: [PATCH 2/4] fix map legend position --- frontend/css/farm_designer/farm_designer.scss | 4 ++-- frontend/css/global.scss | 8 +++++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/frontend/css/farm_designer/farm_designer.scss b/frontend/css/farm_designer/farm_designer.scss index e131a8a44f..d5d2060d8a 100644 --- a/frontend/css/farm_designer/farm_designer.scss +++ b/frontend/css/farm_designer/farm_designer.scss @@ -671,11 +671,11 @@ .garden-map-legend { position: fixed; top: 110px; - right: -140px; + right: -155px; z-index: 3; transition: all 0.4s ease; &.active { - transform: translateX(-150px); + transform: translateX(-165px); } .content { display: flex; diff --git a/frontend/css/global.scss b/frontend/css/global.scss index 711de12636..b3c9e5ddaa 100644 --- a/frontend/css/global.scss +++ b/frontend/css/global.scss @@ -759,7 +759,7 @@ a { .sensor-selection, .sensor-history-time-selection, .sensor-history-location-selection { - margin-bottom: 1rem; + margin-bottom: 1rem !important; } .row { margin-bottom: 0 !important; @@ -775,7 +775,9 @@ a { .add-sensor-reading-menu { width: 300px; .green { - margin-bottom: 1rem; + position: absolute; + bottom: 1rem; + right: 1rem; } .reading-location, .add-reading-value-form { @@ -1782,7 +1784,7 @@ ul { width: 2rem; height: 2rem; text-align: center; - line-height: 1.7rem; + line-height: 1.3rem; margin-left: 5px; } .markdown { From db4787b80eda867b58aa660edd5e7ec66b1685e4 Mon Sep 17 00:00:00 2001 From: gabrielburnworth Date: Wed, 20 Dec 2023 12:40:31 -0800 Subject: [PATCH 3/4] catch additional broadcast workflow errors --- lib/tasks/broadcast.rake | 35 +++++++++++++++++++++++++++++++---- 1 file changed, 31 insertions(+), 4 deletions(-) diff --git a/lib/tasks/broadcast.rake b/lib/tasks/broadcast.rake index c2536cbea1..0c4676fb89 100644 --- a/lib/tasks/broadcast.rake +++ b/lib/tasks/broadcast.rake @@ -181,14 +181,32 @@ namespace :broadcast do href_label = simple_prompt("(optional) Enter href label") while true title = simple_prompt("Enter title") - if GlobalBulletin.find_by(title: title).nil? + if title.nil? + next + end + if GlobalBulletin.find_by(slug: title.parameterize).nil? break else puts "Title already exists. Try another." end end - content = multiline_prompt("Enter content") - device_id = simple_prompt("Enter device ID") + while true + content = multiline_prompt("Enter content") + if content.nil? || content.strip.length == 0 + puts "Content cannot be blank." + else + break + end + end + while true + device_id = simple_prompt("Enter device ID") + device = Device.find_by(id: device_id.to_i) + if device.nil? + puts "Device not found." + else + break + end + end BroadcastToOne.run!(type: type, href: href, href_label: href_label, @@ -199,6 +217,15 @@ namespace :broadcast do desc "Broadcast existing bulletin to all users" task existing_to_all: :environment do - BroadcastExistingToAll.run!(slug: simple_prompt("Bulletin slug")) + while true + slug = simple_prompt("Bulletin slug") + bulletin = GlobalBulletin.find_by(slug: slug) + if bulletin.nil? + puts "Bulletin not found." + else + break + end + end + BroadcastExistingToAll.run!(slug: slug) end end From 837a1cc7413bacf6ff7c9343f0503b16b7cc1794 Mon Sep 17 00:00:00 2001 From: gabrielburnworth Date: Thu, 21 Dec 2023 11:17:44 -0800 Subject: [PATCH 4/4] fix new saved garden bug --- frontend/farm_designer/__tests__/index_test.tsx | 2 +- frontend/farm_designer/__tests__/reducer_test.ts | 6 +++--- .../farm_designer/__tests__/state_to_props_test.ts | 4 ++-- frontend/farm_designer/interfaces.ts | 4 ++-- .../layers/plants/__tests__/plant_actions_test.ts | 2 +- .../map/layers/plants/plant_actions.ts | 11 ++++------- frontend/farm_designer/reducer.ts | 2 +- frontend/farm_designer/state_to_props.ts | 8 ++++---- .../plants/__tests__/map_state_to_props_test.ts | 2 +- frontend/plants/__tests__/plant_info_test.tsx | 2 +- frontend/plants/__tests__/plant_inventory_test.tsx | 2 +- frontend/plants/__tests__/select_plants_test.tsx | 4 ++-- frontend/plants/crop_info.tsx | 2 +- frontend/plants/plant_info.tsx | 4 ++-- frontend/plants/plant_inventory.tsx | 2 +- frontend/plants/select_plants.tsx | 6 +++--- frontend/saved_gardens/__tests__/actions_test.ts | 10 +++++----- .../saved_gardens/__tests__/garden_add_test.tsx | 4 ++-- .../saved_gardens/__tests__/garden_edit_test.tsx | 4 ++-- .../saved_gardens/__tests__/garden_list_test.tsx | 2 +- .../saved_gardens/__tests__/saved_gardens_test.tsx | 2 +- frontend/saved_gardens/actions.ts | 14 ++++++-------- frontend/saved_gardens/garden_add.tsx | 4 ++-- frontend/saved_gardens/garden_edit.tsx | 8 ++++---- frontend/saved_gardens/garden_list.tsx | 4 ++-- frontend/saved_gardens/interfaces.tsx | 4 ++-- 26 files changed, 57 insertions(+), 62 deletions(-) diff --git a/frontend/farm_designer/__tests__/index_test.tsx b/frontend/farm_designer/__tests__/index_test.tsx index 19e743bd65..26acd1746b 100644 --- a/frontend/farm_designer/__tests__/index_test.tsx +++ b/frontend/farm_designer/__tests__/index_test.tsx @@ -126,7 +126,7 @@ describe("", () => { it("renders saved garden indicator", () => { const p = fakeProps(); - p.designer.openedSavedGarden = "SavedGardenUuid"; + p.designer.openedSavedGarden = 1; const wrapper = mount(); expect(wrapper.text().toLowerCase()).toContain("viewing saved garden"); }); diff --git a/frontend/farm_designer/__tests__/reducer_test.ts b/frontend/farm_designer/__tests__/reducer_test.ts index f95dbc4b8b..71ac71edd4 100644 --- a/frontend/farm_designer/__tests__/reducer_test.ts +++ b/frontend/farm_designer/__tests__/reducer_test.ts @@ -256,10 +256,10 @@ describe("designer reducer", () => { }); it("sets opened saved garden", () => { - const payload = "savedGardenUuid"; - const action: ReduxAction = { + const payload = 1; + const action: ReduxAction = { type: Actions.CHOOSE_SAVED_GARDEN, - payload + payload, }; const newState = designer(oldState(), action); expect(newState.openedSavedGarden).toEqual(payload); diff --git a/frontend/farm_designer/__tests__/state_to_props_test.ts b/frontend/farm_designer/__tests__/state_to_props_test.ts index 2be33fa70f..ee1d4bf7dd 100644 --- a/frontend/farm_designer/__tests__/state_to_props_test.ts +++ b/frontend/farm_designer/__tests__/state_to_props_test.ts @@ -167,8 +167,8 @@ describe("getPlants()", () => { it("returns plant templates", () => { const resources = fakeResources(); - const savedGardenUuid = Object.keys(resources.index.byKind["SavedGarden"])[0]; - resources.consumers.farm_designer.openedSavedGarden = savedGardenUuid; + const savedGardenId = 1; + resources.consumers.farm_designer.openedSavedGarden = savedGardenId; expect(getPlants(resources).length).toEqual(1); }); diff --git a/frontend/farm_designer/interfaces.ts b/frontend/farm_designer/interfaces.ts index 119de9742c..bbf966016a 100644 --- a/frontend/farm_designer/interfaces.ts +++ b/frontend/farm_designer/interfaces.ts @@ -165,7 +165,7 @@ export interface DesignerState { chosenLocation: BotPosition; drawnPoint: DrawnPointPayl | undefined; drawnWeed: DrawnWeedPayl | undefined; - openedSavedGarden: string | undefined; + openedSavedGarden: number | undefined; tryGroupSortType: ExtendedPointGroupSortType | undefined; editGroupAreaInMap: boolean; visualizedSequence: UUID | undefined; @@ -311,7 +311,7 @@ export type PlantOptions = Partial; export interface EditPlantInfoProps { dispatch: Function; findPlant(stringyID: string | undefined): TaggedPlant | undefined; - openedSavedGarden: string | undefined; + openedSavedGarden: number | undefined; timeSettings: TimeSettings; getConfigValue: GetWebAppConfigValue; soilHeightPoints: TaggedGenericPointer[]; diff --git a/frontend/farm_designer/map/layers/plants/__tests__/plant_actions_test.ts b/frontend/farm_designer/map/layers/plants/__tests__/plant_actions_test.ts index 1851ab2ad5..ef84ef6444 100644 --- a/frontend/farm_designer/map/layers/plants/__tests__/plant_actions_test.ts +++ b/frontend/farm_designer/map/layers/plants/__tests__/plant_actions_test.ts @@ -54,7 +54,7 @@ describe("newPlantKindAndBody()", () => { y: 0, slug: "mint", cropName: "Mint", - openedSavedGarden: "SavedGarden.1.1", + openedSavedGarden: 1, depth: 0, designer: fakeDesignerState(), }; diff --git a/frontend/farm_designer/map/layers/plants/plant_actions.ts b/frontend/farm_designer/map/layers/plants/plant_actions.ts index d3ff4979b0..184616c6e3 100644 --- a/frontend/farm_designer/map/layers/plants/plant_actions.ts +++ b/frontend/farm_designer/map/layers/plants/plant_actions.ts @@ -4,8 +4,7 @@ import { AxisNumberProperty, TaggedPlant, MapTransformProps, } from "../../interfaces"; import { Plant, DEFAULT_PLANT_RADIUS } from "../../../plant"; -import { unpackUUID } from "../../../../util"; -import { isNumber, isString } from "lodash"; +import { isNumber } from "lodash"; import { DesignerState, GardenMapState, MovePointsProps, } from "../../../interfaces"; @@ -25,7 +24,7 @@ export interface NewPlantKindAndBodyProps { y: number; slug: string; cropName: string; - openedSavedGarden: string | undefined; + openedSavedGarden: number | undefined; depth: number; designer: DesignerState; } @@ -35,9 +34,7 @@ export const newPlantKindAndBody = (props: NewPlantKindAndBodyProps): { kind: TaggedPlant["kind"], body: TaggedPlant["body"], } => { - const savedGardenId = isString(props.openedSavedGarden) - ? unpackUUID(props.openedSavedGarden).remoteId - : undefined; + const savedGardenId = props.openedSavedGarden || undefined; return isNumber(savedGardenId) ? { kind: "PlantTemplate", @@ -75,7 +72,7 @@ export interface CreatePlantProps { gardenCoords: AxisNumberProperty; gridSize: AxisNumberProperty | undefined; dispatch: Function; - openedSavedGarden: string | undefined; + openedSavedGarden: number | undefined; depth: number; designer: DesignerState; } diff --git a/frontend/farm_designer/reducer.ts b/frontend/farm_designer/reducer.ts index e4a1b088b7..a71d8648d8 100644 --- a/frontend/farm_designer/reducer.ts +++ b/frontend/farm_designer/reducer.ts @@ -188,7 +188,7 @@ export const designer = generateReducer(initialState) push(Path.location({ x: payload.x, y: payload.y })); return s; }) - .add(Actions.CHOOSE_SAVED_GARDEN, (s, { payload }) => { + .add(Actions.CHOOSE_SAVED_GARDEN, (s, { payload }) => { s.openedSavedGarden = payload; return s; }) diff --git a/frontend/farm_designer/state_to_props.ts b/frontend/farm_designer/state_to_props.ts index da327ae913..3c2b6cc8e6 100644 --- a/frontend/farm_designer/state_to_props.ts +++ b/frontend/farm_designer/state_to_props.ts @@ -22,13 +22,13 @@ import { selectAllFarmwareEnvs, selectAllCurves, } from "../resources/selectors"; -import { validFwConfig, unpackUUID, validFbosConfig } from "../util"; +import { validFwConfig, validFbosConfig } from "../util"; import { validBotLocationData } from "../util/location"; import { getWebAppConfigValue } from "../config_storage/actions"; import { FarmDesignerProps, CameraCalibrationData } from "./interfaces"; import { TaggedPlant, BotSize } from "./map/interfaces"; import { RestResources } from "../resources/interfaces"; -import { isString, uniq, chain } from "lodash"; +import { isFinite, uniq, chain } from "lodash"; import { BooleanSetting } from "../session_keys"; import { getEnv } from "../farmware/state_to_props"; import { getFirmwareConfig, getFbosConfig } from "../resources/getters"; @@ -50,9 +50,9 @@ export const getPlants = (resources: RestResources) => { const onlyPlants = selectAllPlantPointers(resources.index); const plantTemplates = selectAllPlantTemplates(resources.index); const { openedSavedGarden } = resources.consumers.farm_designer; - return isString(openedSavedGarden) + return isFinite(openedSavedGarden) ? plantTemplates.filter(x => - x.body.saved_garden_id === unpackUUID(openedSavedGarden).remoteId) + x.body.saved_garden_id === openedSavedGarden) : onlyPlants; }; diff --git a/frontend/plants/__tests__/map_state_to_props_test.ts b/frontend/plants/__tests__/map_state_to_props_test.ts index 62ef2bd72f..bef6a75df8 100644 --- a/frontend/plants/__tests__/map_state_to_props_test.ts +++ b/frontend/plants/__tests__/map_state_to_props_test.ts @@ -29,7 +29,7 @@ describe("mapStateToProps()", () => { template.body.id = 10; state.resources = buildResourceIndex([template]); const uuid = Object.keys(state.resources.index.all)[0]; - state.resources.consumers.farm_designer.openedSavedGarden = "uuid"; + state.resources.consumers.farm_designer.openedSavedGarden = 1; const result = mapStateToProps(state); expect(result.findPlant("10")).toEqual( expect.objectContaining({ uuid })); diff --git a/frontend/plants/__tests__/plant_info_test.tsx b/frontend/plants/__tests__/plant_info_test.tsx index 5073da687a..c0f1f760e0 100644 --- a/frontend/plants/__tests__/plant_info_test.tsx +++ b/frontend/plants/__tests__/plant_info_test.tsx @@ -98,7 +98,7 @@ describe("", () => { it("gets template id", () => { mockPath = Path.mock(Path.plantTemplates(2)); const p = fakeProps(); - p.openedSavedGarden = "uuid"; + p.openedSavedGarden = 1; const wrapper = mount(); expect(wrapper.instance().stringyID).toEqual("2"); }); diff --git a/frontend/plants/__tests__/plant_inventory_test.tsx b/frontend/plants/__tests__/plant_inventory_test.tsx index aa8f072b6d..0e19613ee1 100644 --- a/frontend/plants/__tests__/plant_inventory_test.tsx +++ b/frontend/plants/__tests__/plant_inventory_test.tsx @@ -158,7 +158,7 @@ describe("", () => { window.confirm = () => true; const p = fakeProps(); p.plantsPanelState.plants = true; - p.openedSavedGarden = "fake"; + p.openedSavedGarden = 1; const wrapper = mount(); const plantsSection = wrapper.find(PanelSection).at(2); expect(plantsSection.text().toLowerCase()).not.toContain("delete all"); diff --git a/frontend/plants/__tests__/select_plants_test.tsx b/frontend/plants/__tests__/select_plants_test.tsx index 39bdf2b46c..cf9c5ec957 100644 --- a/frontend/plants/__tests__/select_plants_test.tsx +++ b/frontend/plants/__tests__/select_plants_test.tsx @@ -63,7 +63,7 @@ describe("", () => { getConfigValue: () => true, plants: [plant1, plant2], dispatch: jest.fn(x => x), - gardenOpen: undefined, + gardenOpenId: undefined, allPoints: [], toolTransformProps: fakeToolTransformProps(), isActive: () => false, @@ -377,7 +377,7 @@ describe("", () => { it("doesn't create group", () => { const p = fakeProps(); - p.gardenOpen = "uuid"; + p.gardenOpenId = 1; const wrapper = mount(); wrapper.find(".dark-blue").simulate("click"); expect(createGroup).not.toHaveBeenCalled(); diff --git a/frontend/plants/crop_info.tsx b/frontend/plants/crop_info.tsx index 510dc3b3a1..af975467f4 100644 --- a/frontend/plants/crop_info.tsx +++ b/frontend/plants/crop_info.tsx @@ -204,7 +204,7 @@ const Companions = (props: CropInfoListProps) => { interface AddPlantHereButtonProps { botPosition: BotPosition; - openedSavedGarden: string | undefined; + openedSavedGarden: number | undefined; cropName: string; slug: string; dispatch: Function; diff --git a/frontend/plants/plant_info.tsx b/frontend/plants/plant_info.tsx index ee74842b41..2372f5670c 100644 --- a/frontend/plants/plant_info.tsx +++ b/frontend/plants/plant_info.tsx @@ -9,7 +9,7 @@ import { } from "../farm_designer/designer_panel"; import { t } from "../i18next_wrapper"; import { EditPlantInfoProps, PlantOptions } from "../farm_designer/interfaces"; -import { isString } from "lodash"; +import { isFinite } from "lodash"; import { push } from "../history"; import { destroy, edit, save } from "../api/crud"; import { BooleanSetting } from "../session_keys"; @@ -20,7 +20,7 @@ import { validGoButtonAxes } from "../farm_designer/move_to"; export type UpdatePlant = (uuid: string, update: PlantOptions) => void; export class RawPlantInfo extends React.Component { - get templates() { return isString(this.props.openedSavedGarden); } + get templates() { return isFinite(this.props.openedSavedGarden); } get stringyID() { return Path.getSlug((this.templates ? Path.plantTemplates diff --git a/frontend/plants/plant_inventory.tsx b/frontend/plants/plant_inventory.tsx index 1058ddb378..7315fac020 100644 --- a/frontend/plants/plant_inventory.tsx +++ b/frontend/plants/plant_inventory.tsx @@ -48,7 +48,7 @@ export interface PlantInventoryProps { allPoints: TaggedPoint[]; plantTemplates: TaggedPlantTemplate[]; plantPointerCount: number; - openedSavedGarden: string | undefined; + openedSavedGarden: number | undefined; plantsPanelState: PlantsPanelState; getConfigValue: GetWebAppConfigValue; } diff --git a/frontend/plants/select_plants.tsx b/frontend/plants/select_plants.tsx index 8055cbd236..8553d6e98e 100644 --- a/frontend/plants/select_plants.tsx +++ b/frontend/plants/select_plants.tsx @@ -116,7 +116,7 @@ export const mapStateToProps = (props: Everything): SelectPlantsProps => { plants: getPlants(props.resources), allPoints: selectAllActivePoints(props.resources.index), dispatch: props.dispatch, - gardenOpen: openedSavedGarden, + gardenOpenId: openedSavedGarden, tools: selectAllTools(props.resources.index), groups: selectAllPointGroups(props.resources.index), isActive: isActive(selectAllToolSlotPointers(props.resources.index)), @@ -135,7 +135,7 @@ export interface SelectPlantsProps { selected: UUID[] | undefined; selectionPointType: PointType[] | undefined; getConfigValue: GetWebAppConfigValue; - gardenOpen: string | undefined; + gardenOpenId: number | undefined; toolTransformProps: ToolTransformProps; isActive(id: number | undefined): boolean; tools: TaggedTool[]; @@ -288,7 +288,7 @@ export class RawSelectPlants