From 8130a0c5fe61eb85d76b3ba8a314e1acb09fb9eb Mon Sep 17 00:00:00 2001 From: gabrielburnworth Date: Tue, 10 Oct 2023 15:09:44 -0700 Subject: [PATCH 1/9] refactor io --- app/models/farmware_installation.rb | 4 ++- spec/controllers/api/ai/ai_controller_spec.rb | 10 ++++--- spec/models/farmware_installation_spec.rb | 26 ++++++++----------- 3 files changed, 20 insertions(+), 20 deletions(-) diff --git a/app/models/farmware_installation.rb b/app/models/farmware_installation.rb index 8f59d7e183..27cb899e1e 100644 --- a/app/models/farmware_installation.rb +++ b/app/models/farmware_installation.rb @@ -1,3 +1,5 @@ +require "open-uri" + # A record of installation of a Farmware. # Useful for restoring a device after a re-flash. class FarmwareInstallation < ApplicationRecord @@ -41,7 +43,7 @@ def maybe_recover_from_fetch_error(error) # SLOW I/O BOUND STUFF! Don't run this on the # main thread! def infer_package_name_from_url - string_io = open(url) + string_io = URI.parse(url).open string = string_io.read(MAX_JSON_SIZE) json = JSON.parse(string) pkg_name = json.fetch("package") diff --git a/spec/controllers/api/ai/ai_controller_spec.rb b/spec/controllers/api/ai/ai_controller_spec.rb index c8c324c023..1a95ec6c62 100644 --- a/spec/controllers/api/ai/ai_controller_spec.rb +++ b/spec/controllers/api/ai/ai_controller_spec.rb @@ -11,6 +11,8 @@ def chunk(content, done=nil) "\"content\":\"#{content}\"},\"index\":0,\"finish_reason\":#{done.to_json}}]}" end + URL_PATTERN = /raw\.githubusercontent\.com/ + it "makes a successful request for code" do sign_in user FactoryBot.create(:peripheral, device: user.device) @@ -22,7 +24,7 @@ def chunk(content, done=nil) sequence_id: nil, } - stub_request(:get, /raw.githubusercontent.com/).to_return( + stub_request(:get, URL_PATTERN).to_return( body: "---\n---# section\ncontent```lua\n```") stub_request(:post, "https://api.openai.com/v1/chat/completions").to_return( @@ -58,7 +60,7 @@ def chunk(content, done=nil) context_key: "lua", sequence_id: nil, } - stub_request(:get, /raw.githubusercontent.com/).to_return( + stub_request(:get, URL_PATTERN).to_return( body: "---\n---# section\ncontent```lua\n```") stub_request(:post, "https://api.openai.com/v1/chat/completions").to_timeout @@ -75,7 +77,7 @@ def chunk(content, done=nil) sequence_id: nil, } - stub_request(:get, /raw.githubusercontent.com/).to_raise(SocketError) + stub_request(:get, URL_PATTERN).to_raise(SocketError) stub_request(:post, "https://api.openai.com/v1/chat/completions").to_timeout @@ -91,7 +93,7 @@ def chunk(content, done=nil) sequence_id: nil, } - stub_request(:get, /raw.githubusercontent.com/).to_return( + stub_request(:get, URL_PATTERN).to_return( body: "---\n---# nothing for now\n") stub_request(:post, "https://api.openai.com/v1/chat/completions").to_return( diff --git a/spec/models/farmware_installation_spec.rb b/spec/models/farmware_installation_spec.rb index 8e394417ea..7091661db2 100644 --- a/spec/models/farmware_installation_spec.rb +++ b/spec/models/farmware_installation_spec.rb @@ -9,9 +9,9 @@ class Mystery < StandardError; end it "handles unknown errors while parsing farmware manifest" do - error = Mystery.new("wow!") - fi = FarmwareInstallation.create(device: device, url: FAKE_URL) - expect(fi).to receive(:open).and_raise(error) + error = Mystery.new("wow!") + fi = FarmwareInstallation.create(device: device, url: FAKE_URL) + stub_request(:get, FAKE_URL).to_raise(error) expect { fi.infer_package_name_from_url }.to raise_error(error) expect(fi.package_error) .to eq(FarmwareInstallation::OTHER_PROBLEM % Mystery.to_s) @@ -19,9 +19,8 @@ class Mystery < StandardError; end end it "handles unreasonably large package names" do - fi = FarmwareInstallation.create(device: device, url: FAKE_URL) - stringio = StringIO.new({ package: "*" * 100 }.to_json) - expect(fi).to receive(:open).and_return(stringio) + fi = FarmwareInstallation.create(device: device, url: FAKE_URL) + stub_request(:get, FAKE_URL).to_return(body: { package: "*" * 100 }.to_json) fi.infer_package_name_from_url error = FarmwareInstallation::KNOWN_PROBLEMS.fetch(ActiveRecord::ValueTooLong) @@ -31,12 +30,11 @@ class Mystery < StandardError; end it "handles unreasonably large payloads" do old_value = FarmwareInstallation::MAX_JSON_SIZE - fi = FarmwareInstallation.create(device: device, url: FAKE_URL) - stringio = StringIO.new({hello: "world"}.to_json) + fi = FarmwareInstallation.create(device: device, url: FAKE_URL) const_reassign(FarmwareInstallation, :MAX_JSON_SIZE, 2) - expect(fi).to receive(:open).and_return(stringio) + stub_request(:get, FAKE_URL).to_return(body: {hello: "world"}.to_json) fi.infer_package_name_from_url error = FarmwareInstallation::KNOWN_PROBLEMS.fetch(JSON::ParserError) expect(fi.package_error).to eq(error) @@ -46,8 +44,7 @@ class Mystery < StandardError; end it "sets the package name" do fi = FarmwareInstallation.create(device: device, url: FAKE_URL) - fake_json = StringIO.new({package: "FOO"}.to_json) - expect(fi).to receive(:open).and_return(fake_json) + stub_request(:get, FAKE_URL).to_return(body: {package: "FOO"}.to_json) fi.infer_package_name_from_url expect(fi.package_error).to eq(nil) expect(fi.package).to eq("FOO") @@ -55,7 +52,7 @@ class Mystery < StandardError; end it "handles non-JSON strings" do fi = FarmwareInstallation.create(device: device, url: FAKE_URL) - expect(fi).to receive(:open).and_return(StringIO.new("{lol")) + stub_request(:get, FAKE_URL).to_return(body:"{lol") fi.infer_package_name_from_url error = FarmwareInstallation::KNOWN_PROBLEMS.fetch(JSON::ParserError) expect(fi.package_error).to eq(error) @@ -63,9 +60,8 @@ class Mystery < StandardError; end end it "handles `package` fetch errors" do - fi = FarmwareInstallation.create!(device: device, - url: "http://lycos.com") - expect(fi).to receive(:open).and_raise(SocketError.new("No!")) + fi = FarmwareInstallation.create!(device: device, url: FAKE_URL) + stub_request(:get, FAKE_URL).to_raise(SocketError.new("No!")) fi.infer_package_name_from_url error = FarmwareInstallation::KNOWN_PROBLEMS.fetch(SocketError) expect(fi.package_error).to eq(error) From 5e93cb7ca06cafab2a9d9482101b0a5bb7a87ba7 Mon Sep 17 00:00:00 2001 From: gabrielburnworth Date: Fri, 13 Oct 2023 12:23:52 -0700 Subject: [PATCH 2/9] upgrade rollbar --- app/views/dashboard/_addons.html.erb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/dashboard/_addons.html.erb b/app/views/dashboard/_addons.html.erb index 938c18818f..86ff319c2f 100644 --- a/app/views/dashboard/_addons.html.erb +++ b/app/views/dashboard/_addons.html.erb @@ -50,7 +50,7 @@ try { }; // Rollbar Snippet -!function(r){var e={};function o(n){if(e[n])return e[n].exports;var t=e[n]={i:n,l:!1,exports:{}};return r[n].call(t.exports,t,t.exports,o),t.l=!0,t.exports}o.m=r,o.c=e,o.d=function(r,e,n){o.o(r,e)||Object.defineProperty(r,e,{enumerable:!0,get:n})},o.r=function(r){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(r,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(r,"__esModule",{value:!0})},o.t=function(r,e){if(1&e&&(r=o(r)),8&e)return r;if(4&e&&"object"==typeof r&&r&&r.__esModule)return r;var n=Object.create(null);if(o.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:r}),2&e&&"string"!=typeof r)for(var t in r)o.d(n,t,function(e){return r[e]}.bind(null,t));return n},o.n=function(r){var e=r&&r.__esModule?function(){return r.default}:function(){return r};return o.d(e,"a",e),e},o.o=function(r,e){return Object.prototype.hasOwnProperty.call(r,e)},o.p="",o(o.s=0)}([function(r,e,o){"use strict";var n=o(1),t=o(5);_rollbarConfig=_rollbarConfig||{},_rollbarConfig.rollbarJsUrl=_rollbarConfig.rollbarJsUrl||"https://cdn.rollbar.com/rollbarjs/refs/tags/v2.25.0/rollbar.min.js",_rollbarConfig.async=void 0===_rollbarConfig.async||_rollbarConfig.async;var a=n.setupShim(window,_rollbarConfig),l=t(_rollbarConfig);window.rollbar=n.Rollbar,a.loadFull(window,document,!_rollbarConfig.async,_rollbarConfig,l)},function(r,e,o){"use strict";var n=o(2),t=o(3);function a(r){return function(){try{return r.apply(this,arguments)}catch(r){try{console.error("[Rollbar]: Internal error",r)}catch(r){}}}}var l=0;function i(r,e){this.options=r,this._rollbarOldOnError=null;var o=l++;this.shimId=function(){return o},"undefined"!=typeof window&&window._rollbarShims&&(window._rollbarShims[o]={handler:e,messages:[]})}var s=o(4),d=function(r,e){return new i(r,e)},c=function(r){return new s(d,r)};function u(r){return a((function(){var e=this,o=Array.prototype.slice.call(arguments,0),n={shim:e,method:r,args:o,ts:new Date};window._rollbarShims[this.shimId()].messages.push(n)}))}i.prototype.loadFull=function(r,e,o,n,t){var l=!1,i=e.createElement("script"),s=e.getElementsByTagName("script")[0],d=s.parentNode;i.crossOrigin="",i.src=n.rollbarJsUrl,o||(i.async=!0),i.onload=i.onreadystatechange=a((function(){if(!(l||this.readyState&&"loaded"!==this.readyState&&"complete"!==this.readyState)){i.onload=i.onreadystatechange=null;try{d.removeChild(i)}catch(r){}l=!0,function(){var e;if(void 0===r._rollbarDidLoad){e=new Error("rollbar.js did not load");for(var o,n,a,l,i=0;o=r._rollbarShims[i++];)for(o=o.messages||[];n=o.shift();)for(a=n.args||[],i=0;i From 932c7131e86c3375c939faf7edecda57264c5c35 Mon Sep 17 00:00:00 2001 From: gabrielburnworth Date: Wed, 18 Oct 2023 13:38:03 -0700 Subject: [PATCH 3/9] update add plant UI --- app/views/dashboard/_common_assets.html.erb | 3 +- app/views/dashboard/demo.html.erb | 2 +- app/views/layouts/dashboard.html.erb | 3 +- .../fake_crop_search_result.ts | 19 +- frontend/css/farm_designer/farm_designer.scss | 20 +- .../farm_designer/farm_designer_panels.scss | 203 +++++++++++++++--- frontend/css/fonts.scss | 9 +- frontend/css/static_pages.scss | 2 +- frontend/curves/chart.tsx | 95 ++++---- .../__tests__/search_selectors_test.ts | 6 +- frontend/farm_designer/__tests__/util_test.ts | 6 +- frontend/farm_designer/interfaces.ts | 3 +- .../map/__tests__/garden_map_test.tsx | 9 + .../__tests__/add_plant_icon_test.tsx | 49 +++++ .../map/active_plant/add_plant_icon.tsx | 34 +++ .../farm_designer/map/active_plant/index.ts | 1 + frontend/farm_designer/map/garden_map.tsx | 12 ++ frontend/farm_designer/search_selectors.ts | 5 +- frontend/farm_designer/util.ts | 8 +- frontend/open_farm/openfarm.ts | 2 +- frontend/photos/images/image_flipper.tsx | 2 +- frontend/photos/images/interfaces.ts | 1 + frontend/photos/images/photos.tsx | 1 + frontend/plants/__tests__/crop_info_test.tsx | 66 ++++-- .../openfarm_search_results_test.tsx | 8 +- frontend/plants/crop_info.tsx | 157 ++++++++++---- .../plants/grid/__tests__/grid_input_test.tsx | 2 +- frontend/plants/grid/grid_input.tsx | 81 ++++--- frontend/plants/grid/interfaces.ts | 8 - frontend/plants/grid/plant_grid.tsx | 5 +- frontend/plants/openfarm_search_results.tsx | 10 +- frontend/points/create_points.tsx | 3 +- public/404.html | 4 +- public/500.html | 4 +- public/app-resources/languages/_helper.js | 6 +- public/app-resources/languages/_helper.ts | 2 +- .../languages/translation_metrics.md | 24 +-- 37 files changed, 612 insertions(+), 263 deletions(-) create mode 100644 frontend/farm_designer/map/active_plant/__tests__/add_plant_icon_test.tsx create mode 100644 frontend/farm_designer/map/active_plant/add_plant_icon.tsx diff --git a/app/views/dashboard/_common_assets.html.erb b/app/views/dashboard/_common_assets.html.erb index a990e54bea..13181975ab 100644 --- a/app/views/dashboard/_common_assets.html.erb +++ b/app/views/dashboard/_common_assets.html.erb @@ -18,4 +18,5 @@ window.process = { <%= render "addons" %> <%= javascript_include_tag *@js_assets %> - + + diff --git a/app/views/dashboard/demo.html.erb b/app/views/dashboard/demo.html.erb index 5e74f65d4e..8fd0d45c3d 100644 --- a/app/views/dashboard/demo.html.erb +++ b/app/views/dashboard/demo.html.erb @@ -38,7 +38,7 @@ bottom: 30px; box-shadow: 0 0 15px rgba(0,0,0,0.4); color: #fff; - font-family: "Roboto", sans-serif; + font-family: "Cabin", sans-serif; font-size: 25px; font-weight: bold; padding: 15px 30px; diff --git a/app/views/layouts/dashboard.html.erb b/app/views/layouts/dashboard.html.erb index f4d30a7088..17c69ca3ce 100644 --- a/app/views/layouts/dashboard.html.erb +++ b/app/views/layouts/dashboard.html.erb @@ -24,7 +24,8 @@ text-align: center; width: 100%; padding-top: 10%; color: #434343; } <%= stylesheet_link_tag *@css_assets %> - + +