wikimedica-disease-search/app/src/data/model.js

129 lines
3.0 KiB
JavaScript
Raw Normal View History

2019-12-04 23:54:44 +00:00
/**
* @module
* Définit le modèle de données utilisé par lapplication.
*/
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 lextension
* `.isRequired` pour marquer une propriété comme requise.
*
* @param basicValidator Fonction basique de validation.
* @return Fonction augmentée supportant lextension `.isRequired`.
*/
const makePropType = basicValidator =>
{
const validator = (props, propName, componentName) =>
{
// Version optionnelle : on nappelle 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é na 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;
};
2019-12-04 23:54:44 +00:00
/**
* 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://”.`
);
}
});
2019-12-04 23:54:44 +00:00
/**
* Terme.
*
* Peut être une maladie, un symptôme ou un signe.
*/
export const Term = PropTypes.exact({
// Identifiant unique
2019-12-04 23:54:44 +00:00
id: PropTypes.string.isRequired,
// Nom canonique
2019-12-04 23:54:44 +00:00
name: PropTypes.string.isRequired,
// Noms alternatifs
2019-12-04 23:54:44 +00:00
alias: PropTypes.arrayOf(PropTypes.string).isRequired,
// Types (maladie, symptôme, signe)
2019-12-04 23:54:44 +00:00
types: PropTypes.arrayOf(TermType).isRequired,
// Facteur dimportance
2019-12-04 23:54:44 +00:00
weight: PropTypes.number.isRequired,
// Adresse de la ressource de référence
url: URL.isRequired,
2019-12-04 23:54:44 +00:00
});
/**
* Relation entre deux termes.
*/
export const Relation = makePropType((props, propName, componentName) =>
2019-12-04 23:54:44 +00:00
{
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.`
);
}
});