Skip to content
Draft
Show file tree
Hide file tree
Changes from 13 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
12 changes: 8 additions & 4 deletions app/controllers/contributors_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -114,13 +114,17 @@ def translate_roles(hash:)
def process_org(hash:)
return hash unless hash.present? && hash[:org_id].present?

allow = !Rails.configuration.x.application.restrict_orgs
org = org_from_params(params_in: hash,
allow_create: allow)
org = org_from_params(params_in: hash, allow_create: true)

if org.nil?
flash[:alert] =
_('Invalid contributor affiliation. Please double check that your organisation does not appear in the list ' \
'in a slightly different form.')
end

hash = remove_org_selection_params(params_in: hash)

return hash if org.blank? && !allow
return hash if org.blank?
return hash unless org.present?

hash[:org_id] = org.id
Expand Down
13 changes: 12 additions & 1 deletion app/javascript/src/utils/autoComplete.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import 'jquery-ui/ui/widgets/autocomplete';
import getConstant from './constants';
import { isObject, isString, isArray } from './isType';
import debounce from '../utils/debounce';

// Updates the ARIA help text that lets the user know how many suggestions
const updateAriaHelper = (autocomplete, suggestionCount) => {
Expand Down Expand Up @@ -94,6 +95,12 @@ const toggleWarning = (autocomplete, displayIt) => {
}
};

// Delayed warning display (fires only after typing pauses)
const debouncedToggleWarning = debounce((autocomplete, displayIt) => {
toggleWarning(autocomplete, displayIt);
}, 1000);


// Looks up the value in the crosswalk
const findInCrosswalk = (selection, crosswalk) => {
// Default to the name only
Expand Down Expand Up @@ -123,7 +130,11 @@ const warnableSelection = (selection) => {
const handleSelection = (autocomplete, hidden, crosswalk, selection) => {
const out = findInCrosswalk(selection, crosswalk);

toggleWarning(autocomplete, warnableSelection(out));
// When user types, 'displayIt = false' hides warning initially
toggleWarning(autocomplete, false);

// After user pauses for 1 second, show warning
debouncedToggleWarning(autocomplete, warnableSelection(out));

// Set the ID and trigger the onChange event for any view specific
// JS to trigger events
Expand Down
32 changes: 27 additions & 5 deletions app/services/org_selection/hash_to_org_service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,24 @@ def to_identifiers(hash:)

private

def match_hash_to_ror_org(hash:)
return nil unless hash.present?
return nil unless hash[:name].present?

ror_results =
OrgSelection::SearchService.search_externally(
search_term: hash[:name]
)

return nil unless ror_results.present?

# If ROR is provided, require it to match
correct_org = ror_results.find { |r| r[:ror] == hash[:ror] } if hash[:ror].present?
return correct_org if correct_org

nil
end

# Lookup the Org by it's :id and return if the name matches the search
def lookup_org_by_id(hash:)
org = Org.where(id: hash[:id]).first if hash[:id].present?
Expand Down Expand Up @@ -92,14 +110,18 @@ def lookup_org_by_name(hash:)
def initialize_org(hash:)
return nil unless hash.present? && hash[:name].present?

# Attempt to find an ROR match to the hash
ror_hash = match_hash_to_ror_org(hash: hash)
return nil unless ror_hash

Org.new(
name: hash[:name],
links: links_from_hash(name: hash[:name], website: hash[:url]),
language: language_from_hash(hash: hash),
target_url: hash[:url],
name: ror_hash[:name],
links: links_from_hash(name: ror_hash[:name], website: ror_hash[:url]),
language: language_from_hash(hash: ror_hash),
target_url: ror_hash[:url],
institution: true,
is_other: false,
abbreviation: abbreviation_from_hash(hash: hash)
abbreviation: abbreviation_from_hash(hash: ror_hash)
)
end

Expand Down
3 changes: 1 addition & 2 deletions app/views/contributors/_form.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,8 @@ roles_tooltip = _("Select each role that applies to the contributor.")

<div class="form-group row" id="contributor-org-controls"><!-- org -->
<div class="col-md-8">
<%= render partial: org_partial,
<%= render partial:'shared/org_selectors/combined',
locals: { form: form,
orgs: orgs,
default_org: contributor.org,
required: false,
label: _("Affiliation") } %>
Expand Down
2 changes: 1 addition & 1 deletion app/views/shared/org_selectors/_combined.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -47,5 +47,5 @@ placeholder = _("Begin typing to see a list of suggestions.")
class: "autocomplete-result" %>

<p class="autocomplete-warning red hide">
<%= _("A new entry will be created for the organisation you have named above. Please double check that your organisation does not appear in the list in a slightly different form.").html_safe %>
<%= _("Please double check that your organisation does not appear in the list in a slightly different form.").html_safe %>
</p>
10 changes: 10 additions & 0 deletions spec/controllers/contributors_controller_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,12 @@
end

describe '#process_org(hash:)' do
before do
@request = ActionDispatch::TestRequest.create
@response = ActionDispatch::TestResponse.create
@controller.request = @request
@controller.response = @response
end
it 'returns the hash as is if no :org_id is present' do
@params_hash[:contributor].delete(:org_id)
hash = @controller.send(:process_org, hash: @params_hash[:contributor])
Expand All @@ -159,6 +165,10 @@
end
it 'sets the org_id to the idea of the org' do
new_org = create(:org)
# Clear name, id, and ror to prevent matching any existing org
@params_hash[:contributor][:org_name] = nil
@params_hash[:contributor][:org_id] = { id: nil, name: nil, ror: nil }.to_json

@controller.stubs(:org_from_params).returns(new_org)
hash = @controller.send(:process_org, hash: @params_hash[:contributor])
expect(hash[:org_id]).to eql(new_org.id)
Expand Down
29 changes: 29 additions & 0 deletions spec/services/org_selection/hash_to_org_service_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,20 @@
expect(described_class.to_org(hash: @hash)).to eql(org)
end
it 'returns a new Org instance' do
fake_ror = {
ror: Faker::Alphanumeric.alphanumeric(number: 9),
name: "#{@name} (#{@abbrev})",
sort_name: @name,
url: @url,
language: @lang.abbreviation,
fundref: '',
abbreviation: @abbrev,
score: @hash[:score],
weight: @hash[:weight]
}
# Stub the ROR matcher to return the fake ROR hash
# As valid ROR hash is needed for new org creation
described_class.stubs(:match_hash_to_ror_org).returns(fake_ror)
expect(described_class.to_org(hash: @hash).new_record?).to eql(true)
end
end
Expand Down Expand Up @@ -95,6 +109,21 @@
expect(rslt).to eql(nil)
end
it 'returns a new instance of Org' do
fake_ror = {
ror: Faker::Alphanumeric.alphanumeric(number: 9),
name: "#{@name} (#{@abbrev})",
sort_name: @name,
url: @url,
language: @lang.abbreviation,
fundref: '',
abbreviation: @abbrev,
score: @hash[:score],
weight: @hash[:weight]
}
# Stub the ROR matcher to return the fake ROR hash
# As valid ROR hash is needed for new org creation
described_class.stubs(:match_hash_to_ror_org).returns(fake_ror)

rslt = described_class.send(:initialize_org, hash: @hash)
nm = "#{@name} (#{@abbrev})"
lnks = JSON.parse({ org: [{ link: @url, text: nm }] }.to_json)
Expand Down