diff --git a/.github/workflows/build-images-from-branch.yml b/.github/workflows/build-images-from-branch.yml index b5d03c5f19..535f14771a 100644 --- a/.github/workflows/build-images-from-branch.yml +++ b/.github/workflows/build-images-from-branch.yml @@ -9,16 +9,18 @@ name: Publish images to Dockerhub from any branch on: - workflow_dispatch: + workflow_call: inputs: branch_name: description: Branch to build from + required: true + type: string + workflow_dispatch: + inputs: + branch_name: default: develop required: true - pull_request: - branches-ignore: - - 'dependabot/**' - - 'renovate/**' + description: Branch to build from push: branches: - develop @@ -48,6 +50,11 @@ jobs: export VERSION=`git log -1 --pretty=format:%h` echo "Pushing version $VERSION" echo "version=$VERSION" >> $GITHUB_OUTPUT + + # the event_name is the event that triggered the caller workflow + # and not "workflow_call" like how it was supposed to be when + # another workflow is calling this one + if [ "${{ github.event_name }}" == 'push' ]; then BRANCH=${GITHUB_HEAD_REF:-${GITHUB_REF#refs/heads/}} elif [ "${{ github.event_name }}" == 'pull_request' ]; then diff --git a/.github/workflows/deploy-to-feature-environment.yml b/.github/workflows/deploy-to-feature-environment.yml index 4e67d14481..c50cbe4a13 100644 --- a/.github/workflows/deploy-to-feature-environment.yml +++ b/.github/workflows/deploy-to-feature-environment.yml @@ -102,6 +102,14 @@ jobs: } core.setOutput('stack', slugify('${{ env.BRANCH_NAME }}')); + trigger-build: + if: ${{ (github.event_name == 'workflow_dispatch') || (!contains(github.actor, 'bot') && github.event.pull_request.head.repo.fork == false) }} + needs: generate_stack_name_and_branch + uses: ./.github/workflows/build-images-from-branch.yml + with: + branch_name: ${{ needs.generate_stack_name_and_branch.outputs.branch_name }} + secrets: inherit + trigger-e2e: if: ${{ (github.event_name == 'workflow_dispatch') || (!contains(github.actor, 'bot') && github.event.pull_request.head.repo.fork == false) }} runs-on: ubuntu-22.04 diff --git a/.github/workflows/lint-and-test.yml b/.github/workflows/lint-and-test.yml index 8eaea31a5c..7bb1e52131 100644 --- a/.github/workflows/lint-and-test.yml +++ b/.github/workflows/lint-and-test.yml @@ -85,17 +85,36 @@ jobs: with: node-version-file: .nvmrc + - name: Extract dependencies for ${{ matrix.package }} + if: steps.check-scripts.outputs.skip != 'true' + id: extract-dependencies + run: | + DEPENDENCIES=$(node -e " + const { execSync } = require('child_process'); + const output = execSync('yarn --silent workspaces info', { encoding: 'utf-8' }); + const json = JSON.parse(output.replaceAll('@opencrvs', 'packages')); + + const getDependencies = (pkg) => + json[pkg].workspaceDependencies.concat( + json[pkg].workspaceDependencies.flatMap(getDependencies) + ); + + console.log( + getDependencies('${{ matrix.package }}').join(' ') + ); + ") + echo "DEPENDENCIES=${DEPENDENCIES}" >> $GITHUB_ENV + echo "Found dependencies: $DEPENDENCIES" + - name: Remove other package directories if: steps.check-scripts.outputs.skip != 'true' run: | for dir in packages/*; do - if [ "$dir" != "${{ matrix.package }}" ] && [ "$dir" != "packages/commons" ] && [ "$dir" != "packages/components" ]; then - if [ "${{ matrix.package }}" == "packages/client" ] && [ "$dir" == "packages/gateway" ] ; then - echo "Skipping $dir" - else - echo "Removing $dir" - rm -rf "$dir" - fi + if echo "${{ matrix.package }} $DEPENDENCIES" | grep -q -w "$dir"; then + echo "Skipping $dir" + else + echo "Removing $dir" + rm -rf "$dir" fi done @@ -119,15 +138,13 @@ jobs: # TODO: Move out of the matrix to be built once and shared - name: Build common package - if: steps.check-scripts.outputs.skip != 'true' + if: steps.check-scripts.outputs.skip != 'true' && contains(env.DEPENDENCIES, 'packages/commons') run: cd packages/commons && yarn build - name: Build components client and login - if: steps.check-scripts.outputs.skip != 'true' + if: steps.check-scripts.outputs.skip != 'true' && contains(env.DEPENDENCIES, 'packages/components') run: | - if [[ "${{ matrix.package }}" == "packages/client" || "${{ matrix.package }}" == "packages/login" ]]; then - cd packages/components && yarn build - fi + cd packages/components && yarn build # TODO: should run parallel to unit tests as can take as much as unit tests - name: Run linting @@ -166,7 +183,7 @@ jobs: - name: Run knip on base branch id: knip_base run: | - npx knip --no-exit-code --exports --reporter=markdown > knip_report.md + npx knip --tags=-knipignore --no-exit-code --exports --reporter=markdown > knip_report.md TOTAL=$(grep -oP '## [A-Za-z\s]+ \(\K[0-9]+' knip_report.md | awk '{sum+=$1} END {print sum}') echo "Total $TOTAL issue(s) on base branch." echo "total=${TOTAL}" >> $GITHUB_OUTPUT @@ -175,7 +192,7 @@ jobs: - name: Run knip on PR branch id: knip_pr run: | - npx knip --no-exit-code --exports --reporter=markdown > knip_report.md + npx knip --tags=-knipignore --no-exit-code --exports --reporter=markdown > knip_report.md TOTAL=$(grep -oP '## [A-Za-z\s]+ \(\K[0-9]+' knip_report.md | awk '{sum+=$1} END {print sum}') echo "Total $TOTAL issue(s) on PR branch." echo "total=${TOTAL}" >> $GITHUB_OUTPUT diff --git a/.github/workflows/publish-release.yml b/.github/workflows/publish-release.yml index 443566e7cd..c40a17314f 100644 --- a/.github/workflows/publish-release.yml +++ b/.github/workflows/publish-release.yml @@ -48,12 +48,29 @@ jobs: - name: Get list of services id: get-services run: | - services=$(grep "^ [^ ]" docker-compose.yml | grep -v '#' | awk -F: '{print $1}' | sed -e 's/^ *//') + services=$(grep "^ [^ ]" docker-compose.yml | grep -v base| grep -v '#' | awk -F: '{print $1}' | sed -e 's/^ *//') services_json=$(echo $services | tr '\n' ',' | sed 's/,$//' | jq -R 'split(" ")' | tr -d '\n') # Set the list of service names as an output variable echo "services=$services_json" >> $GITHUB_OUTPUT echo "services=$services_json" + - name: Login to DockerHub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_PASSWORD }} + + - name: Build and push base image + uses: docker/build-push-action@v6 + with: + file: packages/Dockerfile.base + context: . + push: true + tags: | + opencrvs/ocrvs-base:${{ steps.set-version.outputs.version }} + cache-from: type=registry,ref=opencrvs/ocrvs-base:${{ steps.set-version.outputs.version }} + cache-to: type=inline + outputs: services: ${{ steps.get-services.outputs.services }} version: ${{ steps.set-version.outputs.version }} @@ -61,6 +78,7 @@ jobs: build: needs: base strategy: + fail-fast: false matrix: service: ${{ fromJSON(needs.base.outputs.services) }} runs-on: ubuntu-22.04 @@ -74,17 +92,23 @@ jobs: if: github.event_name == 'push' - name: Login to DockerHub - uses: docker/login-action@v1 + uses: docker/login-action@v3 with: username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_PASSWORD }} - - name: Build ${{ matrix.service }} - run: | - echo ${{ matrix.service }} - export VERSION=${{ github.event.inputs.release_version }} - docker compose build ${{ matrix.service }} - docker compose push ${{ matrix.service }} + - name: Build and push + uses: docker/build-push-action@v6 + with: + file: packages/${{ matrix.service }}/Dockerfile + build-args: | + VERSION=${{ needs.base.outputs.version }} + push: true + context: . + tags: | + opencrvs/ocrvs-${{ matrix.service }}:${{ needs.base.outputs.version }} + cache-from: type=registry,ref=opencrvs/ocrvs-${{ matrix.service }}:${{ needs.base.outputs.version}} + cache-to: type=inline security-scans: needs: [base, build] diff --git a/CHANGELOG.md b/CHANGELOG.md index a1a3a1628c..635f9db9ba 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,21 +4,11 @@ ### Breaking changes -- **Dashboard:** Changes made to the dashboard configuration will reset after upgrading OpenCRVS. - -## Improvements - -- Fetch child identifier in view record -- Auth token, ip address, remote address redacted from server log -- **Align Patient data model with FHIR**: Previously we were using `string[]` for `Patient.name.family` field instead of `string` as mentioned in the FHIR standard. We've now aligned the field with the standard. +- **Dashboard:** Changes made to the dashboard configuration will reset after upgrading OpenCRVS. ### New features - Misc new feature -- Certificate handlebar for registration fees `registrationFees` [#6817](https://github.com/opencrvs/opencrvs-core/issues/6817) -- Logged in user details handlebar `loggedInUser` [#6529](https://github.com/opencrvs/opencrvs-core/issues/6529) -- Supporting document fields can now be made required -- If there is only one option in the document uploader select, then it stays hidden and only the upload button is showed with the only option being selected by default - Allow configuring the default search criteria for record search [#6924](https://github.com/opencrvs/opencrvs-core/issues/6924) - Add checks to validate client and server are always on the same version. This prevents browsers with a cached or outdated client versions from making potentially invalid requests to the backend [#6695](https://github.com/opencrvs/opencrvs-core/issues/6695) - Two new statuses of record are added: `Validated` and `Correction Requested` for advanced search parameters [#6365](https://github.com/opencrvs/opencrvs-core/issues/6365) @@ -26,9 +16,20 @@ - Deploy UI-Kit Storybook to [opencrvs.pages.dev](https://opencrvs.pages.dev) to allow extending OpenCRVS using the component library - Record audit action buttons are moved into action menu [#7390](https://github.com/opencrvs/opencrvs-core/issues/7390) - Reoder the sytem user add/edit field for surname to be first, also change labels from `Last name` to `User's surname` and lastly remove the NID question from the form [#6830](https://github.com/opencrvs/opencrvs-core/issues/6830) +- Corrected the total amount displayed for _certification_ and _correction_ fees on the Performance Page, ensuring accurate fee tracking across certification and correction sequences. [#7793](https://github.com/opencrvs/opencrvs-core/issues/7793) - Auth now allows registrar's token to be exchanged for a new token that strictly allows confirming or rejecting a specific record. Core now passes this token to country configuration instead of the registrar's token [#7728](https://github.com/opencrvs/opencrvs-core/issues/7728) [#7849](https://github.com/opencrvs/opencrvs-core/issues/7849) +- A new GraphQL mutation `upsertRegistrationIdentifier` is added to allow updating the patient identifiers of a registration record such as NID [#8034](https://github.com/opencrvs/opencrvs-core/pull/8034) -## Bug fixes +### Improvements + +- Auth token, ip address, remote address redacted from server log +- **Align Patient data model with FHIR**: Previously we were using `string[]` for `Patient.name.family` field instead of `string` as mentioned in the FHIR standard. We've now aligned the field with the standard. + +### Deprecated + +- `validator-api` & `age-verification-api` & `nationalId` scopes are deprecated as unused. Corresponding scopes are removed from the `systemScopes` and also removed from the audience when creating the token [#7904](https://github.com/opencrvs/opencrvs-core/issues/7904) + +### Bug fixes - Fix health facilities missing from dropdown after correcting a record address [#7528](https://github.com/opencrvs/opencrvs-core/issues/7528) - "Choose a new password" form now allows the user to submit the form using the "Enter/Return" key [#5502](https://github.com/opencrvs/opencrvs-core/issues/5502) @@ -36,36 +37,27 @@ - Only render units/postfix when field has a value [#7055](https://github.com/opencrvs/opencrvs-core/issues/7055) - Only show items with values in review [#5192](https://github.com/opencrvs/opencrvs-core/pull/5192) - Fix prefix text overlap issue in form text inputs +- Fix the informant column on the Perfomance page showing "Other family member" when `Someone else` is selected for a registration [#6157](https://github.com/opencrvs/opencrvs-core/issues/6157) +- Fix the event name displayed in email templates for death correction requests [#7703](https://github.com/opencrvs/opencrvs-core/issues/7703) -## 1.6.0 Release candidate +## 1.6.1 Release candidate -## Improvements +### Bug fixes -- Internally we were storing the `family` name field as a required property which was limiting what how you could capture the name of a person in the forms. Now we are storing it as an optional property which would make more flexible. -- Remove the leftover features from the application config pages, such as certificates and informant notification. [#7156](https://github.com/opencrvs/opencrvs-core/issues/7156) -- **PDF page size** The generated PDF used to be defaulted to A4 size. Now it respects the SVG dimensions if specified -- Support html content wrapped in `foreignObject` used in svg template in certificate PDF output +- Maximum upload file size limit is now based on the size of the uploaded files after compression and not before. [#7840](https://github.com/opencrvs/opencrvs-core/issues/7840) -## Bug fixes +### New features -- Custom form field validators from country config will work offline. [#7478](https://github.com/opencrvs/opencrvs-core/issues/7478) -- Registrar had to retry from outbox every time they corrected a record. [#7583](https://github.com/opencrvs/opencrvs-core/issues/7583) -- Local environment setup command (`bash setup.sh`) could fail in machines that didn't have a unrelated `compose` binary. Fixed to check for Docker Compose. [#7609](https://github.com/opencrvs/opencrvs-core/pull/7609) -- Fix wrong status shown in the Comparison View page of the duplicate record [#7439](https://github.com/opencrvs/opencrvs-core/issues/7439) -- Fix date validation not working correctly in Firefox [#7615](https://github.com/opencrvs/opencrvs-core/issues/7615) -- Fix layout issue that was causing the edit button on the AdvancedSearch's date range picker to not show on mobile view. [#7417](https://github.com/opencrvs/opencrvs-core/issues/7417) -- Fix hardcoded placeholder copy of input when saving a query in advanced search -- Handle label params used in form inputs when rendering in action details modal -- **Staged files getting reset on precommit hook failure** We were running lint-staged separately on each package using lerna which potentially created a race condition causing staged changes to get lost on failure. Now we are running lint-staged directly without depending on lerna. **_This is purely a DX improvement without affecting any functionality of the system_** -- Fix `informantType` missing in template object which prevented rendering informant relationship data in the certificates [#5952](https://github.com/opencrvs/opencrvs-core/issues/5952) -- Fix users hitting rate limit when multiple users authenticated the same time with different usernames [#7728](https://github.com/opencrvs/opencrvs-core/issues/7728) +- Add an optional configurable field in section `canContinue` which takes an expression. Falsy value of this expression will disable the continue button in forms. This can be used to work with fetch field which has a loading state and prevent the user to get past the section while the request is still in progress. + +## [1.6.0](https://github.com/opencrvs/opencrvs-core/compare/v1.5.1...v1.6.0) ### Breaking changes - Remove informant notification configuration from the UI and read notification configuration settings from `record-notification` endpoint in countryconfig +- Remove DEL /elasticIndex endpoint due to reindexing changes. - **Gateways searchEvents API updated** `operationHistories` only returns `operationType` & `operatedOn` due to the other fields being unused in OpenCRVS - **Config changes to review/preview and signatures** Core used to provide review/preview section by default which are now removed and need to be provided from countryconfig. The signature field definitions (e.g. informant signature, bride signature etc.) were hard coded in core which also have now been removed. The signatures can now be added through the review/preview sections defined in countryconfig just like any other field. You can use the following section definition as the default which is without any additional fields. We highly recommend checking out our reference country repository which has the signature fields in its review/preview sections -- `hasChildLocation` query has been removed from gateway. We have created the query `isLeafLevelLocation` instead which is more descriptive on its intended use. ``` { @@ -90,18 +82,46 @@ } ``` +- `hasChildLocation` query has been removed from gateway. We have created the query `isLeafLevelLocation` instead which is more descriptive on its intended use. + ### New features - **Conditional filtering for document select options** The select options for the DOCUMENT_UPLOADER_WITH_OPTION field can now be conditionally filtered similar to the SELECT_WITH_OPTIONS field using the `optionCondition` field +- Supporting document fields can now be made required +- If there is only one option in the document uploader select, then it stays hidden and only the upload button is showed with the only option being selected by default +- A new certificate handlebar "preview" has been added which can be used to conditionally render some svg element when previewing the certificate e.g. background image similar to security paper +- Add HTTP request creation ability to the form with a set of new form components (HTTP, BUTTON, REDIRECT) [#7489](https://github.com/opencrvs/opencrvs-core/issues/7489) + +### Improvements + +- **ElasticSearch reindexing** Allows reindexing ElasticSearch via a new search-service endpoint `reindex`. We're replacing the original `ocrvs` index with timestamped ones. This is done automatically when upgrading and migrating, but this is an important architectural change that should be noted. More details in [#7033](https://github.com/opencrvs/opencrvs-core/pull/7033). +- Internally we were storing the `family` name field as a required property which was limiting what how you could capture the name of a person in the forms. Now we are storing it as an optional property which would make more flexible. +- Remove the leftover features from the application config pages, such as certificates and informant notification. [#7156](https://github.com/opencrvs/opencrvs-core/issues/7156) +- **PDF page size** The generated PDF used to be defaulted to A4 size. Now it respects the SVG dimensions if specified +- Support html content wrapped in `foreignObject` used in svg template in certificate PDF output + +### Bug fixes + +- Custom form field validators from country config will work offline. [#7478](https://github.com/opencrvs/opencrvs-core/issues/7478) +- Registrar had to retry from outbox every time they corrected a record. [#7583](https://github.com/opencrvs/opencrvs-core/issues/7583) +- Local environment setup command (`bash setup.sh`) could fail in machines that didn't have a unrelated `compose` binary. Fixed to check for Docker Compose. [#7609](https://github.com/opencrvs/opencrvs-core/pull/7609) +- Fix wrong status shown in the Comparison View page of the duplicate record [#7439](https://github.com/opencrvs/opencrvs-core/issues/7439) +- Fix date validation not working correctly in Firefox [#7615](https://github.com/opencrvs/opencrvs-core/issues/7615) +- Fix layout issue that was causing the edit button on the AdvancedSearch's date range picker to not show on mobile view. [#7417](https://github.com/opencrvs/opencrvs-core/issues/7417) +- Fix hardcoded placeholder copy of input when saving a query in advanced search +- Handle label params used in form inputs when rendering in action details modal +- **Staged files getting reset on precommit hook failure** We were running lint-staged separately on each package using lerna which potentially created a race condition causing staged changes to get lost on failure. Now we are running lint-staged directly without depending on lerna. **_This is purely a DX improvement without affecting any functionality of the system_** +- Fix `informantType` missing in template object which prevented rendering informant relationship data in the certificates [#5952](https://github.com/opencrvs/opencrvs-core/issues/5952) +- Fix users hitting rate limit when multiple users authenticated the same time with different usernames [#7728](https://github.com/opencrvs/opencrvs-core/issues/7728) ## 1.5.1 -## Improvements +### Improvements - Fetch child identifier in view record - Home screen application’s name and icons are to be configured from country configuration package as manifest.json and app icon files are moved from core to country config (check `opencrvs-countryconfig/src/client-static` folder) -## Bug fixes +### Bug fixes - On slow connections or in rare corner cases, it was possible that the same record got saved to the database twice. This was caused by a bug in how the unique technical identifier we generate were stored as FHIR. The backend now ensures every record is submitted only once. [#7477](https://github.com/opencrvs/opencrvs-core/issues/7477) - Fixed an issue where address line fields (e.g., address line 1, address line 2, etc.) were not being updated correctly when a user attempted to update a record's event location, such as place of birth or place of death. [#7531](https://github.com/opencrvs/opencrvs-core/issues/7531) @@ -114,30 +134,11 @@ - Registration agent was unable to download declarations that were previously corrected by registrar. [#7582](https://github.com/opencrvs/opencrvs-core/issues/7582) - The internal function we used to check if all the location references listed in the encounter are included in the bundle had incorrect logic which resulted in location details missing in ElasticSearch which broke Advanced search. [7494](https://github.com/opencrvs/opencrvs-core/issues/7494) -## 1.5.0 (TBD) - -### New features - -- Certificate handlebar for registration fees `registrationFees` [#6817](https://github.com/opencrvs/opencrvs-core/issues/6817) -- Logged in user details handlebar `loggedInUser` [#6529](https://github.com/opencrvs/opencrvs-core/issues/6529) -- Supporting document fields can now be made required -- If there is only one option in the document uploader select, then it stays hidden and only the upload button is showed with the only option being selected by default - -* **ElasticSearch reindexing** - -Allows reindexing ElasticSearch via a new search-service endpoint `reindex`. We're replacing the original `ocrvs` index with timestamped ones. This is done automatically when upgrading and migrating, but this is an important architectural change that should be noted. More details in [#7033](https://github.com/opencrvs/opencrvs-core/pull/7033). - -- Introduce a new certificate handlebar "preview" which can be used to conditionally render some svg element when previewing the certificate e.g. background image similar to security paper - -## Bug fixes - -- TBC - -## 1.5.0 (https://github.com/opencrvs/opencrvs-core/compare/v1.4.1...v1.5.0) +## [1.5.0](https://github.com/opencrvs/opencrvs-core/compare/v1.4.1...v1.5.0) ### Breaking changes -- **Removed dependency on OpenHIM.** +- **Removed dependency on OpenHIM** The performance of OpenHIM added an unexpected burden of 200 m/s to every interaction. Cumulatively, this was negatively affecting user experience and therefore we decided to deprecate it. @@ -210,7 +211,7 @@ Follow the descriptions in the migration notes to re-provision all servers safel - Improved formatting of informant name for inProgress declaration emails - There is now an option to print the review page of an event declaration form. The PRINT_DECLARATION feature flag in application config settings can enable this on or off. -## Bug fixes +### Bug fixes - Handle back button click after issuing a declaration [#6424](https://github.com/opencrvs/opencrvs-core/issues/6424) - Fix certificate verification QR code for a death declaration [#6230](https://github.com/opencrvs/opencrvs-core/issues/6230#issuecomment-1996766125) @@ -260,7 +261,7 @@ Follow the descriptions in the migration notes to re-provision all servers safel ## [1.3.4](https://github.com/opencrvs/opencrvs-core/compare/v1.3.3...v1.3.4) -## Bug fixes +### Bug fixes - #### Include middlename when generating fullnames - Refactored out the scattered logic for generating fullnames and converged them into a single function @@ -272,7 +273,7 @@ Follow the descriptions in the migration notes to re-provision all servers safel - #### Fix system crash when opening the started action modal [#6551](https://github.com/opencrvs/opencrvs-core/issues/6551) - #### Convert eventDates to LocalDate before formatting [#6719](https://github.com/opencrvs/opencrvs-core/issues/6719) -## [1.4.1](https://github.com/opencrvs/opencrvs-core/compare/v1.3.3...v1.4.1) +## [1.4.1](https://github.com/opencrvs/opencrvs-core/compare/v1.4.0...v1.4.1) - Fix Metabase versions in Dashboards service. Previously the version used for local development wasn't the one built into the docker image, which caused the locally generated initialisation file to fail in deployed environments. - Fix a seeding script bug, where it failed when done too quickly [#6553](https://github.com/opencrvs/opencrvs-core/issues/6553) @@ -301,18 +302,18 @@ In the next OpenCRVS release v1.5.0, there will be two significant changes both ## [1.3.3](https://github.com/opencrvs/opencrvs-core/compare/v1.3.2...v1.3.3) -## Breaking changes +### New features -## New features +- **New handlebars serving the location ids of the admin level locations** -- #### New handlebars serving the location ids of the admin level locations Apart from the new handlebars, a couple more improvements were introduced: + - stricter type for locations in client - **"location"** handlebar helper can now resolve offices & facilities - restrict the properties exposed through **"location"** handlebar helper - remove deprecated **DIVISION** & **UNION** from client -## Bug fixes +### Bug fixes - #### Fix location seeding scripts throwing error when there are too many source locations from the country config Locations are now seeded in smaller segments instead of one big collection. The newer approach has improved performance to a significant extent and also clears the interruption caused for a large number of country config locations @@ -320,8 +321,8 @@ In the next OpenCRVS release v1.5.0, there will be two significant changes both - Core not recognizing "occupation" as an optional field for deceased - Unassign declaration from a user if the declaration has already been proceeded through the workqueues by a separate user -## Dependency upgrades +### Dependency upgrades -- #### Metabase from v0.45.2.1 to v0.46.6.1 +- **Metabase from v0.45.2.1 to v0.46.6.1** See [Releases](https://github.com/opencrvs/opencrvs-core/releases) for release notes of older releases. diff --git a/docker-compose.yml b/docker-compose.yml index 8e4773ce02..72a894ac8a 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -26,6 +26,7 @@ services: - base environment: - COUNTRY_CONFIG_URL_INTERNAL=http://countryconfig:3040 + - GATEWAY_URL_INTERNAL=http://gateway:7070 dashboards: image: opencrvs/ocrvs-dashboards:${VERSION} #platform: linux/amd64 @@ -48,16 +49,6 @@ services: environment: - COUNTRY_CONFIG_URL_INTERNAL=http://countryconfig:3040 - events: - image: opencrvs/ocrvs-events:${VERSION} - #platform: linux/amd64 - build: - context: . - dockerfile: ./packages/events/Dockerfile - restart: unless-stopped - depends_on: - - base - gateway: image: opencrvs/ocrvs-gateway:${VERSION} #platform: linux/amd64 @@ -73,6 +64,7 @@ services: - CONFIG_SMS_CODE_EXPIRY_SECONDS=600 - CONFIG_TOKEN_EXPIRY_SECONDS=604800 - NODE_ENV=development + - EVENTS_URL=http://events:5555/ - FHIR_URL=http://hearth:3447/fhir - USER_MANAGEMENT_URL=http://user-mgnt:3030/ - SEARCH_URL=http://search:9090/ @@ -86,6 +78,21 @@ services: - CHECK_INVALID_TOKEN=true - MINIO_BUCKET=ocrvs - DOCUMENTS_URL=http://documents:9050 + + events: + image: opencrvs/ocrvs-events:${VERSION} + #platform: linux/amd64 + build: + context: . + dockerfile: ./packages/events/Dockerfile + restart: unless-stopped + depends_on: + - base + environment: + - MONGO_URL=mongodb://mongo1/events + - ES_HOST=elasticsearch:9200 + - COUNTRY_CONFIG_URL=http://countryconfig:3040/ + # User facing services workflow: image: opencrvs/ocrvs-workflow:${VERSION} diff --git a/infrastructure/nginx-deploy-config.sh b/infrastructure/nginx-deploy-config.sh index ffc4a7d6e7..0480f686cc 100755 --- a/infrastructure/nginx-deploy-config.sh +++ b/infrastructure/nginx-deploy-config.sh @@ -10,5 +10,7 @@ set -e sed -i s~{{COUNTRY_CONFIG_URL_INTERNAL}}~$COUNTRY_CONFIG_URL_INTERNAL~g /etc/nginx/conf.d/default.conf sed -i s~{{COUNTRY_CONFIG_URL_INTERNAL}}~$COUNTRY_CONFIG_URL_INTERNAL~g /usr/share/nginx/html/index.html +sed -i s~{{GATEWAY_URL_INTERNAL}}~$GATEWAY_URL_INTERNAL~g /etc/nginx/conf.d/default.conf +sed -i s~{{GATEWAY_URL_INTERNAL}}~$GATEWAY_URL_INTERNAL~g /usr/share/nginx/html/index.html sed -i s~{{CONTENT_SECURITY_POLICY_WILDCARD}}~$CONTENT_SECURITY_POLICY_WILDCARD~g /etc/nginx/conf.d/default.conf nginx -g 'daemon off;' diff --git a/knip.json b/knip.json new file mode 100644 index 0000000000..0e6b37a04b --- /dev/null +++ b/knip.json @@ -0,0 +1,3 @@ +{ + "ignore": ["packages/client/src/utils/gateway.ts"] +} diff --git a/license-config.json b/license-config.json index b2cdab4525..070cafca13 100644 --- a/license-config.json +++ b/license-config.json @@ -2,6 +2,7 @@ "ignore": [ "**/*.@(editorconfig|md|log|lock|patch|prettierrc|gitignore|eslintignore|stylelintrc|csv|gz|geojson|woff2|woff|xml|yarnrc|yarn-integrity|ttf|map|pdf|snap|dockerignore|jsonc|idea|env|info|key|pub|cjs|sql)", ".husky", + "**/*.ipynb", ".git", ".github/DISCUSSION_TEMPLATE/Installation.yml", ".github/CODEOWNERS", @@ -44,7 +45,8 @@ "packages/dashboards/plugins/*.jar", "packages/dashboards/data/metabase/*.db", "packages/client/dev-dist", - "packages/toolkit/.npmignore" + "packages/toolkit/.npmignore", + "packages/toolkit/tsconfig.tsbuildinfo" ], "license": "license-header.txt", "licenseFormats": { diff --git a/package.json b/package.json index eadbf8e207..ee2f762f82 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "description": "OpenCRVS core workspace", "license": "MPL-2.0", - "version": "1.5.0", + "version": "1.7.0", "private": true, "os": [ "darwin", diff --git a/packages/auth/package.json b/packages/auth/package.json index eea3265250..8de2522c6f 100644 --- a/packages/auth/package.json +++ b/packages/auth/package.json @@ -1,6 +1,6 @@ { "name": "@opencrvs/auth", - "version": "1.5.0", + "version": "1.7.0", "description": "OpenCRVS authentication service", "license": "MPL-2.0", "private": true, @@ -20,7 +20,7 @@ "dependencies": { "@hapi/boom": "^9.1.1", "@hapi/hapi": "^20.0.1", - "@opencrvs/commons": "^1.3.0", + "@opencrvs/commons": "^1.7.0", "app-module-path": "^2.2.0", "dotenv": "^6.1.0", "envalid": "^8.0.0", diff --git a/packages/auth/src/constants.ts b/packages/auth/src/constants.ts index c185f5cc15..e86f35237f 100644 --- a/packages/auth/src/constants.ts +++ b/packages/auth/src/constants.ts @@ -24,9 +24,6 @@ export const WEB_USER_JWT_AUDIENCES = [ 'opencrvs:documents-user' ] export const NOTIFICATION_API_USER_AUDIENCE = 'opencrvs:notification-api-user' -export const VALIDATOR_API_USER_AUDIENCE = 'opencrvs:validator-api-user' -export const AGE_VERIFICATION_USER_AUDIENCE = 'opencrvs:age-verification-user' -export const NATIONAL_ID_USER_AUDIENCE = 'opencrvs:nationalId-api-user' export const JWT_ISSUER = 'opencrvs:auth-service' export const INVALID_TOKEN_NAMESPACE = 'invalidToken' export const DEFAULT_TIMEOUT = 600000 diff --git a/packages/auth/src/features/oauthToken/client-credentials.ts b/packages/auth/src/features/oauthToken/client-credentials.ts index 894871d085..434709f1e8 100644 --- a/packages/auth/src/features/oauthToken/client-credentials.ts +++ b/packages/auth/src/features/oauthToken/client-credentials.ts @@ -17,10 +17,7 @@ import { import { WEB_USER_JWT_AUDIENCES, JWT_ISSUER, - NOTIFICATION_API_USER_AUDIENCE, - VALIDATOR_API_USER_AUDIENCE, - AGE_VERIFICATION_USER_AUDIENCE, - NATIONAL_ID_USER_AUDIENCE + NOTIFICATION_API_USER_AUDIENCE } from '@auth/constants' import * as oauthResponse from './responses' @@ -47,21 +44,12 @@ export async function clientCredentialsHandler( } const isNotificationAPIUser = result.scope.includes('notification-api') - const isValidatorAPIUser = result.scope.includes('validator-api') - const isAgeVerificationAPIUser = result.scope.includes('age-verification-api') - const isNationalIDAPIUser = result.scope.includes('nationalId') const token = await createToken( result.systemId, result.scope, isNotificationAPIUser ? WEB_USER_JWT_AUDIENCES.concat([NOTIFICATION_API_USER_AUDIENCE]) - : isValidatorAPIUser - ? WEB_USER_JWT_AUDIENCES.concat([VALIDATOR_API_USER_AUDIENCE]) - : isAgeVerificationAPIUser - ? WEB_USER_JWT_AUDIENCES.concat([AGE_VERIFICATION_USER_AUDIENCE]) - : isNationalIDAPIUser - ? WEB_USER_JWT_AUDIENCES.concat([NATIONAL_ID_USER_AUDIENCE]) : WEB_USER_JWT_AUDIENCES, JWT_ISSUER, true diff --git a/packages/client/Dockerfile b/packages/client/Dockerfile index d63d27950e..f06fbbbaff 100644 --- a/packages/client/Dockerfile +++ b/packages/client/Dockerfile @@ -3,11 +3,16 @@ FROM opencrvs/ocrvs-base:${BRANCH} USER node +COPY --chown=node:node packages/gateway /app/packages/gateway +COPY --chown=node:node packages/events /app/packages/events + WORKDIR /app/packages/components COPY --chown=node:node packages/components /app/packages/components + RUN yarn install --frozen-lockfile && yarn build ENV CONTENT_SECURITY_POLICY_WILDCARD "{{CONTENT_SECURITY_POLICY_WILDCARD}}" ENV COUNTRY_CONFIG_URL_INTERNAL "{{COUNTRY_CONFIG_URL_INTERNAL}}" +ENV GATEWAY_URL_INTERNAL "{{GATEWAY_URL_INTERNAL}}" WORKDIR /app/packages/client COPY --chown=node:node packages/client /app/packages/client RUN yarn install --frozen-lockfile && yarn build diff --git a/packages/client/Dockerfile.dockerignore b/packages/client/Dockerfile.dockerignore index 042ff4d295..2e4079799a 100644 --- a/packages/client/Dockerfile.dockerignore +++ b/packages/client/Dockerfile.dockerignore @@ -20,4 +20,5 @@ packages/* !packages/commons !packages/components !packages/client -!packages/gateway \ No newline at end of file +!packages/gateway +!packages/events \ No newline at end of file diff --git a/packages/client/graphql.schema.json b/packages/client/graphql.schema.json index 4eaf4b8853..7adc9cbfaf 100644 --- a/packages/client/graphql.schema.json +++ b/packages/client/graphql.schema.json @@ -8,6 +8,37 @@ }, "subscriptionType": null, "types": [ + { + "kind": "UNION", + "name": "Action", + "description": null, + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": null, + "possibleTypes": [ + { + "kind": "OBJECT", + "name": "CreateAction", + "ofType": null + }, + { + "kind": "OBJECT", + "name": "DeclareAction", + "ofType": null + }, + { + "kind": "OBJECT", + "name": "NotifyAction", + "ofType": null + }, + { + "kind": "OBJECT", + "name": "RegisterAction", + "ofType": null + } + ] + }, { "kind": "OBJECT", "name": "AdditionalIdWithCompositionId", @@ -804,7 +835,7 @@ "args": [], "type": { "kind": "ENUM", - "name": "Event", + "name": "EventType", "ofType": null }, "isDeprecated": false, @@ -1591,7 +1622,7 @@ "description": null, "type": { "kind": "ENUM", - "name": "Event", + "name": "EventType", "ofType": null }, "defaultValue": null, @@ -2063,6 +2094,41 @@ "enumValues": null, "possibleTypes": null }, + { + "kind": "INPUT_OBJECT", + "name": "ApproveCorrectionActionInput", + "description": null, + "fields": null, + "inputFields": [ + { + "name": "data", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "FieldInput", + "ofType": null + } + } + } + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, { "kind": "OBJECT", "name": "AssignmentData", @@ -3733,6 +3799,41 @@ "enumValues": null, "possibleTypes": null }, + { + "kind": "INPUT_OBJECT", + "name": "CertifyActionInput", + "description": null, + "fields": null, + "inputFields": [ + { + "name": "data", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "FieldInput", + "ofType": null + } + } + } + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, { "kind": "OBJECT", "name": "Comment", @@ -3966,6 +4067,65 @@ "enumValues": null, "possibleTypes": null }, + { + "kind": "INPUT_OBJECT", + "name": "ConfirmRegistrationInput", + "description": null, + "fields": null, + "inputFields": [ + { + "name": "error", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "identifiers", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "IdentifierInput", + "ofType": null + } + } + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "registrationNumber", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, { "kind": "OBJECT", "name": "ContactPoint", @@ -4511,6 +4671,89 @@ "enumValues": null, "possibleTypes": null }, + { + "kind": "OBJECT", + "name": "CreateAction", + "description": null, + "fields": [ + { + "name": "createdAt", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "DateTime", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "createdBy", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "data", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "Field", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "type", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, { "kind": "OBJECT", "name": "CreatedIds", @@ -4568,6 +4811,16 @@ "enumValues": null, "possibleTypes": null }, + { + "kind": "SCALAR", + "name": "DateTime", + "description": null, + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, { "kind": "OBJECT", "name": "DeathEventSearchSet", @@ -5336,11 +5589,11 @@ }, { "kind": "OBJECT", - "name": "Dummy", + "name": "DeclareAction", "description": null, "fields": [ { - "name": "dummy", + "name": "createdAt", "description": null, "args": [], "type": { @@ -5348,32 +5601,166 @@ "name": null, "ofType": { "kind": "SCALAR", - "name": "String", + "name": "DateTime", "ofType": null } }, "isDeprecated": false, "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "DuplicatesInfo", - "description": null, - "fields": [ + }, { - "name": "compositionId", + "name": "createdBy", "description": null, "args": [], "type": { - "kind": "SCALAR", - "name": "ID", - "ofType": null + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "data", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "Field", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "identifiers", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "Identifiers", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "type", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "DeclareActionInput", + "description": null, + "fields": null, + "inputFields": [ + { + "name": "data", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "FieldInput", + "ofType": null + } + } + } + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "Dummy", + "description": null, + "fields": [ + { + "name": "dummy", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "DuplicatesInfo", + "description": null, + "fields": [ + { + "name": "compositionId", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "ID", + "ofType": null }, "isDeprecated": false, "deprecationReason": null @@ -5488,32 +5875,129 @@ "possibleTypes": null }, { - "kind": "ENUM", + "kind": "OBJECT", "name": "Event", "description": null, - "fields": null, - "inputFields": null, - "interfaces": null, - "enumValues": [ + "fields": [ { - "name": "birth", + "name": "actions", "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "UNION", + "name": "Action", + "ofType": null + } + } + } + }, "isDeprecated": false, "deprecationReason": null }, { - "name": "death", + "name": "createdAt", "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "DateTime", + "ofType": null + } + }, "isDeprecated": false, "deprecationReason": null }, { - "name": "marriage", + "name": "id", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "type", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "updatedAt", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "DateTime", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "EventInput", + "description": null, + "fields": null, + "inputFields": [ + { + "name": "type", "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null, "isDeprecated": false, "deprecationReason": null } ], + "interfaces": null, + "enumValues": null, "possibleTypes": null }, { @@ -6363,12 +6847,41 @@ ] }, { - "kind": "INPUT_OBJECT", - "name": "FHIRIDMap", + "kind": "ENUM", + "name": "EventType", "description": null, "fields": null, - "inputFields": [ - { + "inputFields": null, + "interfaces": null, + "enumValues": [ + { + "name": "birth", + "description": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "death", + "description": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "marriage", + "description": null, + "isDeprecated": false, + "deprecationReason": null + } + ], + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "FHIRIDMap", + "description": null, + "fields": null, + "inputFields": [ + { "name": "composition", "description": null, "type": { @@ -6433,6 +6946,92 @@ "enumValues": null, "possibleTypes": null }, + { + "kind": "OBJECT", + "name": "Field", + "description": null, + "fields": [ + { + "name": "id", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "value", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "FieldValue", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "FieldInput", + "description": null, + "fields": null, + "inputFields": [ + { + "name": "id", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "value", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "FieldValue", + "ofType": null + } + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, { "kind": "SCALAR", "name": "FieldValue", @@ -7034,6 +7633,92 @@ "enumValues": null, "possibleTypes": null }, + { + "kind": "INPUT_OBJECT", + "name": "IdentifierInput", + "description": null, + "fields": null, + "inputFields": [ + { + "name": "type", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "value", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "Identifiers", + "description": null, + "fields": [ + { + "name": "registrationNumber", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "trackingId", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, { "kind": "INPUT_OBJECT", "name": "IdentityInput", @@ -7285,18 +7970,47 @@ "interfaces": null, "enumValues": [ { - "name": "MOSIP", + "name": "OTHER", "description": null, "isDeprecated": false, "deprecationReason": null - }, + } + ], + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "IssueActionInput", + "description": null, + "fields": null, + "inputFields": [ { - "name": "OTHER", + "name": "data", "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "FieldInput", + "ofType": null + } + } + } + }, + "defaultValue": null, "isDeprecated": false, "deprecationReason": null } ], + "interfaces": null, + "enumValues": null, "possibleTypes": null }, { @@ -8875,18 +9589,18 @@ "deprecationReason": null }, { - "name": "approveDeathRegistrationCorrection", + "name": "approveCorrectionEvent", "description": null, "args": [ { - "name": "details", + "name": "eventId", "description": null, "type": { "kind": "NON_NULL", "name": null, "ofType": { - "kind": "INPUT_OBJECT", - "name": "DeathRegistrationInput", + "kind": "SCALAR", + "name": "ID", "ofType": null } }, @@ -8895,14 +9609,14 @@ "deprecationReason": null }, { - "name": "id", + "name": "input", "description": null, "type": { "kind": "NON_NULL", "name": null, "ofType": { - "kind": "SCALAR", - "name": "ID", + "kind": "INPUT_OBJECT", + "name": "ApproveCorrectionActionInput", "ofType": null } }, @@ -8915,8 +9629,8 @@ "kind": "NON_NULL", "name": null, "ofType": { - "kind": "SCALAR", - "name": "ID", + "kind": "OBJECT", + "name": "Event", "ofType": null } }, @@ -8924,7 +9638,7 @@ "deprecationReason": null }, { - "name": "approveMarriageRegistrationCorrection", + "name": "approveDeathRegistrationCorrection", "description": null, "args": [ { @@ -8935,7 +9649,7 @@ "name": null, "ofType": { "kind": "INPUT_OBJECT", - "name": "MarriageRegistrationInput", + "name": "DeathRegistrationInput", "ofType": null } }, @@ -8973,18 +9687,67 @@ "deprecationReason": null }, { - "name": "auditUser", + "name": "approveMarriageRegistrationCorrection", "description": null, "args": [ { - "name": "action", + "name": "details", "description": null, "type": { "kind": "NON_NULL", "name": null, "ofType": { - "kind": "SCALAR", - "name": "String", + "kind": "INPUT_OBJECT", + "name": "MarriageRegistrationInput", + "ofType": null + } + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "id", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + } + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "auditUser", + "description": null, + "args": [ + { + "name": "action", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", "ofType": null } }, @@ -9074,6 +9837,55 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "certifyEvent", + "description": null, + "args": [ + { + "name": "eventId", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + } + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "input", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "CertifyActionInput", + "ofType": null + } + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "Event", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "changeAvatar", "description": null, @@ -9338,6 +10150,22 @@ "name": "confirmRegistration", "description": null, "args": [ + { + "name": "details", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "ConfirmRegistrationInput", + "ofType": null + } + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "id", "description": null, @@ -9531,6 +10359,39 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "createEvent", + "description": null, + "args": [ + { + "name": "event", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EventInput", + "ofType": null + } + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "Event", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "createMarriageRegistration", "description": null, @@ -9675,6 +10536,55 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "declareEvent", + "description": null, + "args": [ + { + "name": "eventId", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + } + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "input", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "DeclareActionInput", + "ofType": null + } + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "Event", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "deleteSystem", "description": null, @@ -9704,6 +10614,55 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "issueEvent", + "description": null, + "args": [ + { + "name": "eventId", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + } + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "input", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "IssueActionInput", + "ofType": null + } + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "Event", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "markBirthAsCertified", "description": null, @@ -10653,11 +11612,11 @@ "deprecationReason": null }, { - "name": "reactivateSystem", + "name": "notifyEvent", "description": null, "args": [ { - "name": "clientId", + "name": "eventId", "description": null, "type": { "kind": "NON_NULL", @@ -10671,18 +11630,38 @@ "defaultValue": null, "isDeprecated": false, "deprecationReason": null + }, + { + "name": "input", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "NotifyActionInput", + "ofType": null + } + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null } ], "type": { - "kind": "OBJECT", - "name": "System", - "ofType": null + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "Event", + "ofType": null + } }, "isDeprecated": false, "deprecationReason": null }, { - "name": "refreshSystemSecret", + "name": "reactivateSystem", "description": null, "args": [ { @@ -10693,7 +11672,7 @@ "name": null, "ofType": { "kind": "SCALAR", - "name": "String", + "name": "ID", "ofType": null } }, @@ -10704,12 +11683,90 @@ ], "type": { "kind": "OBJECT", - "name": "SystemSecret", + "name": "System", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "refreshSystemSecret", + "description": null, + "args": [ + { + "name": "clientId", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + } + ], + "type": { + "kind": "OBJECT", + "name": "SystemSecret", "ofType": null }, "isDeprecated": false, "deprecationReason": null }, + { + "name": "registerEvent", + "description": null, + "args": [ + { + "name": "eventId", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + } + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "input", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "RegisterActionInput", + "ofType": null + } + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "Event", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "registerSystem", "description": null, @@ -10735,6 +11792,153 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "reinstateEvent", + "description": null, + "args": [ + { + "name": "eventId", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + } + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "input", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "ReinstateActionInput", + "ofType": null + } + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "Event", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "rejectCorrectionEvent", + "description": null, + "args": [ + { + "name": "eventId", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + } + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "input", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "RejectCorrectionActionInput", + "ofType": null + } + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "Event", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "rejectRegistration", + "description": null, + "args": [ + { + "name": "details", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "RejectRegistrationInput", + "ofType": null + } + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "id", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + } + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "rejectRegistrationCorrection", "description": null, @@ -10813,6 +12017,55 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "requestCorrectionEvent", + "description": null, + "args": [ + { + "name": "eventId", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + } + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "input", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "RequestCorrectionActionInput", + "ofType": null + } + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "Event", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "requestRegistrationCorrection", "description": null, @@ -10920,6 +12173,104 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "revokeCorrectionEvent", + "description": null, + "args": [ + { + "name": "eventId", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + } + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "input", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "RevokeCorrectionActionInput", + "ofType": null + } + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "Event", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "revokeEvent", + "description": null, + "args": [ + { + "name": "eventId", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + } + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "input", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "RevokeActionInput", + "ofType": null + } + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "Event", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "updateDeathRegistration", "description": null, @@ -11014,13 +12365,135 @@ "isDeprecated": false, "deprecationReason": null } - ], + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "Response", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "usernameReminder", + "description": null, + "args": [ + { + "name": "userId", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + } + ], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "NotificationResult", + "description": null, + "fields": [ + { + "name": "success", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "ENUM", + "name": "NotificationType", + "description": null, + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": [ + { + "name": "EMAIL", + "description": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "SMS", + "description": null, + "isDeprecated": false, + "deprecationReason": null + } + ], + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "NotifyAction", + "description": null, + "fields": [ + { + "name": "createdAt", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "DateTime", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "createdBy", + "description": null, + "args": [], "type": { "kind": "NON_NULL", "name": null, "ofType": { - "kind": "OBJECT", - "name": "Response", + "kind": "SCALAR", + "name": "String", "ofType": null } }, @@ -11028,47 +12501,31 @@ "deprecationReason": null }, { - "name": "usernameReminder", + "name": "data", "description": null, - "args": [ - { - "name": "userId", - "description": null, - "type": { + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { "kind": "NON_NULL", "name": null, "ofType": { - "kind": "SCALAR", - "name": "String", + "kind": "OBJECT", + "name": "Field", "ofType": null } - }, - "defaultValue": null, - "isDeprecated": false, - "deprecationReason": null + } } - ], - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null }, "isDeprecated": false, "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "NotificationResult", - "description": null, - "fields": [ + }, { - "name": "success", + "name": "type", "description": null, "args": [], "type": { @@ -11076,7 +12533,7 @@ "name": null, "ofType": { "kind": "SCALAR", - "name": "Boolean", + "name": "String", "ofType": null } }, @@ -11090,26 +12547,38 @@ "possibleTypes": null }, { - "kind": "ENUM", - "name": "NotificationType", + "kind": "INPUT_OBJECT", + "name": "NotifyActionInput", "description": null, "fields": null, - "inputFields": null, - "interfaces": null, - "enumValues": [ - { - "name": "EMAIL", - "description": null, - "isDeprecated": false, - "deprecationReason": null - }, + "inputFields": [ { - "name": "SMS", + "name": "data", "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "FieldInput", + "ofType": null + } + } + } + }, + "defaultValue": null, "isDeprecated": false, "deprecationReason": null } ], + "interfaces": null, + "enumValues": null, "possibleTypes": null }, { @@ -12790,6 +14259,39 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "getEvent", + "description": null, + "args": [ + { + "name": "eventId", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + } + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "Event", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "getEventsWithProgress", "description": null, @@ -13446,9 +14948,13 @@ "name": "userId", "description": null, "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } }, "defaultValue": null, "isDeprecated": false, @@ -13552,9 +15058,13 @@ "name": "email", "description": null, "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } }, "defaultValue": null, "isDeprecated": false, @@ -13577,9 +15087,13 @@ "name": "mobile", "description": null, "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } }, "defaultValue": null, "isDeprecated": false, @@ -14886,29 +16400,163 @@ "name": "Date", "ofType": null }, - "defaultValue": null, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "type", + "description": null, + "type": { + "kind": "ENUM", + "name": "RegStatus", + "ofType": null + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "user", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "UserInput", + "ofType": null + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "RegisterAction", + "description": null, + "fields": [ + { + "name": "createdAt", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "DateTime", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "createdBy", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "data", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "Field", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "identifiers", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "Identifiers", + "ofType": null + } + }, "isDeprecated": false, "deprecationReason": null }, { "name": "type", "description": null, + "args": [], "type": { - "kind": "ENUM", - "name": "RegStatus", - "ofType": null + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } }, - "defaultValue": null, "isDeprecated": false, "deprecationReason": null - }, + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "RegisterActionInput", + "description": null, + "fields": null, + "inputFields": [ { - "name": "user", + "name": "data", "description": null, "type": { - "kind": "INPUT_OBJECT", - "name": "UserInput", - "ofType": null + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "FieldInput", + "ofType": null + } + } + } }, "defaultValue": null, "isDeprecated": false, @@ -15852,6 +17500,41 @@ ], "possibleTypes": null }, + { + "kind": "INPUT_OBJECT", + "name": "ReinstateActionInput", + "description": null, + "fields": null, + "inputFields": [ + { + "name": "data", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "FieldInput", + "ofType": null + } + } + } + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, { "kind": "OBJECT", "name": "Reinstated", @@ -15891,6 +17574,80 @@ "enumValues": null, "possibleTypes": null }, + { + "kind": "INPUT_OBJECT", + "name": "RejectCorrectionActionInput", + "description": null, + "fields": null, + "inputFields": [ + { + "name": "data", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "FieldInput", + "ofType": null + } + } + } + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "RejectRegistrationInput", + "description": null, + "fields": null, + "inputFields": [ + { + "name": "comment", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "reason", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, { "kind": "OBJECT", "name": "RelatedPerson", @@ -16620,6 +18377,41 @@ "enumValues": null, "possibleTypes": null }, + { + "kind": "INPUT_OBJECT", + "name": "RequestCorrectionActionInput", + "description": null, + "fields": null, + "inputFields": [ + { + "name": "data", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "FieldInput", + "ofType": null + } + } + } + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, { "kind": "OBJECT", "name": "Response", @@ -16647,6 +18439,76 @@ "enumValues": null, "possibleTypes": null }, + { + "kind": "INPUT_OBJECT", + "name": "RevokeActionInput", + "description": null, + "fields": null, + "inputFields": [ + { + "name": "data", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "FieldInput", + "ofType": null + } + } + } + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "RevokeCorrectionActionInput", + "description": null, + "fields": null, + "inputFields": [ + { + "name": "data", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "FieldInput", + "ofType": null + } + } + } + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, { "kind": "OBJECT", "name": "Role", @@ -20309,6 +22171,15 @@ } ] }, + { + "name": "oneOf", + "description": "Indicates exactly one field must be supplied and this field must not be `null`.", + "isRepeatable": false, + "locations": [ + "INPUT_OBJECT" + ], + "args": [] + }, { "name": "skip", "description": "Directs the executor to skip this field or fragment when the `if` argument is true.", @@ -20339,7 +22210,7 @@ }, { "name": "specifiedBy", - "description": "Exposes a URL that specifies the behaviour of this scalar.", + "description": "Exposes a URL that specifies the behavior of this scalar.", "isRepeatable": false, "locations": [ "SCALAR" @@ -20347,7 +22218,7 @@ "args": [ { "name": "url", - "description": "The URL that specifies the behaviour of this scalar.", + "description": "The URL that specifies the behavior of this scalar.", "type": { "kind": "NON_NULL", "name": null, diff --git a/packages/client/knip.json b/packages/client/knip.json new file mode 100644 index 0000000000..e4c0a08efc --- /dev/null +++ b/packages/client/knip.json @@ -0,0 +1,3 @@ +{ + "ignore": ["./src/utils/gateway.ts"] +} diff --git a/packages/client/nginx.conf b/packages/client/nginx.conf index 005f2f175e..53f718058f 100644 --- a/packages/client/nginx.conf +++ b/packages/client/nginx.conf @@ -69,6 +69,14 @@ server { proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } + location /api/ { + rewrite ^/api/(.*)$ /$1 break; + proxy_pass {{GATEWAY_URL_INTERNAL}}; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + } location / { root /usr/share/nginx/html; diff --git a/packages/client/package.json b/packages/client/package.json index e0be658b4e..5788232c5c 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -1,6 +1,6 @@ { "name": "@opencrvs/client", - "version": "1.5.0", + "version": "1.7.0", "description": "OpenCRVS client application", "license": "MPL-2.0", "private": true, @@ -16,7 +16,7 @@ "open:cov": "yarn test && opener coverage/index.html", "lint": "yarn lint:css && yarn lint:ts", "lint:css": "stylelint 'src/**/*.{ts,tsx}'", - "lint:ts": "eslint --fix './src/**/*.{ts,tsx}' --max-warnings=349", + "lint:ts": "eslint --fix './src/**/*.{ts,tsx}' --max-warnings=353", "test:compilation": "tsc --noEmit", "extract:translations": "bash extract-translations.sh", "generate-gateway-types": "NODE_OPTIONS=--dns-result-order=ipv4first graphql-codegen --config codegen.ts && prettier --write src/utils/gateway.ts", @@ -34,11 +34,18 @@ "dependencies": { "@apollo/client": "^3.7.0", "@craco/craco": "^6.4.3", - "@opencrvs/components": "^1.3.0", - "@opencrvs/commons": "^1.5.0", + "@opencrvs/commons": "^1.7.0", + "@opencrvs/components": "^1.7.0", + "@opencrvs/gateway": "^1.7.0", "@reduxjs/toolkit": "^1.8.3", "@sentry/react": "^7.12.1", "@sentry/tracing": "^7.12.1", + "@tanstack/react-query": "^5.61.5", + "@tanstack/react-query-devtools": "^5.62.2", + "@tanstack/react-query-persist-client": "^5.62.2", + "@trpc/client": "^11.0.0-rc.648", + "@trpc/react-query": "^11.0.0-rc.648", + "@trpc/server": "^11.0.0-rc.648", "@types/bcryptjs": "^2.4.2", "@types/history": "^4.6.2", "@types/html-to-pdfmake": "^2.4.4", @@ -65,6 +72,7 @@ "formik": "^2.2.9", "google-libphonenumber": "^3.2.32", "graphql": "^15.0.0", + "graphql-tag": "^2.12.6", "graphql-tools": "^4.0.7", "handlebars": "^4.7.6", "history": "^4.7.2", @@ -95,6 +103,7 @@ "redux-sentry-middleware": "^0.2.0", "sanitize-html": "^2.4.0", "styled-components": "^5.2.0", + "superjson": "1.9.0-0", "tsconfig-paths": "^3.13.0", "vite": "^5.4.8", "vite-plugin-svgr": "^0.6.0", @@ -105,7 +114,8 @@ "workbox-precaching": "^7.0.0", "workbox-routing": "^7.0.0", "workbox-strategies": "^7.0.0", - "xregexp": "^4.2.0" + "xregexp": "^4.2.0", + "zustand": "^5.0.2" }, "devDependencies": { "@graphql-codegen/add": "^5.0.0", @@ -113,6 +123,8 @@ "@graphql-codegen/introspection": "^3.0.0", "@graphql-codegen/typescript": "^3.0.0", "@graphql-codegen/typescript-operations": "^3.0.0", + "@testing-library/dom": "^10.4.0", + "@testing-library/react": "^16.1.0", "@types/browser-image-compression": "^1.0.13", "@types/csv2json": "^1.4.5", "@types/enzyme": "^3.1.13", @@ -120,6 +132,7 @@ "@types/fhir": "^0.0.30", "@types/google-libphonenumber": "^7.4.23", "@types/handlebars": "^4.1.0", + "@types/jsonwebtoken": "^9.0.7", "@types/jwt-decode": "^2.2.1", "@types/lodash": "^4.14.149", "@types/node": "^20.12.7", @@ -153,6 +166,7 @@ "fetch-mock": "^10.0.0", "glob": "^7.1.2", "jsonwebtoken": "^9.0.0", + "msw": "^2.6.8", "opener": "^1.5.1", "prettier": "2.8.8", "qrcode": "^1.5.1", diff --git a/packages/client/src/App.tsx b/packages/client/src/App.tsx index ce82f7c167..8433b7519f 100644 --- a/packages/client/src/App.tsx +++ b/packages/client/src/App.tsx @@ -16,7 +16,6 @@ import { ProtectedRoute } from '@client/components/ProtectedRoute' import ScrollToTop from '@client/components/ScrollToTop' import { SessionExpireConfirmation } from '@client/components/SessionExpireConfirmation' import { StyledErrorBoundary } from '@client/components/StyledErrorBoundary' -import TransitionWrapper from '@client/components/TransitionWrapper' import { I18nContainer } from '@client/i18n/components/I18nContainer' import * as routes from '@client/navigation/routes' import styled, { createGlobalStyle, ThemeProvider } from 'styled-components' @@ -70,8 +69,18 @@ import { ReviewCorrection } from './views/ReviewCorrection/ReviewCorrection' import { ReviewCertificate } from './views/PrintCertificate/ReviewCertificateAction' import AllUserEmail from './views/SysAdmin/Communications/AllUserEmail/AllUserEmail' import { ReloadModal } from './views/Modals/ReloadModal' -import { Workqueues } from './v2-events/workqueues' -import { V2_ROOT_ROUTE } from './v2-events/routes' +import { + V2_DECLARE_ACTION_REVIEW_ROUTE, + V2_DECLARE_ACTION_ROUTE, + V2_DECLARE_ACTION_ROUTE_WITH_PAGE, + V2_EVENTS_ROUTE, + V2_ROOT_ROUTE +} from './v2-events/routes' +import { Workqueues } from './v2-events/features/workqueues' +import { DeclareIndex } from './v2-events/features/events/actions/declare/Declare' +import { TRPCProvider } from './v2-events/trpc' +import { EventSelection } from './v2-events/features/events/EventSelection' +import { ReviewSection } from './v2-events/features/events/actions/declare/Review' interface IAppProps { client?: ApolloClient @@ -96,6 +105,7 @@ const GlobalStyle = createGlobalStyle` export function App(props: IAppProps) { const { client } = useApolloClient(props.store) + return ( @@ -127,425 +137,435 @@ export function App(props: IAppProps) { }) => { return ( <> - - - - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ) }} diff --git a/packages/client/src/components/TransitionWrapper.tsx b/packages/client/src/components/TransitionWrapper.tsx deleted file mode 100644 index a93294b0ac..0000000000 --- a/packages/client/src/components/TransitionWrapper.tsx +++ /dev/null @@ -1,123 +0,0 @@ -/* - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at https://mozilla.org/MPL/2.0/. - * - * OpenCRVS is also distributed under the terms of the Civil Registration - * & Healthcare Disclaimer located at http://opencrvs.org/license. - * - * Copyright (C) The OpenCRVS Authors located at https://github.com/opencrvs/opencrvs-core/blob/master/AUTHORS. - */ -import * as React from 'react' -import { TransitionGroup, CSSTransition } from 'react-transition-group' -import { - PAGE_TRANSITIONS_ENTER_TIME, - PAGE_TRANSITIONS_CLASSNAME, - PAGE_TRANSITIONS_EXIT_TIME -} from '@client/utils/constants' -import * as routes from '@client/navigation/routes' -import { matchPath } from 'react-router-dom' -import { Location } from 'history' - -function isPathExactmatch(pathname: string, routesPath: string): boolean { - const match = matchPath(pathname, routesPath) - if (match) { - return match.isExact - } - - return false -} - -function isUserHome(pathname: string): boolean { - if ( - isPathExactmatch(pathname, routes.HOME) || - isPathExactmatch(pathname, routes.REGISTRAR_HOME) || - isPathExactmatch(pathname, routes.REGISTRAR_HOME_TAB) - ) { - return true - } - - return false -} - -function isFormPage(pathname: string): boolean { - if ( - isPathExactmatch(pathname, routes.DRAFT_BIRTH_PARENT_FORM) || - isPathExactmatch(pathname, routes.DRAFT_BIRTH_PARENT_FORM_PAGE) || - isPathExactmatch(pathname, routes.DRAFT_BIRTH_PARENT_FORM_PAGE_GROUP) || - isPathExactmatch(pathname, routes.DRAFT_DEATH_FORM) || - isPathExactmatch(pathname, routes.DRAFT_DEATH_FORM_PAGE) || - isPathExactmatch(pathname, routes.DRAFT_DEATH_FORM_PAGE_GROUP) || - isPathExactmatch(pathname, routes.REVIEW_EVENT_PARENT_FORM_PAGE) || - isPathExactmatch(pathname, routes.REVIEW_EVENT_PARENT_FORM_PAGE_GROUP) - ) { - return true - } - - return false -} - -let locationKey = 'locationkey' - -function setLocationKey(currLocation: Location, prevLocation: Location) { - const prevLocPathname = prevLocation.pathname - const currLocPathname = currLocation.pathname - - if (currLocPathname === routes.SELECT_VITAL_EVENT) { - if (isUserHome(prevLocPathname)) { - locationKey = currLocation.key as string - } - } else if (isUserHome(currLocPathname)) { - if (isFormPage(prevLocPathname)) { - locationKey = currLocation.key as string - } - } -} -interface IProps { - location: Location - children: React.ReactNode -} -interface IState { - locations: Location[] -} -export default class TransitionWrapper extends React.Component { - constructor(props: IProps) { - super(props) - - this.state = { - locations: [this.props.location, this.props.location] - } - } - - static getDerivedStateFromProps( - { location: currLocation }: IProps, - { locations: [prevLocation] }: IState - ) { - return { locations: [currLocation, prevLocation] } - } - - render() { - const { children } = this.props - const { - locations: [currLocation, prevLocation] - } = this.state - - setLocationKey(currLocation, prevLocation) - - return ( - - - {children} - - - ) - } -} diff --git a/packages/client/src/components/charts/RegRatesLineChart.tsx b/packages/client/src/components/charts/RegRatesLineChart.tsx index 9ee0ff2b77..46b0d56ca9 100644 --- a/packages/client/src/components/charts/RegRatesLineChart.tsx +++ b/packages/client/src/components/charts/RegRatesLineChart.tsx @@ -8,7 +8,7 @@ * * Copyright (C) The OpenCRVS Authors located at https://github.com/opencrvs/opencrvs-core/blob/master/AUTHORS. */ -import { Event } from '@client/utils/gateway' +import { EventType } from '@client/utils/gateway' import { constantsMessages } from '@client/i18n/messages' import { IDataPoint, LineChart } from '@opencrvs/components/lib/LineChart' import { ITheme } from '@opencrvs/components/lib/theme' @@ -24,7 +24,7 @@ interface IProps extends WrappedComponentProps { theme: ITheme data?: ILineDataPoint[] loading?: boolean - eventType?: Event + eventType?: EventType completenessRateTime?: CompletenessRateTime } @@ -278,7 +278,7 @@ const RegRatesLineChartComponent = (props: IProps) => { messages.performanceWithinTargetDaysLabel, { target: - eventType === Event.Birth + eventType === EventType.Birth ? window.config.BIRTH.REGISTRATION_TARGET : window.config.DEATH.REGISTRATION_TARGET, withPrefix: false diff --git a/packages/client/src/components/form/FormFieldGenerator.test.tsx b/packages/client/src/components/form/FormFieldGenerator.test.tsx index 7ad2585cc1..b15f46ad29 100644 --- a/packages/client/src/components/form/FormFieldGenerator.test.tsx +++ b/packages/client/src/components/form/FormFieldGenerator.test.tsx @@ -29,7 +29,7 @@ import { DATE, NUMBER } from '@client/forms' -import { Event } from '@client/utils/gateway' +import { EventType } from '@client/utils/gateway' import { countries } from '@client/utils/countries' import { OFFLINE_LOCATIONS_KEY } from '@client/offline/reducer' import { formMessages } from '@client/i18n/messages' @@ -42,7 +42,7 @@ describe('form component', () => { beforeEach(async () => { const { store, history } = createStore() - const draft = createDeclaration(Event.Birth) + const draft = createDeclaration(EventType.Birth) store.dispatch(storeDeclaration(draft)) const modifyDraft = vi.fn() component = await createTestComponent( @@ -216,7 +216,7 @@ describe('when user is in the register section', () => { let component: ReactWrapper<{}, {}> beforeEach(async () => { const { store, history } = createStore() - const draft = createDeclaration(Event.Birth) + const draft = createDeclaration(EventType.Birth) store.dispatch(storeDeclaration(draft)) const modifyDraft = vi.fn() component = await createTestComponent( @@ -258,7 +258,7 @@ describe('when field definition has nested fields', () => { beforeEach(async () => { const { store, history } = createStore() - const draft = createDeclaration(Event.Birth) + const draft = createDeclaration(EventType.Birth) store.dispatch(storeDeclaration(draft)) const modifyDraft = vi.fn() component = await createTestComponent( diff --git a/packages/client/src/components/interface/DownloadButton.tsx b/packages/client/src/components/interface/DownloadButton.tsx index 6ef4dc87c7..6a6fdac853 100644 --- a/packages/client/src/components/interface/DownloadButton.tsx +++ b/packages/client/src/components/interface/DownloadButton.tsx @@ -8,42 +8,42 @@ * * Copyright (C) The OpenCRVS Authors located at https://github.com/opencrvs/opencrvs-core/blob/master/AUTHORS. */ -import * as React from 'react' -import styled from 'styled-components' -import { ResponsiveModal } from '@opencrvs/components/lib/ResponsiveModal' -import { Spinner } from '@opencrvs/components/lib/Spinner' -import { IActionObject } from '@opencrvs/components/lib/Workqueue' -import { Download } from '@opencrvs/components/lib/icons' -import { Button } from '@opencrvs/components/lib/Button' -import { connect } from 'react-redux' -import { - downloadDeclaration, - DOWNLOAD_STATUS, - unassignDeclaration, - deleteDeclaration as deleteDeclarationAction -} from '@client/declarations' -import { Action } from '@client/forms' -import { Event, SystemRoleType } from '@client/utils/gateway' import { ApolloClient, InternalRefetchQueriesInclude, useApolloClient } from '@apollo/client' -import { Downloaded } from '@opencrvs/components/lib/icons/Downloaded' -import type { AssignmentData } from '@client/utils/gateway' -import { IStoreState } from '@client/store' import { AvatarSmall } from '@client/components/Avatar' +import { + deleteDeclaration as deleteDeclarationAction, + DOWNLOAD_STATUS, + downloadDeclaration, + unassignDeclaration +} from '@client/declarations' +import { Action } from '@client/forms' +import { buttonMessages, constantsMessages } from '@client/i18n/messages' +import { conflictsMessages } from '@client/i18n/messages/views/conflicts' +import { IStoreState } from '@client/store' +import { useOnlineStatus } from '@client/utils' import { FIELD_AGENT_ROLES, ROLE_REGISTRATION_AGENT } from '@client/utils/constants' -import { Dispatch } from 'redux' -import { useIntl, IntlShape, MessageDescriptor } from 'react-intl' -import { buttonMessages, constantsMessages } from '@client/i18n/messages' -import { conflictsMessages } from '@client/i18n/messages/views/conflicts' +import type { AssignmentData } from '@client/utils/gateway' +import { EventType, SystemRoleType } from '@client/utils/gateway' +import { Button } from '@opencrvs/components/lib/Button' +import { ResponsiveModal } from '@opencrvs/components/lib/ResponsiveModal' +import { Spinner } from '@opencrvs/components/lib/Spinner' +import { IActionObject } from '@opencrvs/components/lib/Workqueue' +import { Download } from '@opencrvs/components/lib/icons' import { ConnectionError } from '@opencrvs/components/lib/icons/ConnectionError' -import { useOnlineStatus } from '@client/utils' +import { Downloaded } from '@opencrvs/components/lib/icons/Downloaded' +import * as React from 'react' +import { IntlShape, MessageDescriptor, useIntl } from 'react-intl' +import { connect } from 'react-redux' import ReactTooltip from 'react-tooltip' +import { Dispatch } from 'redux' +import styled from 'styled-components' const { useState, useCallback, useMemo } = React interface IDownloadConfig { @@ -229,7 +229,7 @@ function DownloadButtonComponent(props: DownloadButtonProps & HOCProps) { const download = useCallback(() => { const { event, compositionId, action } = downloadConfigs downloadDeclaration( - event.toLowerCase() as unknown as Event, + event.toLowerCase() as unknown as EventType, compositionId, action, client @@ -388,7 +388,7 @@ const mapDispatchToProps = ( ownProps: DownloadButtonProps ): IDispatchProps => ({ downloadDeclaration: ( - event: Event, + event: EventType, compositionId: string, action: Action, client: ApolloClient diff --git a/packages/client/src/components/interface/Navigation.tsx b/packages/client/src/components/interface/Navigation.tsx index 5e6c286848..962cab318f 100644 --- a/packages/client/src/components/interface/Navigation.tsx +++ b/packages/client/src/components/interface/Navigation.tsx @@ -45,7 +45,7 @@ import { INPROGRESS_STATUS } from '@client/SubmissionController' import { isDeclarationInReadyToReviewStatus } from '@client/utils/draftUtils' -import { Event } from '@client/utils/gateway' +import { EventType } from '@client/utils/gateway' import { UserDetails } from '@client/utils/userUtils' import { IWorkqueue, updateRegistrarWorkqueue } from '@client/workqueue' import { IStoreState } from '@opencrvs/client/src/store' @@ -337,10 +337,12 @@ const NavigationView = (props: IFullProps) => { ) const runningVer = String(localStorage.getItem('running-version')) - const isOnePrintInAdvanceOn = Object.values(Event).some((event: Event) => { - const upperCaseEvent = event.toUpperCase() as Uppercase - return offlineCountryConfiguration.config[upperCaseEvent].PRINT_IN_ADVANCE - }) + const isOnePrintInAdvanceOn = Object.values(EventType).some( + (event: EventType) => { + const upperCaseEvent = event.toUpperCase() as Uppercase + return offlineCountryConfiguration.config[upperCaseEvent].PRINT_IN_ADVANCE + } + ) const showRegDashboard = !IS_PROD_ENVIRONMENT || (IS_PROD_ENVIRONMENT && window.config.REGISTRATIONS_DASHBOARD_URL) diff --git a/packages/client/src/components/review/RejectRegistrationForm.test.tsx b/packages/client/src/components/review/RejectRegistrationForm.test.tsx index 09c7c059d2..ceb832787d 100644 --- a/packages/client/src/components/review/RejectRegistrationForm.test.tsx +++ b/packages/client/src/components/review/RejectRegistrationForm.test.tsx @@ -13,7 +13,7 @@ import { ReactWrapper } from 'enzyme' import { createStore } from '@client/store' import { createTestComponent } from '@client/tests/util' import { RejectRegistrationForm } from '@opencrvs/client/src/components/review/RejectRegistrationForm' -import { Event } from '@client/utils/gateway' +import { EventType } from '@client/utils/gateway' import { createDeclaration } from '@client/declarations' import { vi } from 'vitest' @@ -22,7 +22,7 @@ const mockHandler = vi.fn() describe('reject registration form', () => { let component: ReactWrapper<{}, {}> - const draftDeclaration = createDeclaration(Event.Birth) + const draftDeclaration = createDeclaration(EventType.Birth) beforeEach(async () => { component = await createTestComponent( { confirmRejectionEvent={mockHandler} declaration={draftDeclaration} draftId="04ba2b0e-ba38-4049-ad74-332e4ee9fbfe" - event={Event.Birth} + event={EventType.Birth} />, { store, history } ) diff --git a/packages/client/src/components/review/RejectRegistrationForm.tsx b/packages/client/src/components/review/RejectRegistrationForm.tsx index 3de96f8e47..b7904b8395 100644 --- a/packages/client/src/components/review/RejectRegistrationForm.tsx +++ b/packages/client/src/components/review/RejectRegistrationForm.tsx @@ -10,17 +10,21 @@ */ import { FormFieldGenerator } from '@client/components/form' import { + archiveDeclaration, IDeclaration, IPayload, - SUBMISSION_STATUS, - archiveDeclaration + SUBMISSION_STATUS } from '@client/declarations' import { IFormSectionData, SubmissionAction } from '@client/forms' import { hasFormError } from '@client/forms/utils' import { buttonMessages } from '@client/i18n/messages' import { messages } from '@client/i18n/messages/views/reject' -import styled from 'styled-components' -import { Event } from '@client/utils/gateway' +import { goToHome } from '@client/navigation' +import { IOfflineData } from '@client/offline/reducer' +import { getOfflineData } from '@client/offline/selectors' +import { getUserDetails } from '@client/profile/profileSelectors' +import { EventType } from '@client/utils/gateway' +import { UserDetails } from '@client/utils/userUtils' import { IRejectRegistrationForm, rejectRegistration @@ -28,15 +32,11 @@ import { import { IStoreState } from '@opencrvs/client/src/store' import { Button } from '@opencrvs/components/lib/Button' import { ResponsiveModal } from '@opencrvs/components/lib/ResponsiveModal' +import { isEmpty } from 'lodash' import * as React from 'react' import { injectIntl, WrappedComponentProps as IntlShapeProps } from 'react-intl' import { connect } from 'react-redux' -import { isEmpty } from 'lodash' -import { goToHome } from '@client/navigation' -import { getOfflineData } from '@client/offline/selectors' -import { IOfflineData } from '@client/offline/reducer' -import { getUserDetails } from '@client/profile/profileSelectors' -import { UserDetails } from '@client/utils/userUtils' +import styled from 'styled-components' const Instruction = styled.div` margin-bottom: 28px; @@ -51,7 +51,7 @@ interface IProps { config: IOfflineData user: UserDetails | null declaration: IDeclaration - event: Event + event: EventType duplicate?: boolean onClose: () => void archiveDeclaration: typeof archiveDeclaration @@ -160,7 +160,7 @@ class RejectRegistrationView extends React.Component { key="submit_archive" id="submit_archive" size="medium" - type="secondary_negative" + type="secondaryNegative" onClick={() => { this.props.archiveDeclaration( payload.id, diff --git a/packages/client/src/declarations/index.test.ts b/packages/client/src/declarations/index.test.ts index 85794d7855..bedf85a525 100644 --- a/packages/client/src/declarations/index.test.ts +++ b/packages/client/src/declarations/index.test.ts @@ -17,7 +17,7 @@ import { filterProcessingDeclarations, filterProcessingDeclarationsFromQuery } from '.' -import { Event, SystemRoleType, Status } from '@client/utils/gateway' +import { EventType, SystemRoleType, Status } from '@client/utils/gateway' import { AppStore, createStore } from '@client/store' import { mockDeclarationData, flushPromises } from '@client/tests/util' import { storage } from '@client/storage' @@ -277,13 +277,13 @@ describe('Utilty functions', () => { { id: '1', data: {}, - event: Event.Birth, + event: EventType.Birth, compositionId: '1' }, { id: '2', data: {}, - event: Event.Death, + event: EventType.Death, compositionId: '2' } ] @@ -304,7 +304,7 @@ describe('Utilty functions', () => { describe('archiveDeclaration tests', () => { let store: AppStore - const declaration = createDeclaration(Event.Birth, mockDeclarationData) + const declaration = createDeclaration(EventType.Birth, mockDeclarationData) let indexedDB: { USER_DATA: string; USER_DETAILS: string } beforeEach(() => { @@ -342,23 +342,26 @@ describe('archiveDeclaration tests', () => { } // Mocking storage reading - storage.getItem = vi.fn((key: string) => { - switch (key) { - case 'USER_DATA': - case 'USER_DETAILS': - return Promise.resolve(indexedDB[key]) - default: - return Promise.resolve(null) + // eslint-disable-next-line @typescript-eslint/no-explicit-any + storage.getItem = vi.fn<[string], Promise>( + (key: string): Promise => { + switch (key) { + case 'USER_DATA': + case 'USER_DETAILS': + return Promise.resolve(indexedDB[key] as T) + default: + return Promise.resolve(null) + } } - }) + ) // Mocking storage writing - storage.setItem = vi.fn((key: string, value: string) => { + storage.setItem = vi.fn((key: string, value: T): Promise => { switch (key) { case 'USER_DATA': case 'USER_DETAILS': - indexedDB[key] = value - return Promise.resolve(indexedDB[key]) + indexedDB[key] = value as string // Cast to string to match the logic + return Promise.resolve(value) default: return Promise.resolve(value) } diff --git a/packages/client/src/declarations/index.ts b/packages/client/src/declarations/index.ts index 9b8186070d..3860e2838a 100644 --- a/packages/client/src/declarations/index.ts +++ b/packages/client/src/declarations/index.ts @@ -21,7 +21,7 @@ import { } from '@client/forms' import { Attachment, - Event, + EventType, History, Query, RegStatus, @@ -226,7 +226,7 @@ export interface IDeclaration { modifiedOn?: number eventType?: string review?: boolean - event: Event + event: EventType registrationStatus?: RegStatus submissionStatus?: string downloadStatus?: DOWNLOAD_STATUS @@ -410,7 +410,7 @@ interface IDownloadDeclarationSuccess { payload: { queryData: any form: { - [key in Event]: IForm + [key in EventType]: IForm } client: ApolloClient<{}> offlineData?: IOfflineData @@ -504,15 +504,15 @@ const initialState: IDeclarationsState = { /* Need to add mappings for events here */ const QueryMapper = { - [Event.Birth]: getBirthQueryMappings, - [Event.Death]: getDeathQueryMappings, - [Event.Marriage]: getMarriageQueryMappings + [EventType.Birth]: getBirthQueryMappings, + [EventType.Death]: getDeathQueryMappings, + [EventType.Marriage]: getMarriageQueryMappings } -const getQueryMapping = (event: Event, action: DeclarationAction) => { +const getQueryMapping = (event: EventType, action: DeclarationAction) => { return QueryMapper[event] && QueryMapper[event](action) } -export function createDeclaration(event: Event, initialData?: IFormData) { +export function createDeclaration(event: EventType, initialData?: IFormData) { return { id: uuid(), data: initialData || {}, @@ -522,7 +522,7 @@ export function createDeclaration(event: Event, initialData?: IFormData) { } export function makeDeclarationReadyToDownload( - event: Event, + event: EventType, compositionId: string, action: DeclarationAction ): IDeclaration { @@ -538,7 +538,7 @@ export function makeDeclarationReadyToDownload( export function createReviewDeclaration( declarationId: string, formData: IFormData, - event: Event, + event: EventType, status?: RegStatus, duplicates?: IDuplicates[] ): IDeclaration { @@ -1029,7 +1029,7 @@ export async function deleteDeclarationByUser( } export function downloadDeclaration( - event: Event, + event: EventType, compositionId: string, action: DeclarationAction, client: ApolloClient<{}> diff --git a/packages/client/src/declarations/submissionMiddleware.test.ts b/packages/client/src/declarations/submissionMiddleware.test.ts index a74b063b0a..7a2372f2e6 100644 --- a/packages/client/src/declarations/submissionMiddleware.test.ts +++ b/packages/client/src/declarations/submissionMiddleware.test.ts @@ -10,13 +10,15 @@ */ import { ApolloError } from '@apollo/client' import { SubmissionAction } from '@client/forms' +import { offlineDataReady } from '@client/offline/actions' +import { createStore } from '@client/store' import { ACTION_STATUS_MAP, mockDeclarationData, mockOfflineDataDispatch } from '@client/tests/util' import { createClient } from '@client/utils/apolloClient' -import { Event } from '@client/utils/gateway' +import { EventType } from '@client/utils/gateway' import { GraphQLError } from 'graphql' import { SpyInstance, vi } from 'vitest' import { SUBMISSION_STATUS } from '.' @@ -24,8 +26,6 @@ import { declarationReadyForStatusChange, submissionMiddleware } from './submissionMiddleware' -import { createStore } from '@client/store' -import { offlineDataReady } from '@client/offline/actions' describe('Submission middleware', () => { const dispatch = vi.fn() @@ -63,7 +63,7 @@ describe('Submission middleware', () => { const action = declarationReadyForStatusChange({ id: 'mockDeclaration', data: mockDeclarationData, - event: Event.Birth, + event: EventType.Birth, action: SubmissionAction.SUBMIT_FOR_REVIEW, submissionStatus: SUBMISSION_STATUS.READY_TO_SUBMIT }) @@ -82,7 +82,7 @@ describe('Submission middleware', () => { const action = declarationReadyForStatusChange({ id: 'mockDeclaration', data: mockDeclarationData, - event: Event.Birth, + event: EventType.Birth, action: SubmissionAction.REJECT_DECLARATION, submissionStatus: SUBMISSION_STATUS.READY_TO_REJECT }) @@ -112,7 +112,7 @@ describe('Submission middleware', () => { const action = declarationReadyForStatusChange({ id: 'mockDeclaration', data: mockDeclarationData, - event: Event.Birth, + event: EventType.Birth, action: SubmissionAction.SUBMIT_FOR_REVIEW, submissionStatus: SUBMISSION_STATUS.READY_TO_SUBMIT }) @@ -125,10 +125,10 @@ describe('Submission middleware', () => { ) }) - Object.values(Event).forEach((event) => { + Object.values(EventType).forEach((event) => { Object.values(SubmissionAction).forEach((submissionAction) => { if ( - event === Event.Marriage && + event === EventType.Marriage && [ SubmissionAction.APPROVE_CORRECTION, SubmissionAction.REJECT_CORRECTION, diff --git a/packages/client/src/declarations/submissionMiddleware.ts b/packages/client/src/declarations/submissionMiddleware.ts index 9322d0cda3..879d84267e 100644 --- a/packages/client/src/declarations/submissionMiddleware.ts +++ b/packages/client/src/declarations/submissionMiddleware.ts @@ -32,7 +32,7 @@ import { } from '@client/transformer' import { client } from '@client/utils/apolloClient' import { FIELD_AGENT_ROLES } from '@client/utils/constants' -import { Event, RegStatus } from '@client/utils/gateway' +import { EventType, RegStatus } from '@client/utils/gateway' import { MARK_EVENT_AS_DUPLICATE, getBirthMutation @@ -44,12 +44,13 @@ import { updateRegistrarWorkqueue } from '@client/workqueue' import { Action, Middleware, createAction } from '@reduxjs/toolkit' import { Dispatch } from 'redux' // eslint-disable-next-line no-restricted-imports -import { captureException } from '@sentry/browser' -import { getOfflineData } from '@client/offline/selectors' +import { getReviewForm } from '@client/forms/register/review-selectors' import { IOfflineData } from '@client/offline/reducer' +import { getOfflineData } from '@client/offline/selectors' import type { MutationToRequestRegistrationCorrectionArgs } from '@client/utils/gateway-deprecated-do-not-use' import { UserDetails } from '@client/utils/userUtils' -import { getReviewForm } from '@client/forms/register/review-selectors' +// eslint-disable-next-line no-restricted-imports +import { captureException } from '@sentry/browser' type IReadyDeclaration = IDeclaration & { action: SubmissionAction @@ -222,9 +223,9 @@ export const submissionMiddleware: Middleware<{}, IStoreState> = } const mutation = - event === Event.Birth + event === EventType.Birth ? getBirthMutation(submissionAction) - : event === Event.Death + : event === EventType.Death ? getDeathMutation(submissionAction) : getMarriageMutation(submissionAction) diff --git a/packages/client/src/forms/certificate/fieldDefinitions/collectorSection.ts b/packages/client/src/forms/certificate/fieldDefinitions/collectorSection.ts index d306f3df5b..a41156755f 100644 --- a/packages/client/src/forms/certificate/fieldDefinitions/collectorSection.ts +++ b/packages/client/src/forms/certificate/fieldDefinitions/collectorSection.ts @@ -33,7 +33,7 @@ import { validIDNumber } from '@client/utils/validate' import { RadioSize } from '@opencrvs/components/lib/Radio' import { BIRTH_REGISTRATION_NUMBER, NATIONAL_ID } from '@client/utils/constants' import { identityHelperTextMapper, identityNameMapper } from './messages' -import { Event } from '@client/utils/gateway' +import { EventType } from '@client/utils/gateway' import { IDeclaration } from '@client/declarations' import { issueMessages } from '@client/i18n/messages/issueCertificate' @@ -808,11 +808,11 @@ export const collectMarriageCertificateFormSection: IFormSection = { ] } -const otherCertCollectorFormGroup = (event: Event): IFormSectionGroup => { +const otherCertCollectorFormGroup = (event: EventType): IFormSectionGroup => { const labelMap = { - [Event.Birth]: formMessages.informantsRelationWithChild, - [Event.Death]: formMessages.informantsRelationWithDeceased, - [Event.Marriage]: formMessages.relationshipToSpouses + [EventType.Birth]: formMessages.informantsRelationWithChild, + [EventType.Death]: formMessages.informantsRelationWithDeceased, + [EventType.Marriage]: formMessages.relationshipToSpouses } const fields: IFormField[] = [ @@ -1125,7 +1125,7 @@ export function getFilteredRadioOptions( birthForm: IRadioOption[], marriageForm?: IRadioOption[] ): IRadioOption[] { - if (declaration.event === Event.Birth) { + if (declaration.event === EventType.Birth) { options.splice(1, 0, ...birthForm) const rolesToCheck = ['MOTHER', 'FATHER'] @@ -1134,7 +1134,7 @@ export function getFilteredRadioOptions( options = options.filter((opt) => opt.value !== role) } } - } else if (declaration.event === Event.Marriage && marriageForm) { + } else if (declaration.event === EventType.Marriage && marriageForm) { options.splice(1, 0, ...marriageForm) } diff --git a/packages/client/src/forms/correction/corrector.ts b/packages/client/src/forms/correction/corrector.ts index acd1cb1f23..ebc6719864 100644 --- a/packages/client/src/forms/correction/corrector.ts +++ b/packages/client/src/forms/correction/corrector.ts @@ -16,12 +16,12 @@ import { IRadioOption, RADIO_GROUP_WITH_NESTED_FIELDS } from '@client/forms' +import { getFilteredRadioOptions } from '@client/forms/certificate/fieldDefinitions/collectorSection' import { fieldValueSectionExchangeTransformer } from '@client/forms/register/mappings/mutation' -import { formMessages, constantsMessages } from '@client/i18n/messages' +import { constantsMessages, formMessages } from '@client/i18n/messages' import { messages } from '@client/i18n/messages/views/correction' -import { Event } from '@client/utils/gateway' +import { EventType } from '@client/utils/gateway' import { RadioSize } from '@opencrvs/components/lib/Radio' -import { getFilteredRadioOptions } from '@client/forms/certificate/fieldDefinitions/collectorSection' export enum CorrectorRelationship { //death @@ -174,7 +174,7 @@ export const getCorrectorSection = ( name: 'otherRelationship', type: 'TEXT', label: - declaration.event === Event.Birth + declaration.event === EventType.Birth ? formMessages.informantsRelationWithChild : formMessages.informantsRelationWithDeceased, placeholder: { diff --git a/packages/client/src/forms/correction/verifyCorrector.ts b/packages/client/src/forms/correction/verifyCorrector.ts index a3a3cd05d2..82f5205380 100644 --- a/packages/client/src/forms/correction/verifyCorrector.ts +++ b/packages/client/src/forms/correction/verifyCorrector.ts @@ -1,5 +1,5 @@ import { ICertificateCorrectorDefinition } from '@client/views/CorrectionForm/VerifyCorrector' -import { Event } from '@client/utils/gateway' +import { EventType } from '@client/utils/gateway' /* * This Source Code Form is subject to the terms of the Mozilla Public @@ -86,5 +86,5 @@ const verifyDeathCorrector: ICertificateCorrectorDefinition = { } } -export const getVerifyCorrectorDefinition = (event: Event) => - event === Event.Birth ? verifyBirthCorrector : verifyDeathCorrector +export const getVerifyCorrectorDefinition = (event: EventType) => + event === EventType.Birth ? verifyBirthCorrector : verifyDeathCorrector diff --git a/packages/client/src/forms/index.ts b/packages/client/src/forms/index.ts index cbe88e38f5..2218acf648 100644 --- a/packages/client/src/forms/index.ts +++ b/packages/client/src/forms/index.ts @@ -125,7 +125,7 @@ export interface IDynamicOptions { options?: { [key: string]: ISelectOption[] } } -export interface IDispatchOptions { +interface IDispatchOptions { action: string payloadKey: string } @@ -964,6 +964,14 @@ export interface IFormSection { optional?: boolean notice?: MessageDescriptor mapping?: IFormSectionMapping + /** + * used for disabling continue button conditionally on a loading value + * of a FETCH field + * example: canContinue: '!$form.fetch?.loading' + * above example blocks user when fetch is on loading state, preventing implications + * caused by the unresolved pending requests + */ + canContinue?: string } export type ISerializedFormSectionGroup = Omit & { diff --git a/packages/client/src/forms/register/declaration-selectors.ts b/packages/client/src/forms/register/declaration-selectors.ts index 151c0d8cff..43a29fcb77 100644 --- a/packages/client/src/forms/register/declaration-selectors.ts +++ b/packages/client/src/forms/register/declaration-selectors.ts @@ -11,7 +11,7 @@ import { IRegisterFormState } from '@client/forms/register/reducer' import { IStoreState } from '@opencrvs/client/src/store' import { Section, IFormSection } from '@client/forms' -import { Event } from '@client/utils/gateway' +import { EventType } from '@client/utils/gateway' const getPartialState = (state: IStoreState): IRegisterFormState => state.registerForm @@ -39,14 +39,14 @@ export const isRegisterFormReady = (state: IStoreState) => { return Boolean(form) } -export const getEventRegisterForm = (state: IStoreState, event: Event) => { +export const getEventRegisterForm = (state: IStoreState, event: EventType) => { return getRegisterForm(state)[event] } const getRegisterFormSection = ( state: IStoreState, key: Section | string, - event: Event + event: EventType ): IFormSection => { const eventRegisterForm = getEventRegisterForm(state, event) @@ -67,12 +67,12 @@ export const getBirthSection = ( state: IStoreState, section: Section | string ) => { - return getRegisterFormSection(state, section, Event.Birth) + return getRegisterFormSection(state, section, EventType.Birth) } export const getDeathSection = ( state: IStoreState, section: Section | string ) => { - return getRegisterFormSection(state, section, Event.Death) + return getRegisterFormSection(state, section, EventType.Death) } diff --git a/packages/client/src/forms/register/mappings/event-specific-fields/birth/query/registration-mappings.ts b/packages/client/src/forms/register/mappings/event-specific-fields/birth/query/registration-mappings.ts index 31f290ae00..b4b1418782 100644 --- a/packages/client/src/forms/register/mappings/event-specific-fields/birth/query/registration-mappings.ts +++ b/packages/client/src/forms/register/mappings/event-specific-fields/birth/query/registration-mappings.ts @@ -9,8 +9,8 @@ * Copyright (C) The OpenCRVS Authors located at https://github.com/opencrvs/opencrvs-core/blob/master/AUTHORS. */ import { IFormData } from '@client/forms' -import { Event } from '@client/utils/gateway' import { transformStatusData } from '@client/forms/register/mappings/query/utils' +import { EventType } from '@client/utils/gateway' export function getBirthRegistrationSectionTransformer( transformedData: IFormData, @@ -27,7 +27,7 @@ export function getBirthRegistrationSectionTransformer( } if (queryData[sectionId].type && queryData[sectionId].type === 'BIRTH') { - transformedData[sectionId].type = Event.Birth + transformedData[sectionId].type = EventType.Birth } if (queryData[sectionId].status) { diff --git a/packages/client/src/forms/register/mappings/event-specific-fields/death/query/registration-mappings.ts b/packages/client/src/forms/register/mappings/event-specific-fields/death/query/registration-mappings.ts index acd0fb058f..8985caaf19 100644 --- a/packages/client/src/forms/register/mappings/event-specific-fields/death/query/registration-mappings.ts +++ b/packages/client/src/forms/register/mappings/event-specific-fields/death/query/registration-mappings.ts @@ -9,9 +9,9 @@ * Copyright (C) The OpenCRVS Authors located at https://github.com/opencrvs/opencrvs-core/blob/master/AUTHORS. */ import { IFormData } from '@client/forms' -import { Event } from '@client/utils/gateway' -import type { GQLRegWorkflow } from '@client/utils/gateway-deprecated-do-not-use' import { transformStatusData } from '@client/forms/register/mappings/query/utils' +import { EventType } from '@client/utils/gateway' +import type { GQLRegWorkflow } from '@client/utils/gateway-deprecated-do-not-use' export function getDeathRegistrationSectionTransformer( transformedData: IFormData, @@ -39,7 +39,7 @@ export function getDeathRegistrationSectionTransformer( queryData['registration'].type && queryData['registration'].type === 'DEATH' ) { - transformedData['registration'].type = Event.Death + transformedData['registration'].type = EventType.Death } if (queryData['registration'].status) { diff --git a/packages/client/src/forms/register/mappings/event-specific-fields/marriage/query/registration-mappings.ts b/packages/client/src/forms/register/mappings/event-specific-fields/marriage/query/registration-mappings.ts index 0995b1b5a6..b729f08150 100644 --- a/packages/client/src/forms/register/mappings/event-specific-fields/marriage/query/registration-mappings.ts +++ b/packages/client/src/forms/register/mappings/event-specific-fields/marriage/query/registration-mappings.ts @@ -10,7 +10,7 @@ */ import { IFormData } from '@client/forms' import { transformStatusData } from '@client/forms/register/mappings/query/utils' -import { Event } from '@client/utils/gateway' +import { EventType } from '@client/utils/gateway' import type { GQLRegWorkflow } from '@client/utils/gateway-deprecated-do-not-use' export function getMarriageRegistrationSectionTransformer( @@ -32,7 +32,7 @@ export function getMarriageRegistrationSectionTransformer( } if (queryData[sectionId].type && queryData[sectionId].type === 'MARRIAGE') { - transformedData[sectionId].type = Event.Marriage + transformedData[sectionId].type = EventType.Marriage } if (queryData[sectionId].status) { diff --git a/packages/client/src/forms/register/mappings/mutation/field-mappings.ts b/packages/client/src/forms/register/mappings/mutation/field-mappings.ts index 7de338f82c..745b292115 100644 --- a/packages/client/src/forms/register/mappings/mutation/field-mappings.ts +++ b/packages/client/src/forms/register/mappings/mutation/field-mappings.ts @@ -142,6 +142,7 @@ const getDefaultAddressLines = (): string[] => [ '', '', '', + '', '' ] // lines must be available as empty strings for GraphQL to parse all options diff --git a/packages/client/src/forms/register/mappings/query/field-mappings.ts b/packages/client/src/forms/register/mappings/query/field-mappings.ts index 55f243b38e..9e81b1afee 100644 --- a/packages/client/src/forms/register/mappings/query/field-mappings.ts +++ b/packages/client/src/forms/register/mappings/query/field-mappings.ts @@ -915,6 +915,7 @@ enum SupportedFacilityFHIRProp { locationLevel3 = 'locationLevel3', locationLevel4 = 'locationLevel4', locationLevel5 = 'locationLevel5', + locationLevel6 = 'locationLevel6', district = 'district', state = 'state', country = 'country' diff --git a/packages/client/src/forms/register/review-selectors.ts b/packages/client/src/forms/register/review-selectors.ts index 5a4382c5e7..6c694eaaf7 100644 --- a/packages/client/src/forms/register/review-selectors.ts +++ b/packages/client/src/forms/register/review-selectors.ts @@ -10,7 +10,7 @@ */ import { IReviewFormState } from '@client/forms/register/reviewReducer' import { IStoreState } from '@client/store' -import { Event } from '@client/utils/gateway' +import { EventType } from '@client/utils/gateway' const getPartialState = (store: IStoreState): IReviewFormState => store.reviewForm @@ -30,6 +30,6 @@ export const getReviewForm = (store: IStoreState) => { return form } -export const getEventReviewForm = (store: IStoreState, event: Event) => { +export const getEventReviewForm = (store: IStoreState, event: EventType) => { return getReviewForm(store)[event] } diff --git a/packages/client/src/i18n/messages/form.ts b/packages/client/src/i18n/messages/form.ts index 63d655dc2b..8a3b80e28a 100644 --- a/packages/client/src/i18n/messages/form.ts +++ b/packages/client/src/i18n/messages/form.ts @@ -395,10 +395,10 @@ export const formMessageDescriptors = { defaultMessage: 'Informant', description: 'Label for "Informant" select option' }, - otherFamilyMember: { - defaultMessage: 'Other family member', - description: 'Label for option Other family member', - id: 'form.field.label.relationOtherFamilyMember' + someoneElse: { + defaultMessage: 'Someone else', + description: 'Label for option Someone else', + id: 'form.field.label.relationSomeoneElse' }, legalGuardian: { defaultMessage: 'Legal guardian', diff --git a/packages/client/src/i18n/messages/views/integrations.ts b/packages/client/src/i18n/messages/views/integrations.ts index 2b45185230..1e58010051 100644 --- a/packages/client/src/i18n/messages/views/integrations.ts +++ b/packages/client/src/i18n/messages/views/integrations.ts @@ -127,12 +127,6 @@ const messagesToDefine = { description: 'Label for event notification' }, - nationalID: { - id: 'integrations.type.nationalID', - defaultMessage: 'National ID', - description: 'Label for national ID system client' - }, - childDetails: { id: 'integrations.childDetails', defaultMessage: `Child's details`, @@ -310,10 +304,6 @@ const messagesToDefine = { defaultMessage: 'This will deactivate the client', description: 'This will deactivate the client' }, - onlyOneNationalIdError: { - id: 'integrations.onlyOneNationalId', - defaultMessage: 'Only one National ID integration is allowed.' - }, updatePermissionsMsg: { id: 'integrations.updatePermissionsMsg', defaultMessage: 'Permissions updated successfully', diff --git a/packages/client/src/navigation/index.ts b/packages/client/src/navigation/index.ts index 4dc272f1a9..39940b7309 100644 --- a/packages/client/src/navigation/index.ts +++ b/packages/client/src/navigation/index.ts @@ -9,21 +9,37 @@ * Copyright (C) The OpenCRVS Authors located at https://github.com/opencrvs/opencrvs-core/blob/master/AUTHORS. */ -import { UserSection, CorrectionSection } from '@client/forms' -import { Event } from '@client/utils/gateway' +import { IWORKQUEUE_TABS } from '@client/components/interface/Navigation' +import { CorrectionSection, UserSection } from '@client/forms' import { + ADVANCED_SEARCH, + ADVANCED_SEARCH_RESULT, + ALL_USER_EMAIL, CERTIFICATE_COLLECTOR, + CERTIFICATE_CORRECTION, CREATE_USER, CREATE_USER_ON_LOCATION, CREATE_USER_SECTION, + DECLARATION_RECORD_AUDIT, + DRAFT_BIRTH_PARENT_FORM, DRAFT_DEATH_FORM, + DRAFT_MARRIAGE_FORM, EVENT_COMPLETENESS_RATES, HOME, + ISSUE_CERTIFICATE_PAYMENT, + ISSUE_COLLECTOR, + ISSUE_VERIFY_COLLECTOR, + ORGANISATIONS_INDEX, + PERFORMANCE_DASHBOARD, PERFORMANCE_FIELD_AGENT_LIST, PERFORMANCE_HOME, - ADVANCED_SEARCH, + PERFORMANCE_LEADER_BOARDS, + PERFORMANCE_REGISTRATIONS_LIST, + PERFORMANCE_STATISTICS, PRINT_CERTIFICATE_PAYMENT, + PRINT_RECORD, REGISTRAR_HOME_TAB, + REGISTRAR_HOME_TAB_PAGE, REVIEW_CERTIFICATE, REVIEW_USER_DETAILS, REVIEW_USER_FORM, @@ -31,55 +47,39 @@ import { SEARCH_RESULT, SELECT_VITAL_EVENT, SETTINGS, + SYSTEM_LIST, TEAM_SEARCH, - VERIFY_COLLECTOR, - WORKFLOW_STATUS, TEAM_USER_LIST, USER_PROFILE, - CERTIFICATE_CORRECTION, + VERIFY_COLLECTOR, VERIFY_CORRECTOR, - DECLARATION_RECORD_AUDIT, - REGISTRAR_HOME_TAB_PAGE, - SYSTEM_LIST, - VS_EXPORTS, VIEW_RECORD, - ADVANCED_SEARCH_RESULT, - PERFORMANCE_REGISTRATIONS_LIST, - PERFORMANCE_LEADER_BOARDS, - PERFORMANCE_STATISTICS, - PERFORMANCE_DASHBOARD, - ORGANISATIONS_INDEX, - ISSUE_COLLECTOR, - ISSUE_VERIFY_COLLECTOR, - ISSUE_CERTIFICATE_PAYMENT, - DRAFT_BIRTH_PARENT_FORM, - DRAFT_MARRIAGE_FORM, - ALL_USER_EMAIL, - PRINT_RECORD + VS_EXPORTS, + WORKFLOW_STATUS } from '@client/navigation/routes' import { - NATL_ADMIN_ROLES, NATIONAL_REGISTRAR_ROLES, + NATL_ADMIN_ROLES, PERFORMANCE_MANAGEMENT_ROLES, REGISTRAR_ROLES, SYS_ADMIN_ROLES } from '@client/utils/constants' +import { EventType } from '@client/utils/gateway' +import { UserDetails } from '@client/utils/userUtils' +import { IRecordAuditTabs } from '@client/views/RecordAudit/RecordAudit' import { IStatusMapping } from '@client/views/SysAdmin/Performance/reports/operational/StatusWiseDeclarationCountView' import { CompletenessRateTime } from '@client/views/SysAdmin/Performance/utils' import { ISearchLocation } from '@opencrvs/components/lib/LocationSearch' import { goBack as back, + goForward as forward, push, - replace, - goForward as forward + replace } from 'connected-react-router' -import { stringify } from 'query-string' -import { Cmd, loop } from 'redux-loop' -import { IRecordAuditTabs } from '@client/views/RecordAudit/RecordAudit' -import { IWORKQUEUE_TABS } from '@client/components/interface/Navigation' import startOfMonth from 'date-fns/startOfMonth' import subMonths from 'date-fns/subMonths' -import { UserDetails } from '@client/utils/userUtils' +import { stringify } from 'query-string' +import { Cmd, loop } from 'redux-loop' export interface IDynamicValues { [key: string]: any @@ -215,7 +215,7 @@ export function goToPerformanceHome( startOfMonth(subMonths(new Date(Date.now()), 11)).setHours(0, 0, 0, 0) ), timeEnd: Date = new Date(new Date(Date.now()).setHours(23, 59, 59, 999)), - event?: Event, + event?: EventType, locationId?: string ) { return push({ @@ -360,7 +360,10 @@ export function goToVerifyCorrector(declarationId: string, corrector: string) { ) } -export function goToReviewCertificate(registrationId: string, event: Event) { +export function goToReviewCertificate( + registrationId: string, + event: EventType +) { return push( formatUrl(REVIEW_CERTIFICATE, { registrationId: registrationId.toString(), @@ -386,7 +389,7 @@ export function goToVerifyCollector( export function goToPrintCertificatePayment( registrationId: string, - event: Event + event: EventType ) { return push( formatUrl(PRINT_CERTIFICATE_PAYMENT, { @@ -398,7 +401,7 @@ export function goToPrintCertificatePayment( export function goToIssueCertificatePayment( registrationId: string, - event: Event + event: EventType ) { return push( formatUrl(ISSUE_CERTIFICATE_PAYMENT, { @@ -421,7 +424,7 @@ export function goToCreateNewUserWithLocationId(locationId: string) { } export function goToCompletenessRates( - eventType: Event, + eventType: EventType, locationId: string | undefined, timeStart: Date, timeEnd: Date, @@ -489,7 +492,7 @@ export function goToWorkflowStatus( timeStart: Date, timeEnd: Date, status?: keyof IStatusMapping, - event?: Event + event?: EventType ) { return push({ pathname: WORKFLOW_STATUS, diff --git a/packages/client/src/navigation/routes.ts b/packages/client/src/navigation/routes.ts index 35395667ab..de16c90b13 100644 --- a/packages/client/src/navigation/routes.ts +++ b/packages/client/src/navigation/routes.ts @@ -8,22 +8,22 @@ * * Copyright (C) The OpenCRVS Authors located at https://github.com/opencrvs/opencrvs-core/blob/master/AUTHORS. */ -import { Event } from '@client/utils/gateway' +import { EventType } from '@client/utils/gateway' export const HOME = '/' export const SELECT_VITAL_EVENT = '/events' -export const DRAFT_BIRTH_PARENT_FORM = `/drafts/:declarationId/events/${Event.Birth}` -export const DRAFT_BIRTH_PARENT_FORM_PAGE = `/drafts/:declarationId/events/${Event.Birth}/:pageId` -export const DRAFT_BIRTH_PARENT_FORM_PAGE_GROUP = `/drafts/:declarationId/events/${Event.Birth}/:pageId/group/:groupId` -export const SELECT_DEATH_INFORMANT = `/drafts/:declarationId/events/${Event.Death}/registration/informantType` -export const DRAFT_DEATH_FORM = `/drafts/:declarationId/events/${Event.Death}` -export const DRAFT_DEATH_FORM_PAGE = `/drafts/:declarationId/events/${Event.Death}/:pageId` -export const DRAFT_DEATH_FORM_PAGE_GROUP = `/drafts/:declarationId/events/${Event.Death}/:pageId/group/:groupId` -export const SELECT_MARRIAGE_INFORMANT = `/drafts/:declarationId/events/${Event.Marriage}/registration/informantType` -export const DRAFT_MARRIAGE_FORM = `/drafts/:declarationId/events/${Event.Marriage}` -export const DRAFT_MARRIAGE_FORM_PAGE = `/drafts/:declarationId/events/${Event.Marriage}/:pageId` -export const DRAFT_MARRIAGE_FORM_PAGE_GROUP = `/drafts/:declarationId/events/${Event.Marriage}/:pageId/group/:groupId` +export const DRAFT_BIRTH_PARENT_FORM = `/drafts/:declarationId/events/${EventType.Birth}` +export const DRAFT_BIRTH_PARENT_FORM_PAGE = `/drafts/:declarationId/events/${EventType.Birth}/:pageId` +export const DRAFT_BIRTH_PARENT_FORM_PAGE_GROUP = `/drafts/:declarationId/events/${EventType.Birth}/:pageId/group/:groupId` +export const SELECT_DEATH_INFORMANT = `/drafts/:declarationId/events/${EventType.Death}/registration/informantType` +export const DRAFT_DEATH_FORM = `/drafts/:declarationId/events/${EventType.Death}` +export const DRAFT_DEATH_FORM_PAGE = `/drafts/:declarationId/events/${EventType.Death}/:pageId` +export const DRAFT_DEATH_FORM_PAGE_GROUP = `/drafts/:declarationId/events/${EventType.Death}/:pageId/group/:groupId` +export const SELECT_MARRIAGE_INFORMANT = `/drafts/:declarationId/events/${EventType.Marriage}/registration/informantType` +export const DRAFT_MARRIAGE_FORM = `/drafts/:declarationId/events/${EventType.Marriage}` +export const DRAFT_MARRIAGE_FORM_PAGE = `/drafts/:declarationId/events/${EventType.Marriage}/:pageId` +export const DRAFT_MARRIAGE_FORM_PAGE_GROUP = `/drafts/:declarationId/events/${EventType.Marriage}/:pageId/group/:groupId` export const REVIEW_EVENT_PARENT_FORM_PAGE = '/reviews/:declarationId/events/:event/parent/:pageId' diff --git a/packages/client/src/offline/actions.ts b/packages/client/src/offline/actions.ts index 14b5e8b9e0..6dec4c8145 100644 --- a/packages/client/src/offline/actions.ts +++ b/packages/client/src/offline/actions.ts @@ -8,6 +8,7 @@ * * Copyright (C) The OpenCRVS Authors located at https://github.com/opencrvs/opencrvs-core/blob/master/AUTHORS. */ +import { ILanguageState } from '@client/i18n/reducer' import { AdminStructure, CRVSOffice, @@ -15,21 +16,20 @@ import { ILocation, IOfflineData } from '@client/offline/reducer' -import { ILanguageState } from '@client/i18n/reducer' +import { System } from '@client/utils/gateway' import { - ILocationDataResponse, - IFacilitiesDataResponse, - IContentResponse, - IApplicationConfigResponse, + CertificateConfiguration, IApplicationConfig, IApplicationConfigAnonymous, - LoadFormsResponse, - LoadValidatorsResponse, + IApplicationConfigResponse, + IContentResponse, + IFacilitiesDataResponse, + ILocationDataResponse, LoadConditionalsResponse, + LoadFormsResponse, LoadHandlebarHelpersResponse, - CertificateConfiguration + LoadValidatorsResponse } from '@client/utils/referenceApi' -import { System } from '@client/utils/gateway' import { UserDetails } from '@client/utils/userUtils' const GET_LOCATIONS = 'OFFLINE/GET_LOCATIONS' diff --git a/packages/client/src/offline/reducer.ts b/packages/client/src/offline/reducer.ts index af5d8ca3cc..e9897ce470 100644 --- a/packages/client/src/offline/reducer.ts +++ b/packages/client/src/offline/reducer.ts @@ -8,43 +8,43 @@ * * Copyright (C) The OpenCRVS Authors located at https://github.com/opencrvs/opencrvs-core/blob/master/AUTHORS. */ +import { ISerializedForm } from '@client/forms' +import { initConditionals } from '@client/forms/conditionals' +import { initHandlebarHelpers } from '@client/forms/handlebarHelpers' +import { initValidators } from '@client/forms/validators' +import { ILanguage } from '@client/i18n/reducer' import { - loop, - Cmd, - Loop, - liftState, - getModel, - getCmd, - RunCmd -} from 'redux-loop' + Action as NotificationAction, + configurationErrorNotification +} from '@client/notification/actions' import * as actions from '@client/offline/actions' +import { ISVGTemplate } from '@client/pdfRenderer' import * as profileActions from '@client/profile/profileActions' import { storage } from '@client/storage' +import { isNavigatorOnline } from '@client/utils' +import { EventType, System } from '@client/utils/gateway' +import { filterLocations } from '@client/utils/locationUtils' import { + CertificateConfiguration, IApplicationConfig, IApplicationConfigAnonymous, - ILocationDataResponse, - referenceApi, - CertificateConfiguration, IFacilitiesDataResponse, - IOfficesDataResponse + ILocationDataResponse, + IOfficesDataResponse, + referenceApi } from '@client/utils/referenceApi' -import { ILanguage } from '@client/i18n/reducer' -import { filterLocations } from '@client/utils/locationUtils' -import { Event, System } from '@client/utils/gateway' import { UserDetails } from '@client/utils/userUtils' -import { isOfflineDataLoaded } from './selectors' -import { ISVGTemplate } from '@client/pdfRenderer' import { merge } from 'lodash' -import { isNavigatorOnline } from '@client/utils' -import { ISerializedForm } from '@client/forms' -import { initConditionals } from '@client/forms/conditionals' -import { initValidators } from '@client/forms/validators' import { - Action as NotificationAction, - configurationErrorNotification -} from '@client/notification/actions' -import { initHandlebarHelpers } from '@client/forms/handlebarHelpers' + Cmd, + Loop, + RunCmd, + getCmd, + getModel, + liftState, + loop +} from 'redux-loop' +import { isOfflineDataLoaded } from './selectors' export const OFFLINE_LOCATIONS_KEY = 'locations' export const OFFLINE_FACILITIES_KEY = 'facilities' @@ -369,15 +369,15 @@ function reducer( const { certificates, config, systems } = action.payload merge(window.config, config) const birthCertificateTemplate = certificates.find( - ({ event }) => event === Event.Birth + ({ event }) => event === EventType.Birth ) const deathCertificateTemplate = certificates.find( - ({ event }) => event === Event.Death + ({ event }) => event === EventType.Death ) const marriageCertificateTemplate = certificates.find( - ({ event }) => event === Event.Marriage + ({ event }) => event === EventType.Marriage ) let newOfflineData: Partial diff --git a/packages/client/src/profile/mutations.ts b/packages/client/src/profile/mutations.ts index c1c40a963b..587e30a4a5 100644 --- a/packages/client/src/profile/mutations.ts +++ b/packages/client/src/profile/mutations.ts @@ -35,6 +35,7 @@ export const ADVANCED_SEARCH_PARAM_FIELDS = gql` eventLocationLevel3 eventLocationLevel4 eventLocationLevel5 + eventLocationLevel6 childFirstNames childLastName childDoB diff --git a/packages/client/src/search/advancedSearch/reducer.ts b/packages/client/src/search/advancedSearch/reducer.ts index 4a21883130..eda62d7378 100644 --- a/packages/client/src/search/advancedSearch/reducer.ts +++ b/packages/client/src/search/advancedSearch/reducer.ts @@ -33,6 +33,7 @@ export type IAdvancedSearchParamState = { eventLocationLevel3?: string eventLocationLevel4?: string eventLocationLevel5?: string + eventLocationLevel6?: string childFirstNames?: string childLastName?: string childDoB?: string @@ -85,6 +86,7 @@ export const advancedSearchInitialState: IAdvancedSearchParamState = { eventLocationLevel3: '', eventLocationLevel4: '', eventLocationLevel5: '', + eventLocationLevel6: '', childFirstNames: '', childLastName: '', childDoB: '', diff --git a/packages/client/src/search/advancedSearch/utils.ts b/packages/client/src/search/advancedSearch/utils.ts index 41cd71d3f6..04037c827c 100644 --- a/packages/client/src/search/advancedSearch/utils.ts +++ b/packages/client/src/search/advancedSearch/utils.ts @@ -70,6 +70,7 @@ const baseKeysSameAsStore = [ 'eventLocationLevel3', 'eventLocationLevel4', 'eventLocationLevel5', + 'eventLocationLevel6', 'childFirstNames', 'childLastName', 'childGender', @@ -115,6 +116,7 @@ export interface IAdvancedSearchFormState { eventLocationLevel3?: string eventLocationLevel4?: string eventLocationLevel5?: string + eventLocationLevel6?: string childFirstNames?: string childLastName?: string childDoB?: IDateRangePickerValue @@ -609,10 +611,11 @@ const getLabelForRegistrationStatus = ( DECLARATION_UPDATED: [RegStatus.DeclarationUpdated], DECLARED: [RegStatus.Declared], IN_PROGRESS: [RegStatus.InProgress], - REGISTERED: [RegStatus.Registered], + REGISTERED: [RegStatus.Registered, RegStatus.Issued, RegStatus.Certified], REJECTED: [RegStatus.Rejected], VALIDATED: [RegStatus.Validated], - WAITING_VALIDATION: [RegStatus.WaitingValidation] + WAITING_VALIDATION: [RegStatus.WaitingValidation], + CORRECTION_REQUESTED: [RegStatus.CorrectionRequested] } const statusType = Object.keys(statusLabelMapping).find((key) => { if (isEqual([...statusList].sort(), [...statusLabelMapping[key]].sort())) { @@ -648,6 +651,16 @@ const getLabelForRegistrationStatus = ( { value: RegStatus.Archived, label: intl.formatMessage(advancedSearchForm.recordStatusAchived) + }, + { + value: RegStatus.CorrectionRequested, + label: intl.formatMessage( + advancedSearchForm.recordStatusCorrectionRequested + ) + }, + { + value: RegStatus.Validated, + label: intl.formatMessage(advancedSearchForm.recordStatusValidated) } ] @@ -710,6 +723,12 @@ export const getFormattedAdvanceSearchParamPills = ( intl: IntlShape, offlineData: IOfflineData ): pillKeyValueMap => { + const pillLabelFromTimePeriod = { + [TIME_PERIOD.LAST_90_DAYS]: advancedSearchForm.timePeriodLast90Days, + [TIME_PERIOD.LAST_30_DAYS]: advancedSearchForm.timePeriodLast30Days, + [TIME_PERIOD.LAST_7_DAYS]: advancedSearchForm.timePeriodLast7Days, + [TIME_PERIOD.LAST_YEAR]: advancedSearchForm.timePeriodLastYear + } const intlFormattedMapOfParams: pillKeyValueMap = { event: advancedSearchParamsState.event === 'birth' @@ -725,7 +744,13 @@ export const getFormattedAdvanceSearchParamPills = ( ) : '', - timePeriodFrom: advancedSearchParamsState.timePeriodFrom, + timePeriodFrom: + advancedSearchParamsState.timePeriodFrom && + intl.formatMessage( + pillLabelFromTimePeriod[ + advancedSearchParamsState.timePeriodFrom as TIME_PERIOD + ] + ), trackingId: advancedSearchParamsState.trackingId, regNumber: advancedSearchParamsState.registrationNumber, childFirstName: advancedSearchParamsState.childFirstNames, diff --git a/packages/client/src/search/transformer.ts b/packages/client/src/search/transformer.ts index 59b8c55f93..70c7b21813 100644 --- a/packages/client/src/search/transformer.ts +++ b/packages/client/src/search/transformer.ts @@ -8,6 +8,16 @@ * * Copyright (C) The OpenCRVS Authors located at https://github.com/opencrvs/opencrvs-core/blob/master/AUTHORS. */ +import { ITaskHistory } from '@client/declarations' +import { EMPTY_STRING, LANG_EN } from '@client/utils/constants' +import { createNamesMap } from '@client/utils/data-formatting' +import { formatLongDate } from '@client/utils/date-formatting' +import { + EventSearchSet, + EventType, + HumanName, + SearchEventsQuery +} from '@client/utils/gateway' import type { GQLBirthEventSearchSet, GQLDeathEventSearchSet, @@ -16,33 +26,23 @@ import type { GQLRegStatus } from '@client/utils/gateway-deprecated-do-not-use' import { IntlShape } from 'react-intl' -import { createNamesMap } from '@client/utils/data-formatting' -import { formatLongDate } from '@client/utils/date-formatting' -import { - HumanName, - EventSearchSet, - SearchEventsQuery, - Event -} from '@client/utils/gateway' -import { EMPTY_STRING, LANG_EN } from '@client/utils/constants' -import { ITaskHistory } from '@client/declarations' export const isBirthEvent = ( req: EventSearchSet ): req is GQLBirthEventSearchSet => { - return req.type === Event.Birth + return req.type === EventType.Birth } export const isDeathEvent = ( req: EventSearchSet ): req is GQLDeathEventSearchSet => { - return req.type === Event.Death + return req.type === EventType.Death } export const isMarriageEvent = ( reg: EventSearchSet ): reg is GQLMarriageEventSearchSet => { - return reg.type === Event.Marriage + return reg.type === EventType.Marriage } export const transformData = ( @@ -105,7 +105,7 @@ export const transformData = ( return { id: assignedReg.id, name: - assignedReg.type === Event.Marriage + assignedReg.type === EventType.Marriage ? mergedMarriageName : (createNamesMap(names as HumanName[])[locale] as string) || (createNamesMap(names as HumanName[])[LANG_EN] as string) || diff --git a/packages/client/src/storage.ts b/packages/client/src/storage.ts index c9ca05bf37..e5d02d3038 100644 --- a/packages/client/src/storage.ts +++ b/packages/client/src/storage.ts @@ -19,11 +19,11 @@ function configStorage(dbName: string) { validateApplicationVersion() } -async function getItem(key: string): Promise { - return await localForage.getItem(key) +async function getItem(key: string): Promise { + return await localForage.getItem(key) } -async function setItem(key: string, value: string) { +async function setItem(key: string, value: T) { return await localForage.setItem(key, value) } diff --git a/packages/client/src/tests/mock-offline-data.ts b/packages/client/src/tests/mock-offline-data.ts index 24a34b559d..db4eca8bee 100644 --- a/packages/client/src/tests/mock-offline-data.ts +++ b/packages/client/src/tests/mock-offline-data.ts @@ -41,17 +41,6 @@ const systems: System[] = [ ] } }, - { - name: 'National Id', - status: SystemStatus.Active, - type: SystemType.NationalId, - _id: '613ddbbe4c0b86e9b9f114e8', - shaSecret: '22ea09c2-f964-4562-bdac-8e9ca9b9a81a', - clientId: '2f1047bb-af48-4f27-8ab8-993d7b960f92', - settings: { - openIdProviderClientId: '7b621732-6c1d-4808-81b2-fd67f05f3af3' - } - }, { _id: '63a01ffe607915acacc2f553', clientId: '5923118f-c633-40c6-ba97-c3e3cbb412aa', diff --git a/packages/client/src/tests/schema.graphql b/packages/client/src/tests/schema.graphql index 67a49e5ff2..5453f94cb7 100644 --- a/packages/client/src/tests/schema.graphql +++ b/packages/client/src/tests/schema.graphql @@ -82,6 +82,7 @@ type AdvancedSeachParameters { eventLocationLevel3: String eventLocationLevel4: String eventLocationLevel5: String + eventLocationLevel6: String childFirstNames: String childLastName: String childDoB: String @@ -141,6 +142,7 @@ input AdvancedSearchParametersInput { eventLocationLevel3: String eventLocationLevel4: String eventLocationLevel5: String + eventLocationLevel6: String childFirstNames: String childLastName: String childDoB: String @@ -861,7 +863,6 @@ type IntegratedSystem { } enum IntegratingSystemType { - MOSIP OSIA OTHER } diff --git a/packages/client/src/tests/util.tsx b/packages/client/src/tests/util.tsx index ef2df7cb08..5c26f38330 100644 --- a/packages/client/src/tests/util.tsx +++ b/packages/client/src/tests/util.tsx @@ -9,7 +9,7 @@ * Copyright (C) The OpenCRVS Authors located at https://github.com/opencrvs/opencrvs-core/blob/master/AUTHORS. */ import { App } from '@client/App' -import { Event, SystemRoleType, Status } from '@client/utils/gateway' +import { EventType, SystemRoleType, Status } from '@client/utils/gateway' import { UserDetails } from '@client/utils/userUtils' import { getRegisterForm } from '@client/forms/register/declaration-selectors' import { getReviewForm } from '@client/forms/register/review-selectors' @@ -803,7 +803,7 @@ export const mockDeathRegistrationSectionData = { const mockFetchCertificatesTemplatesDefinition = [ { id: '12313546', - event: Event.Birth, + event: EventType.Birth, status: 'ACTIVE', svgCode: '\n\n\n\n{registrarName}
({role}) \n \n \nThis event was registered at {registrationLocation} \n{eventDate} \nDied on \nPlace of death \n \n{placeOfDeath} \n{informantName} \nThis is to certify that \n{registrationNumber} \nDeath Registration No \nDate of issuance of certificate: {certificateDate}\n\n\n\n\n\n\n\n\n\n\n', @@ -814,7 +814,7 @@ const mockFetchCertificatesTemplatesDefinition = [ }, { id: '25313546', - event: Event.Death, + event: EventType.Death, status: 'ACTIVE', svgCode: '\n\n\n\n{registrarName}
({role}) \n \n \nThis event was registered at {registrationLocation} \n{eventDate} \nWas born on \nPlace of birth \n \n{placeOfBirth} \n{informantName} \nThis is to certify that \n{registrationNumber} \nBirth Registration No \nDate of issuance of certificate: {certificateDate}\n\n\n\n\n\n\n\n\n\n\n', @@ -963,7 +963,7 @@ export async function goToMotherSection(component: ReactWrapper) { export async function getRegisterFormFromStore( store: Store, - event: Event + event: EventType ) { await store.dispatch(setOfflineData(userDetails)) const state = store.getState() @@ -972,7 +972,7 @@ export async function getRegisterFormFromStore( export async function getReviewFormFromStore( store: Store, - event: Event + event: EventType ) { await store.dispatch(setOfflineData(userDetails)) const state = store.getState() diff --git a/packages/client/src/transformer/transformer.test.tsx b/packages/client/src/transformer/transformer.test.tsx index 2f060d7563..6d293c251d 100644 --- a/packages/client/src/transformer/transformer.test.tsx +++ b/packages/client/src/transformer/transformer.test.tsx @@ -31,7 +31,7 @@ import { draftToGqlTransformer } from '@client/transformer' import { getRegisterForm } from '@opencrvs/client/src/forms/register/declaration-selectors' import { getOfflineDataSuccess } from '@client/offline/actions' import { IForm } from '@opencrvs/client/src/forms' -import { Event } from '@client/utils/gateway' +import { EventType } from '@client/utils/gateway' import { clone } from 'lodash' import { birthDraftData } from '@client/tests/mock-drafts' import createFetchMock from 'vitest-fetch-mock' @@ -66,11 +66,11 @@ describe('when draft data is transformed to graphql', () => { customDraft = { id: uuid(), data: birthDraftData, - event: Event.Birth, + event: EventType.Birth, submissionStatus: SUBMISSION_STATUS[SUBMISSION_STATUS.DRAFT] } store.dispatch(storeDeclaration(customDraft)) - form = getRegisterForm(store.getState())[Event.Birth] + form = getRegisterForm(store.getState())[EventType.Birth] history.replace( DRAFT_BIRTH_PARENT_FORM.replace( ':declarationId', diff --git a/packages/client/src/user/queries.ts b/packages/client/src/user/queries.ts index e91e4c4243..ac4227a3e4 100644 --- a/packages/client/src/user/queries.ts +++ b/packages/client/src/user/queries.ts @@ -81,7 +81,7 @@ export const GET_USER_AUDIT_LOG = gql` ` export const GET_USER = gql` - query getUser($userId: String) { + query getUser($userId: String!) { getUser(userId: $userId) { id name { diff --git a/packages/client/src/utils/constants.ts b/packages/client/src/utils/constants.ts index f6bcaff137..a982a362e3 100644 --- a/packages/client/src/utils/constants.ts +++ b/packages/client/src/utils/constants.ts @@ -62,10 +62,7 @@ export const SIGNATURE_KEYS = [ 'informantsSignature' ] as const -export const PAGE_TRANSITIONS_CLASSNAME = 'page-transition' -export const PAGE_TRANSITIONS_ENTER_TIME = 500 -export const PAGE_TRANSITIONS_EXIT_TIME = PAGE_TRANSITIONS_ENTER_TIME - 10 - +export const SYNC_WORKQUEUE_TIME = 500 export const REFRESH_TOKEN_CHECK_MILLIS = 4 * 60 * 1000 // 4 minutes export const TOKEN_EXPIRE_MILLIS = 10 * 60 * 1000 // 10 minutes diff --git a/packages/client/src/utils/draftUtils.test.ts b/packages/client/src/utils/draftUtils.test.ts index b7be4734d5..d924be70e3 100644 --- a/packages/client/src/utils/draftUtils.test.ts +++ b/packages/client/src/utils/draftUtils.test.ts @@ -8,7 +8,7 @@ * * Copyright (C) The OpenCRVS Authors located at https://github.com/opencrvs/opencrvs-core/blob/master/AUTHORS. */ -import { Event } from '@client/utils/gateway' +import { EventType } from '@client/utils/gateway' import { getDeclarationFullName, transformSearchQueryDataToDraft @@ -33,7 +33,7 @@ describe('draftUtils tests', () => { familyNameEng: 'Hoque' } }, - event: Event.Birth, + event: EventType.Birth, savedOn: 1558037863335, modifiedOn: 1558037867987 }) @@ -51,7 +51,7 @@ describe('draftUtils tests', () => { familyNameEng: 'Hoque' } }, - event: Event.Birth, + event: EventType.Birth, savedOn: 1558037863335, modifiedOn: 1558037867987 }, @@ -72,7 +72,7 @@ describe('draftUtils tests', () => { familyNameEng: 'Hoque' } }, - event: Event.Death, + event: EventType.Death, savedOn: 1558037863335, modifiedOn: 1558037867987 }) @@ -91,7 +91,7 @@ describe('draftUtils tests', () => { familyNameEng: 'Hoque' } }, - event: Event.Death, + event: EventType.Death, savedOn: 1558037863335, modifiedOn: 1558037867987 }, diff --git a/packages/client/src/utils/draftUtils.ts b/packages/client/src/utils/draftUtils.ts index 47dfe4dbe5..3b5a701dee 100644 --- a/packages/client/src/utils/draftUtils.ts +++ b/packages/client/src/utils/draftUtils.ts @@ -10,11 +10,12 @@ */ import { IDeclaration, - SUBMISSION_STATUS, - IPrintableDeclaration + IPrintableDeclaration, + SUBMISSION_STATUS } from '@client/declarations' import { IFormSectionData } from '@client/forms' -import { Event, History, RegStatus } from '@client/utils/gateway' +import { EMPTY_STRING } from '@client/utils/constants' +import { EventType, History, RegStatus } from '@client/utils/gateway' import type { GQLBirthEventSearchSet, GQLDeathEventSearchSet, @@ -23,7 +24,6 @@ import type { } from '@client/utils/gateway-deprecated-do-not-use' import { getEvent } from '@client/views/PrintCertificate/utils' import { includes } from 'lodash' -import { EMPTY_STRING } from '@client/utils/constants' const getEngName = ( sectionData: IFormSectionData, @@ -78,11 +78,11 @@ export const getDeclarationFullName = ( lastNameFirst?: boolean ) => { switch (draft.event) { - case Event.Birth: + case EventType.Birth: return getFullName(draft.data.child, language, lastNameFirst) - case Event.Death: + case EventType.Death: return getFullName(draft.data.deceased, language, lastNameFirst) - case Event.Marriage: + case EventType.Marriage: const brideName = getFullName(draft.data.bride, language, lastNameFirst) const groomName = getFullName(draft.data.groom, language, lastNameFirst) if (brideName && groomName) { @@ -262,14 +262,14 @@ export const transformSearchQueryDataToDraft = ( data.registration?.createdAt && data.registration.createdAt switch (eventType) { - case Event.Birth: + case EventType.Birth: default: transformBirthSearchQueryDataToDraft(data, declaration) break - case Event.Death: + case EventType.Death: transformDeathSearchQueryDataToDraft(data, declaration) break - case Event.Marriage: + case EventType.Marriage: transformMarriageSearchQueryDataToDraft(data, declaration) break } diff --git a/packages/client/src/utils/gateway.ts b/packages/client/src/utils/gateway.ts index 2381b895e7..ccc4153714 100644 --- a/packages/client/src/utils/gateway.ts +++ b/packages/client/src/utils/gateway.ts @@ -35,11 +35,18 @@ export type Scalars = { Int: number Float: number Date: any + DateTime: any FieldValue: any Map: any PlainDate: PlainDate } +export type Action = + | CreateAction + | DeclareAction + | NotifyAction + | RegisterAction + export type AdditionalIdWithCompositionId = { __typename?: 'AdditionalIdWithCompositionId' compositionId: Scalars['String'] @@ -122,7 +129,7 @@ export type AdvancedSeachParameters = { deceasedIdentifier?: Maybe declarationJurisdictionId?: Maybe declarationLocationId?: Maybe - event?: Maybe + event?: Maybe eventCountry?: Maybe eventLocationId?: Maybe eventLocationLevel1?: Maybe @@ -189,7 +196,7 @@ export type AdvancedSearchParametersInput = { deceasedIdentifier?: InputMaybe declarationJurisdictionId?: InputMaybe declarationLocationId?: InputMaybe - event?: InputMaybe + event?: InputMaybe eventCountry?: InputMaybe eventLocationId?: InputMaybe eventLocationLevel1?: InputMaybe @@ -230,6 +237,10 @@ export type AdvancedSearchParametersInput = { trackingId?: InputMaybe } +export type ApproveCorrectionActionInput = { + data: Array +} + export type AssignmentData = { __typename?: 'AssignmentData' avatarURL: Scalars['String'] @@ -403,6 +414,10 @@ export type CertificationMetric = { total: Scalars['Float'] } +export type CertifyActionInput = { + data: Array +} + export type Comment = { __typename?: 'Comment' comment?: Maybe @@ -428,6 +443,12 @@ export type ComparisonInput = { nin?: InputMaybe> } +export type ConfirmRegistrationInput = { + error?: InputMaybe + identifiers?: InputMaybe> + registrationNumber: Scalars['String'] +} + export type ContactPoint = { __typename?: 'ContactPoint' system?: Maybe @@ -482,6 +503,14 @@ export type CorrectionValueInput = { section: Scalars['String'] } +export type CreateAction = { + __typename?: 'CreateAction' + createdAt: Scalars['DateTime'] + createdBy: Scalars['String'] + data: Array + type: Scalars['String'] +} + export type CreatedIds = { __typename?: 'CreatedIds' compositionId?: Maybe @@ -565,6 +594,19 @@ export type DeclarationsStartedMetrics = { officeDeclarations: Scalars['Int'] } +export type DeclareAction = { + __typename?: 'DeclareAction' + createdAt: Scalars['DateTime'] + createdBy: Scalars['String'] + data: Array + identifiers: Identifiers + type: Scalars['String'] +} + +export type DeclareActionInput = { + data: Array +} + export type Dummy = { __typename?: 'Dummy' dummy: Scalars['String'] @@ -585,10 +627,17 @@ export type Estimation = { totalEstimation: Scalars['Float'] } -export enum Event { - Birth = 'birth', - Death = 'death', - Marriage = 'marriage' +export type Event = { + __typename?: 'Event' + actions: Array + createdAt: Scalars['DateTime'] + id: Scalars['String'] + type: Scalars['String'] + updatedAt: Scalars['DateTime'] +} + +export type EventInput = { + type: Scalars['String'] } export type EventMetrics = { @@ -678,6 +727,12 @@ export type EventSearchSet = { type?: Maybe } +export enum EventType { + Birth = 'birth', + Death = 'death', + Marriage = 'marriage' +} + export type FhiridMap = { composition?: InputMaybe encounter?: InputMaybe @@ -686,6 +741,17 @@ export type FhiridMap = { questionnaireResponse?: InputMaybe } +export type Field = { + __typename?: 'Field' + id: Scalars['String'] + value: Scalars['FieldValue'] +} + +export type FieldInput = { + id: Scalars['String'] + value: Scalars['FieldValue'] +} + export enum Gender { Female = 'female', Male = 'male', @@ -746,6 +812,17 @@ export type Identifier = { value?: Maybe } +export type IdentifierInput = { + type: Scalars['String'] + value: Scalars['String'] +} + +export type Identifiers = { + __typename?: 'Identifiers' + registrationNumber: Scalars['String'] + trackingId: Scalars['String'] +} + export type IdentityInput = { fieldsModifiedByIdentity?: InputMaybe>> id?: InputMaybe @@ -776,10 +853,13 @@ export type IntegratedSystem = { } export enum IntegratingSystemType { - Mosip = 'MOSIP', Other = 'OTHER' } +export type IssueActionInput = { + data: Array +} + export type LabelInput = { label: Scalars['String'] lang: Scalars['String'] @@ -926,10 +1006,12 @@ export type Mutation = { __typename?: 'Mutation' activateUser?: Maybe approveBirthRegistrationCorrection: Scalars['ID'] + approveCorrectionEvent: Event approveDeathRegistrationCorrection: Scalars['ID'] approveMarriageRegistrationCorrection: Scalars['ID'] auditUser?: Maybe bookmarkAdvancedSearch?: Maybe + certifyEvent: Event changeAvatar?: Maybe changeEmail?: Maybe changePassword?: Maybe @@ -939,11 +1021,14 @@ export type Mutation = { createBirthRegistrationCorrection: Scalars['ID'] createDeathRegistration: CreatedIds createDeathRegistrationCorrection: Scalars['ID'] + createEvent: Event createMarriageRegistration: CreatedIds createMarriageRegistrationCorrection: Scalars['ID'] createOrUpdateUser: User deactivateSystem?: Maybe + declareEvent: Event deleteSystem?: Maybe + issueEvent: Event markBirthAsCertified: Scalars['ID'] markBirthAsIssued: Scalars['ID'] markBirthAsRegistered: Scalars['ID'] @@ -964,14 +1049,22 @@ export type Mutation = { markMarriageAsIssued: Scalars['ID'] markMarriageAsRegistered: Scalars['ID'] markMarriageAsValidated?: Maybe + notifyEvent: Event reactivateSystem?: Maybe refreshSystemSecret?: Maybe + registerEvent: Event registerSystem?: Maybe + reinstateEvent: Event + rejectCorrectionEvent: Event + rejectRegistration: Scalars['ID'] rejectRegistrationCorrection: Scalars['ID'] removeBookmarkedAdvancedSearch?: Maybe + requestCorrectionEvent: Event requestRegistrationCorrection: Scalars['ID'] resendInvite?: Maybe resetPasswordInvite?: Maybe + revokeCorrectionEvent: Event + revokeEvent: Event updateDeathRegistration: Scalars['ID'] updatePermissions?: Maybe updateRole: Response @@ -989,6 +1082,11 @@ export type MutationApproveBirthRegistrationCorrectionArgs = { id: Scalars['ID'] } +export type MutationApproveCorrectionEventArgs = { + eventId: Scalars['ID'] + input: ApproveCorrectionActionInput +} + export type MutationApproveDeathRegistrationCorrectionArgs = { details: DeathRegistrationInput id: Scalars['ID'] @@ -1010,6 +1108,11 @@ export type MutationBookmarkAdvancedSearchArgs = { bookmarkSearchInput: BookmarkSearchInput } +export type MutationCertifyEventArgs = { + eventId: Scalars['ID'] + input: CertifyActionInput +} + export type MutationChangeAvatarArgs = { avatar: AvatarInput userId: Scalars['String'] @@ -1036,6 +1139,7 @@ export type MutationChangePhoneArgs = { } export type MutationConfirmRegistrationArgs = { + details: ConfirmRegistrationInput id: Scalars['ID'] } @@ -1057,6 +1161,10 @@ export type MutationCreateDeathRegistrationCorrectionArgs = { id: Scalars['ID'] } +export type MutationCreateEventArgs = { + event: EventInput +} + export type MutationCreateMarriageRegistrationArgs = { details: MarriageRegistrationInput } @@ -1074,10 +1182,20 @@ export type MutationDeactivateSystemArgs = { clientId: Scalars['ID'] } +export type MutationDeclareEventArgs = { + eventId: Scalars['ID'] + input: DeclareActionInput +} + export type MutationDeleteSystemArgs = { clientId: Scalars['ID'] } +export type MutationIssueEventArgs = { + eventId: Scalars['ID'] + input: IssueActionInput +} + export type MutationMarkBirthAsCertifiedArgs = { details: BirthRegistrationInput id: Scalars['ID'] @@ -1180,6 +1298,11 @@ export type MutationMarkMarriageAsValidatedArgs = { id: Scalars['ID'] } +export type MutationNotifyEventArgs = { + eventId: Scalars['ID'] + input: NotifyActionInput +} + export type MutationReactivateSystemArgs = { clientId: Scalars['ID'] } @@ -1188,10 +1311,30 @@ export type MutationRefreshSystemSecretArgs = { clientId: Scalars['String'] } +export type MutationRegisterEventArgs = { + eventId: Scalars['ID'] + input: RegisterActionInput +} + export type MutationRegisterSystemArgs = { system?: InputMaybe } +export type MutationReinstateEventArgs = { + eventId: Scalars['ID'] + input: ReinstateActionInput +} + +export type MutationRejectCorrectionEventArgs = { + eventId: Scalars['ID'] + input: RejectCorrectionActionInput +} + +export type MutationRejectRegistrationArgs = { + details: RejectRegistrationInput + id: Scalars['ID'] +} + export type MutationRejectRegistrationCorrectionArgs = { details: CorrectionRejectionInput id: Scalars['ID'] @@ -1201,6 +1344,11 @@ export type MutationRemoveBookmarkedAdvancedSearchArgs = { removeBookmarkedSearchInput: RemoveBookmarkedSeachInput } +export type MutationRequestCorrectionEventArgs = { + eventId: Scalars['ID'] + input: RequestCorrectionActionInput +} + export type MutationRequestRegistrationCorrectionArgs = { details: CorrectionInput id: Scalars['ID'] @@ -1214,6 +1362,16 @@ export type MutationResetPasswordInviteArgs = { userId: Scalars['String'] } +export type MutationRevokeCorrectionEventArgs = { + eventId: Scalars['ID'] + input: RevokeCorrectionActionInput +} + +export type MutationRevokeEventArgs = { + eventId: Scalars['ID'] + input: RevokeActionInput +} + export type MutationUpdateDeathRegistrationArgs = { details: DeathRegistrationInput id: Scalars['ID'] @@ -1241,6 +1399,18 @@ export enum NotificationType { Sms = 'SMS' } +export type NotifyAction = { + __typename?: 'NotifyAction' + createdAt: Scalars['DateTime'] + createdBy: Scalars['String'] + data: Array + type: Scalars['String'] +} + +export type NotifyActionInput = { + data: Array +} + export type ObservationFhirids = { attendantAtBirth?: InputMaybe birthType?: InputMaybe @@ -1368,6 +1538,7 @@ export type Query = { fetchRegistrationForViewing?: Maybe fetchSystem?: Maybe getDeclarationsStartedMetrics?: Maybe + getEvent: Event getEventsWithProgress?: Maybe getLocationStatistics?: Maybe getRegistrationsListByFilter?: Maybe @@ -1453,6 +1624,10 @@ export type QueryGetDeclarationsStartedMetricsArgs = { timeStart: Scalars['String'] } +export type QueryGetEventArgs = { + eventId: Scalars['ID'] +} + export type QueryGetEventsWithProgressArgs = { compositionType?: InputMaybe>> count?: InputMaybe @@ -1514,7 +1689,7 @@ export type QueryGetTotalPaymentsArgs = { } export type QueryGetUserArgs = { - userId?: InputMaybe + userId: Scalars['String'] } export type QueryGetUserAuditLogArgs = { @@ -1526,11 +1701,11 @@ export type QueryGetUserAuditLogArgs = { } export type QueryGetUserByEmailArgs = { - email?: InputMaybe + email: Scalars['String'] } export type QueryGetUserByMobileArgs = { - mobile?: InputMaybe + mobile: Scalars['String'] } export type QueryIsLeafLevelLocationArgs = { @@ -1685,6 +1860,19 @@ export type RegWorkflowInput = { user?: InputMaybe } +export type RegisterAction = { + __typename?: 'RegisterAction' + createdAt: Scalars['DateTime'] + createdBy: Scalars['String'] + data: Array + identifiers: Identifiers + type: Scalars['String'] +} + +export type RegisterActionInput = { + data: Array +} + export type Registration = { __typename?: 'Registration' _fhirID?: Maybe @@ -1773,12 +1961,25 @@ export enum RegistrationType { Marriage = 'MARRIAGE' } +export type ReinstateActionInput = { + data: Array +} + export type Reinstated = { __typename?: 'Reinstated' registrationStatus?: Maybe taskEntryResourceID: Scalars['ID'] } +export type RejectCorrectionActionInput = { + data: Array +} + +export type RejectRegistrationInput = { + comment?: InputMaybe + reason: Scalars['String'] +} + export type RelatedPerson = { __typename?: 'RelatedPerson' _fhirID?: Maybe @@ -1841,11 +2042,23 @@ export type RemoveBookmarkedSeachInput = { userId: Scalars['String'] } +export type RequestCorrectionActionInput = { + data: Array +} + export type Response = { __typename?: 'Response' roleIdMap: Scalars['Map'] } +export type RevokeActionInput = { + data: Array +} + +export type RevokeCorrectionActionInput = { + data: Array +} + export type Role = { __typename?: 'Role' _id: Scalars['ID'] @@ -2000,7 +2213,6 @@ export enum SystemStatus { export enum SystemType { Health = 'HEALTH', - NationalId = 'NATIONAL_ID', RecordSearch = 'RECORD_SEARCH', Webhook = 'WEBHOOK' } @@ -2324,7 +2536,7 @@ export type GetSystemRolesQuery = { export type AdvancedSeachParametersFragment = { __typename?: 'AdvancedSeachParameters' - event?: Event | null + event?: EventType | null name?: string | null registrationStatuses?: Array | null dateOfEvent?: string | null @@ -2395,7 +2607,7 @@ export type BookmarkAdvancedSearchMutation = { name: string parameters: { __typename?: 'AdvancedSeachParameters' - event?: Event | null + event?: EventType | null name?: string | null registrationStatuses?: Array | null dateOfEvent?: string | null @@ -2469,7 +2681,7 @@ export type RemoveBookmarkedAdvancedSearchMutation = { name: string parameters: { __typename?: 'AdvancedSeachParameters' - event?: Event | null + event?: EventType | null name?: string | null registrationStatuses?: Array | null dateOfEvent?: string | null @@ -2586,7 +2798,7 @@ export type FetchUserQuery = { name: string parameters: { __typename?: 'AdvancedSeachParameters' - event?: Event | null + event?: EventType | null name?: string | null registrationStatuses?: Array | null dateOfEvent?: string | null @@ -2885,7 +3097,7 @@ export type GetUserAuditLogQuery = { } export type GetUserQueryVariables = Exact<{ - userId?: InputMaybe + userId: Scalars['String'] }> export type GetUserQuery = { @@ -6937,7 +7149,7 @@ export type ChangeEmailMutation = { } export type GetUserByMobileQueryVariables = Exact<{ - mobile?: InputMaybe + mobile: Scalars['String'] }> export type GetUserByMobileQuery = { @@ -6955,7 +7167,7 @@ export type GetUserByMobileQuery = { } export type GetUserByEmailQueryVariables = Exact<{ - email?: InputMaybe + email: Scalars['String'] }> export type GetUserByEmailQuery = { diff --git a/packages/client/src/utils/locationUtils.ts b/packages/client/src/utils/locationUtils.ts index 10717a3747..8036befa46 100644 --- a/packages/client/src/utils/locationUtils.ts +++ b/packages/client/src/utils/locationUtils.ts @@ -274,7 +274,11 @@ export function generateFullAddress( const eventLocationLevel5 = address?.line?.[12] && offlineData.locations[address.line[12]]?.name + const eventLocationLevel6 = + address?.line?.[13] && offlineData.locations[address.line[13]]?.name + return [ + eventLocationLevel6, eventLocationLevel5, eventLocationLevel4, eventLocationLevel3, diff --git a/packages/client/src/utils/referenceApi.ts b/packages/client/src/utils/referenceApi.ts index 341257463b..b2343d90c8 100644 --- a/packages/client/src/utils/referenceApi.ts +++ b/packages/client/src/utils/referenceApi.ts @@ -10,6 +10,7 @@ */ import { ISerializedForm } from '@client/forms' import { Conditional } from '@client/forms/conditionals' +import { Validator } from '@client/forms/validators' import { ILanguage } from '@client/i18n/reducer' import { AdminStructure, @@ -18,8 +19,7 @@ import { ILocation } from '@client/offline/reducer' import { getToken } from '@client/utils/authUtils' -import { Event, System } from '@client/utils/gateway' -import { Validator } from '@client/forms/validators' +import { EventType, System } from '@client/utils/gateway' import { IntlShape } from 'react-intl' export interface ILocationDataResponse { @@ -78,7 +78,7 @@ interface ILoginBackground { imageFit?: string } export interface ICertificateTemplateData { - event: Event + event: EventType svgCode: string } export interface ICurrency { diff --git a/packages/client/src/utils/timeoutLink.test.ts b/packages/client/src/utils/timeoutLink.test.ts deleted file mode 100644 index 79b6a5109d..0000000000 --- a/packages/client/src/utils/timeoutLink.test.ts +++ /dev/null @@ -1,112 +0,0 @@ -/* - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at https://mozilla.org/MPL/2.0/. - * - * OpenCRVS is also distributed under the terms of the Civil Registration - * & Healthcare Disclaimer located at http://opencrvs.org/license. - * - * Copyright (C) The OpenCRVS Authors located at https://github.com/opencrvs/opencrvs-core/blob/master/AUTHORS. - */ -import TimeoutLink from '@client/utils/timeoutLink' -import { - gql, - ApolloLink, - Observable, - Operation, - execute, - GraphQLRequest, - FetchResult -} from '@apollo/client' - -const testOperation: GraphQLRequest = { - query: gql` - query { - hello - } - `, - operationName: 'testQuery', - variables: {}, - context: {}, - extensions: {} -} - -const fastResponseLink = new ApolloLink((operation: Operation) => { - return new Observable((observer) => { - new Promise((resolve) => { - setTimeout(() => resolve({ response: true }), 100) - }).then((res) => - observer.next( - res as FetchResult< - { [key: string]: any }, - Record, - Record - > - ) - ) - }) -}) - -const slowResponseLink = new ApolloLink((operation: Operation) => { - return new Observable((observer) => { - new Promise((resolve) => { - setTimeout(() => resolve({ response: true }), 300) - }).then((res) => - observer.next( - res as FetchResult< - { [key: string]: any }, - Record, - Record - > - ) - ) - }) -}) - -const timeoutLink = new TimeoutLink(200) -const fakeTimeoutLink = new TimeoutLink(-1) - -const composedPassingLink = timeoutLink.concat(fastResponseLink) -const composedFailingLink = timeoutLink.concat(slowResponseLink) -const composedTimelessLink = fakeTimeoutLink.concat(slowResponseLink) - -describe('tests for timeout link', () => { - it.skip('request served within timeout', (done) => { - execute(composedPassingLink, testOperation).subscribe({ - next: (data) => { - expect(data).toEqual({ response: true }) - done() - }, - error: (e) => { - expect(e).toBe(null) - done() - } - }) - }) - - it.skip('resquest aborted with error when exceeds timeout', (done) => { - execute(composedFailingLink, testOperation).subscribe({ - next: (data) => { - expect(data).toBe(null) - done() - }, - error: (e) => { - expect(e.message).toBe('Timeout exceeded for query "testQuery"') - done() - } - }) - }) - - it.skip('skips timeout link when timeout is explicitly set <0 even if slow response', (done) => { - execute(composedTimelessLink, testOperation).subscribe({ - next: (data) => { - expect(data).toEqual({ response: true }) - done() - }, - error: (e) => { - expect(e).toBe(null) - done() - } - }) - }) -}) diff --git a/packages/client/src/v2-events/.eslintrc.js b/packages/client/src/v2-events/.eslintrc.js index bef662819b..556e99e91d 100644 --- a/packages/client/src/v2-events/.eslintrc.js +++ b/packages/client/src/v2-events/.eslintrc.js @@ -13,7 +13,17 @@ module.exports = { 'no-restricted-imports': [ 'error', { - patterns: ['@client/*', '!@client/v2-events', '!@client/components'] + patterns: [ + '@client/*', + '!@client/v2-events', + '!@client/components', + '!@client/utils', + '!@client/navigation', + '!@client/storage', + '!@client/forms', + '!@client/i18n', + '!@client/search' + ] } ] } diff --git a/packages/client/src/v2-events/components/forms/FormFieldGenerator.tsx b/packages/client/src/v2-events/components/forms/FormFieldGenerator.tsx new file mode 100644 index 0000000000..6f7e8ac318 --- /dev/null +++ b/packages/client/src/v2-events/components/forms/FormFieldGenerator.tsx @@ -0,0 +1,835 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * + * OpenCRVS is also distributed under the terms of the Civil Registration + * & Healthcare Disclaimer located at http://opencrvs.org/license. + * + * Copyright (C) The OpenCRVS Authors located at https://github.com/opencrvs/opencrvs-core/blob/master/AUTHORS. + */ +import { FetchButtonField } from '@client/components/form/FetchButton' +import { InputField } from '@client/components/form/InputField' +import { + BIG_NUMBER, + BULLET_LIST, + BUTTON, + CHECKBOX, + CHECKBOX_GROUP, + DATE, + DATE_RANGE_PICKER, + DependencyInfo, + DIVIDER, + FETCH_BUTTON, + FIELD_GROUP_TITLE, + FIELD_WITH_DYNAMIC_DEFINITIONS, + HEADING3, + HIDDEN, + HTTP, + IDateRangePickerValue, + IDynamicFormField, + IFormField, + IFormFieldValue, + IFormSectionData, + Ii18nFormField, + Ii18nTextFormField, + InitialValue, + LINK, + LOCATION_SEARCH_INPUT, + NUMBER, + PARAGRAPH, + RADIO_GROUP, + SELECT_WITH_DYNAMIC_OPTIONS, + SELECT_WITH_OPTIONS, + SUBSECTION_HEADER, + TEL, + TEXT, + TEXTAREA, + TIME, + WARNING +} from '@client/forms' +import { buttonMessages } from '@client/i18n/messages/buttons' +import { IAdvancedSearchFormState } from '@client/search/advancedSearch/utils' +import { Checkbox, CheckboxGroup } from '@opencrvs/components/lib/Checkbox' +import { DateField } from '@opencrvs/components/lib/DateField' +import { ErrorText } from '@opencrvs/components/lib/ErrorText' +import { Link } from '@opencrvs/components/lib/Link' +import { RadioGroup } from '@opencrvs/components/lib/Radio' +import { Select } from '@opencrvs/components/lib/Select' +import { Text } from '@opencrvs/components/lib/Text' +import { TextArea } from '@opencrvs/components/lib/TextArea' +import { TextInput } from '@opencrvs/components/lib/TextInput' +import { TimeField } from '@opencrvs/components/lib/TimeField' +import * as React from 'react' +import styled, { keyframes } from 'styled-components' +import { + evalExpressionInFieldDefinition, + flatten, + getConditionalActionsForField, + getDependentFields, + getFieldType, + handleInitialValue, + internationaliseFieldObject, + unflatten +} from './utils' +import { Errors, getValidationErrorsForForm } from './validation' + +import { DateRangePickerForFormField } from '@client/components/DateRangePickerForFormField' + +import { isMobileDevice } from '@client/utils/commonUtils' +import { REGEXP_NUMBER_INPUT_NON_NUMERIC } from '@client/utils/constants' +import { BulletList, Divider } from '@opencrvs/components' +import { Heading2, Heading3 } from '@opencrvs/components/lib/Headings/Headings' +import { LocationSearch } from '@opencrvs/components/lib/LocationSearch' +import { + Field, + FieldProps, + Formik, + FormikProps, + FormikTouched, + FormikValues +} from 'formik' +import { cloneDeep, isEqual, set } from 'lodash' +import { + WrappedComponentProps as IntlShapeProps, + MessageDescriptor, + useIntl +} from 'react-intl' + +const fadeIn = keyframes` + from { opacity: 0; } + to { opacity: 1; } +` + +const FormItem = styled.div<{ + ignoreBottomMargin?: boolean +}>` + animation: ${fadeIn} 500ms; + margin-bottom: ${({ ignoreBottomMargin }) => + ignoreBottomMargin ? '0px' : '22px'}; +` + +function handleSelectFocus(id: string, isSearchable: boolean) { + if (isMobileDevice() && isSearchable) { + setTimeout(() => { + const inputElement = document.getElementById(`${id}-form-input`) + + if (inputElement) { + inputElement.scrollIntoView({ + behavior: 'smooth' + }) + } + }, 20) + } +} + +type GeneratedInputFieldProps = { + fieldDefinition: Ii18nFormField + fields: IFormField[] + values: IFormSectionData + setFieldValue: (name: string, value: IFormFieldValue) => void + onClick?: () => void + onChange: (e: React.ChangeEvent) => void + onBlur: (e: React.FocusEvent) => void + resetDependentSelectValues: (name: string) => void + value: IFormFieldValue + touched: boolean + error: string + formData: IFormSectionData + disabled?: boolean + onUploadingStateChanged?: (isUploading: boolean) => void + requiredErrorMessage?: MessageDescriptor + setFieldTouched: (name: string, isTouched?: boolean) => void +} + +const GeneratedInputField = React.memo( + ({ + fieldDefinition, + onChange, + onBlur, + setFieldValue, + resetDependentSelectValues, + error, + touched, + value, + formData, + disabled, + setFieldTouched, + requiredErrorMessage, + fields, + values + }) => { + const inputFieldProps = { + id: fieldDefinition.name, + label: fieldDefinition.label, + helperText: fieldDefinition.helperText, + tooltip: fieldDefinition.tooltip, + description: fieldDefinition.description, + required: fieldDefinition.required, + disabled: fieldDefinition.disabled, + prefix: fieldDefinition.prefix, + postfix: fieldDefinition.postfix, + unit: fieldDefinition.unit, + hideAsterisk: fieldDefinition.hideAsterisk, + hideInputHeader: fieldDefinition.hideHeader, + error, + touched + } + + const intl = useIntl() + const onChangeGroupInput = React.useCallback( + (val: string) => setFieldValue(fieldDefinition.name, val), + [fieldDefinition.name, setFieldValue] + ) + + const inputProps = { + id: fieldDefinition.name, + onChange, + onBlur, + value, + disabled: fieldDefinition.disabled ?? disabled, + error: Boolean(error), + touched: Boolean(touched), + placeholder: fieldDefinition.placeholder + } + if (fieldDefinition.type === SELECT_WITH_OPTIONS) { + return ( + +