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

SP-63 Feature/improve admin actions extensibility #276

Merged
merged 74 commits into from
Nov 1, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
74 commits
Select commit Hold shift + click to select a range
578dfa2
Lay groundwork for:
tomdonarski Oct 2, 2023
409b198
Add root object to wrap actions into
tomdonarski Oct 2, 2023
488b0e2
Lay groundwork for action items
tomdonarski Oct 2, 2023
a7b9b9a
Use more descriptive module name
tomdonarski Oct 5, 2023
b7386ee
Add builder for admin actions
tomdonarski Oct 5, 2023
2a62731
Add module for availability checking
tomdonarski Oct 5, 2023
883559f
Build orders default actions on boot
tomdonarski Oct 5, 2023
be55d8b
Orders#index - use prebuilt action object
tomdonarski Oct 5, 2023
5603d68
Add remark on a missing feature
tomdonarski Oct 5, 2023
e8001d3
Order#edit - use prebuilt action for resend
tomdonarski Oct 5, 2023
73d1cd8
Order#edit - use prebuild action for reset links
tomdonarski Oct 5, 2023
c16cf79
Fix availability check in Orders#index
tomdonarski Oct 5, 2023
3fb7203
Users#index - use prebuilt action object
tomdonarski Oct 6, 2023
c9865eb
User#edit - use prebuilt action for create order
tomdonarski Oct 6, 2023
afe92bd
Products#index - use prebuilt for create product
tomdonarski Oct 6, 2023
bced606
Add missing id attribute
tomdonarski Oct 6, 2023
2e718a5
Add translation options
tomdonarski Oct 6, 2023
f990329
Refactor action_builder, so that it takes
tomdonarski Oct 9, 2023
1def24b
Product#edit - use prebuilt action object
tomdonarski Oct 9, 2023
b29b96a
Order#edit - add approve, cancel, resume actions
tomdonarski Oct 9, 2023
b6bdaef
Rubocop fixes
tomdonarski Oct 9, 2023
c982655
Add missing attributes
tomdonarski Oct 9, 2023
e253ba8
Add missing attribute
tomdonarski Oct 10, 2023
19b092a
Remove superfluous attributes
tomdonarski Oct 10, 2023
169af65
Add missing attribute
tomdonarski Oct 10, 2023
1cec2aa
Add back mistakenly deleted attributes
tomdonarski Oct 10, 2023
aeb2770
Change attribute in config
tomdonarski Oct 10, 2023
254ed46
Fix taking translation options into account
tomdonarski Oct 10, 2023
e2deee4
Allow multiple availability checks
tomdonarski Oct 10, 2023
5c296e6
Add missing checks
tomdonarski Oct 10, 2023
9c6b402
Add missing attribute
tomdonarski Oct 11, 2023
4b2e4e2
Fix missing translations
tomdonarski Oct 11, 2023
8586d7a
Remove method that's unused anymore
tomdonarski Oct 11, 2023
083b4b2
Improve readability
tomdonarski Oct 12, 2023
0f024c0
Cleanup unused code
tomdonarski Oct 12, 2023
2e7773d
Reorder code for better readability.
tomdonarski Oct 12, 2023
6674c8b
Fix tests
tomdonarski Oct 12, 2023
0215335
Add basic Action spec
tomdonarski Oct 12, 2023
8c58cc2
Supplement test
tomdonarski Oct 12, 2023
957c84d
Fix availability testing
tomdonarski Oct 13, 2023
ba4ba1f
Remove unused functions
tomdonarski Oct 13, 2023
a5617f0
Link action to a non-faulty path
tomdonarski Oct 13, 2023
47ce5e4
Remove incorrectly added option
tomdonarski Oct 18, 2023
5864d6f
Render preview button from partial, instead of
tomdonarski Oct 19, 2023
bf59fc6
Remove unused code
tomdonarski Oct 19, 2023
ac5cc89
Rescue error when there's no partial,
tomdonarski Oct 19, 2023
36da68d
Use prebuild action instead of partial
tomdonarski Oct 23, 2023
0cf5cd8
Improve formatting
tomdonarski Oct 23, 2023
6480e11
Add conditional for rendering product action
tomdonarski Oct 24, 2023
8317b5c
Rename an attribute
tomdonarski Oct 24, 2023
b61659a
Refactor Root class
tomdonarski Oct 24, 2023
a0313ef
Allow multiple availability checks
tomdonarski Oct 24, 2023
b73c177
Contain permission checks in one module
tomdonarski Oct 24, 2023
55bf12c
Correct method signatures.
tomdonarski Oct 24, 2023
fed67d0
Product#edit - add back prebuilt action object
tomdonarski Oct 25, 2023
780887b
Images#index - use prebuilt action
tomdonarski Oct 25, 2023
7b23267
Rename a class
tomdonarski Oct 25, 2023
f6f582b
Append items to config instead of overwriting
tomdonarski Oct 25, 2023
755e891
Prices#index - use prebuilt action
tomdonarski Oct 26, 2023
9bd79c7
Store_credits#index - use prebuilt action
tomdonarski Oct 26, 2023
6b624e2
Fix store_credits
tomdonarski Oct 26, 2023
521b212
Adjustments#index - use prebuilt action
tomdonarski Oct 26, 2023
96c6d8a
Rename a function
tomdonarski Oct 26, 2023
640d513
Rename function
tomdonarski Oct 26, 2023
73d7e4f
Payments#index - use prebuilt action
tomdonarski Oct 26, 2023
198e5e2
Remove superfluous argument
tomdonarski Oct 26, 2023
5bceed2
Product#stock - use prebuilt action
tomdonarski Oct 26, 2023
33f079f
Variants#index - use prebuilt action
tomdonarski Oct 26, 2023
569c00e
Product_properties#index - use prebuilt action
tomdonarski Oct 26, 2023
e2677e3
Lint fix
tomdonarski Oct 26, 2023
7c824e6
Rename variables in tests
tomdonarski Oct 27, 2023
00ce4d1
Fix spec setup
tomdonarski Oct 30, 2023
b8415cd
Fix spec setup
tomdonarski Oct 30, 2023
c1d8aeb
Remove spec that is no longer valid
rafalcymerys Nov 1, 2023
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
58 changes: 58 additions & 0 deletions app/helpers/spree/admin/navigation_helper.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
module Spree
module Admin
# rubocop:disable Metrics/ModuleLength
module NavigationHelper
# Makes an admin navigation tab (<li> tag) that links to a routing resource under /admin.
# The arguments should be a list of symbolized controller names that will cause this tab to
Expand Down Expand Up @@ -320,6 +321,63 @@ def user_tabs
def product_tabs
Rails.application.config.spree_backend.tabs[:product]
end

def orders_actions
Rails.application.config.spree_backend.actions[:orders]
end

def order_actions
Rails.application.config.spree_backend.actions[:order]
end

def users_actions
Rails.application.config.spree_backend.actions[:users]
end

def user_actions
Rails.application.config.spree_backend.actions[:user]
end

def products_actions
Rails.application.config.spree_backend.actions[:products]
end

def product_actions
Rails.application.config.spree_backend.actions[:product]
end

def images_actions
Rails.application.config.spree_backend.actions[:images]
end

def prices_actions
Rails.application.config.spree_backend.actions[:prices]
end

def store_credits_actions
Rails.application.config.spree_backend.actions[:store_credits]
end

def adjustments_actions
Rails.application.config.spree_backend.actions[:adjustments]
end

def payments_actions
Rails.application.config.spree_backend.actions[:payments]
end

def stock_actions
Rails.application.config.spree_backend.actions[:stock]
end

def variants_actions
Rails.application.config.spree_backend.actions[:variants]
end

def product_properties_actions
Rails.application.config.spree_backend.actions[:product_properties]
end
# rubocop:enable Metrics/ModuleLength
end
end
end
18 changes: 0 additions & 18 deletions app/helpers/spree/admin/orders_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,6 @@ module Spree
module Admin
module OrdersHelper
# Renders all the extension partials that may have been specified in the extensions
def event_links(order, events)
links = []
events.each do |event|
next unless order.send("can_#{event}?")

label = Spree.t(event, scope: 'admin.order.events', default: Spree.t(event))
links << button_link_to(
label.capitalize,
[event.to_sym, :admin, order],
method: :put,
icon: event.to_s + '.svg',
data: { confirm: Spree.t(:order_sure_want_to, event: label) },
class: 'btn-light'
)
end
safe_join(links, ''.html_safe)
end

def line_item_shipment_price(line_item, quantity)
Spree::Money.new(line_item.price * quantity, currency: line_item.currency)
end
Expand Down
35 changes: 35 additions & 0 deletions app/models/spree/admin/actions/action.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
module Spree
module Admin
module Actions
class Action
attr_reader :icon_name, :key, :classes, :text, :method, :id, :target, :data

def initialize(config)
@icon_name = config[:icon_name]
@key = config[:key]
@url = config[:url]
@classes = config[:classes]
@availability_checks = config[:availability_checks]
@text = config[:text]
@method = config[:method]
@id = config[:id]
@translation_options = config[:translation_options]
@target = config[:target]
@data = config[:data]
end

def available?(current_ability, resource = nil)
return true if @availability_checks.empty?

result = @availability_checks.map { |check| check.call(current_ability, resource) }

result.all?(true)
end

def url(resource = nil)
@url.is_a?(Proc) ? @url.call(resource) : @url
end
end
end
end
end
48 changes: 48 additions & 0 deletions app/models/spree/admin/actions/action_builder.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
module Spree
module Admin
module Actions
class ActionBuilder
include ::Spree::Admin::PermissionChecks

def initialize(config)
@icon_name = config[:icon_name]
@key = config[:key]
@url = config[:url]
@classes = config[:classes]
@availability_checks = []
@method = config[:method]
@id = config[:id]
@translation_options = config[:translation_options]
@target = config[:target]
@data = config[:data]
end

def build
Action.new(build_config)
end

private

def build_config
{
icon_name: @icon_name,
key: @key,
url: @url,
classes: @classes,
availability_checks: @availability_checks,
text: text(@key, @translation_options),
method: @method,
id: @id,
translation_options: @translation_options,
target: @target,
data: @data
}
end

def text(text, options)
options.present? ? ::Spree.t(text, options) : ::Spree.t(text)
end
end
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
module Spree
module Admin
module Actions
class AdjustmentsDefaultActionsBuilder
include Spree::Core::Engine.routes.url_helpers

def build
root = Root.new
add_new_adjustment_action(root)
root
end

private

def add_new_adjustment_action(root)
action =
ActionBuilder.new(new_adjustment_config).
with_create_ability_check(::Spree::Adjustment).
build

root.add(action)
end

def new_adjustment_config
{
icon_name: 'add.svg',
key: :new_adjustment,
url: ->(resource) { new_admin_order_adjustment_path(resource) },
classes: 'btn-success'
}
end
end
end
end
end
36 changes: 36 additions & 0 deletions app/models/spree/admin/actions/images_default_actions_builder.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
module Spree
module Admin
module Actions
class ImagesDefaultActionsBuilder
include Spree::Core::Engine.routes.url_helpers

def build
root = Root.new
add_new_image_action(root)
root
end

private

def add_new_image_action(root)
action =
ActionBuilder.new(new_image_config).
with_create_ability_check(::Spree::Image).
build

root.add(action)
end

def new_image_config
{
icon_name: 'add.svg',
key: :new_image,
url: ->(resource) { new_admin_product_image_path(resource) },
classes: 'btn-success',
id: 'new_image_link'
}
end
end
end
end
end
138 changes: 138 additions & 0 deletions app/models/spree/admin/actions/order_default_actions_builder.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
module Spree
module Admin
module Actions
class OrderDefaultActionsBuilder
include Spree::Core::Engine.routes.url_helpers

def build
root = Root.new
add_approve_action(root)
add_cancel_action(root)
add_resume_action(root)
add_resend_action(root)
add_reset_download_links_action(root)
root
end

private

def add_approve_action(root)
action =
ActionBuilder.new(approve_config).
with_state_change_check('approve').
with_fire_ability_check.
build

root.add(action)
end

def approve_config
{
icon_name: 'approve.svg',
key: :approve,
url: ->(resource) { approve_admin_order_path(resource) },
classes: 'btn-light',
method: :put,
translation_options: {
scope: 'admin.order.events'
},
data: { confirm: Spree.t(:order_sure_want_to, event: :approve) }
}
end

def add_cancel_action(root)
action =
ActionBuilder.new(cancel_config).
with_state_change_check('cancel').
with_fire_ability_check.
build

root.add(action)
end

def cancel_config
{
icon_name: 'cancel.svg',
key: :cancel,
url: ->(resource) { cancel_admin_order_path(resource) },
classes: 'btn-light',
method: :put,
translation_options: {
scope: 'admin.order.events'
},
data: { confirm: Spree.t(:order_sure_want_to, event: :cancel) }
}
end

def add_resume_action(root)
action =
ActionBuilder.new(resume_config).
with_state_change_check('resume').
with_fire_ability_check.
build

root.add(action)
end

def resume_config
{
icon_name: 'resume.svg',
key: :resume,
url: ->(resource) { resume_admin_order_path(resource) },
classes: 'btn-light',
method: :put,
translation_options: {
scope: 'admin.order.events'
},
data: { confirm: Spree.t(:order_sure_want_to, event: :resume) }
}
end

def add_resend_action(root)
action =
ActionBuilder.new(resend_config).
with_resend_ability_check.
build

root.add(action)
end

def resend_config
{
icon_name: 'envelope.svg',
key: :resend,
url: ->(resource) { resend_admin_order_path(resource) },
classes: 'btn-secondary',
method: :post,
translation_options: {
scope: 'admin.order.events',
default: ::Spree.t(:resend)
}
}
end

def add_reset_download_links_action(root)
action =
ActionBuilder.new(reset_download_links_config).
with_availability_check(
lambda do |ability, resource|
ability.can?(:update, resource) && resource.some_digital?
end
).
build

root.add(action)
end

def reset_download_links_config
{
icon_name: 'hdd.svg',
key: 'admin.digitals.reset_download_links',
url: ->(resource) { reset_digitals_admin_order_path(resource) },
method: :put
}
end
end
end
end
end
Loading
Loading