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

107 lines
3.0 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import React from 'react';
import PropTypes from 'prop-types';
import Graph from './Graph.js';
import {useAsync} from '../util.js';
import {Term, termTypes} from '../data/model.js';
import {symptomsSubgraph} from '../data/mock';
/**
* 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.
*/
const DiseaseGraph = ({
terms,
query,
addQueryTerm,
removeQueryTerm,
}) =>
{
const {nodes, edges} = useAsync({
nodes: {},
edges: [],
}, symptomsSubgraph, terms);
/**
* Rendu dun nœud du graphe.
*
* @param id Identifiant du nœud à afficher.
*/
const render = id =>
{
const term = nodes[id];
const isInQuery = query.some(({id: termId}) => termId === id);
const isDisease = nodes[id].types.includes(termTypes.disease);
return (
<span
className={[
'SearchResults_result',
isInQuery ? 'SearchResults_result-inQuery' : '',
isDisease ? 'SearchResults_result-disease' : '',
].join(' ')}
title={
`Cliquez pour plus dinformations sur « ${term.name} »\n`
+ `(Ctrl-clic pour ${
isInQuery
? 'lenlever de'
: 'lajouter à'
} la requête)`
}
>
{nodes[id].name}
</span>
);
};
/**
* Gère le clic sur un nœud du graphe.
*
* @param id Identifiant du nœud cliqué.
* @param ev Événement DOM décrivant le clic.
*/
const handleNodeClick = (id, ev) =>
{
const term = nodes[id];
const queryIndex = query.findIndex(({id: termId}) => termId === id);
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
{
// Ctrl-clic : Ajout dun nouveau terme dans la requête
addQueryTerm(term);
}
};
return (
<Graph
nodes={Object.keys(nodes)}
edges={edges}
emptyMessage="Aucune maladie ne corresond à ces symptômes"
render={render}
onNodeClick={handleNodeClick}
/>
);
};
DiseaseGraph.propTypes = {
terms: PropTypes.arrayOf(Term).isRequired,
query: PropTypes.arrayOf(Term).isRequired,
addQueryTerm: PropTypes.func.isRequired,
removeQueryTerm: PropTypes.func.isRequired,
};
export default DiseaseGraph;