import {find, result} from "lodash"; import * as React from "react"; import AutocompleteSelect, {AutoCompleteResult} from "focus-components/autocomplete-select"; import AutocompleteText from "focus-components/autocomplete-text/field"; import Select from "focus-components/select"; import {EntityField} from "../entity"; import {StyleInjector} from "../theming"; import {Field, FieldProps} from "./field"; /** Options communes à tous les champs. */ export interface BaseOptions { error?: string; isEdit?: boolean; labelKey?: string; name?: string; value?: any; ref?: (field: Field) => void; contentCellPosition?: string; contentOffset?: number; contentSize?: number; hasLabel?: boolean; isRequired?: boolean; label?: string; labelCellPosition?: string; labelOffset?: number; labelSize?: number; } /** Options pour `autocompleteSelectFor`. */ export interface AutocompleteSelectOptions extends AutocompleteTextOptions { keyResolver: (code: string | number) => Promise; } /** Options pour `autocompleteTextFor`. */ export interface AutocompleteTextOptions extends BaseOptions { onChange?: (code: string) => void; querySearcher: (text: string) => Promise; } /** Options pour `fieldForWith` */ export interface FieldOptions extends BaseOptions { DisplayComponent?: ReactComponent; FieldComponent?: ReactComponent; InputComponent?: ReactComponent; LabelComponent?: ReactComponent<{domain: string, name: string, text: string}>; } /** Options pour `selectFor`. */ export interface SelectOptions extends BaseOptions { onChange?: (code: T) => void; labelKey?: string; valueKey?: string; values?: {code?: T, id?: T}[]; } /** Options pour `stringFor` et `textFor`. */ export interface TextOptions { formatter?: (data: any) => string; labelKey?: string; style?: React.CSSProperties; value?: any; valueKey?: string; values?: {}[]; } /** State propre à ComponentWithEntity. */ export interface CWEState { isEdit?: boolean; error?: {[x: string]: string}; entity?: E; } /** * Crée un champ de type AutocompleteSelect. * @param field La définition de champ. * @param options Les options du champ. */ export function autocompleteSelectFor(field: EntityField, options: AutocompleteSelectOptions) { (options as FieldProps).InputComponent = AutocompleteSelect; return fieldForWith(field, options); } /** * Crée un champ de type AutocompleteText. * @param field La définition de champ. * @param options Les options du champ. */ export function autocompleteTextFor(field: EntityField, options: AutocompleteTextOptions) { (options as FieldProps).InputComponent = AutocompleteText; return fieldForWith(field, options); } /** * Crée un champ standard en lecture seule. * @param field La définition de champ. * @param options Les options du champ. */ export function displayFor(field: EntityField, options: BaseOptions & {[key: string]: any} = {}) { options.isEdit = false; return fieldForWith(field, options); } /** * Crée un champ standard. * @param field La définition de champ. * @param options Les options du champ. */ export function fieldFor(field: EntityField, options: BaseOptions & {[key: string]: any} = {}) { return fieldForWith(field, options); } /** * Crée un champ avec des composants personnalisés. * @param field La définition de champ. * @param options Les options du champ. */ export function fieldForWith(field: EntityField, options: FieldOptions & DisplayProps & FieldProps & InputProps) { const props = buildFieldProps(field, options); return ; } /** * Crée un champ avec résolution de référence. * @param field La définition de champ. * @param listName Le nom de la liste de référence. * @param options Les options du champ. */ export function selectFor(field: EntityField, values: {code?: T, id?: T}[], options: SelectOptions = {}) { (options as FieldProps).InputComponent = Select; (options as FieldProps).values = values.slice(); return fieldForWith(field, options); } /** * Récupère le texte correspondant à un champ. * @param field La définition de champ. * @param options Les options du champ. */ export function stringFor(field: EntityField, options: TextOptions = {}): string { const {formatter, valueKey, labelKey, values, value} = buildFieldProps(field, options); const processedValue = values ? result(find(values, {[valueKey || "code"]: value}), labelKey || "label") : value; return formatter!(processedValue); } /** * Affiche un champ sous format texte. * @param field La définition de champ. * @param options Les options du champ. */ export function textFor(field: EntityField, options: TextOptions = {}) { return
{stringFor(field, options)}
; } export function buildFieldProps(field: EntityField, options: BaseOptions = {}): FieldProps { const {value, $entity: {domain, translationKey, isRequired}} = field; const {hasLabel = true, ref, ...otherOptions} = options; const dom = domain || {}; const props: FieldProps = { domain, formatter: dom.formatter || (x => x), hasLabel, isRequired, label: translationKey, name, ref: (i: StyleInjector) => ref && ref(i && i.instance || null), value, unformatter: dom.unformatter || (x => x) }; return {...(domain || {}), ...props, ...otherOptions}; }