129 lines
3.0 KiB
JavaScript
129 lines
3.0 KiB
JavaScript
/**
|
||
* @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) =>
|
||
{
|
||
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.`
|
||
);
|
||
}
|
||
});
|