1
0
mirror of https://github.com/LaCasemate/fab-manager.git synced 2024-11-29 10:24:20 +01:00

(i18n) reorganize translations per components

This commit is contained in:
Sylvain 2022-04-12 13:54:47 +02:00
parent e91fa00afc
commit ecc7565346
16 changed files with 112 additions and 113 deletions

View File

@ -13,19 +13,19 @@ export interface BooleanMappingFormProps<TFieldValues> {
* Partial form to map an internal boolean field to an external API providing a string value.
*/
export const BooleanMappingForm = <TFieldValues extends FieldValues>({ register, fieldMappingId }: BooleanMappingFormProps<TFieldValues>) => {
const { t } = useTranslation('shared');
const { t } = useTranslation('admin');
return (
<div className="boolean-mapping-form">
<h4>{t('app.shared.authentication.mappings')}</h4>
<h4>{t('app.admin.authentication.boolean_mapping_form.mappings')}</h4>
<FormInput id={`auth_provider_mappings_attributes.${fieldMappingId}.transformation.true_value`}
register={register}
rules={{ required: true }}
label={t('app.shared.authentication.true_value')} />
label={t('app.admin.authentication.boolean_mapping_form.true_value')} />
<FormInput id={`auth_provider_mappings_attributes.${fieldMappingId}.transformation.false_value`}
register={register}
rules={{ required: true }}
label={t('app.shared.authentication.false_value')} />
label={t('app.admin.authentication.boolean_mapping_form.false_value')} />
</div>
);
};

View File

@ -23,7 +23,7 @@ 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.
*/
export const DataMappingForm = <TFieldValues extends FieldValues, TContext extends object>({ register, control }: DataMappingFormProps<TFieldValues, TContext>) => {
const { t } = useTranslation('shared');
const { t } = useTranslation('admin');
const [dataMapping, setDataMapping] = useState<MappingFields>(null);
const [isOpenTypeMappingModal, updateIsOpenTypeMappingModal] = useImmer<Map<number, boolean>>(new Map());
@ -101,12 +101,12 @@ export const DataMappingForm = <TFieldValues extends FieldValues, TContext exten
return (
<div className="data-mapping-form array-mapping-form">
<h4>{t('app.shared.oauth2.define_the_fields_mapping')}</h4>
<h4>{t('app.admin.authentication.data_mapping_form.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')}
{t('app.admin.authentication.data_mapping_form.add_a_match')}
</FabButton>
</div>
{fields.map((item, index) => (
@ -116,33 +116,37 @@ export const DataMappingForm = <TFieldValues extends FieldValues, TContext exten
<div className="local-data">
<FormSelect id={`auth_provider_mappings_attributes.${index}.local_model`}
control={control} rules={{ required: true }}
options={buildModelOptions()} label={t('app.shared.oauth2.model')}/>
options={buildModelOptions()}
label={t('app.admin.authentication.data_mapping_form.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')} />
label={t('app.admin.authentication.data_mapping_form.field')} />
</div>
<div className="remote-data">
<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')} />
label={t('app.admin.authentication.data_mapping_form.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')} />
label={t('app.admin.authentication.data_mapping_form.api_type')} />
<FormInput id={`auth_provider_mappings_attributes.${index}.api_field`}
register={register}
rules={{ required: true }}
placeholder="field_name..."
tooltip={<HtmlTranslate trKey="app.shared.oauth2.api_field_help_html" />}
label={t('app.shared.oauth2.api_fields')} />
tooltip={<HtmlTranslate trKey="app.admin.authentication.data_mapping_form.api_field_help_html" />}
label={t('app.admin.authentication.data_mapping_form.api_field')} />
</div>
</div>
<div className="actions">
<FabButton icon={<i className="fa fa-random" />} onClick={toggleTypeMappingModal(index)} disabled={getField(output, index) === undefined} tooltip={t('app.shared.authentication.data_mapping')} />
<FabButton icon={<i className="fa fa-random" />}
onClick={toggleTypeMappingModal(index)}
disabled={getField(output, index) === undefined}
tooltip={t('app.admin.authentication.data_mapping_form.data_mapping')} />
<FabButton icon={<i className="fa fa-trash" />} onClick={() => remove(index)} className="delete-button" />
<TypeMappingModal model={getModel(output, index)}
field={getField(output, index)}

View File

@ -13,7 +13,7 @@ export interface DateMappingFormProps<TFieldValues, TContext extends object> {
* Partial form for mapping an internal date field to an external API.
*/
export const DateMappingForm = <TFieldValues extends FieldValues, TContext extends object>({ control, fieldMappingId }: DateMappingFormProps<TFieldValues, TContext>) => {
const { t } = useTranslation('shared');
const { t } = useTranslation('admin');
// available date formats
const dateFormats = [
@ -41,12 +41,12 @@ export const DateMappingForm = <TFieldValues extends FieldValues, TContext exten
return (
<div className="date-mapping-form">
<h4>{t('app.shared.authentication.input_format')}</h4>
<h4>{t('app.admin.authentication.date_mapping_form.input_format')}</h4>
<FormSelect id={`auth_provider_mappings_attributes.${fieldMappingId}.transformation.format`}
control={control}
rules={{ required: true }}
options={dateFormats}
label={t('app.shared.authentication.date_format')} />
label={t('app.admin.authentication.date_mapping_form.date_format')} />
</div>
);
};

View File

@ -16,13 +16,13 @@ export interface IntegerMappingFormProps<TFieldValues, TContext extends object>
* Partial for to map an internal integer field to an external API providing a string value.
*/
export const IntegerMappingForm = <TFieldValues extends FieldValues, TContext extends object>({ register, control, fieldMappingId }: IntegerMappingFormProps<TFieldValues, TContext>) => {
const { t } = useTranslation('shared');
const { t } = useTranslation('admin');
const { fields, append, remove } = useFieldArray({ control, name: 'auth_provider_mappings_attributes_transformation_mapping' as ArrayPath<TFieldValues> });
return (
<div className="integer-mapping-form array-mapping-form">
<h4>{t('app.shared.authentication.mappings')}</h4>
<h4>{t('app.admin.authentication.integer_mapping_form.mappings')}</h4>
<div className="mapping-actions">
<FabButton
icon={<i className="fa fa-plus" />}
@ -34,12 +34,12 @@ export const IntegerMappingForm = <TFieldValues extends FieldValues, TContext ex
<FormInput id={`auth_provider_mappings_attributes.${fieldMappingId}.transformation.mapping.${index}.from`}
register={register}
rules={{ required: true }}
label={t('app.shared.authentication.mapping_from')} />
label={t('app.admin.authentication.integer_mapping_form.mapping_from')} />
<FormInput id={`auth_provider_mappings_attributes.${fieldMappingId}.transformation.mapping.${index}.to`}
register={register}
type="number"
rules={{ required: true }}
label={t('app.shared.authentication.mapping_to')} />
label={t('app.admin.authentication.integer_mapping_form.mapping_to')} />
</div>
<div className="actions">
<FabButton icon={<i className="fa fa-trash" />} onClick={() => remove(index)} className="delete-button" />

View File

@ -12,7 +12,7 @@ interface Oauth2FormProps<TFieldValues> {
* Partial form to fill the OAuth2 settings for a new/existing authentication provider.
*/
export const Oauth2Form = <TFieldValues extends FieldValues>({ register }: Oauth2FormProps<TFieldValues>) => {
const { t } = useTranslation('shared');
const { t } = useTranslation('admin');
// regular expression to validate the the input fields
const endpointRegex = /^\/?([-._~:?#[\]@!$&'()*+,;=%\w]+\/?)*$/;
@ -24,34 +24,34 @@ export const Oauth2Form = <TFieldValues extends FieldValues>({ register }: Oauth
<FormInput id="providable_attributes.base_url"
register={register}
placeholder="https://sso.example.net..."
label={t('app.shared.oauth2.common_url')}
label={t('app.admin.authentication.oauth2_form.common_url')}
rules={{ required: true, pattern: urlRegex }} />
<FormInput id="providable_attributes.authorization_endpoint"
register={register}
placeholder="/oauth2/auth..."
label={t('app.shared.oauth2.authorization_endpoint')}
label={t('app.admin.authentication.oauth2_form.authorization_endpoint')}
rules={{ required: true, pattern: endpointRegex }} />
<FormInput id="providable_attributes.token_endpoint"
register={register}
placeholder="/oauth2/token..."
label={t('app.shared.oauth2.token_acquisition_endpoint')}
label={t('app.admin.authentication.oauth2_form.token_acquisition_endpoint')}
rules={{ required: true, pattern: endpointRegex }} />
<FormInput id="providable_attributes.profile_url"
register={register}
placeholder="https://exemple.net/user..."
label={t('app.shared.oauth2.profil_edition_url')}
label={t('app.admin.authentication.oauth2_form.profil_edition_url')}
rules={{ required: true, pattern: urlRegex }} />
<FormInput id="providable_attributes.client_id"
register={register}
label={t('app.shared.oauth2.client_identifier')}
label={t('app.admin.authentication.oauth2_form.client_identifier')}
rules={{ required: true }} />
<FormInput id="providable_attributes.client_secret"
register={register}
label={t('app.shared.oauth2.client_secret')}
label={t('app.admin.authentication.oauth2_form.client_secret')}
rules={{ required: true }} />
<FormInput id="providable_attributes.scopes" register={register}
placeholder="profile,email..."
label={t('app.shared.oauth2.scopes')} />
label={t('app.admin.authentication.oauth2_form.scopes')} />
</div>
);
};

View File

@ -36,14 +36,14 @@ type selectProvidableTypeOption = { value: string, label: string };
export const ProviderForm: React.FC<ProviderFormProps> = ({ action, provider, onError, onSuccess }) => {
const { handleSubmit, register, control } = useForm<AuthenticationProvider>({ defaultValues: { ...provider } });
const [providableType, setProvidableType] = useState<string>(provider?.providable_type);
const { t } = useTranslation('shared');
const { t } = useTranslation('admin');
/**
* Callback triggered when the form is submitted: process with the provider creation or update.
*/
const onSubmit: SubmitHandler<AuthenticationProvider> = (data: AuthenticationProvider) => {
AuthProviderAPI[action](data).then(() => {
onSuccess(t(`app.shared.authentication.${action}_success`));
onSuccess(t(`app.admin.authentication.provider_form.${action}_success`));
}).catch(error => {
onError(error);
});
@ -54,7 +54,7 @@ export const ProviderForm: React.FC<ProviderFormProps> = ({ action, provider, on
*/
const buildProvidableTypeOptions = (): Array<selectProvidableTypeOption> => {
return Object.keys(METHODS).map((method: string) => {
return { value: method, label: t(`app.shared.authentication.${METHODS[method]}`) };
return { value: method, label: t(`app.admin.authentication.provider_form.methods.${METHODS[method]}`) };
});
};
@ -72,17 +72,18 @@ export const ProviderForm: React.FC<ProviderFormProps> = ({ action, provider, on
register={register}
readOnly={action === 'update'}
rules={{ required: true }}
label={t('app.shared.authentication.name')} />
label={t('app.admin.authentication.provider_form.name')} />
<FormSelect id="providable_type"
control={control}
options={buildProvidableTypeOptions()}
label={t('app.shared.authentication.authentication_type')}
label={t('app.admin.authentication.provider_form.authentication_type')}
onChange={onProvidableTypeChange}
readOnly={action === 'update'}
rules={{ required: true }} />
{providableType === 'OAuth2Provider' && <Oauth2Form register={register} />}
{providableType && providableType !== 'DatabaseProvider' && <DataMappingForm register={register} control={control} />}
<div className="main-actions">
<FabButton type="submit" className="submit-button">{t('app.shared.authentication.save')}</FabButton>
<FabButton type="submit" className="submit-button">{t('app.admin.authentication.provider_form.save')}</FabButton>
</div>
</form>
);

View File

@ -16,13 +16,13 @@ export interface StringMappingFormProps<TFieldValues, TContext extends object> {
* Partial form to map an internal string field to an external API.
*/
export const StringMappingForm = <TFieldValues extends FieldValues, TContext extends object>({ register, control, fieldMappingId }: StringMappingFormProps<TFieldValues, TContext>) => {
const { t } = useTranslation('shared');
const { t } = useTranslation('admin');
const { fields, append, remove } = useFieldArray({ control, name: 'auth_provider_mappings_attributes_transformation_mapping' as ArrayPath<TFieldValues> });
return (
<div className="string-mapping-form array-mapping-form">
<h4>{t('app.shared.authentication.mappings')}</h4>
<h4>{t('app.admin.authentication.string_mapping_form.mappings')}</h4>
<div className="mapping-actions">
<FabButton
icon={<i className="fa fa-plus" />}
@ -34,11 +34,11 @@ export const StringMappingForm = <TFieldValues extends FieldValues, TContext ext
<FormInput id={`auth_provider_mappings_attributes.${fieldMappingId}.transformation.mapping.${index}.from`}
register={register}
rules={{ required: true }}
label={t('app.shared.authentication.mapping_from')} />
label={t('app.admin.authentication.string_mapping_form.mapping_from')} />
<FormInput id={`auth_provider_mappings_attributes.${fieldMappingId}.transformation.mapping.${index}.to`}
register={register}
rules={{ required: true }}
label={t('app.shared.authentication.mapping_to')} />
label={t('app.admin.authentication.string_mapping_form.mapping_to')} />
</div>
<div className="actions">
<FabButton icon={<i className="fa fa-trash" />} onClick={() => remove(index)} className="delete-button" />

View File

@ -28,16 +28,16 @@ interface TypeMappingModalProps<TFieldValues, TContext extends object> {
* This component is intended to be used in a react-hook-form context.
*/
export const TypeMappingModal = <TFieldValues extends FieldValues, TContext extends object>({ model, field, type, isOpen, toggleModal, register, control, fieldMappingId }:TypeMappingModalProps<TFieldValues, TContext>) => {
const { t } = useTranslation('shared');
const { t } = useTranslation('admin');
return (
<FabModal isOpen={isOpen}
toggleModal={toggleModal}
className="type-mapping-modal"
title={t('app.shared.authentication.data_mapping')}
title={t('app.admin.authentication.type_mapping_modal.data_mapping')}
confirmButton={<i className="fa fa-check" />}
onConfirm={toggleModal}>
<span>{model} &gt; {field} ({t('app.shared.authentication.TYPE_expected', { TYPE: t(`app.shared.authentication.types.${type}`) })})</span>
<span>{model} &gt; {field} ({t('app.admin.authentication.type_mapping_modal.TYPE_expected', { TYPE: t(`app.admin.authentication.type_mapping_modal.types.${type}`) })})</span>
{type === 'integer' && <IntegerMappingForm register={register} control={control} fieldMappingId={fieldMappingId} />}
{type === 'boolean' && <BooleanMappingForm register={register} fieldMappingId={fieldMappingId} />}
{type === 'date' && <DateMappingForm control={control} fieldMappingId={fieldMappingId} />}

View File

@ -15,6 +15,7 @@ interface FormSelectProps<TFieldValues, TContext extends object, TOptionValue> e
className?: string,
placeholder?: string,
disabled?: boolean,
readOnly?: boolean,
}
/**
@ -26,7 +27,7 @@ type selectOption<TOptionValue> = { value: TOptionValue, label: string };
/**
* This component is a wrapper for react-select to use with react-hook-form
*/
export const FormSelect = <TFieldValues extends FieldValues, TContext extends object, TOptionValue>({ id, label, className, control, placeholder, options, valueDefault, error, rules, disabled, onChange }: FormSelectProps<TFieldValues, TContext, TOptionValue>) => {
export const FormSelect = <TFieldValues extends FieldValues, TContext extends object, TOptionValue>({ id, label, className, control, placeholder, options, valueDefault, error, rules, disabled, onChange, readOnly }: FormSelectProps<TFieldValues, TContext, TOptionValue>) => {
const classNames = `
form-select form-item ${className || ''}
${error && error[id] ? 'is-incorrect' : ''}
@ -62,6 +63,7 @@ export const FormSelect = <TFieldValues extends FieldValues, TContext extends ob
onChange(val.value);
}}
placeholder={placeholder}
isDisabled={readOnly}
options={options} />
} />
</div>

View File

@ -113,6 +113,7 @@ Application.Controllers.controller('NewAuthenticationController', ['$scope', '$s
*/
$scope.onSuccess = function (message) {
growl.success(message);
$scope.cancel();
};
/**

View File

@ -29,8 +29,8 @@
position: absolute;
right: 0;
top: 0;
background-color: black;
color: white;
background-color: white;
color: var(--gray-hard);
border-radius: 8px;
padding: 1rem;
font-size: 12px;

View File

@ -5,6 +5,6 @@ class DatabaseProviderValidator < ActiveModel::Validator
def validate(record)
return if DatabaseProvider.count.zero?
record.errors[:id] << I18n.t('app.admin.authentication_new.a_local_database_provider_already_exists_unable_to_create_another')
record.errors[:id] << I18n.t('authentication_providers.local_database_provider_already_exists')
end
end

View File

@ -9,6 +9,6 @@ class OAuth2ProviderValidator < ActiveModel::Validator
mapping.local_model == 'user' && mapping.local_field == 'uid'
end
record.errors.add(:uid, I18n.t('app.admin.authentication_new.it_is_required_to_set_the_matching_between_User.uid_and_the_API_to_add_this_provider'))
record.errors.add(:uid, I18n.t('authentication_providers.matching_between_User_uid_and_API_required'))
end
end

View File

@ -1049,26 +1049,64 @@ en:
birth_date: "Date of birth"
address: "Address"
phone_number: "Phone number"
#add a new authentication provider (SSO)
#authentication providers (SSO) components
authentication:
boolean_mapping_form:
mappings: "Mappings"
true_value: "True value"
false_value: "False value"
date_mapping_form:
input_format: "Input format"
date_format: "Date format"
integer_mapping_form:
mappings: "Mappings"
mapping_from: "From"
mapping_to: "To"
string_mapping_form:
mappings: "Mappings"
mapping_from: "From"
mapping_to: "To"
data_mapping_form:
define_the_fields_mapping: "Define the fields mapping"
add_a_match: "Add a match"
model: "Model"
field: "Field"
api_endpoint_url: "API endpoint or URL"
api_type: "API type"
api_field: "API field"
api_field_help_html: '<a href="https://jsonpath.com/" target="_blank">JsonPath</a> syntax is supported.<br> If many fields are selected, the first one will be used.<br> Example: $.data[*].name"'
data_mapping: "Data mapping"
type_mapping_modal:
data_mapping: "Data mapping"
TYPE_expected: "{TYPE} expected"
types:
integer: "integer"
string: "string"
text: "text"
date: "date"
boolean: "boolean"
oauth2_form:
common_url: "Server root URL"
authorization_endpoint: "Authorization endpoint"
token_acquisition_endpoint: "Token acquisition endpoint"
profil_edition_url: "Profil edition URL"
client_identifier: "Client identifier"
client_secret: "Client secret"
scopes: "Scopes"
provider_form:
name: "Name"
authentication_type: "Authentication type"
save: "Save"
methods:
local_database: "Local database"
o_auth2: "OAuth 2.0"
openid_connect: "OpenID Connect"
#create a new authentication provider (SSO)
authentication_new:
local_database: "Local Database"
o_auth2: "OAuth 2.0"
add_a_new_authentication_provider: "Add a new authentication provider"
a_local_database_provider_already_exists_unable_to_create_another: "A \"Local Database\" provider already exists. Unable to create another."
local_provider_successfully_saved: "Local provider successfully saved."
it_is_required_to_set_the_matching_between_User.uid_and_the_API_to_add_this_provider: "It is required to set the matching between User.uid and the API to add this provider."
security_issue_detected: "Security issue detected"
beware_the_oauth2_authenticatoin_provider_you_are_about_to_add_isnt_using_HTTPS: "Beware: the OAuth 2 provider you are about to add isn't using HTTPS."
this_is_a_serious_security_issue_on_internet_and_should_never_be_used_except_for_testing_purposes: "This is a serious security issue on internet and should never be used except for testing purposes."
do_you_really_want_to_continue: "Do you really want to continue?"
unsecured_oauth2_provider_successfully_added: "Unsecured OAuth 2.0 provider successfully added."
oauth2_provider_successfully_added: "OAuth 2.0 provider successfully added."
#edit an authentication provider (SSO)
authentication_edit:
provider: "Provider:"
it_is_required_to_set_the_matching_between_User.uid_and_the_API_to_add_this_provider: "It is required to set the matching between User.uid and the API to add this provider."
provider_successfully_updated: "Provider successfully updated."
an_error_occurred_unable_to_update_the_provider: "An error occurred: unable to update the provider."
#statistics tables
statistics:
statistics: "Statistics"

View File

@ -247,57 +247,6 @@ en:
group_is_required: "Group is required."
trainings: "Trainings"
tags: "Tags"
#partial form to edit/create an authentication provider (SSO)
authentication:
name: "Name"
provider_name_is_required: "Provider name is required."
authentication_type: "Authentication type"
local_database: "Local database"
o_auth2: "OAuth 2.0"
authentication_type_is_required: "Authentication type is required."
data_mapping: "Data mapping"
expected_data_type: "Expected data type"
TYPE_expected: "{TYPE} expected"
input_format: "Input format"
mappings: "Mappings"
mapping_from: "From"
mapping_to: "To"
true_value: "True value"
false_value: "False value"
date_format: "Date format"
save: "Save"
types:
integer: "integer"
string: "string"
text: "text"
date: "date"
boolean: "boolean"
#edition/creation form of an OAuth2 authentication provider
oauth2:
common_url: "Server root URL"
common_url_is_required: "Common URL is required."
provided_url_is_not_a_valid_url: "Provided URL is not a valid URL."
authorization_endpoint: "Authorization endpoint"
oauth2_authorization_endpoint_is_required: "OAuth 2.0 authorization endpoint is required."
provided_endpoint_is_not_valid: "Provided endpoint is not valid."
token_acquisition_endpoint: "Token acquisition endpoint"
oauth2_token_acquisition_endpoint_is_required: "OAuth 2.0 token acquisition endpoint is required."
profil_edition_url: "Profil edition URL"
profile_edition_url_is_required: "Profile edition URL is required."
client_identifier: "Client identifier"
oauth2_client_identifier_is_required: "OAuth 2.0 client identifier is required."
obtain_it_when_registering_with_your_provider: "Obtain it when registering with your provider."
client_secret: "Client secret"
oauth2_client_secret_is_required: "OAuth 2.0 client secret is required."
scopes: "Scopes"
define_the_fields_mapping: "Define the fields mapping"
add_a_match: "Add a match"
model: "Model"
field: "Field"
api_endpoint_url: "API endpoint URL"
api_type: "API type"
api_fields: "API fields"
api_field_help_html: '<a href="https://jsonpath.com/" target="_blank">JsonPath</a> syntax is supported.<br> If many fields are selected, the first one will be used.<br> Example: $.data[*].name"'
#machine/training slot modification modal
confirm_modify_slot_modal:
change_the_slot: "Change the slot"

View File

@ -61,6 +61,10 @@ en:
your_authentication_code_is_not_valid: "Your authentication code is not valid."
current_authentication_method_no_code: "The current authentication method does not require any migration code"
requested_account_does_not_exists: "The requested account does not exist"
#SSO external authentication
authentication_providers:
local_database_provider_already_exists: 'A "Local Database" provider already exists. Unable to create another.'
matching_between_User_uid_and_API_required: "It is required to set the matching between User.uid and the API to add this provider."
#PDF invoices generation
invoices:
refund_invoice_reference: "Refund invoice reference: %{REF}"