diff --git a/Gemfile.lock b/Gemfile.lock index 77efa06d0d..f3dfc2d9a5 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -235,6 +235,8 @@ GEM netrc (0.11.0) newrelic_rpm (9.2.2) nio4r (2.5.9) + nokogiri (1.14.3-x86_64-darwin) + racc (~> 1.4) nokogiri (1.14.3-x86_64-linux) racc (~> 1.4) oj (3.14.3) @@ -418,6 +420,7 @@ GEM zeitwerk (2.6.8) PLATFORMS + x86_64-darwin-21 x86_64-linux DEPENDENCIES diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js index f73139ead6..0d0fe33cb7 100644 --- a/app/assets/javascripts/application.js +++ b/app/assets/javascripts/application.js @@ -26,7 +26,6 @@ //= require bp_property_tree //= require concepts //= require home -//= require fair_score //= require_tree ./helpers //= require_tree ./components //= require ontologies diff --git a/app/assets/javascripts/bp_admin.js b/app/assets/javascripts/bp_admin.js index 63ac8ae9e0..7e29b80be9 100644 --- a/app/assets/javascripts/bp_admin.js +++ b/app/assets/javascripts/bp_admin.js @@ -865,6 +865,220 @@ jQuery(".admin.index").ready(function() { }); // end: BUTTON onclick actions ----------------------------------- + + //============================================================== + // GROUPS MANAGEMENT + //============================================================== + displayGroups({}); + + // allow selecting of rows, except on link clicks + jQuery('#adminGroups tbody').on('click', 'tr', function(event) { + if (event.target.tagName.toLowerCase() != 'a') { + jQuery(this).toggleClass('selected'); + } + }); + + jQuery("div.groups_nav").html(` + + + + + + Apply to Selected Rows: + + + + + + `); + + jQuery('#group_admin_action_submit').on('click', function(event) { + var action = jQuery('#group_admin_action').val(); + + if (!action) { + alertify.alert("Please choose an action to perform on the selected groups."); + return; + } + + switch(action) { + case "delete": + DeleteGroups.act(); + break; + } + }); + + jQuery(document).on("reveal.facebox", function (event) { + jQuery("#facebox form[data-collection=groups]").validate({ + errorClass: "groupFormError", + errorElement: "div", + rules: { + "group[name]": "required", + "group[acronym]": "required", + }, + messages: { + "group[name]": "Please enter a name", + "group[acronym]": "Please enter an acronym", + }, + }); + + }); + + jQuery('#group_new_action').on('click', function (event) { + jQuery.facebox({ + ajax: "/admin/groups/new?time=" + new Date().getTime() + }); + }); + + jQuery('#adminGroups').on('click', 'a.edit-group', function(event) { + jQuery.facebox({ + ajax: "/admin/groups/" + encodeURIComponent(event.target.dataset.groupName) + "/edit?time=" + new Date().getTime() + }); + }); + + + //============================================================== + // CATEGORIES MANAGEMENT + //============================================================== + displayCategories({}); + + // allow selecting of rows, except on link clicks + jQuery('#adminCategories tbody').on('click', 'tr', function(event) { + if (event.target.tagName.toLowerCase() != 'a') { + jQuery(this).toggleClass('selected'); + } + }); + + jQuery("div.categories_nav").html(` + + + + + + Apply to Selected Rows: + + + + + + `); + + jQuery('#category_admin_action_submit').on('click', function(event) { + var action = jQuery('#category_admin_action').val(); + + if (!action) { + alertify.alert("Please choose an action to perform on the selected categories."); + return; + } + + switch(action) { + case "delete": + DeleteCategories.act(); + break; + } + }); + + jQuery(document).on("reveal.facebox", function (event) { + jQuery("#facebox form[data-collection=categories]").validate({ + errorClass: "categoryFormError", + errorElement: "div", + rules: { + "category[name]": "required", + "category[acronym]": "required", + }, + messages: { + "category[name]": "Please enter a name", + "category[acronym]": "Please enter an acronym", + }, + }); + + }); + + jQuery('#category_new_action').on('click', function (event) { + jQuery.facebox({ + ajax: "/admin/categories/new?time=" + new Date().getTime() + }); + }); + + jQuery('#adminCategories').on('click', 'a.edit-category', function(event) { + jQuery.facebox({ + ajax: "/admin/categories/" + encodeURIComponent(event.target.dataset.categoryName) + "/edit?time=" + new Date().getTime() + }); + }); + + //============================================================== + // MANAGEMENT COMMONS + //============================================================== + + jQuery(document).on("click", "#facebox a.dismiss-dialog", function (event) { + jQuery(document).trigger('close.facebox'); + }); + + jQuery(document).on('ajax:success', "#facebox form.admin-collection-form", (event, response, status, xhr) => { + jQuery(document).trigger('close.facebox'); + if (response && response.success) { + _showStatusMessages([response.success], [], [], false); + } + refreshCollection(event.target.dataset.collection); + }); + jQuery(document).on('ajax:error', "#facebox form.admin-collection-form", (event, xhr, status, error) => { + if (xhr.responseJSON) { + displayDialogErrorMessages(xhr.responseJSON) + } else { + displayDialogErrorMessages(status); + } + }); + + function refreshCollection(collectionName) { + switch (collectionName) { + case "groups": + displayGroups({}); + break; + case "categories": + displayCategories({}); + break; + default: + alertify.alert("Unable to refresh unknown collection '" + collectionName + "'"); + } + } + + function displayDialogErrorMessages(data, settings) { + settings ||= {} + + let append = settings.append || false; + + let errorListNode = jQuery("#facebox .alert-box ul"); + + if (!append) { + errorListNode.empty(); + } + + let messages = []; + if (typeof data == "string" || data instanceof String) { + messages.push(data) + } + if (typeof data == "object" && data.errors) { + messages.push.apply(messages, Object.values(data.errors)); + } + if (typeof data == "object" && data.status && data.status / 200 != 1) { + messages.push("Request error: " + data.statusText); + } + + for (let msg of messages) { + errorListNode.append(jQuery("
").text(msg)) + } + + if (messages.length == 0) { + errorListNode.parents(".alert-box").hide(); + } else { + errorListNode.parents(".alert-box").show(); + } + } }); @@ -1040,4 +1254,338 @@ DeleteUsers.prototype.ajaxCall = function (username){ } DeleteUsers.act = function(user) { new DeleteUsers(user).ajaxCall(user); -}; \ No newline at end of file +}; + +/* groups part */ +function displayGroups(data, group) { + let ontTable = null; + let allRows + if (jQuery.fn.dataTable.isDataTable('#adminGroups')) { + ontTable = jQuery('#adminGroups').DataTable().ajax.reload(); + } else { + ontTable = jQuery("#adminGroups").DataTable({ + "ajax": { + "url": "/admin/groups", + "contentType": "application/json", + "dataSrc": function (json) { + return populateGroupRows(json); + } + }, + "rowCallback": function(row, data, index) { + var acronym = jQuery('td:nth-child(4)', row).text(); + + jQuery(row).attr("id", "tr_" + acronym); + }, + "initComplete": function(settings, json) { + }, + "columnDefs": [ + { + "targets": 0, + "searchable": true, + "title": "Name", + }, + { + "targets": 1, + "searchable": true, + "title": "Description", + }, + { + "targets": 2, + "searchable": true, + "title": "Created", + }, + { + "targets": 3, + "searchable": true, + "title": "Id", + }, + { + "targets": 4, + "searchable": false, + "orderable": false, + "title": "Count", + }, + { + "targets": 5, + "searchable": false, + "orderable": false, + "title": "Actions", + "width": "200px" + } + ], + "autoWidth": false, + "lengthChange": false, + "searching": true, + "language": { + "search": "Filter: ", + "emptyTable": "No groups available" + }, + "info": true, + "paging": true, + "pageLength": 100, + "ordering": true, + "responsive": true, + "dom": '<"groups_nav"><"top"fi>rtip', + "stripeClasses": ["", "alt"], + }); + } + return ontTable; +} + +function populateGroupRows(data) { + let groups = data['groups']; + let allRows = groups.map(group => { + let name = group['name']; + let description = group['description'] + let created = group['created']; + let id = group['acronym']; + let nb = [ + ' ' + group['ontologies'].length + ' ', + ]; + let actions = [ + 'Edit', + ] + return [name, description, created, id , nb, actions.join('|')]; + }) + + return allRows; +} + +function DeleteGroups() { +} + +DeleteGroups.act = function(groupName) { + let group2delete = jQuery("#adminGroups tr.selected td:nth-child(4)").map(function(index, value) { return value.textContent.trim();}).toArray(); + let confirmMsg = "You are about to delete the following groups:' + definition + '
' + elsif definition.respond_to?(:uri) && definition.uri + html += '' + definition.uri + '
' + end + end + return html.html_safe + end end diff --git a/app/javascript/controllers/fair_score_home_controller.js b/app/javascript/controllers/fair_score_home_controller.js new file mode 100644 index 0000000000..8b4883ad9e --- /dev/null +++ b/app/javascript/controllers/fair_score_home_controller.js @@ -0,0 +1,21 @@ +import { Controller } from "@hotwired/stimulus" +import {FairScorePrincipleBar, FairScoreCriteriaRadar, FairScoreChartContainer} from "../mixins/useFairScore"; +// Connects to data-controller="fair-score-home" +export default class extends Controller { + connect() { + let fairScoreBar = new FairScorePrincipleBar( 'ont-fair-scores-canvas') + let fairScoreRadar = new FairScoreCriteriaRadar( 'ont-fair-criteria-scores-canvas') + let fairContainer = new FairScoreChartContainer('fair-score-charts-container' , [ fairScoreRadar , fairScoreBar]) + let ontologies = jQuery("#ontology_ontologyId"); + + fairContainer.getFairScoreData("all") + ontologies.change( (e) => { + if(ontologies.val() !== null){ + fairContainer.getFairScoreData(ontologies.val().join(',')) + } else if(ontologies.val() === null){ + fairContainer.getFairScoreData("all") + } + e.preventDefault() + }) + } +} diff --git a/app/javascript/controllers/fair_score_landscape_controller.js b/app/javascript/controllers/fair_score_landscape_controller.js new file mode 100644 index 0000000000..e093f68ea1 --- /dev/null +++ b/app/javascript/controllers/fair_score_landscape_controller.js @@ -0,0 +1,20 @@ +import { Controller } from "@hotwired/stimulus" +import { FairScoreChartContainer, FairScoreCriteriaBar } from "../mixins/useFairScore"; +// Connects to data-controller="fair-score-landscape" +export default class extends Controller { + connect() { + let fairCriteriaBars = new FairScoreCriteriaBar('ont-fair-scores-criteria-bars-canvas') + let fairContainer = new FairScoreChartContainer('fair-score-charts-container' , [fairCriteriaBars]) + let ontologies = jQuery("#ontology_ontologyId"); + + fairContainer.getFairScoreData("all") + ontologies.change( (e) => { + if(ontologies.val() !== null){ + fairContainer.getFairScoreData(ontologies.val().join(',')) + } else if(ontologies.val() === null){ + fairContainer.getFairScoreData("all") + } + e.preventDefault() + }) + } +} diff --git a/app/javascript/controllers/fair_score_summary_controller.js b/app/javascript/controllers/fair_score_summary_controller.js new file mode 100644 index 0000000000..883e2cde62 --- /dev/null +++ b/app/javascript/controllers/fair_score_summary_controller.js @@ -0,0 +1,12 @@ +import { Controller } from "@hotwired/stimulus" +import {FairScorePrincipleBar, FairScoreCriteriaRadar, FairScoreChartContainer} from "../mixins/useFairScore"; +// Connects to data-controller="fair-score-summary" +export default class extends Controller { + connect() { + let fairScoreBar = new FairScorePrincipleBar( 'ont-fair-scores-canvas') + let fairScoreRadar = new FairScoreCriteriaRadar( 'ont-fair-criteria-scores-canvas') + let fairContainer = new FairScoreChartContainer('fair-score-charts-container' , [ fairScoreRadar , fairScoreBar]) + + fairContainer.getFairScoreData(window.location.pathname.split('/')[2]) + } +} diff --git a/app/javascript/controllers/index.js b/app/javascript/controllers/index.js index 553504b0ac..83bcc541f1 100644 --- a/app/javascript/controllers/index.js +++ b/app/javascript/controllers/index.js @@ -13,6 +13,15 @@ application.register("class-search-auto-complete", ClassSearchAutoCompleteContro import ContainerSplitterController from "./container_splitter_controller" application.register("container-splitter", ContainerSplitterController) +import FairScoreHomeController from "./fair_score_home_controller" +application.register("fair-score-home", FairScoreHomeController) + +import FairScoreLandscapeController from "./fair_score_landscape_controller" +application.register("fair-score-landscape", FairScoreLandscapeController) + +import FairScoreSummaryController from "./fair_score_summary_controller" +application.register("fair-score-summary", FairScoreSummaryController) + import FormAutoCompleteController from "./form_auto_complete_controller" application.register("form-auto-complete", FormAutoCompleteController) diff --git a/app/assets/javascripts/fair_score.js b/app/javascript/mixins/useFairScore.js similarity index 90% rename from app/assets/javascripts/fair_score.js rename to app/javascript/mixins/useFairScore.js index c9186984d3..82aa516648 100644 --- a/app/assets/javascripts/fair_score.js +++ b/app/javascript/mixins/useFairScore.js @@ -1,7 +1,7 @@ - function round(val , base = 1){ return Math.floor( val * 100 * base) / 100 } + function getObtainedNotObtainedNA(scoresIn, portalMax , max , normalize = true){ const delimiter = (val) => (normalize ? val : 1) const notObtained = portalMax.map((x,i) => { @@ -391,17 +391,17 @@ class FairScoreCriteriaRadar extends FairScoreChart{ getFairScoreDataSet() { const scores = this.fairScoreChartCanvas.data('normalizedScores') - return [ - { - label: 'Fair score', - data: scores, - fill: true, - backgroundColor: 'rgba(151, 187, 205, 0.2)', - borderColor: 'rgba(151, 187, 205, 1)', - pointBorderColor: 'rgba(151, 187, 205, 1)', - pointBackgroundColor: 'rgba(151, 187, 205, 1)' - } - ] + return [ + { + label: 'Fair score', + data: scores, + fill: true, + backgroundColor: 'rgba(151, 187, 205, 0.2)', + borderColor: 'rgba(151, 187, 205, 1)', + pointBorderColor: 'rgba(151, 187, 205, 1)', + pointBackgroundColor: 'rgba(151, 187, 205, 1)' + } + ] } @@ -492,7 +492,7 @@ class FairScoreCriteriaBar extends FairScoreChart{ if (topOffset <= 0) topOffset = 0 - else if( (topOffset + tooltipEl.clientHeight) >= position.height) + else if( (topOffset + tooltipEl.clientHeight) >= position.height) topOffset = position.height - tooltipEl.clientHeight // Display, position, and set styles for font @@ -627,63 +627,5 @@ class FairScoreCriteriaBar extends FairScoreChart{ } } - -/* - For landscape - */ -jQuery('#fairness_assessment').ready(()=> { - let fairCriteriaBars = new FairScoreCriteriaBar('ont-fair-scores-criteria-bars-canvas') - let fairContainer = new FairScoreChartContainer('fair-score-charts-container' , [fairCriteriaBars]) - let ontologies = jQuery("#ontology_ontologyId"); - - fairContainer.getFairScoreData("all") - ontologies.change( (e) => { - if(ontologies.val() !== null){ - fairContainer.getFairScoreData(ontologies.val().join(',')) - } else if(ontologies.val() === null){ - fairContainer.getFairScoreData("all") - } - e.preventDefault() - }) - return false -}) - - - -/* - For the home - */ -jQuery('#fair-home').ready( function (e) { - - let fairScoreBar = new FairScorePrincipleBar( 'ont-fair-scores-canvas') - let fairScoreRadar = new FairScoreCriteriaRadar( 'ont-fair-criteria-scores-canvas') - let fairContainer = new FairScoreChartContainer('fair-score-charts-container' , [ fairScoreRadar , fairScoreBar]) - let ontologies = jQuery("#ontology_ontologyId"); - - fairContainer.getFairScoreData("all") - ontologies.change( (e) => { - if(ontologies.val() !== null){ - fairContainer.getFairScoreData(ontologies.val().join(',')) - } else if(ontologies.val() === null){ - fairContainer.getFairScoreData("all") - } - e.preventDefault() - }) - return false -}) - -/* - For the summary -*/ -jQuery('#fair-summary').ready( function (e) { - - let fairScoreBar = new FairScorePrincipleBar( 'ont-fair-scores-canvas') - let fairScoreRadar = new FairScoreCriteriaRadar( 'ont-fair-criteria-scores-canvas') - let fairContainer = new FairScoreChartContainer('fair-score-charts-container' , [ fairScoreRadar , fairScoreBar]) - - fairContainer.getFairScoreData(window.location.pathname.split('/')[2]) - - return false -}) - +export {round, getObtainedNotObtainedNA, FairScoreChartContainer, FairScoreChart, FairScorePrincipleBar, FairScoreCriteriaRadar, FairScoreCriteriaBar} diff --git a/app/views/admin/categories/_form.html.haml b/app/views/admin/categories/_form.html.haml new file mode 100644 index 0000000000..34bd8e82ae --- /dev/null +++ b/app/views/admin/categories/_form.html.haml @@ -0,0 +1,49 @@ +- new_record = @category.acronym.nil? +%div.alert-box.error{style: @errors.nil? ? "display: none" : nil } + %ul + - unless @errors.nil? + - for error in @errors + %li + = error +%div{:style => "width:500px"} + %span.asterik{:style => "float:right;"} * fields are required + %h3 #{title_text} + %table#category_form.form + %colgroup + %col + %col{style: "width: 100%"} + %tr + %th + Acronym + %span.asterik * + %td.top + - if new_record + = f.text_field :acronym, class: "form-control" + - else + = f.text_field :acronym, class: "form-control", readonly: true + %tr + %th + Name + %span.asterik * + %td.top + = f.text_field :name, class: "form-control" + %tr + %th + Description + %td.top + = f.text_area :description, class: "form-control" + - unless new_record + %tr + %th + Created + %td.top + = f.text_field :created, readonly: true, class: "form-control" + %tr + %th + Ontologies + %td.top + = render SelectInputComponent.new(id: "category_ontologies", name: "category[ontologies]", values: @ontologies_category, selected: @category.ontologies, multiple: true, open_to_add_values: true) + %div.d-flex.mt-1{:style => "display: none;"} + %div.mt-2 + = f.submit button_text, class: "btn btn-primary mr-sm-2 group-form-accept" + = link_to "Cancel", "javascript:;", class: "btn btn-primary dismiss-dialog" \ No newline at end of file diff --git a/app/views/admin/categories/edit.html.haml b/app/views/admin/categories/edit.html.haml new file mode 100644 index 0000000000..b203c02ce3 --- /dev/null +++ b/app/views/admin/categories/edit.html.haml @@ -0,0 +1,6 @@ +- @title = "Edit category" + +%div + = form_for :category, url: admin_categories_path + "/" + escape(@category.acronym), method: "PATCH", remote: true, data: { collection: "categories"}, html: {class: "admin-collection-form" } do |f| + = render partial: "form", locals: {f: f, title_text: "Edit category", + button_text: "Save", button_class: "edit-category"} diff --git a/app/views/admin/categories/new.html.haml b/app/views/admin/categories/new.html.haml new file mode 100644 index 0000000000..4d3b3082d0 --- /dev/null +++ b/app/views/admin/categories/new.html.haml @@ -0,0 +1,6 @@ +- @title = "Create new category" + +%div + = form_for :category, url: admin_categories_path, method: "POST", remote: true, data: { collection: "categories"}, html: {class: "admin-collection-form" } do |f| + = render partial: "form", locals: {f: f, title_text: "Create category", + button_text: "Create category" } diff --git a/app/views/admin/groups/_form.html.haml b/app/views/admin/groups/_form.html.haml new file mode 100644 index 0000000000..ce5c958277 --- /dev/null +++ b/app/views/admin/groups/_form.html.haml @@ -0,0 +1,48 @@ +- new_record = @group.acronym.nil? +%div.alert-box.error{style: @errors.nil? ? "display: none" : nil } + %ul + - unless @errors.nil? + - for error in @errors + %li + = error +%div{:style => "width:500px"} + %span.asterik{:style => "float:right;"} * fields are required + %h3 #{title_text} + %table#group_form.form + %colgroup + %col + %col{style: "width: 100%"} + %tr + %th + Acronym + %span.asterik * + %td.top + - if new_record + = f.text_field :acronym, class: "form-control" + - else + = f.text_field :acronym, class: "form-control", readonly: true + %tr + %th + Name + %span.asterik * + %td.top + = f.text_field :name, class: "form-control" + %tr + %th + Description + %td.top + = f.text_area :description, class: "form-control" + - unless new_record + %tr + %th + Created + %td.top + = f.text_field :created, readonly: true, class: "form-control" + %tr + %th + Ontologies + %td.top + = render SelectInputComponent.new(id: "group_ontologies", name: "group[ontologies]", values: @ontologies_group , selected: @group.ontologies , multiple: true, open_to_add_values: true) + %div.mt-2 + = f.submit button_text, class: "btn btn-primary mr-sm-2 group-form-accept" + = link_to "Cancel", "javascript:;", class: "btn btn-primary dismiss-dialog" \ No newline at end of file diff --git a/app/views/admin/groups/edit.html.haml b/app/views/admin/groups/edit.html.haml new file mode 100644 index 0000000000..7269a374d0 --- /dev/null +++ b/app/views/admin/groups/edit.html.haml @@ -0,0 +1,6 @@ +- @title = "Edit group" + +%div + = form_for :group, url: admin_groups_path + "/" + escape(@group.acronym), method: "PATCH", remote: true, data: { collection: "groups"}, html: {class: "admin-collection-form" } do |f| + = render partial: "form", locals: {f: f, title_text: "Edit group", + button_text: "Save", button_class: "edit-group"} diff --git a/app/views/admin/groups/new.html.haml b/app/views/admin/groups/new.html.haml new file mode 100644 index 0000000000..2a8bf5f425 --- /dev/null +++ b/app/views/admin/groups/new.html.haml @@ -0,0 +1,6 @@ +- @title = "Create new group" + +%div + = form_for :group, url: admin_groups_path, method: "POST", remote: true, data: { collection: "groups"}, html: {class: "admin-collection-form" } do |f| + = render partial: "form", locals: {f: f, title_text: "Create group", + button_text: "Create group" } diff --git a/app/views/admin/index.html.haml b/app/views/admin/index.html.haml index 0b796f2a10..a67c026743 100644 --- a/app/views/admin/index.html.haml +++ b/app/views/admin/index.html.haml @@ -1,4 +1,4 @@ -- @title = "BioPortal Administration" +- @title = "Administration" %div.row %div.col @@ -24,6 +24,10 @@ =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 @@ -103,6 +107,17 @@ %div.tab-pane.fade{id: "ontologies_metadata_curator", role: "tabpanel", aria: { labelledby: "ontologies_metadata_curator-admin-tab" }} = render partial: 'ontologies_metadata_curator/metadata_tab' + -# Groups tab + %div.tab-pane.fade{id: "groups", role: "tabpanel", aria: { labelledby: "groups-admin-tab" }} + %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" }} + %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/_details.html.haml b/app/views/concepts/_details.html.haml index 56cea26439..2b225d586c 100644 --- a/app/views/concepts/_details.html.haml +++ b/app/views/concepts/_details.html.haml @@ -29,7 +29,7 @@ %tr %td{nowrap: ""} Definitions %td - %p= @concept.definition.join(" ") + = dispaly_complex_text(@concept.definition) - if @concept.obsolete? %tr %td{nowrap: ""} Obsolete diff --git a/app/views/concepts/_list.html.haml b/app/views/concepts/_list.html.haml index 83a4a27d3d..6b67d002f2 100644 --- a/app/views/concepts/_list.html.haml +++ b/app/views/concepts/_list.html.haml @@ -3,7 +3,7 @@ next_url: concept_list_url(@page.nextPage, request_collection_id, @ontology.acronym), current_page: @page.page, next_page: @page.nextPage, auto_click: @auto_click) do |c| - - concepts = c.collection.sort_by{|concept| [concept.prefLabel || concept.id]} + - concepts = c.collection.sort_by{|concept| [concept.prefLabel.capitalize || concept.id]} - if concepts && !concepts.empty? = raw tree_link_to_concept(child: concepts.shift, ontology_acronym: @ontology.acronym, active_style: c.auto_click? ? 'active' : '') - concepts.each do |concept| diff --git a/app/views/home/_fair_score_home.html.haml b/app/views/home/_fair_score_home.html.haml index 9e83a221ba..988ef5cf02 100644 --- a/app/views/home/_fair_score_home.html.haml +++ b/app/views/home/_fair_score_home.html.haml @@ -1,4 +1,4 @@ -%div.col +%div.col{data:{controller:"fair-score-home"}} %div.card.mb-3 %div.card-header.d-flex.justify-content-between %span diff --git a/app/views/landscape/_fair_score_landscape.html.haml b/app/views/landscape/_fair_score_landscape.html.haml index 7abc353f87..adac535099 100644 --- a/app/views/landscape/_fair_score_landscape.html.haml +++ b/app/views/landscape/_fair_score_landscape.html.haml @@ -31,7 +31,7 @@ This interface shows how an ontology or a group responded successfully to O’FAIRe FAIRness assessment questions %div See details for each ontologies on the specific ontology summary pages - %div.card-body + %div.card-body{data:{controller:"fair-score-landscape"}} %div#fair-score-charts-container.row %div.col %span.text-secondary.mt-4 diff --git a/app/views/ontologies/_fairs_score.html.haml b/app/views/ontologies/_fairs_score.html.haml index e3c29dd32f..26a98885c3 100644 --- a/app/views/ontologies/_fairs_score.html.haml +++ b/app/views/ontologies/_fairs_score.html.haml @@ -12,7 +12,7 @@ class: "btn btn-primary w-100", data: { show_modal_title_value: "FAIRness assessment questions", show_modal_size_value: 'modal-xl' }, ) - %div.statistics_container + %div.statistics_container{data:{controller:"fair-score-summary"}} %div = render partial: "shared/fair_score_radar" , locals: {data: @fair_scores_data} %div diff --git a/app/views/ontologies/concepts_browsers/_concepts_browser.html.haml b/app/views/ontologies/concepts_browsers/_concepts_browser.html.haml index 967c93e8cd..1c4c5128c2 100644 --- a/app/views/ontologies/concepts_browsers/_concepts_browser.html.haml +++ b/app/views/ontologies/concepts_browsers/_concepts_browser.html.haml @@ -1,18 +1,18 @@ %nav .nav.nav-tabs.text-center{:role => "tablist", style:"background-color: rgba(0, 0, 0, 0.03);"} - %a#concepts-tree-tab.nav-item.nav-link.active.flex-grow-1.border-radius-0{"data-toggle" => "tab", :href => "#concepts-tree-container", title: 'Hierarchy view', 'data-controller': "tooltip"} + %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"} + %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"} + %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.show.active + #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 + #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 + #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 diff --git a/app/views/ontologies/concepts_browsers/_concepts_list.html.haml b/app/views/ontologies/concepts_browsers/_concepts_list.html.haml index 07d48f6807..6fb3b288a1 100644 --- a/app/views/ontologies/concepts_browsers/_concepts_list.html.haml +++ b/app/views/ontologies/concepts_browsers/_concepts_list.html.haml @@ -13,5 +13,5 @@ data: {action: 'changed->turbo-frame#updateFrame'}} %div#sd_content.card.p-1{style: 'overflow-y: scroll; height: 60vh;'} - = render TurboFrameComponent.new(id: 'concepts_list_view-page-1', data: {'turbo-frame-target': 'frame'}) do + = render TurboFrameComponent.new(id: 'concepts_list_view-page-1', data: {'turbo-frame-target': 'frame'}, src:params[:concept_collections] ? "/ajax/classes/list?ontology_id=#{@ontology.acronym}&collection_id=#{params[:concept_collections]}" : '') do Please select a collection to display \ No newline at end of file diff --git a/app/views/shared/_ontology_picker_single.html.erb b/app/views/shared/_ontology_picker_single.html.erb index dbcb731252..53e2b4f9df 100644 --- a/app/views/shared/_ontology_picker_single.html.erb +++ b/app/views/shared/_ontology_picker_single.html.erb @@ -10,8 +10,17 @@ <%disabled ||= nil%> diff --git a/config/routes.rb b/config/routes.rb index 057297ac71..81b907f21f 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -50,6 +50,8 @@ namespace :admin do resources :licenses, only: [:index, :create, :new] + resources :groups, only: [:index, :create, :new, :edit, :update, :destroy] + resources :categories, only: [:index, :create, :new, :edit, :update, :destroy] end resources :subscriptions