# Features — DigitalBio

Evidence date: 2026-10-17. Revision: `master` `2739231` (2023-03-07).

Status words: **Current** (present and wired), **Partial** (screen or path exists but is incomplete or inconsistent), **Unused** (code or config present, no call from the running app), **Removed** (left history only), **Planned** (a written future item — not an approved backlog).

No feature roadmap file exists in the repository.

## Current

### App shell

- Document title and manifest name "Digical Digital" (`public/index.html`, `public/manifest.json`).
- Logo `src/Images/digitalBio.png` in the authenticator header and in the signed-in header (`src/Components/Hearder.jsx`). The filename is spelled Hearder.
- Signed-in header: `Logged In: {username}` and Sign out (`src/Components/AppHeader.jsx`). `pageName` is passed in and not displayed.
- Page background `#efefef`. Sidebar width comes from the grid column `196px` (`src/App.js`).
- Sidebar buttons: ML Results, Jobs, Canvasses. Page state values are `Dashboard`, `Jobs`, and `Canvas Search`.
- `amplify-authenticator` CSS sets a tomato background (`src/App.css`). A rule also sets `#efefef` for `[data-amplify-authenticator][data-variation=modal]`. The `withAuthenticator` call does not set a variation.

### Authentication

- Cognito user pool and identity pool via Amplify `withAuthenticator` (`src/App.js`, `amplify/backend/auth/digitalbio5fd52944/cli-inputs.json`).
- Email required and used for verification. MFA off. Password minimum length 8. No character classes in the checked-in policy. Refresh token validity 30. No user-pool groups.
- Unauthenticated identities disabled.
- Sign out wired to the header button.

### ML Results

- Default page after sign-in (`src/Pages/Dashboard.jsx`).
- Loads up to 10 `image` rows from `GET /getlastslides`, ordered by `slide`.
- Search placeholder "Slide No. Search". Three or more characters call `GET /searchslides/{value}` (contains match on `slide`, limit 10).
- One or two characters clear the list. Empty reloads the default 10.
- Table shows `name` (since `2739231`; before that the cell was `slide`). Header text "Tiles Found", "No results found", or a loader.
- Row click opens the tile viewer.
- Search submit opens Slide Explorer.
- Loading placeholders: six empty rows when a previous result array is still set while loading.

### Slide Explorer

- Reached only by search submit (`src/Pages/SlideExplorer.jsx`, `src/Components/AppSearchField.jsx`).
- Shows the search text as "Search Number".
- `GET /getslides/{searchValue}` with no SQL limit. Cards 200×200, name overlay, click opens the tile viewer.
- Presigned image, or `No_Image_Available.jpg`.
- Empty state "No Results found". Four placeholders while the first load is empty.

### Tile viewer

- Slide number (`slide`), tile number (`name`), zoom in, zoom out, reset (`src/Pages/ResultTileViewer.jsx`, `react-zoom-pan-pinch`).
- Previous and next walk `image.id` between 1 and `max(id)`, skipping ids that return no row.
- Result table from `GET /imageresult/{id}`: bbox `id`, `results`, confidence `Math.round(score * 100)%`.
- Placeholder image area and five placeholder result rows while data is absent.

### Jobs

- Default 10 rows from `GET /getlastjobs`, ordered by `name` (`src/Pages/Jobs.jsx`).
- Columns ID, Image Name, Status, Started. Status is `Done` when `perc === 1`, otherwise a rounded percentage. Started is `created_date` in local `YYYY/MM/DD H:M`.
- Search placeholder "Job No. Search" with the search button hidden (commit `00e1951`).
- Any non-empty input calls `GET /getjobbyname/{value}` (contains match on `name`, no limit).
- Empty state "No Jobs Found".

### Canvasses

- Sidebar label "Canvasses" since `2739231` (the previous label was "Canvass").
- Default 10 cards from `GET /getlastcanvas`, ordered by `name` (`src/Pages/CanvasSearch.jsx`). Cards are 400×400. The name caption is commented out.
- One or more characters call `GET /getCanvas/{value}` (contains match on `canvas.slide`, no limit).
- Empty state "No data to display".
- Card click opens the canvas viewer.

### Canvas viewer

- "Canvas Number" shows `canvas.name` (`src/Pages/CanvasResultViewer.jsx`).
- Same zoom controls and previous/next id walk, using `canvas.id` and `max(canvas.id)`.
- Button labelled Dashboard returns to page `Dashboard`.
- Grid table from `GET /canvastiles/{id}`: `row/col` and `name`.

### Images

- Presign helper (`src/util/s3Utils.js`, `src/util/getDataWithSignedURL.js`): bucket and key parsed from `uri`, region `eu-west-1`, expiry 3600 seconds, credentials from the Cognito identity pool.
- Fallback asset `src/Images/No_Image_Available.jpg`.

### API

- Amplify REST resource `apia19f7356`, every path `permissions.setting` `open`, all pointing at Lambda `SearchTiles` (`amplify/backend/api/apia19f7356/cli-inputs.json`).
- Express routes in `amplify/backend/function/SearchTiles/src/app.js` for the paths the screens call. GET only.
- PostgreSQL via `pg`. Connection fields come from Secrets Manager secret id `webapp_admin_user`.
- CORS allows any origin and any header.
- README records the local steps and the host `https://z24ayjk4pg.execute-api.eu-west-1.amazonaws.com/dev`.

## Partial

### Canvas search control

The Canvasses field placeholder is "Slide No. Search". `AppSearchField` shows a search button and sends submit to Slide Explorer unless the placeholder is "Job No. Search" or "Canvas No. Search". The string "Canvas No. Search" is never passed. Submit on Canvasses opens Slide Explorer with the ML Results search text, not the canvas text. Typing still filters canvases, because filtering is on `onChange`.

Source: `src/Pages/CanvasSearch.jsx`, `src/Components/AppSearchField.jsx`.

### Jobs look clickable

Rows set `cursor: pointer` and do not handle click. There is no job detail page.

### Tile results and canvas tiles have no empty message

An empty `bbox` or `tiles` list renders the same placeholder rows as the loading state (`ResultTileViewer.jsx`, `CanvasResultViewer.jsx`).

### API errors

Screen `catch` blocks log to the console. Several of them leave `isLoading` true. The Lambda `catch` blocks log and do not send an HTTP status, so the client waits until the integration times out (function timeout 25 seconds in the template).

### Names

The sidebar says ML Results. The canvas viewer button still says Dashboard. Both set page `Dashboard`. The document title is Digical Digital. The icon URL is `digicalBio-icon.png`. The file in `public/` is `digitalBio-icon.png`.

### Default lists are not "latest"

Route and function names say last (`getlastslides`, `getlastjobs`, `getlastcanvas`). The SQL orders by `slide` or `name` and limits to 10. Jobs display `created_date` but do not sort by it.

### Tests

`src/App.test.js` still expects a "learn react" link. `src/App.js` has no such text and imports `./aws-exports`, which is not in git. Not executed for this document.

### Lambda permissions

The handler reads Secrets Manager and connects to PostgreSQL. The checked-in execution policy allows CloudWatch Logs only (`SearchTiles-cloudformation-template.json`). `custom-policies.json` is an empty statement. A deployed role may differ. That is **Unknown / Requires Confirmation**.

## Unused

- `src/Components/SignIn.jsx` — email/password form calling `Auth.signIn`. No importer.
- `src/Components/SignUp.jsx` — `Auth.signUp`, `Auth.confirmSignUp`, `Auth.resendSignUp`. No importer.
- `src/Components/FormElement.jsx` — used only by those two forms.
- `@aws-sdk/client-secrets-manager` in the root `package.json`. No import under `src/`. The Lambda has its own copy.
- `src/logo.svg` — CRA logo. The header uses `src/Images/digitalBio.png`.
- `src/reportWebVitals.js` — `index.js` calls it with no callback, so the dynamic import of `web-vitals` does not run.
- `amplify/backend/function/SearchTiles/src/event.json` — sample body `{ msg: "Hello from the event.json body" }` on `POST /item`. No route handles that path.
- `AppHeader`'s `pageName` prop.
- `ResultTileViewer`'s `setPageName` prop.
- GraphQL transformer flags in `amplify/cli.json`. `backend-config.json` has no GraphQL API.
- Commented JSX: job title column (`Jobs.jsx`), canvas card caption (`CanvasSearch.jsx`).

## Removed

- Amplify API `SearchSlide` and Lambda `SearchSlides`, added in `6842c2a` (2023-02-17) and deleted in `e5dd795` the same day. The tip's API is a later resource, `apia19f7356` / `SearchTiles`, first present in `4cc2894` (2023-02-24).
- Dashboard button on Slide Explorer, removed in `d442a33` (2023-03-07). The canvas viewer still has a Dashboard button.
- Search button on job search, removed in `00e1951` (2023-03-03) by hiding it when the placeholder is "Job No. Search".
- ML Results cell used to show `slide`. `2739231` shows `name`.

`origin/ui-update` was merged in pull request #1 (`272949e`) and is not ahead of `master`.

## Planned

None. `src/App.js` still contains the CRA comments "Todo logic here" and "Add Todo JSX here". They do not name a product feature.

## Recently changed

The last commit, `2739231` on 2023-03-07, is the only change after the Dashboard button was removed from Slide Explorer the same day:

- Sidebar "Dashboard" became "ML Results".
- Sidebar "Canvass" became "Canvasses".
- The ML Results table cell changed from `result.slide` to `result.name`.

No later commit is on `origin/master`.
