diff --git a/app/assets/images/icons/delete.svg b/app/assets/images/icons/delete.svg index 0c3ed5204..b2336ea6c 100644 --- a/app/assets/images/icons/delete.svg +++ b/app/assets/images/icons/delete.svg @@ -1,3 +1,3 @@ - + diff --git a/app/assets/images/icons/full-screen.svg b/app/assets/images/icons/full-screen.svg new file mode 100644 index 000000000..14c5e1e3b --- /dev/null +++ b/app/assets/images/icons/full-screen.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/images/json.svg b/app/assets/images/json.svg index e7f7e8898..a09e3aa45 100644 --- a/app/assets/images/json.svg +++ b/app/assets/images/json.svg @@ -1,3 +1,3 @@ - + \ No newline at end of file diff --git a/app/assets/stylesheets/bioportal.scss b/app/assets/stylesheets/bioportal.scss index 9d1ae3b4d..d55804aac 100644 --- a/app/assets/stylesheets/bioportal.scss +++ b/app/assets/stylesheets/bioportal.scss @@ -556,11 +556,15 @@ tr.mainresource td { margin-bottom: 1em; } -.feedback ul li, .enable-lists ul li { +.enable-lists ul li { list-style-position: outside; list-style-type: square; margin-left: 1.5em; } +.feedback ul li{ + list-style-position: outside; + margin-left: 1.5em; +} .enable-lists ul { margin-bottom: 15px; diff --git a/app/assets/stylesheets/browse.scss b/app/assets/stylesheets/browse.scss index bc031c672..51422a836 100644 --- a/app/assets/stylesheets/browse.scss +++ b/app/assets/stylesheets/browse.scss @@ -333,6 +333,10 @@ padding: 14px 20px; margin-bottom: 12px; box-shadow: rgba(100, 100, 111, 0.08) 0 7px 29px 0; + .switch-filter{ + justify-content: space-between; + margin-bottom: 23px; + } } diff --git a/app/assets/stylesheets/components/switch.scss b/app/assets/stylesheets/components/switch.scss index b5a91db4d..003474383 100644 --- a/app/assets/stylesheets/components/switch.scss +++ b/app/assets/stylesheets/components/switch.scss @@ -2,8 +2,7 @@ .switch-filter{ display:flex; align-items: center; - justify-content: space-between; - margin-bottom: 20px; + } .switch-filter > p, .switch-filter > div{ font-size: 16px; diff --git a/app/assets/stylesheets/components/tabs_container.scss b/app/assets/stylesheets/components/tabs_container.scss index 422a29872..707d79b19 100644 --- a/app/assets/stylesheets/components/tabs_container.scss +++ b/app/assets/stylesheets/components/tabs_container.scss @@ -55,3 +55,6 @@ border: 1px solid var(--primary-color); opacity: 100%; } +.container{ + overflow-x: auto; +} diff --git a/app/assets/stylesheets/nav_bar.scss b/app/assets/stylesheets/nav_bar.scss index 427389b82..ddf561962 100644 --- a/app/assets/stylesheets/nav_bar.scss +++ b/app/assets/stylesheets/nav_bar.scss @@ -174,6 +174,7 @@ .top-nav-ul.show-responsive { display: block; + text-decoration-style: none !important; } .nav-items.show-responsive { diff --git a/app/assets/stylesheets/summary.scss.erb b/app/assets/stylesheets/summary.scss.erb index d53e734f9..0c4811de9 100644 --- a/app/assets/stylesheets/summary.scss.erb +++ b/app/assets/stylesheets/summary.scss.erb @@ -161,7 +161,33 @@ text-align: right; } - +#networkContainer{ + transition: transform 0.3s; + } + +.active-fullscreen { + width: 100%; + height: 100vh; + position: fixed; + left: 0; + top: 0; + background-color: #ffffff; + z-index: 9999; +} +#fullscreen-button { + background-color: var(--primary-color); + -webkit-mask-image: url(asset-path('icons/full-screen.svg')); + mask-image: url(asset-path('icons/full-screen.svg')); + float: right; + position: relative; + bottom: 79px; + width: 32px; + height: 31px; + background-repeat: no-repeat!important; + background-position: 2px 2px; + right: 58px; + cursor: pointer; + } div.vis-network div.vis-navigation { div.vis-button.vis-up{ diff --git a/app/assets/stylesheets/upload_ontology.scss b/app/assets/stylesheets/upload_ontology.scss index 85f18aec8..aecdcd960 100644 --- a/app/assets/stylesheets/upload_ontology.scss +++ b/app/assets/stylesheets/upload_ontology.scss @@ -90,3 +90,9 @@ .upload-ontology-input-field-container .switch-filter p{ font-size: 12px !important; } +.edit-ontology-tab .switch-filter { + img{ + width: 15px; + height: 15px; + } +} \ No newline at end of file diff --git a/app/components/concept_details_component.rb b/app/components/concept_details_component.rb index 10eff50d5..16635e419 100644 --- a/app/components/concept_details_component.rb +++ b/app/components/concept_details_component.rb @@ -164,14 +164,25 @@ def remove_owl_notation(string) unless string.nil? strings = string.split(":") - if strings.size<2 - #return string.titleize + if strings.size < 2 + # return string.titleize return string else - #return strings[1].titleize + # return strings[1].titleize return strings[1] end end end + def convert_dates(hash) + hash.transform_values do |property| + if property[:key].to_s.include?("modified") || property[:key].to_s.include?("created") + value = property[:values].first + parsed_date = l(Date.parse(value), format: :monthfull_day_year.to_sym) rescue value + property[:values] = [parsed_date] + end + property + end + end + end diff --git a/app/components/concept_details_component/concept_details_component.html.haml b/app/components/concept_details_component/concept_details_component.html.haml index abd8b1c05..4b1d6015c 100644 --- a/app/components/concept_details_component/concept_details_component.html.haml +++ b/app/components/concept_details_component/concept_details_component.html.haml @@ -6,6 +6,7 @@ - if @bottom_keys.present? = render DropdownContainerComponent.new(title: 'Raw data', id: "accordion-#{@id}") do - top_set, leftover_set, bottom_set = filter_properties(@top_keys, @bottom_keys, @exclude_keys, prefix_properties(@concept_properties)) + - leftover_set = convert_dates(leftover_set) = render TableComponent.new(stripped: true) do |t| - row_hash_properties(top_set, @acronym).each do |row| diff --git a/app/components/dropdown_container_component.rb b/app/components/dropdown_container_component.rb index 3d785f85e..e06b3fa7a 100644 --- a/app/components/dropdown_container_component.rb +++ b/app/components/dropdown_container_component.rb @@ -2,10 +2,14 @@ class DropdownContainerComponent < ViewComponent::Base renders_one :empty_state - def initialize(title:, id:, tooltip:nil) + def initialize(title:, id:, tooltip:nil, is_open: false) super @title = title @id = id @tooltip = tooltip + @is_open = is_open + end + def open_class + @is_open ? "show" : "" end end diff --git a/app/components/dropdown_container_component/dropdown_container_component.html.haml b/app/components/dropdown_container_component/dropdown_container_component.html.haml index 11c0dd2ee..7b9d4965e 100644 --- a/app/components/dropdown_container_component/dropdown_container_component.html.haml +++ b/app/components/dropdown_container_component/dropdown_container_component.html.haml @@ -3,7 +3,7 @@ = render Display::HeaderComponent.new(text: @title, tooltip: @tooltip) = image_tag("summary/arrow-down.svg", class: 'ml-2') - .collapse{id: @id} + .collapse{id: @id, class: open_class} - if content && !content.empty? = content - else diff --git a/app/components/icon_with_tooltip_component.rb b/app/components/icon_with_tooltip_component.rb new file mode 100644 index 000000000..a5c0aa97a --- /dev/null +++ b/app/components/icon_with_tooltip_component.rb @@ -0,0 +1,28 @@ +class IconWithTooltipComponent < ViewComponent::Base + def initialize(icon: "", link: "#", size: "small", target: '', title: '', style: '') + @icon = icon + @link = link + @size = size + @target = target + @title = title + @style = style + end + + private + + def size + case @size + when "small" + ["32px", "1", "16px"] + when "medium" + ["45px", "1", "23px"] + when "big" + ["100px", "2.5", "50px"] + end + end + + def icon_with_tooltip_style + "font-size: 50px; line-height: 0.5; #{@style}" + end +end + \ No newline at end of file diff --git a/app/components/icon_with_tooltip_component/icon_with_tooltip_component.html.haml b/app/components/icon_with_tooltip_component/icon_with_tooltip_component.html.haml new file mode 100644 index 000000000..abd4eec46 --- /dev/null +++ b/app/components/icon_with_tooltip_component/icon_with_tooltip_component.html.haml @@ -0,0 +1,3 @@ +%a.icon-with-tooltip{href: @link, style: icon_with_tooltip_style, target: @target, title: @title, 'data-controller': 'tooltip'} + %span.icon + = inline_svg @icon diff --git a/app/components/input/input_field_component.rb b/app/components/input/input_field_component.rb index bed61a95f..b5f9cb88f 100644 --- a/app/components/input/input_field_component.rb +++ b/app/components/input/input_field_component.rb @@ -22,7 +22,7 @@ def error? end def help? - !@helper_text&.empty? + !@helper_text.blank? end def label? diff --git a/app/components/layout/reveal_component.rb b/app/components/layout/reveal_component.rb index f6211ffed..5e24fef0d 100644 --- a/app/components/layout/reveal_component.rb +++ b/app/components/layout/reveal_component.rb @@ -2,19 +2,19 @@ class Layout::RevealComponent < ViewComponent::Base renders_one :button + renders_many :containers - def initialize(init_show: false, show_condition: nil,hidden_class: 'd-none') + def initialize(selected: nil, possible_values: [], hidden_class: 'd-none', toggle: false) @hidden_class = hidden_class - @init_show = init_show - @show_condition = show_condition + @possible_values = possible_values + @selected = selected + @toggle = toggle end def container_data - out = { + { controller: 'reveal-component', 'reveal-component-hidden-class': @hidden_class } - out['reveal-component-condition-value'] = @show_condition if @show_condition - out end end diff --git a/app/components/layout/reveal_component/reveal_component.html.haml b/app/components/layout/reveal_component/reveal_component.html.haml index 747ba02ea..7e16ed5af 100644 --- a/app/components/layout/reveal_component/reveal_component.html.haml +++ b/app/components/layout/reveal_component/reveal_component.html.haml @@ -1,5 +1,6 @@ %div{data: container_data} - %div{'data-action': "change->reveal-component#toggle"} + %div{'data-action': @toggle ? "change->reveal-component#toggle" : "change->reveal-component#select"} = button - %div{'data-reveal-component-target': "item", class: @init_show ? '' : @hidden_class} - = content \ No newline at end of file + - containers.each_with_index do |c, i| + %div{'data-reveal-component-target': "item", 'data-value': @possible_values[i] , class: @possible_values[i].eql?(@selected) ? '' : @hidden_class} + = c \ No newline at end of file diff --git a/app/components/layout/reveal_component/reveal_component_controller.js b/app/components/layout/reveal_component/reveal_component_controller.js index e30df8d76..997f8a953 100644 --- a/app/components/layout/reveal_component/reveal_component_controller.js +++ b/app/components/layout/reveal_component/reveal_component_controller.js @@ -1,61 +1,63 @@ -import { Controller } from "@hotwired/stimulus" - -export default class extends Controller{ - static values = { - condition: String, - hiddenClass : {type: String, default: "d-none"} - } - - static targets = ["hideButton", "showButton", 'item' ] - - toggle(event) { - if (!this.conditionValue) { - this.#toggle(event) - } else if (this.#shown() && !this.#conditionChecked(event)) { - this.#toggle(event) - } else if (!this.#shown() && this.#conditionChecked(event)) { - this.#toggle(event) - } - } - - show(event){ - this.#getItems(event).classList.remove(this.hiddenClassValue) - this.hideButtonTarget.classList.remove(this.hiddenClassValue) - this.showButtonTarget.classList.add(this.hiddenClassValue) - } - hide(event){ - this.#getItems(event).classList.add(this.hiddenClassValue) - this.hideButtonTarget.classList.add(this.hiddenClassValue) - this.showButtonTarget.classList.remove(this.hiddenClassValue) - } - - - #conditionChecked(event) { - return this.conditionValue === event.target.value - } - - #shown() { - return !this.itemTargets[0].classList.contains(this.class); - } - - #toggle(event) { - this.#getItems(event).forEach((s) => { - s.classList.toggle(this.hiddenClassValue); - }); - } - - #ItemById(event){ - let button = event.target.closest("[data-id]"); - return document.getElementById(button.dataset.id); - } - #getItems(event){ - let items - if(this.hasItemTarget){ - items = this.itemTarget - } else { - items = [this.#ItemById(event)] - } - return items - } +import { Controller } from '@hotwired/stimulus' + +export default class extends Controller { + static values = { + hiddenClass: { type: String, default: 'd-none' } + } + + static targets = ['hideButton', 'showButton', 'item'] + + /* + Toggle all the items + */ + toggle (event) { + this.#getItems(event).forEach((s) => { + s.classList.toggle(this.hiddenClassValue) + }) + } + + /* + Hide all the items except the selected one + */ + select (event) { + let selectedValue = event.target.value + let items = this.#getItems(event) + items.forEach((s) => { + s.classList.add(this.hiddenClassValue) + }) + + items.forEach((s) => { + if (selectedValue === s.dataset.value) { + s.classList.remove(this.hiddenClassValue) + } + }) + } + + show (event) { + this.#getItems(event).forEach((s) => s.classList.remove(this.hiddenClassValue)) + this.hideButtonTarget.classList.remove(this.hiddenClassValue) + this.showButtonTarget.classList.add(this.hiddenClassValue) + } + + hide (event) { + this.#getItems(event).forEach((s) => s.classList.add(this.hiddenClassValue)) + this.hideButtonTarget.classList.add(this.hiddenClassValue) + this.showButtonTarget.classList.remove(this.hiddenClassValue) + } + + #ItemById (event) { + let button = event.target.closest('[data-id]') + return document.getElementById(button.dataset.id) + } + + #getItems (event) { + let items + if (this.hasItemTarget) { + items = this.itemTargets + } else { + items = [this.#ItemById(event)] + } + return items + } } \ No newline at end of file diff --git a/app/components/link_field_component/link_field_component.html.haml b/app/components/link_field_component/link_field_component.html.haml index 06e23212b..5b9fa3fff 100644 --- a/app/components/link_field_component/link_field_component.html.haml +++ b/app/components/link_field_component/link_field_component.html.haml @@ -1,6 +1,6 @@ - if internal_link? = render ChipButtonComponent.new(url: @value.to_s.sub("data.", ""), text: @raw ? @value : @value.to_s.split("/").last, type: "clickable") - elsif @value.to_s =~ /\A#{URI::regexp(%w[http https])}\z/ - = render ChipButtonComponent.new(url: @value.to_s, text: @value.to_s, type: "clickable") + = render ChipButtonComponent.new(url: @value.to_s, text: @value.to_s, type: "clickable", target: "_blank") - else = render ChipButtonComponent.new( text: @value.to_s, type: "static") \ No newline at end of file diff --git a/app/components/summary_section_component.rb b/app/components/summary_section_component.rb index 0ca33932f..7f87dc123 100644 --- a/app/components/summary_section_component.rb +++ b/app/components/summary_section_component.rb @@ -3,15 +3,21 @@ class SummarySectionComponent < ViewComponent::Base renders_many :action_links - def initialize(title: , link: nil, link_title: nil, show_card: true) + def initialize(title: , link: nil, link_title: nil, show_card: true, service_link: nil) super @title = title @link = link @link_title = link_title @show_card = show_card + @service_link = service_link end def show_card? @show_card end + + def show_icon? + !@service_link.nil? + end + end diff --git a/app/components/summary_section_component/summary_section_component.html.haml b/app/components/summary_section_component/summary_section_component.html.haml index c43356866..8e93b55c6 100644 --- a/app/components/summary_section_component/summary_section_component.html.haml +++ b/app/components/summary_section_component/summary_section_component.html.haml @@ -5,7 +5,8 @@ %span = link_to(@link, target: "_blank") do = render Display::InfoTooltipComponent.new(text: @link_title) - + - if show_icon? + = render IconWithTooltipComponent.new(icon: "json.svg",link: @service_link, target: '_blank', title: 'Go to API', size:'small', style: 'line-height: 0; margin-top: 3px;margin-left: 6px;') - if action_links? %span = render Layout::HorizontalListComponent.new do |l| diff --git a/app/components/switch_input_component.rb b/app/components/switch_input_component.rb index ce0fd259c..450bfcfca 100644 --- a/app/components/switch_input_component.rb +++ b/app/components/switch_input_component.rb @@ -3,7 +3,7 @@ class SwitchInputComponent < ViewComponent::Base - def initialize(id:, name: , label: '', value: '', checked: false, boolean_switch: false, style: nil) + def initialize(id:, name: , label: '', value: '', checked: false, boolean_switch: false, style: nil, help: nil) super @id = id @name = name @@ -12,6 +12,7 @@ def initialize(id:, name: , label: '', value: '', checked: false, boolean_switch @checked = checked @boolean_switch = boolean_switch @style = style + @help = help end def boolean_switch_action diff --git a/app/components/switch_input_component/switch_input_component.html.haml b/app/components/switch_input_component/switch_input_component.html.haml index 51af0ecac..4cb85767c 100644 --- a/app/components/switch_input_component/switch_input_component.html.haml +++ b/app/components/switch_input_component/switch_input_component.html.haml @@ -5,4 +5,8 @@ = hidden_field_tag @name, @value %label.switch{for: check_box_id} = check_box_tag check_box_name, @value, @checked, class: '', id: check_box_id, onChange: "#{boolean_switch_action}" - %span.slider \ No newline at end of file + %span.slider +- if @help + %div.upload-ontology-desc + = @help + \ No newline at end of file diff --git a/app/controllers/concerns/submission_filter.rb b/app/controllers/concerns/submission_filter.rb index 1c0ecedf0..a5144e198 100644 --- a/app/controllers/concerns/submission_filter.rb +++ b/app/controllers/concerns/submission_filter.rb @@ -192,10 +192,10 @@ def ontology_filters_init(categories, groups) @formats = [['All formats', ''], 'OBO', 'OWL', 'SKOS', 'UMLS'] @sorts_options = [ ['Sort by name', 'ontology_name'], - ['Sort by class count', 'metrics_classes'], + ['Sort by classes count', 'metrics_classes'], ['Sort by instances/concepts count', 'metrics_individuals'], - ['Sort by upload date', 'creationDate'], - ['Sort by release date', 'released'], + ['Sort by submitted date', 'creationDate'], + ['Sort by creation date', 'released'], ['Sort by FAIR score', 'fair'], ['Sort by popularity', 'visits'], ['Sort by notes', 'notes'], diff --git a/app/controllers/ontologies_controller.rb b/app/controllers/ontologies_controller.rb index f6469e280..0193593b2 100644 --- a/app/controllers/ontologies_controller.rb +++ b/app/controllers/ontologies_controller.rb @@ -56,7 +56,7 @@ def ontologies_filter end ] + update_filters_counts - streams =if params[:page].nil? + streams = if params[:page].nil? [ prepend('ontologies_list_container', partial: 'ontologies/browser/ontologies'), prepend('ontologies_list_container') { @@ -157,6 +157,7 @@ def mappings def new @ontology = LinkedData::Client::Models::Ontology.new @submission = LinkedData::Client::Models::OntologySubmission.new + @submission.hasOntologyLanguage = 'OWL' @ontologies = LinkedData::Client::Models::Ontology.all(include: 'acronym', include_views: true, display_links: false, display_context: false) @categories = LinkedData::Client::Models::Category.all @groups = LinkedData::Client::Models::Group.all @@ -209,7 +210,6 @@ def collections end end - def sparql if request.xhr? render partial: 'ontologies/sections/sparql', layout: false @@ -217,6 +217,7 @@ def sparql render partial: 'ontologies/sections/sparql', layout: 'ontology_viewer' end end + # GET /ontologies/ACRONYM # GET /ontologies/1.xml def show @@ -262,8 +263,7 @@ def show # Get the latest submission (not necessarily the latest 'ready' submission) - @submission_latest = @ontology.explore.latest_submission(include: 'all', invalidate_cache: invalidate_cache?) rescue @ontology.explore.latest_submission(include: '') - + @submission_latest = @ontology.explore.latest_submission(include: 'all', invalidate_cache: invalidate_cache?) rescue @ontology.explore.latest_submission(include: '') if !helpers.submission_ready?(@submission_latest) && params[:p].present? && data_pages.include?(params[:p].to_s) redirect_to(ontology_path(params[:ontology]), status: :temporary_redirect) and return @@ -280,15 +280,15 @@ def show params[:p] = 'classes' redirect_to "/ontologies/#{params[:ontology]}#{params_string_for_redirect(params)}", status: :moved_permanently when 'classes' - self.classes #rescue self.summary + self.classes # rescue self.summary when 'mappings' - self.mappings #rescue self.summary + self.mappings # rescue self.summary when 'notes' - self.notes #rescue self.summary + self.notes # rescue self.summary when 'widgets' - self.widgets #rescue self.summary + self.widgets # rescue self.summary when 'properties' - self.properties #rescue self.summary + self.properties # rescue self.summary when 'summary' self.summary when 'instances' @@ -326,7 +326,7 @@ def summary @view_decorators = @views.map { |view| ViewDecorator.new(view, view_context) } @ontology_relations_data = ontology_relations_data - category_attributes = submission_metadata.group_by{|x| x['category']}.transform_values{|x| x.map{|attr| attr['attribute']} } + category_attributes = submission_metadata.group_by { |x| x['category'] }.transform_values { |x| x.map { |attr| attr['attribute'] } } @relations_array_display = @relations_array.map do |relation| attr = relation.split(':').last ["#{helpers.attr_label(attr, attr_metadata: helpers.attr_metadata(attr), show_tooltip: false)}(#{relation})", @@ -377,8 +377,8 @@ def subscriptions end count = helpers.count_subscriptions(params[:ontology_id]) - render inline: helpers.turbo_frame_tag('subscribe_button') { - render_to_string(OntologySubscribeButtonComponent.new(id: '', ontology_id: ontology_id, subscribed: subscribed, user_id: user_id, count: count, link: link), layout: nil) + render inline: helpers.turbo_frame_tag('subscribe_button') { + render_to_string(OntologySubscribeButtonComponent.new(id: '', ontology_id: ontology_id, subscribed: subscribed, user_id: user_id, count: count, link: link), layout: nil) } end @@ -409,19 +409,17 @@ def show_licenses @metadata = submission_metadata @ontology = LinkedData::Client::Models::Ontology.find_by_acronym(params[:id]).first - @licenses= %w[hasLicense morePermissions copyrightHolder useGuidelines] + @licenses = %w[hasLicense morePermissions copyrightHolder useGuidelines] @submission_latest = @ontology.explore.latest_submission(include: @licenses.join(",")) render partial: 'ontologies/sections/licenses' end - def ajax_ontologies + def ajax_ontologies render json: LinkedData::Client::Models::Ontology.all(include_views: true, display: 'acronym,name', display_links: false, display_context: false) end - - def metrics @ontology = LinkedData::Client::Models::Ontology.find_by_acronym(params[:ontology_id]).first @metrics = @ontology.explore.metrics(display_context: false, display_links: false) @@ -435,7 +433,7 @@ def metrics_evolution # Retrieve submissions in descending submissionId order (should be reverse chronological order) @submissions = @ontology.explore.submissions({ include: "metrics" }) - .sort { |a, b| a.submissionId.to_i <=> b.submissionId.to_i }.reverse || [] + .sort { |a, b| a.submissionId.to_i <=> b.submissionId.to_i }.reverse || [] metrics = @submissions.map { |s| s.metrics } @@ -447,10 +445,11 @@ def metrics_evolution end private + def get_views(ontology) views = ontology.explore.views || [] - views.select!{ |view| view.access?(session[:user]) } - views.sort{ |a,b| a.acronym.downcase <=> b.acronym.downcase } + views.select! { |view| view.access?(session[:user]) } + views.sort { |a, b| a.acronym.downcase <=> b.acronym.downcase } end def ontology_relations_data(sub = @submission_latest) @@ -458,7 +457,7 @@ def ontology_relations_data(sub = @submission_latest) @relations_array = ["omv:useImports", "door:isAlignedTo", "door:ontologyRelatedTo", "omv:isBackwardCompatibleWith", "omv:isIncompatibleWith", "door:comesFromTheSameDomain", "door:similarTo", "door:explanationEvolution", "voaf:generalizes", "door:hasDisparateModelling", "dct:hasPart", "voaf:usedBy", "schema:workTranslation", "schema:translationOfWork"] - return if sub.nil? + return if sub.nil? ont = sub.ontology # Get ontology relations between each other (ex: STY isAlignedTo GO) @@ -475,9 +474,13 @@ def ontology_relations_data(sub = @submission_latest) target_in_portal = false target_ont = nil # if we find our portal URL in the ontology URL, then we just keep the ACRONYM to try to get the ontology. - if relation_value.include?(portal_name) + if relation_value.include?(helpers.portal_name.downcase) relation_value = relation_value.split('/').last target_ont = LinkedData::Client::Models::Ontology.find_by_acronym(relation_value).first + end + + # Use acronym to get ontology from the portal + if target_ont target_id = target_ont.acronym target_in_portal = true end @@ -488,6 +491,7 @@ def ontology_relations_data(sub = @submission_latest) ontology_relations_array end + def properties_hash_values(properties, sub: @submission_latest, custom_labels: {}) return {} if sub.nil? @@ -498,7 +502,7 @@ def get_metrics_hash metrics_hash = {} # TODO: Metrics do not return for views on the backend, need to enable include_views param there @metrics = LinkedData::Client::Models::Metrics.all(include_views: true) - @metrics.each {|m| metrics_hash[m.links['ontology']] = m } + @metrics.each { |m| metrics_hash[m.links['ontology']] = m } return metrics_hash end diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 507078a0e..874fb3492 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -573,6 +573,7 @@ def prefix_properties(concept_properties) modified_properties end + def prefix_property_url(key_string, key = nil) namespace_key, _ = RESOLVE_NAMESPACE.find { |_, value| key_string.include?(value) } diff --git a/app/helpers/components_helper.rb b/app/helpers/components_helper.rb index c1aa0e1fb..78e06cbe8 100644 --- a/app/helpers/components_helper.rb +++ b/app/helpers/components_helper.rb @@ -104,8 +104,8 @@ def properties_card(title, tooltip, properties, &block) end end - def properties_dropdown(id, title, tooltip, properties, &block) - render DropdownContainerComponent.new(title: title, id: id, tooltip: tooltip) do |d| + def properties_dropdown(id, title, tooltip, properties, is_open: false, &block) + render DropdownContainerComponent.new(title: title, id: id, tooltip: tooltip, is_open: is_open) do |d| d.empty_state do properties_string = properties.keys[0..4].map { |key| "#{attr_label(key, attr_metadata: attr_metadata(key), show_tooltip: false)}" }.join(', ') + '... ' if properties empty_state_message "The fields #{properties_string} are empty" diff --git a/app/helpers/fair_score_helper.rb b/app/helpers/fair_score_helper.rb index 4c2c5309f..7025a91b1 100644 --- a/app/helpers/fair_score_helper.rb +++ b/app/helpers/fair_score_helper.rb @@ -32,11 +32,6 @@ def get_fair_combined_score(ontologies_acronyms, apikey = user_apikey) get_fairness_json(ontologies_acronyms, apikey)['combinedScores'] end - def fairness_link - link_to(get_fairness_service_url, id: "fairness-service-url", target: "_blank", "aria-label": t("get_json_version"), title: t("get_json_version")) do - tag.img(src: asset_path('json.svg'), "aria-hidden" => "true", style: "margin-left: 0.5rem; width: 18px; margin-bottom: 4px;") - end - end def create_fair_scores_data(fair_scores, count = nil) @@ -130,5 +125,10 @@ def get_name_with_out_dot(name) def print_score(score) number_with_precision(score, precision: 2, strip_insignificant_zeros: true) end + + def fairness_link(style = '') + custom_style = "font-size: 50px; line-height: 0.5; margin-left: 6px; #{style}".strip + render IconWithTooltipComponent.new(icon: "json.svg",link: get_fairness_service_url, target: '_blank', title: 'Go to API', size:'small', style: custom_style) + end end diff --git a/app/helpers/inputs_helper.rb b/app/helpers/inputs_helper.rb index 0130ecc2f..30a235817 100644 --- a/app/helpers/inputs_helper.rb +++ b/app/helpers/inputs_helper.rb @@ -25,8 +25,8 @@ def check_input(id:, name:, value:, label: '', checked: false, &block) end end - def switch_input(id:, name:, label:, checked: false, value: '', boolean_switch: false, style: nil) - render SwitchInputComponent.new(id: id, name: name, label: label, checked: checked, value: value, boolean_switch: boolean_switch, style: style) + def switch_input(id:, name:, label:, checked: false, value: '', boolean_switch: false, style: nil, help: nil) + render SwitchInputComponent.new(id: id, name: name, label: label, checked: checked, value: value, boolean_switch: boolean_switch, style: style, help: help) end def url_input(name:, value:, label: nil, help: nil) diff --git a/app/helpers/ontologies_helper.rb b/app/helpers/ontologies_helper.rb index 3a75d358a..2253d1409 100644 --- a/app/helpers/ontologies_helper.rb +++ b/app/helpers/ontologies_helper.rb @@ -529,7 +529,7 @@ def ontology_icon_links(links, submission_latest) content_tag(:span, data: {controller:"tooltip" } , title: title) do link_to(inline_svg("#{icon}.svg", width: "32", height: '32'), - Array(value).first || '', link_options) + Array(value).first || '', link_options.merge(target: '_blank')) end end.join.html_safe end @@ -656,6 +656,25 @@ def ontology_pull_location? !(@submission.pullLocation.nil? || @submission.pullLocation.empty?) end + def generate_link_title + inside_color = 'var(--primary-color)' + outside_color = '#007bff' + + inside_span = content_tag(:span, "#{portal_name}", style: "color: #{inside_color} !important;") + outside_span = content_tag(:span, 'outside', style: "color: #{outside_color};") + + link_title = "Relation with other ontologies either in #{inside_span} or #{outside_span}".html_safe + end + + + def edit_button(link:, title: ) + render IconWithTooltipComponent.new(icon: "edit.svg",link: link, target: '_blank', title: title) + end + + def service_button(link:, title: ) + render IconWithTooltipComponent.new(icon: "json.svg",link: link, target: '_blank', title: title) + end + private def submission_languages(submission = @submission) diff --git a/app/helpers/submission_inputs_helper.rb b/app/helpers/submission_inputs_helper.rb index 90c52a5a4..97f3e0f15 100644 --- a/app/helpers/submission_inputs_helper.rb +++ b/app/helpers/submission_inputs_helper.rb @@ -52,14 +52,13 @@ def required? end # @param attr_key String - def attribute_input(attr_key, long_text: false, label: nil, show_tooltip: true, max_date: nil) + def attribute_input(attr_key, long_text: false, label: nil, show_tooltip: true, max_date: nil, help: nil) attr = SubmissionMetadataInput.new(attribute_key: attr_key, submission: @submission, label: label, attr_metadata: attr_metadata(attr_key)) - if attr.type?('Agent') if attr.type?('list') - generate_list_agent_input(attr) + generate_list_agent_input(attr, helper_text: help) else generate_agent_input(attr) end @@ -76,24 +75,24 @@ def attribute_input(attr_key, long_text: false, label: nil, show_tooltip: true, elsif enforce_values?(attr) if attr.type?('list') - generate_select_input(attr, multiple: true) + generate_select_input(attr, multiple: true, help_text: help) elsif attr.type?('boolean') - generate_boolean_input(attr) + generate_boolean_input(attr, help: help) else - generate_select_input(attr) + generate_select_input(attr, help_text: help) end elsif attr.type?('isOntology') generate_select_input(attr, multiple: attr['enforce'].include?('list')) elsif attr.type?('uri') - generate_url_input(attr) + generate_url_input(attr, helper_text: help) elsif attr.type?('boolean') - generate_boolean_input(attr) + generate_boolean_input(attr, help: help) else # If input a simple text name = attr.name label = attr_header_label(attr, show_tooltip: show_tooltip) if attr.type?('list') - generate_list_text_input(attr) + generate_list_text_input(attr, helper_text: help, long_text: long_text) elsif attr.metadata['attribute'].to_s.eql?('URI') url_input(name: name, label: label, value: @submission.URI) elsif long_text @@ -101,7 +100,7 @@ def attribute_input(attr_key, long_text: false, label: nil, show_tooltip: true, value: attr.values) else text_input(name: name, label: label, - value: attr.values) + value: attr.values, help: help) end end @@ -140,17 +139,64 @@ def ontology_categories_input(ontology = @ontology, categories = @categories) end end + def ontology_skos_language_help + content_tag(:div, class: 'upload-ontology-desc has_ontology_language_input') do + link = link_to('Please refer to the documentation for more details.', "https://doc.jonquetlab.lirmm.fr/share/618372fb-a852-4f3e-8e9f-8b07ebc053e6", target: "_blank") + text = <<-EOS + SKOS vocabularies submitted to #{portal_name} shall follow a few constraints (e.g., contain a minimum of one skos:ConceptScheme also typed as owl:Ontology) + and top concept assertion. #{link} + EOS + text.html_safe + end + end + + def ontology_obo_language_help + content_tag(:div, class: 'upload-ontology-desc has_ontology_language_input') do + link = link_to('the OBOinOWL parser.', "#", target: "_blank") + text = <<-EOS + OBO ontologies submitted to #{portal_name} will be parsed by the OWL-API which integrates #{link} + The resulting RDF triples will then be loaded in #{portal_name} triple-store. + EOS + text.html_safe + end + end + + def ontology_owl_language_help + content_tag(:div, class: 'upload-ontology-desc has_ontology_language_input') do + link = link_to('the Protégé ', "https://protege.stanford.edu/", target: "_blank") + text = <<-EOS + OWL ontologies submitted to #{portal_name} will be parsed by the OWL-API. An easy way to verify if your ontology will parse is to open it with + #{link} + software which does use the same component. + EOS + text.html_safe + end + end + + def ontology_umls_language_help + content_tag(:div, class: 'upload-ontology-desc has_ontology_language_input') do + link = link_to('by the UMLS2RDF tool.', "#", target: "_blank") + text = <<-EOS + UMLS-RRF resources are usually produced #{link} + EOS + text.html_safe + end + end + def has_ontology_language_input(submission = @submission) - render Layout::RevealComponent.new(init_show: submission.hasOntologyLanguage&.eql?('SKOS'), show_condition: 'SKOS') do |c| + render(Layout::RevealComponent.new(possible_values: %w[SKOS OBO UMLS OWL], selected: @submission.hasOntologyLanguage)) do |c| c.button do attribute_input("hasOntologyLanguage") end - content_tag(:div, class: "upload-ontology-desc") do - content_tag(:div) do - "SKOS vocabularies submitted to BioPortal must contain a minimum of one concept scheme and top concept assertion. Please - refer to the NCBO wiki for a more #{link_to(ExternalLinkTextComponent.new(text: 'detailed explanation').call, "#seethewiki")} with examples.".html_safe - end - end + + c.container { ontology_skos_language_help } + + c.container { ontology_obo_language_help } + + c.container { ontology_umls_language_help } + + c.container { ontology_owl_language_help } + end end @@ -175,28 +221,33 @@ def ontology_visibility_input(ontology = @ontology) @user_select_list.sort! { |a, b| a[1].downcase <=> b[1].downcase } end - render(Layout::RevealComponent.new(init_show: ontology.viewingRestriction&.eql?('private'), show_condition: 'private')) do |c| + render(Layout::RevealComponent.new(possible_values: %w[private public], selected: ontology.viewingRestriction)) do |c| c.button do select_input(label: "Visibility", name: "ontology[viewingRestriction]", required: true, values: %w[public private], selected: ontology.viewingRestriction) end - content_tag(:div, class: 'upload-ontology-input-field-container') do - select_input(label: "Add or remove accounts that are allowed to see this ontology in #{portal_name}.", name: "ontology[acl]", values: @user_select_list, selected: ontology.acl, multiple: true) + + c.container do + content_tag(:div, class: 'upload-ontology-input-field-container') do + select_input(label: "Add or remove accounts that are allowed to see this ontology in #{portal_name}.", name: "ontology[acl]", values: @user_select_list, selected: ontology.acl, multiple: true) + end end end end def ontology_view_of_input(ontology = @ontology) - render Layout::RevealComponent.new(init_show: ontology.view?) do |c| + render Layout::RevealComponent.new(selected: !ontology.view?, toggle: true) do |c| c.button do content_tag(:span, class: 'd-flex') do switch_input(id: 'ontology_isView', name: 'ontology[isView]', label: 'Is this ontology a view of another ontology?', checked: ontology.view?, style: 'font-size: 14px;') end - end - content_tag(:div) do - render partial: "shared/ontology_picker_single", locals: { placeholder: "", field_name: "viewOf", selected: ontology.viewOf } + c.container do + content_tag(:div) do + render partial: "shared/ontology_picker_single", locals: { placeholder: "", field_name: "viewOf", selected: ontology.viewOf } + end + end end end end @@ -289,8 +340,8 @@ def generate_agent_input(attr) end end - def generate_list_agent_input(attr) - render Input::InputFieldComponent.new(name: '', error_message: attribute_error(attr.metadata['attribute'])) do + def generate_list_agent_input(attr, helper_text: nil) + render Input::InputFieldComponent.new(name: '', error_message: attribute_error(attr.metadata['attribute']), helper_text: helper_text) do render NestedAgentSearchInputComponent.new(label: attr_header_label(attr), agents: attr.values, agent_type: agent_type(attr.metadata), @@ -317,10 +368,10 @@ def generate_date_input(attr, max_date: nil) def generate_textarea_input(attr) text_input(name: attr.name, - value: attr.values) + value: attr.values, helper_text: nil) end - def generate_select_input(attr, multiple: false) + def generate_select_input(attr, multiple: false, help_text: nil) name = attr.name label = attr_header_label(attr) metadata_values, select_values = selected_values(attr, enforced_values(attr)) @@ -332,11 +383,11 @@ def generate_select_input(attr, multiple: false) select_input(name: name, label: label, values: select_values, selected: metadata_values, multiple: multiple, required: attr.required?, - open_to_add: open_to_add_metadata?(attr.attr_key)) + open_to_add: open_to_add_metadata?(attr.attr_key), help: help_text) end - def generate_list_field_input(attr, name, label, values, &block) - render Input::InputFieldComponent.new(name: '', error_message: attribute_error(attr.attr)) do + def generate_list_field_input(attr, name, label, values, helper_text: nil, &block) + render Input::InputFieldComponent.new(name: '', error_message: attribute_error(attr.attr), helper_text: helper_text) do render NestedFormInputsComponent.new do |c| c.header do label @@ -359,7 +410,7 @@ def generate_list_field_input(attr, name, label, values, &block) end - def generate_url_input(attr) + def generate_url_input(attr, helper_text: nil) label = attr_header_label(attr) values = attr.values name = attr.name @@ -369,7 +420,7 @@ def generate_url_input(attr) if is_relation generate_ontology_select_input(name, label, values, true) else - generate_list_field_input(attr, name, label, values) do |value, row_name, id| + generate_list_field_input(attr, name, label, values, helper_text: helper_text) do |value, row_name, id| url_input(label: '', name: row_name, value: value) end end @@ -377,7 +428,7 @@ def generate_url_input(attr) if is_relation generate_ontology_select_input(name, label, values, false) else - url_input(label: label, name: name, value: values) + url_input(label: label, name: name, value: values, help: helper_text) end end end @@ -399,23 +450,27 @@ def generate_ontology_select_input(name, label, selected, multiple) open_to_add: true) end - def generate_list_text_input(attr) + def generate_list_text_input(attr, helper_text: nil, long_text: false) label = attr_header_label(attr) values = attr.values || [''] name = attr.name - generate_list_field_input(attr, name, label, values) do |value, row_name, id| - text_input(label: '', name: row_name, value: value) + + generate_list_field_input(attr, name, label, values, helper_text: helper_text) do |value, row_name, id| + if long_text + text_area_tag(row_name, value, class: 'input-field-component', label: '') + else + text_input(label: '', name: row_name, value: value) + end end end - def generate_boolean_input(attr) + def generate_boolean_input(attr, help: nil) value = attr.values value = value.to_s unless value.nil? name = attr.name - content_tag(:div, class: 'd-flex') do + content_tag(:div) do switch_input(id: name, name: name, label: attr_header_label(attr), checked: value.eql?('true'), value: value, - boolean_switch: true, - style: 'font-size: 14px;') + boolean_switch: true, style: 'font-size: 14px;', help: help) end end diff --git a/app/helpers/submissions_helper.rb b/app/helpers/submissions_helper.rb index ba4aa9da0..aaa2bd55f 100644 --- a/app/helpers/submissions_helper.rb +++ b/app/helpers/submissions_helper.rb @@ -2,17 +2,71 @@ module SubmissionsHelper def metadata_help_link content_tag(:div, class: 'edit-ontology-desc') do html = content_tag(:div) do - content_tag(:div, 'Please fill in basic general information about your ontology.') + - content_tag(:span, 'AgroPortal will automatically extract metadata properties declared for the owl:Ontology object in the source file, ') + + content_tag(:div, 'Edit the metadata of your ontology here.') + + content_tag(:span, "Some of these values are used by #{portal_name} functionalities, includng for FAIRness assessment. ") + + content_tag(:span) do + link_to('See guidelines and recommendations for metadata here.', Rails.configuration.settings.links[:metadata_help], target: "_blank") + end + end + + html.html_safe + end + end + + def metadata_license_help_link + content_tag(:div, class: 'edit-ontology-desc') do + html = content_tag(:div) do + content_tag(:span, " #{portal_name} requires an URI for the license. If you do not find your choice here, ") + + content_tag(:span) do + link_to('Please pick up an URI from here.', "https://rdflicense.linkeddata.es/", target: "_blank") + end + end + html.html_safe + end + end + + def metadata_deprecated_help + content_tag(:div, style: 'edit-ontology-desc') do + html = content_tag(:div) do + content_tag(:div, " An ontology with status retired shall necessarily be also deprecated, but not the opposite.") + end + html.html_safe + end + end + + def metadata_knownUsage_help + content_tag(:div, class: 'edit-ontology-desc') do + html = content_tag(:div) do + content_tag(:span, 'Consider also declaring ') + content_tag(:span, style: 'width: 10px; height: 10px') do - link_to(render(ExternalLinkTextComponent.new(text: 'see guidelines and recommendations for metadata here:')), Rails.configuration.settings.links[:metadata_help], target: "_blank") + link_to('the projects that are using the ontology.', "/projects/new", target: "_blank") end end + html.html_safe + end + end + + def metadata_help_creator + content_tag(:div, class: 'edit-ontology-desc') do + html = content_tag(:div, style: 'text-align: center; margin-top: 56px;') do + content_tag(:span, "The following properties take for value an 'agent' in #{portal_name} (either a person or an organization). These agents are shared over all the ontologies and suggested with autocompletion if they already exist. Editing an agent here will change it to all the ontologies that agent is involved in.") + end html.html_safe end end + def metadata_version_help + content_tag(:div, class: 'edit-ontology-desc') do + html = content_tag(:div) do + content_tag(:span, 'For more information on how to encode versionning information in an ontology, see ') + + content_tag(:span, style: 'width: 10px; height: 10px') do + link_to('guidelines and recommendations.', "https://hal.science/hal-04094847", target: "_blank") + end + end + html.html_safe + end + end def ontology_submission_id_label(acronym, submission_id) [acronym, submission_id].join('#') @@ -164,10 +218,8 @@ def submission_editable_properties end end - - def attribute_infos(attr_label) - submission_metadata.select{ |attr_hash| attr_hash["attribute"].to_s.eql?(attr_label) }.first + submission_metadata.select { |attr_hash| attr_hash["attribute"].to_s.eql?(attr_label) }.first end def object_name(acronym = @ontology.acronym, submissionId = @submission.submissionId) @@ -190,20 +242,18 @@ def render_submission_inputs(frame_id) output += ontology_name_input end - if selected_attribute?('hasOntologyLanguage') output += has_ontology_language_input end if selected_attribute?('categories') - output += ontology_categories_input + output += ontology_categories_input end if selected_attribute?('groups') - output += ontology_groups_input + output += ontology_groups_input end - if selected_attribute?('administeredBy') output += ontology_administered_by_input end @@ -219,6 +269,7 @@ def render_submission_inputs(frame_id) @submission.contact = [] unless @submission.contact && @submission.contact.size > 0 contact_input(label: 'Contacts', name: '') end + output += metadata_help_creator end if selected_attribute?('viewingRestriction') @@ -227,36 +278,74 @@ def render_submission_inputs(frame_id) end end - if selected_attribute?('viewOf') output += attribute_form_group_container('viewOf') do ontology_view_of_input end end - reject_metadata = %w[abstract description uploadFilePath contact pullLocation hasOntologyLanguage] + reject_metadata = %w[abstract description uploadFilePath contact pullLocation hasOntologyLanguage hasLicense bugDatabase knownUsage version notes deprecated status] label = inline_save? ? '' : nil if selected_attribute?('abstract') output += attribute_form_group_container('abstract') do - raw attribute_input('abstract',long_text: true, label: label) + raw attribute_input('abstract', long_text: true, label: label) end end if selected_attribute?('description') output += attribute_form_group_container('description') do - raw attribute_input('description',long_text: true, label: label) + raw attribute_input('description', long_text: true, label: label) end end - submission_metadata.reject { |attr| reject_metadata.include?(attr['attribute']) || !selected_attribute?(attr['attribute']) }.each do |attr| - output += attribute_form_group_container(attr['attribute']) do - raw attribute_input(attr['attribute'], label: label) + if selected_attribute?('hasLicense') + output += attribute_form_group_container('hasLicense') do + raw attribute_input('hasLicense', help: metadata_license_help_link) end end + if selected_attribute?('bugDatabase') + output += attribute_form_group_container('bugDatabase') do + raw attribute_input('bugDatabase', help: 'Some ontology feedback and notes features are only possible if a GitHub repository is informed.') + end + end + if selected_attribute?('knownUsage') + output += attribute_form_group_container('knownUsage') do + raw attribute_input('knownUsage', help: metadata_knownUsage_help) + end + end + if selected_attribute?('version') + output += attribute_form_group_container('version') do + raw attribute_input('version', help: metadata_version_help) + end + end + + if selected_attribute?('notes') + output += attribute_form_group_container('notes') do + raw attribute_input('notes', long_text: true) + end + end + + if selected_attribute?('status') + output += attribute_form_group_container('status') do + raw attribute_input('status') + end + end + + if selected_attribute?('deprecated') + output += attribute_form_group_container('deprecated') do + raw attribute_input('deprecated', help: metadata_deprecated_help) + end + end + + submission_metadata.reject { |attr| reject_metadata.include?(attr['attribute']) || !selected_attribute?(attr['attribute']) }.each do |attr| + output += attribute_form_group_container(attr['attribute']) do + raw attribute_input(attr['attribute'], label: label) + end + end render TurboFrameComponent.new(id: frame_id) do output.html_safe diff --git a/app/javascript/controllers/ontology_relations_network_controller.js b/app/javascript/controllers/ontology_relations_network_controller.js index 7043a8384..75ea02909 100644 --- a/app/javascript/controllers/ontology_relations_network_controller.js +++ b/app/javascript/controllers/ontology_relations_network_controller.js @@ -111,7 +111,6 @@ export default class extends Controller { const options = { autoResize: true, - height: networkHeight, groups: { useDefaultGroups: true, myGroupId: { @@ -165,5 +164,26 @@ export default class extends Controller { // initialize your network! const network = new Network(container, data, options); network.fit(); + // Add a button click event listener + var fullscreenButton = document.getElementById('fullscreen-button'); + fullscreenButton.addEventListener('click', function () { + toggleFullScreen(container); + }); + + // Function to toggle full screen mode + function toggleFullScreen(element) { + var networkContainer = document.getElementById('networkContainer'); + + // check to existance of element + if (networkContainer) { + var parentElement = networkContainer.parentNode; + + // add style background: + parentElement.style.backgroundColor = 'white'; + } + networkContainer.parentNode.classList.toggle('active-fullscreen'); + networkContainer.style.height = "100%"; + networkContainer.style.width = "100%"; + } } } diff --git a/app/views/admin/index.html.haml b/app/views/admin/index.html.haml index 7a3d863d0..31b683f16 100644 --- a/app/views/admin/index.html.haml +++ b/app/views/admin/index.html.haml @@ -37,17 +37,15 @@ %p.tab_description{:style => "clear:both;"} %table#adminOntologies.zebra{:cellpadding => "0", :cellspacing => "0", :width => "100%"} - t.item_content do - %div#renew-license-notice - - %table.table.table-sm.table-bordered.mt-5#license-table - %thead - %tr - %th{scope: "col"} Licensed to - %th{scope: "col"} Appliance ID - %th{scope: "col"} Valid till - %th{scope: "col"} Days remaining - %tbody + %table.table.table-sm.table-bordered.mt-5#license-table + %thead + %tr + %th{scope: "col"} Licensed to + %th{scope: "col"} Appliance ID + %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") diff --git a/app/views/fair_score/_fair_service_header.html.haml b/app/views/fair_score/_fair_service_header.html.haml index c4dd1e462..9f2125695 100644 --- a/app/views/fair_score/_fair_service_header.html.haml +++ b/app/views/fair_score/_fair_service_header.html.haml @@ -3,4 +3,5 @@ = beta_badge %span = render Display::InfoTooltipComponent.new(text: t("view_fair_scores_definitions")) - = fairness_link \ No newline at end of file +%span{style: 'vertical-align: bottom; margin-left: -5px;'} + = fairness_link('vertical-align: middle;') \ No newline at end of file diff --git a/app/views/home/index.html.haml b/app/views/home/index.html.haml index 5685a43ec..b150d2094 100644 --- a/app/views/home/index.html.haml +++ b/app/views/home/index.html.haml @@ -84,7 +84,7 @@ %div.align-items %h4.margin-items= t('home.fairness') = render Display::InfoTooltipComponent.new(text: "You are seing the average scores for all the public ontologies in AgroPortal. FAIR scores are computed with the O'FAIRe methodology. More details here: https://github.com/agroportal/fairness") - = fairness_link + = fairness_link('margin-bottom: 6px; vertical-align: top;') %hr.home-section-line/ .home-card.home-fair-scores %div.fair-scores-badge-section diff --git a/app/views/ontologies/_fairs_score.html.haml b/app/views/ontologies/_fairs_score.html.haml index 2c0a05757..cbeba7bd2 100644 --- a/app/views/ontologies/_fairs_score.html.haml +++ b/app/views/ontologies/_fairs_score.html.haml @@ -10,7 +10,7 @@ "/ajax/fair_score/html/?ontologies=#{@ontology.acronym}", class: "btn", id:'fair-details-link', - data: { show_modal_title_value: "FAIRness assessment questions", show_modal_size_value: 'modal-xl' }, + data: { show_modal_title_value: "O'FAIRe FAIRness assessment questions", show_modal_size_value: 'modal-xl' }, ) - else %p.font-italic= "We are still collecting data for #{@ontology.acronym}" diff --git a/app/views/ontologies/new.html.haml b/app/views/ontologies/new.html.haml index dd3f2251a..577224376 100644 --- a/app/views/ontologies/new.html.haml +++ b/app/views/ontologies/new.html.haml @@ -28,24 +28,17 @@ = attribute_input('description', long_text: true) - if @is_update_ontology .upload-ontology-input-field-container{id: "submissionnotes_from_group_input"} - = attribute_input("notes", label: 'Change notes') + = attribute_input("notes", label: 'Change notes', long_text: true) .upload-ontology-field-container - = render Layout::RevealComponent.new(init_show: @submission.hasOntologyLanguage&.eql?('SKOS'), show_condition: 'SKOS') do |c| - - c.button do - = attribute_input("hasOntologyLanguage") - .upload-ontology-desc - %div - SKOS vocabularies submitted to BioPortal must contain a minimum of one concept scheme and top concept assertion. Please - refer to the NCBO wiki for a more - = link_to ExternalLinkTextComponent.new(text: 'detailed explanation').call, "#seethewiki" - with examples. + = has_ontology_language_input .upload-ontology-field-container.mt-3 - = render Layout::RevealComponent.new(init_show: @submission.status&.eql?('retired'), show_condition: 'retired') do |c| + = render Layout::RevealComponent.new(selected: @submission.status, possible_values: ['retired']) do |c| - c.button do = attribute_input("status") - .upload-ontology-field-container - - @submission.valid = nil unless @submission.status&.eql?('retired') - = attribute_input("valid") + - c.container do + .upload-ontology-field-container + - @submission.valid = nil unless @submission.status&.eql?('retired') + = attribute_input("valid") .upload-ontology-field-container = render partial: 'ontologies/submission_location_form' diff --git a/app/views/ontologies/sections/_metadata.html.haml b/app/views/ontologies/sections/_metadata.html.haml index 28c35b509..75b14e9fa 100755 --- a/app/views/ontologies/sections/_metadata.html.haml +++ b/app/views/ontologies/sections/_metadata.html.haml @@ -25,12 +25,15 @@ = properties_dropdown('link','Other links','Metadata properties that highlight the links enabling access to datasets, downloading semantic resources, etc', @links_properties) do |values| = horizontal_list_container(values) do |v| = render LinkFieldComponent.new(value: v, raw: true) - = properties_dropdown('projects_section','Projects and usage information','Details pertaining to the utilization of the ontology.', nil) do |c| - c.row do = projects_field(@projects) - properties_list_component(c, @projects_properties) - + :javascript + var projectsUrl = document.location.hash + if (projectsUrl == "#projects_section"){ + document.querySelector("[data-target='#projects_section']")?.click() + } = properties_dropdown('methodology','Methodology and provenance', 'Metadata properties primarily encompass the design, methods, and actions to create the ontology. This includes elements such as the tools and software employed by the creator of the ontology during its configuration.', @methodology_properties) = properties_dropdown('community','Community', 'Metadata properties primarily encompass the design, methods, and actions to create the ontology. This includes elements such as the tools and software employed by the creator of the ontology during its configuration.', nil ) do |c| - properties_list_component(c, @community_properties) diff --git a/app/views/ontologies/sections/metadata/_ontology_fairness_section.html.haml b/app/views/ontologies/sections/metadata/_ontology_fairness_section.html.haml index 550776961..f74e2aee4 100644 --- a/app/views/ontologies/sections/metadata/_ontology_fairness_section.html.haml +++ b/app/views/ontologies/sections/metadata/_ontology_fairness_section.html.haml @@ -8,7 +8,7 @@ %div.ont-section-toolbar.justify-content-between.flex-row-reverse %div.align-items-start .btn.btn-primary.rounded-pill.right-button - .span Total score : #{@fair_scores_data[:score]} ( #{@fair_scores_data[:normalizedScore]}% ) + .span{ style: 'cursor: default;' } Total score : #{@fair_scores_data[:score]} ( #{@fair_scores_data[:normalizedScore]}% ) %div#fair-score-charts-container = render partial: "fairs_score" diff --git a/app/views/ontologies/sections/metadata/_ontology_metrics_section.html.haml b/app/views/ontologies/sections/metadata/_ontology_metrics_section.html.haml index 068e502b1..fd609fef2 100644 --- a/app/views/ontologies/sections/metadata/_ontology_metrics_section.html.haml +++ b/app/views/ontologies/sections/metadata/_ontology_metrics_section.html.haml @@ -1,4 +1,4 @@ -= render SummarySectionComponent.new(title: "Metrics" , link: Rails.configuration.settings.links[:metrics], link_title: "Information and evolution diagrams about metrics and other measurements of the ontology.", show_card: false) do |s| += render SummarySectionComponent.new(title: "Metrics" , link: Rails.configuration.settings.links[:metrics], link_title: "Information and evolution diagrams about metrics and other measurements of the ontology.", show_card: false, service_link: "#{@ontology.id}/metrics?display=all") do |s| - s.action_link do = link_to_modal '', ontology_path(@ontology.acronym) + "/metrics", class: "metrics-item", title: "See all the metrics of #{@ontology.acronym}", diff --git a/app/views/ontologies/sections/metadata/_ontology_relations_network.html.haml b/app/views/ontologies/sections/metadata/_ontology_relations_network.html.haml index 61eeb2131..458042a53 100644 --- a/app/views/ontologies/sections/metadata/_ontology_relations_network.html.haml +++ b/app/views/ontologies/sections/metadata/_ontology_relations_network.html.haml @@ -1,5 +1,5 @@ - unless @ontology_relations_data.nil? || @ontology_relations_data.empty? - = render SummarySectionComponent.new(title: 'Ontology relations network') do + = render SummarySectionComponent.new(title: 'Ontology relations network', link: "", link_title: generate_link_title) do %div.d-flex.flex-column.justify-content-center{data: {controller: "ontology-relations-network", "ontology-relations-network-data-value": @ontology_relations_data.to_json.html_safe }} %button.btn.btn-link.m-2{'data-toggle': "collapse",'data-target': "#ontologyRelations"} %span= t("landscape.filter_network") @@ -10,4 +10,5 @@ %div{:style => "width: 100%;"} %div#networkContainer{:style => "height: 465px; width: 100%;", "data-ontology-relations-network-target": "container" } - %div#ontologyNetwork \ No newline at end of file + %div#ontologyNetwork + %button#fullscreen-button \ No newline at end of file diff --git a/app/views/ontologies/sections/metadata/_ontology_submissions_section.html.haml b/app/views/ontologies/sections/metadata/_ontology_submissions_section.html.haml index 6a27ebb1c..a4dfc5d02 100644 --- a/app/views/ontologies/sections/metadata/_ontology_submissions_section.html.haml +++ b/app/views/ontologies/sections/metadata/_ontology_submissions_section.html.haml @@ -1,2 +1,2 @@ -= render SummarySectionComponent.new(title: 'Submissions', link: "", link_title: "Set of all the files that have been submitted to #{portal_name}. Each previous metadata record is accessible but only the content of the latest parsed file is accessible via #{portal_name} services") do |s| += render SummarySectionComponent.new(title: 'Submissions', link: "", link_title: "Set of all the files that have been submitted to #{portal_name}. Each previous metadata record is accessible but only the content of the latest parsed file is accessible via #{portal_name} services", service_link: "#{@ontology.id}/submissions?display=all") do |s| = render TurboFrameComponent.new(id: 'ontology_submissions', src: ontology_submissions_path(@ontology.acronym, invalidate_cache: params[:invalidate_cache])) \ No newline at end of file diff --git a/app/views/ontologies/submit_success.html.haml b/app/views/ontologies/submit_success.html.haml index 7e042d164..d3ec9b11c 100644 --- a/app/views/ontologies/submit_success.html.haml +++ b/app/views/ontologies/submit_success.html.haml @@ -16,7 +16,7 @@ We will now put your ontology in the queue to be processed. Please keep in mind that it may take up to several hours before #{$SITE} users will be able to explore and search your ontology. %p - When your ontology is ready for viewing, you will receive an email notiifcation and it will be available here: + When your ontology is ready for viewing, you will receive an email notification and it will be available here: = link_to ontology_url(@ontology.acronym), ontology_path(@ontology.acronym) %p If you have any questions or problems, please email the #{$SITE} support team at: diff --git a/app/views/properties/_show.html.haml b/app/views/properties/_show.html.haml index 9ed56a565..209109d51 100644 --- a/app/views/properties/_show.html.haml +++ b/app/views/properties/_show.html.haml @@ -10,6 +10,6 @@ exclude_keys: []) do |c| - c.header(stripped: true) do |t| - t.add_row({th: 'ID'}, {td: c.concept_properties[:id][:values]}) if c.concept_properties[:id][:values].present? - - t.add_row({th: 'Labels'}, {td: c.concept_properties[:prefLabel][:values]}) if c.concept_properties[:prefLabel][:values].present? + - t.add_row({th: 'Prefered name'}, {td: c.concept_properties[:prefLabel][:values]}) if c.concept_properties[:prefLabel][:values].present? - t.add_row({th: 'Definitions'}, {td: c.concept_properties[:definition][:values].join(', ')}) if c.concept_properties[:definition][:values].present? - t.add_row({th: 'Parent'}, {td: c.concept_properties[:parents][:values].join(', ')}) if c.concept_properties[:parents][:values].present? diff --git a/app/views/submissions/_submissions.html.haml b/app/views/submissions/_submissions.html.haml index 9c67073b6..f3e3f8151 100644 --- a/app/views/submissions/_submissions.html.haml +++ b/app/views/submissions/_submissions.html.haml @@ -21,45 +21,43 @@ = attr_label("creationDate", "Submitted", show_tooltip: false) - unless @ont_restricted - header.th do - %div.align-middle - Downloads - - if @ontology.admin?(session[:user]) - - header.th do - %div.align-middle + %div.align-middle{style: 'text-align: center; margin-right: 33px;'} Actions - @submissions.each_with_index do |sub, index| - hidden_row_class = index >= 5 ? "hidden_ont hidden_select" : "" - t.row(id:"submission_#{sub.submissionId}" , class_css: hidden_row_class) do |r| - - if @ontology.admin?(session[:user]) - r.td { raw sub.submissionId } - r.td do - = render SubmissionStatusComponent.new(sub, submission_ready?(sub)) - - r.td { xmldatetime_to_date(sub.modificationDate) unless sub.modificationDate.nil? } - - r.td { xmldatetime_to_date(sub.creationDate) unless sub.creationDate.nil? } + = render SubmissionStatusComponent.new(sub, sub.submissionId==submission_ready?(sub)) + - r.td { render DateTimeFieldComponent.new(value: sub.modificationDate) unless sub.modificationDate.nil? } + - r.td { render DateTimeFieldComponent.new(value: sub.creationDate) unless sub.creationDate.nil? } + - unless @ont_restricted - - r.td do - %div.dropdown - %button.btn.btn-outline-primary.rounded-pill.dropdown-toggle{type:"button", 'data-toggle':"dropdown", 'aria-expanded': "false", style:'white-space: nowrap'} - Download - %span.sr-only Toggle Dropdown - .dropdown-menu - - links = download_link(sub,@ontology) - - links.each do |value| - - link,label = value.values - %a.dropdown-item{ href: link }= label - - -# = raw download_link(sub, @ontology) - - if @ontology.admin?(session[:user]) - r.td do %div.d-flex - %a.btn.btn-sm.btn-link{:href => "/ontologies/#{@ontology.acronym}/submissions/#{sub.submissionId}/edit", 'data-turbo-frame':"_top"} - %span Edit - - unless index.zero? - - alert_text = "Are you sure you want to delete submission " + sub.submissionId.to_s + " for ontology " + @ontology.acronym + "?
This action CAN NOT be undone!!!" - = button_to "Delete", "/admin/ontologies/#{@ontology.acronym}/submissions/#{sub.submissionId}?turbo_stream=true", method: :delete, class:'btn btn-sm btn-link', form: {data: { turbo: true, turbo_confirm: alert_text, turbo_frame: '_top'}} + %div.dropdown + %button.btn.btn-outline-primary.rounded-pill.dropdown-toggle{type:"button", 'data-toggle':"dropdown", 'aria-expanded': "false", style:'white-space: nowrap; width: 94%;font-size: small;'} + Download + %span.sr-only Toggle Dropdown + .dropdown-menu + - links = download_link(sub,@ontology) + - links.each do |value| + - link,label = value.values + %a.dropdown-item{ href: link }= label + + -# = raw download_link(sub, @ontology) + - if @ontology.admin?(session[:user]) + %div.d-flex + %div{style: 'margin-right: 10px;'} + = service_button(link: "#{@ontology.id}/submissions/#{sub.submissionId}?display=all", title: 'Go to API') + = edit_button(link: "/ontologies/#{@ontology.acronym}/submissions/#{sub.submissionId}/edit", title: "Edit") + - unless index.zero? + - alert_text = "Are you sure you want to delete submission " + sub.submissionId.to_s + " for ontology " + @ontology.acronym + "?
This action CAN NOT be undone!!!" + = button_to "/admin/ontologies/#{@ontology.acronym}/submissions/#{sub.submissionId}?turbo_stream=true", method: :delete, class: 'btn btn-sm btn-link', form: {data: { turbo: true, turbo_confirm: alert_text, turbo_frame: '_top'}} do + = inline_svg_tag('icons/delete.svg') - if @submissions.length > 5 - t.row(class_css: "show_more_subs") do |r| diff --git a/app/views/users/_form.html.haml b/app/views/users/_form.html.haml index 3dc7daa20..920b2d2b3 100644 --- a/app/views/users/_form.html.haml +++ b/app/views/users/_form.html.haml @@ -52,6 +52,6 @@ .d-flex %input#user_register_mail_list{:checked => "checked", :name => "user[register_mail_list]", :type => "checkbox", :value => "1"}/ %p#register-check-text - = t('register.mailing_list') + = t('register.mailing_list', site: portal_name) .register-button-container = render Buttons::RegularButtonComponent.new(id: 'register-button', value: "Register", type:'submit') diff --git a/app/views/users/index.html.haml b/app/views/users/index.html.haml index 9ea4b851f..a6f555ecc 100644 --- a/app/views/users/index.html.haml +++ b/app/views/users/index.html.haml @@ -26,10 +26,10 @@ - count = (user.ontologies&.size || 0) + (user.projects&.size || 0) %div.d-flex.align-items-center{style: 'width: 250px'} %span.mx-1 - = link_to 'Detail', "/accounts/#{user.username}", {data: {turbo_frame: '_top'}} + = link_to 'Detail', user_path(CGI.escape(user.id.split('/').last)), {data: {turbo_frame: '_top'}} %span.mx-1 - if count.zero? - = button_to "Delete", CGI.unescape(user_path(user.id.split('/').last)), method: :delete, class: 'btn btn-link', form: {data: { turbo: true, turbo_confirm: "Are you sure?", turbo_frame: '_top'}} + = button_to "Delete", user_path(CGI.escape(user.id.split('/').last)), method: :delete, class: 'btn btn-link', form: {data: { turbo: true, turbo_confirm: "Are you sure?", turbo_frame: '_top'}} - else %span{data: { controller: 'tooltip' }, title: "Can't delete this user because still used"} = link_to "Delete", "", class: 'btn btn-link disabled' diff --git a/config/locales/en.yml b/config/locales/en.yml index 2ca520abe..db9020260 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -179,9 +179,9 @@ en: logout: Logout mappings: Mappings publications: Publications - release_notes: Release notes + release_notes: Release Notes search_prompt: Search in %{portal_name} ... - submit_feedback: Send feedback + submit_feedback: Send Feedback support: Support cite_us: Cite Us footer: @@ -194,6 +194,7 @@ en: contact_us: Contact Us wiki: Wiki documentation: Documentation + agro_documentation: AgroPortal documentation agreements: Legal terms: Terms and Conditions privacy_policy: Privacy Policy @@ -408,6 +409,6 @@ en: text: Text type: Type umls_sem_type: UMLS Semantic Type - view_fair_scores_definitions: View FAIR scores definitions + view_fair_scores_definitions: "You are seeing the FAIRness assessment score for this ontology in AgroPortal. FAIR scores are computed with the O'FAIRe methodology. More details here: https://github.com/agroportal/fairness" visits: Visits weights_configuration: Weights configuration diff --git a/config/locales/fr.yml b/config/locales/fr.yml index 68d23840d..afbc08cbe 100644 --- a/config/locales/fr.yml +++ b/config/locales/fr.yml @@ -177,7 +177,7 @@ fr: help: Aide landscape: Panorama login: Connexion - logout: Décconnexion + logout: Déconnexion mappings: Alignements publications: Publications recommender: Recommendeur @@ -196,6 +196,7 @@ fr: contact_us: Contactez nous wiki: Wiki documentation: Documentation + agro_documentation: Documentation de AgroPortal agreements: Juridique terms: Termes et Conditions privacy_policy: Politique de confidentialité