Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
783166d
global(add-global-page): Add a global page
barshathakuri Oct 13, 2025
73051d5
eap(add-eap-link): Add EAP Tab in account page
barshathakuri Oct 14, 2025
c6edf32
dref-process(tabs): Add tabs in dref process link
barshathakuri Nov 5, 2025
f102fc4
eap-table(table): Add eap development table
barshathakuri Nov 10, 2025
6a0745a
eap(eap-registration-form): Add EAP Registration Form
barshathakuri Oct 15, 2025
ac6555f
eap-table(table): Add eap development table
barshathakuri Nov 10, 2025
9223238
eap(lisitng): Add eap listing page
barshathakuri Nov 12, 2025
6767eea
fix(eap): update eap section according to new UI
shreeyash07 Nov 18, 2025
4395c69
feat(eap): add simplified EAP form
barshathakuri Oct 28, 2025
e408b92
feat(eap): add export for simplified EAP
frozenhelium Dec 2, 2025
7e2c5d4
feat(eap): update simplified eap form schema
barshathakuri Dec 8, 2025
38322d6
feat(admin-2-input): add basic component
frozenhelium Dec 11, 2025
05b1b84
feat(eap): clean-up simplied form schema
frozenhelium Dec 11, 2025
c2ecdb8
feat(eap): add status transition
frozenhelium Dec 11, 2025
6f16bd3
feat(eap): add eap export modal
frozenhelium Dec 11, 2025
012942a
feat(eap): add expansion columns in eap table
frozenhelium Dec 12, 2025
30397c6
feat(eap): add indicators in simplified form
frozenhelium Dec 12, 2025
56e1dca
feat(eap): add PrintableDescription component
frozenhelium Nov 25, 2025
4c88096
feat(eap): add option to export with changes
frozenhelium Dec 15, 2025
4362c3e
test(e2e): Added UI automated test for EAP Registration
Shhhhhubh Dec 23, 2025
0e835f3
eap(update-ci): Update CI for playwright
barshathakuri Dec 23, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 10 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -63,34 +63,41 @@
path: packages/ui/dist

test:
name: Run tests
name: Run tests (Unit + Playwright)
environment: 'test'
runs-on: ubuntu-latest
defaults:
run:
working-directory: app
needs: [ui]
steps:
- uses: actions/checkout@v4
- name: Install pnpm
uses: pnpm/action-setup@v4
- name: Install Node.js
uses: actions/setup-node@v4
with:
node-version: 20
cache: 'pnpm'
- name: Install dependencies
run: pnpm install

- uses: actions/download-artifact@v4
with:
name: ui-build
path: packages/ui/dist

- name: Run test
run: pnpm test
- name: Build app
run: pnpm build

- name: Install Playwright browsers
run: pnpm exec playwright install --with-deps

- name: Run Playwright tests
working-directory: packages/e2e-tests
run: pnpm exec playwright test

translation:

Check warning

Code scanning / CodeQL

Workflow does not contain permissions Medium

Actions job or workflow does not limit the permissions of the GITHUB_TOKEN. Consider setting an explicit permissions block, using the following as a minimal starting point: {contents: read}
continue-on-error: true
name: Identify error with translation files
runs-on: ubuntu-latest
Expand Down
27 changes: 27 additions & 0 deletions .github/workflows/playwright.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
name: Playwright Tests
on:
push:
branches: [ main, master ]
pull_request:
branches: [ main, master ]
jobs:
test:
timeout-minutes: 60
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: lts/*
- name: Install dependencies
run: npm ci
- name: Install Playwright Browsers
run: npx playwright install --with-deps
- name: Run Playwright tests
run: npx playwright test
- uses: actions/upload-artifact@v4
if: ${{ !cancelled() }}
with:
name: playwright-report
path: playwright-report/
retention-days: 30
Comment on lines +9 to +27

Check warning

Code scanning / CodeQL

Workflow does not contain permissions Medium

Actions job or workflow does not limit the permissions of the GITHUB_TOKEN. Consider setting an explicit permissions block, using the following as a minimal starting point: {contents: read}

Copilot Autofix

AI 5 days ago

In general, the fix is to explicitly declare a permissions block at the workflow or job level, limiting GITHUB_TOKEN to only what this workflow needs. Since this job just checks out code, installs dependencies, runs Playwright tests, and uploads artifacts, it only needs read access to repository contents; no write permissions or access to other scopes (issues, pull-requests, etc.) are required.

The best minimal fix without changing existing functionality is to add a permissions block at the root level of .github/workflows/playwright.yml, just under name: (or above jobs:). This will apply to all jobs in the workflow (currently only test) and set contents: read. No other scopes are necessary for the listed actions. Concretely, edit .github/workflows/playwright.yml to insert:

permissions:
  contents: read

between the existing name: Playwright Tests and the on: block, leaving the rest of the workflow unchanged. No additional imports, methods, or definitions are required because this is purely a configuration change.

Suggested changeset 1
.github/workflows/playwright.yml

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/.github/workflows/playwright.yml b/.github/workflows/playwright.yml
--- a/.github/workflows/playwright.yml
+++ b/.github/workflows/playwright.yml
@@ -1,4 +1,6 @@
 name: Playwright Tests
+permissions:
+  contents: read
 on:
   push:
     branches: [ main, master ]
EOF
@@ -1,4 +1,6 @@
name: Playwright Tests
permissions:
contents: read
on:
push:
branches: [ main, master ]
Copilot is powered by AI and may make mistakes. Always verify output.
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,10 @@ storybook-static/

# Helm
.helm-charts/

# Playwright
/test-results/
/playwright-report/
/blob-report/
/playwright/.cache/
/playwright/.auth/
1 change: 1 addition & 0 deletions app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
"@togglecorp/toggle-request": "^1.0.0-beta.3",
"@turf/bbox": "^6.5.0",
"@turf/buffer": "^6.5.0",
"diff": "^8.0.2",
"exceljs": "^4.3.0",
"file-saver": "^2.0.5",
"html-to-image": "^1.11.11",
Expand Down
156 changes: 156 additions & 0 deletions app/src/App/routes/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,50 @@ const emergencyAdditionalInfo = customWrapRoute({
},
});

type DefaultDrefDetailChild = 'dref-detail';
const drefProcessLayout = customWrapRoute({
parent: rootLayout,
path: 'dref-process',
forwardPath: 'dref-detail' satisfies DefaultDrefDetailChild,
component: {
render: () => import('#views/DrefProcess'),
props: {},
},
wrapperComponent: Auth,
context: {
title: 'DREF Process',
visibility: 'anything',
},
});

const drefDetail = customWrapRoute({
parent: drefProcessLayout,
path: 'dref-detail' satisfies DefaultDrefDetailChild,
component: {
render: () => import('#views/DrefDetail'),
props: {},
},
wrapperComponent: Auth,
context: {
title: 'Response and Imminent DREF',
visibility: 'anything',
},
});

const eapDetail = customWrapRoute({
parent: drefProcessLayout,
path: 'eap-detail',
component: {
render: () => import('#views/EarlyActionProtocols'),
props: {},
},
wrapperComponent: Auth,
context: {
title: 'Early Action Protocols',
visibility: 'anything',
},
});

type DefaultPreparednessChild = 'global-summary';
const preparednessLayout = customWrapRoute({
parent: rootLayout,
Expand Down Expand Up @@ -715,6 +759,49 @@ const accountMyFormsThreeW = customWrapRoute({
},
});

const accountMyFormsEap = customWrapRoute({
parent: accountMyFormsLayout,
path: 'eap-applications',
component: {
render: () => import('#views/AccountMyFormsEap'),
props: {},
},
context: {
title: 'Account - EAP Applications',
visibility: 'is-authenticated',
permissions: ({ isGuestUser }) => !isGuestUser,
},
});

const fullEapForm = customWrapRoute({
parent: rootLayout,
path: 'eap/:eapId/full',
component: {
render: () => import('#views/EapFullForm'),
props: {},
},
wrapperComponent: Auth,
context: {
title: 'EAP Full Forms',
visibility: 'is-authenticated',
permissions: ({ isGuestUser }) => !isGuestUser,
},
});

const simplifiedEapForm = customWrapRoute({
parent: rootLayout,
path: 'eap/:eapId/simplified',
component: {
render: () => import('#views/SimplifiedEapForm'),
props: {},
},
wrapperComponent: Auth,
context: {
title: 'Simplified EAP Form',
visibility: 'is-authenticated',
},
});

const accountNotifications = customWrapRoute({
parent: accountLayout,
path: 'notifications',
Expand Down Expand Up @@ -1094,6 +1181,65 @@ const fieldReportDetails = customWrapRoute({
},
});

type DefaultEapRegistrationChild = 'new';
const eapRegistrationLayout = customWrapRoute({
parent: rootLayout,
path: 'eap-registration',
forwardPath: 'new' satisfies DefaultEapRegistrationChild,
component: {
render: () => import('#views/EapRegistration'),
props: {},
},
wrapperComponent: Auth,
context: {
title: 'EAP Process',
visibility: 'is-authenticated',
},
});

const newEapDevelopmentRegistration = customWrapRoute({
parent: eapRegistrationLayout,
path: 'new' satisfies DefaultEapRegistrationChild,
component: {
render: () => import('#views/EapRegistration'),
props: {},
},
wrapperComponent: Auth,
context: {
title: 'New EAP Development Registration',
visibility: 'is-authenticated',
permissions: ({ isGuestUser }) => !isGuestUser,
},
});

const eapDevelopmentRegistrationForm = customWrapRoute({
parent: eapRegistrationLayout,
path: ':eapId/',
component: {
render: () => import('#views/EapRegistration'),
props: {},
},
wrapperComponent: Auth,
context: {
title: 'View EAP',
visibility: 'is-authenticated',
},
});

const simplifiedEapExport = customWrapRoute({
parent: rootLayout,
path: 'eap/:eapId/export',
component: {
render: () => import('#views/SimplifiedEapExport'),
props: {},
},
wrapperComponent: Auth,
context: {
title: 'Simplified EAP Export',
visibility: 'is-authenticated',
},
});

type DefaultPerProcessChild = 'new';
const perProcessLayout = customWrapRoute({
parent: rootLayout,
Expand Down Expand Up @@ -1317,6 +1463,7 @@ const wrappedRoutes = {
accountMyFormsPer,
accountMyFormsDref,
accountMyFormsThreeW,
accountMyFormsEap,
resources,
search,
allThreeWProject,
Expand Down Expand Up @@ -1353,6 +1500,9 @@ const wrappedRoutes = {
termsAndConditions,
operationalLearning,
montandonLandingPage,
newEapDevelopmentRegistration,
fullEapForm,
simplifiedEapForm,
...regionRoutes,
...countryRoutes,
...surgeRoutes,
Expand All @@ -1363,6 +1513,12 @@ const wrappedRoutes = {
// Redirects
preparednessOperationalLearning,
obsoleteFieldReportDetails,
drefDetail,
eapDetail,
drefProcessLayout,
eapRegistrationLayout,
eapDevelopmentRegistrationForm,
simplifiedEapExport,
};

export const unwrappedRoutes = unwrapRoute(Object.values(wrappedRoutes));
Expand Down
1 change: 1 addition & 0 deletions app/src/components/Navbar/i18n.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
"userMenuDrefProcessDescription":"Disaster Response Emergency Fund (DREF) is the quickest way of getting funding directly to local humanitarian actors. Use one of the links below to submit a DREF Application or an update.",
"userMenuCreateDrefApplication":"Create DREF Application",
"myDrefApplications": "My DREF Applications",
"earlyActionProtocols": "Early Action Protocols (EAP)",
"userMenuSurge":"The section displays the summary of deployments within current and ongoing emergencies. Login to see available details",
"userMenuSurgeGlobalOverview":"Surge Global Overview",
"userMenuOperationalToolbox":"Operational Toolbox",
Expand Down
10 changes: 9 additions & 1 deletion app/src/components/Navbar/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -370,12 +370,20 @@ function Navbar(props: Props) {
</Description>
<DropdownMenuItem
type="link"
to="accountMyFormsDref"
to="drefDetail"
styleVariant="action"
withoutFullWidth
>
{strings.myDrefApplications}
</DropdownMenuItem>
<DropdownMenuItem
type="link"
to="eapDetail"
styleVariant="action"
withoutFullWidth
>
{strings.earlyActionProtocols}
</DropdownMenuItem>
<DropdownMenuItem
type="link"
to="newDrefApplicationForm"
Expand Down
12 changes: 9 additions & 3 deletions app/src/components/PerExportModal/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,15 @@ import {

import Link from '#components/Link';
import { type components } from '#generated/types';
import { useRequest } from '#utils/restRequest';
import {
type GoApiBody,
useRequest,
} from '#utils/restRequest';

import i18n from './i18n.json';

type ExportStatusEnum = components<'read'>['schemas']['ExportStatusEnum'];
type ExportBody = GoApiBody<'/api/v2/pdf-export/', 'POST'>;

const EXPORT_STATUS_PENDING = 0 satisfies ExportStatusEnum;
const EXPORT_STATUS_COMPLETED = 1 satisfies ExportStatusEnum;
Expand All @@ -45,8 +49,10 @@ function PerExportModal(props: Props) {
export_id: Number(perId),
export_type: 'per' as const,
per_country: Number(countryId),
is_pga: false,
}),
is_pga: undefined,
version: undefined,
diff: undefined,
} satisfies ExportBody),
[perId, countryId],
);

Expand Down
Loading
Loading