Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: QR code scanner #1

Open
wants to merge 36 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
f56735b
chore: qr code related changes
tahmidrahman-dsi Nov 13, 2024
ec66906
fix: handle optional values
tahmidrahman-dsi Nov 13, 2024
19f93e0
chore: add qr scanner form field
tahmidrahman-dsi Nov 14, 2024
be3e321
chore: some more changes
tahmidrahman-dsi Nov 14, 2024
036b0f0
feat: qr code variants
tahmidrahman-dsi Nov 19, 2024
3fd40ef
fix: add form configuration changes
tahmidrahman-dsi Nov 19, 2024
64bf134
fix: add missing import
tahmidrahman-dsi Dec 11, 2024
385bcfe
chore(WIP): set an example of how id reader field can be incorporated
tahmidrahman-dsi Dec 18, 2024
43a1e5f
chore: add translations
tahmidrahman-dsi Dec 24, 2024
6b79627
fix: conditionals
tahmidrahman-dsi Dec 24, 2024
b8048be
Merge branch 'develop' of github.com:opencrvs/opencrvs-countryconfig-…
tahmidrahman-dsi Jan 6, 2025
be7b103
Merge branch 'develop' of github.com:opencrvs/opencrvs-countryconfig …
tahmidrahman-dsi Jan 6, 2025
3ffe6b3
fix: update yarn-lock
tahmidrahman-dsi Jan 6, 2025
13477e4
Merge pull request #3 from opencrvs/qr-reader-with-latest-develop
tahmidrahman-dsi Jan 6, 2025
d3a6bd6
chore(wip): changes
tahmidrahman-dsi Jan 6, 2025
89ed652
fix: update form config defining pending logic
tahmidrahman-dsi Jan 7, 2025
6829114
Merge branch 'develop' of github.com:opencrvs/opencrvs-countryconfig-…
tahmidrahman-dsi Jan 7, 2025
e5d3432
refactor: rename REDIRECT to LINK_BUTTON
tahmidrahman-dsi Jan 7, 2025
a67dde2
chore: implement e-signet links
tahmidrahman-dsi Jan 8, 2025
d15f9ac
fix: remove unused custom field
tahmidrahman-dsi Jan 9, 2025
f8996f4
fix: improve naming
tahmidrahman-dsi Jan 9, 2025
cb8d286
chore: add hidden form field type
tahmidrahman-dsi Jan 10, 2025
0fb71a3
Adjust field definitions and add env var for server package
euanmillar Jan 10, 2025
b4322f4
Merge branch 'feat/ocrvs-7978/qr-reader' of github.com:opencrvs/openc…
euanmillar Jan 10, 2025
f6de859
bump package number
euanmillar Jan 10, 2025
974535c
fix: typo
tahmidrahman-dsi Jan 13, 2025
7cb991d
Ensure redirectUri is populated
euanmillar Jan 13, 2025
a44b3c9
chore: update mosip images tags
tahmidrahman-dsi Jan 14, 2025
7ba86ff
refactor: rename variable esignet auth url
tahmidrahman-dsi Jan 14, 2025
c5469a9
fix: env vars
tahmidrahman-dsi Jan 14, 2025
352a962
chore: upgrade @opencrvs/mosip
tahmidrahman-dsi Jan 15, 2025
a36bebc
chore: upgrade mosip dep version
tahmidrahman-dsi Jan 16, 2025
36f61aa
chore: update form field condition
tahmidrahman-dsi Jan 16, 2025
f1dc222
chore: update mosip dependency
tahmidrahman-dsi Jan 16, 2025
f381fe4
Merge branch 'develop' into feat/ocrvs-7978/qr-reader
tahmidrahman-dsi Jan 16, 2025
e810071
Merge branch 'develop' into feat/ocrvs-7978/qr-reader
tahmidrahman-dsi Jan 20, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
115 changes: 115 additions & 0 deletions src/form/birth/custom-fields.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
import { getCustomFieldMapping } from '@countryconfig/utils/mapping/field-mapping-utils'
import { formMessageDescriptors } from '../common/messages'
import { Conditional, SerializedFormField } from '../types/types'
import { genderOptions } from '../common/select-options'
import { MessageDescriptor } from 'react-intl'

/**
*
* @param event
* @param sectionId
* @returns hidden field to store QR scanned data
*/
export function getIDReaderField(
event: string,
sectionId: string,
conditionals: Conditional[],
label: MessageDescriptor
): SerializedFormField {
const fieldName: string = 'informantIDReadeer'
const fieldId: string = `${event}.${sectionId}.${sectionId}-view-group.${fieldName}`
return {
name: fieldName,
customQuestionMappingId: fieldId,
custom: true,
required: false,
type: 'ID_READER',
label,
initialValue: '',
validator: [],
mapping: getCustomFieldMapping(fieldId),
placeholder: formMessageDescriptors.formSelectPlaceholder,
conditionals,
dividerLabel: {
id: 'id.divider.label',
defaultMessage: 'Or'
},
manualInputInstructionLabel: {
id: 'id.manualInputInstruction.label',
defaultMessage: 'Complete fields below'
},
readers: [
{
type: 'QR',
labels: {
button: {
id: 'id.qr.button.label',
defaultMessage: 'Scan ID QR code'
},
scannerDialogSupportingCopy: {
id: 'id.qr.scanner.supportingCopy',
defaultMessage:
"Place the Notifier's ID card in front of the camera."
},
tutorial: {
cameraCleanliness: {
id: 'id.qr.tutorial.cameraCleanliness',
defaultMessage: 'Ensure your camera is clean and functional.'
},
distance: {
id: 'id.qr.tutorial.distance',
defaultMessage:
'Hold the device steadily 6-12 inches away from the QR code.'
},
lightBalance: {
id: 'id.qr.tutorial.lightBalance',
defaultMessage:
'Ensure the QR code is well-lit and not damaged or blurry.'
}
}
}
},
{
name: 'redirect',
validator: [],
type: 'REDIRECT',
label: {
id: 'redirect.id',
defaultMessage: 'E-signet'
},
options: {
url: 'test',
callback: {
params: {
authorized: 'true'
},
trigger: 'someHTTPField'
}
}
}
]
}
}

/** To bypass config validation */
export function getGenderCustom(
event: string,
sectionId: string,
initialValue: { dependsOn: string[]; expression: string } | string = ''
) {
const fieldName: string = 'gender'
const fieldId: string = `${event}.${sectionId}.${sectionId}-view-group.${fieldName}`
return {
name: fieldName,
type: 'SELECT_WITH_OPTIONS',
customQuestionMappingId: fieldId,
custom: true,
label: formMessageDescriptors.sex,
required: false,
initialValue,
validator: [],
placeholder: formMessageDescriptors.formSelectPlaceholder,
mapping: getCustomFieldMapping(fieldId),
options: genderOptions
} satisfies SerializedFormField
}
55 changes: 52 additions & 3 deletions src/form/birth/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ import { getSectionMapping } from '@countryconfig/utils/mapping/section/birth/ma
import { getCommonSectionMapping } from '@countryconfig/utils/mapping/field-mapping-utils'
import { getReasonForLateRegistration } from '../custom-fields'
import { getIDNumberFields, getIDType } from '../custom-fields'
import { getGenderCustom, getIDReaderField } from './custom-fields'
// import { createCustomFieldExample } from '../custom-fields'

// ======================= FORM CONFIGURATION =======================
Expand Down Expand Up @@ -219,20 +220,68 @@ export const birthForm: ISerializedForm = {
fields: [
informantType, // Required field.
otherInformantType(Event.Birth), // Required field.
getIDReaderField(

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tahmidrahman-dsi I thought that we would apply these functions using functions from here: opencrvs/mosip#26. Do we have to merge that one in first?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes @euanmillar eventually we will import these from @opencrvs/mosip. please feel free to merge if the changes look okay. After the changes are published, I can import these functions here

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tahmidrahman-dsi I spoke with Pyry, and we are going to publish multiple versions so can you close this PR and instead copy over the appropriate form changes to https://github.com/opencrvs/mosip then we can merge in and use the form functions properly in this repo. Please note the latest WIP changes I merged in that repo. Will set up a call with you to discuss how to send the draft id, e.g. $. from the REDIRECT button. Can you apply any updates to the functions I created with Pathum as I gather you have renamed it LINK_BUTTON now if thats correct?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes that's correct. The update should be in mosip repo as well

'birth',
'informant',
informantFirstNameConditionals
.concat(hideIfInformantMotherOrFather)
.concat([
{
action: 'disable',
expression: 'Boolean($form.qrCode1)'
}
]),
{
id: 'form.field.label.qrScanner.0',
defaultMessage: 'Scan QR code with Scanner 1'
}
),
{
name: 'someHTTPField',
type: 'HTTP',
custom: true,
label: {
id: 'messages.empty',
defaultMessage: ' '
},
validator: [],
options: {
url: 'someRoute',
headers: {
'Content-type': 'application/json'
},
method: 'GET'
}
},
getFirstNameField(
'informantNameInEnglish',
informantFirstNameConditionals.concat(
hideIfInformantMotherOrFather
),
certificateHandlebars.informantFirstName
), // Required field.
certificateHandlebars.informantFirstName,
{
dependsOn: ['qrCode1', 'qrCode2'],
expression:
'$form.qrCode1?.firstName?.[0].value || $form.qrCode2?.firstName?.[0].value'
}
), // Required field. In Farajaland, we have built the option to integrate with MOSIP. So we have different conditionals for each name to check MOSIP responses. You could always refactor firstNamesEng for a basic setup
getFamilyNameField(
'informantNameInEnglish',
informantFamilyNameConditionals.concat(
hideIfInformantMotherOrFather
),
certificateHandlebars.informantFamilyName
certificateHandlebars.informantFamilyName,
{
dependsOn: ['qrCode1', 'qrCode2'],
expression:
'$form.qrCode1?.lastName?.[0].value || $form.qrCode2?.lastName?.[0].value'
}
), // Required field.
getGenderCustom('birth', 'informant', {
dependsOn: ['qrCode1', 'qrCode2'],
expression:
'$form.qrCode1?.gender?.[0].value?.toLowerCase() || $form.qrCode2?.gender?.[0].value?.toLowerCase()'
}),
getBirthDate(
'informantBirthDate',
informantBirthDateConditionals.concat(
Expand Down
10 changes: 6 additions & 4 deletions src/form/common/common-required-fields.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@ export const getGender = (certificateHandlebar: string) =>
export const getFamilyNameField = (
previewGroup: string,
conditionals: Conditional[],
certificateHandlebar: string
certificateHandlebar: string,
initialValue: string | { dependsOn: string[]; expression: string } = ''
) =>
({
name: 'familyNameEng', // A field with this name MUST exist
Expand All @@ -58,7 +59,7 @@ export const getFamilyNameField = (
label: formMessageDescriptors.familyName,
maxLength: 32,
required: true,
initialValue: '',
initialValue,
validator: [
{
operation: 'englishOnlyNameFormat'
Expand All @@ -70,7 +71,8 @@ export const getFamilyNameField = (
export const getFirstNameField = (
previewGroup: string,
conditionals: Conditional[],
certificateHandlebar: string
certificateHandlebar: string,
initialValue: string | { dependsOn: string[]; expression: string } = ''
) =>
({
name: 'firstNamesEng', // A field with this name MUST exist
Expand All @@ -84,7 +86,7 @@ export const getFirstNameField = (
conditionals,
maxLength: 32,
required: true,
initialValue: '',
initialValue,
validator: [
{
operation: 'englishOnlyNameFormat'
Expand Down
3 changes: 2 additions & 1 deletion src/form/death/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,8 @@
spouseBirthDateConditionals,
spouseFamilyNameConditionals,
spouseFirstNameConditionals,
hideIfInformantSpouse
hideIfInformantSpouse,
hideIfDeceasedAddressNotAvailable

Check failure on line 65 in src/form/death/index.ts

View workflow job for this annotation

GitHub Actions / test

Module '"../common/default-validation-conditionals"' has no exported member 'hideIfDeceasedAddressNotAvailable'.
} from '../common/default-validation-conditionals'
import {
documentsSection,
Expand Down
54 changes: 54 additions & 0 deletions src/form/types/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ export const TEL = 'TEL'
export const NUMBER = 'NUMBER'
export const BIG_NUMBER = 'BIG_NUMBER'
export const RADIO_GROUP = 'RADIO_GROUP'
export const HIDDEN = 'HIDDEN'
export const INFORMATIVE_RADIO_GROUP = 'INFORMATIVE_RADIO_GROUP'
export const CHECKBOX_GROUP = 'CHECKBOX_GROUP'
export const CHECKBOX = 'CHECKBOX'
Expand Down Expand Up @@ -142,6 +143,9 @@ export const NID_VERIFICATION_BUTTON = 'NID_VERIFICATION_BUTTON'
export const DIVIDER = 'DIVIDER'
export const HEADING3 = 'HEADING3'
export const SIGNATURE = 'SIGNATURE'
export const REDIRECT = 'REDIRECT'
export const ID_READER = 'ID_READER'
export const HTTP = 'HTTP'
euanmillar marked this conversation as resolved.
Show resolved Hide resolved

export enum RadioSize {
LARGE = 'large',
Expand Down Expand Up @@ -491,6 +495,48 @@ export interface ISignatureFormField extends IFormFieldBase {
)[]
}

export interface IHttpFormField extends IFormFieldBase {
euanmillar marked this conversation as resolved.
Show resolved Hide resolved
type: typeof HTTP
options: {
url: string
method?: string
headers: Record<string, string>
body?: Record<string, any>
}
}

export interface IRedirectFormField extends IFormFieldBase {
type: typeof REDIRECT
options: {
url: string
callback: {
trigger: string
params: Record<string, string>
}
}
}

export interface QRReaderType {
type: 'QR'
labels: {
button: MessageDescriptor
scannerDialogSupportingCopy: MessageDescriptor
tutorial: {
cameraCleanliness: MessageDescriptor
distance: MessageDescriptor
lightBalance: MessageDescriptor
}
}
}

type ReaderType = QRReaderType | IRedirectFormField
export interface IIDReaderFormField extends IFormFieldBase {
type: typeof ID_READER
dividerLabel: MessageDescriptor
manualInputInstructionLabel: MessageDescriptor
readers: [ReaderType, ...ReaderType[]]
}

export type IFormField =
| ITextFormField
| ITelFormField
Expand Down Expand Up @@ -524,6 +570,10 @@ export type IFormField =
| IDividerField
| IHeading3Field
| ISignatureFormField
| IHiddenFormField
| IIDReaderFormField
| IRedirectFormField
| IHttpFormField

export interface SelectComponentOption {
value: string
Expand Down Expand Up @@ -739,6 +789,10 @@ export type SerializedFormField = UnionOmit<
mapping?: IFormFieldMapping
}

interface IHiddenFormField extends IFormFieldBase {
type: typeof HIDDEN
}

export type IFormSectionQueryMapFunction = (
transFormedData: IFormData,
queryData: any,
Expand Down
Loading