diff --git a/.github/ISSUE_TEMPLATE/release.md b/.github/ISSUE_TEMPLATE/release.md index 4013964fc1..202b75c148 100644 --- a/.github/ISSUE_TEMPLATE/release.md +++ b/.github/ISSUE_TEMPLATE/release.md @@ -22,11 +22,13 @@ assignees: '' -- [ ] Create a tag: `git push upstream HEAD:refs/tags/vX.Y.Z` +- [ ] Create a tag: + - `script/tag_release` will auto increment patch version, otherwise + - `git push upstream HEAD:refs/tags/vX.Y.Z` - [ ] [Draft new release]. Look at previous [releases] for inspiration. - Select new release tag - _Generate release notes_ and check to ensure all items are arranged in the right category. -- [ ] Notify [#instance-managers] of both user-facing :eyes: and :warning: API changes. +- [ ] Notify [#instance-managers] of user-facing :eyes:, API :warning: and experimental :construction: changes. ## 2. Testing diff --git a/Gemfile.lock b/Gemfile.lock index 0656215cb4..4b0c57bec4 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -131,8 +131,8 @@ GEM i18n (>= 1.6, < 2) minitest (>= 5.1) tzinfo (~> 2.0) - acts-as-taggable-on (9.0.1) - activerecord (>= 6.0, < 7.1) + acts-as-taggable-on (10.0.0) + activerecord (>= 6.1, < 7.2) acts_as_list (1.0.4) activerecord (>= 4.2) addressable (2.8.5) @@ -180,7 +180,7 @@ GEM bugsnag (6.26.0) concurrent-ruby (~> 1.0) builder (3.2.4) - bullet (7.1.1) + bullet (7.1.2) activesupport (>= 3.0.0) uniform_notifier (~> 1.11) cable_ready (5.0.1) @@ -621,7 +621,7 @@ GEM rswag-ui (2.11.0) actionpack (>= 3.1, < 7.2) railties (>= 3.1, < 7.2) - rubocop (1.57.0) + rubocop (1.57.1) base64 (~> 0.1.1) json (~> 2.3) language_server-protocol (>= 3.17.0) diff --git a/app/jobs/report_job.rb b/app/jobs/report_job.rb index 73184ae574..9d1e081433 100644 --- a/app/jobs/report_job.rb +++ b/app/jobs/report_job.rb @@ -21,6 +21,14 @@ class ReportJob < ApplicationJob email_result(user, blob) if execution_time > NOTIFICATION_TIME broadcast_result(channel, format, blob) if channel + rescue StandardError => e + Bugsnag.notify(e) do |payload| + payload.add_metadata :report, { + report_class:, user:, params:, format: + } + end + + broadcast_error(channel) end def email_result(user, blob) @@ -37,6 +45,13 @@ class ReportJob < ApplicationJob ).broadcast end + def broadcast_error(channel) + cable_ready[channel].inner_html( + selector: "#report-table", + html: I18n.t("report_job.report_failed") + ).broadcast + end + def actioncable_content(format, blob) return blob.result if format.to_sym == :html diff --git a/app/reflexes/admin/orders_reflex.rb b/app/reflexes/admin/orders_reflex.rb index bafa51dd68..765438d7cc 100644 --- a/app/reflexes/admin/orders_reflex.rb +++ b/app/reflexes/admin/orders_reflex.rb @@ -11,9 +11,7 @@ module Admin morph dom_id(@order), render(partial: "spree/admin/orders/table_row", locals: { order: @order.reload, success: true }) else - flash[:error] = with_locale{ - payment_capture.gateway_error || I18n.t(:payment_processing_failed) - } + flash[:error] = payment_capture.gateway_error || I18n.t(:payment_processing_failed) morph_admin_flashes end end @@ -23,7 +21,7 @@ module Admin morph dom_id(@order), render(partial: "spree/admin/orders/table_row", locals: { order: @order.reload, success: true }) else - flash[:error] = with_locale{ I18n.t("api.orders.failed_to_update") } + flash[:error] = I18n.t("api.orders.failed_to_update") morph_admin_flashes end end @@ -90,7 +88,7 @@ module Admin end def success(i18n_key, count) - flash[:success] = with_locale { I18n.t(i18n_key, count:) } + flash[:success] = I18n.t(i18n_key, count:) cable_ready.dispatch_event(name: "modal:close") morph_admin_flashes end diff --git a/app/reflexes/application_reflex.rb b/app/reflexes/application_reflex.rb index 941a8c4f0c..42981e5361 100644 --- a/app/reflexes/application_reflex.rb +++ b/app/reflexes/application_reflex.rb @@ -5,31 +5,22 @@ class ApplicationReflex < StimulusReflex::Reflex # # Learn more at: https://docs.stimulusreflex.com/rtfm/reflex-classes # - # If your ActionCable connection is: `identified_by :current_user` - # delegate :current_user, to: :connection - # - # If you need to localize your Reflexes, you can set the I18n locale here: - # - # before_reflex do - # I18n.locale = :fr - # end - # # For code examples, considerations and caveats, see: # https://docs.stimulusreflex.com/rtfm/patterns#internationalization include CanCan::ControllerAdditions delegate :current_user, to: :connection + before_reflex do + I18n.locale = current_user.locale + end + private def current_ability Spree::Ability.new(current_user) end - def with_locale(&) - I18n.with_locale(current_user.locale, &) - end - def morph_admin_flashes morph "#flashes", render(partial: "admin/shared/flashes", locals: { flashes: flash }) end diff --git a/app/reflexes/invite_manager_reflex.rb b/app/reflexes/invite_manager_reflex.rb index 2d7463cf3a..51d7bc484b 100644 --- a/app/reflexes/invite_manager_reflex.rb +++ b/app/reflexes/invite_manager_reflex.rb @@ -35,8 +35,6 @@ class InviteManagerReflex < ApplicationReflex def return_morph(locals) morph "#add_manager_modal", - with_locale { - render(partial: "admin/enterprises/form/add_new_unregistered_manager", locals:) - } + render(partial: "admin/enterprises/form/add_new_unregistered_manager", locals:) end end diff --git a/app/reflexes/white_label_reflex.rb b/app/reflexes/white_label_reflex.rb index 44462c8449..ac7fa4983b 100644 --- a/app/reflexes/white_label_reflex.rb +++ b/app/reflexes/white_label_reflex.rb @@ -11,15 +11,11 @@ class WhiteLabelReflex < ApplicationReflex f = ActionView::Helpers::FormBuilder.new(:enterprise, @enterprise, view_context, {}) - html = with_locale { - render(partial: "admin/enterprises/form/white_label", + html = render(partial: "admin/enterprises/form/white_label", locals: { f:, enterprise: @enterprise }) - } morph "#white_label_panel", html - flash[:success] = with_locale { - I18n.t("admin.enterprises.form.white_label.remove_logo_success") - } + flash[:success] = I18n.t("admin.enterprises.form.white_label.remove_logo_success") cable_ready.dispatch_event(name: "modal:close") morph_admin_flashes end diff --git a/app/views/admin/products_v3/_table.html.haml b/app/views/admin/products_v3/_table.html.haml index 28d2a3ded3..7417f676cd 100644 --- a/app/views/admin/products_v3/_table.html.haml +++ b/app/views/admin/products_v3/_table.html.haml @@ -1,4 +1,4 @@ -= form_with url: bulk_update_admin_products_v3_index_path, method: :patch, id: "products-form", += form_with url: bulk_update_admin_products_path, method: :patch, id: "products-form", html: {'data-reflex-serialize-form': true, 'data-reflex': 'submit->products#bulk_update', 'data-controller': "bulk-form", 'data-bulk-form-disable-selector-value': "#sort,#filters"} do |form| %fieldset.form-actions.hidden{ 'data-bulk-form-target': "actions" } @@ -56,9 +56,9 @@ -# TODO: new requirement "DISPLAY ON DEMAND IF ALL VARIANTS ARE ON DEMAND". And translate value .content= if product.variants.all?(&:on_demand) then "On demand" else product.on_hand || 0 end %td.align-left - .content= product.supplier.name + .content= product.supplier&.name %td.align-left - .content= product.primary_taxon.name + .content= product.primary_taxon&.name %td.align-left %td.align-left .content= product.inherits_properties ? 'YES' : 'NO' #TODO: consider using https://github.com/RST-J/human_attribute_values, else use I18n.t (also below) @@ -82,7 +82,7 @@ %td.align-right .content= variant.on_hand || 0 #TODO: spec for this according to requirements. %td.align-left - .content= variant.product.supplier.name # same as product + .content= variant.product.supplier&.name # same as product %td.align-left -# empty %td.align-left diff --git a/app/views/spree/admin/shared/_product_sub_menu.html.haml b/app/views/spree/admin/shared/_product_sub_menu.html.haml index 771366f57a..b89b16c764 100644 --- a/app/views/spree/admin/shared/_product_sub_menu.html.haml +++ b/app/views/spree/admin/shared/_product_sub_menu.html.haml @@ -1,9 +1,6 @@ - content_for :sub_menu do %ul#sub_nav.inline-menu - - if feature?(:admin_style_v3, spree_current_user) - = tab :products_v3, url: main_app.admin_products_v3_index_path - - else - = tab :products + = tab :products = tab :properties = tab :variant_overrides, url: main_app.admin_inventory_path, match_path: '/inventory' = tab :import, url: main_app.admin_product_import_path, match_path: '/product_import' diff --git a/config/locales/en.yml b/config/locales/en.yml index b93a9b9563..2e9842a73f 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -335,6 +335,10 @@ en: not_array_error: "must be an array" invalid_element_error: "must contain only valid integers" + report_job: + report_failed: | + This report failed. It may be too big to process. + We will look into it but please let us know if the problem persists. enterprise_mailer: confirmation_instructions: subject: "Please confirm the email address for %{enterprise}" diff --git a/config/routes/admin.rb b/config/routes/admin.rb index 3d22d65201..b8fef0838c 100644 --- a/config/routes/admin.rb +++ b/config/routes/admin.rb @@ -68,7 +68,7 @@ Openfoodnetwork::Application.routes.draw do post '/product_import/reset_absent', to: 'product_import#reset_absent_products', as: 'product_import_reset_async' constraints FeatureToggleConstraint.new(:admin_style_v3) do - resources :products_v3, as: :products_v3, only: :index do + resources :products, to: 'products_v3#index', only: :index do patch :bulk_update, on: :collection end end diff --git a/config/routes/spree.rb b/config/routes/spree.rb index cdc8d7660e..2568731c9a 100644 --- a/config/routes/spree.rb +++ b/config/routes/spree.rb @@ -50,9 +50,15 @@ Spree::Core::Engine.routes.draw do resources :users - resources :products do - post :bulk_update, :on => :collection, :as => :bulk_update + constraints FeatureToggleConstraint.new(:admin_style_v3, negate: true) do + # Show old bulk products screen + resources :products, :index do + post :bulk_update, :on => :collection, :as => :bulk_update + end + end + + resources :products, except: :index do member do get :clone get :group_buy_options @@ -78,6 +84,9 @@ Spree::Core::Engine.routes.draw do end end + # duplicate old path for reference when admin_style_v3 enabled + resources :products_old, to: 'products#index', only: :index + get '/variants/search', :to => "variants#search", :as => :search_variants resources :properties diff --git a/script/tag_release b/script/tag_release index 1fc68ef539..718397ef27 100755 --- a/script/tag_release +++ b/script/tag_release @@ -19,3 +19,6 @@ major, minor, patch = latest_version.segments next_tag = "v#{major}.#{minor}.#{patch.succ}" puts `git push upstream 'HEAD:refs/tags/#{next_tag}'` + +puts "Draft a new release with this tag: + https://github.com/openfoodfoundation/openfoodnetwork/releases/new?tag=#{next_tag}&title=#{next_tag}+Code+Name" diff --git a/spec/jobs/report_job_spec.rb b/spec/jobs/report_job_spec.rb index b8326634b0..c99f5fc38a 100644 --- a/spec/jobs/report_job_spec.rb +++ b/spec/jobs/report_job_spec.rb @@ -64,6 +64,17 @@ describe ReportJob do }.to_not enqueue_mail end + it "rescues errors" do + expect(report_class).to receive(:new).and_raise + expect(Bugsnag).to receive(:notify) + + job = ReportJob.perform_later(**report_args) + + expect { + perform_enqueued_jobs(only: ReportJob) + }.to_not raise_error + end + def expect_csv_report blob.reload expect(blob.filename.to_s).to eq "report.csv" diff --git a/spec/reflexes/products_reflex_spec.rb b/spec/reflexes/products_reflex_spec.rb index ead1c57739..ae95f16b8c 100644 --- a/spec/reflexes/products_reflex_spec.rb +++ b/spec/reflexes/products_reflex_spec.rb @@ -5,7 +5,7 @@ require "reflex_helper" describe ProductsReflex, type: :reflex do let(:current_user) { create(:admin_user) } # todo: set up an enterprise user to test permissions let(:context) { - { url: admin_products_v3_index_url, connection: { current_user: } } + { url: admin_products_url, connection: { current_user: } } } before do diff --git a/spec/system/admin/products_v3/products_spec.rb b/spec/system/admin/products_v3/products_spec.rb index a706beeb41..c6ddc8e7f3 100644 --- a/spec/system/admin/products_v3/products_spec.rb +++ b/spec/system/admin/products_v3/products_spec.rb @@ -19,7 +19,7 @@ describe 'As an admin, I can see the new product page' do end it "can see the new product page" do - visit admin_products_v3_index_url + visit admin_products_url expect(page).to have_content "Bulk Edit Products" end @@ -28,7 +28,7 @@ describe 'As an admin, I can see the new product page' do let!(:product_a) { create(:simple_product, name: "Apples") } before do - visit admin_products_v3_index_url + visit admin_products_url end it "Should sort products alphabetically by default" do @@ -44,7 +44,7 @@ describe 'As an admin, I can see the new product page' do describe "pagination" do before do - visit admin_products_v3_index_url + visit admin_products_url end it "has a pagination, has 15 products per page by default and can change the page" do @@ -76,7 +76,7 @@ describe 'As an admin, I can see the new product page' do let!(:product_by_name) { create(:simple_product, name: "searchable product") } before do - visit admin_products_v3_index_url + visit admin_products_url end it "can search for a product" do @@ -128,7 +128,7 @@ describe 'As an admin, I can see the new product page' do let!(:product_by_supplier) { create(:simple_product, supplier: producer) } it "can search for a product" do - visit admin_products_v3_index_url + visit admin_products_url search_by_producer "Producer 1" @@ -145,7 +145,7 @@ describe 'As an admin, I can see the new product page' do } it "can search for a product" do - visit admin_products_v3_index_url + visit admin_products_url search_by_category "Category 1" @@ -168,7 +168,7 @@ describe 'As an admin, I can see the new product page' do let!(:product_a) { create(:simple_product, name: "Apples", sku: "APL-00") } before do - visit admin_products_v3_index_url + visit admin_products_url end it "shows an actions memu with an edit link when clicking on icon for product" do @@ -198,7 +198,7 @@ describe 'As an admin, I can see the new product page' do let!(:product_a) { create(:simple_product, name: "Apples", sku: "APL-00") } before do - visit admin_products_v3_index_url + visit admin_products_url end it "updates product and variant fields" do