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

(bug) unable to remove an SSO data mapping field once saved

This commit is contained in:
Sylvain 2022-06-22 16:42:14 +02:00
parent 2d80600e97
commit c1246092ed
5 changed files with 52 additions and 15 deletions

View File

@ -24,6 +24,7 @@
- Fix a bug: unable to generate the secret key base during the setup - Fix a bug: unable to generate the secret key base during the setup
- Fix a bug: error message during the setup: the input device is not a TTY - Fix a bug: error message during the setup: the input device is not a TTY
- Fix a bug: when Fab-manager was installed as non-root user, unable to compile the assets during the upgrade - Fix a bug: when Fab-manager was installed as non-root user, unable to compile the assets during the upgrade
- Fix a bug: unable to remove an SSO data mapping field once saved
- [TODO DEPLOY] `\curl -sSL https://raw.githubusercontent.com/sleede/fab-manager/master/scripts/set-docker-user.sh | bash` - [TODO DEPLOY] `\curl -sSL https://raw.githubusercontent.com/sleede/fab-manager/master/scripts/set-docker-user.sh | bash`
## v5.4.4 2022 June 8 ## v5.4.4 2022 June 8

View File

@ -1,9 +1,9 @@
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
import { UseFormRegister, useFieldArray, ArrayPath, useWatch, Path } from 'react-hook-form'; import { UseFormRegister, useFieldArray, ArrayPath, useWatch, Path, FieldPathValue } from 'react-hook-form';
import { FieldValues } from 'react-hook-form/dist/types/fields'; import { FieldValues } from 'react-hook-form/dist/types/fields';
import AuthProviderAPI from '../../api/auth-provider'; import AuthProviderAPI from '../../api/auth-provider';
import { AuthenticationProviderMapping, MappingFields, mappingType, ProvidableType } from '../../models/authentication-provider'; import { AuthenticationProviderMapping, MappingFields, mappingType, ProvidableType } from '../../models/authentication-provider';
import { Control, UseFormSetValue } from 'react-hook-form/dist/types/form'; import { Control, UnpackNestedValue, UseFormSetValue } from 'react-hook-form/dist/types/form';
import { FormSelect } from '../form/form-select'; import { FormSelect } from '../form/form-select';
import { FormInput } from '../form/form-input'; import { FormInput } from '../form/form-input';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
@ -96,6 +96,31 @@ export const DataMappingForm = <TFieldValues extends FieldValues, TContext exten
}; };
}; };
/**
* Remove the data whom index is provided: mark it as "to destroy" or simply remove it if it was unsaved
*/
const removeMapping = (index: number): void => {
if (currentFormValues[index].id) {
setValue(
`auth_provider_mappings_attributes.${index}._destroy` as Path<TFieldValues>,
true as UnpackNestedValue<FieldPathValue<TFieldValues, Path<TFieldValues>>>
);
} else {
remove(index);
}
};
/**
* Return a className based on the current mapping-item status
*/
const itemStatus = (index: number): string => {
if (currentFormValues[index]?.id) {
if (currentFormValues[index]._destroy) return 'destroyed-item';
return 'saved-item';
}
return 'new-item';
};
// fetch the mapping data from the API on mount // fetch the mapping data from the API on mount
useEffect(() => { useEffect(() => {
AuthProviderAPI.mappingFields().then((data) => { AuthProviderAPI.mappingFields().then((data) => {
@ -114,7 +139,7 @@ export const DataMappingForm = <TFieldValues extends FieldValues, TContext exten
</FabButton> </FabButton>
</div> </div>
{fields.map((item, index) => ( {fields.map((item, index) => (
<div key={item.id} className="mapping-item"> <div key={item.id} className={`mapping-item ${itemStatus(index)}`}>
<div className="inputs"> <div className="inputs">
<FormInput id={`auth_provider_mappings_attributes.${index}.id`} register={register} type="hidden" /> <FormInput id={`auth_provider_mappings_attributes.${index}.id`} register={register} type="hidden" />
<div className="local-data"> <div className="local-data">
@ -141,7 +166,7 @@ export const DataMappingForm = <TFieldValues extends FieldValues, TContext exten
onClick={toggleTypeMappingModal(index)} onClick={toggleTypeMappingModal(index)}
disabled={getField(output, index) === undefined} disabled={getField(output, index) === undefined}
tooltip={t('app.admin.authentication.data_mapping_form.data_mapping')} /> tooltip={t('app.admin.authentication.data_mapping_form.data_mapping')} />
<FabButton icon={<i className="fa fa-trash" />} onClick={() => remove(index)} className="delete-button" /> <FabButton icon={<i className="fa fa-trash" />} onClick={() => removeMapping(index)} className="delete-button" />
<TypeMappingModal model={getModel(output, index)} <TypeMappingModal model={getModel(output, index)}
field={getField(output, index)} field={getField(output, index)}
type={getDataType(output, index)} type={getDataType(output, index)}

View File

@ -44,17 +44,19 @@ export const OpenidConnectDataMappingForm = <TFieldValues extends FieldValues>({
const model = currentFormValues[index]?.local_model; const model = currentFormValues[index]?.local_model;
const field = currentFormValues[index]?.local_field; const field = currentFormValues[index]?.local_field;
const configuration = standardConfiguration[`${model}.${field}`]; const configuration = standardConfiguration[`${model}.${field}`];
setValue( if (configuration) {
`auth_provider_mappings_attributes.${index}.api_field` as Path<TFieldValues>, setValue(
configuration.api_field as UnpackNestedValue<FieldPathValue<TFieldValues, Path<TFieldValues>>> `auth_provider_mappings_attributes.${index}.api_field` as Path<TFieldValues>,
); configuration.api_field as UnpackNestedValue<FieldPathValue<TFieldValues, Path<TFieldValues>>>
if (configuration.transformation) { );
Object.keys(configuration.transformation).forEach((key) => { if (configuration.transformation) {
setValue( Object.keys(configuration.transformation).forEach((key) => {
`auth_provider_mappings_attributes.${index}.transformation.${key}` as Path<TFieldValues>, setValue(
configuration.transformation[key] as UnpackNestedValue<FieldPathValue<TFieldValues, Path<TFieldValues>>> `auth_provider_mappings_attributes.${index}.transformation.${key}` as Path<TFieldValues>,
); configuration.transformation[key] as UnpackNestedValue<FieldPathValue<TFieldValues, Path<TFieldValues>>>
}); );
});
}
} }
}; };

View File

@ -14,6 +14,7 @@ export type mappingType = 'string' | 'text' | 'date' | 'integer' | 'boolean';
export interface AuthenticationProviderMapping { export interface AuthenticationProviderMapping {
id?: number, id?: number,
_destroy?: boolean,
local_model: 'user' | 'profile', local_model: 'user' | 'profile',
local_field: string, local_field: string,
api_field: string, api_field: string,

View File

@ -24,5 +24,13 @@
color: white; color: white;
} }
} }
&.destroyed-item {
display: none;
}
&.new-item {
background-color: var(--information-lightest);
}
} }
} }