Skip to content

Commit

Permalink
Merge pull request #37 from open-formulieren/feature/2-cosign-types
Browse files Browse the repository at this point in the history
Implement types for cosign components
  • Loading branch information
sergei-maertens authored Dec 7, 2023
2 parents 56d6edf + 1c40152 commit 5c61e27
Show file tree
Hide file tree
Showing 5 changed files with 256 additions and 1 deletion.
66 changes: 66 additions & 0 deletions src/formio/components/cosign.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import {OFExtensions, StrictComponentSchema} from '..';
import {EmailInputSchema} from './email';

type TranslatableKeys = 'label' | 'description';

/**
* We don't currently support these properties - they get added in by base types, so we
* need to strip them out again.
*/
type KeysToOmit =
| 'hideLabel'
| 'placeholder'
| 'multiple'
| 'clearOnHide'
| 'conditional'
| 'errors'
| 'disabled'
| 'validateOn'
| 'tooltip';

export type CosignV1InputSchema = StrictComponentSchema<never> &
Pick<OFExtensions<TranslatableKeys>, 'openForms'>;

/**
* The legacy Cosign component type, otherwise known as 'CosignOld'.
*
* The component does not actually provide any input data, it mostly functions as a
* marker in the form that cosigning is expected, hence the `never` value type. In the
* UI, it displays a button to start an (additional) login session to authenticate the
* cosigner and requires them to be physically in the same space.
*
* @group Form.io components
* @category Concrete types
*
* @deprecated
*
* The in-band cosign flow is problematic with existing DigiD/eHerkenning sessions. It
* is currently not scheduled for removal, but we recommend using the V2 variant for
* better UX.
*/
export interface CosignV1ComponentSchema extends Omit<CosignV1InputSchema, KeysToOmit> {
type: 'coSign';
authPlugin: string; // plugin identifiers in the backend are dynamic
}

type V2KeysToOmit = 'hideLabel' | 'disabled' | 'placeholder' | 'registration';

/**
* The cosign component type, otherwise known as 'Cosign'.
*
* This is a custom component sharing most of the functionality with the email input
* component type - it collects the e-mail address of any/a cosigner so that they
* receive a notification they're expected to cosign. The actual cosigning happens
* out-of-band. This component *does* take form data input, as opposed to the V1
* component implementation.
*
* @group Form.io components
* @category Concrete types
*/
export interface CosignV2ComponentSchema extends Omit<EmailInputSchema, V2KeysToOmit> {
type: 'cosign';
validateOn: 'blur';
authPlugin: string; // plugin identifiers in the backend are dynamic
defaultValue?: string; // no multiple support, so must always be a single string
autocomplete?: string;
}
1 change: 1 addition & 0 deletions src/formio/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export * from './addressNL';
export * from './map';
export * from './editgrid';
export * from './signature';
export * from './cosign';

// Layout components
export * from './content';
Expand Down
7 changes: 6 additions & 1 deletion src/formio/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import {
CheckboxComponentSchema,
ColumnsComponentSchema,
ContentComponentSchema,
CosignV1ComponentSchema,
CosignV2ComponentSchema,
CurrencyComponentSchema,
DateComponentSchema,
DateTimeComponentSchema,
Expand Down Expand Up @@ -74,12 +76,15 @@ export type AnyComponentSchema =
| AddressNLComponentSchema
| NpFamilyMembersComponentSchema
| SignatureComponentSchema
| CosignV2ComponentSchema
| MapComponentSchema
| EditGridComponentSchema
// layout
| ContentComponentSchema
| ColumnsComponentSchema
| FieldsetComponentSchema;
| FieldsetComponentSchema
// deprecated
| CosignV1ComponentSchema;

/**
* Convenience type alias for all supported concrete component schema types.
Expand Down
58 changes: 58 additions & 0 deletions test-d/formio/components/cosign-v1.test-d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import {expectAssignable, expectNotAssignable} from 'tsd';

import {CosignV1ComponentSchema} from '../../../lib/';

// minimal CoSign component schema
expectAssignable<CosignV1ComponentSchema>({
id: 'yejak',
type: 'coSign',
key: 'someCoSign',
label: 'Some cosign',
authPlugin: 'digid',
});

// full, correct schema
expectAssignable<CosignV1ComponentSchema>({
id: 'yejak',
type: 'coSign',
key: 'someCoSign',
// basic tab in builder form
label: 'Some cosign',
description: 'A description',
authPlugin: 'oidc-digid',
hidden: false,
// translations tab in builder form
openForms: {
translations: {
nl: {
label: 'foo',
description: 'bar',
},
},
},
});

// different component type
expectNotAssignable<CosignV1ComponentSchema>({
type: 'fieldset' as const,
});

// using unsupported properties
expectNotAssignable<CosignV1ComponentSchema>({
id: 'yejak',
type: 'CoSign' as const,
key: 'someCoSign',
label: 'Some cosign',
authPlugin: 'digid',
hideLabel: true,
});

// multiple is not supported
expectNotAssignable<CosignV1ComponentSchema>({
id: 'yejak',
type: 'CoSign' as const,
key: 'someCoSign',
label: 'Some cosign',
authPlugin: 'digid',
multiple: true as boolean,
});
125 changes: 125 additions & 0 deletions test-d/formio/components/cosign-v2.test-d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
import {expectAssignable, expectNotAssignable} from 'tsd';

import {CosignV2ComponentSchema} from '../../../lib/';

// minimal cosign component schema
expectAssignable<CosignV2ComponentSchema>({
id: 'yejak',
type: 'cosign',
validateOn: 'blur',
key: 'someCoSign',
label: 'Some cosign',
authPlugin: 'digid',
});

// full, correct schema
expectAssignable<CosignV2ComponentSchema>({
id: 'yejak',
type: 'cosign',
validateOn: 'blur',
// basic tab in builder form
label: 'Some cosign',
key: 'someCoSign',
description: 'A description',
tooltip: 'A tooltip',
authPlugin: 'oidc-digid',
showInSummary: true,
showInEmail: false,
showInPDF: true,
hidden: false,
clearOnHide: true,
isSensitiveData: true,
defaultValue: '',
autocomplete: 'email',
// advanced tab in builder form
conditional: {
show: undefined,
when: undefined,
eq: undefined,
},
// validation tab in builder form
validate: {
required: false,
plugins: undefined,
},
translatedErrors: {
nl: {
required: 'Je moet een waarde opgeven!!!',
},
},
errors: {
// translatedErrors is converted into errors by the backend
required: 'Je moet een waarde opgeven!!!',
},
// translations tab in builder form
openForms: {
translations: {
nl: {
label: 'foo',
description: 'bar',
tooltip: 'baz',
},
},
},
});

// different component type
expectNotAssignable<CosignV2ComponentSchema>({
type: 'fieldset' as const,
});

// using unsupported properties
expectNotAssignable<CosignV2ComponentSchema>({
id: 'yejak',
type: 'cosign' as const,
validateOn: 'blur' as const,
key: 'someCoSign',
label: 'Some cosign',
authPlugin: 'digid',
hideLabel: true,
});

// multiple is not supported
expectNotAssignable<CosignV2ComponentSchema>({
id: 'yejak',
type: 'cosign' as const,
validateOn: 'blur' as const,
key: 'someCoSign',
label: 'Some cosign',
authPlugin: 'digid',
multiple: true as boolean,
});
expectNotAssignable<CosignV2ComponentSchema>({
id: 'yejak',
type: 'cosign' as const,
validateOn: 'blur' as const,
key: 'someCoSign',
label: 'Some cosign',
authPlugin: 'digid',
defaultValue: [],
});

// while it shares functionality with email, we should not be able to use all
// email extensions
expectNotAssignable<CosignV2ComponentSchema>({
id: 'yejak',
type: 'cosign' as const,
validateOn: 'blur' as const,
key: 'someCoSign',
label: 'Some cosign',
authPlugin: 'digid',
confirmationRecipient: true,
});

// registration attributes are not supported
expectNotAssignable<CosignV2ComponentSchema>({
id: 'yejak',
type: 'cosign' as const,
validateOn: 'blur' as const,
key: 'someCoSign',
label: 'Some cosign',
authPlugin: 'digid',
registration: {
attribute: 'foo',
},
});

0 comments on commit 5c61e27

Please sign in to comment.