From 040d7de47e8b878c0fd1900f3bc6d9f8280bcac1 Mon Sep 17 00:00:00 2001 From: Hasarinda Thenuwara Date: Tue, 27 Feb 2024 17:25:43 +1030 Subject: [PATCH] Add custom column widths --- .../koi/components/_index-table.scss | 21 +- app/components/koi/tables/body.rb | 22 +- .../koi/tables/body_row_component.rb | 148 ++++++++++-- app/components/koi/tables/header.rb | 88 ++++++- .../koi/tables/header_cell_component.rb | 30 +++ .../koi/tables/header_row_component.rb | 224 ++++++++++++++++-- spec/components/koi/tables/body_spec.rb | 13 +- spec/components/koi/tables/header_spec.rb | 88 +++++++ .../koi/tables/table_component_spec.rb | 45 ++-- 9 files changed, 602 insertions(+), 77 deletions(-) create mode 100644 spec/components/koi/tables/header_spec.rb diff --git a/app/assets/stylesheets/koi/components/_index-table.scss b/app/assets/stylesheets/koi/components/_index-table.scss index 981a0a9ab..c9c2ed242 100644 --- a/app/assets/stylesheets/koi/components/_index-table.scss +++ b/app/assets/stylesheets/koi/components/_index-table.scss @@ -62,8 +62,11 @@ $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; } @@ -71,6 +74,22 @@ $row-height: 48px !default; th { font-weight: bold; + + &.koi--tables-col-xs { + width: 5rem; + } + + &.koi--tables-col-s { + width: 10rem; + } + + &.koi--tables-col-m { + width: 15rem; + } + + &.koi--tables-col-l { + width: 20rem; + } } thead a.ascending:after, diff --git a/app/components/koi/tables/body.rb b/app/components/koi/tables/body.rb index a33092c24..5535f26d9 100644 --- a/app/components/koi/tables/body.rb +++ b/app/components/koi/tables/body.rb @@ -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) @@ -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) @@ -39,19 +41,27 @@ 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 @@ -59,11 +69,12 @@ def rendered_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 @@ -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) diff --git a/app/components/koi/tables/body_row_component.rb b/app/components/koi/tables/body_row_component.rb index ea2e7c1a6..3edcf8169 100644 --- a/app/components/koi/tables/body_row_component.rb +++ b/app/components/koi/tables/body_row_component.rb @@ -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 %> # => Yes + 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 %> # => 29 Feb 2024 + 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 %> # => 29 Feb 2024, 5:00pm + 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 %> # => 0 + 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 %> # => $3.50 + 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 %> # => Emphasis + 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 %> # => About us + # @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 %> + # # => Edit About us + 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 %> # => About us + 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 %> # => + 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 %> # => background.png + def attachment(method, **attributes, &block) + with_column(Body::AttachmentComponent.new(@table, @record, method, **attributes), &block) end end end diff --git a/app/components/koi/tables/header.rb b/app/components/koi/tables/header.rb index 2d70be5e1..c372009e8 100644 --- a/app/components/koi/tables/header.rb +++ b/app/components/koi/tables/header.rb @@ -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 diff --git a/app/components/koi/tables/header_cell_component.rb b/app/components/koi/tables/header_cell_component.rb index 9240328f8..dc328334c 100644 --- a/app/components/koi/tables/header_cell_component.rb +++ b/app/components/koi/tables/header_cell_component.rb @@ -3,6 +3,36 @@ module Koi module Tables class HeaderCellComponent < Katalyst::Tables::HeaderCellComponent + using Katalyst::HtmlAttributes::HasHtmlAttributes + + attr_reader :width + + def initialize(table, attribute, label: nil, link: {}, width: nil, **html_attributes) + @width = width + + super(table, attribute, label:, link:, **html_attributes) + end + + def default_html_attributes + super.merge_html(class: width_class) + end + + private + + def width_class + case width + when :xs + "koi--tables-col-xs" + when :s + "koi--tables-col-s" + when :m + "koi--tables-col-m" + when :l + "koi--tables-col-l" + else + "" + end + end end end end diff --git a/app/components/koi/tables/header_row_component.rb b/app/components/koi/tables/header_row_component.rb index 60f687524..4541499c9 100644 --- a/app/components/koi/tables/header_row_component.rb +++ b/app/components/koi/tables/header_row_component.rb @@ -5,50 +5,230 @@ module Tables # Custom header row component, in order to override the default header cell component # for number columns, we add a class to the header cell to allow for custom styling class HeaderRowComponent < Katalyst::Tables::HeaderRowComponent - def boolean(attribute, **attributes, &block) - header_cell(attribute, **attributes, &block) + # Renders a boolean column header + # @param method [Symbol] the method to call on the record to get the value + # @param attributes [Hash] additional arguments are applied as html attributes to the th element + # @option opts [String] :label (nil) The label options to display in the header + # @option opts [Hash] :link ({}) The link options for the sorting link + # @option opts [String] :width (:xs) The width of the column, can be +:xs+, +:s+, +:m+, +:l+ or nil + # + # @example Render a boolean column header + # <% row.boolean :active %> # => Active + # + # @example Render a boolean column header with a custom label + # <% row.boolean :active, label: "Published" %> # => Published + # + # @example Render a boolean column header with medium width + # <% row.boolean :active, width: :m %> + # # => Active + # + # @see Koi::Tables::BodyRowComponent#boolean + def boolean(method, **attributes, &block) + header_cell(method, component: Header::BooleanComponent, **attributes, &block) end - def date(attribute, **attributes, &block) - header_cell(attribute, **attributes, &block) + # Renders a date column header + # @param method [Symbol] the method to call on the record to get the value + # @param attributes [Hash] additional arguments are applied as html attributes to the th element + # @option opts [String] :label (nil) The label options to display in the header + # @option opts [Hash] :link ({}) The link options for the sorting link + # @option opts [String] :width (:s) The width of the column, can be +:xs+, +:s+, +:m+, +:l+ or nil + # + # @example Render a date column header + # <% row.date :published_on %> # => Published on + # + # @example Render a date column header with a custom label + # <% row.date :published_on, label: "Date" %> # => Date + # + # @example Render a date column header with small width + # <% row.date :published_on, width: :s %> + # # => Published on + # + # @see Koi::Tables::BodyRowComponent#date + def date(method, **attributes, &block) + header_cell(method, component: Header::DateComponent, **attributes, &block) end - def datetime(attribute, **attributes, &block) - header_cell(attribute, **attributes, &block) + # Renders a datetime column header + # @param method [Symbol] the method to call on the record to get the value + # @param attributes [Hash] additional arguments are applied as html attributes to the th element + # @option opts [String] :label (nil) The label options to display in the header + # @option opts [Hash] :link ({}) The link options for the sorting link + # @option opts [String] :width (:m) The width of the column, can be +:xs+, +:s+, +:m+, +:l+ or nil + # + # @example Render a datetime column header + # <% row.datetime :created_at %> # => Created at + # + # @example Render a datetime column header with a custom label + # <% row.datetime :created_at, label: "Published at" %> # => Published at + # + # @example Render a datetime column header with small width + # <% row.datetime :created_at, width: :s %> + # # => Created at + # + # @see Koi::Tables::BodyRowComponent#datetime + def datetime(method, **attributes, &block) + header_cell(method, component: Header::DateTimeComponent, **attributes, &block) end - def number(attribute, **attributes, &block) - header_cell(attribute, **attributes, component: Header::NumberComponent, &block) + # Renders a number column header + # @param method [Symbol] the method to call on the record to get the value + # @param attributes [Hash] additional arguments are applied as html attributes to the th element + # @option opts [String] :label (nil) The label options to display in the header + # @option opts [Hash] :link ({}) The link options for the sorting link + # @option opts [String] :width (:xs) The width of the column, can be +:xs+, +:s+, +:m+, +:l+ or nil + # + # @example Render a number column header + # <% row.number :comment_count %> # => Comments + # + # @example Render a number column header with a custom label + # <% row.number :comment_count, label: "Comments" %> # => Comments + # + # @example Render a number column header with medium width + # <% row.number :comment_count, width: :m %> + # # => Comment Count + # + # @see Koi::Tables::BodyRowComponent#number + def number(method, **attributes, &block) + header_cell(method, component: Header::NumberComponent, **attributes, &block) end - def money(attribute, **attributes, &block) - header_cell(attribute, **attributes, component: Header::NumberComponent, &block) + # Renders a currency column header + # @param method [Symbol] the method to call on the record to get the value + # @param attributes [Hash] additional arguments are applied as html attributes to the th element + # @option opts [String] :label (nil) The label options to display in the header + # @option opts [Hash] :link ({}) The link options for the sorting link + # @option opts [String] :width (:s) The width of the column, can be +:xs+, +:s+, +:m+, +:l+ or nil + # + # @example Render a currency column header + # <% row.currency :price %> # => Price + # + # @example Render a currency column header with a custom label + # <% row.currency :price, label: "Amount($)" %> # => Amount($) + # + # @example Render a currency column header with medium width + # <% row.currency :price, width: :m %> + # # => Price + # + # @see Koi::Tables::BodyRowComponent#currency + def currency(method, **attributes, &block) + header_cell(method, component: Header::CurrencyComponent, **attributes, &block) end - def rich_text(attribute, **attributes, &block) - header_cell(attribute, **attributes, &block) + # Renders a rich text column header + # @param method [Symbol] the method to call on the record to get the value + # @param attributes [Hash] additional arguments are applied as html attributes to the th element + # @option opts [String] :label (nil) The label options to display in the header + # @option opts [Hash] :link ({}) The link options for the sorting link + # @option opts [String] :width (nil) The width of the column, can be +:xs+, +:s+, +:m+, +:l+ or nil + # + # @example Render a rich text column header + # <% row.rich_text :content %> # => Content + # + # @example Render a rich text column header with a custom label + # <% row.rich_text :content, label: "Post content" %> # => Post content + # + # @example Render a rich text column header with large width + # <% row.rich_text :content, width: :l %> + # # => Content + # + # @see Koi::Tables::BodyRowComponent#rich_text + def rich_text(method, **attributes, &block) + header_cell(method, component: Header::TextComponent, **attributes, &block) end - def link(attribute, **attributes, &block) - header_cell(attribute, **attributes, &block) + # Renders a link column header + # @param method [Symbol] the method to call on the record to get the value + # @param attributes [Hash] additional arguments are applied as html attributes to the th element + # @option opts [String] :label (nil) The label options to display in the header + # @option opts [Hash] :link ({}) The link options for the sorting link + # @option opts [String] :width (nil) The width of the column, can be +:xs+, +:s+, +:m+, +:l+ or nil + # + # @example Render a link column header + # <% row.link :link %> # => Link + # + # @example Render a link column header with a custom label + # <% row.link :link, label: "Post" %> # => Post + # + # @example Render a link column header with small width + # <% row.link :content, width: :s %> + # # => Content + # + # @see Koi::Tables::BodyRowComponent#link + def link(method, **attributes, &block) + header_cell(method, component: Header::LinkComponent, **attributes, &block) end - def attachment(attribute, **attributes, &block) - header_cell(attribute, type: :link, **attributes, &block) + # Renders a text column header + # @param method [Symbol] the method to call on the record to get the value + # @param attributes [Hash] additional arguments are applied as html attributes to the th element + # @option opts [String] :label (nil) The label options to display in the header + # @option opts [Hash] :link ({}) The link options for the sorting link + # @option opts [String] :width (nil) The width of the column, can be +:xs+, +:s+, +:m+, +:l+ or nil + # + # @example Render a text column header + # <% row.text :content %> # => Content + # + # @example Render a text column header with a custom label + # <% row.text :content, label: "Description" %> # => Description + # + # @example Render a text column header with large width + # <% row.text :content, width: :l %> + # # => Content + # + # @see Koi::Tables::BodyRowComponent#text + def text(method, **attributes, &block) + header_cell(method, component: Header::TextComponent, **attributes, &block) end - def text(attribute, **attributes, &block) - header_cell(attribute, **attributes, &block) + # Renders a image column header + # @param method [Symbol] the method to call on the record to get the value + # @param attributes [Hash] additional arguments are applied as html attributes to the th element + # @option opts [String] :label (nil) The label options to display in the header + # @option opts [Hash] :link ({}) The link options for the sorting link + # @option opts [String] :width (nil) The width of the column, can be +:xs+, +:s+, +:m+, +:l+ or nil + # + # @example Render a image column header + # <% row.image :image %> # => Image + # + # @example Render a image column header with a custom label + # <% row.image :image, label: "Preview" %> # => Preview + # + # @example Render a image column header with small width + # <% row.image :image, width: :s %> + # # => Content + # + # @see Koi::Tables::BodyRowComponent#image + def image(method, **attributes, &block) + header_cell(method, component: Header::ImageComponent, **attributes, &block) end - def image(attribute, **attributes, &block) - header_cell(attribute, **attributes, &block) + # Renders a attachment column header + # @param method [Symbol] the method to call on the record to get the value + # @param attributes [Hash] additional arguments are applied as html attributes to the th element + # @option opts [String] :label (nil) The label options to display in the header + # @option opts [Hash] :link ({}) The link options for the sorting link + # @option opts [String] :width (nil) The width of the column, can be +:xs+, +:s+, +:m+, +:l+ or nil + # + # @example Render a attachment column header + # <% row.attachment :attachment %> # => Attachment + # + # @example Render a attachment column header with a custom label + # <% row.attachment :attachment, label: "Document" %> # => Document + # + # @example Render a attachment column header with small width + # <% row.attachment :attachment, width: :s %> + # # => Attachment + # + # @see Koi::Tables::BodyRowComponent#attachment + def attachment(method, **attributes, &block) + header_cell(method, component: Header::AttachmentComponent, **attributes, &block) end private - def header_cell(attribute, component: HeaderCellComponent, **attributes, &block) - with_column(component.new(@table, attribute, link: @link_attributes, **attributes), &block) + def header_cell(method, component: HeaderCellComponent, **attributes, &block) + with_column(component.new(@table, method, link: @link_attributes, **attributes), &block) end end end diff --git a/spec/components/koi/tables/body_spec.rb b/spec/components/koi/tables/body_spec.rb index 0f477afe1..ff6db3911 100644 --- a/spec/components/koi/tables/body_spec.rb +++ b/spec/components/koi/tables/body_spec.rb @@ -120,7 +120,18 @@ component = described_class.new(table, record, :ordinal) rendered = render_inline(component) expect(rendered).to match_html(<<~HTML) - #{record.ordinal} + #{record.ordinal} + HTML + end + end + + describe Koi::Tables::Body::CurrencyComponent do + it "renders column" do + record = create(:banner) + component = described_class.new(table, record, :ordinal) + rendered = render_inline(component) + expect(rendered).to match_html(<<~HTML) + $#{record.ordinal / 100.0} HTML end end diff --git a/spec/components/koi/tables/header_spec.rb b/spec/components/koi/tables/header_spec.rb new file mode 100644 index 000000000..fbcf1fc80 --- /dev/null +++ b/spec/components/koi/tables/header_spec.rb @@ -0,0 +1,88 @@ +# frozen_string_literal: true + +require "rails_helper" + +describe Koi::Tables::Header do + let(:table) { Koi::Tables::TableComponent.new(collection:, id: "table") } + let(:collection) { Post.all } + + describe Koi::Tables::Header::BooleanComponent do + it "renders column header" do + component = described_class.new(table, :active) + rendered = render_inline(component) + expect(rendered).to match_html(<<~HTML) + Active + HTML + end + + context "when width is specified" do + it "renders column header" do + component = described_class.new(table, :active, width: :m) + rendered = render_inline(component) + expect(rendered).to match_html(<<~HTML) + Active + HTML + end + end + + context "when width is set to nil" do + it "renders column header" do + component = described_class.new(table, :active, width: nil) + rendered = render_inline(component) + expect(rendered).to match_html(<<~HTML) + Active + HTML + end + end + + context "when additional css class is specified" do + it "renders column header" do + component = described_class.new(table, :active, class: "custom-class") + rendered = render_inline(component) + expect(rendered).to match_html(<<~HTML) + Active + HTML + end + end + end + + describe Koi::Tables::Header::NumberComponent do + let(:collection) { Banner.all } + + it "renders column header" do + component = described_class.new(table, :ordinal) + rendered = render_inline(component) + expect(rendered).to match_html(<<~HTML) + Ordinal + HTML + end + + context "with sorting" do + let(:collection) { Katalyst::Tables::Collection::Base.new(sorting: "ordinal desc").apply(Banner.all) } + + it "renders column header" do + component = described_class.new(table, :ordinal) + rendered = render_inline(component) + expect(rendered).to match_html(<<~HTML) + + Ordinal + + HTML + end + end + + context "with custom class and sorting" do + let(:collection) { Katalyst::Tables::Collection::Base.new(sorting: "ordinal desc").apply(Banner.all) } + + it "renders column header" do + component = described_class.new(table, :ordinal, class: "custom-class") + rendered = render_inline(component) + expect(rendered).to match_html(<<~HTML) + + Ordinal + + HTML + end + end + end +end diff --git a/spec/components/koi/tables/table_component_spec.rb b/spec/components/koi/tables/table_component_spec.rb index 11f30a6b8..5af82587e 100644 --- a/spec/components/koi/tables/table_component_spec.rb +++ b/spec/components/koi/tables/table_component_spec.rb @@ -23,26 +23,24 @@ end it "renders column" do - expect(table).to match_html(<<~HTML, + expect(table).to match_html(<<~HTML)
Name
#{collection.items.first&.name}
HTML - ) end context "with boolean" do let(:content) { Proc.new { |row| row.boolean :active } } it "renders boolean column" do - expect(table).to match_html(<<~HTML, + expect(table).to match_html(<<~HTML) - +
Active
Active
Yes
HTML - ) end context "with content" do @@ -55,13 +53,12 @@ end it "renders boolean column with custom content" do - expect(table).to match_html(<<~HTML, + expect(table).to match_html(<<~HTML) - +
Active
Active
Green
HTML - ) end end end @@ -71,13 +68,12 @@ let(:content) { Proc.new { |row| row.date :published_on } } it "renders date column" do - expect(table).to match_html(<<~HTML, + expect(table).to match_html(<<~HTML) - +
Published on
Published on
#{value}
HTML - ) end end @@ -86,13 +82,12 @@ let(:content) { Proc.new { |row| row.datetime :created_at } } it "renders datetime column" do - expect(table).to match_html(<<~HTML, + expect(table).to match_html(<<~HTML) - +
Created at
Created at
#{value}
HTML - ) end end @@ -101,13 +96,12 @@ let(:content) { Proc.new { |row| row.number :ordinal } } it "renders number column" do - expect(table).to match_html(<<~HTML, + expect(table).to match_html(<<~HTML) - - + +
Ordinal
#{collection.items.first&.ordinal}
Ordinal
#{collection.items.first&.ordinal}
HTML - ) end end @@ -115,9 +109,9 @@ let(:content) { Proc.new { |row| row.rich_text :content } } it "renders rich text column" do - expect(table).to match_html(<<~HTML, + expect(table).to match_html(<<~HTML) - +
Content
Content
#{collection.items.first&.content} @@ -125,7 +119,6 @@
HTML - ) end end @@ -133,15 +126,14 @@ let(:content) { Proc.new { |row| row.link :name } } it "renders link column" do - expect(table).to match_html(<<~HTML, + expect(table).to match_html(<<~HTML) - +
Name
Name
#{collection.items.first&.name}
HTML - ) end end @@ -149,13 +141,12 @@ let(:content) { Proc.new { |row| row.text :title } } it "renders text column" do - expect(table).to match_html(<<~HTML, + expect(table).to match_html(<<~HTML) - +
Title
Title
#{collection.items.first&.title}
HTML - ) end end end