Skip to content

Commit

Permalink
Merge branch 'staging'
Browse files Browse the repository at this point in the history
  • Loading branch information
Mihoub2 committed Jan 2, 2024
2 parents 7bfe0de + 91dcbbc commit 5b8a072
Show file tree
Hide file tree
Showing 45 changed files with 987 additions and 199 deletions.
Binary file added public/models/BulkImportPersonsIdentifiers.xlsx
Binary file not shown.
Binary file modified public/models/BulkImportStructures.xlsx
Binary file not shown.
Binary file not shown.
37 changes: 17 additions & 20 deletions src/components/blocs/modification-journal/index.js
Original file line number Diff line number Diff line change
@@ -1,55 +1,52 @@
import React, { useState } from 'react';
import { Accordion, AccordionItem, Col, Pagination, Row } from '@dataesr/react-dsfr';
import { useParams } from 'react-router-dom';
import { useParams, useSearchParams } from 'react-router-dom';
import useFetch from '../../../hooks/useFetch';
import { Bloc, BlocContent, BlocTitle } from '../../bloc';
import ModificationDetails from './components/modification-details';
import ModificationTitle from './components/modification-title';

const LAST_DAYS = 15;
const pageSize = 30;

const DATE = new Date(Date.now() - LAST_DAYS * 24 * 60 * 60 * 1000).toISOString();

export default function ModificationJournal() {
const [openAccordions, setOpenAccordions] = useState([]);
const [page, setPage] = useState(1);

const [searchParams, setSearchParams] = useSearchParams();
const page = searchParams.get('page') || 1;
const limit = 50;
const skip = (page - 1) * 50;
const { id: resourceId } = useParams();
const url = resourceId
? `/journal?filters[resourceId]=${resourceId}&filters[createdAt][$gte]=${DATE}&sort=-createdAt&limit=100&filters[resourceType][$ne]=admin&filters[resourceType][$ne]=groups`
: `/journal?filters[createdAt][$gte]=${DATE}&sort=-createdAt&limit=100&filters[resourceType][$ne]=admin`;
? `/journal?filters[resourceId]=${resourceId}&filters[createdAt][$gte]=${DATE}&sort=-createdAt&skip=${skip}&limit=${limit}&filters[resourceType][$ne]=admin&filters[resourceType][$ne]=groups`
: `/journal?filters[createdAt][$gte]=${DATE}&sort=-createdAt&skip=${skip}&limit=${limit}&filters[resourceType][$ne]=admin`;

const { data, error, isLoading } = useFetch(url);

const handlePaginationClick = (newPage) => {
setPage(newPage);
};

const startIndex = (page - 1) * pageSize;
const endIndex = startIndex + pageSize;
if (!data?.totalCount) {
return null;
}

return (

<Bloc isLoading={isLoading} error={error} data={data}>
<BlocTitle as="h1" look="h3">Journal des modifications</BlocTitle>
<BlocContent>
<Row gutters>
<Col n="12">
<Accordion keepOpen>
{data?.data?.length && data.data.slice(startIndex, endIndex).map((event, i) => (
<AccordionItem onClick={() => setOpenAccordions((prev) => [...prev, i + startIndex])} key={event.createdAt} title={<ModificationTitle data={event} />}>
{openAccordions.includes(i + startIndex) && <ModificationDetails data={event} />}
{data?.data?.length && data.data.map((event, i) => (
<AccordionItem onClick={() => setOpenAccordions((prev) => [...prev, i])} key={event.createdAt} title={<ModificationTitle data={event} />}>
{openAccordions.includes(i) && <ModificationDetails data={event} />}
</AccordionItem>
))}
</Accordion>
</Col>
</Row>
<Row className="flex--space-around fr-pt-3w">
<Pagination
onClick={(newPage) => setSearchParams({ page: newPage })}
surrendingPages={2}
currentPage={page}
pageCount={data ? Math.ceil(data.totalCount / pageSize) : 0}
onClick={handlePaginationClick}
currentPage={Number(page)}
pageCount={data?.totalCount ? Math.ceil(data.totalCount / limit) : 0}
/>
</Row>
</BlocContent>
Expand Down
2 changes: 1 addition & 1 deletion src/components/blocs/relations/utils/status.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ export function isFinished(relation) {
}

export function spreadByStatus(data) {
const current = data?.filter((el) => (el.startDate <= getComparableNow() || (!el.startDate && !el.endDate)) && !isFinished(el));
const current = data?.filter((el) => (el.startDate <= getComparableNow() || (!el.startDate) || (!el.startDate && !el.endDate)) && !isFinished(el));
const inactive = data?.filter((el) => isFinished(el));
const forthcoming = data?.filter((el) => el.startDate > getComparableNow());
const counts = {
Expand Down
5 changes: 4 additions & 1 deletion src/components/bulk-imports/components/analysis.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import { prizesHeadersMapping } from '../lib/analysers/prizes/headers-mapping';
import { laureatHeadersMapping } from '../lib/analysers/laureats/headers-mapping';
import { gouvernanceHeadersMapping } from '../lib/analysers/gouvernance/headers-mapping';
import { termsHeadersMapping } from '../lib/analysers/terms/headers-mapping';
import { structuresIdentifiersHeadersMapping } from '../lib/analysers/structures-identifiers/headers-mapping';
import { personsIdentifiersHeadersMapping } from '../lib/analysers/persons-identifiers/headers-mapping';

export default function Analysis({ type, rows, handleForceImport }) {
const [displayList, setDisplayList] = useState(false);
Expand All @@ -23,7 +25,8 @@ export default function Analysis({ type, rows, handleForceImport }) {
laureats: laureatHeadersMapping,
gouvernance: gouvernanceHeadersMapping,
terms: termsHeadersMapping,

'structures (identifiants)': structuresIdentifiersHeadersMapping,
'personnes (identifiants)': personsIdentifiersHeadersMapping,
};

const convertRowsToXLSXData = (dataRows) => {
Expand Down
42 changes: 27 additions & 15 deletions src/components/bulk-imports/components/form-step.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Alert, Button, ButtonGroup, Link, Text, TextInput } from '@dataesr/react-dsfr';
import { Alert, Button, ButtonGroup, Col, Icon, Link, Row, Text, TextInput } from '@dataesr/react-dsfr';
import PropTypes from 'prop-types';
import { useState } from 'react';
import HelperForStructures from '../lib/helpers/helper';
Expand All @@ -10,26 +10,38 @@ const MODELS = {
laureats: '/models/BulkImportLaureats.xlsx',
gouvernance: '/models/BulkImportGouvernance.xlsx',
termes: '/models/BulkImportTerms.xlsx',
'structures (identifiants)': '/models/BulkImportStructuresIdentifiers.xlsx',
'personnes (identifiants)': '/models/BulkImportPersonsIdentifiers.xlsx',
};

export default function FormStep({ type, onInputValidation, fileError }) {
const [input, setInput] = useState('');

return (
<>
<Text size="sm">
<i>
Récupérer le
{' '}
<Link href={MODELS[type]}>
fichier modèle
</Link>
, le remplir (une ligne correspond à un élément), copier puis
coller dans le champ ci-dessous les cellules correspondant aux
éléments à ajouter. La première ligne doit correspondre à l'en-tête de chaque colonne. Veuillez utiliser Ctrl + 'a' pour copier votre tableau d'imports.
</i>
</Text>
<HelperForStructures type={type} />
<Row>
<Text size="sm">
<i>
Récupérer le
{' '}
<Link href={MODELS[type]}>
fichier modèle
</Link>
, le remplir (une ligne correspond à un élément), copier puis
coller dans le champ ci-dessous les cellules correspondant aux
éléments à ajouter. La première ligne doit correspondre à l'en-tête de chaque colonne. Veuillez utiliser Ctrl + 'a' pour copier votre tableau d'imports.
</i>
</Text>
</Row>
<Row>
<HelperForStructures type={type} />
</Row>
<Row spacing="mb-1v">
<Col>
<Icon name="ri-error-warning-line" size="lg" />
Vérifiez que votre fichier correspond au fichier modèle.
</Col>
</Row>
<TextInput
label="Coller dans le champ ci-dessous les cellules du fichier modèle correspondant aux éléments à ajouter:"
onChange={(e) => setInput(e.target.value)}
Expand All @@ -52,7 +64,7 @@ export default function FormStep({ type, onInputValidation, fileError }) {
}

FormStep.propTypes = {
type: PropTypes.oneOf(['structures', 'personnes', 'gouvernance', 'prix', 'laureats', 'termes']).isRequired,
type: PropTypes.oneOf(['structures', 'personnes', 'gouvernance', 'prix', 'laureats', 'termes', 'structures (identifiants)', 'personnes (identifiants)']).isRequired,
onInputValidation: PropTypes.func.isRequired,
fileError: PropTypes.bool,
};
Expand Down
4 changes: 2 additions & 2 deletions src/components/bulk-imports/components/report-step.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import Button from '../../button';
import Report from './report';

export default function ReportStep({ state, onReset }) {
const errors = state.filter((row) => row.imports?.status === 'error');
const success = state.filter((row) => row.imports?.status === 'imported');
const errors = state?.filter((row) => row.imports?.status === 'error');
const success = state?.filter((row) => row.imports?.status === 'imported');

return (
<>
Expand Down
66 changes: 50 additions & 16 deletions src/components/bulk-imports/components/report.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,11 @@ import { prizesHeadersMapping } from '../lib/analysers/prizes/headers-mapping';
import { laureatHeadersMapping } from '../lib/analysers/laureats/headers-mapping';
import { gouvernanceHeadersMapping } from '../lib/analysers/gouvernance/headers-mapping';
import { termsHeadersMapping } from '../lib/analysers/terms/headers-mapping';
import { structuresIdentifiersHeadersMapping } from '../lib/analysers/structures-identifiers/headers-mapping';

export default function Report({ type, rows }) {
const [displayList, setDisplayList] = useState(true);

if (!rows.length) return null;

const typeOfImport = rows.map((el) => el.type)[0];
Expand All @@ -22,7 +24,7 @@ export default function Report({ type, rows }) {
laureats: laureatHeadersMapping,
gouvernance: gouvernanceHeadersMapping,
terms: termsHeadersMapping,

'structures-identifiers': structuresIdentifiersHeadersMapping,
};

const convertRowsToXLSXData = (dataRows) => {
Expand All @@ -47,9 +49,9 @@ export default function Report({ type, rows }) {
value = warningMessages;
} else {
const fieldKey = currentModel[header];
const fieldValues = row.body[fieldKey];
const fieldValues = row?.body[fieldKey];

if (typeof fieldValues === 'object' && fieldValues !== null) {
if (Array.isArray(fieldValues)) {
value = fieldValues.filter(Boolean).join('; ');
} else if (fieldValues !== undefined) {
value = fieldValues;
Expand Down Expand Up @@ -145,7 +147,7 @@ export default function Report({ type, rows }) {
{item?.message}
</li>
))}
{(row?.imports?.status === 'imported' && row?.type !== 'laureats') && (
{(row?.imports?.status === 'imported' && row?.type !== 'laureats' && row?.type !== 'structures (identifiants)' && row?.type !== 'personnes (identifiants)') && (
<li>
L'objet a été importé avec succès
{row.imports?.href && ' '}
Expand Down Expand Up @@ -174,6 +176,36 @@ export default function Report({ type, rows }) {
a bien été effectuée
</li>
)}
{row.type === 'structures (identifiants)' && (
<li>
L'identifiant
{' '}
{row.body.type}
{' '}
{row.body.value}
{' '}
a été ajouté.
{' '}
<Link target="_blank" href={`/structures/${row?.body?.structureId}`}>
Voir la structure
</Link>
</li>
)}
{row.type === 'personnes (identifiants)' && (
<li>
L'identifiant
{' '}
{row.body.type}
{' '}
{row.body.value}
{' '}
a été ajouté.
{' '}
<Link target="_blank" href={`/personnes/${row?.body?.personId}`}>
Voir la personne
</Link>
</li>
)}
</ul>
</td>
</tr>
Expand All @@ -182,20 +214,22 @@ export default function Report({ type, rows }) {
</tbody>
</table>
</div>
{rows.map((el) => el.type === 'persons' || el.type === 'structures') && (
<Button
onClick={() => {
const xlsxData = convertRowsToXLSXData(rows);
if (xlsxData) {
exportToXLSX(xlsxData);
}
}}
>
Exporter la liste des imports en XLSX
</Button>
)}
</Col>
)}
<Row className="fr-mt-3w">
{rows.map((el) => el.type === 'persons' || el.type === 'structures') && (
<Button
onClick={() => {
const xlsxData = convertRowsToXLSXData(rows);
if (xlsxData) {
exportToXLSX(xlsxData);
}
}}
>
Exporter la liste des imports en XLSX
</Button>
)}
</Row>
</Row>
</Container>
);
Expand Down
2 changes: 1 addition & 1 deletion src/components/bulk-imports/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -128,5 +128,5 @@ export default function BulkImport({ type }) {
}

BulkImport.propTypes = {
type: PropTypes.oneOf(['structures', 'personnes', 'gouvernance', 'lauréats', 'prix', 'terms']).isRequired,
type: PropTypes.oneOf(['structures', 'personnes', 'gouvernance', 'lauréats', 'prix', 'terms', 'structures (identifiants)', 'personnes (identifiants)']).isRequired,
};
14 changes: 14 additions & 0 deletions src/components/bulk-imports/lib/analysers/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import parsePriceTSV from './prizes';
import parseLaureatsTSV from './laureats';
import parseGouvernanceTSV from './gouvernance';
import parseTermsTSV from './terms';
import parseStructuresIdentifiersTSV from './structures-identifiers';
import parsePersonsIdentifiersTSV from './persons-identifiers';

export default async function analyse(str, type) {
let analyses;
Expand Down Expand Up @@ -38,6 +40,18 @@ export default async function analyse(str, type) {
return analyses;
}
throw new Error('File Error');
case 'structures (identifiants)':
analyses = await parseStructuresIdentifiersTSV(str);
if (analyses.length > 0) {
return analyses;
}
throw new Error('File Error');
case 'personnes (identifiants)':
analyses = await parsePersonsIdentifiersTSV(str);
if (analyses.length > 0) {
return analyses;
}
throw new Error('File Error');
case 'termes':
analyses = await parseTermsTSV(str);
if (analyses.length > 0) {
Expand Down
Loading

0 comments on commit 5b8a072

Please sign in to comment.