wikimedica-disease-search/app/src/components/DiseaseGraph.js

107 lines
3.0 KiB
JavaScript
Raw Normal View History

import React from 'react';
2019-12-04 23:54:44 +00:00
import PropTypes from 'prop-types';
import Graph from './Graph.js';
import {useAsync} from '../util.js';
2019-12-04 23:54:44 +00:00
import {Term, termTypes} from '../data/model.js';
import {symptomsSubgraph} from '../data/mock';
2019-12-04 23:54:44 +00:00
/**
* Graphe de maladies et symptômes.
*
* @prop terms Termes à afficher.
* @prop query Ensemble de termes recherchés par lutilisateur.
* @prop addQueryTerm Fonction de rappel pour ajouter un terme à la requête.
* @prop removeQueryTerm Fonction de rappel pour ôter un terme de la requête.
2019-12-04 23:54:44 +00:00
*/
const DiseaseGraph = ({
terms,
query,
addQueryTerm,
removeQueryTerm,
}) =>
{
const {nodes, edges} = useAsync({
nodes: {},
edges: [],
}, symptomsSubgraph, terms);
2019-12-04 04:20:06 +00:00
/**
* Rendu dun nœud du graphe.
*
* @param id Identifiant du nœud à afficher.
*/
const render = id =>
{
2019-12-05 02:06:19 +00:00
const term = nodes[id];
const isInQuery = query.some(({id: termId}) => termId === id);
2019-12-04 23:54:44 +00:00
const isDisease = nodes[id].types.includes(termTypes.disease);
return (
2019-12-05 02:06:19 +00:00
<span
className={[
'SearchResults_result',
isInQuery ? 'SearchResults_result-inQuery' : '',
2019-12-05 02:06:19 +00:00
isDisease ? 'SearchResults_result-disease' : '',
].join(' ')}
title={
`Cliquez pour plus dinformations sur « ${term.name} »\n`
+ `(Ctrl-clic pour ${
isInQuery
? 'lenlever de'
: 'lajouter à'
} la requête)`
2019-12-05 02:06:19 +00:00
}
>
{nodes[id].name}
</span>
);
};
2019-12-04 04:20:06 +00:00
/**
* Gère le clic sur un nœud du graphe.
*
* @param id Identifiant du nœud cliqué.
2019-12-05 02:06:19 +00:00
* @param ev Événement DOM décrivant le clic.
2019-12-04 04:20:06 +00:00
*/
2019-12-05 02:06:19 +00:00
const handleNodeClick = (id, ev) =>
2019-12-04 04:20:06 +00:00
{
const term = nodes[id];
const queryIndex = query.findIndex(({id: termId}) => termId === id);
2019-12-04 04:20:06 +00:00
if (!ev.ctrlKey)
{
// Clic normal : Ouverture de la ressource
window.open(term.url, '_blank');
}
else if (queryIndex >= 0)
{
// Ctrl-clic : Retrait dun terme déjà dans la requête
removeQueryTerm(queryIndex);
}
else
2019-12-04 04:20:06 +00:00
{
// Ctrl-clic : Ajout dun nouveau terme dans la requête
addQueryTerm(term);
2019-12-04 04:20:06 +00:00
}
};
return (
<Graph
nodes={Object.keys(nodes)}
edges={edges}
2019-12-04 04:20:06 +00:00
emptyMessage="Aucune maladie ne corresond à ces symptômes"
render={render}
2019-12-04 04:20:06 +00:00
onNodeClick={handleNodeClick}
/>
);
};
2019-12-04 23:54:44 +00:00
DiseaseGraph.propTypes = {
terms: PropTypes.arrayOf(Term).isRequired,
query: PropTypes.arrayOf(Term).isRequired,
addQueryTerm: PropTypes.func.isRequired,
removeQueryTerm: PropTypes.func.isRequired,
2019-12-04 23:54:44 +00:00
};
export default DiseaseGraph;