Skip to content

Commit

Permalink
Merge pull request #306 from cioos-siooc/267-add-url-test-to-resources
Browse files Browse the repository at this point in the history
267 add url test to resources
  • Loading branch information
sorochak authored Jan 29, 2024
2 parents 9772be6 + 2c97aba commit e47246d
Show file tree
Hide file tree
Showing 10 changed files with 261 additions and 17 deletions.
2 changes: 2 additions & 0 deletions firebase-functions/functions/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
const admin = require("firebase-admin");
const { translate } = require("./translate");
const { checkURLActive } = require("./serverUtils");
const { createDraftDoi, updateDraftDoi, deleteDraftDoi, getDoiStatus } = require("./datacite");
const { notifyReviewer, notifyUser } = require("./notify");
const {
Expand All @@ -24,3 +25,4 @@ exports.createDraftDoi = createDraftDoi;
exports.deleteDraftDoi = deleteDraftDoi;
exports.updateDraftDoi = updateDraftDoi;
exports.getDoiStatus = getDoiStatus;
exports.checkURLActive = checkURLActive;
26 changes: 26 additions & 0 deletions firebase-functions/functions/serverUtils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
const functions = require("firebase-functions");
const fetch = require('node-fetch');

// Function to check if a given URL is active
exports.checkURLActive = functions.https.onCall(async (data) => {
let url = data;
functions.logger.log('Received URL:', url);

if (!url) {
throw new functions.https.HttpsError('invalid-argument', 'The function must be called with one argument "url".');
}

// Prepend 'http://' if the URL does not start with 'http://' or 'https://'
if (!url.startsWith('http://') && !url.startsWith('https://')) {
url = 'http://' + url;
}

try {
const response = await fetch(url, {method: "HEAD" });
functions.logger.log(`Fetch response status for ${url}:`, response.status);
return response.ok; // Return true if response is OK, otherwise false
} catch (error) {
functions.logger.error('Error in checkURLActive for URL:', url, error);
return false; // Return false if an error occurs
}
})
11 changes: 11 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"firebase-admin": "^11.5.0",
"firebase-functions": "^4.2.1",
"javascript-time-ago": "^2.3.4",
"just-debounce-it": "1.0.1",
"leaflet": "^1.6.0",
"leaflet-draw": "^1.0.4",
"nunjucks": "^3.2.3",
Expand Down
16 changes: 12 additions & 4 deletions src/components/FormComponents/ContactEditor.jsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useEffect, useState } from "react";
import React, { useEffect, useState, useRef } from "react";

import {
TextField,
Expand Down Expand Up @@ -45,6 +45,7 @@ const ContactEditor = ({
updateContactRor,
updateContactOrcid,
}) => {
const mounted = useRef(false);
const orgEmailValid = validateEmail(value.orgEmail);
const indEmailValid = validateEmail(value.indEmail);
const orgURLValid = validateURL(value.orgURL);
Expand All @@ -64,19 +65,26 @@ const ContactEditor = ({
newInputValue.startsWith("http") &&
!newInputValue.includes("ror.org")
) {
setRorSearchActive(false);
if (mounted.current) setRorSearchActive(false);
} else {
fetch(`https://api.ror.org/organizations?query=${newInputValue}`)
.then((response) => response.json())
.then((response) => setRorOptions(response.items))
.then(() => setRorSearchActive(false));
.then((response) => {if (mounted.current) setRorOptions(response.items)})
.then(() => {if (mounted.current) setRorSearchActive(false)});
}
}

useEffect(() => {

mounted.current = true;

if (debouncedRorInputValue) {
updateRorOptions(debouncedRorInputValue);
}

return () => {
mounted.current = false;
};
}, [debouncedRorInputValue]);

return (
Expand Down
57 changes: 46 additions & 11 deletions src/components/FormComponents/Resources.jsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from "react";
import React, { useContext, useEffect, useState, useRef } from "react";
import {
Add,
Delete,
Expand All @@ -7,18 +7,49 @@ import {
} from "@material-ui/icons";
import { Button, Grid, Paper, TextField } from "@material-ui/core";
import validator from "validator";
import debounce from "just-debounce-it";
import { En, Fr, I18n } from "../I18n";

import BilingualTextInput from "./BilingualTextInput";
import RequiredMark from "./RequiredMark";
import { deepCopy } from "../../utils/misc";
import { validateURL } from "../../utils/validate";
import { QuestionText, paperClass, SupplementalText } from "./QuestionStyles";

const validateURL = (url) => !url || validator.isURL(url);
import { UserContext } from "../../providers/UserProvider";

const Resources = ({ updateResources, resources, disabled }) => {

const mounted = useRef(false);
const { checkURLActive } = useContext(UserContext);
const [urlIsActive, setUrlIsActive] = useState({});
const emptyResource = { url: "", name: "", description: { en: "", fr: "" } };

const debouncePool = useRef({});

useEffect( () => {

mounted.current = true

resources.forEach( (resource, idx) => {

if (resource.url && validateURL(resource.url)) {
if (!debouncePool.current[idx]){
debouncePool.current[idx] = debounce( async (innerResource) => {
const response = await checkURLActive(innerResource.url)
if (mounted.current){
setUrlIsActive((prevStatus) => ({ ...prevStatus, [innerResource.url]: response.data }))
}
}, 500);
}
debouncePool.current[idx](resource);
}
});

return () => {
mounted.current = false;
};
}, [resources, checkURLActive]);

function addResource() {
updateResources(resources.concat(deepCopy(emptyResource)));
}
Expand All @@ -35,13 +66,15 @@ const Resources = ({ updateResources, resources, disabled }) => {
resources.splice(newIndex, 0, element);
updateResources(resources);
}

const nameLabel = <I18n en="Name" fr="Titre" />;
const descriptionLabel = <I18n en="Description" fr="Description" />;

return (
<div>
{resources.map((dist = deepCopy(emptyResource), i) => {
const urlIsValid = !dist.url || validateURL(dist.url);
{resources.map((resourceItem = deepCopy(emptyResource), i) => {
const urlIsValid = !resourceItem.url || validateURL(resourceItem.url);

function handleResourceChange(key) {
return (e) => {
const newValue = [...resources];
Expand All @@ -58,11 +91,11 @@ const Resources = ({ updateResources, resources, disabled }) => {
<En>Enter a name for the resource</En>
<Fr>Entrez un titre pour la ressource</Fr>
</I18n>
<RequiredMark passes={dist.name?.en || dist.name?.fr} />
<RequiredMark passes={resourceItem.name?.en || resourceItem.name?.fr} />
</QuestionText>
<BilingualTextInput
label={nameLabel}
value={dist.name}
value={resourceItem.name}
onChange={handleResourceChange("name")}
fullWidth
disabled={disabled}
Expand All @@ -75,7 +108,7 @@ const Resources = ({ updateResources, resources, disabled }) => {
<Fr>Entrez l'URL de la ressource</Fr>
</I18n>

<RequiredMark passes={validator.isURL(dist.url)} />
<RequiredMark passes={validator.isURL(resourceItem.url)} />
<SupplementalText>
<I18n>
<En>
Expand All @@ -99,11 +132,13 @@ const Resources = ({ updateResources, resources, disabled }) => {

<TextField
helperText={
!urlIsValid && <I18n en="Invalid URL" fr="URL non valide" />
(!urlIsValid && <I18n en="Invalid URL" fr="URL non valide" />)
|| (resourceItem.url && urlIsActive[resourceItem.url] === false && <I18n en="URL is not active" fr="L'URL n'est pas active" />)
|| (resourceItem.url && urlIsActive[resourceItem.url] === true && <I18n en="URL is active" fr="L'URL est active" />)
}
error={!urlIsValid}
label="URL"
value={dist.url}
value={resourceItem.url}
onChange={handleResourceChange("url")}
fullWidth
disabled={disabled}
Expand All @@ -119,7 +154,7 @@ const Resources = ({ updateResources, resources, disabled }) => {
<BilingualTextInput
name="description"
label={descriptionLabel}
value={dist.description}
value={resourceItem.description}
onChange={handleResourceChange("description")}
disabled={disabled}
/>
Expand Down
Loading

0 comments on commit e47246d

Please sign in to comment.