From 20fb46aec70dc5ed19adb96c06b299ef69de31a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anne=20L=27H=C3=B4te?= Date: Fri, 6 Dec 2024 19:01:56 +0100 Subject: [PATCH] fix(openalex): Try to improve UX ... --- .../openalex-affiliations/results/index.jsx | 45 ++-- .../results/list-view.jsx | 196 ++++++++++-------- 2 files changed, 130 insertions(+), 111 deletions(-) diff --git a/client/src/pages/openalex-affiliations/results/index.jsx b/client/src/pages/openalex-affiliations/results/index.jsx index 0489bc1..2fc61c5 100644 --- a/client/src/pages/openalex-affiliations/results/index.jsx +++ b/client/src/pages/openalex-affiliations/results/index.jsx @@ -7,6 +7,7 @@ import { ModalContent, ModalTitle, Row, + Spinner, Tag, Text, TextInput, @@ -51,6 +52,7 @@ export default function Affiliations() { status.validated.id, status.excluded.id, ]); + const [isLoading, setIsLoading] = useState(false); const [isLoadingRorData, setIsLoadingRorData] = useState(false); // TODO: spinner dans modal const [isAddModalOpen, setIsAddModalOpen] = useState(false); const [isRemoveModalOpen, setIsRemoveModalOpen] = useState(false); @@ -58,7 +60,6 @@ export default function Affiliations() { const [rorMessage, setRorMessage] = useState(''); const [rorMessageType, setRorMessageType] = useState(''); const [rorsToRemove, setRorsToRemove] = useState([]); - const [timer, setTimer] = useState(); const [uniqueRors, setUniqueRors] = useState({}); const { data, error, isFetched, isFetching, refetch } = useQuery({ @@ -172,26 +173,22 @@ export default function Affiliations() { }, [data]); useEffect(() => { - if (timer) clearTimeout(timer); - const timerTmp = setTimeout(() => { - const regex = new RegExp(removeDiacritics(filteredAffiliationName)); - const filteredAffiliationsTmp = affiliations.filter( - (affiliation) => regex.test( - `${affiliation.key.replace('[ source: ', '').replace(' ]', '')} ${affiliation.rors.map((_ror) => _ror.rorId).join(' ')}`, - ), - ); - // Recompute corrections only when the array has changed - if (filteredAffiliationsTmp.length !== filteredAffiliations.length) { - setAllOpenalexCorrections([ - ...allOpenalexCorrections, - ...getAffiliationsCorrections(filteredAffiliationsTmp), - ]); - } - setFilteredAffiliations(filteredAffiliationsTmp); - }, 500); - setTimer(timerTmp); - // The timer should not be tracked - // eslint-disable-next-line react-hooks/exhaustive-deps + setIsLoading(true); + const regex = new RegExp(removeDiacritics(filteredAffiliationName)); + const filteredAffiliationsTmp = affiliations.filter( + (affiliation) => regex.test( + `${affiliation.key.replace('[ source: ', '').replace(' ]', '')} ${affiliation.rors.map((_ror) => _ror.rorId).join(' ')}`, + ), + ); + // Recompute corrections only when the array has changed + if (filteredAffiliationsTmp.length !== filteredAffiliations.length) { + setAllOpenalexCorrections([ + ...allOpenalexCorrections, + ...getAffiliationsCorrections(filteredAffiliationsTmp), + ]); + } + setFilteredAffiliations(filteredAffiliationsTmp); + setIsLoading(false); }, [affiliations, allOpenalexCorrections, filteredAffiliationName, filteredAffiliations.length, filteredStatus]); useEffect(() => { @@ -353,7 +350,7 @@ export default function Affiliations() { <>
- {isFetching && ( + {(isFetching || isLoading) && ( )} + {isLoading && ( + + )} + {error && ( diff --git a/client/src/pages/openalex-affiliations/results/list-view.jsx b/client/src/pages/openalex-affiliations/results/list-view.jsx index 8254e6b..376d8fa 100644 --- a/client/src/pages/openalex-affiliations/results/list-view.jsx +++ b/client/src/pages/openalex-affiliations/results/list-view.jsx @@ -5,6 +5,7 @@ import { Col, Modal, ModalContent, ModalFooter, ModalTitle, Row, + Spinner, Text, } from '@dataesr/dsfr-plus'; import PropTypes from 'prop-types'; @@ -23,8 +24,10 @@ export default function ListView({ setSelectAffiliations, toggleRemovedRor, }) { + const [isLoading, setIsLoading] = useState(false); const [isModalOpen, setIsModalOpen] = useState(false); const [isColorInfoModalOpen, setIsColorInfoModalOpen] = useState(false); + const [search, setSearch] = useState(''); const [selectSortOnNumberOfRors, setSelectSortOnNumberOfRors] = useState('default'); const [selectShowAffiliations, setSelectShowAffiliations] = useState('all'); const [selectRorCountry, setSelectRorCountry] = useState('all'); @@ -51,6 +54,7 @@ export default function ListView({ defineRorColor.push(...sortedRor.slice(0, 5).map((ror, index) => ({ ror, color: dsColors[index % dsColors.length] }))); useEffect(() => { + setIsLoading(true); // Deep copy of filteredAffiliations object let initialAffiliations = JSON.parse(JSON.stringify(filteredAffiliations)); if (sortsAndFilters.sortOnNumberOfRors === 'numberASC') { @@ -72,6 +76,7 @@ export default function ListView({ } setSortedOrFilteredAffiliations(initialAffiliations); + setIsLoading(false); }, [filteredAffiliations, sortsAndFilters]); return ( @@ -100,7 +105,7 @@ export default function ListView({ setFilteredAffiliationName(e.target.value)} + onChange={(e) => setSearch(e.target.value)} style={{ border: '1px solid #ced4da', borderRadius: '4px', @@ -108,14 +113,23 @@ export default function ListView({ width: '600px', backgroundColor: 'white', }} - value={filteredAffiliationName} + value={search} /> +