diff --git a/src/css/metacatui-common.css b/src/css/metacatui-common.css index f786db5ce..6b167e72d 100644 --- a/src/css/metacatui-common.css +++ b/src/css/metacatui-common.css @@ -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; diff --git a/src/js/models/AppModel.js b/src/js/models/AppModel.js index ec03f714f..065f86ba5 100644 --- a/src/js/models/AppModel.js +++ b/src/js/models/AppModel.js @@ -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 diff --git a/src/js/models/LookupModel.js b/src/js/models/LookupModel.js index 34ad80f75..d65573b4e 100644 --- a/src/js/models/LookupModel.js +++ b/src/js/models/LookupModel.js @@ -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) { diff --git a/src/js/views/metadata/EML211View.js b/src/js/views/metadata/EML211View.js index 700595a1b..dead17758 100644 --- a/src/js/views/metadata/EML211View.js +++ b/src/js/views/metadata/EML211View.js @@ -1196,7 +1196,6 @@ define(['underscore', 'jquery', 'backbone', fundingInput.val(value); $(".funding .ui-helper-hidden-accessible").hide(); - loadingSpinner.css("top", "5px"); view.updateFunding(e);