/** * @module * Définit le modèle de données utilisé par l’application. */ import PropTypes from 'prop-types'; /** * Types de termes existants. */ export const termTypes = { disease: 'Maladie', symptom: 'Symptôme', sign: 'Signe', }; /** * Crée un valideur de type de propriété React supportant l’extension * `.isRequired` pour marquer une propriété comme requise. * * @param basicValidator Fonction basique de validation. * @return Fonction augmentée supportant l’extension `.isRequired`. */ const makePropType = basicValidator => { const validator = (props, propName, componentName) => { // Version optionnelle : on n’appelle le valideur que si la propriété a // été passée if (propName in props) { return basicValidator(props, propName, componentName); } }; validator.isRequired = (props, propName, componentName) => { // Version obligatoire : on jette une erreur si la propriété n’a pas // été passée puis on procède à la validation if (!(propName in props)) { return new Error( `Missing prop “${propName}” in props supplied to ` + `${componentName}.` ); } return basicValidator(props, propName, componentName); }; return validator; }; /** * Type de terme. */ export const TermType = PropTypes.oneOf(Object.values(termTypes)); /** * URL. */ const URL = makePropType((props, propName, componentName) => { const value = props[propName]; if (typeof value !== 'string') { return new Error( `URL passed as ${componentName}’s ${propName} prop must be ` + `a string, not a ${typeof value}.` ); } if (!value.startsWith('http://') && !value.startsWith('https://')) { return new Error( `URL “${value}”, passed as ${componentName}’s ${propName} ` + `prop, does not start with “http://” or “https://”.` ); } }); /** * Terme. * * Peut être une maladie, un symptôme ou un signe. */ export const Term = PropTypes.exact({ // Identifiant unique id: PropTypes.string.isRequired, // Nom canonique name: PropTypes.string.isRequired, // Noms alternatifs alias: PropTypes.arrayOf(PropTypes.string).isRequired, // Types (maladie, symptôme, signe) types: PropTypes.arrayOf(TermType).isRequired, // Facteur d’importance weight: PropTypes.number.isRequired, // Adresse de la ressource de référence url: URL.isRequired, }); /** * Relation entre deux termes. */ export const Relation = makePropType((props, propName, componentName) => { const value = props[propName]; if (!Array.isArray(value)) { return new Error( `Relation ${propName} must be an array.` ); } if (value.length !== 2) { return new Error( `Relation ${propName} must contain exactly two entries.` ); } });