From dd34810d9a5caf40faafbb27110ccad433126313 Mon Sep 17 00:00:00 2001 From: learner97 Date: Tue, 24 Oct 2023 17:51:55 -0600 Subject: [PATCH] changed the instances of replacing synbiohub.org with blanks to using the registries processUrl function. Fixed a couple issues that would lead to render warnings with formatting of tables --- frontend/components/Admin/Registries.js | 3 - frontend/components/Basket/BasketItem.js | 22 +++--- .../StandardSearch/ResultTable/ResultRow.js | 17 ++++- .../Search/StandardSearch/StandardSearch.js | 13 ++-- .../Submission/SubmissionDisplay.js | 16 ++++- .../Submit/SubmissionStatusPanel.js | 22 +++--- .../components/Viewing/Collection/Members.js | 39 ++++++---- frontend/components/Viewing/MetadataInfo.js | 6 +- .../Viewing/PageJSON/Rendering/RowWrapper.js | 10 ++- .../PageJSON/Rendering/SectionRenderer.js | 72 +++++++++++++------ .../components/Viewing/SectionSelector.js | 2 - .../Sections/Attachments/AttachmentRows.js | 26 +++++-- .../Sections/Attachments/UploadAttachments.js | 40 +++++------ .../Viewing/Sections/MemberOfCollections.js | 6 +- frontend/components/Viewing/SidePanel.js | 25 ++++--- 15 files changed, 211 insertions(+), 108 deletions(-) diff --git a/frontend/components/Admin/Registries.js b/frontend/components/Admin/Registries.js index 2133b0ba..9b89e3cd 100644 --- a/frontend/components/Admin/Registries.js +++ b/frontend/components/Admin/Registries.js @@ -281,17 +281,14 @@ const fetcher = (url, token, dispatch) => }); export async function processUrl(inputUrl, token, dispatch) { - console.log(inputUrl) const data = await fetcher(`${publicRuntimeConfig.backend}/admin/registries`, token, dispatch); const registries = data.registries; - console.log(registries) for (const registry of registries) { if (inputUrl.startsWith(registry.uri)) { const urlRemovedForLink = inputUrl.replace(registry.uri, ""); const urlReplacedForBackend = inputUrl.replace(registry.uri, registry.url); - console.log(urlRemovedForLink) return { urlRemovedForLink, urlReplacedForBackend }; } } diff --git a/frontend/components/Basket/BasketItem.js b/frontend/components/Basket/BasketItem.js index a86c2b38..e0e23708 100644 --- a/frontend/components/Basket/BasketItem.js +++ b/frontend/components/Basket/BasketItem.js @@ -3,22 +3,28 @@ import { useRouter } from 'next/router'; import styles from '../../styles/submissions.module.css'; const { publicRuntimeConfig } = getConfig(); +import { processUrl } from '../Admin/Registries'; export default function BasketItem(properties) { const router = useRouter(); + const token = useSelector(state => state.user.token); // assuming you use Redux for state management + const dispatch = useDispatch(); + + // Process the URI using processUrl function + const handleClick = async () => { + const processedUrlData = await processUrl(properties.item.uri, token, dispatch); + if (processedUrlData.urlReplacedForBackend) { + router.push(processedUrlData.urlReplacedForBackend); + } else if (processedUrlData.original) { + router.push(processedUrlData.original); + } + }; return ( { - router.push( - properties.item.uri.replace( - 'https://synbiohub.org', - publicRuntimeConfig.backend - ) - ); - }} + onClick={handleClick} > state.user.token); + const dispatch = useDispatch(); + const [processedUri, setProcessedUri] = useState(properties.uri); + + useEffect(() => { + async function processAndSetUri() { + const result = await processUrl(properties.uri, token, dispatch); + setProcessedUri(result.urlRemovedForLink || result.original); + } + + processAndSetUri(); + }, [properties.uri]); // Identify what type of object the search result is from type url if (potentialType.includes('component')) { @@ -32,7 +47,7 @@ export default function ResultRow(properties) { return ( { - router.push(properties.uri.replace('https://synbiohub.org', '')); + router.push(processedUri); }} > diff --git a/frontend/components/Search/StandardSearch/StandardSearch.js b/frontend/components/Search/StandardSearch/StandardSearch.js index 56cbc833..d780c29e 100644 --- a/frontend/components/Search/StandardSearch/StandardSearch.js +++ b/frontend/components/Search/StandardSearch/StandardSearch.js @@ -5,6 +5,7 @@ import Loader from 'react-loader-spinner'; import { useDispatch, useSelector } from 'react-redux'; import useSWR from 'swr'; const { publicRuntimeConfig } = getConfig(); +import { processUrl } from '../../Admin/Registries'; import { countloader, @@ -124,7 +125,7 @@ const useSearchCount = (query, token, dispatch) => { }; }; -const getTypeAndUrl = result => { +const getTypeAndUrl = async (result, token, dispatch) => { let type = ''; const potentialType = result.type.toLowerCase(); @@ -144,11 +145,15 @@ const getTypeAndUrl = result => { result.type = type; - let newUrl = result.uri.replace('https://synbiohub.org', ''); - newUrl = newUrl.replace('https://dev.synbiohub.org', ''); - result.url = newUrl; + const processed = await processUrl(result.uri, token, dispatch); + result.url = processed.urlRemovedForLink || processed.original; + + // let newUrl = result.uri.replace('https://synbiohub.org', ''); + // newUrl = newUrl.replace('https://dev.synbiohub.org', ''); + // result.url = newUrl; }; + const fetcher = (url, token, dispatch) => axios .get(url, { diff --git a/frontend/components/Submission/SubmissionDisplay.js b/frontend/components/Submission/SubmissionDisplay.js index df1641e2..9fe0bca5 100644 --- a/frontend/components/Submission/SubmissionDisplay.js +++ b/frontend/components/Submission/SubmissionDisplay.js @@ -6,6 +6,8 @@ import { import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { useRouter } from 'next/router'; import { useEffect, useState } from 'react'; +import { processUrl } from '../Admin/Registries'; +import { useDispatch, useSelector } from 'react-redux'; import styles from '../../styles/submissions.module.css'; @@ -13,6 +15,9 @@ export default function SubmissionDisplay(properties) { const router = useRouter(); const [privacyDisplay, setPrivacyDisplay] = useState(); + const [processedUri, setProcessedUri] = useState(properties.submission.uri); + const token = useSelector(state => state.user.token); + const dispatch = useDispatch(); useEffect(() => { if (properties.submission.privacy === 'public') @@ -27,13 +32,22 @@ export default function SubmissionDisplay(properties) { ); }, [properties.submission.privacy]); + useEffect(() => { + async function processAndSetUri() { + const result = await processUrl(properties.submission.uri, token, dispatch); + setProcessedUri(result.urlRemovedForLink || result.original); + } + + processAndSetUri(); + }, [properties.submission.uri]); + return ( { router.push( - properties.submission.uri.replace('https://synbiohub.org', '') + processedUri ); }} > diff --git a/frontend/components/Submit/SubmissionStatusPanel.js b/frontend/components/Submit/SubmissionStatusPanel.js index 9bd157eb..0adc6c57 100644 --- a/frontend/components/Submit/SubmissionStatusPanel.js +++ b/frontend/components/Submit/SubmissionStatusPanel.js @@ -9,6 +9,7 @@ import { useEffect, useState } from 'react'; import Loader from 'react-loader-spinner'; import { useDispatch, useSelector } from 'react-redux'; import { useRouter } from 'next/router'; +import { processUrl } from '../Admin/Registries'; import { resetSubmit } from '../../redux/actions'; import styles from '../../styles/submit.module.css'; @@ -19,9 +20,10 @@ export default function SubmissionStatusPanel() { const fileFailed = useSelector(state => state.submit.fileFailed); const submitting = useSelector(state => state.submit.submitting); const submissionUri = useSelector(state => state.submit.selectedCollection.uri); - console.log(submissionUri); const [header, setHeader] = useState(null); + const [processedUri, setProcessedUri] = useState(submissionUri); + const token = useSelector(state => state.user.token); const dispatch = useDispatch(); const router = useRouter(); @@ -65,7 +67,14 @@ export default function SubmissionStatusPanel() { } }, [submitting, fileFailed]); - var submissionLink = replaceBeginning(submissionUri, "https://synbiohub.org", ""); + useEffect(() => { + async function processAndSetUri() { + const result = await processUrl(submissionUri, token, dispatch); + setProcessedUri(result.urlRemovedForLink || result.original); + } + + processAndSetUri(); + }, [submissionUri]); return (
@@ -89,7 +98,7 @@ export default function SubmissionStatusPanel() { className={styles.aftersubmitbutton} role="button" onClick={() => { - router.push(submissionLink).then(() => { + router.push(processedUri).then(() => { dispatch(resetSubmit()); }); }} @@ -108,10 +117,3 @@ export default function SubmissionStatusPanel() {
); } - -function replaceBeginning(original, oldBeginning, newBeginning) { - if (original.startsWith(oldBeginning)) { - return newBeginning + original.slice(oldBeginning.length); - } - return original; -} diff --git a/frontend/components/Viewing/Collection/Members.js b/frontend/components/Viewing/Collection/Members.js index 9a9f11c3..94b24a01 100644 --- a/frontend/components/Viewing/Collection/Members.js +++ b/frontend/components/Viewing/Collection/Members.js @@ -20,6 +20,7 @@ import { shortName } from '../../../namespace/namespace'; import lookupRole from '../../../namespace/lookupRole'; import Link from 'next/link'; import { addError } from '../../../redux/actions'; +import { processUrl } from '../../Admin/Registries'; /* eslint sonarjs/cognitive-complexity: "off" */ @@ -68,7 +69,7 @@ export default function Members(properties) { const parameters = { graphs: '', - graphPrefix: 'https://synbiohub.org/', + graphPrefix: 'https://synbiohub.org/', // TODO: Maybe get this from somewhere? collection: properties.uri, sort: sort, search: preparedSearch, @@ -217,6 +218,27 @@ function FilterHeader(properties) { } function MemberTable(properties) { + const [processedMembers, setProcessedMembers] = useState([]); + + const token = useSelector(state => state.user.token); + const dispatch = useDispatch(); + useEffect(() => { + async function processMembers() { + if (properties.members) { + const updatedMembers = await Promise.all(properties.members.map(async member => { + const processed = await processUrl(member.uri, token, dispatch); + return { + ...member, + uri: processed.urlRemovedForLink + }; + })); + setProcessedMembers(updatedMembers); + } + } + + processMembers(); + }, [properties.members]); + let count = (
@@ -230,10 +252,9 @@ function MemberTable(properties) { Number(properties.totalMembers).toLocaleString() + ')'; } - console.log(properties) return ( @@ -299,13 +319,6 @@ function getType(member) { return memberType; } -function replaceBeginning(original, oldBeginning, newBeginning) { - if (original.startsWith(oldBeginning)) { - return newBeginning + original.slice(oldBeginning.length); - } - return original; -} - const createUrl = (query, options) => { query = loadTemplate(query, options); return `${publicRuntimeConfig.backend}/sparql?query=${encodeURIComponent( diff --git a/frontend/components/Viewing/MetadataInfo.js b/frontend/components/Viewing/MetadataInfo.js index 0adb23f2..e153d9cf 100644 --- a/frontend/components/Viewing/MetadataInfo.js +++ b/frontend/components/Viewing/MetadataInfo.js @@ -30,7 +30,11 @@ export default function MetadataInfo({ title, link, label, icon, specific }) {
{label}
- {title} +
- + {textArea.value} - + {member.displayId}
+ + {title} + +
); diff --git a/frontend/components/Viewing/PageJSON/Rendering/RowWrapper.js b/frontend/components/Viewing/PageJSON/Rendering/RowWrapper.js index 75d32ac1..2cc62ed2 100644 --- a/frontend/components/Viewing/PageJSON/Rendering/RowWrapper.js +++ b/frontend/components/Viewing/PageJSON/Rendering/RowWrapper.js @@ -243,7 +243,13 @@ export default function RowWrapper({ sections, metadata, setSectionIcon }) { }, [titleToValueMap, sectionsToRender]); if (loading) { - return ; - } + return ( + + {/* colSpan="100%" makes sure it spans the entire width of the table */} + + + + ); + } return {content}; } diff --git a/frontend/components/Viewing/PageJSON/Rendering/SectionRenderer.js b/frontend/components/Viewing/PageJSON/Rendering/SectionRenderer.js index d4770e41..b895d1be 100644 --- a/frontend/components/Viewing/PageJSON/Rendering/SectionRenderer.js +++ b/frontend/components/Viewing/PageJSON/Rendering/SectionRenderer.js @@ -2,7 +2,7 @@ import styles from '../../../../styles/view.module.css'; import Link from 'next/link'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { faSearch } from '@fortawesome/free-solid-svg-icons'; -import { useDispatch } from 'react-redux'; +import { useDispatch, useSelector } from 'react-redux'; import useRegistries from '../Fetching/useRegistries'; import getConfig from 'next/config'; import axios from 'axios'; @@ -11,6 +11,8 @@ import { useState } from 'react'; import { addError } from '../../../../redux/actions'; const { publicRuntimeConfig } = getConfig(); +import { processUrl } from '../../../Admin/Registries'; + function loadText(template, args) { for (const key of Object.keys(args)) { template = template.replace(new RegExp(`\\$<${key}>`, 'g'), args[key]); @@ -23,25 +25,56 @@ export default function SectionRenderer({ section, metadata }) { const url = `${publicRuntimeConfig.backend}/admin/registries`; const [data, setData] = useState(null); + const [processedLink, setProcessedLink] = useState(null); + const token = useSelector(state => state.user.token); useEffect(() => { + let isMounted = true; + + async function fetchDataAndProcessLink() { + //... your existing code fetching the data + + // After you set the data, process the link + if(isMounted && section.link) { + const processed = await processUrl(section.link, token, dispatch); // Assuming you have token available + setProcessedLink(processed); + } + } + + fetchDataAndProcessLink(); + + return () => { + isMounted = false; + }; + }, []); + + + useEffect(() => { + let isMounted = true; // <-- add this line + axios - .get(url, { headers: { accept: 'text/plain' } }) - .then(res => res.data.registries) - .then((registries) => { - setData(registries); - }) - .catch(error => { - error.customMessage = 'Request failed for GET /admin/registries'; - error.fullUrl = url; - dispatch(addError(error)) - }) + .get(url, { headers: { accept: 'text/plain' } }) + .then(res => res.data.registries) + .then((registries) => { + if (isMounted) { // <-- check this condition before setting state + setData(registries); + } + }) + .catch(error => { + error.customMessage = 'Request failed for GET /admin/registries'; + error.fullUrl = url; + dispatch(addError(error)) + }); + + return () => { // <-- cleanup function + isMounted = false; // <-- set the flag to false when the component unmounts + }; }, []); if (data && section.link) { data.forEach(registry => { if (section.link.startsWith(registry.uri)) { - section.link = replaceBeginning("" + section.link, registry.uri, ""); + section.link = processedLink.urlRemovedForLink; } }) if (section.grouped) { @@ -69,8 +102,8 @@ export default function SectionRenderer({ section, metadata }) { ); }); if (metadata) { - return
{content}
; - } + return {content}; + } return {content}; } return ( @@ -89,18 +122,11 @@ export default function SectionRenderer({ section, metadata }) { ); } else { - return
+ return Loading... -
- } - + } -function replaceBeginning(original, oldBeginning, newBeginning) { - if (original.startsWith(oldBeginning)) { - return newBeginning + original.slice(oldBeginning.length); - } - return original; } diff --git a/frontend/components/Viewing/SectionSelector.js b/frontend/components/Viewing/SectionSelector.js index 2f42d9c0..6764b8fc 100644 --- a/frontend/components/Viewing/SectionSelector.js +++ b/frontend/components/Viewing/SectionSelector.js @@ -43,7 +43,6 @@ export default function SectionSelector({ pagesInfo, json }) { const hiddenSections = useSelector(state => state.pageSections.hiddenSections) const selectors = headerCreate(pageSectionsOrder, pagesInfo.type, json, hiddenSections); - console.log(json) //Initializes the store page sections and minimized order. useEffect(() => { let savedMinimizedValues, savedSelectedSections; @@ -231,7 +230,6 @@ function headerCreate(pages, type, json, hiddenSections) { }; const renderDraggable = useDraggableInPortal(); - console.log(pages) const headers = pages.map((page, index) => { return ( diff --git a/frontend/components/Viewing/Sections/Attachments/AttachmentRows.js b/frontend/components/Viewing/Sections/Attachments/AttachmentRows.js index ec3c4b7b..68fcee19 100644 --- a/frontend/components/Viewing/Sections/Attachments/AttachmentRows.js +++ b/frontend/components/Viewing/Sections/Attachments/AttachmentRows.js @@ -15,6 +15,7 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; const { publicRuntimeConfig } = getConfig(); import getConfig from 'next/config'; +import { processUrl } from '../../../Admin/Registries'; import styles from '../../../../styles/view.module.css'; @@ -27,6 +28,7 @@ import styles from '../../../../styles/view.module.css'; export default function AttachmentRows(properties) { const token = useSelector(state => state.user.token); const [attachmentInfo, setStateAttachments] = useState(); + const [processedAttachments, setProcessedAttachments] = useState([]); const dispatch = useDispatch(); //There are attachments from the parent but they haven't been added to the state yet. @@ -36,6 +38,20 @@ export default function AttachmentRows(properties) { //There are no attachments to get. if (properties.attachments.length === 0) return null; + useEffect(() => { + async function processAndSetAttachments() { + const processed = await Promise.all(properties.attachments.map(async (attachment) => { + const result = await processUrl(attachment.topLevel, token, dispatch); + return { + ...attachment, + processedTopLevel: result.urlRemovedForLink || result.original + }; + })); + setProcessedAttachments(processed); + } + processAndSetAttachments(); + }, [properties.attachments]); + /** * @param {Number} bytes The number of bytes. * @returns The correct unit and formatted number of bytes. @@ -62,7 +78,7 @@ export default function AttachmentRows(properties) { : attachment.format.split('/').pop()} - + {attachment.title} @@ -80,12 +96,8 @@ export default function AttachmentRows(properties) { }); } else { const item = { - url: `${ - publicRuntimeConfig.backend - }${attachment.topLevel.replace( - 'https://synbiohub.org', - '' - )}/download`, + url: `${publicRuntimeConfig.backend + }${attachment.processedTopLevel}/download`, name: attachment.title.substring( 0, attachment.title.lastIndexOf('.') diff --git a/frontend/components/Viewing/Sections/Attachments/UploadAttachments.js b/frontend/components/Viewing/Sections/Attachments/UploadAttachments.js index 8edff36c..02204751 100644 --- a/frontend/components/Viewing/Sections/Attachments/UploadAttachments.js +++ b/frontend/components/Viewing/Sections/Attachments/UploadAttachments.js @@ -15,6 +15,8 @@ import options from './SelectOptions'; const { publicRuntimeConfig } = getConfig(); import getConfig from 'next/config'; +import { processUrl } from '../../../Admin/Registries'; + /** * @param {Any} properties Information passed in from parent component. * @returns A section where the owner can upload attachments or lookup attachments. @@ -70,7 +72,7 @@ export default function UploadAttachments(properties) { parameters.append('url', attachment.url); parameters.append('name', attachment.name); parameters.append('type', attachment.type); - + let response; try { @@ -181,14 +183,11 @@ export default function UploadAttachments(properties) { document.getElementById('attached-file-input').value = ''; setSelectedFiles([]); - attachFromFile( - selectedFiles, - properties.uri.replace( - 'https://synbiohub.org', - publicRuntimeConfig.backend - ) - ).then(() => { - dispatch(setUploadStatus('')); + processUrl(properties.uri, token, dispatch).then(processedUriData => { + const uriToUse = processedUriData.urlReplacedForBackend || processedUriData.original; + attachFromFile(selectedFiles, uriToUse).then(() => { + dispatch(setUploadStatus('')); + }); //Query all the attachments so the store can be updated. getQueryResponse(dispatch, getAttachments, { @@ -278,17 +277,18 @@ export default function UploadAttachments(properties) { } else if (!urlInput.includes('http')) { alert('The URL has to be a link'); } else { - const attachment = { - name: nameInput, - url: urlInput, - type: typeInput, - uri: uri.replace( - 'https://synbiohub.org', - publicRuntimeConfig.backend - ) - }; - - attachFromURL(attachment); + processUrl(uri, token, dispatch).then(processedUriData => { + const uriToUse = processedUriData.urlReplacedForBackend || processedUriData.original; + + const attachment = { + name: nameInput, + url: urlInput, + type: typeInput, + uri: uriToUse + }; + + attachFromURL(attachment); + }); const convertedUrl = uri.slice( 0, diff --git a/frontend/components/Viewing/Sections/MemberOfCollections.js b/frontend/components/Viewing/Sections/MemberOfCollections.js index 3c4158bd..926116a9 100644 --- a/frontend/components/Viewing/Sections/MemberOfCollections.js +++ b/frontend/components/Viewing/Sections/MemberOfCollections.js @@ -20,19 +20,15 @@ export default function MemberOfCollections(properties) { const [otherProps, setOtherProps] = useState(); const dispatch = useDispatch(); const token = useSelector(state => state.user.token); - console.log(properties) - console.log(otherProps) useEffect(() => { if (otherProps == undefined) getQueryResponse(dispatch, getOtherProperties, { uri: properties.uri - }).then(console.log(properties.uri)) - .then(props => { + }).then(props => { if (props.length > 0) setOtherProps(props); }); }, [otherProps]); - console.log(otherProps) if (!otherProps) return ; return ( diff --git a/frontend/components/Viewing/SidePanel.js b/frontend/components/Viewing/SidePanel.js index fff37b32..1b489afa 100644 --- a/frontend/components/Viewing/SidePanel.js +++ b/frontend/components/Viewing/SidePanel.js @@ -9,6 +9,7 @@ import { import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { useState } from 'react'; +import { useSelector, useDispatch } from 'react-redux'; import Link from 'next/link'; @@ -17,6 +18,9 @@ import styles from '../../styles/view.module.css'; import SectionSelector from './SectionSelector'; import SidePanelTools from './SidePanelTools'; +import { processUrl } from '../Admin/Registries'; +import { useEffect } from 'react'; + import getConfig from 'next/config'; import GenericContent from './PageJSON/Rendering/GenericContent'; import MetadataInfo from './MetadataInfo'; @@ -30,7 +34,19 @@ const { publicRuntimeConfig } = getConfig(); */ export default function SidePanel({ metadata, type, json, uri, plugins }) { const [translation, setTranslation] = useState(0); + const [processedUrl, setProcessedUrl] = useState({ original: uri }); const date = metadata.created.replace('T', ' ').replace('Z', ''); + const token = useSelector(state => state.user.token); + const dispatch = useDispatch(); + + useEffect(() => { + async function fetchAndProcessUrl() { + const result = await processUrl(uri, token, dispatch); + setProcessedUrl(result); + } + + fetchAndProcessUrl(); + }, [uri]); const pagesInfo = getPagesInfo(type, json, plugins); @@ -87,7 +103,7 @@ export default function SidePanel({ metadata, type, json, uri, plugins }) { type={type} displayId={metadata.displayId} name={metadata.name} - url={uri.replace('https://synbiohub.org', '')} + url={processedUrl.urlRemovedForLink || processedUrl.original} uri={uri} />
@@ -166,11 +182,4 @@ function getPagesInfo(type, json, plugins) { } return { type: type, order: orderUpdated }; -} - -function replaceBeginning(original, oldBeginning, newBeginning) { - if (original.startsWith(oldBeginning)) { - return newBeginning + original.slice(oldBeginning.length); - } - return original; } \ No newline at end of file