From 3d37537cd8103d87cc25ca5226cf1553814a0734 Mon Sep 17 00:00:00 2001 From: Peter Muriuki Date: Mon, 11 Dec 2023 14:56:03 +0300 Subject: [PATCH] Disable button when invalid form and submitting, Refactor mission data download (#1313) * Disable button when invalid form and submitting * Refactor mission data download * Remove surplus test suites * Update snapshots probably regressed in previous i18n changes --- .../tests/__snapshots__/index.test.tsx.snap | 2 +- .../tests/__snapshots__/index.test.tsx.snap | 2 +- .../tests/__snapshots__/index.test.tsx.snap | 6 +-- .../src/components/LocationForm/index.tsx | 43 +++++++++++++++---- .../tests/__snapshots__/index.test.tsx.snap | 2 +- .../src/components/MissionData/index.tsx | 35 +++++++++++++-- .../MissionData/tests/index.test.tsx | 5 +-- .../tests/__snapshots__/index.test.tsx.snap | 2 - .../src/helpers/tests/utils.test.tsx | 13 +----- packages/opensrp-plans/src/helpers/utils.tsx | 38 +++++++++++++++- 10 files changed, 109 insertions(+), 39 deletions(-) diff --git a/packages/inventory/src/components/PostConfirmationSuccess/tests/__snapshots__/index.test.tsx.snap b/packages/inventory/src/components/PostConfirmationSuccess/tests/__snapshots__/index.test.tsx.snap index edc1d3119..2b219ad59 100644 --- a/packages/inventory/src/components/PostConfirmationSuccess/tests/__snapshots__/index.test.tsx.snap +++ b/packages/inventory/src/components/PostConfirmationSuccess/tests/__snapshots__/index.test.tsx.snap @@ -2,4 +2,4 @@ exports[`post confirmation success card works correctly: card title 1`] = `"“processed.csv” inventory items successfully added"`; -exports[`post confirmation success card works correctly: full snapshot 1`] = `"“processed.csv” inventory items successfully added5 inventory items added to Service point inventory.  Inventory may take a few minutes to appear.Upload another file"`; +exports[`post confirmation success card works correctly: full snapshot 1`] = `"“processed.csv” inventory items successfully added5 inventory items added to Service point inventory.  Inventory may take a few minutes to appear.Upload another file"`; diff --git a/packages/inventory/src/components/PreConfirmationError/tests/__snapshots__/index.test.tsx.snap b/packages/inventory/src/components/PreConfirmationError/tests/__snapshots__/index.test.tsx.snap index 229350edd..6d9a081ab 100644 --- a/packages/inventory/src/components/PreConfirmationError/tests/__snapshots__/index.test.tsx.snap +++ b/packages/inventory/src/components/PreConfirmationError/tests/__snapshots__/index.test.tsx.snap @@ -2,7 +2,7 @@ exports[`pre confirmation error card renders correctly 1`] = `[Function]`; -exports[`pre confirmation error card renders correctly: full general snapshot 1`] = `"Use a CSV file to add service point inventoryplease fix the errors listed below, then retry csv uploadRow numberErrors2Service point ID does not exist3Service point ID does not exist, UNICEF section is not valid, Donor is not valid15 / pageRetry"`; +exports[`pre confirmation error card renders correctly: full general snapshot 1`] = `"Use a CSV file to add service point inventoryplease fix the errors listed below, then retry csv uploadRow numberErrors2Service point ID does not exist3Service point ID does not exist, UNICEF section is not valid, Donor is not valid15 / pageRetry"`; exports[`pre confirmation error card renders correctly: table row 1`] = `"Row numberErrors"`; diff --git a/packages/inventory/src/containers/BulkUpload/tests/__snapshots__/index.test.tsx.snap b/packages/inventory/src/containers/BulkUpload/tests/__snapshots__/index.test.tsx.snap index c0c711e35..08d71709a 100644 --- a/packages/inventory/src/containers/BulkUpload/tests/__snapshots__/index.test.tsx.snap +++ b/packages/inventory/src/containers/BulkUpload/tests/__snapshots__/index.test.tsx.snap @@ -2,13 +2,13 @@ exports[`Inventory bulk upload renders correctly: start upload page 1`] = `"Add inventory via CSVUse a CSV file to add service point inventoryYou’ll get a chance to review before committing inventory updates.Select CSV file"`; -exports[`Inventory bulk upload shows post confirmation error card: post confirmation error page 1`] = `"Add inventory via CSVProcessing error: inventory items failed to be added0 inventory items failed to be added from “”. To add items, follow these steps: Extract the rows listed below from \\"\\"Paste the rows into a new CSV fileUpload the CSV fileInventory items not listed below were successfully added to theService point inventory. Caution: do not re-upload the successful items or duplicates will be created.Inventory items from “” that were not addedRow numberErrorsNo data"`; +exports[`Inventory bulk upload shows post confirmation error card: post confirmation error page 1`] = `"Add inventory via CSVProcessing error: inventory items failed to be added0 inventory items failed to be added from “”. To add items, follow these steps: Extract the rows listed below from \\"\\"Paste the rows into a new CSV fileUpload the CSV fileInventory items not listed below were successfully added to theService point inventory. Caution: do not re-upload the successful items or duplicates will be created.Inventory items from “” that were not addedRow numberErrorsNo data"`; -exports[`Inventory bulk upload shows post confirmation success card: post confirmation success page 1`] = `"Add inventory via CSV“” inventory items successfully added0 inventory items added to Service point inventory.  Inventory may take a few minutes to appear.Upload another file"`; +exports[`Inventory bulk upload shows post confirmation success card: post confirmation success page 1`] = `"Add inventory via CSV“” inventory items successfully added0 inventory items added to Service point inventory.  Inventory may take a few minutes to appear.Upload another file"`; exports[`Inventory bulk upload shows post confirmation upload card: post confirmation upload page 1`] = `"Add inventory via CSVInventory is being added to service points…Inventory may take a few minutes to appear."`; -exports[`Inventory bulk upload shows pre confirmation error page: pre confirmation error page 1`] = `"Add inventory via CSVUse a CSV file to add service point inventoryplease fix the errors listed below, then retry csv uploadRow numberErrorsNo dataRetry"`; +exports[`Inventory bulk upload shows pre confirmation error page: pre confirmation error page 1`] = `"Add inventory via CSVUse a CSV file to add service point inventoryplease fix the errors listed below, then retry csv uploadRow numberErrorsNo dataRetry"`; exports[`Inventory bulk upload shows pre confirmation success page: pre confirmation success page 1`] = `"Add inventory via CSV“” ready0 inventory items will be added to service points. Do you wish to proceed?Proceed with adding inventoryCancel"`; diff --git a/packages/location-management/src/components/LocationForm/index.tsx b/packages/location-management/src/components/LocationForm/index.tsx index 92ff619dc..1d13702b1 100644 --- a/packages/location-management/src/components/LocationForm/index.tsx +++ b/packages/location-management/src/components/LocationForm/index.tsx @@ -1,5 +1,5 @@ import React, { useState } from 'react'; -import { Form, Input, Space, Button, Radio } from 'antd'; +import { Form, Input, Space, Button, Radio, FormInstance } from 'antd'; import { sendErrorNotification, sendSuccessNotification } from '@opensrp/notifications'; import { Redirect } from 'react-router'; import { ExtraFields } from './ExtraFields'; @@ -175,6 +175,7 @@ const LocationForm = (props: LocationFormProps) => { is_jurisdiction: values.isJurisdiction, }; + setSubmitting(true); postPutLocationUnit(payload, opensrpBaseURL, isEditMode, params) .then(() => { afterSubmit(payload); @@ -353,14 +354,7 @@ const LocationForm = (props: LocationFormProps) => { - + @@ -375,3 +369,34 @@ const LocationForm = (props: LocationFormProps) => { LocationForm.defaultProps = defaultProps; export { LocationForm }; + +const SubmitButton = ({ form, isSubmitting }: { form: FormInstance; isSubmitting: boolean }) => { + const { t } = useTranslation(); + const [submittable, setSubmittable] = React.useState(false); + + // Watch all values + const values = Form.useWatch([], form); + + React.useEffect(() => { + form.validateFields({ validateOnly: true }).then( + () => { + setSubmittable(true); + }, + () => { + setSubmittable(false); + } + ); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [values]); + + return ( + + ); +}; diff --git a/packages/location-management/src/components/LocationForm/tests/__snapshots__/index.test.tsx.snap b/packages/location-management/src/components/LocationForm/tests/__snapshots__/index.test.tsx.snap index e3e5eaa36..94207e60c 100644 --- a/packages/location-management/src/components/LocationForm/tests/__snapshots__/index.test.tsx.snap +++ b/packages/location-management/src/components/LocationForm/tests/__snapshots__/index.test.tsx.snap @@ -461,7 +461,7 @@ exports[`LocationForm renders correctly: status label 1`] = ` exports[`LocationForm renders correctly: submit button 1`] = ` - + ) : null; @@ -109,3 +108,31 @@ const MissionData = (props: MissionDataProps) => { MissionData.defaultProps = defaultProps; export { MissionData }; + +// Download Mission button. + +interface DownloadMissionDataProps { + baseUrl: string; + plan: PlanDefinition; +} + +export const DownloadMissionData = (props: DownloadMissionDataProps) => { + const { baseUrl, plan } = props; + const { t } = useTranslation(); + const [downloading, setDownloading] = useState(false); + const handleClick = () => { + setDownloading(true); + downloadMissionData(baseUrl, plan) + .catch(() => { + sendErrorNotification(t('Mission data download failed.')); + }) + .finally(() => { + setDownloading(false); + }); + }; + return ( + + ); +}; diff --git a/packages/opensrp-plans/src/components/MissionData/tests/index.test.tsx b/packages/opensrp-plans/src/components/MissionData/tests/index.test.tsx index bf57372d0..6a2300d1c 100644 --- a/packages/opensrp-plans/src/components/MissionData/tests/index.test.tsx +++ b/packages/opensrp-plans/src/components/MissionData/tests/index.test.tsx @@ -77,10 +77,7 @@ describe('mission data listing & download', () => { `"Mission dataService points visited: 13Products checked: 7Number of flagged products: 3Download mission data"` ); expect(wrapper.find('Button').text()).toEqual('Download mission data'); - // downloads mission data - expect(wrapper.find('a').at(0).props().href).toEqual( - 'https://opensrp-stage.smartregister.org/opensrp/rest/event/export-data?eventTypes=flag_problem,service_point_check,looks_good,record_gps&planIdentifier=335ef7a3-7f35-58aa-8263-4419464946d8' - ); + expect(fetch.mock.calls).toEqual([ [ 'https://opensrp-stage.smartregister.org/opensrp/rest/task/search?planIdentifier=335ef7a3-7f35-58aa-8263-4419464946d8&code=service_point_check&returnTaskCountOnly=true&status=Completed', diff --git a/packages/opensrp-plans/src/containers/UpdatePlan/tests/__snapshots__/index.test.tsx.snap b/packages/opensrp-plans/src/containers/UpdatePlan/tests/__snapshots__/index.test.tsx.snap index 6d46cd137..bf4b1390b 100644 --- a/packages/opensrp-plans/src/containers/UpdatePlan/tests/__snapshots__/index.test.tsx.snap +++ b/packages/opensrp-plans/src/containers/UpdatePlan/tests/__snapshots__/index.test.tsx.snap @@ -1,5 +1,3 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Update plan Page planform is configured correctly: full text snapshot 1`] = `"Edit missionIntervention TypeSupply ManagementPlan TitleStatusactivecompleteretiredActive date rangeDescription0 / 200Add JurisdictionActivitiesProduct CheckActionDescriptionCheck for all products (100%) within the jurisdictionReasonRoutineGoalQuantityunknownStart DateEnd DatePriorityMedium PriorityTriggers and ConditionsFix Product ProblemActionDescriptionFix problems for all products (100%) within the jurisdictionReasonRoutineGoalQuantityunknownStart DateEnd DatePriorityMedium PriorityTriggers and ConditionsRecord GPSActionDescriptionRecord GPS for all service points (100%) without GPS within the jurisdictionReasonRoutineGoalQuantityunknownStart DateEnd DatePriorityMedium PriorityTriggers and ConditionsService Point CheckActionDescriptionConduct checkfor all service points (100%) within the jurisdictionReasonRoutineGoalQuantityunknownStart DateEnd DatePriorityMedium PriorityTriggers and ConditionsSave PlanCancel"`; - exports[`Update plan Page renders correctly with store(for editing plans): full text snapshot 1`] = `"Edit missionIntervention TypeSupply ManagementPlan TitleStatusactivecompleteretiredActive date rangeDescription0 / 200Add JurisdictionActivitiesProduct CheckActionDescriptionCheck for all products (100%) within the jurisdictionReasonRoutineGoalQuantityunknownStart DateEnd DatePriorityMedium PriorityTriggers and ConditionsFix Product ProblemActionDescriptionFix problems for all products (100%) within the jurisdictionReasonRoutineGoalQuantityunknownStart DateEnd DatePriorityMedium PriorityTriggers and ConditionsRecord GPSActionDescriptionRecord GPS for all service points (100%) without GPS within the jurisdictionReasonRoutineGoalQuantityunknownStart DateEnd DatePriorityMedium PriorityTriggers and ConditionsService Point CheckActionDescriptionConduct checkfor all service points (100%) within the jurisdictionReasonRoutineGoalQuantityunknownStart DateEnd DatePriorityMedium PriorityTriggers and ConditionsSave PlanCancel"`; diff --git a/packages/opensrp-plans/src/helpers/tests/utils.test.tsx b/packages/opensrp-plans/src/helpers/tests/utils.test.tsx index f72b4e644..451b22547 100644 --- a/packages/opensrp-plans/src/helpers/tests/utils.test.tsx +++ b/packages/opensrp-plans/src/helpers/tests/utils.test.tsx @@ -2,18 +2,12 @@ import { ACTIVE_PLANS_LIST_VIEW_URL, COMPLETE_PLANS_LIST_VIEW_URL, DRAFT_PLANS_LIST_VIEW_URL, - OPENSRP_API_BASE_URL, SORT_BY_EFFECTIVE_PERIOD_START_FIELD, RETIRED_PLANS_LIST_VIEW_URL, } from '../../constants'; import * as planDefinitionFixtures from '../../ducks/planDefinitions/tests/fixtures'; import { InterventionType, PlanDefinition, PlanStatus } from '@opensrp/plan-form-core'; -import { - descendingOrderSort, - isPlanDefinitionOfType, - getPlanType, - BuildDownloadUrl, -} from '../utils'; +import { descendingOrderSort, isPlanDefinitionOfType, getPlanType } from '../utils'; import { redirectPathGetter } from '../common'; describe('helpers/utils', () => { @@ -76,9 +70,4 @@ describe('helpers/utils', () => { expect(redirectPathGetter(PlanStatus.COMPLETE)).toEqual(COMPLETE_PLANS_LIST_VIEW_URL); expect(redirectPathGetter(PlanStatus.RETIRED)).toEqual(RETIRED_PLANS_LIST_VIEW_URL); }); - it('tests BuildDownloadUrl', () => { - expect(BuildDownloadUrl(OPENSRP_API_BASE_URL, '123')).toEqual( - 'https://opensrp-stage.smartregister.org/opensrp/rest/event/export-data?eventTypes=flag_problem,service_point_check,looks_good,record_gps&planIdentifier=123' - ); - }); }); diff --git a/packages/opensrp-plans/src/helpers/utils.tsx b/packages/opensrp-plans/src/helpers/utils.tsx index 03cc1aadb..b203d41aa 100644 --- a/packages/opensrp-plans/src/helpers/utils.tsx +++ b/packages/opensrp-plans/src/helpers/utils.tsx @@ -9,6 +9,9 @@ import { SERVICE_POINT_CHECK_CODE, RECORD_GPS_CODE, } from '@opensrp/plan-form-core'; +import { HTTPMethod } from '@opensrp/server-service'; +import { getFileNameFromCDHHeader, downloadFile } from '@opensrp/react-utils'; +import { OpenSRPService } from './dataLoaders'; /** * helper to retrieve the plan Type from a plan definition object @@ -62,7 +65,38 @@ export const PlanLoading = () => { return ; }; -export const BuildDownloadUrl = (baseURL: string, planId: string) => { +const getFetchOptions = (_: AbortSignal, accessToken: string, method: HTTPMethod): RequestInit => { + return { + headers: { + authorization: `Bearer ${accessToken}`, + }, + method, + }; +}; + +/** + * download a misisons data. + * + * @param baseURL - opensrp server base url + * @param plan - plan whose mission data we fetching. + */ +export const downloadMissionData = async (baseURL: string, plan: PlanDefinition) => { + const { title, identifier } = plan; + const fileTitle = title.replaceAll(/\\s/g, ' ').split(' ').join('_'); const eventType = `${FLAG_PROBLEM_CODE},${SERVICE_POINT_CHECK_CODE},${LOOKS_GOOD_CODE},${RECORD_GPS_CODE}`; - return `${baseURL}${OPENSRP_TASK_EXPORT_DATA}?eventTypes=${eventType}&planIdentifier=${planId}`; + const exportPath = `${OPENSRP_TASK_EXPORT_DATA}?eventTypes=${eventType}&planIdentifier=${identifier}`; + + const serve = new OpenSRPService(exportPath, baseURL, getFetchOptions); + const response = await serve.download(); + + // get filename from content-disposition header + const contentDispositionHeader = response.headers.get('content-disposition'); + const fileName = contentDispositionHeader + ? getFileNameFromCDHHeader(contentDispositionHeader) + : `${fileTitle}_${Date.now()}.zip`; + + // get blob data from response + const blob = await response.blob(); + + downloadFile(blob, fileName); };