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

feature: add action icon #2628

Merged
merged 16 commits into from
Apr 3, 2024
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
16 changes: 2 additions & 14 deletions app/components/avo/actions_component.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -32,20 +32,8 @@
>
<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 %>
<% next_action = actions[index + 1] %>
<%= render_item(action, next_action)%>
gabrielgiroe1 marked this conversation as resolved.
Show resolved Hide resolved
<% 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, next_action)
if action.is_a?(Avo::DividerComponent)
render Avo::DividerComponent.new
else
render_action_link(action, next_action)
end
end
gabrielgiroe1 marked this conversation as resolved.
Show resolved Hide resolved

private

def render_action_link(action, next_action)
link_to action_path(action),
data: action_data_attributes(action),
title: action.action_name,
class: action_css_class(action, next_action) do
raw("#{icon(action)} #{action.action_name}")
end
end
gabrielgiroe1 marked this conversation as resolved.
Show resolved Hide resolved

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, next_action)
gabrielgiroe1 marked this conversation as resolved.
Show resolved Hide resolved
"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
4 changes: 2 additions & 2 deletions app/controllers/avo/base_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -358,10 +358,10 @@ def set_actions
@actions = @resource
.get_actions
.map do |action|
action[:class].new(record: @record, resource: @resource, view: @view, arguments: action[:arguments])
action.is_a?(DividerComponent) ? [action] : action[:class].new(record: @record, resource: @resource, view: @view, arguments: action[:arguments], icon: action[:icon])
gabrielgiroe1 marked this conversation as resolved.
Show resolved Hide resolved
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")
gabrielgiroe1 marked this conversation as resolved.
Show resolved Hide resolved
@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: "play"|
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to specify a default here as well? Wouldn't the initializer default take precedence?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, we must specify a default value. I tried as below and it won't get a default icon value.👇

define_method entity do |entity_class, arguments: {}, icon: nil|

entity_loader(entity).use({class: entity_class, arguments: arguments, icon: icon})
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