Skip to content

Commit

Permalink
Merge pull request #234 from ncbo/kgcl-change-requests
Browse files Browse the repository at this point in the history
Add initial support for ontology change requests
  • Loading branch information
jvendetti authored Dec 12, 2022
2 parents a80420d + 6337641 commit 1b2b74f
Show file tree
Hide file tree
Showing 45 changed files with 142,222 additions and 99 deletions.
1 change: 1 addition & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ gem 'select2-rails'
gem 'cube-ruby', require: 'cube'
gem 'dalli'
gem 'flamegraph'
gem 'graphql-client'
gem 'haml', '~> 5.1'
gem 'i18n'
gem 'iconv'
Expand Down
5 changes: 5 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,10 @@ GEM
flamegraph (0.9.5)
globalid (1.0.0)
activesupport (>= 5.0)
graphql (2.0.9)
graphql-client (0.18.0)
activesupport (>= 3.0)
graphql
haml (5.2.2)
temple (>= 0.8.0)
tilt
Expand Down Expand Up @@ -353,6 +357,7 @@ DEPENDENCIES
dalli
ed25519 (>= 1.2, < 2.0)
flamegraph
graphql-client
haml (~> 5.1)
html2haml
i18n
Expand Down
1 change: 1 addition & 0 deletions app/assets/javascripts/application.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
//= require bp_admin
//= require bp_recommender
//= require bp_property_tree
//= require concepts
//= require home
//= require ontologies
//= require projects
Expand Down
7 changes: 7 additions & 0 deletions app/assets/javascripts/concepts.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
jQuery(document).ready(function() {

jQuery('#changeRequestModal').on('submit', function() {
$('#changeRequestModal').modal('hide');
});

});
1 change: 1 addition & 0 deletions app/assets/stylesheets/application.css.scss
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
@import "admin";
@import "annotator";
@import "bioportal";
@import "concepts";
@import "footer";
@import "home";
@import "mappings";
Expand Down
21 changes: 0 additions & 21 deletions app/assets/stylesheets/bioportal.scss
Original file line number Diff line number Diff line change
Expand Up @@ -547,27 +547,6 @@ li.ac_over > .obsolete_class {
cursor: inherit; /*override the help cursor for selection menus*/
}

.concept_details p {
margin-bottom: .5em;
}

.concept_details .label {
vertical-align: top;
width: 180px;
max-width: 200px;
}

.concept_details tbody td {
padding: 0.6em 0.8em 0 !important;
white-space: normal; /* css-3 */
white-space: -moz-normal; /* Mozilla, since 1999 */
word-wrap: break-word; /* Internet Explorer 5.5+ */
}

.concept_details td:nth-child(1) {
white-space: nowrap;
}

#format_specific_options td {
border-top: 1px solid #C1DAD7;
}
Expand Down
33 changes: 33 additions & 0 deletions app/assets/stylesheets/concepts.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
.concept_details .label {
vertical-align: top;
width: 180px;
max-width: 200px;
}

.concept_details tbody td {
white-space: normal; /* css-3 */
white-space: -moz-normal; /* Mozilla, since 1999 */
word-wrap: break-word; /* Internet Explorer 5.5+ */

p {
margin-bottom: 0;
}

a.btn.btn-link {
padding: 0;
}
}

.concept_details td:nth-child(1) {
white-space: nowrap;
}

div.synonym-change-request {
display: flex;
column-gap: 5px;
justify-content: flex-end;
}

div.synonym-change-request button {
padding: 0px;
}
37 changes: 37 additions & 0 deletions app/controllers/change_requests_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# frozen_string_literal: true

class ChangeRequestsController < ApplicationController
def create_synonym
@concept_label = params[:concept_label]
@concept_id = params[:concept_id]
@ont_acronym = params[:ont_acronym]
@username = session[:user].username

respond_to :js
end

def create
params[:curie] = generate_curie(params[:ont_acronym], params[:concept_id])
params[:content] = KGCL::IssueContentGenerator.call(params)
@issue = IssueCreatorService.call(params)
flash.now.notice = helpers.change_request_success_message if @issue['id'].present?

respond_to :js
end

private

def generate_curie(ont_acronym, concept_id)
ontology = LinkedData::Client::Models::Ontology.find_by_acronym(ont_acronym).first
query_string = { display: 'notation,prefixIRI', display_links: false, display_context: false }
concept = ontology.explore.single_class(query_string, concept_id)

if concept.notation
concept.notation
elsif concept.prefixIRI
concept.prefixIRI
else
concept_id
end
end
end
17 changes: 7 additions & 10 deletions app/helpers/application_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -392,16 +392,13 @@ def xmldatetime_to_date(xml_date_time_str)
end

def flash_class(level)
case level
when "notice"
"alert alert-info"
when "success"
"alert alert-success"
when "error"
"alert alert-danger"
when "alert"
"alert alert-error"
end
bootstrap_alert_class = {
'notice' => 'alert-info',
'success' => 'alert-success',
'error' => 'alert-danger',
'alert' => 'alert-danger'
}
bootstrap_alert_class[level]
end

###BEGIN ruby equivalent of JS code in bp_ajax_controller.
Expand Down
12 changes: 12 additions & 0 deletions app/helpers/change_requests_helper.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# frozen_string_literal: true

module ChangeRequestsHelper
def change_request_success_message
url = link_to 'details', @issue['url'], target: '_blank', class: 'alert-link'
"Your change request was successfully submitted! View the #{url} on GitHub.".html_safe
end

def change_request_alert_context
flash.notice.present? ? 'alert-success' : 'alert-danger'
end
end
77 changes: 65 additions & 12 deletions app/helpers/concepts_helper.rb
Original file line number Diff line number Diff line change
@@ -1,27 +1,29 @@
module ConceptsHelper
# frozen_string_literal: true

module ConceptsHelper
def exclude_relation?(relation_to_check, ontology = nil)
excluded_relations = [ "type", "rdf:type", "[R]", "SuperClass", "InstanceCount" ]
excluded_relations = %w[type rdf:type [R] SuperClass InstanceCount]

# Show or hide property based on the property and ontology settings
if ontology
# TODO_REV: Handle obsolete classes
# Hide owl:deprecated if a user has set class or property based obsolete checking
# if !ontology.obsoleteParent.nil? && relation_to_check.include?("owl:deprecated") || !ontology.obsoleteProperty.nil? && relation_to_check.include?("owl:deprecated")
# if !ontology.obsoleteParent.nil? && relation_to_check.include?("owl:deprecated") ||
# !ontology.obsoleteProperty.nil? && relation_to_check.include?("owl:deprecated")
# return true
# end
end

excluded_relations.each do |relation|
return true if relation_to_check.include?(relation)
end
return false
false
end

def concept_properties2hash(properties)
# NOTE: example properties
#
#properties
# properties
#=> #<struct
# http://www.w3.org/2000/01/rdf-schema#label=
# [#<struct
Expand All @@ -47,32 +49,83 @@ def concept_properties2hash(properties)
# links=nil,
# context=nil>
properties_data = {}
keys = properties.members # keys is an array of symbols
keys = properties.members # keys is an array of symbols
for key in keys
next if properties[key].nil? # ignore :context and :links when nil.
next if properties[key].nil? # ignore :context and :links when nil.

# Shorten the key into a simple label
k = key.to_s if key.kind_of?(Symbol)
k ||= key
if k.start_with?("http")
label = LinkedData::Client::HTTP.get("/ontologies/#{@ontology.acronym}/properties/#{CGI.escape(k)}/label").label rescue ""
if label.nil? || label.empty?
k = k.gsub(/.*#/,'') # greedy regex replace everything up to last '#'
k = k.gsub(/.*\//,'') # greedy regex replace everything up to last '/'
k = k.gsub(/.*#/, '') # greedy regex replace everything up to last '#'
k = k.gsub(/.*\//, '') # greedy regex replace everything up to last '/'
# That might take care of nearly everything to be shortened.
label = k
end
end
begin
# Try to simplify the property values, when they are a struct.
values = properties[key].map {|v| v.string }
values = properties[key].map { |v| v.string }
rescue
# Each value is probably a simple datatype already.
values = properties[key]
end
data = { :key => key, :values => values }
data = { key: key, values: values }
properties_data[label] = data
end
return properties_data
properties_data
end

def add_synonym_button
return unless change_requests_enabled?(@ontology.acronym)

if session[:user].nil?
link_to(login_index_path(redirect: concept_redirect_path),
role: 'button',
class: 'btn btn-link',
aria: { label: 'Create synonym' }) do
content_tag(:i, '', class: 'fas fa-plus-circle fa-lg', aria: { hidden: 'true' }).html_safe
end
else
link_to(change_requests_create_synonym_path(concept_id: @concept.id, concept_label: @concept.prefLabel,
ont_acronym: @ontology.acronym),
role: 'button',
class: 'btn btn-link',
aria: { label: 'Create synonym' },
data: { toggle: 'modal', target: '#changeRequestModal' },
remote: 'true') do
content_tag(:i, '', class: 'fas fa-plus-circle fa-lg', aria: { hidden: 'true' }).html_safe
end
end
end

def remove_synonym_button
return unless change_requests_enabled?(@ontology.acronym)

if session[:user].nil?
link_to(login_index_path(redirect: concept_redirect_path),
role: 'button',
class: 'btn btn-link',
aria: { label: 'Remove a synonym' }) do
content_tag(:i, '', class: 'fas fa-minus-circle fa-lg', aria: { hidden: 'true' }).html_safe
end
else
link_to('#', role: 'button', class: 'btn btn-link', aria: { label: 'Remove a synonym' }) do
content_tag(:i, '', class: 'fas fa-minus-circle fa-lg', aria: { hidden: 'true' }).html_safe
end
end
end

def synonym_qualifier_select(form)
options = [%w[exact exact], %w[narrow narrow], %w[broad broad], %w[related related]]
form.select :qualifier, options_for_select(options, 0), {}, { class: 'form-control' }
end

private

def concept_redirect_path
ontology_path(@ontology.acronym, p: 'classes', conceptid: @concept.id)
end
end
Loading

0 comments on commit 1b2b74f

Please sign in to comment.