Skip to content

Commit

Permalink
refactor(status): Set status options as config and refactor code
Browse files Browse the repository at this point in the history
  • Loading branch information
annelhote committed Nov 9, 2023
1 parent 0f4e6f7 commit 59ad212
Show file tree
Hide file tree
Showing 5 changed files with 93 additions and 114 deletions.
28 changes: 28 additions & 0 deletions client/src/config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
const status = {
validated: {
badgeType: 'success',
buttonClassName: 'btn-keep',
buttonIcon: 'ri-checkbox-circle-line',
buttonLabel: 'Validate',
id: 'validated',
label: 'Validated',
},
excluded: {
badgeType: 'error',
buttonClassName: 'btn-hide',
buttonIcon: 'ri-indeterminate-circle-line',
buttonLabel: 'Exclude',
id: 'excluded',
label: 'Excluded',
},
tobedecided: {
badgeType: 'info',
buttonClassName: 'btn-reset',
buttonIcon: 'ri-reply-fill',
buttonLabel: 'Reset status',
id: 'tobedecided',
label: 'To be decided',
},
};

export { status };
3 changes: 2 additions & 1 deletion client/src/pages/home/actions.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { Tooltip } from 'react-tooltip';

import Button from '../../components/button';
import { export2BsoCsv, export2json, importJson } from '../../utils/file';
import { status } from '../../config';

export default function Actions({
allAffiliations,
Expand All @@ -18,7 +19,7 @@ export default function Actions({
const [, setSearchParams] = useSearchParams();
const [displayFileUpload, setDisplayFileUpload] = useState(false);

const decidedAffiliations = allAffiliations.filter((affiliation) => ['excluded', 'validated'].includes(affiliation.status));
const decidedAffiliations = allAffiliations.filter((affiliation) => affiliation.status !== status.tobedecided.id);

return (
<>
Expand Down
143 changes: 53 additions & 90 deletions client/src/pages/home/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import {
getOpenAlexPublications,
mergePublications,
} from '../../utils/works';
import { status } from '../../config';

import 'primereact/resources/primereact.min.css';
import 'primereact/resources/themes/lara-light-indigo/theme.css';
Expand All @@ -39,9 +40,6 @@ const {

const DATASOURCES = [{ key: 'bso', label: 'French OSM' }, { key: 'openalex', label: 'OpenAlex' }];
const FOSM_IDENTIFIERS = ['crossref', 'hal_id', 'datacite'];
const STATUS_EXCLUDED = 'excluded';
const STATUS_TO_BE_DECIDED = 'to be decided';
const STATUS_VALIDATED = 'validated';

const getData = async (options) => {
const promises1 = [getBsoWorks({ options, index: VITE_BSO_PUBLICATIONS_INDEX }), getOpenAlexPublications(options)];
Expand Down Expand Up @@ -119,10 +117,10 @@ export default function Home() {
const groupByAffiliations = (publications) => {
setIsLoading(true);
// Save already decided affiliations
const decidedAffiliations = Object.values(allAffiliations).filter((affiliation) => affiliation.status !== STATUS_TO_BE_DECIDED);
// Compute distinct affiliations of the undecided publications
const decidedAffiliations = Object.values(allAffiliations).filter((affiliation) => affiliation.status !== status.tobedecided.id);
// Compute distinct affiliations of the undecided works
let allAffiliationsTmp = {};
publications.filter((publication) => publication.status === STATUS_TO_BE_DECIDED).forEach((publication) => {
publications.filter((publication) => publication.status === status.tobedecided.id).forEach((publication) => {
(publication?.affiliations ?? [])
.filter((affiliation) => Object.keys(affiliation).length && affiliation?.name)
.forEach((affiliation) => {
Expand All @@ -141,7 +139,7 @@ export default function Home() {
nameHtml: affiliation.name.replace(regexp, '<b>$&</b>'),
ror,
rorHtml: ror?.replace(regexp, '<b>$&</b>'),
status: STATUS_TO_BE_DECIDED,
status: status.tobedecided.id,
publications: [],
};
}
Expand Down Expand Up @@ -193,7 +191,7 @@ export default function Home() {
allIdsHtml: getAllIdsHtmlField(dataset),
authorsHtml: getAuthorsHtmlField(dataset),
authorsTooltip: getAuthorsTooltipField(dataset),
status: STATUS_TO_BE_DECIDED,
status: status.tobedecided.id,
}));
allPublicationsTmp = data.publications
.map((publication) => ({
Expand All @@ -203,7 +201,7 @@ export default function Home() {
allIdsHtml: getAllIdsHtmlField(publication),
authorsHtml: getAuthorsHtmlField(publication),
authorsTooltip: getAuthorsTooltipField(publication),
status: STATUS_TO_BE_DECIDED,
status: status.tobedecided.id,
}));
}
setAllDatasets(allDatasetsTmp);
Expand All @@ -227,7 +225,7 @@ export default function Home() {
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [allPublications, regexp]);

const tagPublications = (publications, action) => {
const tagWorks = (publications, action) => {
const allPublicationsTmp = [...allPublications];
const publicationsIds = publications.map((publication) => publication.id);
allPublicationsTmp.filter((publication) => publicationsIds.includes(publication.id)).map((publication) => publication.status = action);
Expand All @@ -236,7 +234,7 @@ export default function Home() {
};

const tagAffiliations = (affiliations, action) => {
if (action !== STATUS_EXCLUDED) {
if (action !== status.excluded.id) {
const allPublicationsTmp = [...allPublications];
const publicationsIds = affiliations.map((affiliation) => affiliation.publications).flat();
allPublicationsTmp.filter((publication) => publicationsIds.includes(publication.id)).map((publication) => publication.status = action);
Expand All @@ -249,73 +247,35 @@ export default function Home() {
setSelectedAffiliations([]);
};

const renderAffiliationsButtons = () => (
const renderAffiliationsButtons = (selected) => (
<>
<Button
className="fr-mr-1w btn-keep"
disabled={!selectedAffiliations.length}
icon="ri-checkbox-circle-line"
onClick={() => tagAffiliations(selectedAffiliations, STATUS_VALIDATED)}
size="sm"
>
Validate
{` (${selectedAffiliations.length})`}
</Button>
<Button
className="fr-mr-1w btn-hide"
disabled={!selectedAffiliations.length}
icon="ri-indeterminate-circle-line"
onClick={() => tagAffiliations(selectedAffiliations, STATUS_EXCLUDED)}
size="sm"
>
Exclude
{` (${selectedAffiliations.length})`}
</Button>
<Button
className="fr-mb-1w btn-reset"
disabled={!selectedAffiliations.length}
icon="ri-reply-fill"
onClick={() => tagAffiliations(selectedAffiliations, STATUS_TO_BE_DECIDED)}
size="sm"
>
Reset status
{` (${selectedAffiliations.length})`}
</Button>
{Object.values(status).map((st) => (
<Button
className={`fr-mb-1w fr-mr-1w ${st.buttonClassName}`}
disabled={!selected.length}
icon={st.buttonIcon}
onClick={() => tagAffiliations(selected, st.id)}
size="sm"
>
{`${st.buttonLabel} (${selected.length})`}
</Button>
))}
</>
);

const renderWorksButtons = (selected) => (
<>
<Button
className="fr-mr-1w btn-keep"
disabled={!selected.length}
icon="ri-checkbox-circle-line"
onClick={() => tagPublications(selected, STATUS_VALIDATED)}
size="sm"
>
Validate
{` (${selected.length})`}
</Button>
<Button
className="fr-mr-1w btn-hide"
disabled={!selected.length}
icon="ri-indeterminate-circle-line"
onClick={() => tagPublications(selected, STATUS_EXCLUDED)}
size="sm"
>
Exclude
{` (${selected.length})`}
</Button>
<Button
className="fr-mb-1w btn-reset"
disabled={!selected.length}
icon="ri-reply-fill"
onClick={() => tagPublications(selected, STATUS_TO_BE_DECIDED)}
size="sm"
>
Reset status
{` (${selected.length})`}
</Button>
{Object.values(status).map((st) => (
<Button
className={`fr-mb-1w fr-mr-1w ${st.buttonClassName}`}
disabled={!selected.length}
icon={st.buttonIcon}
onClick={() => tagWorks(selected, st.id)}
size="sm"
>
{`${st.buttonLabel} (${selected.length})`}
</Button>
))}
</>
);

Expand Down Expand Up @@ -391,15 +351,16 @@ export default function Home() {
)}
<Row>
<Col n="4">
{renderAffiliationsButtons()}
{renderAffiliationsButtons(selectedAffiliations)}
</Col>
<Col>
<Gauge
data={[
{ className: 'tobedecided', id: 'tobedecided', label: 'To be decided', value: allAffiliations.filter((affiliation) => affiliation.status === STATUS_TO_BE_DECIDED).length },
{ className: 'validated', id: 'validated', label: 'Validated', value: allAffiliations.filter((affiliation) => affiliation.status === STATUS_VALIDATED).length },
{ className: 'excluded', id: 'excluded', label: 'Excluded', value: allAffiliations.filter((affiliation) => affiliation.status === STATUS_EXCLUDED).length },
]}
data={Object.values(status).map((st) => ({
className: st.id,
id: st.id,
label: st.label,
value: allAffiliations.filter((affiliation) => affiliation.status === st.id).length,
}))}
/>
</Col>
</Row>
Expand All @@ -417,7 +378,7 @@ export default function Home() {
</Row>
<Row>
<Col>
{renderAffiliationsButtons()}
{renderAffiliationsButtons(selectedAffiliations)}
</Col>
</Row>
</Tab>
Expand All @@ -428,11 +389,12 @@ export default function Home() {
</Col>
<Col>
<Gauge
data={[
{ className: 'tobedecided', id: 'tobedecided', label: 'To be decided', value: allPublications.filter((publication) => publication.status === STATUS_TO_BE_DECIDED).length },
{ className: 'validated', id: 'validated', label: 'Validated', value: allPublications.filter((publication) => publication.status === STATUS_VALIDATED).length },
{ className: 'excluded', id: 'excluded', label: 'Excluded', value: allPublications.filter((publication) => publication.status === STATUS_EXCLUDED).length },
]}
data={Object.keys(status).map((st) => ({
className: status[st].id,
id: status[st].id,
label: status[st].label,
value: allPublications.filter((publication) => publication.status === status[st].id).length,
}))}
/>
</Col>
</Row>
Expand All @@ -442,7 +404,7 @@ export default function Home() {
<Col n="2">
<CheckboxGroup
hint="Filter results on selected datasources"
legend="Datasources"
legend="Source"
>
{DATASOURCES.map((datasource) => (
<Checkbox
Expand Down Expand Up @@ -519,11 +481,12 @@ export default function Home() {
</Col>
<Col>
<Gauge
data={[
{ className: 'tobedecided', id: 'tobedecided', label: 'To be decided', value: allDatasets.filter((dataset) => dataset.status === STATUS_TO_BE_DECIDED).length },
{ className: 'validated', id: 'validated', label: 'Validated', value: allDatasets.filter((dataset) => dataset.status === STATUS_VALIDATED).length },
{ className: 'excluded', id: 'excluded', label: 'Excluded', value: allDatasets.filter((dataset) => dataset.status === STATUS_EXCLUDED).length },
]}
data={Object.keys(status).map((st) => ({
className: status[st].id,
id: status[st].id,
label: status[st].label,
value: allDatasets.filter((dataset) => dataset.status === status[st].id).length,
}))}
/>
</Col>
</Row>
Expand Down
12 changes: 7 additions & 5 deletions client/src/utils/file.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { status } from '../config';

const export2BsoCsv = (allPublications) => {
const csvHeader = ['doi', 'hal_id', 'nnt_id'].join(';');
const validatedPublications = allPublications.filter((publication) => publication.status === 'validated');
const validatedPublications = allPublications.filter((publication) => publication.status === status.validated.id);
const getValue = (row, idType) => {
if (!row) return '';
if (row.doi && idType === 'doi') return row.doi;
Expand Down Expand Up @@ -49,10 +51,10 @@ const importJson = (e, optionsInit, setAllAffiliations, setAllPublications, setS
setAllPublications(allPublications);
}
if (decidedAffiliations) {
const validatedAffiliations = decidedAffiliations.filter((decidedAffiliation) => decidedAffiliation.status === 'validated');
tagAffiliations(validatedAffiliations, 'validated');
const excludedAffiliations = decidedAffiliations.filter((decidedAffiliation) => decidedAffiliation.status === 'excluded');
tagAffiliations(excludedAffiliations, 'excluded');
const validatedAffiliations = decidedAffiliations.filter((decidedAffiliation) => decidedAffiliation.status === status.validated.id);
tagAffiliations(validatedAffiliations, status.validated.id);
const excludedAffiliations = decidedAffiliations.filter((decidedAffiliation) => decidedAffiliation.status === status.excluded.id);
tagAffiliations(excludedAffiliations, status.excluded.id);
}
setSearchParams(options);
};
Expand Down
21 changes: 3 additions & 18 deletions client/src/utils/templates.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { Dropdown } from 'primereact/dropdown';
import { Tooltip } from 'react-tooltip';

import { getIdLink } from './works';
import { status } from '../config';

const affiliationsTemplate = (rowData) => (
<>
Expand Down Expand Up @@ -88,30 +89,14 @@ const getAuthorsTooltipField = (rowData) => {

const nameTemplate = (rowData) => <span dangerouslySetInnerHTML={{ __html: rowData.nameHtml }} />;

const getBadgeTypeByStatus = (status) => {
let type;
switch (status) {
case 'validated':
type = 'success';
break;
case 'excluded':
type = 'error';
break;
default:
type = 'info';
break;
}
return type;
};

const statusTemplate = (rowData) => <Badge text={rowData?.status ?? rowData} type={getBadgeTypeByStatus(rowData?.status ?? rowData)} />;
const statusTemplate = (rowData) => <Badge text={status[rowData?.status ?? rowData]?.label} type={status[rowData?.status ?? rowData]?.badgeType} />;

const statusFilterTemplate = (options) => (
<Dropdown
className="p-column-filter"
itemTemplate={statusTemplate}
onChange={(e) => options.filterApplyCallback(e.value)}
options={['to be decided', 'validated', 'excluded']}
options={Object.keys(status)}
placeholder=""
style={{ width: '6rem' }}
showClear
Expand Down

0 comments on commit 59ad212

Please sign in to comment.