diff --git a/app/src/utils/domain/dref.ts b/app/src/utils/domain/dref.ts index 1b98a1f02..857cfc1f5 100644 --- a/app/src/utils/domain/dref.ts +++ b/app/src/utils/domain/dref.ts @@ -62,11 +62,13 @@ export const nsActionsOrder: Record = { other: 18, }; -export type DrefSheetName = 'Operation Overview' | 'Event Detail' | 'Actions Needs' | 'Operation' | 'Timeframes and Contacts'; +export type DrefSheetName = 'Operation Overview' | 'Event Detail' | 'Actions Needs' | 'Operation' | 'Scenario Analysis' | 'Plan' | 'Timeframes and Contacts'; export const SHEET_OPERATION_OVERVIEW = 'Operation Overview' satisfies DrefSheetName; export const SHEET_EVENT_DETAIL = 'Event Detail' satisfies DrefSheetName; export const SHEET_ACTIONS_NEEDS = 'Actions Needs' satisfies DrefSheetName; export const SHEET_OPERATION = 'Operation' satisfies DrefSheetName; +export const SHEET_SCENARIO_ANALYSIS = 'Scenario Analysis' satisfies DrefSheetName; +export const SHEET_PLAN = 'Plan' satisfies DrefSheetName; export const SHEET_TIMEFRAMES_AND_CONTACTS = 'Timeframes and Contacts' satisfies DrefSheetName; export const DREF_OPTIONS_SHEET_NAME = 'options'; @@ -81,8 +83,8 @@ export function getDrefSheetNames(typeOfDref: TypeOfDrefEnum): DrefSheetName[] { if (typeOfDref === DREF_TYPE_IMMINENT) { return [ SHEET_OPERATION_OVERVIEW, - SHEET_EVENT_DETAIL, - SHEET_OPERATION, + SHEET_SCENARIO_ANALYSIS, + SHEET_PLAN, SHEET_TIMEFRAMES_AND_CONTACTS, ]; } diff --git a/app/src/utils/importTemplate.ts b/app/src/utils/importTemplate.ts index fd92ab6fc..f300bcb75 100644 --- a/app/src/utils/importTemplate.ts +++ b/app/src/utils/importTemplate.ts @@ -39,6 +39,7 @@ interface BaseField { label: string | Segment[]; description?: string | Segment[]; headingBefore?: string; + defaultValue?: string | number | boolean; } interface InputField< @@ -134,6 +135,7 @@ type InputTemplateField = { description?: string | CellRichTextValue; headingBefore?: string; context: { field: string, key: string }[], + defaultValue?: string | number | boolean; } & ({ dataValidation: 'list'; optionsKey: ObjectKey; @@ -288,6 +290,7 @@ export function createImportTemplate< : undefined, outlineLevel, context, + defaultValue: schema.defaultValue, } satisfies InputTemplateField; fields.push(field); @@ -304,6 +307,7 @@ export function createImportTemplate< dataValidation: 'list', optionsKey: schema.optionsKey, context, + defaultValue: schema.defaultValue, } satisfies InputTemplateField; fields.push(field); @@ -420,8 +424,12 @@ export function getValueFromImportTemplate< const updatedValue = value.replace(/(^|\n)\s*\*/g, '$1•'); return updatedValue; } + const isTextField = schema.validation === 'string' + || schema.validation === 'textArea' + || schema.validation === 'date'; + // TODO: add validation from schema.validation - return value; + return isTextField ? value?.toString() : value; } if (schema.type === 'select') { diff --git a/app/src/views/AccountMyFormsDref/DownloadImportTemplateButton/DownloadImportTemplateModal/template/i18n.json b/app/src/views/AccountMyFormsDref/DownloadImportTemplateButton/DownloadImportTemplateModal/template/i18n.json index f7c088e69..3346f3c42 100644 --- a/app/src/views/AccountMyFormsDref/DownloadImportTemplateButton/DownloadImportTemplateModal/template/i18n.json +++ b/app/src/views/AccountMyFormsDref/DownloadImportTemplateButton/DownloadImportTemplateModal/template/i18n.json @@ -272,7 +272,7 @@ "immDisasterTypeLabel": "Type of disaster", "immDisasterTypeDesc": "Select the relevant type of disaster from the drop-down list.", "immTypeOfOnsetLabel": "Type of Onset", - "immTypeOfOnsetDesc": "Select the type of onset from the drop-down list.", + "immTypeOfOnsetDesc": "The type of onset is selected by default.", "immIsManMadeEventLabel": "Is this a man made event?", "immIsManMadeEventDesc": "Select Yes or No from the drop-down list.", "immCountryLabel": "Affected Country", @@ -280,12 +280,13 @@ "immTitleLabel": "DREF Title", "immDescriptionOfTheHazardHeading": "Description of the Hazard", "immHazardDateLabel": "Date when the trigger was met / is expected to be met", - "immHazardDateDesc": "DD/MM/YYYY. Must be today or a future date.", - "immHazardDateAndLocationLabel": "Location and approximate date of the hazard", - "immHazardVulnerabilitiesAndRisksLabel": "Target communities’ vulnerabilities and exposure to the hazard", - "immHazardVulnerabilitiesAndRisksDesc": "Describe the anticipated humanitarian impact and which people are most likely to be affected and why.", + "immHazardDateDesc": "MM/DD/YYYY. Must be today or a future date.", + "immHazardDateAndLocationLabel": "When and where is the hazard expected to happen?", + "immHazardDateAndLocationDesc": "Include here the forecasted date of impact as well as the geographical areas at risk.", + "immHazardVulnerabilitiesAndRisksLabel": "Explain the underlying vulnerabilities and risks the hazard poses for at-risk communities?", + "immHazardVulnerabilitiesAndRisksDesc": "Based on comparison of past events, what humanitarian impacts do you expect? Of what magnitude? (e.g. last time there was a cyclone making landfall with this windspeed, XX houses were destroyed, and we had to launch a DREF/emergency appeal for CHF xxx).", "immNumAffectedLabel": "Total population likely to be affected", - "immNumAffectedDesc": "People likely to be affected as a direct result of the anticipated event.", + "immNumAffectedDesc": "Includes all those whose lives and livelihoods are at risk as a direct result of the shock or stress.", "immEstimatedNumberOfAffectedMaleLabel": "Estimated number of affected male", "immEstimatedNumberOfAffectedFemaleLabel": "Estimated number of affected female", "immEstimatedNumberOfAffectedGirlsUnder18Label": "Estimated number of affected girls (under 18)", @@ -307,22 +308,14 @@ "immIsSurgePersonnelDeployedLabel": "Will surge personnel be deployed?", "immIsSurgePersonnelDeployedDesc": "Select Yes or No from the drop-down list.", "immSurgePersonnelDeployedLabel": "Role profile of the deployed personnel", - "immSurgePersonnelDeployedDesc": "Complete only if surge personnel will be deployed.", - "immPoliciesHeading": "Policies", - "immHasAntiFraudCorruptionPolicyLabel": "Does your National Society have anti-fraud and corruption policy?", - "immHasSexualAbusePolicyLabel": "Does your National Society have prevention of sexual exploitation and abuse policy?", - "immHasChildProtectionPolicyLabel": "Does your National Society have child protection/child safeguarding policy?", - "immHasWhistleblowerProtectionPolicyLabel": "Does your National Society have whistleblower protection policy?", - "immHasAntiSexualHarassmentPolicyLabel": "Does your National Society have anti-sexual harassment policy?", - "immAddressedHumanitarianImpactsLabel": "Addressed humanitarian impacts", - "immAddressedHumanitarianImpactsDesc": "Describe the humanitarian impacts the operation aims to address through the proposed early actions and early response.", + "immSurgePersonnelDeployedDesc": "Describe the skills and qualifications/profile of the surge personnel or any additional staff (to be) deployed specifically for the operation.\nWhat expertise or skill sets are required for the personnel being deployed?\nWhat roles will these personnel fulfil?\nAre there specific tasks or sectors they will be managing?", + "immAddressedHumanitarianImpactsLabel": "Which severe humanitarian impacts are your actions addressing, and why?", + "immAddressedHumanitarianImpactsDesc": "Prioritized impact of the foreseen disaster.", "immTimeframeHeading": "Timeframe", "immNsRequestDateLabel": "Date of National Society Application", "immNsRequestDateDesc": "DD/MM/YYYY", "immOperationTimeframeImminentLabel": "Operation timeframe (days)", - "immOperationTimeframeImminentDesc1": "Indicate the number of days, e.g.", - "immOperationTimeframeImminentDesc2": "45", - "immOperationTimeframeImminentDesc3": ".", + "immOperationTimeframeImminentDesc": "Fixed operation timeframe. This value is predefined and cannot be changed.", "columnFieldHeader": "Field", "columnValueHeader": "Value", "columnDescriptionHeader": "Description", @@ -345,7 +338,7 @@ "coverHowToUseDescription": "Mandatory fields\nInput required information in the “Value” column. Do not add data outside of these designated fields.\n\nCollaboration\nThis Excel file can be uploaded to OneDrive/SharePoint/Google Drive for multiple users to work on simultaneously. Please note that only one user can edit any specific cell at a time.\n\nEntry limits\nSome sections, like sources of information, risks and mitigation, and indicators, have a maximum of 5 entries. Please do not attempt to add more.", "coverStructureHeading": "Structure of the template", "coverStructureResponse": "The template is divided into the following sections:\n\nOperation Overview – general context of the emergency operation.\nEvent Details – information on the event triggering the DREF request.\nActions and Needs – description of key actions and needs.\nOperation Plan – outline of the planned operation and identified risks.\nTimeframes and Contacts – key timeframes and relevant contact details.", - "coverStructureImminent": "The template is divided into the following sections:\n\nOperation Overview – general context of the operation.\nEvent Details – information on the imminent hazard triggering the DREF request.\nOperation – proposed early actions, early response and support services.\nTimeframes and Contacts – key timeframes and relevant contact details.", + "coverStructureImminent": "The template is divided into the following sections:\n\nOperation Overview – general context of the operation.\nScenario Analysis – information on the imminent hazard triggering the DREF request.\nPlan – proposed early actions, early response and support services.\nTimeframes and Contacts – key timeframes and relevant contact details.", "coverStepsHeading": "Steps for importing the template", "coverStepsDescription": "1. Ensure the template is fully completed and all fields are correctly filled.\n2. Log in to the GO platform.\n3. Create a “New DREF Application” and use the Import function to upload this Excel file.\n4. After importing, any additional work on the application should be done directly in the GO platform.", "respIsManMadeEventDesc1": "Select Yes or No from the drop-down list.", diff --git a/app/src/views/AccountMyFormsDref/DownloadImportTemplateButton/DownloadImportTemplateModal/template/useImportTemplateSchema.ts b/app/src/views/AccountMyFormsDref/DownloadImportTemplateButton/DownloadImportTemplateModal/template/useImportTemplateSchema.ts index 558069aac..bf8872802 100644 --- a/app/src/views/AccountMyFormsDref/DownloadImportTemplateButton/DownloadImportTemplateModal/template/useImportTemplateSchema.ts +++ b/app/src/views/AccountMyFormsDref/DownloadImportTemplateButton/DownloadImportTemplateModal/template/useImportTemplateSchema.ts @@ -13,6 +13,10 @@ import { type TypeOfDrefEnum, } from '#utils/constants'; import { type TemplateSchema } from '#utils/importTemplate'; +import { + ONSET_SUDDEN, + OPERATION_TIMEFRAME_IMMINENT, +} from '#views/DrefApplicationForm/common'; import { type DrefRequestBody } from '#views/DrefApplicationForm/schema'; import i18n from './i18n.json'; @@ -1119,6 +1123,9 @@ function useImportTemplateSchema() { label: strings.immTypeOfOnsetLabel, validation: 'number', optionsKey: 'type_of_onset', + defaultValue: optionsMap.type_of_onset.find( + (option) => option.key === ONSET_SUDDEN, + )?.label, description: strings.immTypeOfOnsetDesc, }, @@ -1158,6 +1165,7 @@ function useImportTemplateSchema() { type: 'input', label: strings.immHazardDateAndLocationLabel, validation: 'textArea', + description: strings.immHazardDateAndLocationDesc, }, hazard_vulnerabilities_and_risks: { @@ -1283,42 +1291,6 @@ function useImportTemplateSchema() { description: strings.immSurgePersonnelDeployedDesc, }, - has_anti_fraud_corruption_policy: { - headingBefore: strings.immPoliciesHeading, - type: 'select', - optionsKey: '__boolean', - validation: 'boolean', - label: strings.immHasAntiFraudCorruptionPolicyLabel, - }, - - has_sexual_abuse_policy: { - type: 'select', - optionsKey: '__boolean', - validation: 'boolean', - label: strings.immHasSexualAbusePolicyLabel, - }, - - has_child_protection_policy: { - type: 'select', - optionsKey: '__boolean', - validation: 'boolean', - label: strings.immHasChildProtectionPolicyLabel, - }, - - has_whistleblower_protection_policy: { - type: 'select', - optionsKey: '__boolean', - validation: 'boolean', - label: strings.immHasWhistleblowerProtectionPolicyLabel, - }, - - has_anti_sexual_harassment_policy: { - type: 'select', - optionsKey: '__boolean', - validation: 'boolean', - label: strings.immHasAntiSexualHarassmentPolicyLabel, - }, - addressed_humanitarian_impacts: { type: 'input', validation: 'textArea', @@ -1340,15 +1312,11 @@ function useImportTemplateSchema() { type: 'input', validation: 'number', label: strings.immOperationTimeframeImminentLabel, - description: [ - { text: strings.immOperationTimeframeImminentDesc1 }, - { text: ' ' }, - { text: strings.immOperationTimeframeImminentDesc2, bold: true }, - { text: strings.immOperationTimeframeImminentDesc3 }, - ], + defaultValue: OPERATION_TIMEFRAME_IMMINENT, + description: strings.immOperationTimeframeImminentDesc, }, }, - }), [strings]); + }), [strings, optionsMap.type_of_onset]); const drefSchemaByType = useMemo< Partial>> diff --git a/app/src/views/AccountMyFormsDref/DownloadImportTemplateButton/DownloadImportTemplateModal/template/utils.ts b/app/src/views/AccountMyFormsDref/DownloadImportTemplateButton/DownloadImportTemplateModal/template/utils.ts index f9d9218ac..3a4d92a94 100644 --- a/app/src/views/AccountMyFormsDref/DownloadImportTemplateButton/DownloadImportTemplateModal/template/utils.ts +++ b/app/src/views/AccountMyFormsDref/DownloadImportTemplateButton/DownloadImportTemplateModal/template/utils.ts @@ -35,6 +35,8 @@ import { SHEET_EVENT_DETAIL, SHEET_OPERATION, SHEET_OPERATION_OVERVIEW, + SHEET_PLAN, + SHEET_SCENARIO_ANALYSIS, SHEET_TIMEFRAMES_AND_CONTACTS, } from '#utils/domain/dref'; import { @@ -537,7 +539,10 @@ async function generateOtherWorksheets( optionsWorksheet: Worksheet, workbook: Workbook, validationStrings: ValidationStrings, + typeOfDref: TypeOfDrefEnum, ) { + const isImminent = typeOfDref === DREF_TYPE_IMMINENT; + const fieldNameToTabNameMap: Record = { ...listToMap( overviewTabFields, @@ -547,7 +552,7 @@ async function generateOtherWorksheets( ...listToMap( eventDetailTabFields, (key) => key as string, - () => SHEET_EVENT_DETAIL, + () => (isImminent ? SHEET_SCENARIO_ANALYSIS : SHEET_EVENT_DETAIL), ), ...listToMap( actionsTabFields, @@ -557,7 +562,7 @@ async function generateOtherWorksheets( ...listToMap( operationTabFields, (key) => key as string, - () => SHEET_OPERATION, + () => (isImminent ? SHEET_PLAN : SHEET_OPERATION), ), ...listToMap( timeframeAndContactsTabFields, @@ -664,6 +669,11 @@ async function generateOtherWorksheets( templateAction.dataValidation, ); } + + if (isDefined(templateAction.defaultValue)) { + // eslint-disable-next-line no-param-reassign + worksheet.getCell(row, 2).value = templateAction.defaultValue; + } } }); }); @@ -751,6 +761,7 @@ export async function generateTemplate( listError: templateStrings.validationListError, errorTitle: templateStrings.validationErrorTitle, }, + typeOfDref, ); Object.values(sheetMap).forEach( diff --git a/app/src/views/DrefApplicationForm/DrefImportButton/DrefImportModal/index.tsx b/app/src/views/DrefApplicationForm/DrefImportButton/DrefImportModal/index.tsx index 677259ef7..55ca29b2a 100644 --- a/app/src/views/DrefApplicationForm/DrefImportButton/DrefImportModal/index.tsx +++ b/app/src/views/DrefApplicationForm/DrefImportButton/DrefImportModal/index.tsx @@ -198,7 +198,11 @@ function DrefImportModal(props: Props) { // Require EXACTLY the type's sheet set: a count check would accept a // Response file (5 sheets) as Imminent (a 4-sheet subset). const expectedSheetNames = getDrefSheetNames(typeOfDref); - const presentSheetNames = getDrefSheetNames(DREF_TYPE_RESPONSE) + const knownSheetNames = Array.from(new Set([ + ...getDrefSheetNames(DREF_TYPE_RESPONSE), + ...getDrefSheetNames(DREF_TYPE_IMMINENT), + ])); + const presentSheetNames = knownSheetNames .filter((sheetName) => isDefined(workbook.getWorksheet(sheetName))); const sheetsMatchType = presentSheetNames.length === expectedSheetNames.length && expectedSheetNames.every( diff --git a/app/src/views/FlashUpdateDetails/index.tsx b/app/src/views/FlashUpdateDetails/index.tsx index ef6ae5b7c..7bee917d0 100644 --- a/app/src/views/FlashUpdateDetails/index.tsx +++ b/app/src/views/FlashUpdateDetails/index.tsx @@ -215,7 +215,7 @@ export function Component() { {flashUpdateResponse.map_files.map((item) => ( ))} @@ -236,7 +236,7 @@ export function Component() { {flashUpdateResponse?.graphics_files?.map((item) => ( diff --git a/cacheppuccino b/cacheppuccino index 373b1659b..7fe8c8344 160000 --- a/cacheppuccino +++ b/cacheppuccino @@ -1 +1 @@ -Subproject commit 373b1659b5f376cb6af9b05ce142a503ee23b085 +Subproject commit 7fe8c83449195f3df6dfbdebbdf60e11fedf19ca diff --git a/go-api b/go-api index e9949d551..3e313d7d2 160000 --- a/go-api +++ b/go-api @@ -1 +1 @@ -Subproject commit e9949d55124523c375948b304ee65cdeb8d00f84 +Subproject commit 3e313d7d2885fe0080e3077076828cade7a5e4a4