Skip to content

Commit

Permalink
Add custom column widths
Browse files Browse the repository at this point in the history
  • Loading branch information
hasarindaKI committed Feb 29, 2024
1 parent 4e19d00 commit 9431fad
Show file tree
Hide file tree
Showing 9 changed files with 602 additions and 77 deletions.
21 changes: 20 additions & 1 deletion app/assets/stylesheets/koi/components/_index-table.scss
Original file line number Diff line number Diff line change
Expand Up @@ -62,15 +62,34 @@ $row-height: 48px !default;
max-height: 3rem;
padding: 0;
}
}

&.number {
td {
&.koi--tables-col-currency,
&.koi--tables-col-number {
text-align: right;
padding-right: 0.5rem;
}
}

th {
font-weight: bold;

&.koi--tables-col-xs {
width: 5rem;
}

&.koi--tables-col-s {
width: 8rem;
}

&.koi--tables-col-m {
width: 12rem;
}

&.koi--tables-col-l {
width: 20rem;
}
}

thead a.ascending:after,
Expand Down
22 changes: 17 additions & 5 deletions app/components/koi/tables/body.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ def rendered_value
end

# Formats the value as a date
#
# default format is :admin
class DateComponent < BodyCellComponent
def initialize(table, record, attribute, format: :admin, **options)
Expand All @@ -25,6 +26,7 @@ def rendered_value
end

# Formats the value as a datetime
#
# default format is :admin
class DatetimeComponent < BodyCellComponent
def initialize(table, record, attribute, format: :admin, **options)
Expand All @@ -39,31 +41,40 @@ def rendered_value
end

# Formats the value as a money value
# The value is expected to be in cents
#
# The value is expected to be in cents.
# Adds a class to the cell to allow for custom styling
class MoneyComponent < BodyCellComponent
class CurrencyComponent < BodyCellComponent
def initialize(table, record, attribute, options: {}, **html_attributes)
super(table, record, attribute, **html_attributes)

@options = options
end

def rendered_value
value.present? ? number_to_currency(value / 100.0) : ""
value.present? ? number_to_currency(value / 100.0, @options) : ""
end

def default_html_attributes
{ class: "number" }
{ class: "koi--tables-col-currency" }
end
end

# Formats the value as a number
#
# Adds a class to the cell to allow for custom styling
class NumberComponent < BodyCellComponent
def rendered_value
value.present? ? number_to_human(value) : ""
end

def default_html_attributes
{ class: "number" }
{ class: "koi--tables-col-number" }
end
end

# Displays the plain text for rich text content
#
# Adds a title attribute to allow for hover over display of the full content
class RichTextComponent < BodyCellComponent
def default_html_attributes
Expand Down Expand Up @@ -102,6 +113,7 @@ def url
end

# Shows a thumbnail image
#
# The value is expected to be an ActiveStorage attachment with a default variant named :thumb
class ImageComponent < BodyCellComponent
def initialize(table, record, attribute, variant: :thumb, **options)
Expand Down
148 changes: 128 additions & 20 deletions app/components/koi/tables/body_row_component.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,44 +4,152 @@ module Koi
module Tables
# Custom body row component, in order to override the default body cell component
class BodyRowComponent < Katalyst::Tables::BodyRowComponent
def boolean(attribute, **options, &block)
with_column(Body::BooleanComponent.new(@table, @record, attribute, **options), &block)
# Generates a column from boolean values rendered as "Yes" or "No".
#
# @param method [Symbol] the method to call on the record
# @param attributes [Hash] HTML attributes to be added to the cell
# @param block [Proc] optional block to alter the cell content
# @return [void]
#
# @example Render a boolean column indicating whether the record is active
# <% row.boolean :active %> # => <td>Yes</td>
def boolean(method, **attributes, &block)
with_column(Body::BooleanComponent.new(@table, @record, method, **attributes), &block)
end

def date(attribute, format: :admin, **options, &block)
with_column(Body::DateComponent.new(@table, @record, attribute, format:, **options), &block)
# Generates a column from date values rendered using I18n.l.
# The default format is :admin, but it can be overridden.
#
# @param method [Symbol] the method to call on the record
# @param format [Symbol] the I18n date format to use when rendering
# @param attributes [Hash] HTML attributes to be added to the cell tag
# @param block [Proc] optional block to alter the cell content
# @return [void]
#
# @example Render a date column describing when the record was created
# <% row.date :created_at %> # => <td>29 Feb 2024</td>
def date(method, format: :admin, **attributes, &block)
with_column(Body::DateComponent.new(@table, @record, method, format:, **attributes), &block)
end

def datetime(attribute, format: :admin, **options, &block)
with_column(Body::DatetimeComponent.new(@table, @record, attribute, format:, **options), &block)
# Generates a column from datetime values rendered using I18n.l.
# The default format is :admin, but it can be overridden.
#
# @param method [Symbol] the method to call on the record
# @param format [Symbol] the I18n datetime format to use when rendering
# @param attributes [Hash] HTML attributes to be added to the cell tag
# @param block [Proc] optional block to alter the cell content
# @return [void]
#
# @example Render a datetime column describing when the record was created
# <% row.datetime :created_at %> # => <td>29 Feb 2024, 5:00pm</td>
def datetime(method, format: :admin, **attributes, &block)
with_column(Body::DatetimeComponent.new(@table, @record, method, format:, **attributes), &block)
end

def number(attribute, **options, &block)
with_column(Body::NumberComponent.new(@table, @record, attribute, **options), &block)
# Generates a column from numeric values formatted appropriately.
#
# @param method [Symbol] the method to call on the record
# @param attributes [Hash] HTML attributes to be added to the cell tag
# @param block [Proc] optional block to alter the cell content
# @return [void]
#
# @example Render the number of comments on a post
# <% row.number :comment_count %> # => <td>0</td>
def number(method, **attributes, &block)
with_column(Body::NumberComponent.new(@table, @record, method, **attributes), &block)
end

def money(attribute, **options, &block)
with_column(Body::MoneyComponent.new(@table, @record, attribute, **options), &block)
# Generates a column from numeric values rendered using `number_to_currency`.
#
# @param method [Symbol] the method to call on the record
# @param options [Hash] options to be passed to `number_to_currency`
# @param attributes [Hash] HTML attributes to be added to the cell tag
# @param block [Proc] optional block to alter the cell content
# @return [void]
#
# @example Render a currency column for the price of a product
# <% row.currency :price %> # => <td>$3.50</td>
def currency(method, options: {}, **attributes, &block)
with_column(Body::CurrencyComponent.new(@table, @record, method, options:, **attributes), &block)
end

def rich_text(attribute, **options, &block)
with_column(Body::RichTextComponent.new(@table, @record, attribute, **options), &block)
# Generates a column containing HTML markup.
#
# @param method [Symbol] the method to call on the record
# @param attributes [Hash] HTML attributes to be added to the cell tag
# @param block [Proc] optional block to alter the cell content
# @return [void]
#
# @note This method assumes that the method returns HTML-safe content.
# If the content is not HTML-safe, it will be escaped.
#
# @example Render a description column containing HTML markup
# <% row.rich_text :description %> # => <td><em>Emphasis</em></td>
def rich_text(method, **attributes, &block)
with_column(Body::RichTextComponent.new(@table, @record, method, **attributes), &block)
end

def link(attribute, url: [:admin, @record], link: {}, **attributes, &block)
with_column(Body::LinkComponent.new(@table, @record, attribute, url:, link:, **attributes), &block)
# Generates a column that links to the record's show page (by default).
#
# @param method [Symbol] the method to call on the record
# @param link [Hash] options to be passed to the link_to helper
# @option opts [Hash, Array, String, Symbol] :url ([:admin, object]) options for url_for,
# or a symbol to be passed to the route helper
# @param attributes [Hash] HTML attributes to be added to the cell tag
# @param block [Proc] optional block to alter the cell content
# @return [void]
#
# @example Render a column containing the record's title, linked to its show page
# <% row.link :title %> # => <td><a href="/admin/post/15">About us</a></td>
# @example Render a column containing the record's title, linked to its edit page
# <% row.link :title, url: :edit_admin_post_path do |cell| %>
# Edit <%= cell %>
# <% end %>
# # => <td><a href="/admin/post/15/edit">Edit About us</a></td>
def link(method, url: [:admin, @record], link: {}, **attributes, &block)
with_column(Body::LinkComponent.new(@table, @record, method, url:, link:, **attributes), &block)
end

def text(attribute, **options, &block)
with_column(BodyCellComponent.new(@table, @record, attribute, **options), &block)
# Generates a column that renders the contents as text.
#
# @param method [Symbol] the method to call on the record
# @param attributes [Hash] HTML attributes to be added to the cell tag
# @param block [Proc] optional block to alter the cell content
# @return [void]
#
# @example Render a column containing the record's title
# <% row.text :title %> # => <td>About us</td>
def text(method, **attributes, &block)
with_column(BodyCellComponent.new(@table, @record, method, **attributes), &block)
end

def image(attribute, variant: :thumb, **options, &block)
with_column(Body::ImageComponent.new(@table, @record, attribute, variant:, **options), &block)
# Generates a column that renders an ActiveStorage attachment as an image.
# Assumes that a variant called `:thumb` is defined for the attachment.
#
# @param method [Symbol] the method to call on the record
# @param variant [Symbol] the variant to use when rendering the image (default :thumb)
# @param attributes [Hash] HTML attributes to be added to the cell tag
# @param block [Proc] optional block to alter the cell content
# @return [void]
#
# @example Render a column containing a thumbnail of the record's background image
# <% row.image :background %> # => <td><img src="..." /></td>
def image(method, variant: :thumb, **attributes, &block)
with_column(Body::ImageComponent.new(@table, @record, method, variant:, **attributes), &block)
end

def attachment(attribute, **options, &block)
with_column(Body::AttachmentComponent.new(@table, @record, attribute, **options), &block)
# Generates a column that renders an ActiveStorage attachment as a downloadable link.
#
# @param method [Symbol] the method to call on the record
# @param attributes [Hash] HTML attributes to be added to the cell tag
# @param block [Proc] optional block to alter the cell content
# @return [void]
#
# @example Render a column containing a download link to the record's background image
# <% row.attachment :background %> # => <td><a href="...">background.png</a></td>
def attachment(method, **attributes, &block)
with_column(Body::AttachmentComponent.new(@table, @record, method, **attributes), &block)
end
end
end
Expand Down
88 changes: 87 additions & 1 deletion app/components/koi/tables/header.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,94 @@ module Koi
module Tables
module Header
class NumberComponent < HeaderCellComponent
using Katalyst::HtmlAttributes::HasHtmlAttributes

def initialize(table, attribute, label: nil, link: {}, width: :xs, **html_attributes)
super(table, attribute, label:, link:, width:, **html_attributes)
end

def default_html_attributes
super.merge_html(class: "koi--tables-col-number")
end
end

class CurrencyComponent < HeaderCellComponent
using Katalyst::HtmlAttributes::HasHtmlAttributes

def initialize(table, attribute, label: nil, link: {}, width: :s, **html_attributes)
super(table, attribute, label:, link:, width:, **html_attributes)
end

def default_html_attributes
super.merge_html(class: "koi--tables-col-currency")
end
end

class BooleanComponent < HeaderCellComponent
using Katalyst::HtmlAttributes::HasHtmlAttributes

def initialize(table, attribute, label: nil, link: {}, width: :xs, **html_attributes)
super(table, attribute, label:, link:, width:, **html_attributes)
end

def default_html_attributes
super.merge_html(class: "koi--tables-col-boolean")
end
end

class DateComponent < HeaderCellComponent
using Katalyst::HtmlAttributes::HasHtmlAttributes

def initialize(table, attribute, label: nil, link: {}, width: :s, **html_attributes)
super(table, attribute, label:, link:, width:, **html_attributes)
end

def default_html_attributes
super.merge_html(class: "koi--tables-col-date")
end
end

class DateTimeComponent < HeaderCellComponent
using Katalyst::HtmlAttributes::HasHtmlAttributes

def initialize(table, attribute, label: nil, link: {}, width: :m, **html_attributes)
super(table, attribute, label:, link:, width:, **html_attributes)
end

def default_html_attributes
super.merge_html(class: "koi--tables-col-datetime")
end
end

class LinkComponent < HeaderCellComponent
using Katalyst::HtmlAttributes::HasHtmlAttributes

def default_html_attributes
super.merge_html(class: "koi--tables-col-link")
end
end

class TextComponent < HeaderCellComponent
using Katalyst::HtmlAttributes::HasHtmlAttributes

def default_html_attributes
super.merge_html(class: "koi--tables-col-text")
end
end

class ImageComponent < HeaderCellComponent
using Katalyst::HtmlAttributes::HasHtmlAttributes

def default_html_attributes
super.merge_html(class: "koi--tables-col-image")
end
end

class AttachmentComponent < HeaderCellComponent
using Katalyst::HtmlAttributes::HasHtmlAttributes

def default_html_attributes
{ class: "number" }
super.merge_html(class: "koi--tables-col-attachment")
end
end
end
Expand Down
Loading

0 comments on commit 9431fad

Please sign in to comment.