Skip to content

Commit

Permalink
Fix grant/funding lookup
Browse files Browse the repository at this point in the history
- Update the default grantsUrl to point to a proxy relative to the repository’s domain
- Remove unused getGrant method from the LookupModel
- Use native fetch API instead of jQuery.ajax to retrieve grants
- Show spinner to indicate that grants are being retrieved (was set up but not used)
- Move some logic from the getGrantAutocomplete method to new, smaller methods
- Add missing JS docs
- Add error handling

Issue #2233
  • Loading branch information
robyngit committed Jan 16, 2024
1 parent 5831d46 commit 6316b35
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 95 deletions.
8 changes: 4 additions & 4 deletions src/css/metacatui-common.css
Original file line number Diff line number Diff line change
Expand Up @@ -8322,11 +8322,11 @@ textarea.medium{
position: relative;
}
.Editor .funding-container .icon-spinner{
position: absolute;
left: 11px;
top: 5px;
left: 45px;
position: absolute;
font-size: 1.5em;
display: none;
font-size: 1.5em;
display: none;
}
.metadata-container #funding-visible{
padding-left: 30px;
Expand Down
4 changes: 2 additions & 2 deletions src/js/models/AppModel.js
Original file line number Diff line number Diff line change
Expand Up @@ -722,9 +722,9 @@ define(['jquery', 'underscore', 'backbone'],
* The URL for the NSF Award API, which can be used by the {@link LookupModel}
* to look up award information for the dataset editor or other views
* @type {string}
* @default "https://www.research.gov/awardapi-service/v1/awards.json"
* @default "/research.gov/awardapi-service/v1/awards.json"
*/
grantsUrl: "https://www.research.gov/awardapi-service/v1/awards.json",
grantsUrl: "/research.gov/awardapi-service/v1/awards.json",

/**
* The base URL for the ORCID REST services
Expand Down
180 changes: 92 additions & 88 deletions src/js/models/LookupModel.js
Original file line number Diff line number Diff line change
Expand Up @@ -375,99 +375,103 @@ define(["jquery", "jqueryui", "underscore", "backbone"], function (
});
},

getGrantAutocomplete: function (request, response) {
var term = $.ui.autocomplete.escapeRegex(request.term),
filterBy = "";

// Only search after 3 characters or more. Don't search for digit only
// since it's most likely a user just entering the grant number directly
if (term.length < 3) return;
else if (term.match(/\d/))
return;
else filterBy = "keyword";

var url =
MetacatUI.appModel.get("grantsUrl") +
"?" +
filterBy +
"=" +
term +
"&printFields=title,id";

// Send the AJAX request as a JSONP data type since it will be
// cross-origin
var requestSettings = {
url: url,
dataType: "jsonp",
success: function (data, textStatus, xhr) {
// Handle the response from the NSF Award Search API and transform
//each award query result into a jQueryUI autocomplete item

if (!data || !data.response || !data.response.award) return [];

var list = [];
/**
* Using the NSF Award Search API, get a list of grants that match the
* given term, as long as the term is at least 3 characters long and
* doesn't consist of only digits. Used to populate the autocomplete list
* for the Funding fields in the metadata editor. For this method to work,
* there must be a grantsUrl set in the MetacatUI.appModel.
* @param {jQuery} request - The jQuery UI autocomplete request object
* @param {function} response - The jQuery UI autocomplete response function
* @see {@link https://www.research.gov/common/webapi/awardapisearch-v1.htm}
*/
getGrantAutocomplete: function (
request,
response,
beforeRequest,
afterRequest
) {
// Handle errors in this function or in the findGrants function
function handleError(error) {
if (typeof afterRequest == "function") afterRequest();
console.log("Error fetching awards from NSF: ", error);
response([]);
}

_.each(data.response.award, function (award, i) {
list.push({
value: award.id,
label: award.title,
});
try {
let term = request.term;

// Only search after 3 characters or more, and not just digits
if (!term || term.length < 3 || /^\d+$/.test(term)) return;

// If the beforeRequest function was passed, call it now
if (typeof beforeRequest == "function") beforeRequest();

// Search for grants
this.findGrants(term)
.then((awards) => {
response(this.formatFundingForAutocomplete(awards));
})
.catch(handleError)
.finally(() => {
if (typeof afterRequest == "function") afterRequest();
});

var term = $.ui.autocomplete.escapeRegex(request.term),
startsWithMatcher = new RegExp("^" + term, "i"),
startsWith = $.grep(list, function (value) {
return startsWithMatcher.test(
value.label || value.value || value
);
}),
containsMatcher = new RegExp(term, "i"),
contains = $.grep(list, function (value) {
return (
$.inArray(value, startsWith) < 0 &&
containsMatcher.test(value.label || value.value || value)
);
});

response(startsWith.concat(contains));
},
};

//Send the query
$.ajax(requestSettings);
} catch (error) {
handleError(error);
}
},

getGrant: function (id, onSuccess, onError) {
if (
!id ||
!onSuccess ||
!MetacatUI.appModel.get("useNSFAwardAPI") ||
!MetacatUI.appModel.get("grantsUrl")
)
return;

var requestSettings = {
url: MetacatUI.appModel.get("grantsUrl") + "?id=" + id,
success: function (data, textStatus, xhr) {
if (
!data ||
!data.response ||
!data.response.award ||
!data.response.award.length
) {
if (onError) onError();
return;
}

onSuccess(data.response.award[0]);
},
error: function () {
if (onError) onError();
},
};
/**
* Search the NSF Award Search API for grants that match the given term.
* @param {string} term - The term to search for
* @param {number} [offset=1] - The offset to use in the search. Defaults
* to 1.
* @returns {Promise} A promise that resolves to an array of awards in the
* format {id: string, title: string}
* @since x.x.x
*/
findGrants: function (term, offset = 1) {
let awards = [];
if (!term || term.length < 3) return awards;
const grantsUrl = MetacatUI.appModel.get("grantsUrl");
if (!grantsUrl) return awards;

term = $.ui.autocomplete.escapeRegex(term);
term = encodeURIComponent(term);
const filterBy = "keyword";
const url =
`${grantsUrl}?${filterBy}=${term}` +
`&printFields=title,id&offset=${offset}`;

return fetch(url)
.then((response) => {
return response.json();
})
.then((data) => {
if (!data || !data.response || !data.response.award) return awards;
return data.response.award;
})
.catch((error) => {
console.error("Error fetching data: ", error);
return awards;
});
},

//Send the query
$.ajax(requestSettings);
/**
* Format awards from the NSF Award Search API for use in the jQuery UI
* autocomplete widget.
* @param {Array} awards - An array of awards in the format
* {id: string, title: string}
* @returns {Array} An array of awards in the format
* {value: string, label: string}
* @since x.x.x
*/
formatFundingForAutocomplete: function (awards) {
if (!awards || !awards.length) return [];
return awards.map((award) => ({
value: award.id,
label: award.title,
}));
},

getAccountsAutocomplete: function (request, response) {
Expand Down
1 change: 0 additions & 1 deletion src/js/views/metadata/EML211View.js
Original file line number Diff line number Diff line change
Expand Up @@ -1196,7 +1196,6 @@ define(['underscore', 'jquery', 'backbone',
fundingInput.val(value);

$(".funding .ui-helper-hidden-accessible").hide();
loadingSpinner.css("top", "5px");

view.updateFunding(e);

Expand Down

0 comments on commit 6316b35

Please sign in to comment.