This directory contains the web UI for ORT Server.
The UI is a React application and uses Vite as the build tool and pnpm as the package manager.
The build runs React Compiler through @rolldown/plugin-babel, configured in vite.config.ts.
It memoizes components and hooks, so new code usually does not need useMemo, useCallback or memo().
Keep a manual useMemo or useCallback where a value must keep its identity while the compiler would see a changed input, such as a new object with the same contents, and say why in a comment.
- The compiler silently skips a component it cannot handle, and
pnpm lintdoes not report every reason for a skip; unsupported syntax such astry … finallyis not reported. A skipped component also hides its other compiler lint findings. - The compiler reuses a value computed from an object for as long as the object stays the same.
A component that reads state through an object whose identity does not change when the state does, such as TanStack Table rows and columns, would show outdated content.
Either read the state through an API that re-renders the component, such as
table.Subscribe, or leave the component out with a'use no memo'directive and a comment saying why. - With React Hook Form, a component that receives the result of
useFormfrom its parent must subscribe to what it shows: read values withuseWatchand form state withuseFormState.watch()is rejected by lint. Leaving out only the child does not help, because the compiled parent keeps reusing the child's element. If the child cannot subscribe, leave out the parent instead, with a comment saying why. CallgetValues()only in event handlers and effects. - Define components at module level. For a component defined inside another function, the compiler can move callbacks out of the function, where they no longer see its variables.
- Code is compiled only in tests that run in the jsdom environment (
// @vitest-environment jsdom).
By default, the UI expects ORT Server to be running locally.
If there are no local changes, the fastest way to get started is to use published ORT Server images for UI development. To do so, run the following commands from the project root directory:
$ docker compose pull # Ensure that all images are up-to-date.
$ docker compose up -d # Bring services up in detached mode.If you depend on local changes to the Kotlin backend, you instead need to build the images locally:
$ ./gradlew :buildAllImages # Build all images locally.
$ docker compose up -d # Bring services up in detached mode.Next, ensure that the API definitions are up to date by running:
$ ./gradlew :core:generateOpenApiSpec
$ pnpm -C ui install
$ pnpm -C ui buildFor interactive UI development with live-preview in the browser follow these steps:
- Run
pnpm -C ui dev. - Ctrl-click the shown
http://localhost:5173/link. - Log in via Keycloak (use "admin" / "admin" as username / password).
If changes to the API were done during development, these are the minimum commands to rerun to reflect the changes (again from the project root):
$ ./gradlew -PdockerImagePrefix=ghcr.io/eclipse-apoapsis/ -PdockerImageTag=main :core:tinyJibDocker
$ docker compose up -d core
$ ./gradlew :core:generateOpenApiSpec
$ pnpm -C ui generate:apiAfter completing the normal UI setup above, run the Vitest suite from the repository root:
$ pnpm -C ui test --run
$ pnpm -C ui test:coverageThese tests use local fixtures and mocks and do not require running Docker services or installing Playwright browsers.
Coverage is disabled for ordinary test runs. The coverage command prints statement, branch, function, and line totals and writes reports to ui/coverage/:
- Open
ui/coverage/index.htmlin a browser to inspect coverage by source file. ui/coverage/coverage-summary.jsoncontains machine-readable totals.ui/coverage/lcov.infocan be used by coverage reporting tools.
Reports include untested TypeScript and TSX source files, but exclude generated API code, the generated route tree, and type declarations. Generated reports are ignored by version control, ESLint, and Prettier. No coverage threshold is enforced.
The "UI Coverage" workflow measures UI test coverage for every pull request, and the "Report UI Coverage" workflow posts the result as a comment on it once "UI Coverage" has finished.
This also works for pull requests from forks.
Each new push updates the same comment.
The comment shows the coverage of the pull request and, below each value, the change against the commit of the target branch the pull request is based on.
The change is labelled pp, which means percentage points.
The pull request is measured as GitHub merges it into the target branch for testing, so the change comes from the pull request only, even if the branch is behind the target branch.
The footer names the last commit of the pull request.
The status icon of each metric shows its coverage level: 🔴 below 50%, 🟠 from 50% and 🟢 from 80%. These thresholds are a trial and only colour the report.
Coverage is for information only: a drop in coverage does not fail the build, and "UI Coverage" is not a required check. Measuring coverage makes the tests slower, so a test can occasionally hit its time limit and fail "UI Coverage" without blocking the merge. If measuring either coverage fails, the comment is not updated and still shows the numbers of an earlier commit, named in its footer.
The full HTML and LCOV reports can be downloaded from the "UI Coverage" run. Small changes can come from code that depends on the current time, and the React Compiler can change function and branch counts, so look at the reports before reading too much into a change of a few hundredths.
To run the Playwright e2e tests locally, first start core service (also starts keycloak, postgres and rabbitmq) and dev UI, then run the tests:
$ docker compose up -d core
$ cd ui
$ pnpm dev
$ pnpm test:e2eThe Docker image for the UI is built as part of the buildAllImages Gradle task.
To build it manually, run the following steps from the root of the repository:
- Build the OpenAPI specification:
./gradlew :core:generateOpenApiSpec - Build the Docker image:
docker build -t ort-server-ui -f ui/docker/UI.Dockerfile ui
To run the Docker image, use the following command:
docker run --rm -p 8082:8080 ort-server-uiThe Docker image can be configured by the following environment variables:
| Variable | Default | Description |
|---|---|---|
UI_API_URL |
http://localhost:8080 |
The URL of the ORT Server API. |
UI_URL |
http://localhost:8082 |
The URL of the UI. |
UI_BASEPATH |
/ |
The base path of the UI. |
UI_AUTHORITY |
http://localhost:8081/realms/master |
The URL of the Keycloak realm. |
UI_CLIENT_ID |
ort-server-ui |
The client ID of the UI in Keycloak. |
The image supports running with a read-only root filesystem (e.g. in OpenShift).
The following directories must be writable and should be mounted as emptyDir volumes:
