Skip to content

Commit c4a42d5

Browse files
committed
Merge branch 'staging' into main
2 parents 8e49ee0 + 4d211ee commit c4a42d5

File tree

14 files changed

+438
-298
lines changed

14 files changed

+438
-298
lines changed

.github/workflows/main.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ jobs:
3939
docker push $IMAGE_ID:${{ steps.version.outputs.tag }}
4040
4141
deploy:
42-
name: Update staging deployment
42+
name: Update production deployment
4343
runs-on: ubuntu-latest
4444
needs: publish-ghcr
4545
steps:
Lines changed: 65 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { useState } from 'react';
2-
import { useNavigate, useParams } from 'react-router-dom';
3-
import { Badge, BadgeGroup, Col, Modal, ModalContent, ModalTitle, Row, Tag, Text, Link, Icon } from '@dataesr/react-dsfr';
2+
import { useNavigate } from 'react-router-dom';
3+
import { Badge, BadgeGroup, Col, Modal, ModalContent, ModalTitle, Row, Tag, Text, Link } from '@dataesr/react-dsfr';
44
import useEditMode from '../../../hooks/useEditMode';
55
import useFetch from '../../../hooks/useFetch';
66
import useNotice from '../../../hooks/useNotice';
@@ -15,14 +15,15 @@ import { Download } from '../../download';
1515
import DocumentForm from '../../forms/documents';
1616
import useAuth from '../../../hooks/useAuth';
1717
import TagList from '../../tag-list';
18+
import WeblinksResources from './weblinks-resources';
19+
import useUrl from '../../../hooks/useUrl';
1820

1921
export default function DocumentsOutlet() {
2022
const { editMode } = useEditMode();
2123
const { viewer } = useAuth();
22-
const { id: resourceId } = useParams();
24+
const { id: resourceId, apiObject } = useUrl();
2325
const navigate = useNavigate();
2426
const url = `/documents?filters[relatesTo]=${resourceId}&sort=-startDate&limit=500`;
25-
const getHCERES = useFetch(`/structures/${resourceId}/weblinks?filters[type]=hceres`);
2627
const { data, isLoading, error, reload } = useFetch(url);
2728
const { notice } = useNotice();
2829
const [isOpen, setIsOpen] = useState(false);
@@ -71,94 +72,75 @@ export default function DocumentsOutlet() {
7172
const renderContent = () => {
7273
if (!data || !data.data.length) return null;
7374
return (
74-
<>
75-
{getHCERES.data?.data[0]?.url && (
76-
<Col n="12 md-4 sm-6 lg-3" className="fr-mb-2w">
77-
<div className="fr-card fr-card--sm fr-card--grey fr-card--no-border">
78-
<Link target="_blank" href={getHCERES.data?.data[0]?.url}>
79-
<div className="flex-col flex--center">
80-
<Text>Rapport(s) d'évaluation </Text>
81-
<Icon
82-
className="fr-mb-1w fr-pt-1w"
83-
size="3x"
84-
name="ri-global-line"
85-
/>
86-
<Text>Consulter le site du HCERES</Text>
87-
</div>
88-
</Link>
89-
</div>
90-
</Col>
91-
) }
92-
<Row gutters>
93-
{data.data.map((document) => (
94-
<Col n="12 md-6" key={document.id}>
95-
<div className="fr-card fr-card--xs fr-card--shadow">
96-
<div className="fr-card__body">
97-
<div className="fr-card__content">
98-
<div className="fr-card__start">
99-
<Row className="flex--space-between">
100-
<BadgeGroup>
101-
{renderGroupBadge(document.canAccess)}
102-
</BadgeGroup>
103-
{editMode && <Button onClick={() => onOpenModalHandler(document)} className="edit-button" icon="ri-edit-line" title="Editer le document" tertiary borderless rounded />}
104-
</Row>
105-
</div>
106-
<p className="fr-card__title">{document.title}</p>
107-
<Row className="fr-card__desc">
108-
<BadgeGroup className="fr-mt-1v">
109-
<Badge text={document.documentType?.usualName} />
110-
<Badge type="info" text={document.startDate?.slice(0, 4)} />
75+
<Row gutters>
76+
{data.data.map((document) => (
77+
<Col n="12 md-6" key={document.id}>
78+
<div className="fr-card fr-card--xs fr-card--shadow" style={{ zIndex: 'calc(var(--ground) + 499 !important' }}>
79+
<div className="fr-card__body">
80+
<div className="fr-card__content">
81+
<div className="fr-card__start">
82+
<Row className="flex--space-between">
83+
<BadgeGroup>
84+
{renderGroupBadge(document.canAccess)}
11185
</BadgeGroup>
86+
{editMode && <Button onClick={() => onOpenModalHandler(document)} className="edit-button" icon="ri-edit-line" title="Editer le document" tertiary borderless rounded />}
11287
</Row>
113-
{document.description && <div className="fr-card__desc">{document.description}</div>}
114-
<div className="fr-card__end">
115-
{(document.relatedObjects.length > 1) && <Text spacing="mb-1w" bold>Autres objets associés :</Text>}
116-
{document.documentUrl && (
117-
<Row>
118-
<Col className="fr-pb-1w">
119-
<Link target="_blank" href={document.documentUrl} rel="noreferrer">
120-
Lien vers le document
121-
</Link>
122-
</Col>
123-
</Row>
124-
)}
125-
{document.relatedObjects && (
126-
<TagList maxTags={2}>
127-
{document.relatedObjects
128-
.filter((related) => (related.id !== resourceId))
129-
.map((related) => <Tag iconPosition="right" icon="ri-arrow-right-line" onClick={() => navigate(related.href)} key={related.id}>{related.displayName}</Tag>)}
130-
</TagList>
131-
)}
88+
</div>
89+
<p className="fr-card__title">{document.title}</p>
90+
<Row className="fr-card__desc">
91+
<BadgeGroup className="fr-mt-1v">
92+
<Badge text={document.documentType?.usualName} />
93+
<Badge type="info" text={document.startDate?.slice(0, 4)} />
94+
</BadgeGroup>
95+
</Row>
96+
{document.description && <div className="fr-card__desc">{document.description}</div>}
97+
<div className="fr-card__end">
98+
{(document.relatedObjects.length > 1) && <Text spacing="mb-1w" bold>Autres objets associés :</Text>}
99+
{document.documentUrl && (
132100
<Row>
133-
{document.files.map((file) => (<Download key={file.url} file={file} />
134-
))}
101+
<Col className="fr-pb-1w">
102+
<Link target="_blank" href={document.documentUrl} rel="noreferrer">
103+
Lien vers le document
104+
</Link>
105+
</Col>
135106
</Row>
136-
</div>
107+
)}
108+
{document.relatedObjects && (
109+
<TagList maxTags={2}>
110+
{document.relatedObjects
111+
.filter((related) => (related.id !== resourceId))
112+
.map((related) => <Tag iconPosition="right" icon="ri-arrow-right-line" onClick={() => navigate(related.href)} key={related.id}>{related.displayName}</Tag>)}
113+
</TagList>
114+
)}
115+
<Row>
116+
{document.files.map((file) => (<Download key={file.url} file={file} />
117+
))}
118+
</Row>
137119
</div>
138120
</div>
139121
</div>
140-
</Col>
141-
))}
142-
</Row>
143-
144-
</>
145-
122+
</div>
123+
</Col>
124+
))}
125+
</Row>
146126
);
147127
};
148-
149128
return (
150-
<Bloc isLoading={isLoading} error={error} data={data}>
151-
<BlocTitle as="h2" look="h6">Documents</BlocTitle>
152-
<BlocActionButton onClick={() => onOpenModalHandler()}>
153-
Ajouter un document
154-
</BlocActionButton>
155-
<BlocContent>{renderContent()}</BlocContent>
156-
<BlocModal>
157-
<Modal isOpen={isOpen} size="lg" hide={() => setIsOpen(false)}>
158-
<ModalTitle>{modalTitle}</ModalTitle>
159-
<ModalContent>{modalContent}</ModalContent>
160-
</Modal>
161-
</BlocModal>
162-
</Bloc>
129+
<>
130+
{(apiObject === 'structures') && <WeblinksResources resourceId={resourceId} />}
131+
<Bloc isLoading={isLoading} error={error} data={data}>
132+
<BlocTitle as="h2" look="h6">Documents</BlocTitle>
133+
<BlocActionButton onClick={() => onOpenModalHandler()}>
134+
Ajouter un document
135+
</BlocActionButton>
136+
<BlocContent>{renderContent()}</BlocContent>
137+
<BlocModal>
138+
<Modal isOpen={isOpen} size="lg" hide={() => setIsOpen(false)}>
139+
<ModalTitle>{modalTitle}</ModalTitle>
140+
<ModalContent>{modalContent}</ModalContent>
141+
</Modal>
142+
</BlocModal>
143+
</Bloc>
144+
</>
163145
);
164146
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import PropTypes from 'prop-types';
2+
import { Icon } from '@dataesr/react-dsfr';
3+
import useFetch from '../../../hooks/useFetch';
4+
import Bloc from '../../bloc/bloc';
5+
import BlocContent from '../../bloc/bloc-content';
6+
import BlocTitle from '../../bloc/bloc-title';
7+
import ExpendableListCards from '../../card/expendable-list-cards';
8+
9+
const mapping = {
10+
PiaWEB: 'Données PiaWEB',
11+
hceres: "Rapport d'évaluation HCERES",
12+
};
13+
14+
export default function WeblinksResources({ resourceId }) {
15+
const { data, isLoading, error } = useFetch(`/structures/${resourceId}/weblinks?filters[type][$in]=hceres&filters[type][$in]=PiaWEB`);
16+
17+
const cards = data?.data?.filter((el) => Object.keys(mapping).includes(el.type)).map((el) => (
18+
<div key={el.id} className="fr-card fr-card--sm fr-card--grey fr-card--no-border">
19+
<div className="fr-card__body fr-enlarge-link">
20+
<div className="fr-card__content">
21+
<div className="flex-col flex--center">
22+
<Icon
23+
className="fr-mb-1w fr-pt-1w"
24+
name="ri-global-line"
25+
size="3x"
26+
color="var(--structures-color)"
27+
/>
28+
<span className="fr-text fr-text--sm fr-text--bold fr-m-0 flex-col">
29+
<a
30+
className="fr-mb-0 fr-text fr-text--sm text-center"
31+
href={el.url}
32+
target="_blank"
33+
rel="noreferrer"
34+
>
35+
{mapping[el.type]}
36+
</a>
37+
<span className="only-print">{el.url}</span>
38+
</span>
39+
</div>
40+
</div>
41+
</div>
42+
</div>
43+
));
44+
45+
return (
46+
<Bloc isLoading={isLoading} error={error} data={data}>
47+
<BlocTitle as="h2" look="h6">Resources externes</BlocTitle>
48+
<BlocContent>
49+
<ExpendableListCards max={10000} nCol="12 sm-6 md-4" list={cards} />
50+
</BlocContent>
51+
</Bloc>
52+
);
53+
}
54+
55+
WeblinksResources.propTypes = {
56+
resourceId: PropTypes.string.isRequired,
57+
};

src/components/blocs/relations-by-group/index.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ export default function RelationsByGroup({ group, reloader }) {
1919
const { id: groupId, name: groupName, accepts: groupAccepts } = group;
2020
const { notice } = useNotice();
2121
const { id: resourceId, apiObject } = useUrl('relations-groups');
22-
const url = `/relations?filters[relationsGroupId]=${groupId}&sort=relatedObject.collection&limit=100`;
22+
const url = `/relations?filters[relationsGroupId]=${groupId}&sort=relatedObject.collection&limit=10000`;
2323
const { data, isLoading, error, reload } = useFetch(url);
2424
const [showModal, setShowModal] = useState(false);
2525
const [showListModal, setShowListModal] = useState(false);
@@ -110,7 +110,7 @@ export default function RelationsByGroup({ group, reloader }) {
110110
onEdit={() => onOpenModalHandler(element)}
111111
/>
112112
));
113-
if (orderedList.length) {
113+
if (markers.length) {
114114
return (
115115
<Row gutters>
116116
<Col n="12">
@@ -136,7 +136,7 @@ export default function RelationsByGroup({ group, reloader }) {
136136
<BlocActionButton
137137
icon="ri-download-line"
138138
edit={false}
139-
onClick={() => exportToCsv(data?.data, `${resourceId}-${groupName}`, groupName, groupAccepts[0])}
139+
onClick={() => exportToCsv({ data: data?.data, fileName: `${resourceId}-${groupName}`, listName: groupName, tag: groupAccepts[0] })}
140140
>
141141
Télécharger la liste
142142
</BlocActionButton>

src/components/blocs/relations-by-tag/index.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,9 +97,10 @@ export default function RelationsByTag({ blocName, tag, resourceType, relatedObj
9797
|| (element.startDate < getComparableNow() && element.endDate > getComparableNow())
9898
|| (element.startDate < getComparableNow() && !element.endDate && element.active !== false)
9999
|| (element.startDate === null && element.endDate === null && element.active !== false)
100-
));
100+
)).sort((a, b) => new Date(b.startDate) - new Date(a.startDate));
101101

102-
const activesIds = currentRelations.map((element) => element.id);
102+
const activesIds = currentRelations
103+
.map((element) => element.id);
103104

104105
const inactives = data.data.filter((element) => (!activesIds.includes(element.id)));
105106

src/components/blocs/relations-by-tag/utils/exports.js

Lines changed: 52 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ function createCsvStructureRowFromRelation({ relation, inverse, listName }) {
7070
'Status de la liaison': isFinished(relation) ? 'Terminée' : 'En cours',
7171
'Date de début': relation.startDate,
7272
'Date de fin': relation.endDate,
73+
'Terminée à une date inconnue': (isFinished(relation) && !relation.endDate) ? 'Oui' : null,
7374
'Date de fin prévue': relation.endDatePrevisional,
7475
'Texte officiel de début de liaison': relation.startDateOfficialText?.title,
7576
'Lien du texte officiel de début de liaison': relation.startDateOfficialText?.pageUrl,
@@ -275,15 +276,60 @@ function createCsvGovernanceFromRelation({ relation, short = false }) {
275276
}
276277
return result;
277278
}
279+
function createCsvPersonFromRelation({ relation, inverse }) {
280+
const person = inverse ? relation.resource : relation.relatedObject;
281+
const relatedObject = inverse ? relation.relatedObject : relation.resource;
282+
return {
283+
'ID paysage ressource': relatedObject.id,
284+
Ressource: relatedObject.displayName,
285+
Civilité: getCivility(person.gender),
286+
Nom: person.lastName,
287+
Prénom: person.firstName,
288+
Fonction: relation.relationType?.[getRelationTypeLabel(person.gender)] || 'Appartient à la liste',
289+
'Date de début': relation.startDate,
290+
'Date de fin': relation.endDate,
291+
'Terminée à une date inconnue': (isFinished(relation) && !relation.endDate) ? 'Oui' : null,
292+
'Date de fin prévue': relation.endDatePrevisional,
293+
'Texte officiel de début de fonction': relation.startDateOfficialText?.title,
294+
'Lien du texte officiel de début de fonction': relation.startDateOfficialText?.pageUrl,
295+
'Texte officiel de fin de fonction': relation.endDateOfficialText?.title,
296+
'Lien du texte officiel de fin de fonction': relation.endDateOfficialText?.pageUrl,
297+
'Identifiant paysage de la personne': person.id,
298+
'idref de la personne': person.identifiers?.filter((i) => (i.type === 'idRef')).sort((a, b) => a?.startDate?.localCompare(b?.startDate)).map((i) => i.value).join('|'),
299+
'Orcid de la personne': person.identifiers?.filter((i) => (i.type === 'ORCID Id')).sort((a, b) => a?.startDate?.localCompare(b?.startDate)).map((i) => i.value).join('|'),
300+
'wikidata de la personne': person.identifiers?.filter((i) => (i.type === 'Wikidata')).sort((a, b) => a?.startDate?.localCompare(b?.startDate)).map((i) => i.value).join('|'),
301+
};
302+
}
303+
304+
function createCsvPrizeFromRelation({ relation, inverse }) {
305+
const prize = inverse ? relation.resource : relation.relatedObject;
306+
const relatedObject = inverse ? relation.relatedObject : relation.resource;
307+
return {
308+
'ID paysage ressource': relatedObject.id,
309+
Ressource: relatedObject.displayName,
310+
Libellé: prize.displayName,
311+
'Libellé anglais': prize.nameEn,
312+
Description: prize.descriptionFr,
313+
'Description en anglais': prize.descriptionEn,
314+
'Date de début': relation.startDate,
315+
'Date de fin': relation.endDate,
316+
'Terminée à une date inconnue': (isFinished(relation) && !relation.endDate) ? 'Oui' : null,
317+
'Date de fin prévue': relation.endDatePrevisional,
318+
'Texte officiel de début de fonction': relation.startDateOfficialText?.title,
319+
'Lien du texte officiel de début de fonction': relation.startDateOfficialText?.pageUrl,
320+
'Texte officiel de fin de fonction': relation.endDateOfficialText?.title,
321+
'Lien du texte officiel de fin de fonction': relation.endDateOfficialText?.pageUrl,
322+
};
323+
}
278324

279325
const inverseMapping = {
280326
'categorie-parent': createCategoryTermRowFromRelation,
281327
gouvernance: createCsvGovernanceFromRelation,
282328
laureat: createCsvLaureatesFromRelation,
283-
'personne-categorie': null,
284-
'personne-terme': null,
285-
'prix-categorie': null,
286-
'prix-terme': null,
329+
'personne-categorie': createCsvPersonFromRelation,
330+
'personne-terme': createCsvPersonFromRelation,
331+
'prix-categorie': createCsvPrizeFromRelation,
332+
'prix-terme': createCsvPrizeFromRelation,
287333
'prix-porteur': null,
288334
'projet-contact': null,
289335
'projet-categorie': null,
@@ -322,6 +368,8 @@ const regularMapping = {
322368
'terme-categorie': createCategoryTermRowFromRelation,
323369
'terme-parent': createCategoryTermRowFromRelation,
324370
structures: createCsvStructureRowFromRelation,
371+
persons: createCsvPersonFromRelation,
372+
prizes: createCsvPrizeFromRelation,
325373
'prix-des-membres': createCsvLaureatesFromRelation,
326374
};
327375

src/components/blocs/weblinks/constants.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ export const WEBLINKS_TYPES = [
2727
'mooc',
2828
'CanalU',
2929
'ServicePublic',
30+
'PiaWEB',
3031
// 'Sujet d\'actualités sue le site web du journal Le Monde'
3132
'EdCF',
3233
'OE1',

src/components/forms/documents/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@ export default function DocumentsForm({ id, data, onSave, onDelete }) {
184184
<File
185185
required
186186
label="Ajouter des fichiers"
187-
hint="Format acceptés csv, jpg, png, pdf, doc, docx, xls, xlsx, csv"
187+
hint="Formats acceptés csv, doc, docx, jpg, pdf, png, xls, xlsx"
188188
onChange={(e) => { setIsLoading(true); setFiles(e.target.files); }}
189189
multiple
190190
errorMessage={(showErrors && errors.files) ? errors.files : null}

0 commit comments

Comments
 (0)