-
-
Notifications
You must be signed in to change notification settings - Fork 314
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #2972 from kulturbande/resource-table-component
Resource Table Component
- Loading branch information
Showing
25 changed files
with
852 additions
and
434 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
# frozen_string_literal: true | ||
|
||
module Alchemy | ||
module Admin | ||
module Resource | ||
# Renders a container for a button, which evaluate CanCanCan and shows a tooltip. This | ||
# is an internal component for the resource table, to make easier to read. | ||
# | ||
# @param [String, Symbol, nil] :name | ||
# name of an action to evaluate if the user can perform these action on the given object | ||
# @param [String, nil] :tooltip | ||
# show a tooltip around the button | ||
# @param [Lambda] :block | ||
# a block to include a button or a link | ||
# | ||
class Action < ViewComponent::Base | ||
delegate :can?, to: :helpers | ||
|
||
attr_reader :block, :name, :tooltip | ||
|
||
erb_template <<~ERB | ||
<% if name.nil? || can?(name, @resource) %> | ||
<% if tooltip.present? %> | ||
<sl-tooltip content="<%= tooltip %>"> | ||
<%= view_context.capture(@resource, &block) %> | ||
</sl-tooltip> | ||
<% else %> | ||
<%= view_context.capture(@resource, &block) %> | ||
<% end %> | ||
<% end %> | ||
ERB | ||
|
||
def initialize(name = nil, tooltip = nil, &block) | ||
@name = name | ||
@tooltip = tooltip | ||
@block = block | ||
end | ||
|
||
def with_resource(resource) | ||
@resource = resource | ||
self | ||
end | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
# frozen_string_literal: true | ||
|
||
module Alchemy | ||
module Admin | ||
module Resource | ||
# Renders a table cell with the given css classes | ||
# | ||
# @param [String, nil] :css_classes | ||
# css classes that are show at the table cell | ||
# @param [Lambda] :block | ||
# a block to include a button or a link | ||
# | ||
class Cell < ViewComponent::Base | ||
attr_reader :block, :css_classes | ||
|
||
erb_template <<~ERB | ||
<td class="<%= css_classes %>"> | ||
<%= view_context.capture(@resource, &block) %> | ||
</td> | ||
ERB | ||
|
||
def initialize(css_classes, &block) | ||
@css_classes = css_classes | ||
@block = block | ||
end | ||
|
||
def with_resource(resource) | ||
@resource = resource | ||
self | ||
end | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
# frozen_string_literal: true | ||
|
||
module Alchemy | ||
module Admin | ||
module Resource | ||
# Renders a table header tag | ||
# the component is an internal component of the Table component | ||
# | ||
# @param [String] :name | ||
# name of the sortable link or the text if not additional text is given | ||
# @param [String] :query | ||
# Ransack query | ||
# @param [String] :css_classes ("") | ||
# css class of the th - tag | ||
# @param [String, nil] :text (nil) | ||
# optional text of the header | ||
# @param [Symbol] :type (:string) | ||
# type of the column will be used to inverse the sorting order for data/time - objects | ||
# @param [Boolean] :sortable (false) | ||
# enable a sortable link | ||
# | ||
class Header < ViewComponent::Base | ||
delegate :sort_link, to: :helpers | ||
|
||
erb_template <<~ERB | ||
<th class="<%= @css_classes %>"> | ||
<% if @sortable %> | ||
<%= sort_link @query, @name, @text, default_order: @default_order %> | ||
<% else %> | ||
<%= @text %> | ||
<% end %> | ||
</th> | ||
ERB | ||
|
||
def initialize(name, query, css_classes: "", text: nil, type: :string, sortable: false) | ||
@name = name | ||
@query = query | ||
@text = text || name | ||
@css_classes = css_classes | ||
@default_order = /date|time/.match?(type.to_s) ? "desc" : "asc" | ||
@sortable = sortable | ||
end | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,150 @@ | ||
# frozen_string_literal: true | ||
|
||
module Alchemy | ||
module Admin | ||
module Resource | ||
# Renders a resource table with columns and buttons | ||
# | ||
# == Example | ||
# | ||
# <%= render Alchemy::Admin::Resource::Table.new(@languages, query: @query) do |table| %> | ||
# <% table.icon_column "translate-2", style: false %> | ||
# <% table.column :name, sortable: true %> | ||
# <% table.column :language_code, sortable: true %> | ||
# <% table.column :page_layout do |language| %> | ||
# <%= Alchemy::Page.human_layout_name(language.page_layout) %> | ||
# <% end %> | ||
# <% table.delete_button %> | ||
# <% table.edit_button %> | ||
# <% end %> | ||
# | ||
# @param [ActiveRecord::Relation] :collection | ||
# a collection of Alchemy::Resource objects that are shown in the table | ||
# @param [Ransack::Search] :query | ||
# The ransack search object to allow sortable table columns | ||
# @param [String] :nothing_found_label (Alchemy.t("Nothing found")) | ||
# The message that will be shown, if the collection is empty | ||
# @param [Hash] :search_filter_params ({}) | ||
# An additional hash that will attached to the delete and edit button to redirect back to | ||
# the same page of the table | ||
# @param [String] :icon (nil) | ||
# a default icon, if the table is auto generated | ||
class Table < ViewComponent::Base | ||
delegate :render_attribute, | ||
:resource_path, | ||
:render_icon, | ||
:edit_resource_path, | ||
:resource_handler, | ||
:resource_window_size, | ||
to: :helpers | ||
|
||
attr_reader :collection, | ||
:nothing_found_label, | ||
:search_filter_params | ||
|
||
renders_many :headers, Header | ||
|
||
renders_many :cells, ->(css_classes, &block) do | ||
Cell.new(css_classes, &block) | ||
end | ||
|
||
renders_many :actions, ->(name, tooltip = nil, &block) do | ||
Action.new(name, tooltip, &block) | ||
end | ||
|
||
erb_template <<~ERB | ||
<% if collection.any? %> | ||
<table class="list"> | ||
<thead> | ||
<tr> | ||
<% headers.each do |header| %> | ||
<%= header %> | ||
<% end %> | ||
<% if actions? %> | ||
<th class="tools"></th> | ||
<% end %> | ||
</tr> | ||
</thead> | ||
<tbody> | ||
<% collection.each do |resource| %> | ||
<tr class="<%= cycle('even', 'odd') %>"> | ||
<% cells.each do |cell| %> | ||
<%= render cell.with_resource(resource) %> | ||
<% end %> | ||
<% if actions? %> | ||
<td class="tools"> | ||
<% actions.each do |action| %> | ||
<%= render action.with_resource(resource) %> | ||
<% end %> | ||
</td> | ||
<% end %> | ||
</tr> | ||
<% end %> | ||
</tbody> | ||
</table> | ||
<% else %> | ||
<alchemy-message type="info"> | ||
<%= nothing_found_label %> | ||
</alchemy-message> | ||
<% end %> | ||
ERB | ||
|
||
def initialize(collection, query: nil, nothing_found_label: Alchemy.t("Nothing found"), search_filter_params: {}, icon: nil) | ||
@collection = collection | ||
@query = query | ||
@nothing_found_label = nothing_found_label | ||
@search_filter_params = search_filter_params | ||
@icon = icon | ||
end | ||
|
||
def column(name, header: nil, sortable: false, type: nil, class_name: nil, &block) | ||
header ||= resource_handler.model.human_attribute_name(name) | ||
type ||= resource_handler.model.columns_hash[name.to_s]&.type | ||
attribute = resource_handler.attributes.find { |item| item[:name] == name.to_s } || {name: name, type: type} | ||
block ||= lambda { |item| render_attribute(item, attribute) } | ||
|
||
css_classes = [name, type, class_name].compact.join(" ") | ||
with_header(name, @query, css_classes: css_classes, text: header, type: type, sortable: sortable) | ||
with_cell(css_classes, &block) | ||
end | ||
|
||
def icon_column(icon = nil, style: nil) | ||
column(:icon, header: "") do |resource| | ||
render_icon(icon || yield(resource), size: "xl", style: style) | ||
end | ||
end | ||
|
||
def delete_button(tooltip: Alchemy.t("Delete"), message: Alchemy.t("Are you sure?")) | ||
with_action(:destroy, tooltip) do |row| | ||
helpers.delete_button(resource_path(row, search_filter_params), {message: message}) | ||
end | ||
end | ||
|
||
def edit_button(tooltip: Alchemy.t("Edit"), size: resource_window_size) | ||
with_action(:edit, tooltip) do |row| | ||
helpers.link_to_dialog render_icon(:edit), | ||
edit_resource_path(row, search_filter_params), | ||
{size: size}, | ||
class: "icon_button" | ||
end | ||
end | ||
|
||
private | ||
|
||
## | ||
# if no cells are available the resource_helper will be used, to generate the | ||
# default attributes of the given resource | ||
def before_render | ||
unless cells? | ||
icon_column(@icon) if @icon.present? | ||
resource_handler.sorted_attributes.each do |attribute| | ||
column(attribute[:name], sortable: true) | ||
end | ||
delete_button | ||
edit_button | ||
end | ||
end | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.