diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 20c34ccfb3..a775d05f1d 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -421,6 +421,8 @@ def using_captcha? def get_class(params) + lang = params[:language]&.upcase&.to_sym + if @ontology.flat? ignore_concept_param = params[:conceptid].nil? || @@ -437,7 +439,7 @@ def get_class(params) @concept.children = [] else # Display only the requested class in the tree - @concept = @ontology.explore.single_class({full: true}, params[:conceptid]) + @concept = @ontology.explore.single_class({full: true, lang: lang }, params[:conceptid]) @concept.children = [] end @root = LinkedData::Client::Models::Class.new @@ -452,7 +454,7 @@ def get_class(params) if ignore_concept_param # get the top level nodes for the root # TODO_REV: Support views? Replace old view call: @ontology.top_level_classes(view) - roots = @ontology.explore.roots(concept_schemes: params[:concept_schemes]) + roots = @ontology.explore.roots(concept_schemes: params[:concept_schemes], lang: lang) if roots.nil? || roots.empty? LOG.add :debug, "Missing roots for #{@ontology.acronym}" not_found("Missing roots for #{@ontology.acronym}") @@ -463,7 +465,7 @@ def get_class(params) # get the initial concept to display root_child = @root.children.first - @concept = root_child.explore.self(full: true) + @concept = root_child.explore.self(full: true, lang: lang) # Some ontologies have "too many children" at their root. These will not process and are handled here. if @concept.nil? LOG.add :debug, "Missing class #{root_child.links.self}" @@ -471,16 +473,16 @@ def get_class(params) end else # if the id is coming from a param, use that to get concept - @concept = @ontology.explore.single_class({full: true}, params[:conceptid]) + @concept = @ontology.explore.single_class({full: true, lang: lang}, params[:conceptid]) if @concept.nil? || @concept.errors LOG.add :debug, "Missing class #{@ontology.acronym} / #{params[:conceptid]}" not_found("Missing class #{@ontology.acronym} / #{params[:conceptid]}") end # Create the tree - rootNode = @concept.explore.tree(include: "prefLabel,hasChildren,obsolete", concept_schemes: params[:concept_schemes]) + rootNode = @concept.explore.tree(include: "prefLabel,hasChildren,obsolete", concept_schemes: params[:concept_schemes], lang: lang) if rootNode.nil? || rootNode.empty? - roots = @ontology.explore.roots(concept_schemes: params[:concept_schemes]) + roots = @ontology.explore.roots(concept_schemes: params[:concept_schemes], lang: lang) if roots.nil? || roots.empty? LOG.add :debug, "Missing roots for #{@ontology.acronym}" not_found("Missing roots for #{@ontology.acronym}") diff --git a/app/controllers/ontologies_controller.rb b/app/controllers/ontologies_controller.rb index 12035ac7fc..d3058da73a 100644 --- a/app/controllers/ontologies_controller.rb +++ b/app/controllers/ontologies_controller.rb @@ -28,8 +28,7 @@ def index @app_name = 'FacetedBrowsing' @app_dir = '/browse' @base_path = @app_dir - ontologies = LinkedData::Client::Models::Ontology.all( -include: LinkedData::Client::Models::Ontology.include_params + ',viewOf', include_views: true, display_context: false) + ontologies = LinkedData::Client::Models::Ontology.all(include: LinkedData::Client::Models::Ontology.include_params + ',viewOf', include_views: true, display_context: false) ontologies_hash = Hash[ontologies.map {|o| [o.id, o] }] @admin = session[:user] ? session[:user].admin? : false @development = Rails.env.development? @@ -39,8 +38,7 @@ def index # The attributes used when retrieving the submission. We are not retrieving all attributes to be faster browse_attributes = 'ontology,acronym,submissionStatus,description,pullLocation,creationDate,released,name,naturalLanguage,hasOntologyLanguage,hasFormalityLevel,isOfType,contact' - submissions = LinkedData::Client::Models::OntologySubmission.all(include_views: true, display_links: false, -display_context: false, include: browse_attributes) + submissions = LinkedData::Client::Models::OntologySubmission.all(include_views: true, display_links: false,display_context: false, include: browse_attributes) submissions_map = Hash[submissions.map {|sub| [sub.ontology.acronym, sub] }] @categories = LinkedData::Client::Models::Category.all(display_links: false, display_context: false) @@ -153,8 +151,8 @@ def classes get_class(params) if @submission.hasOntologyLanguage == 'SKOS' - @schemes = get_schemes(@ontology) - @collections = get_collections(@ontology, add_colors: true) + @schemes = get_schemes(params, @ontology) + @collections = get_collections(params, @ontology, add_colors: true) else @instance_details, type = get_instance_and_type(params[:instanceid]) unless @instance_details.empty? || type.nil? || concept_id_param_exist?(params) @@ -236,8 +234,7 @@ def mappings def new @ontology = LinkedData::Client::Models::Ontology.new - @ontologies = LinkedData::Client::Models::Ontology.all(include: 'acronym', include_views: true, -display_links: false, display_context: false) + @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 @user_select_list = LinkedData::Client::Models::User.all.map {|u| [u.username, u.id]} @@ -266,9 +263,9 @@ def instances end def schemes - @schemes = get_schemes(@ontology) + @schemes = get_schemes(params, @ontology) scheme_id = params[:scheme_id] || @submission_latest.URI || nil - @scheme = get_scheme(@ontology, scheme_id) if scheme_id + @scheme = get_scheme(params, @ontology, scheme_id) if scheme_id if request.xhr? render partial: 'ontologies/sections/schemes', layout: false @@ -278,9 +275,9 @@ def schemes end def collections - @collections = get_collections(@ontology) + @collections = get_collections(params, @ontology) collection_id = params[:collection_id] - @collection = get_collection(@ontology, collection_id) if collection_id + @collection = get_collection(params, @ontology, collection_id) if collection_id if request.xhr? render partial: 'ontologies/sections/collections', layout: false @@ -292,6 +289,7 @@ def collections # GET /ontologies/ACRONYM # GET /ontologies/1.xml def show + # Hack to make ontologyid and conceptid work in addition to id and ontology params params[:id] = params[:id].nil? ? params[:ontologyid] : params[:id] @@ -340,6 +338,10 @@ def show # Get the latest submission (not necessarily the latest 'ready' submission) @submission_latest = @ontology.explore.latest_submission rescue @ontology.explore.latest_submission(include: '') + + submission_lang = get_submission_languages(@submission_latest.naturalLanguage) + + @submission_lang_options = transform_langs_to_select_options(submission_lang, params[:language]) # Is the ontology downloadable? @ont_restricted = ontology_restricted?(@ontology.acronym) @@ -459,6 +461,25 @@ def widgets private + + def get_submission_languages(submission_natural_language = []) + submission_natural_language.map { |natural_language| natural_language["iso639"] && natural_language.split('/').last }.compact + end + + def transform_langs_to_select_options(langs = [], current_lang = nil) + # Transform each language into a select option + options = langs.map do |lang| + lang = lang.split('/').last + [lang.capitalize, lang.upcase, { selected: lang.casecmp(current_lang) == 0 }] + end + + # If none of the languages are marked as default, mark "All" as default + options.unshift(['All', nil, { selected: options.none? { |option| option[2][:selected] } }]) + + options + end + + def ontology_params p = params.require(:ontology).permit(:name, :acronym, { administeredBy:[] }, :viewingRestriction, { acl:[] }, { hasDomain:[] }, :isView, :viewOf, :subscribe_notifications, {group:[]}) diff --git a/app/helpers/collections_helper.rb b/app/helpers/collections_helper.rb index b2c20a2ba3..c01ad0ba83 100644 --- a/app/helpers/collections_helper.rb +++ b/app/helpers/collections_helper.rb @@ -1,14 +1,16 @@ module CollectionsHelper - def get_collections(ontology, add_colors: false) - collections = ontology.explore.collections + def get_collections(params, ontology, add_colors: false) + lang = params[:language]&.upcase&.to_sym + collections = ontology.explore.collections({ include: 'all', lang: lang }) generate_collections_colors(collections) if add_colors collections end - def get_collection(ontology, collection_uri) - ontology.explore.collections({ include: 'all' },collection_uri) + def get_collection(params, ontology, collection_uri) + lang = params[:language]&.upcase&.to_sym + ontology.explore.collections({ include: 'all', lang: lang},collection_uri) end def get_collection_label(collection) diff --git a/app/helpers/ontologies_helper.rb b/app/helpers/ontologies_helper.rb index 6e43ba8193..f0c5bd7ae6 100644 --- a/app/helpers/ontologies_helper.rb +++ b/app/helpers/ontologies_helper.rb @@ -2,6 +2,9 @@ module OntologiesHelper REST_URI = $REST_URL API_KEY = $API_KEY + LANGUAGE_FILTERABLE_SECTIONS = ['classes', 'schemes', 'collections'] + + def additional_details return "" if $ADDITIONAL_ONTOLOGY_DETAILS.nil? || $ADDITIONAL_ONTOLOGY_DETAILS[@ontology.acronym].nil? @@ -386,6 +389,10 @@ def selected_section?(section_title) current_section.eql?(section_title) end + def allowed_to_show_language_filter?(section) + LANGUAGE_FILTERABLE_SECTIONS.include?(section) + end + def lazy_load_section(section_title, &block) if current_section.eql?(section_title) block.call diff --git a/app/helpers/schemes_helper.rb b/app/helpers/schemes_helper.rb index 799e52b131..acb732c148 100644 --- a/app/helpers/schemes_helper.rb +++ b/app/helpers/schemes_helper.rb @@ -1,11 +1,13 @@ module SchemesHelper - def get_schemes(ontology) - ontology.explore.schemes + def get_schemes(params, ontology) + lang = params[:language]&.upcase&.to_sym + ontology.explore.schemes({ include: 'all', lang: lang }) end - def get_scheme(ontology, scheme_uri) - ontology.explore.schemes({ include: 'all' }, scheme_uri) + def get_scheme(params, ontology, scheme_uri) + lang = params[:language]&.upcase&.to_sym + ontology.explore.schemes({ include: 'all', lang: lang }, scheme_uri) end def get_scheme_label(scheme) diff --git a/app/javascript/controllers/chosen_controller.js b/app/javascript/controllers/chosen_controller.js index 38d1a092d4..3293c985fd 100644 --- a/app/javascript/controllers/chosen_controller.js +++ b/app/javascript/controllers/chosen_controller.js @@ -61,9 +61,6 @@ export default class extends Controller { chosenClose.style.position = "unset" chosenClose.style.margin = "auto" - - - } }) } diff --git a/app/javascript/controllers/history_controller.js b/app/javascript/controllers/history_controller.js index d339c32f82..48518c64ac 100644 --- a/app/javascript/controllers/history_controller.js +++ b/app/javascript/controllers/history_controller.js @@ -1,5 +1,5 @@ -import {Controller} from "@hotwired/stimulus" -import {HistoryService} from "../mixins/useHistory"; +import { Controller } from "@hotwired/stimulus" +import { HistoryService } from "../mixins/useHistory"; // Connects to data-controller="history" export default class extends Controller { @@ -7,9 +7,9 @@ export default class extends Controller { this.history = new HistoryService() } updateURL(event) { - const newData = event.detail.data - if (newData !== undefined) { - this.history.updateHistory(document.location.pathname + document.location.search, newData) + const { data } = event.detail + if (data !== undefined && Object.keys(data).length > 0) { + this.history.updateHistory(document.location.pathname + document.location.search, data) } } diff --git a/app/javascript/controllers/index.js b/app/javascript/controllers/index.js index 553504b0ac..448e9b76f4 100644 --- a/app/javascript/controllers/index.js +++ b/app/javascript/controllers/index.js @@ -25,6 +25,9 @@ application.register("label-ajax", LabelAjaxController) import LabelsAjaxContainerController from "./labels_ajax_container_controller" application.register("labels-ajax-container", LabelsAjaxContainerController) +import LanguageChangeController from "./language_change_controller" +application.register("language-change", LanguageChangeController) + import LoadChartController from "./load_chart_controller" application.register("load-chart", LoadChartController) @@ -43,6 +46,9 @@ application.register("simple-tree", SimpleTreeController) import SkosCollectionColorsController from "./skos_collection_colors_controller" application.register("skos-collection-colors", SkosCollectionColorsController) +import TabChangeController from "./tab_change_controller" +application.register("tab-change", TabChangeController) + import TooltipController from "./tooltip_controller" application.register("tooltip", TooltipController) diff --git a/app/javascript/controllers/language_change_controller.js b/app/javascript/controllers/language_change_controller.js new file mode 100644 index 0000000000..446a37a7f8 --- /dev/null +++ b/app/javascript/controllers/language_change_controller.js @@ -0,0 +1,18 @@ +import { Controller } from "@hotwired/stimulus" +import { showLoader } from "../mixins/showLoader"; + +export default class extends Controller { + + static targets = ["sections"] + + + onChange(event) { + showLoader(this.sectionsTarget); + + const url = new URL(window.location.href); + url.searchParams.set('language', event.target.value); + + Turbo.visit(url.toString()); + } + +} diff --git a/app/javascript/controllers/tab_change_controller.js b/app/javascript/controllers/tab_change_controller.js new file mode 100644 index 0000000000..3b0c50b3cc --- /dev/null +++ b/app/javascript/controllers/tab_change_controller.js @@ -0,0 +1,35 @@ +import { Controller } from "@hotwired/stimulus" +import { showLoader } from "../mixins/showLoader"; + +export default class extends Controller { + + + static targets = ["sections"] + + + onClick(event) { + + const anchorElement = event.target.closest('a'); + + // add active class to the clicked tab + + if (anchorElement) { + + showLoader(this.sectionsTarget); + + anchorElement.classList.add('active'); + + // remove active class from the other tabs + const otherTabs = anchorElement.parentElement.parentElement.querySelectorAll('a'); + otherTabs.forEach(tab => { + if (tab !== anchorElement) { + tab.classList.remove('active'); + } + }); + + const href = anchorElement.getAttribute('href'); + Turbo.visit(href); + } + + } +} diff --git a/app/javascript/controllers/turbo_frame_controller.js b/app/javascript/controllers/turbo_frame_controller.js index 821bb4fc58..7fbf6603da 100644 --- a/app/javascript/controllers/turbo_frame_controller.js +++ b/app/javascript/controllers/turbo_frame_controller.js @@ -1,11 +1,11 @@ -import {Controller} from "@hotwired/stimulus" -import {HistoryService} from "../mixins/useHistory"; +import { Controller } from "@hotwired/stimulus" +import { HistoryService } from "../mixins/useHistory"; // Connects to data-controller="turbo-frame" export default class extends Controller { static values = { url: String, - placeHolder: {type: String, default: 'Nothing loaded'}, + placeHolder: { type: String, default: 'Nothing loaded' }, } static targets = ['frame'] @@ -14,13 +14,21 @@ export default class extends Controller { } updateFrame(event) { - const newData = event.detail.data - const values = Object.entries(newData)[0][1] - if (values.filter(x => x.length !== 0).length === 0) { + const { data } = event.detail + const values = Object.values(data) + + // remove null and empty values + values.filter((value) => value !== "" || value !== null) + + if (values.length === 0) { this.frame.innerHTML = this.placeHolderValue } else { this.frame.innerHTML = "" - this.urlValue = new HistoryService().getUpdatedURL(this.urlValue, newData); + + this.urlValue ||= window.location.pathname + window.location.search; + + this.urlValue = new HistoryService().getUpdatedURL(this.urlValue, data); + this.frame.src = this.urlValue } } diff --git a/app/javascript/mixins/showLoader.js b/app/javascript/mixins/showLoader.js new file mode 100644 index 0000000000..2235b28c08 --- /dev/null +++ b/app/javascript/mixins/showLoader.js @@ -0,0 +1,16 @@ +const loaderHtml = ` +