diff --git a/app/assets/images/icons/calendar.svg b/app/assets/images/icons/calendar.svg
new file mode 100644
index 0000000000..7ad6a2f7ac
--- /dev/null
+++ b/app/assets/images/icons/calendar.svg
@@ -0,0 +1,3 @@
+
diff --git a/app/assets/images/icons/list-tree.svg b/app/assets/images/icons/list-tree.svg
new file mode 100644
index 0000000000..eac310be4a
--- /dev/null
+++ b/app/assets/images/icons/list-tree.svg
@@ -0,0 +1,3 @@
+
diff --git a/app/assets/images/icons/list.svg b/app/assets/images/icons/list.svg
new file mode 100644
index 0000000000..4c1b3ded20
--- /dev/null
+++ b/app/assets/images/icons/list.svg
@@ -0,0 +1,6 @@
+
diff --git a/app/assets/images/list-tree.svg b/app/assets/images/list-tree.svg
deleted file mode 100644
index 4180dac32a..0000000000
--- a/app/assets/images/list-tree.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/app/assets/stylesheets/components/index.scss b/app/assets/stylesheets/components/index.scss
index 35a9b13920..09c2d57732 100644
--- a/app/assets/stylesheets/components/index.scss
+++ b/app/assets/stylesheets/components/index.scss
@@ -12,6 +12,9 @@
@import 'input_field';
@import 'file_input_loader';
@import 'text_area_field';
+@import 'tabs_container';
+@import 'pill_tabs_container';
+@import 'outline_tabs_container';
@import 'pill_button';
@import "switch";
@import "table";
diff --git a/app/assets/stylesheets/components/outline_tabs_container.scss b/app/assets/stylesheets/components/outline_tabs_container.scss
new file mode 100644
index 0000000000..76c390d92a
--- /dev/null
+++ b/app/assets/stylesheets/components/outline_tabs_container.scss
@@ -0,0 +1,27 @@
+
+.outline-tabs{
+ border: 1px solid rgba(0, 0, 0, 0.125);
+ border-radius: 0.25rem 0.25rem 0 0;
+ padding-top: 1rem;
+}
+.outline-tabs .tab-items .nav-item{
+ margin-right: 0;
+
+}
+
+.outline-tabs .tab-items .nav-item.active a{
+ color: var(--primary-color) !important;
+}
+
+.outline-tabs .nav-item .tab-link{
+ display: block;
+ padding: 0 1rem 0.2rem 1rem;
+}
+
+.outline-tabs + .tab-content {
+ .tab-pane{
+ border: 1px solid rgba(0, 0, 0, 0.125);
+ border-top: none ;
+ border-radius: 0 0 0.25rem 0.25rem;
+ }
+}
\ No newline at end of file
diff --git a/app/assets/stylesheets/components/pill_tabs_container.scss b/app/assets/stylesheets/components/pill_tabs_container.scss
new file mode 100644
index 0000000000..e03697544c
--- /dev/null
+++ b/app/assets/stylesheets/components/pill_tabs_container.scss
@@ -0,0 +1,22 @@
+.pill-tabs-container {
+ display: flex;
+ justify-content: space-between;
+}
+
+.pill-tabs-container .tab-items{
+ margin-bottom: 10px;
+}
+
+.pill-tabs-container .nav-item {
+ display: block;
+ padding: 0.2rem 1rem;
+}
+
+.pill-tabs-container .nav-item.active {
+ border-radius: 5px;
+ background-color: var(--primary-color);
+ color: white !important;
+ a {
+ color: white !important;
+ }
+}
\ No newline at end of file
diff --git a/app/assets/stylesheets/components/tabs_container.scss b/app/assets/stylesheets/components/tabs_container.scss
new file mode 100644
index 0000000000..87ef9291ce
--- /dev/null
+++ b/app/assets/stylesheets/components/tabs_container.scss
@@ -0,0 +1,56 @@
+.tabs-container {
+ border-bottom: 1px solid #DFDFDF;
+ display: flex;
+ justify-content: space-between;
+ & > div {
+ display: flex;
+ justify-content: space-between;
+ }
+}
+
+.tabs-container hr {
+ border: 1px solid #f3f3f3;
+ width: 100%;
+ margin: 0;
+}
+
+.tabs-container .tab-items {
+ display: flex;
+ margin: 0;
+ position: relative;
+}
+
+.tabs-container .tab-items div {
+ font-size: 16px;
+ font-weight: 400;
+ color: #5e5e5e;
+ margin-right: 50px;
+ cursor: pointer;
+ opacity: 60%;
+ transition: opacity 0.3s ease;
+
+ a {
+ color: #5e5e5e !important;
+ }
+}
+
+.tabs-container .tab-items div:hover {
+
+ opacity: 100%;
+}
+
+.tabs-container .tab-items div hr {
+ display: none;
+ margin-top: 10px;
+}
+
+.tabs-container .tab-items .active {
+ font-weight: 500;
+ opacity: 100%;
+}
+
+.tabs-container .tab-items .active hr {
+ display: block;
+ border: 1px solid var(--primary-color);
+ opacity: 100%;
+}
diff --git a/app/assets/stylesheets/concepts.scss b/app/assets/stylesheets/concepts.scss
index 87627bd5ce..783cf2097f 100644
--- a/app/assets/stylesheets/concepts.scss
+++ b/app/assets/stylesheets/concepts.scss
@@ -14,7 +14,7 @@
}
a.btn.btn-link {
- padding: 0;
+ padding: 0;
}
}
@@ -55,7 +55,7 @@ div.synonym-change-request button {
justify-content: space-between;
align-items: center;
}
-.concepts-tabs{
+.concepts-tabs{
display: flex;
justify-content: space-between;
width: 589px;
@@ -105,7 +105,7 @@ div.synonym-change-request button {
margin-top: 20px;
border-radius: 5px;
border: 1px solid #DFDFDF;
-
+
}
.concepts-raw-title{
display: flex;
@@ -119,6 +119,34 @@ div.synonym-change-request button {
.concepts-raw-title div{
padding: 10px 0px;
}
+
#details_content{
- margin-top: 15px;
+ border: none !important;
+}
+
+#details_content .card{
+ border-top: none !important;
+ border-top-left-radius: 0;
+ border-top-right-radius: 0;
+}
+
+#concept_browser{
+ .outline-tabs .tab-items{
+ width: 100%;
+ }
+ .outline-tabs .tab-items .nav-item {
+ flex: 1;
+ }
+ .outline-tabs .tab-items .nav-item a {
+ display: flex;
+ justify-content: center;
+ svg path {
+ fill: #5e5e5e !important;
+ }
+ }
+ .outline-tabs .tab-items .nav-item.active a {
+ svg path {
+ fill: var(--primary-color) !important;
+ }
+ }
}
\ No newline at end of file
diff --git a/app/assets/stylesheets/ontologies.scss b/app/assets/stylesheets/ontologies.scss
index 4de56daa7a..ffd00d9aaf 100644
--- a/app/assets/stylesheets/ontologies.scss
+++ b/app/assets/stylesheets/ontologies.scss
@@ -11,7 +11,6 @@ $ont-show-bg-color: #e9ecef;
}
.ontologies.show .gutter {
- background-color: rgba(0, 0, 0, 0.03);
background-repeat: no-repeat;
background-position: center;
@@ -271,4 +270,3 @@ $ont-show-bg-color: #e9ecef;
flex-direction: row;
}
-
diff --git a/app/components/rounded_button_component.rb b/app/components/rounded_button_component.rb
index 65a11dd0ae..47983fce1b 100644
--- a/app/components/rounded_button_component.rb
+++ b/app/components/rounded_button_component.rb
@@ -1,19 +1,20 @@
class RoundedButtonComponent < ViewComponent::Base
- def initialize(icon: "json.svg", link: "#", size: "small")
- @icon = icon
- @link = link
- @size = size
- end
+ def initialize(icon: "json.svg", link: "#", size: "small", target: '')
+ @icon = icon
+ @link = link
+ @size = size
+ @target = target
+ end
- def size
- case @size
- when "small"
- ["32px", "1", "16px"]
- when "medium"
- ["64px", "2", "32px"]
- when "big"
- ["100px", "2.5", "50px"]
- end
+ def size
+ case @size
+ when "small"
+ ["32px", "1", "16px"]
+ when "medium"
+ ["64px", "2", "32px"]
+ when "big"
+ ["100px", "2.5", "50px"]
end
+ end
end
\ No newline at end of file
diff --git a/app/components/rounded_button_component/rounded_button_component.html.haml b/app/components/rounded_button_component/rounded_button_component.html.haml
index 7eb803affe..4baa20df96 100644
--- a/app/components/rounded_button_component/rounded_button_component.html.haml
+++ b/app/components/rounded_button_component/rounded_button_component.html.haml
@@ -1,2 +1,2 @@
-%a.rounded-button{:href => @link, style: "height:"+size[0]+"; width:"+size[0]+"; border-radius:"+size[2]+";"}
+%a.rounded-button{:href => @link, style: "height:"+size[0]+"; width:"+size[0]+"; border-radius:"+size[2]+";", target:@target}
= inline_svg_tag @icon, style: "transform: scale("+size[1]+");"
diff --git a/app/components/tab_item_component.rb b/app/components/tab_item_component.rb
new file mode 100644
index 0000000000..b6612bb5be
--- /dev/null
+++ b/app/components/tab_item_component.rb
@@ -0,0 +1,51 @@
+# frozen_string_literal: true
+
+class TabItemComponent < ViewComponent::Base
+
+ include ActionView::Helpers::UrlHelper
+
+ def initialize(id: nil, title: nil, path: nil, page_name: '', selected: false)
+ super
+ @id = id
+ @title = title
+ @path = path
+ @page_name = page_name
+ @selected = selected
+ end
+
+ def selected_item?
+ @selected
+ end
+
+ def item_id
+ id.parameterize.underscore
+ end
+
+ def target_id
+ "#{item_id}_content"
+ end
+
+
+ def id
+ @title || @id
+ end
+
+ def title
+ @title&.humanize
+ end
+
+ def active_class
+ selected_item? ? 'active show' : ''
+ end
+
+ def call
+ if title && !title.empty?
+ link_to(title, @path, id: "#{item_id}_tab", class: "#{active_class} tab-link")
+ else
+ link_to(@path, id: "#{item_id}_tab", class: "#{active_class} tab-link") do
+ content
+ end
+ end
+ end
+
+end
diff --git a/app/components/tabs_container_component.rb b/app/components/tabs_container_component.rb
new file mode 100644
index 0000000000..bb9ecaa21c
--- /dev/null
+++ b/app/components/tabs_container_component.rb
@@ -0,0 +1,47 @@
+# frozen_string_literal: true
+
+class TabsContainerComponent < ViewComponent::Base
+
+ renders_many :items, TabItemComponent
+ renders_many :item_contents
+ renders_one :pinned_right
+
+ def initialize(id: '', url_parameter: nil, type: 'primary')
+ super
+ @url_parameter = url_parameter
+ @type = type
+ @id = id
+ end
+
+ def container_class
+ case @type
+ when 'primary'
+ 'tabs-container'
+ when 'outline'
+ 'tabs-container outline-tabs'
+ when 'pill'
+ 'pill-tabs-container'
+ else
+ 'tabs-container'
+ end
+ end
+
+ def item_target(item)
+ "##{@id}#{item.target_id}"
+ end
+
+ def item_content_id(item)
+ @id + item.target_id
+ end
+
+ def tabs_container_data(item)
+ {
+ toggle: 'tab',
+ target: item_target(item),
+ 'tab-id': item.id,
+ 'tab-title': item.title,
+ 'url-parameter': @url_parameter,
+ action: 'click->tabs-container#selectTab'
+ }
+ end
+end
diff --git a/app/components/tabs_container_component/tabs_container_component.html.haml b/app/components/tabs_container_component/tabs_container_component.html.haml
new file mode 100644
index 0000000000..2ee9f88186
--- /dev/null
+++ b/app/components/tabs_container_component/tabs_container_component.html.haml
@@ -0,0 +1,16 @@
+%div{data: {controller:'tabs-container'}, class: container_class}
+ .tab-items.nav
+ - items.each do |item|
+ %div{data: tabs_container_data(item), class: item.active_class + ' nav-item'}
+ = item
+ - unless @pill
+ %hr
+ - if pinned_right?
+ %div.d-flex.mx-1
+ = pinned_right
+
+.tab-content
+ - item_contents.each_with_index do |item_content, index|
+ %div.tab-pane{id: item_content_id(items[index]), class: items[index].active_class}
+ = item_content
+
diff --git a/app/components/tabs_container_component/tabs_container_component_controller.js b/app/components/tabs_container_component/tabs_container_component_controller.js
new file mode 100644
index 0000000000..9991b699f0
--- /dev/null
+++ b/app/components/tabs_container_component/tabs_container_component_controller.js
@@ -0,0 +1,43 @@
+import {Controller} from "@hotwired/stimulus";
+import {HistoryService} from "../../javascript/mixins/useHistory";
+
+export default class extends Controller {
+
+ connect() {
+ this.event = null
+ }
+
+
+ selectTab(event) {
+ this.event = event
+ if (this.#parameter()) {
+ this.#updateURL()
+ }
+ this.element.dispatchEvent(new CustomEvent("tab-selected", {
+ bubbles: true,
+ detail: {data: {selectedTab: this.#pageId()}}
+ }))
+ }
+
+ #pageId() {
+ return this.event.currentTarget.getAttribute("data-tab-id")
+ }
+
+ #title() {
+ return this.event.currentTarget.getAttribute("data-tab-title")
+ }
+
+ #parameter() {
+ return this.event.currentTarget.getAttribute("data-url-parameter")
+ }
+
+
+ #url() {
+ return `?${this.#parameter()}=${this.#pageId()}`
+ }
+
+ #updateURL() {
+ (new HistoryService()).pushState({[this.#parameter()]: this.#pageId()}, this.#title(), this.#url());
+ }
+
+}
diff --git a/app/helpers/ontologies_helper.rb b/app/helpers/ontologies_helper.rb
index b2706d9eb9..dfbcf251aa 100644
--- a/app/helpers/ontologies_helper.rb
+++ b/app/helpers/ontologies_helper.rb
@@ -457,7 +457,7 @@ def language_selector_tag(name)
end
end
else
- select_tag name, languages_options, class: 'custom-select', disabled: !ontology_data_section?, style: "visibility: #{ontology_data_section? ? 'visible' : 'hidden'}; margin-bottom: -10px;", data: {'ontology-viewer-tabs-target': 'languageSelector'}
+ select_tag name, languages_options, class: '', disabled: !ontology_data_section?, style: "visibility: #{ontology_data_section? ? 'visible' : 'hidden'}; border: none; outline: none;", data: {'ontology-viewer-tabs-target': 'languageSelector'}
end
end
diff --git a/app/javascript/component_controllers/index.js b/app/javascript/component_controllers/index.js
index b9968423b4..cb96f8b3e1 100644
--- a/app/javascript/component_controllers/index.js
+++ b/app/javascript/component_controllers/index.js
@@ -13,9 +13,13 @@ import Ontology_subscribe_button_component_controller
import Search_input_component_controller
from "../../components/search_input_component/search_input_component_controller";
+import Tabs_container_component_controller
+ from "../../components/tabs_container_component/tabs_container_component_controller";
+
application.register("turbo-modal", TurboModalController)
application.register("file-input", FileInputLoaderController)
application.register("select-input", Select_input_component_controller)
application.register("metadata-select", Metadata_selector_component_controller)
application.register("subscribe-notes", Ontology_subscribe_button_component_controller)
application.register("search-input", Search_input_component_controller)
+application.register("tabs-container", Tabs_container_component_controller)
diff --git a/app/javascript/controllers/ontology_viewer_tabs_controller.js b/app/javascript/controllers/ontology_viewer_tabs_controller.js
index f8cb2a3106..6ddf9b71bd 100644
--- a/app/javascript/controllers/ontology_viewer_tabs_controller.js
+++ b/app/javascript/controllers/ontology_viewer_tabs_controller.js
@@ -26,16 +26,9 @@ export default class extends Controller {
this.changeEvent.removeEventListener()
}
- selectTab(event) {
- this.#updateURL(event)
- }
-
- #updateURL(event){
- const page = event.target.getAttribute("data-bp-ont-page");
- const page_name = event.target.getAttribute("data-bp-ont-page-name");
-
- (new HistoryService()).pushState({p: page}, page_name + " | " + jQuery(document).data().bp.ont_viewer.org_site, "?p=" + page);
-
+ updateLanguageSelector(event) {
+ console.log('language selector update')
+ let page = event.detail.data.selectedTab
this.#disableLanguageSelector(page)
}
diff --git a/app/views/admin/index.html.haml b/app/views/admin/index.html.haml
index a67c026743..91b174eb52 100644
--- a/app/views/admin/index.html.haml
+++ b/app/views/admin/index.html.haml
@@ -13,27 +13,14 @@
%div.row
%div.col
- %ul.nav.nav-tabs{id: "admin-tabs", role: "tablist"}
- %li.nav-item
- =link_to("Site Administration", "#site-admin", id: "site-admin-tab", class: "nav-link active", role: "tab", data: { toggle: "tab" }, aria: { controls: "site-admin", selected: "true" })
- %li.nav-item
- =link_to("Ontology Administration", "#ontology-admin", id: "ontology-admin-tab", class: "nav-link", role: "tab", data: { toggle: "tab" }, aria: { controls: "ontology-admin", selected: "false" })
- %li.nav-item
- =link_to("Licensing", "#licensing", id: "licensing-admin-tab", class: "nav-link", role: "tab", data: { toggle: "tab", href: admin_licenses_path() }, aria: { controls: "licensing", selected: "false" })
- %li.nav-item
- =link_to("Users", "#users", id: "users-admin-tab", class: "nav-link", role: "tab", data: { toggle: "tab", href: users_path() }, aria: { controls: "users", selected: "false" })
- %li.nav-item
- =link_to("Metadata Administration", "#ontologies_metadata_curator", id: "ontologies_metadata_curator-admin-tab", class: "nav-link", role: "tab", data: { toggle: "tab"}, aria: { controls: "ontologies_metadata_curator", selected: "false" })
- %li.nav-item
- =link_to("Groups", "#groups", id: "groups-admin-tab", class: "nav-link", role: "tab", data: { toggle: "tab", href: "groups" }, aria: { controls: "groups", selected: "false" })
- %li.nav-item
- =link_to("Categories", "#categories", id: "categories-admin-tab", class: "nav-link", role: "tab", data: { toggle: "tab", href: "categories" }, aria: { controls: "categories", selected: "false" })
- %div#adminTabContent.tab-content
-
- -# Site Administration tab
- %div.tab-pane.active.show.fade{id: "site-admin", role: "tabpanel", aria: { labelledby: "site-admin-tab" }}
-
- -# Clear caches
+ - sections = ['Site Administration','Ontology Administration', 'Licensing', 'Users', 'Metadata Administration', 'Groups', 'Categories']
+ = render TabsContainerComponent.new do |t|
+ - sections.each do |section_title|
+ - t.item(title: section_title,
+ path: '',
+ selected: section_title.eql?(sections.first),
+ page_name: '')
+ - t.item_content do
%div#site-admin-clear-caches.my-5
%div.site-admin-page-header
CACHE MANAGEMENT
@@ -42,33 +29,27 @@
= link_to("Reset UI cache connection", "#", id: "reset_memcache_connection_action", class: "btn btn-outline-secondary btn-sm admin-action-item", role: "button")
= link_to("Flush GOO cache", "#", id: "flush_goo_cache_action", class: "btn btn-outline-secondary btn-sm admin-action-item", role: "button")
= link_to("Flush HTTP cache", "#", id: "flush_http_cache_action", class: "btn btn-outline-secondary btn-sm", role: "button")
-
- -# Check for updates
+
%div#site-admin-update-check.mb-5
%div.site-admin-page-header
VERSION MANAGEMENT
%dive.site-admin-page-section
= link_to("Check for updates", "#", id: "update_check_action", class: "btn btn-outline-secondary btn-sm", role: "button")
- -# View appliance ID
%div#site-admin-appliance-id.mb-5
%div.site-admin-page-header
APPLIANCE ID
%dive.site-admin-page-section
%div#appliance-id
%span
-
- -# Clear caches
+
%div#site-admin-clear-caches.my-5
%div.site-admin-page-header
MONITORING LINKS
%dive.site-admin-page-section
= link_to("Newrelic", "https://login.newrelic.com/login", target: '_blank', id: "newrelic_link", class: "btn btn-outline-secondary btn-sm admin-action-item", role: "button")
= link_to("StatusCake", "https://app.statuscake.com/Login", target: '_blank', id: "statuscake_link", class: "btn btn-outline-secondary btn-sm admin-action-item", role: "button")
-
-
- -# Ontology Administration tab
- %div.tab-pane.fade{id: "ontology-admin", role: "tabpanel", aria: { labelledby: "ontology-admin-tab" }}
+ - t.item_content do
%div.ontologies_list_container.mt-3
%table{:style => "float:left;"}
%tr
@@ -79,9 +60,8 @@
%span.ui-button-text{:class => "report_date_generated_button"}
%p.tab_description{:style => "clear:both;"}
%table#adminOntologies.zebra{:cellpadding => "0", :cellspacing => "0", :width => "100%"}
+ - t.item_content do
- -# Licensing tab
- %div.tab-pane.fade{id: "licensing", role: "tabpanel", aria: { labelledby: "licensing-admin-tab" }}
%div#renew-license-notice
%table.table.table-sm.table-bordered.mt-5#license-table
@@ -89,35 +69,26 @@
%tr
%th{scope: "col"} Licensed to
%th{scope: "col"} Appliance ID
- %th{scope: "col"} Valid till
+ %th{scope: "col"} Valid till
%th{scope: "col"} Days remaining
%tbody
%div.mb-5#renew-license-button
- = link_to("Renew license", new_admin_license_path(), class: "btn btn-primary", role: "button", remote: "true")
+ = link_to("Renew license", new_admin_license_path, class: "btn btn-primary", role: "button", remote: "true")
%div.mb-5#renew-license-form
-
- -# Users tab
- %div.tab-pane.fade{id: "users", role: "tabpanel", aria: { labelledby: "users-admin-tab" }}
+ - t.item_content do
%div.ontologies_list_container.mt-3
%table#adminUsers.zebra{:cellpadding => "0", :cellspacing => "0", :width => "100%"}
-
- -# metadata tab
- %div.tab-pane.fade{id: "ontologies_metadata_curator", role: "tabpanel", aria: { labelledby: "ontologies_metadata_curator-admin-tab" }}
+ - t.item_content do
= render partial: 'ontologies_metadata_curator/metadata_tab'
-
- -# Groups tab
- %div.tab-pane.fade{id: "groups", role: "tabpanel", aria: { labelledby: "groups-admin-tab" }}
+ - t.item_content do
%div.ontologies_list_container.mt-3
%table#adminGroups.zebra{:cellpadding => "0", :cellspacing => "0", :width => "100%"}
-
- -# Categories tab
- %div.tab-pane.fade{id: "categories", role: "tabpanel", aria: { labelledby: "categories-admin-tab" }}
+ - t.item_content do
%div.ontologies_list_container.mt-3
%table#adminCategories.zebra{:cellpadding => "0", :cellspacing => "0", :width => "100%"}
-
\ No newline at end of file
diff --git a/app/views/concepts/_show.html.haml b/app/views/concepts/_show.html.haml
index af69f8f2ef..1988ec9000 100644
--- a/app/views/concepts/_show.html.haml
+++ b/app/views/concepts/_show.html.haml
@@ -3,58 +3,62 @@
%div{:style => "padding: 100px 0; font-size: larger; font-weight: bold; text-align: center;"}
Use the "Jump To" to find a class and display details, visualization, notes, and mappings
- else
+ = render TabsContainerComponent.new(type:'outline') do |c|
+
+ - c.pinned_right do
+ - if $PURL_ENABLED
+ %div.mx-1
+ = link_to("#classPermalinkModal", class: "class-permalink nav-link", title: "Get a permanent link to this class", aria: {label: "Get a permanent link to this class"}, data: {toggle: "modal", current_purl: "#{@current_purl}"}) do
+ %i{class: "fas fa-link", aria: {hidden: "true"}}
+ %div
+ = render RoundedButtonComponent.new(link: "#{@ontology.id}/classes/#{escape(@concept.id)}?display=all&apikey=#{get_apikey}", target:'_blank')
+
+ - c.item(title: 'Details', path: '#details', selected: true)
- %ul.nav.tabs
- %li#details_top.nav-item
- %a.nav-link.active.py-1{:href => "#details" , data:{toggle: 'tab', target: '#details_content'}} Details
- unless skos?
- %li#instances_top.nav-item
- %a.nav-link.py-1{:href => "#instances" , data:{toggle: 'tab', target: '#instances_content'}}
- Instances
- (
- %span#instances_count
- )
- %li#visualization_top.nav-item
- %a.nav-link.py-1{:href => "#visualization", data:{toggle: 'tab', target: '#visualization_content'}} Visualization
- %li#notes_top.nav-item
- %a.nav-link.py-1{:href => "#notes", data:{toggle: 'tab', target: '#notes_content'}}
- Notes
- %span#note_count_wrapper
- (
- %span#note_count= @notes.length
- )
- %li#mappings_top.nav-item
- %a.nav-link.py-1{:href => "#mappings", data:{toggle: 'tab', target: '#mappings_content'}}
- #{concept_label_to_show(submission: @submission)} Mappings (
- %span#mapping_count= 'loading'
+ - c.item(id: 'instances', path: '#instances') do
+ Instances
+ (
+ %span#instances_count
+ )
+
+ - c.item(title: 'Visualization', path: '#visualization')
+
+ - c.item(id: 'notes', path: '#notes') do
+ Notes
+ %span#note_count_wrapper
+ (
+ %span#note_count= @notes.length
)
- %a.concepts-json{:href => "#{@ontology.id}/classes/#{escape(@concept.id)}?display=all&apikey=#{get_apikey}", target: '_blank'}
- = inline_svg_tag "json.svg"
+ - c.item(id: 'mappings', path: '#mappings') do
+ #{concept_label_to_show(submission: @submission)} Mappings (
+ %span#mapping_count= 'loading'
+ )
- if @enable_ontolobridge
- %li#request_term_top.nav-item
- %a.nav-link.py-1{:href => "#request_term", data:{toggle: 'tab', target: '#request_term'}}
- New Term Requests
- - if $PURL_ENABLED
- = link_to("#classPermalinkModal", class: "class-permalink nav-link", title: "Get a permanent link to this class", aria: {label: "Get a permanent link to this class"}, data: {toggle: "modal", current_purl: "#{@current_purl}"}) do
- %i{class: "fas fa-link", aria: {hidden: "true"}}
- #contents.tab-content
- #details_content.tab-pane.active.show
+ - c.item(title: ' New Term Requests', path: '#request_term')
+
+ - c.item_content do
= render :partial =>'/concepts/details'
+
- unless skos?
- #instances_content.tab-pane
+ - c.item_content do
= render :partial =>'instances/instances' , locals: {id: "class-instances-data-table"}
- #visualization_content.tab-pane
+ - c.item_content do
= render :partial =>'/concepts/biomixer'
- #notes_content.tab-pane
+
+ - c.item_content do
= render :partial =>'/notes/list'
- #mappings_content.tab-pane
+
+ - c.item_content do
= render TurboFrameComponent.new(id:'concept_mappings',
src:"/ajax/mappings/get_concept_table?ontologyid=#{@ontology.acronym}&conceptid=#{CGI.escape(@concept.id)}")
+
- if @enable_ontolobridge
- #request_term_content.tab-pane
+ - c.item_content do
= render :partial =>'/concepts/request_term'
+
:javascript
jQuery(document).ready(function(){
diff --git a/app/views/layouts/_ontology_viewer.html.haml b/app/views/layouts/_ontology_viewer.html.haml
index 7b7094dd67..5b826f3117 100644
--- a/app/views/layouts/_ontology_viewer.html.haml
+++ b/app/views/layouts/_ontology_viewer.html.haml
@@ -41,28 +41,26 @@
= render partial: 'kgcl_dialogs'
- %div.row.pt-md-3.pb-md-2
- %div.col
+ %div.pt-md-3.pb-md-2.p-2
+ %div
= render partial: 'layouts/ontology_viewer/header'
- %div.row.pb-4{data: {controller: 'ontology-viewer-tabs', 'ontology-viewer-tabs-language-sections-value': ontology_data_sections }}
- %div.col
+ %div.pb-4.p-2.bg-white{data: {controller: 'ontology-viewer-tabs', 'ontology-viewer-tabs-language-sections-value': ontology_data_sections }}
+ %div
- sections = sections_to_show
- %div.card
- %div.card-header
- %div{style: "display: flex; justify-content: space-between;"}
- %ul.nav.nav-tabs.card-header-tabs{id: "navbar-ontology", role: "tablist"}
- - sections.each do |section|
- %li.nav-item
- = link_to_section(section)
- %div
+ %div.ontologies-tabs-container{data:{action: 'tab-selected->ontology-viewer-tabs#updateLanguageSelector'}}
+ = render TabsContainerComponent.new(id: 'ontology_viewer', url_parameter: 'p') do |t|
+ - sections.each do |section_title|
+ - t.item(title: section_title,
+ path: ontology_path(@ontology.acronym, p: section_title),
+ selected: selected_section?(section_title),
+ page_name: ontology_viewer_page_name(@ontology.name, @concept&.prefLabel || '', section_title))
+ - t.pinned_right do
= language_selector_tag(:language_selector)
- %div.card-body
- %div.tab-content
- - sections.each do |section|
- %div.tab-pane{id: "ont_#{section}_content", class: selected_section?(section) ? 'active show' : '', data: section_data(section)}
- = language_selector_hidden_tag(section) if ontology_data_section?(section)
- = lazy_load_section(section) { yield }
+ - t.item_content do
+ %div.p-1{data: section_data(section_title)}
+ = language_selector_hidden_tag(section_title) if ontology_data_section?(section_title)
+ = lazy_load_section(section_title) { yield }
= render partial: "layouts/footer"
diff --git a/app/views/ontologies/concepts_browsers/_concepts_browser.html.haml b/app/views/ontologies/concepts_browsers/_concepts_browser.html.haml
index 1c4c5128c2..8f74659d2d 100644
--- a/app/views/ontologies/concepts_browsers/_concepts_browser.html.haml
+++ b/app/views/ontologies/concepts_browsers/_concepts_browser.html.haml
@@ -1,18 +1,25 @@
-%nav
- .nav.nav-tabs.text-center{:role => "tablist", style:"background-color: rgba(0, 0, 0, 0.03);"}
+%div#concept_browser
+ = render TabsContainerComponent.new(type:'outline') do |c|
+ - c.item(id: 'tree-tab', selected: default_sub_menu?) do
+ %span{title: 'Hierarchy view', 'data-controller': "tooltip"}
+ = inline_svg('icons/list-tree.svg', style:'width: 18px; height: 18px')
- %a#concepts-tree-tab.nav-item.nav-link.flex-grow-1.border-radius-0{"data-toggle" => "tab", :href => "#concepts-tree-container", title: 'Hierarchy view', 'data-controller': "tooltip", class: default_sub_menu_class}
- %img{src: asset_path('list-tree.svg') , style:'width: 25px; height: 25px'}
- if skos?
- %a#concepts-list-tab.nav-item.nav-link.flex-grow-1.border-radius-0{"data-toggle" => "tab", :href => "#concepts-list-container", title: 'Collection view', 'data-controller': "tooltip", class: sub_menu_active_class('list')}
- %i.fas.fa-list.text-dark{style:'font-size: 25px'}
- %a#concepts-date-sort-tab.nav-item.nav-link.flex-grow-1.border-radius-0{"data-toggle" => "tab", :href => "#concepts-date-sort-container", title: 'Date view', 'data-controller': "tooltip", class: sub_menu_active_class('date')}
- %i.far.fa-calendar-alt.text-dark{style:'font-size: 25px'}
-.tab-content.px-1.py-2
- #concepts-tree-container.tab-pane.fade{class: default_sub_menu_class}
- = render partial: 'ontologies/concepts_browsers/concepts_tree'
- - if skos?
- #concepts-list-container.tab-pane.fade{class: sub_menu_active_class('list')}
- = render partial: 'ontologies/concepts_browsers/concepts_list'
- #concepts-date-sort-container.tab-pane.fade{class: sub_menu_active_class('date')}
- = render partial: 'ontologies/concepts_browsers/concepts_date_sort'
\ No newline at end of file
+ - c.item(id: 'list-tab', selected: sub_menu_active?('list')) do
+ %span{title: 'Collection view', 'data-controller': "tooltip"}
+ = inline_svg('icons/list.svg', style:'width: 18px; height: 18px')
+
+ - c.item(id: 'date-tab', selected: sub_menu_active?('date')) do
+ %span{title: 'Date view', 'data-controller': "tooltip"}
+ = inline_svg('icons/calendar.svg', style:'width: 18px; height: 18px')
+
+ - c.item_content do
+ %div.p-1
+ = render partial: 'ontologies/concepts_browsers/concepts_tree'
+ - if skos?
+ - c.item_content do
+ %div.p-1
+ = render partial: 'ontologies/concepts_browsers/concepts_list'
+ - c.item_content do
+ %div.p-1
+ = render partial: 'ontologies/concepts_browsers/concepts_date_sort'
diff --git a/app/views/ontologies/sections/visualize.html.haml b/app/views/ontologies/sections/visualize.html.haml
index fcaa805f2a..3851db29de 100644
--- a/app/views/ontologies/sections/visualize.html.haml
+++ b/app/views/ontologies/sections/visualize.html.haml
@@ -5,9 +5,9 @@
- @enable_ontolobridge = !$NEW_TERM_REQUEST_ONTOLOGIES.nil? && $NEW_TERM_REQUEST_ONTOLOGIES.include?(@ontology.acronym)
%div.tooltip
%div#bd_content.bd_content.explore{data:{controller: 'container-splitter'}}
- %div.sidebar.d-flex.flex-column.mr-2.card{data:{'container-splitter-target': 'container'}}
+ %div.sidebar.d-flex.flex-column.p-1.mr-1{data:{'container-splitter-target': 'container'}}
= render partial: 'ontologies/concepts_browsers/concepts_browser'
- %div#concept_content.d-flex.flex-column.p-1.ml-2{data:{'container-splitter-target': 'container'}}
+ %div#concept_content.d-flex.flex-column.p-1.ml-1{data:{'container-splitter-target': 'container'}}
= render partial: 'concepts/show'
- form_for(:search, :url => {:controller =>'search',:action=>'fetch_results'},:html=>{:id=>'search_form'}) do |f|
diff --git a/test/components/previews/layout/tabs_container_component_preview.rb b/test/components/previews/layout/tabs_container_component_preview.rb
new file mode 100644
index 0000000000..b82e09f32a
--- /dev/null
+++ b/test/components/previews/layout/tabs_container_component_preview.rb
@@ -0,0 +1,78 @@
+class Layout::TabsContainerComponentPreview < ViewComponent::Preview
+
+
+ def default
+ render TabsContainerComponent.new do |c|
+ sections = ['section 1', 'section 2', 'section 3', 'section 4']
+
+ sections.each do |section_title|
+ c.item(title: section_title,
+ path: "#{section_title}path",
+ selected: section_title.eql?('section 2'),
+ page_name: "#{section_title}path")
+
+ c.item_content do
+ section_title
+ end
+ end
+
+ end
+ end
+
+ def pill
+ render TabsContainerComponent.new(type: 'pill') do |c|
+ sections = ['section 1', 'section 2', 'section 3', 'section 4']
+
+ sections.each do |section_title|
+ c.item(title: section_title,
+ path: "#{section_title}path",
+ selected: section_title.eql?('section 2'),
+ page_name: "#{section_title}path")
+
+ c.item_content do
+ section_title
+ end
+ end
+
+ end
+ end
+
+ def outline
+ render TabsContainerComponent.new(type: 'outline') do |c|
+ sections = ['section 1', 'section 2', 'section 3', 'section 4']
+
+ sections.each do |section_title|
+ c.item(title: section_title,
+ path: "#{section_title}path",
+ selected: section_title.eql?('section 2'),
+ page_name: "#{section_title}path")
+
+ c.item_content do
+ section_title
+ end
+ end
+
+ end
+ end
+
+ def with_action_links
+ render TabsContainerComponent.new do |c|
+ sections = ['section 1', 'section 2', 'section 3', 'section 4']
+
+ sections.each do |section_title|
+ c.item(title: section_title,
+ path: "#{section_title}path",
+ selected: section_title.eql?('section 2'),
+ page_name: "#{section_title}path")
+
+ c.item_content do
+ section_title
+ end
+ end
+ c.pinned_right do
+ RoundedButtonComponent.new(icon: 'check.svg').render_in(c) + ''.html_safe + RoundedButtonComponent.new.render_in(c)
+ end
+ end
+ end
+
+end
\ No newline at end of file