diff --git a/CHANGELOG.md b/CHANGELOG.md index 5ed33b227..dc5917500 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -46,7 +46,15 @@ INSERT CSV ROWS IN ENGLISH ONLY - TBC -## 1.6.0 Release candidate +## 1.6.1 (TBD) + +### Bug fixes + +- We make sure that the automatic cleanup job only runs before deployment (instead of cron schedule cleanup). +- Previously it was possible MongoDB replica set and users were left randomly uninitialised after a deployment. MongoDB initialisation container now retries on failure. +- On some machines 'file' utility was not preinstalled causing provision to fail. We now install the utility if it doesn't exist. + +## 1.6.0 ### Breaking changes @@ -93,6 +101,7 @@ INSERT CSV ROWS IN ENGLISH ONLY 5. 'PHONE_NUMBER', 6. 'EMAIL' - Updated `allowedFileFormats` in signature fields to use MIME types (`image/png`, `image/jpg`, `image/jpeg`, `image/svg`) instead of simple file extensions. If you are already using the `allowedFileFormats` field in your implementation, please ensure to update the format accordingly. +- The details exists conditionals for the various sections i.e. father, mother, spouse has to use the `values.detailsExist` property instead of accessing it from `draftData.[sectionName].detailsExists`. This is due to the fact that the draftData is not populated until any changes have been made to any of the fields in the current section. ### New features @@ -127,6 +136,7 @@ INSERT CSV ROWS IN ENGLISH ONLY - Github pipeline dedicated for reading secrets and variables from other environments now checks if GH_TOKEN is still valid before attempting other operations - Remove unnecessary UI dividers that add in various sections of the declaration forms(e.g the Death, Birth and Marriage forms) [#244](https://github.com/opencrvs/opencrvs-countryconfig/pull/244) - Update template transformer for fields `informantType` and `otherInformantType` that fixes the bug of unavailability of these template fields [#5952](https://github.com/opencrvs/opencrvs-countryconfig/pull/5952) +- Fixed missing InitialValue property to set initial values based on an expression ## 1.5.2 (https://github.com/opencrvs/opencrvs-countryconfig/compare/v1.5.1...v1.5.2) diff --git a/infrastructure/docker-compose.deploy.yml b/infrastructure/docker-compose.deploy.yml index 7d7c133bc..f561e8909 100644 --- a/infrastructure/docker-compose.deploy.yml +++ b/infrastructure/docker-compose.deploy.yml @@ -243,6 +243,7 @@ services: - OPENHIM_MONGODB_PASSWORD=${OPENHIM_MONGODB_PASSWORD} - WEBHOOKS_MONGODB_PASSWORD=${WEBHOOKS_MONGODB_PASSWORD} - NOTIFICATION_MONGODB_PASSWORD=${NOTIFICATION_MONGODB_PASSWORD} + - EVENTS_MONGODB_PASSWORD=${EVENTS_MONGODB_PASSWORD} networks: - overlay_net logging: diff --git a/package.json b/package.json index de35fc4b0..fd4ac8e66 100644 --- a/package.json +++ b/package.json @@ -64,7 +64,7 @@ "@hapi/boom": "^9.1.1", "@hapi/hapi": "^20.0.1", "@hapi/inert": "^6.0.3", - "@opencrvs/toolkit": "^0.0.5", + "@opencrvs/toolkit": "0.0.6-events", "@types/chalk": "^2.2.0", "@types/csv2json": "^1.4.0", "@types/fhir": "^0.0.30", diff --git a/src/form/addresses/index.ts b/src/form/addresses/index.ts index 6576f0015..920f09390 100644 --- a/src/form/addresses/index.ts +++ b/src/form/addresses/index.ts @@ -10,9 +10,6 @@ */ import { - FATHER_DETAILS_DONT_EXIST, - MOTHER_DETAILS_DONT_EXIST, - SPOUSE_DETAILS_DONT_EXIST, detailsDontExist, expressionToConditional, hideIfInformantBrideOrGroom, @@ -99,11 +96,11 @@ export const defaultAddressConfiguration: IAddressConfiguration[] = [ { config: AddressSubsections.PRIMARY_ADDRESS_SUBSECTION, label: formMessageDescriptors.primaryAddress, - conditionalCase: MOTHER_DETAILS_DONT_EXIST + conditionalCase: detailsDontExist }, { config: AddressCases.PRIMARY_ADDRESS, - conditionalCase: MOTHER_DETAILS_DONT_EXIST + conditionalCase: detailsDontExist } /*, { config: AddressSubsections.SECONDARY_ADDRESS_SUBSECTION, @@ -125,9 +122,9 @@ export const defaultAddressConfiguration: IAddressConfiguration[] = [ config: AddressSubsections.PRIMARY_ADDRESS_SUBSECTION, label: formMessageDescriptors.primaryAddress, conditionalCase: [ - expressionToConditional(FATHER_DETAILS_DONT_EXIST), + expressionToConditional(detailsDontExist), expressionToConditional( - `${FATHER_DETAILS_DONT_EXIST} || ${primaryAddressSameAsOtherPrimaryAddress}`, + `${detailsDontExist} || ${primaryAddressSameAsOtherPrimaryAddress}`, 'hideInPreview' ) ] @@ -149,7 +146,7 @@ export const defaultAddressConfiguration: IAddressConfiguration[] = [ }, { config: AddressCases.PRIMARY_ADDRESS, - conditionalCase: `((${FATHER_DETAILS_DONT_EXIST} || ${primaryAddressSameAsOtherPrimaryAddress}) && !(${mothersDetailsDontExistOnOtherPage}) || ((${detailsDontExist}) && (${mothersDetailsDontExistOnOtherPage})))` + conditionalCase: `((${detailsDontExist} || ${primaryAddressSameAsOtherPrimaryAddress}) && !(${mothersDetailsDontExistOnOtherPage}) || ((${detailsDontExist}) && (${mothersDetailsDontExistOnOtherPage})))` } /*, { config: AddressSubsections.SECONDARY_ADDRESS_SUBSECTION, @@ -275,9 +272,9 @@ export const defaultAddressConfiguration: IAddressConfiguration[] = [ config: AddressSubsections.PRIMARY_ADDRESS_SUBSECTION, label: formMessageDescriptors.primaryAddress, conditionalCase: [ - expressionToConditional(SPOUSE_DETAILS_DONT_EXIST), + expressionToConditional(detailsDontExist), expressionToConditional( - `${SPOUSE_DETAILS_DONT_EXIST} || ${primaryAddressSameAsOtherPrimaryAddress}`, + `${detailsDontExist} || ${primaryAddressSameAsOtherPrimaryAddress}`, 'hideInPreview' ) ] @@ -297,7 +294,7 @@ export const defaultAddressConfiguration: IAddressConfiguration[] = [ }, { config: AddressCases.PRIMARY_ADDRESS, - conditionalCase: `((${SPOUSE_DETAILS_DONT_EXIST} || ${primaryAddressSameAsOtherPrimaryAddress}) || (${detailsDontExist}))` + conditionalCase: `(${detailsDontExist} || ${primaryAddressSameAsOtherPrimaryAddress})` } ] }, diff --git a/src/form/common/default-validation-conditionals.ts b/src/form/common/default-validation-conditionals.ts index d0038478b..d67d06881 100644 --- a/src/form/common/default-validation-conditionals.ts +++ b/src/form/common/default-validation-conditionals.ts @@ -9,7 +9,6 @@ * Copyright (C) The OpenCRVS Authors located at https://github.com/opencrvs/opencrvs-core/blob/master/AUTHORS. */ import { Conditional } from '../types/types' -import { IntegratingSystemType } from '../types/types' import { Validator } from '../types/validators' /** @@ -442,18 +441,11 @@ export const spouseFamilyNameConditionals = [ } ] -export const FATHER_DETAILS_DONT_EXIST = - '(draftData?.father && !draftData?.father.detailsExist) || !values.detailsExist' -export const MOTHER_DETAILS_DONT_EXIST = - '(draftData?.mother && !draftData?.mother.detailsExist) || !values.detailsExist' -export const SPOUSE_DETAILS_DONT_EXIST = - '(draftData?.spouse && !draftData?.spouse.detailsExist) || !values.detailsExist' - // if mothers details do not exist on other page export const mothersDetailsDontExistOnOtherPage = 'draftData && draftData.mother && !draftData.mother.detailsExist' -// if fathers details do not exist +// if details don't exist for the current section export const detailsDontExist = '!values.detailsExist' // primary address same as other primary diff --git a/src/form/tennis-club-membership.ts b/src/form/tennis-club-membership.ts index 7cd31b438..efb0ec55d 100644 --- a/src/form/tennis-club-membership.ts +++ b/src/form/tennis-club-membership.ts @@ -9,7 +9,142 @@ * Copyright (C) The OpenCRVS Authors located at https://github.com/opencrvs/opencrvs-core/blob/master/AUTHORS. */ -import { defineConfig } from '@opencrvs/toolkit/events' +import { defineConfig, defineForm } from '@opencrvs/toolkit/events' +import { + defineConditional, + or, + eventHasAction, + userHasScope, + and, + not, + field +} from '@opencrvs/toolkit/conditionals' + +const TENNIS_CLUB_FORM = defineForm({ + label: { + id: 'event.tennis-club-membership.action.declare.form.label', + defaultMessage: 'Tennis club membership application', + description: 'This is what this form is referred as in the system' + }, + review: { + title: { + id: 'event.tennis-club-membership.action.declare.form.review.title', + defaultMessage: 'Member declaration for {firstname} {surname}', + description: 'Title of the form to show in review page' + } + }, + active: true, + version: { + id: '1.0.0', + label: { + id: 'event.tennis-club-membership.action.declare.form.version.1', + defaultMessage: 'Version 1', + description: 'This is the first version of the form' + } + }, + pages: [ + { + id: 'applicant', + title: { + id: 'event.tennis-club-membership.action.declare.form.section.who.title', + defaultMessage: 'Who is applying for the membership?', + description: 'This is the title of the section' + }, + fields: [ + { + id: 'applicant.firstname', + type: 'TEXT', + required: true, + label: { + defaultMessage: "Applicant's first name", + description: 'This is the label for the field', + id: 'event.tennis-club-membership.action.declare.form.section.who.field.firstname.label' + } + }, + { + id: 'applicant.surname', + type: 'TEXT', + required: true, + label: { + defaultMessage: "Applicant's surname", + description: 'This is the label for the field', + id: 'event.tennis-club-membership.action.declare.form.section.who.field.surname.label' + } + }, + { + id: 'applicant.dob', + type: 'DATE', + required: true, + validation: [ + { + message: { + defaultMessage: 'Please enter a valid date', + description: 'This is the error message for invalid date', + id: 'event.tennis-club-membership.action.declare.form.section.who.field.dob.error' + }, + validator: field('applicant.dob').isBeforeNow() + } + ], + label: { + defaultMessage: "Applicant's date of birth", + description: 'This is the label for the field', + id: 'event.tennis-club-membership.action.declare.form.section.who.field.dob.label' + } + } + // { + // id: 'applicant.image', + // type: 'FILE', + // required: false, + // label: { + // defaultMessage: "Applicant's profile picture", + // description: 'This is the label for the field', + // id: 'event.tennis-club-membership.action.declare.form.section.who.field.image.label' + // } + // } + ] + }, + { + id: 'recommender', + title: { + id: 'event.tennis-club-membership.action.declare.form.section.recommender.title', + defaultMessage: 'Who is recommending the applicant?', + description: 'This is the title of the section' + }, + fields: [ + { + id: 'recommender.firstname', + type: 'TEXT', + required: true, + label: { + defaultMessage: "Recommender's first name", + description: 'This is the label for the field', + id: 'event.tennis-club-membership.action.declare.form.section.recommender.field.firstname.label' + } + }, + { + id: 'recommender.surname', + type: 'TEXT', + required: true, + label: { + defaultMessage: "Recommender's surname", + description: 'This is the label for the field', + id: 'event.tennis-club-membership.action.declare.form.section.recommender.field.surname.label' + } + }, + { + id: 'recommender.id', + type: 'TEXT', + required: true, + label: { + defaultMessage: "Recommender's membership ID", + description: 'This is the label for the field', + id: 'event.tennis-club-membership.action.declare.form.section.recommender.field.id.label' + } + } + ] + } + ] +}) export const tennisClubMembershipEvent = defineConfig({ id: 'TENNIS_CLUB_MEMBERSHIP', @@ -18,115 +153,160 @@ export const tennisClubMembershipEvent = defineConfig({ description: 'This is what this event is referred as in the system', id: 'event.tennis-club-membership.label' }, + summary: { + title: { + defaultMessage: '{applicant.firstname} {applicant.surname}', + description: 'This is the title of the summary', + id: 'event.tennis-club-membership.summary.title' + }, + fields: [ + { + id: 'applicant.firstname' + }, + { + id: 'applicant.surname' + }, + { + id: 'recommender.firstname' + }, + { + id: 'recommender.surname' + }, + { + id: 'recommender.id' + } + ] + }, + workqueues: [ + { + id: 'all', + title: { + defaultMessage: 'All events', + description: 'Label for in progress workqueue', + id: 'event.tennis-club-membership.workqueue.all.label' + }, + fields: [ + { + id: 'applicant.firstname' + }, + { + id: 'applicant.surname' + } + ], + filters: [] + }, + { + id: 'ready-for-review', + title: { + defaultMessage: 'Ready for review', + description: 'Label for in review workqueue', + id: 'event.tennis-club-membership.workqueue.in-review.label' + }, + fields: [ + { + id: 'applicant.firstname' + }, + { + id: 'event.type' + }, + { + id: 'event.createdAt' + }, + { + id: 'event.modifiedAt' + } + ], + filters: [ + { + status: ['DECLARED'] + } + ] + }, + { + id: 'registered', + title: { + defaultMessage: 'Ready to print', + description: 'Label for registered workqueue', + id: 'event.tennis-club-membership.workqueue.registered.label' + }, + fields: [ + { + id: 'applicant.firstname' + }, + { + id: 'event.type' + }, + { + id: 'event.createdAt' + }, + { + id: 'event.modifiedAt' + } + ], + filters: [ + { + status: ['REGISTERED'] + } + ] + } + ], actions: [ { type: 'DECLARE', label: { - defaultMessage: 'Send an application', + defaultMessage: 'Declare', description: 'This is shown as the action name anywhere the user can trigger the action from', id: 'event.tennis-club-membership.action.declare.label' }, - forms: [ - { - label: { - id: 'event.tennis-club-membership.action.declare.form.label', - defaultMessage: 'Tennis club membership application', - description: 'This is what this form is referred as in the system' - }, - active: true, - version: { - id: '1.0.0', - label: { - id: 'event.tennis-club-membership.action.declare.form.version.1', - defaultMessage: 'Version 1', - description: 'This is the first version of the form' - } - }, - pages: [ - { - id: 'applicant', - title: { - id: 'event.tennis-club-membership.action.declare.form.section.who.title', - defaultMessage: 'Who is applying for the membership?', - description: 'This is the title of the section' - }, - fields: [ - { - id: 'applicant.firstname', - type: 'TEXT', - required: true, - label: { - defaultMessage: "Applicant's first name", - description: 'This is the label for the field', - id: 'event.tennis-club-membership.action.declare.form.section.who.field.firstname.label' - } - }, - { - id: 'applicant.surname', - type: 'TEXT', - required: true, - label: { - defaultMessage: "Applicant's surname", - description: 'This is the label for the field', - id: 'event.tennis-club-membership.action.declare.form.section.who.field.surname.label' - } - }, - { - id: 'applicant.dob', - type: 'DATE', - required: true, - label: { - defaultMessage: "Applicant's date of birth", - description: 'This is the label for the field', - id: 'event.tennis-club-membership.action.declare.form.section.who.field.dob.label' - } - } - ] - }, - { - id: 'recommender', - title: { - id: 'event.tennis-club-membership.action.declare.form.section.recommender.title', - defaultMessage: 'Who is recommending the applicant?', - description: 'This is the title of the section' - }, - fields: [ - { - id: 'recommender.firstname', - type: 'TEXT', - required: true, - label: { - defaultMessage: "Recommender's first name", - description: 'This is the label for the field', - id: 'event.tennis-club-membership.action.declare.form.section.recommender.field.firstname.label' - } - }, - { - id: 'recommender.surname', - type: 'TEXT', - required: true, - label: { - defaultMessage: "Recommender's surname", - description: 'This is the label for the field', - id: 'event.tennis-club-membership.action.declare.form.section.recommender.field.surname.label' - } - }, - { - id: 'recommender.id', - type: 'TEXT', - required: true, - label: { - defaultMessage: "Recommender's membership ID", - description: 'This is the label for the field', - id: 'event.tennis-club-membership.action.declare.form.section.recommender.field.id.label' - } - } - ] - } - ] - } - ] + forms: [TENNIS_CLUB_FORM], + allowedWhen: defineConditional(not(eventHasAction('DECLARE'))) + }, + { + type: 'VALIDATE', + label: { + defaultMessage: 'Validate', + description: + 'This is shown as the action name anywhere the user can trigger the action from', + id: 'event.tennis-club-membership.action.validate.label' + }, + allowedWhen: defineConditional(eventHasAction('DECLARE')), + forms: [TENNIS_CLUB_FORM] + }, + { + type: 'REGISTER', + label: { + defaultMessage: 'Register', + description: + 'This is shown as the action name anywhere the user can trigger the action from', + id: 'event.tennis-club-membership.action.register.label' + }, + allowedWhen: defineConditional( + and( + or( + eventHasAction('VALIDATE'), + and(eventHasAction('DECLARE'), userHasScope('register')) + ), + not(eventHasAction('REGISTER')) + ) + ), + forms: [TENNIS_CLUB_FORM] + }, + { + type: 'CUSTOM', + label: { + defaultMessage: 'My custom action', + description: + 'This is shown as the action name anywhere the user can trigger the action from', + id: 'event.tennis-club-membership.action.sdf.label' + }, + allowedWhen: defineConditional( + or( + eventHasAction('VALIDATE'), + and(eventHasAction('DECLARE'), userHasScope('register')) + ) + ), + forms: [] } ] }) diff --git a/src/form/types/types.ts b/src/form/types/types.ts index b73f9008b..6af2c0b2e 100644 --- a/src/form/types/types.ts +++ b/src/form/types/types.ts @@ -562,7 +562,7 @@ export interface IFormFieldBase { disabled?: boolean enabled?: string custom?: boolean - initialValue?: IFormFieldValue + initialValue?: InitialValue initialValueKey?: string extraValue?: IFormFieldValue conditionals?: Conditional[] @@ -838,6 +838,13 @@ export interface IDateRangePickerValue { isDateRangeActive: boolean | undefined } +export type DependencyInfo = { + expression: string + dependsOn: string[] +} + +export type InitialValue = IFormFieldValue | DependencyInfo + export type IFormFieldValue = | string | string[] diff --git a/src/translations/client.csv b/src/translations/client.csv index 282dcb8dc..55ea6a280 100644 --- a/src/translations/client.csv +++ b/src/translations/client.csv @@ -176,6 +176,10 @@ certificates.death.certificate.copy,Death Certificate Certified Copy,Death Certi certificates.marriage.certificate,Marriage Certificate,Marriage Certificate,Acte de mariage certificates.marriage.certificate.copy,Marriage Certificate Certified Copy,Marriage Certificate Certified Copy,Copie certifiée conforme de l'acte de mariage changeEmail.validation.msg,Phone number validation message,Must be a valid email address,Doit être une adresse e-mail valide +changeModal.cancel,The label for cancel button of change modal,Cancel,Annuler +changeModal.continue,The label for continue button of change modal,Continue,Continuer +changeModal.description,The description for change modal,A record will be created of any changes you make,Un enregistrement sera créé pour chaque modification que vous apporterez. +changeModal.title,The title for change modal,Edit declaration?,Modifier la déclaration? changePhone.validation.msg,Phone number validation message,Must be a valid 10 digit number that starts with 0,Doit être un numéro valide à {num} chiffres qui commence par {start}. config.advanced.search,This is used for the advanced search,Advanced Search,Recherche avancée config.advanced.search.instruction,This is used for the advanced search,Select the options to build an advanced search. A minimum of two search parameters is required.,Sélectionnez les options pour construire une recherche avancée. Un minimum de deux paramètres de recherche est requis. @@ -794,6 +798,21 @@ error.title,Error title,Oops!,Oups ! error.title.unauthorized,Error title unauthorized,Unauthorized!,Non autorisé ! error.userListError,Error message when user list loads fails,Failed to load users,Impossible de charger les utilisateurs error.weAreTryingToFixThisError,Error description,This page could not be found,"Ce n'est pas vous, c'est nous. C'est notre faute." +event.tennis-club-membership.action.declare.form.label,This is what this form is referred as in the system,Tennis club membership application,Demande d'adhésion au club de tennis +event.tennis-club-membership.action.declare.form.section.recommender.field.firstname.label,This is the label for the field,Recommender's first name,Prénom du recommandeur +event.tennis-club-membership.action.declare.form.section.recommender.field.id.label,This is the label for the field,Recommender's membership ID,ID d'adhésion du recommandeur +event.tennis-club-membership.action.declare.form.section.recommender.field.surname.label,This is the label for the field,Recommender's surname,Nom de famille du recommandeur +event.tennis-club-membership.action.declare.form.section.recommender.title,This is the title of the section,Who is recommending the applicant?,Qui recommande le demandeur? +event.tennis-club-membership.action.declare.form.section.who.field.dob.label,This is the label for the field,Applicant's date of birth,Date de naissance du demandeur +event.tennis-club-membership.action.declare.form.section.who.field.firstname.label,This is the label for the field,Applicant's first name,Prénom du demandeur +event.tennis-club-membership.action.declare.form.section.who.field.surname.label,This is the label for the field,Applicant's surname,Nom de famille du demandeur +event.tennis-club-membership.action.declare.form.section.who.title,This is the title of the section,Who is applying for the membership?,Qui postule pour l'adhésion? +event.tennis-club-membership.action.declare.form.version.1,This is the first version of the form,Version 1,Version 1 +event.tennis-club-membership.action.declare.label,This is shown as the action name anywhere the user can trigger the action from,Send an application,Envoyer une demande +event.tennis-club-membership.label,This is what this event is referred as in the system,Tennis club membership application,Demande d'adhésion au club de tennis +exitModal.cancel,The label for cancel button in exit modal,Cancel,Annuler +exitModal.exitWithoutSaving,The title for exit without saving modal,Exit without saving changes?,Quitter sans enregistrer les modifications? +exitModal.exitWithoutSavingDescription,The description for exit without saving modal,You have unsaved changes on your declaration form. Are you sure you want to exit without saving?,Vous avez des modifications non enregistrées sur votre formulaire de déclaration. Êtes-vous sûr de vouloir quitter sans enregistrer? fieldAgentHome.allUpdatesText,,Great job! You have updated all declarations,Bon travail ! Vous avez mis à jour toutes les déclarations fieldAgentHome.inProgressCount,,In progress ({total}),En cours ({total}) fieldAgentHome.queryError,The text when error ocurred loading rejected declarations,An error occurred while loading declarations,Une erreur s'est produite lors du chargement des déclarations @@ -2019,6 +2038,16 @@ register.selectVitalEvent.registerNewEventHeading,The section heading on the pag register.selectVitalEvent.registerNewEventTitle,The title that appears on the select vital event page,New declaration,Nouvelle déclaration register.selectinformant.legalGuardian,,Legal guardian,Tuteur légal register.workQueue.declarations.banner,,Declarations to register in your area,Déclarations à enregistrer dans votre région +registerModal.cancel,The label for cancel button of register modal,Cancel,Annuler +registerModal.description,The description for register modal,The declarant will be notified of this correction and a record of this decision will be recorded,Le déclarant sera informé de cette correction et un enregistrement de cette décision sera créé. +registerModal.register,The label for register button of register modal,Register,Enregistrer +registerModal.title,The title for register modal,Register the member?,Enregistrer le membre? +rejectModal.archive,The label for archive button of reject modal,Archive,Archiver +rejectModal.cancel,The label for cancel button of reject modal,Cancel,Annuler +rejectModal.description,The description for reject modal,Please describe the updates required to this record for follow up action.,Veuillez décrire les mises à jour nécessaires à ce dossier pour un suivi. +rejectModal.markAsDuplicate,The label for mark as duplicate checkbox of reject modal,Mark as a duplicate,Marquer comme doublon +rejectModal.sendForUpdate,The label for send For Update button of reject modal,Send For Update,Envoyer pour mise à jour +rejectModal.title,The title for reject modal,Reason for rejection?,Raison du rejet? reloadmodal.body,Body of reload modal,There’s a new version of {app_name} available. Please update to continue.,Une nouvelle version de {app_name} est disponible. Veuillez effectuer la mise à jour pour continuer. reloadmodal.button.update,Label of update button,Update,Mise à jour reloadmodal.title,Title when update is available,Update available,Mise à jour disponible @@ -2075,6 +2104,10 @@ review.signature.delete,Label for button that deletes signature,Delete,Supprimer review.signature.description,Label awknowledging the correctness of the declaration,"I, the undersigned, hereby declare that the particulars in this form are true and correct to the best of my knowledge.","Je soussigné(e) déclare par la présente que les informations contenues dans ce formulaire sont, à ma connaissance, vraies et correctes." review.signature.input.description,Description awknowledging the correctness of the declaration,"By signing this document with an electronic signature, I agree that such signature will be valid as handwritten signatures to the extent allowed by the laws of Farajaland.","En signant ce document avec une signature électronique, j'accepte que cette signature soit valable comme les signatures manuscrites dans la mesure où les lois du Farajaland le permettent." review.signature.open,Label for button that opens the signature input,Sign,Signer +reviewAction.description,The description for review action,"By clicking register, you confirm that the information entered is correct and the member can be registered.","En cliquant sur enregistrer, vous confirmez que les informations saisies sont correctes et que le membre peut être enregistré." +reviewAction.register,The label for register button of review action,Register,Enregistrer +reviewAction.reject,The label for reject button of review action,Reject,Rejeter +reviewAction.title,The title for review action,Register member,Enregistrer un membre search.bookmark.error.notification,Error Notification messages for bookmark advanced search result,"Sorry, something went wrong. Please try again","Désolé, quelque chose s'est mal passé. Veuillez réessayer" search.bookmark.loading.notification,Loading Notification messages for bookmark advanced search result,Bookmarking your advanced search results...,Mettre en signet les résultats de votre recherche avancée... search.bookmark.remove.loading.notification,Loading Notification messages for remove advanced search bookmark,Removing your advanced search bookmark...,Suppression de votre signet de recherche avancée...