diff --git a/admin/app/components/solidus_admin/roles/edit/component.html.erb b/admin/app/components/solidus_admin/roles/edit/component.html.erb new file mode 100644 index 0000000000..541df92c40 --- /dev/null +++ b/admin/app/components/solidus_admin/roles/edit/component.html.erb @@ -0,0 +1,16 @@ +<%= turbo_frame_tag :edit_role_modal do %> + <%= render component("ui/modal").new(title: t(".title")) do |modal| %> + <%= form_for @role, url: solidus_admin.role_path(@role), html: { id: form_id } do |f| %> +
+ <%= render component("ui/forms/field").text_field(f, :name, class: "required") %> +
+ <% modal.with_actions do %> +
+ <%= render component("ui/button").new(scheme: :secondary, text: t('.cancel')) %> +
+ <%= render component("ui/button").new(form: form_id, type: :submit, text: t('.submit')) %> + <% end %> + <% end %> + <% end %> +<% end %> +<%= render component("roles/index").new(page: @page) %> diff --git a/admin/app/components/solidus_admin/roles/edit/component.rb b/admin/app/components/solidus_admin/roles/edit/component.rb new file mode 100644 index 0000000000..3d2e06dc2f --- /dev/null +++ b/admin/app/components/solidus_admin/roles/edit/component.rb @@ -0,0 +1,12 @@ +# frozen_string_literal: true + +class SolidusAdmin::Roles::Edit::Component < SolidusAdmin::BaseComponent + def initialize(page:, role:) + @page = page + @role = role + end + + def form_id + dom_id(@role, "#{stimulus_id}_edit_role_form") + end +end diff --git a/admin/app/components/solidus_admin/roles/edit/component.yml b/admin/app/components/solidus_admin/roles/edit/component.yml new file mode 100644 index 0000000000..22945513da --- /dev/null +++ b/admin/app/components/solidus_admin/roles/edit/component.yml @@ -0,0 +1,6 @@ +# Add your component translations here. +# Use the translation in the example in your template with `t(".hello")`. +en: + title: "Edit Role" + cancel: "Cancel" + submit: "Update Role" diff --git a/admin/app/components/solidus_admin/roles/index/component.rb b/admin/app/components/solidus_admin/roles/index/component.rb index 6d2063e0fc..63ac5c1592 100644 --- a/admin/app/components/solidus_admin/roles/index/component.rb +++ b/admin/app/components/solidus_admin/roles/index/component.rb @@ -14,7 +14,7 @@ def search_url end def row_url(role) - solidus_admin.roles_path(role) + solidus_admin.edit_role_path(role, _turbo_frame: :edit_role_modal) end def page_actions @@ -29,6 +29,7 @@ def page_actions def turbo_frames %w[ new_role_modal + edit_role_modal ] end diff --git a/admin/app/controllers/solidus_admin/roles_controller.rb b/admin/app/controllers/solidus_admin/roles_controller.rb index f01cf30cb2..1d601ce7c6 100644 --- a/admin/app/controllers/solidus_admin/roles_controller.rb +++ b/admin/app/controllers/solidus_admin/roles_controller.rb @@ -4,6 +4,8 @@ module SolidusAdmin class RolesController < SolidusAdmin::BaseController include SolidusAdmin::ControllerHelpers::Search + before_action :find_role, only: %i[edit update] + search_scope(:all) search_scope(:admin) { _1.where(name: "admin") } @@ -52,6 +54,39 @@ def create end end + def edit + set_index_page + + respond_to do |format| + format.html { render component('roles/edit').new(page: @page, role: @role) } + end + end + + def update + if @role.update(role_params) + respond_to do |format| + flash[:notice] = t('.success') + + format.html do + redirect_to solidus_admin.roles_path, status: :see_other + end + + format.turbo_stream do + render turbo_stream: '' + end + end + else + set_index_page + + respond_to do |format| + format.html do + page_component = component('roles/edit').new(page: @page, role: @role) + render page_component, status: :unprocessable_entity + end + end + end + end + def destroy @roles = Spree::Role.where(id: params[:id]) @@ -63,6 +98,10 @@ def destroy private + def find_role + @role = Spree::Role.find(params[:id]) + end + def set_index_page roles = apply_search_to( Spree::Role.unscoped.order(id: :desc), diff --git a/admin/config/locales/roles.en.yml b/admin/config/locales/roles.en.yml index 3017e99ac9..abf6936513 100644 --- a/admin/config/locales/roles.en.yml +++ b/admin/config/locales/roles.en.yml @@ -6,3 +6,5 @@ en: success: "Roles were successfully removed." create: success: "Role was successfully created." + update: + success: "Role was successfully updated." diff --git a/admin/config/routes.rb b/admin/config/routes.rb index e2c6e716a0..61f5a72979 100644 --- a/admin/config/routes.rb +++ b/admin/config/routes.rb @@ -63,7 +63,7 @@ admin_resources :refund_reasons, except: [:show] admin_resources :reimbursement_types, only: [:index] admin_resources :return_reasons, except: [:show] - admin_resources :roles, only: [:index, :new, :create, :destroy] + admin_resources :roles, except: [:show] admin_resources :adjustment_reasons, except: [:show] admin_resources :store_credit_reasons, except: [:show] end diff --git a/admin/spec/features/roles_spec.rb b/admin/spec/features/roles_spec.rb index a05e4f88c4..2b08dab450 100644 --- a/admin/spec/features/roles_spec.rb +++ b/admin/spec/features/roles_spec.rb @@ -74,4 +74,34 @@ end end end + + context "when editing an existing role" do + let(:query) { "?page=1&q%5Bname_cont%5D=er" } + + before do + Spree::Role.create(name: "Reviewer") + visit "/admin/roles#{query}" + find_row("Reviewer").click + expect(page).to have_content("Edit Role") + expect(page).to be_axe_clean + end + + it "opens a modal" do + expect(page).to have_selector("dialog") + within("dialog") { click_on "Cancel" } + expect(page).not_to have_selector("dialog") + expect(page.current_url).to include(query) + end + + it "successfully updates the existing role" do + fill_in "Name", with: "Publisher" + + click_on "Update Role" + expect(page).to have_content("Role was successfully updated.") + expect(page).to have_content("Publisher") + expect(page).not_to have_content("Reviewer") + expect(Spree::Role.find_by(name: "Publisher")).to be_present + expect(page.current_url).to include(query) + end + end end diff --git a/admin/spec/requests/solidus_admin/roles_spec.rb b/admin/spec/requests/solidus_admin/roles_spec.rb index fea41daabf..95e57c6cb6 100644 --- a/admin/spec/requests/solidus_admin/roles_spec.rb +++ b/admin/spec/requests/solidus_admin/roles_spec.rb @@ -64,6 +64,53 @@ end end + describe "GET /edit" do + it "renders the edit template with a 200 OK status" do + get solidus_admin.edit_role_path(role) + expect(response).to have_http_status(:ok) + end + end + + describe "PATCH /update" do + context "with valid parameters" do + let(:valid_attributes) { { name: "Publisher" } } + + it "updates the role" do + patch solidus_admin.role_path(role), params: { role: valid_attributes } + role.reload + expect(role.name).to eq("Publisher") + end + + it "redirects to the index page with a 303 See Other status" do + patch solidus_admin.role_path(role), params: { role: valid_attributes } + expect(response).to redirect_to(solidus_admin.roles_path) + expect(response).to have_http_status(:see_other) + end + + it "displays a success flash message" do + patch solidus_admin.role_path(role), params: { role: valid_attributes } + follow_redirect! + expect(response.body).to include("Role was successfully updated.") + end + end + + context "with invalid parameters" do + let(:invalid_attributes) { { name: "admin" } } + + it "does not update the role" do + original_name = role.name + patch solidus_admin.role_path(role), params: { role: invalid_attributes } + role.reload + expect(role.name).to eq(original_name) + end + + it "renders the edit template with unprocessable_entity status" do + patch solidus_admin.role_path(role), params: { role: invalid_attributes } + expect(response).to have_http_status(:unprocessable_entity) + end + end + end + describe "DELETE /destroy" do let!(:role_to_delete) { create(:role) }