Skip to content

Commit

Permalink
Add Role component to the new admin
Browse files Browse the repository at this point in the history
This includes the index, the new/create logic, and the singular or bulk
deletion logic as well as the associated components and specs.
  • Loading branch information
MadelineCollier committed Aug 19, 2024
1 parent eb6f734 commit 1fbe6d5
Show file tree
Hide file tree
Showing 11 changed files with 361 additions and 0 deletions.
65 changes: 65 additions & 0 deletions admin/app/components/solidus_admin/roles/index/component.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# frozen_string_literal: true

class SolidusAdmin::Roles::Index::Component < SolidusAdmin::UsersAndRoles::Component
def model_class
Spree::Role
end

def search_key
:name_cont
end

def search_url
solidus_admin.roles_path
end

def row_url(role)
solidus_admin.roles_path(role)
end

def page_actions
render component("ui/button").new(
tag: :a,
text: t('.add'),
href: solidus_admin.new_role_path, data: { turbo_frame: :new_role_modal },
icon: "add-line",
)
end

def turbo_frames
%w[
new_role_modal
]
end

def batch_actions
[
{
label: t('.batch_actions.delete'),
action: solidus_admin.roles_path,
method: :delete,
icon: 'delete-bin-7-line',
},
]
end

def scopes
[
{ name: :all, label: t('.scopes.all'), default: true },
{ name: :admin, label: t('.scopes.admin') },
]
end

def filters
[]
end

def columns
[
{
header: :role,
data: :name,
}
]
end
end
6 changes: 6 additions & 0 deletions admin/app/components/solidus_admin/roles/index/component.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
en:
batch_actions:
delete: 'Delete'
scopes:
admin: Admin
all: All
17 changes: 17 additions & 0 deletions admin/app/components/solidus_admin/roles/new/component.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<%= turbo_frame_tag :new_role_modal do %>
<%= render component("ui/modal").new(title: t(".title")) do |modal| %>
<%= form_for @role, url: solidus_admin.roles_path, html: { id: form_id } do |f| %>
<div class="flex flex-col gap-6 pb-4">
<%= render component("ui/forms/field").text_field(f, :name, class: "required") %>
</div>
<% modal.with_actions do %>
<form method="dialog">
<%= render component("ui/button").new(scheme: :secondary, text: t('.cancel')) %>
</form>
<%= render component("ui/button").new(form: form_id, type: :submit, text: t('.submit')) %>
<% end %>
<% end %>
<% end %>
<% end %>

<%= render component("roles/index").new(page: @page) %>
12 changes: 12 additions & 0 deletions admin/app/components/solidus_admin/roles/new/component.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# frozen_string_literal: true

class SolidusAdmin::Roles::New::Component < SolidusAdmin::BaseComponent
def initialize(page:, role:)
@page = page
@role = role
end

def form_id
dom_id(@role, "#{stimulus_id}_new_role_form")
end
end
6 changes: 6 additions & 0 deletions admin/app/components/solidus_admin/roles/new/component.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Add your component translations here.
# Use the translation in the example in your template with `t(".hello")`.
en:
title: "New Role"
cancel: "Cancel"
submit: "Add Role"
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@ def tabs
href: solidus_admin.users_path,
current: model_class == Spree.user_class,
},
{
text: Spree::Role.model_name.human(count: 2),
href: solidus_admin.roles_path,
current: model_class == Spree::Role,
},
]
end
end
79 changes: 79 additions & 0 deletions admin/app/controllers/solidus_admin/roles_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
# frozen_string_literal: true

module SolidusAdmin
class RolesController < SolidusAdmin::BaseController
include SolidusAdmin::ControllerHelpers::Search

search_scope(:all)
search_scope(:admin) { _1.where(name: "admin") }

def index
set_index_page

respond_to do |format|
format.html { render component('roles/index').new(page: @page) }
end
end

def new
@role = Spree::Role.new

set_index_page

respond_to do |format|
format.html { render component('roles/new').new(page: @page, role: @role) }
end
end

def create
@role = Spree::Role.new(role_params)

if @role.save
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: '<turbo-stream action="refresh" />'
end
end
else
set_index_page

respond_to do |format|
format.html do
page_component = component('roles/new').new(page: @page, role: @role)
render page_component, status: :unprocessable_entity
end
end
end
end

def destroy
@roles = Spree::Role.where(id: params[:id])

Spree::Role.transaction { @roles.destroy_all }

flash[:notice] = t('.success')
redirect_back_or_to solidus_admin.roles_path, status: :see_other
end

private

def set_index_page
roles = apply_search_to(
Spree::Role.unscoped.order(id: :desc),
param: :q,
)

set_page_and_extract_portion_from(roles)
end

def role_params
params.require(:role).permit(:role_id, :name, :description, :type)
end
end
end
8 changes: 8 additions & 0 deletions admin/config/locales/roles.en.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
en:
solidus_admin:
roles:
title: "Roles"
destroy:
success: "Roles were successfully removed."
create:
success: "Role was successfully created."
1 change: 1 addition & 0 deletions admin/config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +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 :adjustment_reasons, except: [:show]
admin_resources :store_credit_reasons, except: [:show]
end
77 changes: 77 additions & 0 deletions admin/spec/features/roles_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
# frozen_string_literal: true

require 'spec_helper'

describe "Roles", :js, type: :feature do
before { sign_in create(:admin_user, email: 'admin@example.com') }

it "lists roles and allows deleting them" do
create(:role, name: "Customer Role" )
Spree::Role.find_or_create_by(name: 'admin')

visit "/admin/roles"
expect(page).to have_content("Users and Roles")
expect(page).to have_content("Customer Role")
expect(page).to have_content("admin")
click_on "Admin"
expect(page).to have_content("admin")
expect(page).not_to have_content("Customer Role")
click_on "All"
expect(page).to have_content("Customer Role")
expect(page).to have_content("admin")

expect(page).to be_axe_clean

select_row("Customer Role")
click_on "Delete"
expect(page).to have_content("Roles were successfully removed.")
expect(page).not_to have_content("Customer Role")
expect(Spree::Role.count).to eq(1)
end

context "when creating a role" do
let(:query) { "?page=1&q%5Bname_cont%5D=new" }

before do
visit "/admin/roles#{query}"
click_on "Add new"
expect(page).to have_content("New 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

context "with valid data" do
it "successfully creates a new role, keeping page and q params" do
fill_in "Name", with: "Purchaser"

click_on "Add Role"

expect(page).to have_content("Role was successfully created.")
expect(Spree::Role.find_by(name: "Purchaser")).to be_present
expect(page.current_url).to include(query)
end
end

context "with invalid data" do
# @note: The only validation that Roles currently have is that names must
# be unique (but they can still be blank).
before do
create(:role, name: "Customer Role" )
end

it "fails to create a new role, keeping page and q params" do
fill_in "Name", with: "Customer Role"
click_on "Add Role"

expect(page).to have_content("has already been taken")
expect(page.current_url).to include(query)
end
end
end
end
85 changes: 85 additions & 0 deletions admin/spec/requests/solidus_admin/roles_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
# frozen_string_literal: true

require "spec_helper"

RSpec.describe "SolidusAdmin::RolesController", type: :request do
let(:admin_user) { create(:admin_user) }
let(:role) { create(:role) }

before do
allow_any_instance_of(SolidusAdmin::BaseController).to receive(:spree_current_user).and_return(admin_user)
Spree::Role.find_or_create_by(name: 'admin')
end

describe "GET /index" do
it "renders the index template with a 200 OK status" do
get solidus_admin.roles_path
expect(response).to have_http_status(:ok)
end
end

describe "GET /new" do
it "renders the new template with a 200 OK status" do
get solidus_admin.new_role_path
expect(response).to have_http_status(:ok)
end
end

describe "POST /create" do
context "with valid parameters" do
let(:valid_attributes) { { name: "Customer" } }

it "creates a new Role" do
expect {
post solidus_admin.roles_path, params: { role: valid_attributes }
}.to change(Spree::Role, :count).by(1)
end

it "redirects to the index page with a 303 See Other status" do
post solidus_admin.roles_path, 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
post solidus_admin.roles_path, params: { role: valid_attributes }
follow_redirect!
expect(response.body).to include("Role was successfully created.")
end
end

context "with invalid parameters" do
let(:invalid_attributes) { { name: "admin" } }

it "does not create a new Role" do
expect {
post solidus_admin.roles_path, params: { role: invalid_attributes }
}.not_to change(Spree::Role, :count)
end

it "renders the new template with unprocessable_entity status" do
post solidus_admin.roles_path, 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) }

it "deletes the role and redirects to the index page with a 303 See Other status" do
expect {
delete solidus_admin.role_path(role_to_delete)
}.to change(Spree::Role, :count).by(-1)

expect(response).to redirect_to(solidus_admin.roles_path)
expect(response).to have_http_status(:see_other)
end

it "displays a success flash message after deletion" do
delete solidus_admin.role_path(role_to_delete)
follow_redirect!
expect(response.body).to include("Roles were successfully removed.")
end
end
end

0 comments on commit 1fbe6d5

Please sign in to comment.