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

267 add url test to resources #306

Merged
merged 36 commits into from
Jan 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
519ef2c
add debounce util function
sorochak Jan 15, 2024
4c9dcbf
added checkURL misc util function
sorochak Jan 15, 2024
1c0815b
validateURL already defined in validate.js, remove definition from Re…
sorochak Jan 16, 2024
cfe7e21
add isURLActive
sorochak Jan 16, 2024
42d78ba
update debounce to handle promises and be more readable
sorochak Jan 16, 2024
44dc768
add isURLActive Firebase Function
sorochak Jan 16, 2024
3ccfb11
fix url assignment
sorochak Jan 17, 2024
fc5749f
use url variable
sorochak Jan 17, 2024
8a829d8
Merge remote-tracking branch 'origin/main' into 267-add-url-test-to-r…
sorochak Jan 17, 2024
045dc6c
update checkURLActive function
sorochak Jan 17, 2024
7b9584f
implement checkURLActive call in Resources component
sorochak Jan 17, 2024
c1b71d5
add more debugging logs for checkURLActive:
sorochak Jan 23, 2024
ec2d3f6
broken - debounce url input
sorochak Jan 24, 2024
b05b0db
urlMessage
sorochak Jan 24, 2024
ae48f4a
provide positive feedback for active URL
sorochak Jan 24, 2024
1c69d16
this seems to get pretty close to what we want. There is still an err…
fostermh Jan 24, 2024
463cfef
Merge branch '267-add-url-test-to-resources' of https://github.com/ci…
fostermh Jan 24, 2024
7fa9b7b
url warning validation - broken
sorochak Jan 25, 2024
edd8ce1
Merge branch '267-add-url-test-to-resources' of github.com:cioos-sioo…
sorochak Jan 25, 2024
377f86b
super hack
fostermh Jan 25, 2024
8671b68
remove unused custom debounce util func
sorochak Jan 25, 2024
e98c5f9
reduce debounce time from 3s to 1s
sorochak Jan 25, 2024
9d243df
fix 'record' naming collision as per linter error
sorochak Jan 25, 2024
510cf09
fix linter warning Assignment to function parameter 'val'
sorochak Jan 25, 2024
c1b8cf4
Refactor to replace for...of loop with array methods as per linter wa…
sorochak Jan 25, 2024
e5b7188
fix memory leak errors
sorochak Jan 25, 2024
423361f
reduce debounce time
sorochak Jan 25, 2024
e251517
cleanup logs and unused code
sorochak Jan 25, 2024
ea8303f
remove irrelevant comment
sorochak Jan 25, 2024
c75ff37
Merge remote-tracking branch 'origin/main' into 267-add-url-test-to-r…
sorochak Jan 25, 2024
1f93788
attempt to solve debounce bug
sorochak Jan 25, 2024
6a248dc
reduce debounce time
sorochak Jan 25, 2024
deb4982
add headings for errors & warnings on submit page
sorochak Jan 26, 2024
c107106
fix debounce on resouces
fostermh Jan 26, 2024
9934569
Merge remote-tracking branch 'origin/da_debounce' into 267-add-url-te…
sorochak Jan 26, 2024
2c97aba
cleanup useEffect
sorochak Jan 26, 2024
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
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
Loading