diff --git a/app/assets/stylesheets/components/concept_details.scss b/app/assets/stylesheets/components/concept_details.scss
new file mode 100644
index 000000000..7ae6fef43
--- /dev/null
+++ b/app/assets/stylesheets/components/concept_details.scss
@@ -0,0 +1,11 @@
+
+.concept_details_component .raw-table .dropdown-title-bar p {
+ padding: 10px 0px;
+ color: rgb(136, 136, 136);
+ font-weight: 400;
+}
+
+
+.concept_details_component table th {
+ width: 220px;
+}
\ No newline at end of file
diff --git a/app/assets/stylesheets/components/dropdown.scss b/app/assets/stylesheets/components/dropdown.scss
index d3221cc80..d923eae5c 100644
--- a/app/assets/stylesheets/components/dropdown.scss
+++ b/app/assets/stylesheets/components/dropdown.scss
@@ -6,12 +6,12 @@
font-size: 16px;
color: #000000;
cursor: pointer;
+ padding: 14px 20px;
}
.dropdown-container {
border: 1px solid #dfdfdf;
border-radius: 5px;
- padding: 14px 20px;
margin-bottom: 20px;
margin-top: 20px;
}
\ No newline at end of file
diff --git a/app/assets/stylesheets/components/index.scss b/app/assets/stylesheets/components/index.scss
index 8c01c27e2..fd221d5d7 100644
--- a/app/assets/stylesheets/components/index.scss
+++ b/app/assets/stylesheets/components/index.scss
@@ -10,4 +10,5 @@
@import 'input_field';
@import 'file_input_loader';
@import 'text_area_field';
-
+@import "table";
+@import "concept_details";
\ No newline at end of file
diff --git a/app/assets/stylesheets/components/table.scss b/app/assets/stylesheets/components/table.scss
new file mode 100644
index 000000000..c132a4c31
--- /dev/null
+++ b/app/assets/stylesheets/components/table.scss
@@ -0,0 +1,30 @@
+.table-content{
+ border-collapse: collapse;
+ width: 100%;
+ border-spacing: 0;
+}
+
+.table-content thead th{
+ background-color: hsl(0, 0%, 100%);
+ border-bottom: 1px solid hsl(240, 4%, 85%);
+ font-weight: 700;
+ color: hsl(230, 13%, 9%);
+}
+
+
+.table-content td, .table-content th{
+ padding: 12px 24px;
+ vertical-align: top;
+}
+
+
+.table-content-stripped tbody tr:nth-child(odd) {
+ background-color: #FAFAFA;
+}
+
+.table-content tbody th:first-child {
+ color: #888888;
+ font-weight: 400;
+}
+
+
diff --git a/app/assets/stylesheets/concepts.scss b/app/assets/stylesheets/concepts.scss
index 0c8c7a08d..87627bd5c 100644
--- a/app/assets/stylesheets/concepts.scss
+++ b/app/assets/stylesheets/concepts.scss
@@ -97,32 +97,7 @@ div.synonym-change-request button {
.concepts-json:hover svg path{
fill: white;
}
-.concepts-content{
- border-collapse: collapse;
- width: 100%;
- border-spacing: 0;
-
-}
-.concepts-content td{
- padding: 12px 24px;
- vertical-align: top;
-}
-.concepts-content tr:nth-child(odd) {
- background-color: #FAFAFA;
-}
-.concepts-content td:first-child {
- color: #888888;
- width: 220px;
-}
-.concepts-content td:first-child {
- color: #888888;
- width: 220px;
-}
-.concepts-content a{
- text-decoration: underline;
- color: #888888;
-}
.concepts-content div{
margin-bottom: 5px;
}
diff --git a/app/components/concept_details_component.rb b/app/components/concept_details_component.rb
index 86074870e..a6d1ee737 100644
--- a/app/components/concept_details_component.rb
+++ b/app/components/concept_details_component.rb
@@ -3,8 +3,8 @@
class ConceptDetailsComponent < ViewComponent::Base
include ApplicationHelper
- renders_one :header
- renders_many :sections
+ renders_one :header, TableComponent
+ renders_many :sections, TableRowComponent
attr_reader :concept_properties
@@ -19,8 +19,20 @@ def initialize(id:, acronym:, properties:, top_keys:, bottom_keys:, exclude_keys
@concept_properties = concept_properties2hash(@properties) if @properties
end
- def render_properties(properties_set, ontology_acronym, &block)
- out = ''
+ def add_sections(keys, &block)
+ scheme_set = properties_set_by_keys(keys, concept_properties)
+ rows = row_hash_properties(scheme_set, concept_properties, &block)
+
+ rows.each do |row|
+ section do |table_row|
+ table_row.create(*row)
+ end
+ end
+
+ end
+
+ def row_hash_properties(properties_set, ontology_acronym, &block)
+ out = []
properties_set&.each do |key, data|
next if exclude_relation?(key) || !data[:values]
@@ -35,17 +47,12 @@ def render_properties(properties_set, ontology_acronym, &block)
end
end
- line = <<-EOS
-
-
- #{remove_owl_notation(key)}
- |
- #{" #{ajax_links.join(' ')}".html_safe} |
-
- EOS
- out += line
+ out << [
+ { th: "#{remove_owl_notation(key)}".html_safe },
+ { td: " #{"
#{ajax_links.join('
')}"}
".html_safe }
+ ]
end
- raw out
+ out
end
def properties_set_by_keys(keys, concept_properties, exclude_keys = [])
@@ -64,10 +71,11 @@ def filter_properties(top_keys, bottom_keys, exclude_keys, concept_properties)
end
private
+
def concept_properties2hash(properties)
# NOTE: example properties
#
- #properties
+ # properties
#=> # "#collapse-#{@id}", "data-toggle" => "collapse"}
- %div Raw data
- %img{src: asset_path("arrow-down.svg")}
- .collapse{id: "collapse-#{@id}", "data-parent" => "#accordion-#{@id}"}
- %table#concepts-content.concepts-content
- - top_set, leftover_set, bottom_set = filter_properties(@top_keys, @bottom_keys, @exclude_keys, @concept_properties)
- = render_properties(top_set, @acronym)
- = render_properties(leftover_set, @acronym)
- - sections&.each do |section|
- = section
- = render_properties(bottom_set, @acronym)
+ %div.raw-table
+ = render DropdownContainerComponent.new(title: 'Raw data', id: "accordion-#{@id}") do
+ - top_set, leftover_set, bottom_set = filter_properties(@top_keys, @bottom_keys, @exclude_keys, @concept_properties)
+ = render TableComponent.new(stripped: true) do |t|
+
+ - row_hash_properties(top_set, @acronym).each do |row|
+ - t.add_row(*row)
+
+ - row_hash_properties(leftover_set, @acronym).each do |row|
+ - t.add_row(*row)
+
+
+ - sections.each do |section|
+ - t.row do
+ = section
+
+
+ - row_hash_properties(bottom_set, @acronym).each do |row|
+ - t.add_row(*row)
diff --git a/app/components/table_cell_component.rb b/app/components/table_cell_component.rb
new file mode 100644
index 000000000..2e459cb32
--- /dev/null
+++ b/app/components/table_cell_component.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+class TableCellComponent < ViewComponent::Base
+
+ def initialize(width: nil, colspan: nil,type: 'td')
+ super
+ @width = width
+ @type = type
+ @colspan = colspan
+ end
+
+ def call
+ options = {}
+ options[:width] = @width if @width
+ options[:colspan] = @colspan if @colspan
+ content_tag(@type, content&.html_safe, options)
+ end
+end
diff --git a/app/components/table_component.rb b/app/components/table_component.rb
new file mode 100644
index 000000000..05a2f3a7c
--- /dev/null
+++ b/app/components/table_component.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+class TableComponent < ViewComponent::Base
+
+ renders_one :header, TableRowComponent
+ renders_many :rows, TableRowComponent
+
+ def initialize(id: '', stripped: true)
+ super
+ @id = id
+ @stripped = stripped
+ end
+
+ def stripped_class
+ @stripped ? 'table-content-stripped' : ''
+ end
+
+ def add_row(*array, &block)
+ self.row.create(*array, &block)
+ end
+end
diff --git a/app/components/table_component/table_component.html.haml b/app/components/table_component/table_component.html.haml
new file mode 100644
index 000000000..089870b44
--- /dev/null
+++ b/app/components/table_component/table_component.html.haml
@@ -0,0 +1,7 @@
+%table.table-content{id: @id, class: stripped_class}
+ %thead
+ = header
+ %tbody{id: "#{@id}_table_body"}
+ - rows.each do |row|
+ = row
+ = content
\ No newline at end of file
diff --git a/app/components/table_row_component.rb b/app/components/table_row_component.rb
new file mode 100644
index 000000000..90c995a2a
--- /dev/null
+++ b/app/components/table_row_component.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+class TableRowComponent < ViewComponent::Base
+
+ renders_many :cells, TableCellComponent
+
+ def initialize(id: '')
+ super
+ @id = id
+ end
+
+ def create(*array, &block)
+ array.each do |key_value|
+ key, value = key_value.to_a.first
+ self.cell(type: key) { value&.to_s }
+ end
+ block.call(self) if block_given?
+ end
+
+ def th(width: nil, colspan: nil, &block)
+ self.cell(type: 'th', width: width, colspan: colspan, &block)
+ end
+
+ def td(width: nil, colspan: nil, &block)
+ self.cell(type: 'td', width: width, colspan: colspan, &block)
+ end
+end
diff --git a/app/components/table_row_component/table_row_component.html.haml b/app/components/table_row_component/table_row_component.html.haml
new file mode 100644
index 000000000..55dad8c73
--- /dev/null
+++ b/app/components/table_row_component/table_row_component.html.haml
@@ -0,0 +1,4 @@
+%tr{id: @id}
+ - cells.each do |cell|
+ = cell
+ = content
\ No newline at end of file
diff --git a/app/controllers/notes_controller.rb b/app/controllers/notes_controller.rb
index 83051c4e1..b47208ac2 100644
--- a/app/controllers/notes_controller.rb
+++ b/app/controllers/notes_controller.rb
@@ -103,7 +103,7 @@ def create
success_message = 'New comment added successfully'
locals = { note: new_note, ontology_acronym: ontology_acronym, parent_type: parent_type }
partial = 'notes/note_line'
- container_id = "#{parent_type}_notes_table_content"
+ container_id = "#{parent_type}_notes_table_body"
alerts_container_id = nil
end
diff --git a/app/views/collections/_collection.html.haml b/app/views/collections/_collection.html.haml
index a3310e726..580c0b74e 100644
--- a/app/views/collections/_collection.html.haml
+++ b/app/views/collections/_collection.html.haml
@@ -4,24 +4,8 @@
top_keys: %w[created modified comment note],
bottom_keys: [],
exclude_keys: %w[member]) do |c|
- = c.header do
- %tr
- %td.label
- ID
- %td
- %p
- = collection["@id"]
- %tr
- %td{nowrap: ""} Preferred Name
- %td
- %p= get_collection_label(collection)
- %tr
- %td{nowrap: ""} Members count
- %td
- %p= collection["memberCount"]
- %tr
- %td.label
- Type
- %td
- %p
- = collection["@type"]
\ No newline at end of file
+ - c.header(stripped: true) do |t|
+ - t.add_row({th: 'ID'}, {td: collection["@id"]})
+ - t.add_row({th: 'Preferred Name'}, {td: get_collection_label(collection)})
+ - t.add_row({th: 'Members count'}, {td: collection["memberCount"]})
+ - t.add_row({th: 'Type'}, {td: collection["@type"]})
\ No newline at end of file
diff --git a/app/views/concepts/_details.html.haml b/app/views/concepts/_details.html.haml
index 4a9fb9c3c..a83f051fa 100644
--- a/app/views/concepts/_details.html.haml
+++ b/app/views/concepts/_details.html.haml
@@ -1,73 +1,62 @@
= turbo_frame_tag 'concept_details' do
- schemes_keys = %w[hasTopConcept topConceptOf]
- label_xl_set = %w[skos-xl#prefLabel skos-xl#altLabel skos-xl#hiddenLabel]
-
- if @concept.prefLabel.nil?
%div.py-3.px-2
= render(AlertMessageComponent.new(message: t('ontology_details.concept.no_preferred_name_for_selected_language'), type: "warning", closeable: true))
-
+
= render ConceptDetailsComponent.new(id:'concept-details', acronym: @ontology.acronym,
properties: @concept.properties,
top_keys: %w[description comment],
bottom_keys: %w[disjoint subclass is_a has_part],
exclude_keys: schemes_keys + label_xl_set + ['inScheme']) do |c|
-
- - c.header do
- %tr
- %td{nowrap: ""}= t('ontology_details.concept.id')
- %td
- = @concept.id
- %tr
- %td{nowrap: ""}= t('ontology_details.concept.preferred_name')
- %td
- = @concept.prefLabel({:use_html => true}).html_safe
+
+ - c.header(stripped: true) do |t|
+ - t.add_row({th: t('ontology_details.concept.id')}, {td:@concept.id})
+ - t.add_row({th: t('ontology_details.concept.preferred_name')}, {td:@concept.prefLabel({:use_html => true}).html_safe})
+
- unless @concept.synonym.nil? || @concept.synonym.empty?
- %tr
- %td{nowrap: ""}= t('ontology_details.concept.synonyms')
- %td
- - for synonym in @concept.synonym
- = synonym
- %td
- %div.synonym-change-request
- = add_synonym_button
- = remove_synonym_button
-
-
+ - t.add_row({th: t('ontology_details.concept.synonyms')}) do |h|
+ - h.td do
+ %div.d-flex
+ %div
+ - for synonym in @concept.synonym
+ = synonym
+ %div.synonym-change-request
+ = add_synonym_button
+ = remove_synonym_button
+
+
- unless @concept.definition.nil? || @concept.definition.empty?
- %tr
- %td{nowrap: ""}= t('ontology_details.concept.definitions')
- %td
- = dispaly_complex_text(@concept.definition)
+ - t.add_row({th: t('ontology_details.concept.definitions')}, {td:dispaly_complex_text(@concept.definition)})
+
- if @concept.obsolete?
- %tr
- %td{nowrap: ""}= t('ontology_details.concept.obsolete')
- %td
- true
+ - t.add_row({th: t('ontology_details.concept.obsolete')}, {td: 'true'})
+
- if skos?
- unless @concept.memberOf.nil? || @concept.memberOf.empty?
- %tr
- %td{nowrap: ""}= t('ontology_details.concept.member_of')
- %td
+ - t.add_row({th: t('ontology_details.concept.member_of')}) do |h|
+ - h.td do
%div.my-1
- @concept.memberOf.each do |v|
= raw get_link_for_collection_ajax(v, @ontology.acronym, '_blank')
+
- unless @concept.inScheme.nil? || @concept.inScheme.empty?
- %tr
- %td{nowrap: ""}= t('ontology_details.concept.in_schemes')
- %td
+ - t.add_row({th: t('ontology_details.concept.in_schemes')}) do |h|
+ - h.td do
%div.my-1
- @concept.inScheme.each do |v|
= raw get_link_for_scheme_ajax(v, @ontology.acronym, '_blank')
- %tr
- %td{nowrap: ""}= t('ontology_details.concept.type')
- %td
- = @concept.type
-
- - scheme_set = c.properties_set_by_keys(schemes_keys, c.concept_properties)
- - label_xl_set = c.properties_set_by_keys(label_xl_set, c.concept_properties)
- - c.section do
- = c.render_properties(scheme_set, c.concept_properties) do |v|
- - get_link_for_scheme_ajax(v, @ontology.acronym, '_blank')
- - c.section do
- = c.render_properties(label_xl_set, c.concept_properties) do |v|
- - get_link_for_label_xl_ajax(v, @ontology.acronym, @concept.id)
+
+ - t.add_row({th: t('ontology_details.concept.type')} , {td: @concept.type})
+
+
+ - c.add_sections(schemes_keys) do |v|
+ - get_link_for_scheme_ajax(v, @ontology.acronym, '_blank')
+
+ - c.add_sections(label_xl_set) do |v|
+ - get_link_for_label_xl_ajax(v, @ontology.acronym, @concept.id)
+
+
+
+
diff --git a/app/views/label_xl/show.html.haml b/app/views/label_xl/show.html.haml
index 7b94c4971..424b9e4e2 100644
--- a/app/views/label_xl/show.html.haml
+++ b/app/views/label_xl/show.html.haml
@@ -5,18 +5,7 @@
top_keys: %w[description comment],
bottom_keys: %w[disjoint subclass is_a has_part],
exclude_keys: []) do |c|
- - c.header do
- %tr
- %td.label
- ID
- %td
- %p
- = @label_xl["@id"]
- %tr
- %td{nowrap: ""} Preferred Name
- %td
- %p= get_label_xl_label(@label_xl)
- %tr
- %td{nowrap: ""} Type
- %td
- %p= @label_xl["@type"]
+ - c.header(stripped: true) do |t|
+ - t.add_row({th: 'ID'}, {td: @label_xl["@id"]})
+ - t.add_row({th: 'Preferred Name'}, {td: get_label_xl_label(@label_xl)})
+ - t.add_row({th: 'Type'}, {td: @label_xl["@type"]})
diff --git a/app/views/mappings/_count.html.haml b/app/views/mappings/_count.html.haml
index 149d59d7a..a0a244cec 100644
--- a/app/views/mappings/_count.html.haml
+++ b/app/views/mappings/_count.html.haml
@@ -1,19 +1,19 @@
-%table#mapping_count_table.zebra{cellpadding: "0", cellspacing: "0"}
- %thead
- %tr
- %th Ontology
- %th Mappings
- %tbody
- - if @mapping_counts.blank?
- %tr
- %td There are no mappings to or from this ontology
- %td
- - else
- - for mapping_count in @mapping_counts
- %tr
- %td
- %a.facebox{href: "/mappings/show_mappings?id=#{@ontology_acronym}&target=#{mapping_count[:target_ontology].id}&height=600&width=800"}= mapping_count[:target_ontology].name
- %td= number_with_delimiter(mapping_count[:count], delimiter: ',')
+= render TableComponent.new(id: 'mapping_count_table') do |t|
+ - t.header do |h|
+ - h.th {'Ontology'}
+ - h.th {'Mappings'}
+
+ - if @mapping_counts.blank?
+ - t.row do |r|
+ - r.td {'There are no mappings to or from this ontology'}
+ - r.td {' '}
+ - else
+ - @mapping_counts.each do |mapping_count|
+ - t.row do |r|
+ - r.td do
+ %a.facebox{href: "/mappings/show_mappings?id=#{@ontology_acronym}&target=#{mapping_count[:target_ontology].id}&height=600&width=800"}= mapping_count[:target_ontology].name
+ - r.td do
+ = number_with_delimiter(mapping_count[:count], delimiter: ',')
:javascript
$(document).ready(() => {
diff --git a/app/views/notes/_note_line.html.haml b/app/views/notes/_note_line.html.haml
index 77823dd57..ce50b99ba 100644
--- a/app/views/notes/_note_line.html.haml
+++ b/app/views/notes/_note_line.html.haml
@@ -1,29 +1,26 @@
-%tr{id: "#{note.id}_tr_#{parent_type}"}
- %td
+= render TableRowComponent.new(id: "#{note.id}_tr_#{parent_type}") do |row|
+ - row.td do
- if current_user_admin?
- alert_text = "Are you sure you want to delete the note ''" + (note.subject || '') + "'' created by " + note.creator.split('/')[-1] + "?
This action CAN NOT be undone!!!"
= button_to "Delete", notes_path(noteid: note.id, parent_type: parent_type), method: :delete, class:'btn btn-sm btn-link', form: {data: { turbo: true, turbo_confirm: alert_text, turbo_frame: '_top'}}
- %td
+ - row.td do
- note_link = "/ontologies/#{ontology_acronym}/notes/"
- note_link = "#{note_link}?noteid=#{CGI.escape(note.id)}"
= link_to_modal note.subject || note_link , note_link, id:"row_#{note.id}",
- class: "ont_notes_list_link notes_list_link",
- data: { show_modal_title_value: ""}
+ class: "ont_notes_list_link notes_list_link",
+ data: { show_modal_title_value: ""}
%span{:id => "#{note.id}_row_archived", :style => "font-size: x-small; color: grey;"}
- if note.archived
archived
- %td.d-none
- = note.subject
- %td.d-none
- = note.archived || "false"
- %td
+ - row.td do
= note.creator.split('/')[-1]
- %td
+
+ - row.td do
= note.proposal ? get_note_type_text(note.proposal.type) : "Comment"
- if parent_type.eql?('ontology')
- %td
+ - row.td do
- if note.relatedClass && note.relatedClass.length > 0
- %a{href: "/ontologies/#{ontology_acronym}?p=classes&conceptid=#{CGI.escape(note.relatedClass.first)}"}= note.relatedClass.first
- %td
+ %a{href: "/ontologies/#{ontology_acronym}?p=classes&conceptid=#{CGI.escape(note.relatedClass.first)}", 'data-turbo': 'false'}= note.relatedClass.first
+ - row.td do
= DateTime.parse(note.created).strftime("%Y-%m-%d")
\ No newline at end of file
diff --git a/app/views/notes/_notes.html.haml b/app/views/notes/_notes.html.haml
index d7a13e4a6..57b77791a 100644
--- a/app/views/notes/_notes.html.haml
+++ b/app/views/notes/_notes.html.haml
@@ -17,35 +17,21 @@
= render_alerts_container("notes_#{parent_type}_list_table_alerts")
.ont_notes_table_container
- %table.zebra.notes_ont_list_table{:id => "#{notes_table_id}", :style => "width: 100%;", :width => "100%"}
- %thead
- %tr
- %th
- Delete
- %th
- Subject
- %th.d-none
- Subject Sort
- %th.d-none
- Archive Sort
- %th
- Author
- %th
- Type
- - if parent_type.eql?('ontology')
- %th
- Class
- %th
- Created
- %tbody{id: "#{parent_type}_notes_table_content"}
- - if @notes.nil? || @notes.empty?
- %tr#ont_no_notes
- %td{colspan: colspan} No notes to display
- - (colspan-1).times.each do
- %td
- - else
- - @notes.each do |note|
- = render partial: 'notes/note_line', locals: {note: note, ontology_acronym: @ontology.acronym, parent_type: parent_type}
+ - cols = ['Action', 'Subject', 'Author', 'Type', (parent_type.eql?('ontology') ? 'Class' : nil),'Created'].compact
+ = render TableComponent.new(id:"#{parent_type}_notes") do |t|
+ - t.header do |row|
+ - row.create(*cols.map{|col| {th: col}})
+
+ - if @notes.nil? || @notes.empty?
+ - t.row do |row|
+ - row.td(colspan: colspan) do
+ %div.text-center
+ No notes to display
+
+ - else
+ - @notes.each do |note|
+ = render partial: 'notes/note_line', locals: {note: note, ontology_acronym: @ontology.acronym, parent_type: parent_type}
+
:javascript
jQuery(".ontologies.show").ready(function(){
jQuery("#hide_archived_ont").click(function(){
diff --git a/app/views/schemes/_scheme.html.haml b/app/views/schemes/_scheme.html.haml
index 91607bf91..2fcf310c9 100644
--- a/app/views/schemes/_scheme.html.haml
+++ b/app/views/schemes/_scheme.html.haml
@@ -5,19 +5,8 @@
top_keys: %w[description comment],
bottom_keys: %w[disjoint subclass is_a has_part],
exclude_keys: []) do |c|
- = c.header do
- %tr
- %td.label
- ID
- %td
- %p= scheme["@id"]
- %tr
- %td{nowrap: ""} Preferred Name
- %td
- %p= get_scheme_label(scheme)
- %tr
- %td.label
- Type
- %td
- %p= scheme["@type"]
+ - c.header(stripped: true) do |t|
+ - t.add_row({th: 'ID'} , {td: scheme["@id"]})
+ - t.add_row({th: 'Preferred Name'} , {td: get_scheme_label(scheme)})
+ - t.add_row({th: 'Type'} , {td: scheme["@type"]})
diff --git a/test/components/previews/concept_details_component_preview.rb b/test/components/previews/concept_details_component_preview.rb
new file mode 100644
index 000000000..3d486535a
--- /dev/null
+++ b/test/components/previews/concept_details_component_preview.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+class ConceptDetailsComponentPreview < ViewComponent::Preview
+ def default
+ properties = { links: nil,
+ context: nil,
+ "http://www.w3.org/2004/02/skos/core#narrower": ["http://opendata.inrae.fr/thesaurusINRAE/d_0101",
+ "http://opendata.inrae.fr/thesaurusINRAE/d_0103",
+ "http://opendata.inrae.fr/thesaurusINRAE/d_0102",
+ "http://opendata.inrae.fr/thesaurusINRAE/d_0104",
+ "http://opendata.inrae.fr/thesaurusINRAE/d_0105"],
+ "http://www.w3.org/1999/02/22-rdf-syntax-ns#type": ["http://www.w3.org/2004/02/skos/core#Concept",
+ "http://www.w3.org/2002/07/owl#NamedIndividual"],
+ "http://www.w3.org/2004/02/skos/core#topConceptOf": ["http://opendata.inrae.fr/thesaurusINRAE/thesaurusINRAE"],
+ "http://www.w3.org/2004/02/skos/core#prefLabel": ["01. ENVIRONMENT [domain]"],
+ "http://www.w3.org/2004/02/skos/core#inScheme": ["http://opendata.inrae.fr/thesaurusINRAE/thesaurusINRAE"],
+ "http://purl.org/dc/terms/modified": ["2021-02-24T15:25:56"]
+ }
+ schemes_keys = %w[hasTopConcept topConceptOf]
+ label_xl_set = %w[skos-xl#prefLabel skos-xl#altLabel skos-xl#hiddenLabel]
+ render ConceptDetailsComponent.new(id: 'concept-details', acronym: "Ontology",
+ properties: OpenStruct.new(properties),
+ top_keys: %w[description comment],
+ bottom_keys: %w[disjoint subclass is_a has_part],
+ exclude_keys: schemes_keys + label_xl_set + ['inScheme']) do |c|
+ c.header(stripped: true) do |table|
+ table.add_row({ th: 'ID' }, { td: "http://opendata.inrae.fr/thesaurusINRAE/d_1" })
+ table.add_row({ th: 'Preferred Name' }, { td: "01. ENVIRONMENT [domain]" })
+ table.add_row({ th: 'Type' }, { td: "http://www.w3.org/2004/02/skos/core#Concept" })
+ end
+ end
+ end
+end
diff --git a/test/components/previews/layout/table_component_preview.rb b/test/components/previews/layout/table_component_preview.rb
new file mode 100644
index 000000000..b38a7cd0f
--- /dev/null
+++ b/test/components/previews/layout/table_component_preview.rb
@@ -0,0 +1,45 @@
+# frozen_string_literal: true
+
+class Layout::TableComponentPreview < ViewComponent::Preview
+
+ include ActionView::Helpers::UrlHelper
+
+ def default
+ render TableComponent.new do |t|
+ table_content(t)
+ end
+ end
+
+ def stripped
+ render TableComponent.new(stripped: true) do |t|
+ table_content(t)
+ end
+ end
+
+ private
+
+ def table_content(t)
+ headers = 5.times.map { |i| "header #{i}" }
+ rows = 6.times.map { |row| 5.times.map { |i| "line #{row} :#{i} " } }
+
+ t.header do |h|
+ headers.each do |header|
+ h.th { header }
+ end
+ h.th { 'Action' }
+ end
+
+ rows.each do |row|
+ t.row do |r|
+ row.each do |col|
+ r.td { col }
+ end
+
+ r.td do
+ link_to('Edit', '', class: 'mr-3') + link_to('Delete', '')
+ end
+ end
+ end
+
+ end
+end