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

Data Table Component and update to profiles PAT table #836

Merged
merged 11 commits into from
Nov 20, 2024
59 changes: 59 additions & 0 deletions app/components/viral/data_table/column_component.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# frozen_string_literal: true

module Viral
module DataTable
# Component responsible for specific column data of DataTableComponent
class ColumnComponent < Viral::Component
attr_reader :title

STICKY_CLASSES = {
left: {
header: 'sticky left-0 bg-slate-50 dark:bg-slate-700 z-10 ',
body: 'sticky left-0 bg-slate-50 dark:bg-slate-800 z-10'
},
left_fixed_index_zero: {
header: 'sticky left-0 min-w-56 max-w-56 bg-slate-50 dark:bg-slate-700 z-10',
body: 'sticky left-0 min-w-56 max-w-56 bg-slate-50 dark:bg-slate-800 z-10'
},
left_fixed_index_one: {
header: 'sticky left-56 bg-slate-50 dark:bg-slate-700 z-10',
body: 'sticky left-56 bg-slate-50 dark:bg-slate-800 z-10'
},
right: {
header: 'sticky right-0 bg-slate-50 dark:bg-slate-700 z-10',
body: 'sticky right-0 bg-white dark:bg-slate-800 space-x-2 z-10'
}
}.freeze

def initialize(
title,
**system_arguments,
&block
)
@title = title
@system_arguments = system_arguments
@block = block
end

def header_cell_arguments
{
classes:
class_names('px-3 py-3',
@system_arguments[:sticky_key] && STICKY_CLASSES[@system_arguments[:sticky_key]][:header])
}
end

def body_cell_arguments
{
classes:
class_names('px-3 py-3',
@system_arguments[:sticky_key] && STICKY_CLASSES[@system_arguments[:sticky_key]][:body])
}
end

def call(row)
@block.call(row)
end
end
end
end
49 changes: 49 additions & 0 deletions app/components/viral/data_table_component.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<%= render Viral::BaseComponent.new(**wrapper_arguments) do %>
<%= render Viral::BaseComponent.new(**system_arguments) do %>
<table
class="
w-full text-sm text-left rtl:text-right text-slate-500 dark:text-slate-400
whitespace-nowrap
"
>
<thead
class="
sticky top-0 z-10 text-xs uppercase text-slate-700 bg-slate-50 dark:bg-slate-700
dark:text-slate-300
"
>
<tr>
<% columns.each_with_index do |column, index| %>
<%= render_cell(
tag: 'th',
scope: 'col',
**column.header_cell_arguments
) do %>
<%= column.title %>
<% end %>
<% end %>
</tr>
</thead>
<tbody
class="
overflow-y-auto bg-white divide-y divide-slate-200 dark:bg-slate-800
dark:divide-slate-700
"
>
<% @data.each do |row| %>
<%= render Viral::BaseComponent.new(**row_arguments(row)) do %>
<% columns.each_with_index do |column, index| %>
<%= render_cell(
tag: index.zero? ? 'th' :'td',
scope: index.zero? ? 'row' : nil,
**column.body_cell_arguments
) do %>
<%= column.call(row) %>
<% end %>
<% end %>
<% end %>
<% end %>
</tbody>
</table>
<% end %>
<% end %>
52 changes: 52 additions & 0 deletions app/components/viral/data_table_component.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# frozen_string_literal: true

module Viral
# Table Component used to display data
class DataTableComponent < Viral::Component
renders_many :columns, lambda { |title, **system_arguments, &block|
Viral::DataTable::ColumnComponent.new(title, **system_arguments, &block)
}
def initialize(
data,
id: '',
**system_arguments
)
@data = data
@id = id
@system_arguments = system_arguments
end

def system_arguments
{ tag: 'div' }.deep_merge(@system_arguments).tap do |args|
args[:id] = @id
args[:classes] = class_names(args[:classes], 'overflow-auto scrollbar')
# possibly to be used once implemented into tables with selection
# if @abilities[:select]
# args[:data] ||= {}
# args[:data][:controller] = 'selection'
# args[:data][:'selection-total-value'] = @pagy.count
# args[:data][:'selection-action-link-outlet'] = '.action-link'
# end
end
end

def wrapper_arguments
{
tag: 'div',
classes: class_names('table-container flex flex-col shrink min-h-0 data-turbo-temporary'),
scope: 'col'
}
end

def row_arguments(data)
{ tag: 'tr' }.tap do |args|
args[:classes] = class_names('bg-white', 'border-b', 'dark:bg-slate-800', 'dark:border-slate-700')
args[:id] = data[:id]
end
end

def render_cell(**arguments, &)
render(Viral::BaseComponent.new(**arguments), &)
end
end
end
9 changes: 6 additions & 3 deletions app/controllers/profiles/personal_access_tokens_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ def index
@personal_access_token = PersonalAccessToken.new(scopes: [])
end

def create
def create # rubocop:disable Metrics/MethodLength
@personal_access_token = PersonalAccessTokens::CreateService.new(current_user,
personal_access_token_params).execute

Expand All @@ -24,7 +24,8 @@ def create
else
format.turbo_stream do
render status: :unprocessable_entity, locals: { personal_access_token: @personal_access_token,
new_personal_access_token: nil }
new_personal_access_token: nil,
message: @personal_access_token.errors.full_messages.first }
end
end
end
Expand All @@ -36,7 +37,9 @@ def revoke

@personal_access_token.revoke!
respond_to do |format|
format.turbo_stream
format.turbo_stream do
render locals: { message: t('.success', name: @personal_access_token.name) }
end
end
end

Expand Down
1 change: 1 addition & 0 deletions app/helpers/view_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ module ViewHelper
datepicker: 'Viral::Form::DatepickerComponent',
dialog: 'Viral::DialogComponent',
empty: 'Viral::EmptyStateComponent',
data_table: 'Viral::DataTableComponent',
dropdown: 'Viral::DropdownComponent',
file_input: 'Viral::Form::FileInputComponent',
flash: 'Viral::FlashComponent',
Expand Down
3 changes: 2 additions & 1 deletion app/views/profiles/personal_access_tokens/_form.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@
<%= check_box_tag "personal_access_token[scopes][]",
scope,
personal_access_token.scopes.include?(scope),
id: "personal_access_token_scopes_#{scope}" %>
id: "personal_access_token_scopes_#{scope}",
class: "w-4 h-4 text-primary-600 bg-slate-100 border-slate-300 rounded focus:ring-primary-500 dark:focus:ring-primary-600 dark:ring-offset-slate-800 focus:ring-2 dark:bg-slate-700 dark:border-slate-600" %>
</div>
<div class="ml-2 text-sm">
<%= label_tag "personal_access_token_scopes_#{scope}",
Expand Down

This file was deleted.

52 changes: 52 additions & 0 deletions app/views/profiles/personal_access_tokens/_table.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<%= turbo_frame_tag "personal_access_tokens" do %>
<% if @active_access_tokens.count.positive? %>
<%= viral_data_table(@active_access_tokens, id: "personal-access-tokens-table") do |table| %>
<% table.with_column(t("activerecord.attributes.personal_access_token.name")) do |row| %>
<%= row[:name] %>
<% end %>
<% table.with_column(t("activerecord.attributes.personal_access_token.scopes")) do |row| %>
<%= row[:scopes].join(", ") %>
<% end %>
<% table.with_column(t("activerecord.attributes.personal_access_token.created_at")) do |row| %>
<%= local_time(row[:created_at], :full_date) %>
<% end %>
<% table.with_column(t("activerecord.attributes.personal_access_token.last_used_at")) do |row| %>
<% if row[:last_used_at].present? %>
<%= local_time(row[:last_used_at], :full_date) %>
<% else %>
<%= t(".never") %>
<% end %>
<% end %>
<% table.with_column(t(".expires_at")) do |row| %>
<% if row[:expires_at].present? %>
<%= local_time(row[:expires_at], :full_date) %>
<% else %>
<%= t(".never") %>
<% end %>
<% end %>
<% table.with_column(t("viral.data_table_component.header.action"),
sticky_key: :right
) do |row| %>
<%= link_to(
t(".revoke_button"),
revoke_profile_personal_access_token_path(id: row.id),
data: {
turbo_frame: "personal-access-tokens",
turbo_method: :delete,
turbo_confirm: t(".revoke_confirm")
},
class:
"font-medium text-blue-600 underline dark:text-blue-500 hover:no-underline cursor-pointer"
) %>
<% end %>
<% end %>
<% else %>
<div class="empty_state_message">
<%= viral_empty(
title: t(".empty_state.title"),
description: t(".empty_state.description"),
icon_name: :document_text
) %>
</div>
<% end %>
<% end %>
26 changes: 18 additions & 8 deletions app/views/profiles/personal_access_tokens/create.turbo_stream.erb
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,31 @@
<%= turbo_stream.replace "access-token-section",
partial: "access_token_section",
locals: {
token: new_personal_access_token.token
token: new_personal_access_token.token,
} %>
<%= turbo_stream.update "personal-access-tokens-header",
t(
:"profiles.personal_access_tokens.index.active_personal_access_tokens",
count: @active_access_tokens.count
count: @active_access_tokens.count,
) %>
<%= turbo_stream.append "access-tokens-table-body",
partial: "personal_access_token",
locals: {
personal_access_token: new_personal_access_token
} %>
<%= turbo_stream.replace "personal_access_tokens",
partial: "table",
locals: {
personal_access_token: new_personal_access_token,
} %>
<%= turbo_stream.append "flashes" do %>
<%= viral_flash(
type: :success,
data: t(".success", name: new_personal_access_token.name),
) %>
<% end %>
<% else %>
<%= turbo_stream.append "flashes" do %>
<%= viral_flash(type: :error, data: message) %>
<% end %>
<% end %>
<%= turbo_stream.replace "personal_access_token_form",
partial: "form",
locals: {
personal_access_token: personal_access_token
personal_access_token: personal_access_token,
} %>
41 changes: 2 additions & 39 deletions app/views/profiles/personal_access_tokens/index.html.erb
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
<%= turbo_refreshes_with method: :morph, scroll: :preserve %>
<%= render Viral::PageHeaderComponent.new(title: t("profiles.personal_access_tokens.index.title"), subtitle: t("profiles.personal_access_tokens.index.subtitle")) do |component| %>
<%= component.with_icon(name: "ticket", classes: "h-14 w-14 text-primary-700") %>
<% end %>
Expand All @@ -18,44 +19,6 @@
), title_id: "personal-access-tokens-header") do %>
<%= turbo_frame_tag("personal-access-token-revoke-errors") %>

<%= turbo_frame_tag("personal-access-tokens") do %>
<div class="relative overflow-x-auto">
<table
class="
w-full
text-sm
text-left
rtl:text-right
text-slate-500
dark:text-slate-400
dark:divide-slate-600
whitespace-nowrap
"
>
<thead
class="
text-xs
text-slate-700
uppercase
bg-slate-50
dark:bg-slate-700
dark:text-slate-400
"
>
<tr>
<th scope="col" class="px-6 py-3"><%= t("activerecord.attributes.personal_access_token.name") %></th>
<th scope="col" class="px-6 py-3"><%= t("activerecord.attributes.personal_access_token.scopes") %></th>
<th scope="col" class="px-6 py-3"><%= t("activerecord.attributes.personal_access_token.created_at") %></th>
<th scope="col" class="px-6 py-3"><%= t("activerecord.attributes.personal_access_token.last_used_at") %></th>
<th scope="col" class="px-6 py-3"><%= t(".expires_at") %></th>
<th scope="col" class="px-6 py-3"><%= t(".action") %></th>
</tr>
</thead>
<tbody id="access-tokens-table-body">
<%= render partial: "personal_access_token", collection: @active_access_tokens %>
</tbody>
</table>
</div>
<% end %>
<%= render partial: 'table' %>
<% end %>
</div>
Loading
Loading