1
0
mirror of https://github.com/LaCasemate/fab-manager.git synced 2025-02-02 22:52:21 +01:00

158 lines
6.7 KiB
TypeScript
Raw Normal View History

2022-04-06 17:14:23 +02:00
import React, { useEffect, useState } from 'react';
import { UseFormRegister, useFieldArray, ArrayPath, useWatch, Path } from 'react-hook-form';
import { FieldValues } from 'react-hook-form/dist/types/fields';
import AuthProviderAPI from '../../api/auth-provider';
2022-04-11 13:19:07 +02:00
import { MappingFields, mappingType } from '../../models/authentication-provider';
2022-04-06 17:14:23 +02:00
import { Control } from 'react-hook-form/dist/types/form';
import { FormSelect } from '../form/form-select';
import { FormInput } from '../form/form-input';
2022-04-06 17:14:23 +02:00
import { useTranslation } from 'react-i18next';
import { FabButton } from '../base/fab-button';
import { TypeMappingModal } from './type-mapping-modal';
2022-04-12 10:02:39 +02:00
import { useImmer } from 'use-immer';
2022-04-06 17:14:23 +02:00
export interface DataMappingFormProps<TFieldValues, TContext extends object> {
register: UseFormRegister<TFieldValues>,
2022-04-06 17:14:23 +02:00
control: Control<TFieldValues, TContext>,
}
2022-04-06 17:14:23 +02:00
type selectModelFieldOption = { value: string, label: string };
/**
* Partial form to define the mapping of the data between the API of the authentication provider and the application internals.
*/
2022-04-06 17:14:23 +02:00
export const DataMappingForm = <TFieldValues extends FieldValues, TContext extends object>({ register, control }: DataMappingFormProps<TFieldValues, TContext>) => {
const { t } = useTranslation('shared');
const [dataMapping, setDataMapping] = useState<MappingFields>(null);
2022-04-12 10:02:39 +02:00
const [isOpenTypeMappingModal, updateIsOpenTypeMappingModal] = useImmer<Map<number, boolean>>(new Map());
2022-04-06 17:14:23 +02:00
const { fields, append, remove } = useFieldArray({ control, name: 'auth_provider_mappings_attributes' as ArrayPath<TFieldValues> });
const output = useWatch({ name: 'auth_provider_mappings_attributes' as Path<TFieldValues>, control });
/**
* Build the list of available models for the data mapping
*/
const buildModelOptions = (): Array<selectModelFieldOption> => {
if (!dataMapping) return [];
2022-04-06 17:14:23 +02:00
return Object.keys(dataMapping).map(model => {
return {
label: model,
value: model
};
}) || [];
};
/**
* Build the list of fields of the current model for the data mapping
*/
const buildFieldOptions = (formData: Array<TFieldValues>, index: number): Array<selectModelFieldOption> => {
if (!dataMapping) return [];
2022-04-06 17:14:23 +02:00
return dataMapping[getModel(formData, index)]?.map(field => {
return {
label: field[0],
value: field[0]
};
}) || [];
};
/**
* Return the name of the modal for the given index, in the current data-mapping form
*/
const getModel = (formData: Array<TFieldValues>, index: number): string => {
return formData ? formData[index]?.local_model : undefined;
};
/**
* Return the name of the field for the given index, in the current data-mapping form
*/
const getField = (formData: Array<TFieldValues>, index: number): string => {
return formData ? formData[index]?.local_field : undefined;
};
/**
* Return the type of data expected for the given index, in the current data-mapping form
*/
2022-04-11 13:19:07 +02:00
const getDataType = (formData: Array<TFieldValues>, index: number): mappingType => {
2022-04-06 17:14:23 +02:00
const model = getModel(formData, index);
const field = getField(formData, index);
if (model && field && dataMapping) {
2022-04-06 17:14:23 +02:00
return dataMapping[model]?.find(f => f[0] === field)?.[1];
}
};
/**
2022-04-12 10:02:39 +02:00
* Open/closes the "edit type mapping" modal dialog for the given mapping index
2022-04-06 17:14:23 +02:00
*/
2022-04-12 10:02:39 +02:00
const toggleTypeMappingModal = (index: number): () => void => {
return () => {
updateIsOpenTypeMappingModal(draft => draft.set(index, !draft.get(index)));
};
2022-04-06 17:14:23 +02:00
};
// fetch the mapping data from the API on mount
useEffect(() => {
AuthProviderAPI.mappingFields().then((data) => {
setDataMapping(data);
});
}, []);
return (
2022-04-11 13:19:07 +02:00
<div className="data-mapping-form array-mapping-form">
2022-04-06 17:14:23 +02:00
<h4>{t('app.shared.oauth2.define_the_fields_mapping')}</h4>
<div className="mapping-actions">
<FabButton
icon={<i className="fa fa-plus"/>}
onClick={() => append({})}>
{t('app.shared.oauth2.add_a_match')}
</FabButton>
</div>
2022-04-06 17:14:23 +02:00
{fields.map((item, index) => (
2022-04-11 13:19:07 +02:00
<div key={item.id} className="mapping-item">
2022-04-06 17:14:23 +02:00
<div className="inputs">
<FormInput id={`auth_provider_mappings_attributes.${index}.id`} register={register} type="hidden" />
<div className="local-data">
2022-04-11 13:19:07 +02:00
<FormSelect id={`auth_provider_mappings_attributes.${index}.local_model`}
control={control} rules={{ required: true }}
options={buildModelOptions()} label={t('app.shared.oauth2.model')}/>
<FormSelect id={`auth_provider_mappings_attributes.${index}.local_field`}
options={buildFieldOptions(output, index)}
control={control}
rules={{ required: true }}
label={t('app.shared.oauth2.field')} />
2022-04-06 17:14:23 +02:00
</div>
<div className="remote-data">
2022-04-11 13:19:07 +02:00
<FormInput id={`auth_provider_mappings_attributes.${index}.api_endpoint`}
register={register}
rules={{ required: true }}
placeholder="/api/resource..."
label={t('app.shared.oauth2.api_endpoint_url')} />
<FormSelect id={`auth_provider_mappings_attributes.${index}.api_data_type`}
options={[{ label: 'JSON', value: 'json' }]}
control={control} rules={{ required: true }}
label={t('app.shared.oauth2.api_type')} />
<FormInput id={`auth_provider_mappings_attributes.${index}.api_field`}
register={register}
rules={{ required: true }}
placeholder="field_name..."
label={t('app.shared.oauth2.api_fields')} />
2022-04-06 17:14:23 +02:00
</div>
</div>
<div className="actions">
2022-04-12 10:02:39 +02:00
<FabButton icon={<i className="fa fa-random" />} onClick={toggleTypeMappingModal(index)} disabled={getField(output, index) === undefined} tooltip={t('app.shared.authentication.data_mapping')} />
2022-04-06 17:14:23 +02:00
<FabButton icon={<i className="fa fa-trash" />} onClick={() => remove(index)} className="delete-button" />
2022-04-11 13:19:07 +02:00
<TypeMappingModal model={getModel(output, index)}
field={getField(output, index)}
type={getDataType(output, index)}
2022-04-12 10:02:39 +02:00
isOpen={isOpenTypeMappingModal.get(index)}
toggleModal={toggleTypeMappingModal(index)}
2022-04-11 13:19:07 +02:00
control={control} register={register}
fieldMappingId={index} />
2022-04-06 17:14:23 +02:00
</div>
</div>
))}
</div>
);
};