diff --git a/app/frontend/src/javascript/components/authentication-provider/boolean-mapping-form.tsx b/app/frontend/src/javascript/components/authentication-provider/boolean-mapping-form.tsx index deb8f03d9..3ee843db2 100644 --- a/app/frontend/src/javascript/components/authentication-provider/boolean-mapping-form.tsx +++ b/app/frontend/src/javascript/components/authentication-provider/boolean-mapping-form.tsx @@ -9,6 +9,9 @@ export interface BooleanMappingFormProps { fieldMappingId: number, } +/** + * Partial form to map an internal boolean field to an external API providing a string value. + */ export const BooleanMappingForm = ({ register, fieldMappingId }: BooleanMappingFormProps) => { const { t } = useTranslation('shared'); diff --git a/app/frontend/src/javascript/components/authentication-provider/data-mapping-form.tsx b/app/frontend/src/javascript/components/authentication-provider/data-mapping-form.tsx index eb74942f0..cdb1bd7da 100644 --- a/app/frontend/src/javascript/components/authentication-provider/data-mapping-form.tsx +++ b/app/frontend/src/javascript/components/authentication-provider/data-mapping-form.tsx @@ -17,6 +17,9 @@ export interface DataMappingFormProps { 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 = ({ register, control }: DataMappingFormProps) => { const { t } = useTranslation('shared'); const [dataMapping, setDataMapping] = useState(null); @@ -91,11 +94,13 @@ export const DataMappingForm =

{t('app.shared.oauth2.define_the_fields_mapping')}

- } - onClick={() => append({})}> - {t('app.shared.oauth2.add_a_match')} - +
+ } + onClick={() => append({})}> + {t('app.shared.oauth2.add_a_match')} + +
{fields.map((item, index) => (
@@ -128,7 +133,7 @@ export const DataMappingForm =
- } onClick={toggleTypeMappingModal} disabled={getField(output, index) === undefined} /> + } onClick={toggleTypeMappingModal} disabled={getField(output, index) === undefined} tooltip={t('app.shared.authentication.data_mapping')} /> } onClick={() => remove(index)} className="delete-button" /> { fieldMappingId: number, } +/** + * Partial form for mapping an internal date field to an external API. + */ export const DateMappingForm = ({ control, fieldMappingId }: DateMappingFormProps) => { const { t } = useTranslation('shared'); diff --git a/app/frontend/src/javascript/components/authentication-provider/integer-mapping-form.tsx b/app/frontend/src/javascript/components/authentication-provider/integer-mapping-form.tsx index 5c01f2044..e1a071aa1 100644 --- a/app/frontend/src/javascript/components/authentication-provider/integer-mapping-form.tsx +++ b/app/frontend/src/javascript/components/authentication-provider/integer-mapping-form.tsx @@ -12,6 +12,9 @@ export interface IntegerMappingFormProps fieldMappingId: number, } +/** + * Partial for to map an internal integer field to an external API providing a string value. + */ export const IntegerMappingForm = ({ register, control, fieldMappingId }: IntegerMappingFormProps) => { const { t } = useTranslation('shared'); @@ -20,9 +23,11 @@ export const IntegerMappingForm =

{t('app.shared.authentication.mappings')}

- } - onClick={() => append({})} /> +
+ } + onClick={() => append({})} /> +
{fields.map((item, index) => (
diff --git a/app/frontend/src/javascript/components/authentication-provider/provider-form.tsx b/app/frontend/src/javascript/components/authentication-provider/provider-form.tsx index 17a88ef3e..4fe9da905 100644 --- a/app/frontend/src/javascript/components/authentication-provider/provider-form.tsx +++ b/app/frontend/src/javascript/components/authentication-provider/provider-form.tsx @@ -9,6 +9,7 @@ import { useTranslation } from 'react-i18next'; import { FormSelect } from '../form/form-select'; import { Oauth2Form } from './oauth2-form'; import { DataMappingForm } from './data-mapping-form'; +import { FabButton } from '../base/fab-button'; declare const Application: IApplication; @@ -79,7 +80,9 @@ export const ProviderForm: React.FC = ({ action, provider, on rules={{ required: true }} /> {providableType === 'OAuth2Provider' && } {providableType && providableType !== 'DatabaseProvider' && } - +
+ {t('app.shared.authentication.save')} +
); }; diff --git a/app/frontend/src/javascript/components/authentication-provider/string-mapping-form.tsx b/app/frontend/src/javascript/components/authentication-provider/string-mapping-form.tsx index 5002188cb..48a2d9b8c 100644 --- a/app/frontend/src/javascript/components/authentication-provider/string-mapping-form.tsx +++ b/app/frontend/src/javascript/components/authentication-provider/string-mapping-form.tsx @@ -12,6 +12,9 @@ export interface StringMappingFormProps { fieldMappingId: number, } +/** + * Partial form to map an internal string field to an external API. + */ export const StringMappingForm = ({ register, control, fieldMappingId }: StringMappingFormProps) => { const { t } = useTranslation('shared'); @@ -20,9 +23,11 @@ export const StringMappingForm =

{t('app.shared.authentication.mappings')}

- } - onClick={() => append({})} /> +
+ } + onClick={() => append({})} /> +
{fields.map((item, index) => (
diff --git a/app/frontend/src/javascript/components/authentication-provider/type-mapping-modal.tsx b/app/frontend/src/javascript/components/authentication-provider/type-mapping-modal.tsx index c1713b843..75f51294c 100644 --- a/app/frontend/src/javascript/components/authentication-provider/type-mapping-modal.tsx +++ b/app/frontend/src/javascript/components/authentication-provider/type-mapping-modal.tsx @@ -21,12 +21,19 @@ interface TypeMappingModalProps { fieldMappingId: number, } +/** + * Modal dialog to display the expected type for the current data field. + * Also allows to map the incoming data (from the authentication provider API) to the expected type/data. + * + * This component is intended to be used in a react-hook-form context. + */ export const TypeMappingModal = ({ model, field, type, isOpen, toggleModal, register, control, fieldMappingId }:TypeMappingModalProps) => { const { t } = useTranslation('shared'); return ( } onConfirm={toggleModal}> diff --git a/app/frontend/src/javascript/components/base/fab-button.tsx b/app/frontend/src/javascript/components/base/fab-button.tsx index f200d971b..33951ff8a 100644 --- a/app/frontend/src/javascript/components/base/fab-button.tsx +++ b/app/frontend/src/javascript/components/base/fab-button.tsx @@ -7,12 +7,13 @@ interface FabButtonProps { disabled?: boolean, type?: 'submit' | 'reset' | 'button', form?: string, + tooltip?: string, } /** * This component is a template for a clickable button that wraps the application style */ -export const FabButton: React.FC = ({ onClick, icon, className, disabled, type, form, children }) => { +export const FabButton: React.FC = ({ onClick, icon, className, disabled, type, form, tooltip, children }) => { /** * Check if the current component was provided an icon to display */ @@ -37,7 +38,7 @@ export const FabButton: React.FC = ({ onClick, icon, className, }; return ( - diff --git a/app/frontend/src/stylesheets/application.scss b/app/frontend/src/stylesheets/application.scss index ac98a5a0e..51c389d84 100644 --- a/app/frontend/src/stylesheets/application.scss +++ b/app/frontend/src/stylesheets/application.scss @@ -17,6 +17,8 @@ @import "modules/authentication-provider/data-mapping-form"; @import "modules/authentication-provider/array-mapping-form"; +@import "modules/authentication-provider/provider-form"; +@import "modules/authentication-provider/type-mapping-modal"; @import "modules/base/fab-alert"; @import "modules/base/fab-button"; @import "modules/base/fab-input"; diff --git a/app/frontend/src/stylesheets/modules/authentication-provider/array-mapping-form.scss b/app/frontend/src/stylesheets/modules/authentication-provider/array-mapping-form.scss index 63106d495..3779b8e0a 100644 --- a/app/frontend/src/stylesheets/modules/authentication-provider/array-mapping-form.scss +++ b/app/frontend/src/stylesheets/modules/authentication-provider/array-mapping-form.scss @@ -1,9 +1,14 @@ .array-mapping-form { + .mapping-actions { + display: flex; + flex-direction: row-reverse; + margin-right: 1rem; + } .mapping-item { - margin: 1rem; - border-left: 4px solid var(--gray-soft-dark); - border-radius: 4px; - padding-left: 1em; + margin: 1rem 1rem 2rem; + border: 1px solid var(--gray-soft-dark); + border-radius: 8px; + padding: 1em; display: flex; flex-direction: row; align-items: center; diff --git a/app/frontend/src/stylesheets/modules/authentication-provider/data-mapping-form.scss b/app/frontend/src/stylesheets/modules/authentication-provider/data-mapping-form.scss index 2d2f766b2..c1166ed03 100644 --- a/app/frontend/src/stylesheets/modules/authentication-provider/data-mapping-form.scss +++ b/app/frontend/src/stylesheets/modules/authentication-provider/data-mapping-form.scss @@ -1,6 +1,9 @@ .data-mapping-form { + .mapping-item .inputs .form-item { + margin-left: 20px; + } .local-data, - .remote-data{ + .remote-data { display: flex; flex-direction: row; } diff --git a/app/frontend/src/stylesheets/modules/authentication-provider/provider-form.scss b/app/frontend/src/stylesheets/modules/authentication-provider/provider-form.scss new file mode 100644 index 000000000..8e410a206 --- /dev/null +++ b/app/frontend/src/stylesheets/modules/authentication-provider/provider-form.scss @@ -0,0 +1,20 @@ + +.provider-form { + .main-actions { + display: flex; + flex-direction: row-reverse; + + .submit-button { + margin-top: 2em; + border-color: var(--information-light); + background-color: var(--information); + color: white; + + &:hover { + border-color: var(--information); + background-color: var(--information-dark); + color: white; + } + } + } +} diff --git a/app/frontend/src/stylesheets/modules/authentication-provider/type-mapping-modal.scss b/app/frontend/src/stylesheets/modules/authentication-provider/type-mapping-modal.scss new file mode 100644 index 000000000..a5f0a1613 --- /dev/null +++ b/app/frontend/src/stylesheets/modules/authentication-provider/type-mapping-modal.scss @@ -0,0 +1,15 @@ +.type-mapping-modal { + .fab-modal-footer { + .modal-btn--confirm { + border-color: var(--information-light); + background-color: var(--information); + color: white; + + &:hover { + border-color: var(--information); + background-color: var(--information-dark); + color: white; + } + } + } +} diff --git a/app/frontend/templates/admin/authentications/new.html b/app/frontend/templates/admin/authentications/new.html index 8f082b5a5..9a55d8e31 100644 --- a/app/frontend/templates/admin/authentications/new.html +++ b/app/frontend/templates/admin/authentications/new.html @@ -31,23 +31,14 @@
-
-
-
+
+
- + - - -
- - - -
- +
+
diff --git a/config/locales/app.shared.en.yml b/config/locales/app.shared.en.yml index b2d4759cc..ffa5f4e7c 100644 --- a/config/locales/app.shared.en.yml +++ b/config/locales/app.shared.en.yml @@ -265,6 +265,7 @@ en: true_value: "True value" false_value: "False value" date_format: "Date format" + save: "Save" types: integer: "integer" string: "string"