Skip to content

Commit

Permalink
Merge branch 'main' into chore/whats-new-child-heading-fix
Browse files Browse the repository at this point in the history
  • Loading branch information
rhys-burendo authored Nov 18, 2024
2 parents 40569cd + f3ff496 commit aea6ba1
Show file tree
Hide file tree
Showing 72 changed files with 3,656 additions and 1,680 deletions.
3 changes: 2 additions & 1 deletion .github/workflows/lighthouse.yml
Original file line number Diff line number Diff line change
Expand Up @@ -72,11 +72,12 @@ jobs:

- name: Unlighthouse assertions and client
run: npx unlighthouse-ci --build-static --site ${{ env.TARGET_URL }} --budget=80

- uses: actions/upload-artifact@v3
if: always()
with:
name: unlighthouse-report
path: ./.unlighthouse
path: ./.unlighthouse/ci-result.json
retention-days: 10

slack-notify:
Expand Down
24 changes: 24 additions & 0 deletions docs/a11y-progressive-enhancement.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Accessibility and Progressive Enhancement on the UKHSA Data Dashboard

In alignment with the **GDS (Government Digital Service) guidelines**, our approach to building the UKHSA Data Dashboard emphasises **progressive enhancement**. This ensures that core functionality is accessible and performant across all users and devices, regardless of JavaScript support. By designing features to function with minimal JavaScript, we improve both **accessibility** and **performance**, as most of the application is either statically or server-rendered. Below are key examples illustrating how progressive enhancement is applied across different features on the dashboard.

## Key Examples of Progressive Enhancement

1. **Navigation Dropdown Menu**
The primary navigation dropdown menu relies on JavaScript for opening and closing. However, to support users without JavaScript, the "Menu" text is also a hyperlink that redirects to a dedicated `/browse` page. This page provides a fully accessible fallback navigation menu, ensuring all users can navigate the site effectively.

2. **Interactive Charts**
We use **Plotly.js** to enhance charts with interactivity. Initially, all charts are rendered as static images upon page load, making them accessible and performant. Once the page's JavaScript is downloaded, the charts are progressively “hydrated” with Plotly.js to enable dynamic interactions, providing enhanced functionality without sacrificing accessibility.

3. **File Downloads**
All file downloads are implemented using plain `<form>` elements with `action` attributes pointing to the Next.js proxy API. This structure allows file downloads to function without JavaScript, offering seamless access for users with or without JS enabled.

4. **Topic Page Area Selector**
The area selector on Topic pages is implemented as a standard `<form>`. The form submission simply appends query parameters to the URL, which the server then interprets to serve location-based content. This approach enables functionality for users without JavaScript and ensures graceful handling of location-based page requests.

5. **Weather Health Alerts Map**
The weather health alerts map is an inherently JavaScript-heavy feature, using dynamic content to display interactive map elements. For users unable to access JavaScript content, an alternative, fully server-rendered view of the map data is provided on the weather health alert pages. This ensures critical information is accessible to all users, regardless of device or browser capabilities.

## Summary

Following GDS guidelines on progressive enhancement allows the UKHSA Data Dashboard to prioritise accessibility and performance. By ensuring each feature has a fallback or a server-rendered version, we provide a robust, inclusive experience for users across a range of capabilities and devices, making the data dashboard both accessible and highly performant.
38 changes: 38 additions & 0 deletions docs/api-route-handlers.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Next.js API Route Handlers Documentation

## Overview

Next.js API route handlers are designed to manage specific API requests and can return files as server responses. They play a crucial role in proxying requests, thereby enhancing security and functionality.

## Key Use Cases

1. **File Downloads:**

- API route handlers are used for endpoints such as `/api/download/chart`, where a file must be returned in response to a request. Currently, server actions do not support returning files.

2. **Proxying Requests:**

- By using API route handlers, we can act as a proxy, keeping our private API endpoints hidden from public access. This is particularly useful for validating responses after form submissions.

3. **Weather Health Alerts:**
- We use Next.js API route handlers for the Weather Health Alerts (WHA) endpoints. The specific endpoints are:
- `/api/proxy/alerts/v1/[category]/route.ts`
- `/api/proxy/alerts/v1/[category]/[region]/route.ts`
- Here, **category** can be either heat or cold, and **region** corresponds to one of the nine supported regions (e.g., East of England or London).
- For client-side requests, it is essential to proxy them through API route handlers to securely attach the API_KEY, preventing exposure in the browser.

## Example Endpoints

- **File Download Endpoint:**

- **Endpoint:** `/api/download/chart`
- **Purpose:** Returns a file in response to the request.

- **Weather Health Alerts Endpoints:**
- **Endpoint:** `/api/proxy/alerts/v1/[category]/route.ts`
- **Endpoint:** `/api/proxy/alerts/v1/[category]/[region]/route.ts`
- **Purpose:** Manages both server-side and client-side requests while securing the API_KEY.

## Conclusion

In our Next.js application, API route handlers serve a crucial purpose in managing data responses and enhancing security.
19 changes: 19 additions & 0 deletions docs/api-server-actions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Next.js Server Actions Documentation

## Overview

Next.js server actions are the preferred method for handling data manipulation tasks, such as form submissions. They provide a seamless way to manage data on the server side without needing to create separate API endpoints for JSON responses.

## Key Points

- **Form Submissions:** Server actions are used for form submissions that require JSON responses. For example, we currently use server actions for the feedback form submission.
- **Limitations:** Server actions should be avoided for tasks that require non-JSON responses, such as file downloads.

## Example Usage

- **Feedback Form Submission:**
- Use a server action to handle the submission of feedback forms, allowing for easy management and processing of user input.

## Conclusion

In our Next.js application, server actions serve a distinct purpose that helps streamline data manipulation.
41 changes: 41 additions & 0 deletions docs/architecture-future.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# Future Plans for Next.js Architecture

We are planning to enhance our Next.js architecture by removing CloudFront and re-enabling request-level caching. This change will optimise performance while allowing us to leverage Next.js features more effectively.

## Key Changes

1. **Removal of CloudFront:**

- Simplifies our architecture and reduces complexity.
- Eliminates CDN latency, allowing direct requests to Next.js.

2. **Re-enabling Request-Level Caching:**

- Utilises Next.js's built-in caching mechanisms to improve response times for dynamic routes.
- **Redis Integration:** Employing Redis for shared caching across multiple containers in the load balancer to ensure consistent performance and reduced latency.

3. **Incremental Static Regeneration (ISR):**

- ISR will be reactivated, allowing us to update static content without a full rebuild.
- Allows for caching of dynamic pages, enabling efficient content delivery.

4. **CMS Integration for On-Demand Purges:**

- Hooking up the caching strategy to our CMS for instant purging of outdated content, now managed directly without CloudFront.
- Allows us to manage content updates dynamically based on CMS events.

5. **Optimised Data Fetching with App Router:**
- Leveraging the App Router in Next.js 14 for better routing and data fetching strategies.
- Utilising **React Server Components** for improved data handling and rendering without relying on traditional data fetching methods.

## Benefits

- **On-Demand Revalidation:** The main benefit of this architecture is the ability to perform on-demand revalidation of cached content, ensuring that users receive the most up-to-date information without delays.
- **Dynamic Content Handling:** Efficiently manage dynamic content updates with ISR and request-level caching.
- **Easier Content Management:** Immediate updates from the CMS streamline our workflow, without the need for manual cache purges.

## Further Investigation

For more details on this transition, please refer to the investigation in the [Pull Request #525](https://github.com/UKHSA-Internal/data-dashboard-frontend/pull/525).

This updated architecture will ensure better performance, scalability, and ease of maintenance while fully leveraging Next.js capabilities.
22 changes: 22 additions & 0 deletions docs/architecture.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Next.js 14 Architecture Overview

This architecture is optimized for aggressive caching to enhance performance, using Next.js 14 with AWS deployment in a Docker container and AWS CloudFront CDN for efficient delivery. Here’s a brief overview:

1. **Next.js 14 with App Router:**
- `forceDynamic`: Applied on all routes to prevent caching at the origin level, ensuring that cache-control settings rely entirely on CloudFront.
2. **Docker & AWS:**
- **Docker:** Provides a consistent, portable runtime environment.
- **AWS Deployment:** Hosting in AWS allows scalability and tight integration with CloudFront.
3. **CloudFront CDN:**
- **Caching Strategy:**
- **Default TTL:** A 30-day TTL for all routes ensures that cached responses are aggressively reused.
- **Manual Cache Flush:** CMS changes require manual cache invalidation to reflect updates across cached content.
- **Specific TTL Adjustments:** Landing page and weather alerts are set to shorter TTLs for selective, more frequent updates.

## Workflow Summary

1. **User Request → CloudFront:** If cached, the response is delivered immediately. If not, it forwards the request to Next.js.
2. **Next.js processes uncached requests dynamically,** delivering them back to CloudFront.
3. **CloudFront Caches the response** for the configured TTL, requiring manual purges for any CMS-driven content updates.

This setup ensures performance optimisation via aggressive caching, reducing server load and latency while relying on manual cache management for selective updates.
55 changes: 55 additions & 0 deletions docs/i18n.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# i18n Documentation

## Overview

We use the [i18next](https://www.i18next.com/) package for internationalization (i18n) in our Next.js application. This allows us to manage UI copy in a structured manner, enabling easier future localisation and maintaining a consistent approach for front-end developers.

## Structure

- **Localization Files:**
- All UI copy is stored in JSON files located inside the `public/locales/*` directory. For example, you can find common translations in `public/locales/common.json`.
- **Current Language Support:**
- We are currently supporting English only, but this setup provides a foundation for future product changes and multilingual support.

## Integration with Next.js 14 App Router

With the migration to Next.js 14's App Router architecture, including React Server Components (RSC) and client components, implementing i18n requires careful handling:

### Client Components

- **Import Statement:**

- Use the following import to access translation functionality:
```javascript
import { useTranslation } from '@/app/i18n/client'
```

- **Usage:**
- To retrieve translations, use the following syntax:
```javascript
const { t } = useTranslation('common')
...
<p>{t('exampleKey')}</p>
```
- **Note:** This must NOT be an async function.

### Server Components

- **Import Statement:**

- For server components, use this import to access translations:
```javascript
import { getServerTranslation } from '@/app/i18n'
```

- **Usage:**
- To retrieve translations, the following syntax is used:
```javascript
const { t } = await getServerTranslation('common')
...
<p>{t('exampleKey')}</p>
```

## Conclusion

Implementing i18n with the i18next package in our Next.js application allows for efficient management of UI copy and provides a scalable structure for future internationalization needs. By following the guidelines for both client and server components, we can ensure a consistent user experience across our application.
35 changes: 35 additions & 0 deletions docs/interactive-charts.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Interactive Charts Documentation

## Overview

This documentation outlines the new interactive chart functionality integrated into our application. This feature is designed to enhance user experience while maintaining the integrity of our existing static charts.

## Key Features

1. **Tooltip Integration:**

- The initial phase introduces a tooltip for interactive charts, providing users with detailed information on hover.

2. **Feature Flag Activation:**

- The interactive chart functionality is controlled through a feature flag, allowing for easy toggling during development and deployment.

3. **Interactive Control:**

- The `enableInteractive` prop has been added to specify which areas of the chart should utilize Plotly.js for interactivity, ensuring precise control over interactive features.

4. **Lazy Rendering with Intersection Observer API:**

- We employ the Intersection Observer API to render interactive charts only when they are scrolled into view. This enhances performance by deferring rendering until necessary.
- If the chart is not in view, it will default to existing static charts, ensuring a smooth user experience without unnecessary resource consumption.

5. **Progressive Enhancement:**

- The implementation is fully progressively enhanced. On the first load, the static charts are displayed to ensure that users can access the information without delay.
- Interactive features are activated once the chart comes into view, providing an enhanced experience without compromising initial load performance.

## Future Expansion

As we move forward with the development of interactive charts, it is essential to note that the backend serves as the source of truth for both data and layout configurations. Any additional interactivity must be sourced from the backend to ensure consistency and accuracy across all chart implementations.

However, front-end developers have the opportunity to experiment with interactive features by modifying `ChartInteractive.tsx`. By adjusting the contents of the figure object within this file, developers can prototype and test new interactions locally before finalising any backend changes. This approach encourages innovation while maintaining a structured and reliable data flow.
88 changes: 88 additions & 0 deletions docs/mock-server-and-switchboard.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
# Mock Server and Switchboard Documentation

## Overview

This documentation provides an overview of the **Mock Server** and **Switchboard**, two essential tools for local development in our front-end application. These tools facilitate independent development and testing without relying on the actual backend API.

## Mock Server

### What is the Mock Server?

The **Mock Server** is a Node.js Express application that mimics our backend's private API. It runs locally within the front-end application, allowing developers to simulate API responses and behaviours.

### Key Features

- **Local Development:** The mock server is designed to run only in the front-end application environment, enabling developers to work offline and independently from the live backend.
- **Customisable Responses:** The server can be configured to return specific responses based on your testing needs, making it easier to simulate various scenarios.

### Location and Configuration

- The mock server code is located in the `src/mock-server` directory of the project.
- **Endpoints Configuration:** The endpoints are configured in mock-server/index.ts. Each endpoint references a handler found in the mock-server/handlers directory.
- For example, for the /api/bulkdownloads/v1 endpoint, the corresponding handler file is mock-server/handlers/bulkdownloads/v1.ts.

### Handlers

- Handlers are standard Express.js API handlers that return JSON responses mimicking the actual API.
- The JSON responses are usually located in a fixtures folder adjacent to the handler file, allowing for easy management and updates of the mock data.

### Dynamic Responses

- Dynamic JSON can be served through integration with the Switchboard using the getSwitchBoardState helper. This allows for real-time changes to the mock responses based on the Switchboard's configuration.

### Starting the Mock Server

The mock server starts automatically when you run the command npm run dev. It will be accessible at http://localhost:3005, allowing for seamless local development.

## Environment Configuration

When working locally, you need to set up a .env.local file to configure the API endpoint and authentication key. This file should include the following:

```
API_URL=http://localhost:3005
API_KEY=123
```

### Testing Against a Deployed Environment

If you want to test against a real deployed environment, you can adjust your .env.local file as follows:

```
API_URL=https://private-api.dev.ukhsa-dashboard.data.gov.uk
API_KEY={DEV_API_KEY}
```

Make sure to uncomment these lines when you wish to test against the actual API.

## Switchboard

### What is the Switchboard?

The **Switchboard** is a local-only UI dashboard that allows developers to manipulate the responses from the mock server dynamically. It achieves this through the use of cookies, providing a flexible way to test different front-end states.

### Key Features

- **Dynamic Mock Responses:** The switchboard enables you to change the data returned by the mock server in real time, which is particularly useful for testing feature flags and other conditional behaviours in the front end.
- **Facilitates Testing:** By allowing developers to simulate different backend responses, the switchboard is instrumental in validating the front end against various scenarios, especially in automated tests like Playwright.

### Location

The switchboard is located in the `src/app/(pages)/switchboard` directory. You can access the switchboard interface in your local development environment at http://localhost:3000/switchboard to manipulate mock responses as needed.

## Usage

1. **Starting the Development Environment:**
- Run the command npm run dev to start the development server, including the mock server.
2. **Accessing the Mock Server:**

- Once the mock server is running, navigate to http://localhost:3005 in your browser to access the mock API.

3. **Accessing the Switchboard:**
- After starting the mock server, navigate to http://localhost:3000/switchboard in your browser to access the switchboard UI.
- Use the interface to modify mock responses by setting cookies, testing various configurations, and validating front-end behaviours.

## Conclusion

The Mock Server and Switchboard are powerful tools that enhance local development and testing workflows. By simulating backend API responses and allowing dynamic manipulation of those responses, they enable developers to work more efficiently and effectively test the front-end application.

For any questions or additional information, please refer to the project README or reach out to the development team.
Loading

0 comments on commit aea6ba1

Please sign in to comment.