Skip to content
Merged
Changes from all commits
Commits
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
112 changes: 61 additions & 51 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,92 +1,102 @@
## Quick Start (From Scratch)
# Metadata Visualizer

```
$ nvm use
$ corepack enable
$ yarn install
$ cp .env.example .env.local
# Edit .env.local with your DHIS2 instance values
$ yarn start
```
DHIS2 web app (React 18 + TypeScript + Vite) to explore and visualize metadata
relationships as interactive 2D/3D graphs.

Open `http://localhost:8081`.
## Installation

## Setup
Requirements: Node 22 (see `.nvmrc`) and Yarn 4 (via `corepack`).

```
$ nvm use # uses Node 22 from .nvmrc
$ nvm use
$ corepack enable
$ yarn install
```

## Build
Copy `.env.example` to `.env.local` and configure the target DHIS2 instance
(`VITE_DHIS2_BASE_URL`, `DHIS2_AUTH`).

## Development

Build a production distributable DHIS2 zip file:
Start the development server:

```
$ yarn build
$ yarn start
```

## Development
Open `http://localhost:<VITE_PORT>` (default: `http://localhost:8081`). Requests to
DHIS2 are transparently proxied from `/dhis2/...` to `VITE_DHIS2_BASE_URL` (see
`vite.config.ts`) to avoid CORS issues.

Copy `.env.example` to `.env.local` and configure the DHIS2 instance to use. Then start the development server:
## Build

Produce the distributable DHIS2 zip:

```
$ yarn start
$ yarn build
```

Now in your browser, go to `http://localhost:8081`.
The web build output is placed under `build/`. The `.zip` ready to upload via App
Management is written to the repository root.

## Tests

```
$ yarn test
```

## Some development tips
## Features

### Clean architecture folder structure
The app is organized in two main tabs:

- `src/domain`: Domain layer (entities, resource types, repository definitions)
- `src/application`: Application layer (use cases)
- `src/data`: Infrastructure layer (DHIS2 data engine repositories)
- `src/webapp/pages`: Main React pages.
- `src/webapp/components`: React components.
- `src/utils`: Misc utilities.
- `i18n/`: Contains literal translations (gettext format)
- `public/`: General non-React webapp resources.
### 1. Instance Metadata

## Data structures
Live queries against the configured DHIS2 instance.

- `Future.ts`: Async values, similar to promises, but cancellables and with type-safe errors.
- `Collection.ts`: Similar to Lodash, provides a wrapper over JS arrays.
- `Obj.ts`: Similar to Lodash, provides a wrapper over JS objects.
- `HashMap.ts`: Similar to ES6 map, but immutable.
- `Struct.ts`: Base class for typical classes with attributes. Features: create, update.
- `Either.ts`: Either a success value or an error.
- Pick the **resource type**. Currently only the following types are supported:
`dataElements`, `dataSets`, `categories`, `categoryCombos`, `categoryOptions`,
`categoryOptionCombos`.
- Adjust **fields** and **filters** (standard DHIS2 API syntax, one filter per line or
separated by `;`). Any top-level field you add to **fields** is automatically rendered
as an additional column in the results table, so you can tailor the view to the
attributes you care about.
- The table shows paginated results; selecting a row renders the dependency graph of
that item on the right panel.
- Each row is prefixed with a deterministic **identicon avatar** derived from the item's
type and UID, providing a stable visual fingerprint that makes metadata easier to scan
and recognize across the table and graph views.

## Docs
### 2. JSON Package

We use [TypeDoc](https://typedoc.org/example/):
Load a metadata package exported as JSON (for example, from the DHIS2 import/export
module) and explore its relationships without needing a live instance.

```
$ yarn generate-docs
```
- Upload the `.json`, filter by type / id / name and pick an item to view its graph.
- **Direct only** mode: shows just the references directly declared in the JSON.
- **Expanded** mode: follows references transitively within the package.

### i18n
### Graph views

Update i18n .po files from `i18n.t(...)` calls in the source code:
On both tabs the graph panel offers three visualization modes:

```
$ yarn localize
```
- **2D View** — flat layout, best for seeing the structure at a glance.
- **3D Tree** — 3D force-directed graph (based on `react-force-graph-3d`).
- **3D Timeline** — 3D layout grouping nodes by type / level.

Clicking a node in the graph selects it as the new focus and recomputes its
dependencies.

### Scripts
## Architecture

Standalone scripts live in `src/scripts/` and are run via `yarn run-script <path>` (e.g. `yarn run-script src/scripts/zip-build.ts`).
Clean Architecture with three layers (`src/domain`, `src/data`, `src/webapp`) and a
`CompositionRoot` as the single dependency-injection point. Use cases live under
`src/domain/usecases/`.

### Misc Notes
## i18n

- Requests to DHIS2 will be transparently proxied (see `vite.config.ts` -> `server.proxy`) from `http://localhost:8081/dhis2/xyz` to `${VITE_DHIS2_BASE_URL}/xyz`. This prevents CORS and cross-domain problems.
After adding or modifying `i18n.t(...)` strings:

- You can use `.env` variables within the React app: `const value = import.meta.env.NAME;`
```
$ yarn extract-pot
Copy link

Copilot AI Apr 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The i18n instructions run yarn extract-pot and then yarn localize, but localize already runs update-po, which itself calls extract-pot (see package.json scripts). This makes the documented steps redundant and can slow down workflows; consider documenting just yarn localize, or adjusting the scripts so each step is necessary.

Suggested change
$ yarn extract-pot

Copilot uses AI. Check for mistakes.
$ yarn localize
```
Loading