Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Admin] Introduce role creation #5826

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
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
@@ -1,6 +1,6 @@
# frozen_string_literal: true

class SolidusAdmin::Users::Index::Component < SolidusAdmin::UI::Pages::Index::Component
class SolidusAdmin::Users::Index::Component < SolidusAdmin::UsersAndRoles::Component
def model_class
Spree.user_class
end
Expand Down
24 changes: 24 additions & 0 deletions admin/app/components/solidus_admin/users_and_roles/component.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# frozen_string_literal: true

class SolidusAdmin::UsersAndRoles::Component < SolidusAdmin::UI::Pages::Index::Component
def title
page_header_title safe_join([
tag.div(t(".title")),
])
end

def tabs
[
{
text: Spree.user_class.model_name.human(count: 2),
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
en:
title: "Users and Roles"
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.joins(:role_users).distinct }

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, only: [:index, :destroy]
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
1 change: 1 addition & 0 deletions admin/spec/features/users_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
create(:user, :with_orders, email: "customer-with-order@example.com")

visit "/admin/users"
expect(page).to have_content("Users and Roles")
expect(page).to have_content("customer@example.com")
expect(page).not_to have_content("admin-2@example.com")
click_on "Admins"
Expand Down
Loading