Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added in new ROR search to funding body #2690

Merged
merged 19 commits into from
Dec 3, 2024
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .rubocop_fix_me.yml
Original file line number Diff line number Diff line change
Expand Up @@ -982,6 +982,7 @@ Style/MethodDefParentheses:
Lint/UriEscapeUnescape:
Exclude:
- "lib/qa/authorities/geonames.rb"
- "lib/qa/authorities/research_organization_registry.rb"

Capybara/VisibilityMatcher:
Exclude:
Expand Down Expand Up @@ -1010,6 +1011,10 @@ RSpec/RepeatedExampleGroupDescription:
- "spec/models/default_spec.rb"
- "spec/scholars_archive/validators/graduation_year_validator_spec.rb"

RSpec/UnspecifiedException:
Exclude:
- "spec/services/scholars_archive/research_organization_registry_service_spec.rb"

Lint/RedundantCopDisableDirective:
Exclude:
- "app/indexers/concerns/scholars_archive/indexes_combined_sort_date.rb"
Expand Down
64 changes: 64 additions & 0 deletions app/assets/javascripts/hyrax/autocomplete.es6
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import Default from './autocomplete/default'
import Resource from './autocomplete/resource'
import LinkedData from './autocomplete/linked_data'

// OVERRIDE: Add in new field to the autocomplete form
export default class Autocomplete {
/**
* Setup for the autocomplete field.
* @param {jQuery} element - The input field to add autocompete to
* @param {string} fieldName - The name of the field (e.g. 'based_near')
* @param {string} url - The url for the autocompete search endpoint
*/
setup (element, fieldName, url) {
if(element.data('autocomplete-type') && element.data('autocomplete-type').length > 0) {
this.byDataAttribute(element, url)
} else {
this.byFieldName(element, fieldName, url)
}
}

byDataAttribute(element, url) {
let type = element.data('autocomplete-type')
let exlude = element.data('exclude-work')
if(type === 'resource' && exclude.length > 0) {
new Resource(
element,
url,
{ excluding: exclude }
)
} else if(type === 'resource' ) {
new Resource(
element,
url)
} else if(type === 'linked') {
new LinkedData(element, url)
} else {
new Default(element, url)
}
}

byFieldName(element, fieldName, url) {
switch (fieldName) {
case 'work':
new Resource(
element,
url,
{ excluding: element.data('exclude-work') }
)
break
case 'collection':
new Resource(
element,
url)
break
// ADD: Add case for 'funding_body' on autocomplete
case 'funding_body':
case 'based_near':
new LinkedData(element, url)
default:
new Default(element, url)
break
}
}
}
2 changes: 1 addition & 1 deletion app/controllers/catalog_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ def self.modified_field
config.add_facet_field solr_name('degree_level', :facetable), limit: 5, label: 'Degree Level'
config.add_facet_field solr_name('degree_name', :facetable), limit: 5, label: 'Degree Name'
config.add_facet_field solr_name('file_format', :facetable), label: 'File Format', limit: 5
config.add_facet_field solr_name('funding_body', :facetable), label: 'Funding Body', limit: 5
config.add_facet_field solr_name('funding_body_label', :facetable), label: 'Funding Body', limit: 5
config.add_facet_field 'has_journal_sfacet', limit: 5, label: 'Journal Title'
config.add_facet_field 'language_label_ssim', label: 'Language', limit: 5
config.add_facet_field 'license_label_ssim', label: 'License', limit: 5
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,13 @@ def edit
end

def update
store_funding
set_other_option_values
super
end

def create
store_funding
set_other_option_values
super
end
Expand Down Expand Up @@ -74,6 +76,35 @@ def destroy_all_files

private

# METHOD: Manually add controlled_vocab object to funding body
def store_funding
straleyb marked this conversation as resolved.
Show resolved Hide resolved
# FETCH: Get the attributes from params, setup a tmp array, & get object if exist in curation_concern
funding_params = params[hash_key_for_curation_concern]['funding_body_attributes']
funding_current = curation_concern.funding_body.blank? ? [] : curation_concern.funding_body
tmp_arr = []

# LOOP: Loop through each entry from attribute(s)
funding_params.each do |_key, value|
# CREATE & CHECK: Setup a exist tracker to see if already exist in work & skip if 'id' value is blank
exist_tracker = 0
next if value['id'].blank? || value['_destroy'] == 'true'

# LOOP: Check the current funding to see if any exist so we don't have to create a new 'cv'
funding_current.each do |current|
if current.id == value['id']
tmp_arr << current
exist_tracker = 1
end
end

# CONDITION: If no 'id' match current, then create a new 'cv'
tmp_arr << ScholarsArchive::ControlledVocabularies::ResearchOrganizationRegistry.new(value['id']) if exist_tracker.zero?
end

# RETURN: Assign the obj arrays into the funding_body area
curation_concern.funding_body = tmp_arr.flatten
end

# METHOD: Create a method to fetch individual file set
def file_set_actor(file_set)
Hyrax::Actors::FileSetActor.new(file_set, current_user)
Expand Down
5 changes: 3 additions & 2 deletions app/models/concerns/scholars_archive/default_metadata.rb
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,8 @@ def set_default_visibility
index.as :stored_searchable, :facetable
end

property :funding_body, predicate: ::RDF::Vocab::MARCRelators.fnd do |index|
# UPDATE: Add in the class name for 'controlled_vocab' to the funding_body
property :funding_body, predicate: ::RDF::Vocab::MARCRelators.fnd, class_name: ScholarsArchive::ControlledVocabularies::ResearchOrganizationRegistry do |index|
index.as :stored_searchable, :facetable
end

Expand Down Expand Up @@ -299,7 +300,7 @@ def set_default_visibility
attr_accessor :current_username

class_attribute :controlled_properties
self.controlled_properties = [:based_near]
self.controlled_properties = %i[based_near funding_body]
end
end
end
5 changes: 5 additions & 0 deletions app/models/solr_document.rb
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,11 @@ def embargo_date_range
self['embargo_date_range_ssim']
end

# METHOD: A funding_body fetching label method
def funding_body_label
ScholarsArchive::LabelParserService.parse_label_uris(self['funding_body_linked_ssim']) || []
end

def nested_geo
self['nested_geo_label_ssim'] || []
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ module DefaultPresenterBehavior
:other_affiliation_label,
:peerreviewed_label,
:based_near_linked_label,
:funding_body_label,
:rights_statement_label, to: :solr_document
delegate(*::ScholarsArchive::DefaultTerms.base_terms, to: :solr_document)
end
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# frozen_string_literal: true

module ScholarsArchive
# SERVICE: Add in class for ROR Service
class ResearchOrganizationRegistryService < ::Qa::Authorities::ResearchOrganizationRegistry
CACHE_KEY_PREFIX = 'scholars_archive_ror_label-v1-'
CACHE_EXPIRATION = 1.week

# All method follow the exact same layout on how Hyrax::LocationService works
def full_label(uri)
return if uri.blank?

id = extract_id uri
Rails.cache.fetch(cache_key(id), expires_in: CACHE_EXPIRATION) do
label.call(find(id))
end
rescue URI::InvalidURIError
# Old data may be just a string, display it.
uri
end

private

def extract_id(obj)
uri = case obj
when String
URI(obj)
when URI
obj
else
raise ArgumentError, "#{obj} is not a valid type"
end
uri.path.split('/').last
end

def cache_key(id)
"#{CACHE_KEY_PREFIX}#{id}"
end
end
end
13 changes: 13 additions & 0 deletions app/views/records/edit_fields/_funding_body.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<%# OVERRIDE: Override the edit field for 'funding_body' to have autocomplete field %>
<%= f.input key,
as: :controlled_vocabulary,
placeholder: 'Search for a funding body',
input_html: {
class: 'form-control',
data: { 'autocomplete-url' => "/authorities/search/research_organization_registry",
'autocomplete' => key }
},
### Required for the ControlledVocabulary javascript:
wrapper_html: { data: { 'autocomplete-url' => "/authorities/search/research_organization_registry",
'field-name' => key }},
required: f.object.required?(key) %>
16 changes: 14 additions & 2 deletions app/workers/fetch_failed_graph_worker.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ class FetchFailedGraphWorker
include Sidekiq::Worker
sidekiq_options retry: 11

def perform(pid, val, _controlled_prop)
# rubocop:disable Metrics/MethodLength
def perform(pid, val, controlled_prop)
work = ActiveFedora::Base.find(pid)
solr_doc = work.to_solr

Expand All @@ -14,18 +15,29 @@ def perform(pid, val, _controlled_prop)
val.persist!
end

solr_based_near_linked_insert(solr_doc, val)
if controlled_prop.to_s == 'based_near'
solr_based_near_linked_insert(solr_doc, val)
else
solr_funding_body_linked_insert(solr_doc, val)
end

ActiveFedora::SolrService.add(solr_doc)
ActiveFedora::SolrService.commit
end
# rubocop:enable Metrics/MethodLength

def solr_based_near_linked_insert(solr_doc, val)
solr_doc['based_near_linked_tesim'] = [val.solrize.last.is_a?(String) ? val.solrize.last : val.solrize.last[:label].split('$').first]
solr_doc['based_near_linked_ssim'] = [val.solrize.last.is_a?(String) ? val.solrize.last : val.solrize.last[:label].split('$').first]
solr_doc['based_near_linked_sim'] = [val.solrize.last.is_a?(String) ? val.solrize.last : val.solrize.last[:label].split('$').first]
end

def solr_funding_body_linked_insert(solr_doc, val)
solr_doc['funding_body_linked_tesim'] = [val.solrize.last.is_a?(String) ? val.solrize.last : val.solrize.last[:label].split('$').first]
solr_doc['funding_body_linked_ssim'] = [val.solrize.last.is_a?(String) ? val.solrize.last : val.solrize.last[:label].split('$').first]
solr_doc['funding_body_linked_sim'] = [val.solrize.last.is_a?(String) ? val.solrize.last : val.solrize.last[:label].split('$').first]
end

def default_accept_header
RDF::Util::File::HttpAdapter.default_accept_header.sub(%r{, \*\/\*;q=0\.1\Z}, '')
end
Expand Down
65 changes: 47 additions & 18 deletions app/workers/fetch_graph_worker.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,46 +6,63 @@ class FetchGraphWorker
sidekiq_options retry: 11

# rubocop:disable Metrics/MethodLength
# rubocop:disable Metrics/CyclomaticComplexity
# rubocop:disable Metrics/PerceivedComplexity
def perform(pid, _user_key)
work = ActiveFedora::Base.find(pid)
solr_doc = work.to_solr

# VARIABLES: Create two labels to store value of location in
labels_linked = []
labels_only = []

work.attributes['based_near'].each do |val|
val = Hyrax::ControlledVocabularies::Location.new(val) if val.include? 'sws.geonames.org'

next if fetch_and_persist(val, pid) == false

# ADD: Add the val into the labels arr to be added to solr
labels_linked << extracted_label(val.solrize, onlylabel: false)
labels_only << extracted_label(val.solrize, onlylabel: true)
# LOOP: Loop through controlled_properties to fetch work
work.controlled_properties.each do |cv|
# VARIABLES: Create two labels to store value of location in
labels_linked = []
labels_only = []

work.attributes[cv.to_s].each do |val|
if cv.to_s == 'based_near'
val = Hyrax::ControlledVocabularies::Location.new(val) if val.include? 'sws.geonames.org'
elsif val.include? 'ror.org'
val = ScholarsArchive::ControlledVocabularies::ResearchOrganizationRegistry.new(val)
end

next if fetch_and_persist(val, pid, cv) == false

# ADD: Add the val into the labels arr to be added to solr
labels_linked << extracted_label(val.solrize, onlylabel: false)
labels_only << extracted_label(val.solrize, onlylabel: true)
end

# INSERT: Added to solr to appropriate field
if cv.to_s == 'based_near'
solr_based_near_linked_insert(solr_doc, labels_linked)
solr_based_near_label_insert(solr_doc, labels_only)
else
solr_funding_body_linked_insert(solr_doc, labels_linked)
solr_funding_body_label_insert(solr_doc, labels_only)
end
end

# INSERT: Added to solr to appropriate field
solr_based_near_linked_insert(solr_doc, labels_linked)
solr_based_near_label_insert(solr_doc, labels_only)

ActiveFedora::SolrService.add(solr_doc)
ActiveFedora::SolrService.commit
end
# rubocop:enable Metrics/MethodLength
# rubocop:enable Metrics/CyclomaticComplexity
# rubocop:enable Metrics/PerceivedComplexity

def fetch_and_persist(val, pid)
def fetch_and_persist(val, pid, controlled_prop)
begin
val.fetch(headers: { 'Accept' => default_accept_header }) if val.respond_to?(:fetch)
# rubocop:disable Style/RescueStandardError
rescue => e
Rails.logger.info "Failed #{e}"
fetch_failed_graph(pid, val, :based_near)
fetch_failed_graph(pid, val, controlled_prop)
return false
end
# rubocop:enable Style/RescueStandardError
val.persist!
end

# SOLR: Add based_near index
def solr_based_near_linked_insert(solr_doc, labels_linked)
solr_doc['based_near_linked_tesim'] = labels_linked
solr_doc['based_near_linked_ssim'] = labels_linked
Expand All @@ -57,6 +74,18 @@ def solr_based_near_label_insert(solr_doc, labels_only)
solr_doc['based_near_label_sim'] = ScholarsArchive::LabelParserService.location_parse_labels(labels_only)
end

# SOLR: Add funding_body index
def solr_funding_body_linked_insert(solr_doc, labels_linked)
solr_doc['funding_body_linked_tesim'] = labels_linked
solr_doc['funding_body_linked_ssim'] = labels_linked
solr_doc['funding_body_linked_sim'] = labels_linked
end

def solr_funding_body_label_insert(solr_doc, labels_only)
solr_doc['funding_body_label_tesim'] = labels_only
solr_doc['funding_body_label_sim'] = labels_only
end

def extracted_label(input, onlylabel: false)
return input.last if input.last.is_a?(String)

Expand Down
Loading