Skip to content

Commit

Permalink
feature: add action icon (#2628)
Browse files Browse the repository at this point in the history
* Add action icon

* Refactoring icon method

* Refactoring icon method

* Add icon option to action in resources

* Refactor render_entity method

* Add divider action functionality

* Fix indentation
quit

* Refactor action CSS class to conditionally include border-bottom

* Rename method render_entity to render_item

* Refactor action_css_class

* Set default play icon when no icon is providerd

* Refactor action_component and base_controller

* Change icon parameter type from string to symbol

* Add tests for icon and divider

* tweaks

---------

Co-authored-by: Paul Bob <paul.ionut.bob@gmail.com>
  • Loading branch information
gabrielgiroe1 and Paul-Bob authored Apr 3, 2024
1 parent 2887838 commit 44d4bb6
Show file tree
Hide file tree
Showing 9 changed files with 83 additions and 23 deletions.
17 changes: 2 additions & 15 deletions app/components/avo/actions_component.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -31,21 +31,8 @@
data-transition-leave-end="transform opacity-0 -translate-y-1"
>
<div data-target="actions-list" class="w-full space divide-y">
<% actions.each_with_index do |action, index| %>
<%= link_to action_path(action),
data: {
action_name: action.action_name,
'turbo-frame': Avo::ACTIONS_TURBO_FRAME_ID,
'action': 'click->actions-picker#visitAction',
'actions-picker-target': action.standalone ? 'standaloneAction' : 'resourceAction',
'disabled': is_disabled?(action),
# for some reason InstantClick fetches the URL even if it's prefetched.
turbo_prefetch: false,
},
title: action.action_name,
class: "flex items-center px-4 py-3 w-full font-semibold text-sm hover:bg-primary-100 #{is_disabled?(action) ? 'text-gray-500' : 'text-black'}" do %>
<%= svg 'play', class: 'h-5 mr-1 inline pointer-events-none' %> <%= action.action_name %>
<% end %>
<% actions.each do |action| %>
<%= render_item(action)%>
<% end %>
</div>
</div>
Expand Down
38 changes: 38 additions & 0 deletions app/components/avo/actions_component.rb
Original file line number Diff line number Diff line change
Expand Up @@ -79,4 +79,42 @@ def action_url(action, path)
}.compact
).to_s
end

def icon(action)
svg action.icon, class: "h-5 mr-1 inline pointer-events-none"
end

def render_item(action)
if action.is_a?(Avo::DividerComponent)
render Avo::DividerComponent.new
else
render_action_link(action)
end
end

private

def render_action_link(action)
link_to action_path(action),
data: action_data_attributes(action),
title: action.action_name,
class: action_css_class(action) do
raw("#{icon(action)} #{action.action_name}")
end
end

def action_data_attributes(action)
{
action_name: action.action_name,
"turbo-frame": Avo::ACTIONS_TURBO_FRAME_ID,
action: "click->actions-picker#visitAction",
"actions-picker-target": action.standalone ? "standaloneAction" : "resourceAction",
disabled: is_disabled?(action),
turbo_prefetch: false,
}
end

def action_css_class(action)
"flex items-center px-4 py-3 w-full font-semibold text-sm hover:bg-primary-100 border-b#{is_disabled?(action) ? " text-gray-500" : " text-black"}"
end
end
3 changes: 3 additions & 0 deletions app/components/avo/divider_component.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<div class="relative col-span-full border-t border-gray-300 border-solid" style= "border-width: 1.75px;">
<div class="absolute inset-auto -translate-y-1/2 -translate-x-1/2 ml-1/2 z-20 text-xs font-semibold uppercase leading-none text-gray-500 bg-application px-2"></div>
</div>
6 changes: 6 additions & 0 deletions app/components/avo/divider_component.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# frozen_string_literal: true

class Avo::DividerComponent < ViewComponent::Base
def initialize(**args)
end
end
6 changes: 3 additions & 3 deletions app/controllers/avo/base_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -357,11 +357,11 @@ def set_filters
def set_actions
@actions = @resource
.get_actions
.map do |action|
action[:class].new(record: @record, resource: @resource, view: @view, arguments: action[:arguments])
.map do |action_bag|
action_bag.delete(:class).new(record: @record, resource: @resource, view: @view, **action_bag)
end
.select do |action|
action.visible_in_view(parent_resource: @parent_resource)
action.is_a?(DividerComponent) || action.visible_in_view(parent_resource: @parent_resource)
end
end

Expand Down
4 changes: 3 additions & 1 deletion lib/avo/base_action.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ class BaseAction
attr_accessor :resource
attr_accessor :user
attr_reader :arguments
attr_reader :icon

# TODO: find a differnet way to delegate this to the uninitialized Current variable
delegate :context, to: Avo::Current
Expand Down Expand Up @@ -101,11 +102,12 @@ def action_name
self.class.to_s.demodulize.underscore.humanize(keep_id_suffix: true)
end

def initialize(record: nil, resource: nil, user: nil, view: nil, arguments: {})
def initialize(record: nil, resource: nil, user: nil, view: nil, arguments: {}, icon: :play)
@record = record
@resource = resource
@user = user
@view = Avo::ViewInquirer.new(view)
@icon = icon
@arguments = Avo::ExecutionContext.new(
target: arguments,
resource: resource,
Expand Down
8 changes: 6 additions & 2 deletions lib/avo/base_resource.rb
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,10 @@ def fetch_cards
cards
end

def divider
action DividerComponent
end

# def fields / def cards
[:fields, :cards].each do |method_name|
define_method method_name do
Expand All @@ -310,8 +314,8 @@ def fetch_cards
end

# def action / def filter / def scope
define_method entity do |entity_class, arguments: {}|
entity_loader(entity).use({class: entity_class, arguments: arguments})
define_method entity do |entity_class, arguments: {}, icon: nil|
entity_loader(entity).use({class: entity_class, arguments: arguments, icon: icon}.compact)
end

# def get_actions / def get_filters / def get_scopes
Expand Down
6 changes: 4 additions & 2 deletions spec/dummy/app/avo/resources/user.rb
Original file line number Diff line number Diff line change
Expand Up @@ -65,10 +65,12 @@ def fields
end

def actions
action Avo::Actions::ToggleInactive
action Avo::Actions::ToggleInactive, icon: "heroicons/outline/globe"
action Avo::Actions::ToggleAdmin
divider
action Avo::Actions::Sub::DummyAction
action Avo::Actions::DownloadFile
action Avo::Actions::DownloadFile, icon: "heroicons/outline/arrow-left"
divider
action Avo::Actions::Test::NoConfirmationRedirect
action Avo::Actions::Test::CloseModal
end
Expand Down
18 changes: 18 additions & 0 deletions spec/features/action_icon_and_divider_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
require "rails_helper"

RSpec.describe "action icon and divider", type: :feature do
describe "icon and divider" do
let(:user) { create(:user) }

it "Viewing actions with icon and divider" do
visit "admin/resources/users"

expect(page).to have_css("button[data-action='click->toggle#togglePanel']")

expect(page).to have_css("path[stroke-linecap='round'][stroke-linejoin='round'][d*='M3.055 11']")
expect(page).to have_css("path[stroke-linecap='round'][stroke-linejoin='round'][d*='M10.5 19.5']")

expect(page).to have_css(".relative.col-span-full.border-t.border-gray-300.border-solid")
end
end
end

0 comments on commit 44d4bb6

Please sign in to comment.