diff --git a/app/src/components/App.js b/app/src/components/App.js index 626f990..aa03cff 100644 --- a/app/src/components/App.js +++ b/app/src/components/App.js @@ -9,22 +9,22 @@ import { const App = () => { - const [terms, setTerms] = useState([]); + const [query, setQuery] = useState([]); - const diseases = useAsync([], diseasesBySymptoms, terms); - const results = useAsync([], exploreSymptoms, diseases); + const diseases = useAsync([], diseasesBySymptoms, query); + const terms = useAsync([], exploreSymptoms, diseases); return (
); diff --git a/app/src/components/DiseaseGraph.js b/app/src/components/DiseaseGraph.js index b613573..1427c18 100644 --- a/app/src/components/DiseaseGraph.js +++ b/app/src/components/DiseaseGraph.js @@ -8,17 +8,17 @@ import {symptomsSubgraph} from '../data/mock'; /** * Graphe de maladies et symptômes. * - * @prop terms Ensemble de symptômes recherchés par l’utilisateur. - * @prop setTerms Fonction de rappel pour ajouter de nouveaux termes de + * @prop terms Termes à afficher. + * @prop query Ensemble de termes recherchés par l’utilisateur. + * @prop setQuery Fonction de rappel pour ajouter de nouveaux termes de * recherche. - * @prop results Maladies correspondant à la recherche de l’utilisateur. */ -const DiseaseGraph = ({terms, setTerms, results}) => +const DiseaseGraph = ({terms, query, setQuery}) => { const {nodes, edges} = useAsync({ nodes: {}, edges: [] - }, symptomsSubgraph, results); + }, symptomsSubgraph, terms); /** * Rendu d’un nœud du graphe. @@ -28,14 +28,14 @@ const DiseaseGraph = ({terms, setTerms, results}) => const render = id => { const term = nodes[id]; - const isTerm = terms.some(({id: termId}) => termId === id); + const isInQuery = query.some(({id: termId}) => termId === id); const isDisease = nodes[id].types.includes(termTypes.disease); return ( */ const handleNodeClick = (id, ev) => { - const result = results.find(({id: termId}) => termId === id); - const termIndex = terms.findIndex(({id: termId}) => termId === id); + const term = nodes[id]; + const queryIndex = query.findIndex(({id: termId}) => termId === id); - if (result !== undefined) + if (!ev.ctrlKey) { - if (!ev.ctrlKey) - { - // Clic normal : Ouverture de la ressource - window.open(result.url, '_blank'); - } - else if (termIndex >= 0) - { - // Ctrl-clic : Retrait d’un terme déjà dans la requête - setTerms([ - ...terms.slice(0, termIndex), - ...terms.slice(termIndex + 1) - ]); - } - else - { - // Ctrl-clic : Ajout d’un nouveau terme dans la requête - setTerms(terms.concat([result])); - } + // Clic normal : Ouverture de la ressource + window.open(term.url, '_blank'); + } + else if (queryIndex >= 0) + { + // Ctrl-clic : Retrait d’un terme déjà dans la requête + setQuery([ + ...query.slice(0, queryIndex), + ...query.slice(queryIndex + 1) + ]); + } + else + { + // Ctrl-clic : Ajout d’un nouveau terme dans la requête + setQuery(query.concat([term])); } }; @@ -95,8 +92,8 @@ const DiseaseGraph = ({terms, setTerms, results}) => DiseaseGraph.propTypes = { terms: PropTypes.arrayOf(Term).isRequired, - setTerms: PropTypes.func.isRequired, - results: PropTypes.arrayOf(Term).isRequired, + query: PropTypes.arrayOf(Term).isRequired, + setQuery: PropTypes.func.isRequired, }; export default DiseaseGraph; diff --git a/app/src/components/TermInput.js b/app/src/components/TermInput.js index 0b0b9da..35eb5f2 100644 --- a/app/src/components/TermInput.js +++ b/app/src/components/TermInput.js @@ -19,12 +19,11 @@ const keys = Object.assign(Object.create(null), { /** * Zone de saisie des termes de recherche. * - * @prop terms Ensemble de termes déjà validés. + * @prop query Ensemble de termes déjà dans la requête. + * @prop setQuery Fonction de rappel utilisée pour modifier la requête. * @param availableTerms Termes pouvant être ajoutés par l’utilisateur. - * @prop setTerms Fonction de rappel utilisée pour modifier l’ensemble des - * termes validés par l’utilisateur. */ -const TermInput = ({terms, availableTerms, setTerms}) => +const TermInput = ({query, setQuery, availableTerms}) => { // Valeur actuellement saisie dans le champ de recherche de termes const [value, setValue] = useState(''); @@ -41,19 +40,19 @@ const TermInput = ({terms, availableTerms, setTerms}) => const inputRef = useRef(null); /** - * Ajoute un terme à l’ensemble des termes sélectionnés. + * Ajoute un terme à la requête. * * @param term Terme à ajouter. */ - const addTerm = term => + const addQueryTerm = term => { - if (terms.some(({id}) => id === term.id)) + if (query.some(({id}) => id === term.id)) { // N’ajoute pas les termes déjà sélectionnés return; } - setTerms(terms.concat([term])); + setQuery(query.concat([term])); setValue(''); setSuggestions([]); @@ -64,15 +63,15 @@ const TermInput = ({terms, availableTerms, setTerms}) => }; /** - * Supprime un terme des termes sélectionnés. + * Supprime un terme de la requête. * * @param index Indice du terme à supprimer dans la liste. */ - const removeTerm = index => + const removeQueryTerm = index => { - setTerms([ - ...terms.slice(0, index), - ...terms.slice(index + 1) + setQuery([ + ...query.slice(0, index), + ...query.slice(index + 1) ]); }; @@ -90,19 +89,19 @@ const TermInput = ({terms, availableTerms, setTerms}) => if (focusedSuggestion < suggestions.length) { - addTerm(suggestions[focusedSuggestion]); + addQueryTerm(suggestions[focusedSuggestion]); } } else if ( ev.keyCode === keys.backspace && !value - && terms.length !== 0 + && query.length !== 0 ) { // Touche Retour alors que le champ de saisie est vide : - // retrait du dernier terme + // retrait du dernier terme de la requête ev.preventDefault(); - setTerms(terms.slice(0, -1)); + setQuery(query.slice(0, -1)); } else if (ev.keyCode === keys.up) { @@ -141,7 +140,7 @@ const TermInput = ({terms, availableTerms, setTerms}) => // Sélectionne les termes qui n’ont pas déjà été choisis availableTerms.filter(({id: suggestionId}) => - !terms.some(({id: termId}) => + !query.some(({id: termId}) => termId === suggestionId ) ) @@ -151,11 +150,12 @@ const TermInput = ({terms, availableTerms, setTerms}) => return (
- {terms.map((term, index) => + {query.map((term, index) => {term.name} @@ -180,14 +180,17 @@ const TermInput = ({terms, availableTerms, setTerms}) => : '' ].join(' ')} onMouseEnter={setFocusedSuggestion.bind(null, index)} - onClick={addTerm.bind(null, suggestion)} + onClick={addQueryTerm.bind(null, suggestion)} + title="Cliquez pour ajouter ce terme à la recherche" > {suggestion.name} {suggestion.alias.length >= 1 ? ( = 2 + ? 'Autres noms : ' + : 'Autre nom : ') + suggestion.alias.join(', ') } > @@ -202,9 +205,9 @@ const TermInput = ({terms, availableTerms, setTerms}) => }; TermInput.propTypes = { - terms: PropTypes.arrayOf(Term).isRequired, + query: PropTypes.arrayOf(Term).isRequired, + setQuery: PropTypes.func.isRequired, availableTerms: PropTypes.arrayOf(Term).isRequired, - setTerms: PropTypes.func.isRequired }; export default TermInput; diff --git a/app/src/data/model.js b/app/src/data/model.js index c16121d..7fbe286 100644 --- a/app/src/data/model.js +++ b/app/src/data/model.js @@ -75,7 +75,7 @@ const URL = makePropType((props, propName, componentName) => { return new Error( `URL “${value}”, passed as ${componentName}’s ${propName} ` - + `prop, does not start with “http://” or “https://”.` + + 'prop, does not start with “http://” or “https://”.' ); } }); @@ -108,7 +108,7 @@ export const Term = PropTypes.exact({ /** * Relation entre deux termes. */ -export const Relation = makePropType((props, propName, componentName) => +export const Relation = makePropType((props, propName) => { const value = props[propName]; diff --git a/app/style/style.css b/app/style/style.css index 404cf0f..e4d4551 100644 --- a/app/style/style.css +++ b/app/style/style.css @@ -109,7 +109,7 @@ input box-shadow: var(--shadow-high); } -.TermInput_term +.TermInput_queryTerm { display: inline-block; @@ -128,7 +128,7 @@ input transition: background var(--animation-short) var(--animation-ease-out); } -.TermInput_term:hover +.TermInput_queryTerm:hover { background: var(--color-accent); } @@ -296,7 +296,7 @@ input color: var(--color-dark); } -.SearchResults_result-term +.SearchResults_result-inQuery { background: var(--color-secondary); color: var(--color-light);