Skip to content
Draft
Show file tree
Hide file tree
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
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ $ yarn start

[demo & step-by-step manual](https://github.com/ComPlat/react-spectra-editor/blob/master/DEMO_MANUAL.md)

### Documentation

- [Developer documentation](docs/README.md): architecture and diagrams

### Testing
#### Unit test
```
Expand Down
23 changes: 23 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Documentation

Developer documentation for `@complat/react-spectra-editor` (`react-spectra-editor`).

## Architecture

- [High-Level Overview](architecture/high-level-overview.md): package purpose, system boundaries, layers, and rendering branches
- [Frontend Architecture](architecture/frontend-architecture.md): Redux, sagas, data pipeline, multi-curve/CV, forecast, and runtime synchronization

## Diagrams

- [Diagram Generation](diagram.md): maintain and regenerate Mermaid diagrams

Regenerate all diagrams from the repository root:

```bash
yarn docs:diagrams
```

## User-Facing Guides

- [Demo & step-by-step manual](../DEMO_MANUAL.md): interactive demo usage
- [README](../README.md): installation and quick start
241 changes: 241 additions & 0 deletions docs/architecture/frontend-architecture.md

Large diffs are not rendered by default.

163 changes: 163 additions & 0 deletions docs/architecture/high-level-overview.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
# High-Level Overview

This page describes the high-level architecture of `@complat/react-spectra-editor`. The public entry point is `SpectraEditor` in [`src/app.js`](../../src/app.js).

The package is a stateful React editor for chemical spectra. A host application owns data loading, backend communication, persistence, and product workflows. The editor owns client-side spectrum rendering, editing interactions, Redux state orchestration, and callback-based integration.

## Project Purpose

`react-spectra-editor` provides an embedded editor for viewing and editing chemical spectra. The package supports NMR, IR, MS, UV, CV, XRD, and additional layout types listed in [`src/constants/list_layout.js`](../../src/constants/list_layout.js). See [`README.md`](../../README.md) for the published feature summary.

Supported layout identifiers include:

- `PLAIN`
- `IR`
- `RAMAN`
- `UV/VIS`
- `1H`, `13C`, `19F`, `31P`, `15N`, `29Si`
- `MS`
- `THERMOGRAVIMETRIC ANALYSIS`
- `X-RAY DIFFRACTION`
- `HPLC UV/VIS`
- `CYCLIC VOLTAMMETRY`
- `CIRCULAR DICHROISM SPECTROSCOPY`
- `SIZE EXCLUSION CHROMATOGRAPHY`
- `AIF`
- `Emissions`
- `DLS ACF`
- `DLS intensity`
- `DIFFERENTIAL SCANNING CALORIMETRY`
- `GAS CHROMATOGRAPHY`

The editor supports these main user-facing responsibilities:

- Display spectrum data as line charts, MS bar charts, or multi-spectrum overlays.
- Navigate spectra through zooming, brushing, scan selection, and curve selection.
- Edit peak data, thresholds, shifts, integrations, multiplicities, and cyclic voltammetry peaks.
- Compare compatible spectra through the comparison panel.
- Submit edited spectrum payloads through host-provided operations.
- Trigger prediction workflows and display forecast results when the host supplies `forecast` props and callbacks.

The package provides these main technical responsibilities:

- Convert JCAMP sources into the editor data model through `ExtractJcamp` in [`src/helpers/chem.js`](../../src/helpers/chem.js).
- Initialize Redux state from host-provided props in [`src/layer_init.js`](../../src/layer_init.js).
- Derive renderable spectrum inputs through selectors and helpers in [`src/helpers/chem.js`](../../src/helpers/chem.js) and [`src/helpers/extractParams.js`](../../src/helpers/extractParams.js).
- Select the appropriate rendering branch in [`src/layer_content.js`](../../src/layer_content.js).
- Render spectra with D3/SVG through [`src/components/d3_line`](../../src/components/d3_line), [`src/components/d3_rect`](../../src/components/d3_rect), and [`src/components/d3_multi`](../../src/components/d3_multi).
- Coordinate editing workflows through Redux reducers, undoable state, and Redux Saga.
- Expose integration helpers through `FN` in [`src/fn.js`](../../src/fn.js).

## Technology Stack

| Technology | Source files | Architectural role |
|---|---|---|
| React 17 | [`package.json`](../../package.json), [`src/app.js`](../../src/app.js) | Provides the component model for the embedded editor. The core codebase primarily uses class components connected to Redux through `connect`. |
| React Redux | [`src/app.js`](../../src/app.js), [`src/reducers/index.js`](../../src/reducers/index.js) | Holds the editor-wide state model for layouts, UI mode, thresholds, peaks, integrations, multiplicities, curves, forecast state, comparison state, and cyclic voltammetry data. |
| Redux Saga | [`src/app.js`](../../src/app.js), [`src/sagas/index.js`](../../src/sagas/index.js) | Coordinates action-driven workflows that span multiple reducers, especially UI interactions, resets, metadata calculation, multiplicity updates, and multi-entity initialization. |
| Redux Undo | [`src/reducers/undo_redo_config.js`](../../src/reducers/undo_redo_config.js), [`src/reducers/reducer_edit_peak.js`](../../src/reducers/reducer_edit_peak.js), [`src/reducers/reducer_integration.js`](../../src/reducers/reducer_integration.js), [`src/reducers/reducer_multiplicity.js`](../../src/reducers/reducer_multiplicity.js) | Provides bounded undo/redo history for editing-sensitive state: peaks, integrations, and multiplicities. |
| D3 | [`src/components/d3_line`](../../src/components/d3_line), [`src/components/d3_rect`](../../src/components/d3_rect), [`src/components/d3_multi`](../../src/components/d3_multi), [`src/helpers/mount.js`](../../src/helpers/mount.js) | Owns SVG rendering, axes, grids, paths, brushes, tooltips, markers, overlays, comparison lines, integrations, and multiplicity visualization. |
| Material UI | [`src/app.js`](../../src/app.js), [`src/components/cmd_bar/index.js`](../../src/components/cmd_bar/index.js), [`src/components/panel/index.js`](../../src/components/panel/index.js) | Provides UI structure for grids, buttons, tooltips, accordions, panel styling, and theme integration. |
| `jcampconverter` | [`src/helpers/chem.js`](../../src/helpers/chem.js), [`package.json`](../../package.json) | Converts JCAMP input into the internal `entity` shape consumed by initialization, selectors, and viewers. |
| `reselect` | [`src/helpers/chem.js`](../../src/helpers/chem.js) | Memoizes derived rendering data such as seed points, peaks, thresholds, comparisons, and frequency values. |
| Create React App / `react-scripts` | [`package.json`](../../package.json) | Supports local development and the demo application workflow through `start`, `build`, and `test`. |
| Babel compile | [`package.json`](../../package.json) | Builds distributable package output into `dist/` through the `compile` script. |
| Storybook / Cypress | [`package.json`](../../package.json), [`cypress.config.ts`](../../cypress.config.ts) | Supports component exploration and end-to-end testing workflows around the editor. |

## System Boundaries

The package is an embedded editor. It owns the in-browser editing experience and delegates persistence, prediction services, and product workflows to the host application.

![Frontend Context Map](../diagrams/generated/frontend-context-map.svg)

### Frontend Package Responsibilities

The package owns:

- The public editor component, `SpectraEditor`, exported from [`src/app.js`](../../src/app.js).
- The internal Redux store, reducers, and sagas.
- JCAMP conversion helpers exposed through `FN.ExtractJcamp`.
- Spectrum rendering through D3/SVG viewers.
- Editor controls for viewer mode, zoom, peak editing, integration, multiplicity, submit, thresholds, layout, wavelength, axes, detector, and cyclic voltammetry density.
- Panel UI for spectrum information, peaks, multiplicity, comparisons, graph selection, and cyclic voltammetry data.
- Construction of host-facing submit payloads in [`src/components/cmd_bar/r05_submit_btn.js`](../../src/components/cmd_bar/r05_submit_btn.js).
- Construction of host-facing prediction payloads in [`src/components/cmd_bar/r06_predict_btn.js`](../../src/components/cmd_bar/r06_predict_btn.js).

### Host Application Responsibilities

The host application owns the application context around the editor:

- Loading spectrum data and passing it as `entity` or `multiEntities`.
- Calling backend services and persisting edited results.
- Providing submit operations through the `operations` prop.
- Providing prediction callbacks and forecast state through the `forecast` prop.
- Providing comparison data and file import behavior through the `others` prop and `addOthersCb`.
- Handling rich description changes through `onDescriptionChanged`.
- Owning authentication, authorization, routing, ELN synchronization, and product-level navigation.

### Data Entry and Exit Points

Data enters the editor through props:

- `entity` initializes the main spectrum.
- `multiEntities` initializes multi-spectrum and cyclic voltammetry workflows.
- `others` initializes comparison spectra and the comparison import callback.
- `forecast` initializes prediction state and prediction callbacks.
- `descriptions`, `molSvg`, `multiMolSvgs`, `exactMass`, `entityFileNames`, and labels provide display context.

Edited data exits the editor through callbacks:

- `operation.value(payload)` receives the submit payload built by [`src/components/cmd_bar/r05_submit_btn.js`](../../src/components/cmd_bar/r05_submit_btn.js).
- `forecast.btnCb(payload)` receives prediction requests.
- `forecast.refreshCb(payload)` receives simulation refresh requests.
- `forecast.inputCb(...)` is passed into forecast viewers for analysis interactions.
- `others.addOthersCb({ jcamps })` receives dropped comparison files from [`src/components/panel/compare.js`](../../src/components/panel/compare.js).
- `onDescriptionChanged(delta)` receives user-authored rich description changes from the info panel flow.

The integration model is callback-driven. The editor manages local rendering and editing state, then returns structured payloads to the host for persistence, prediction, and synchronization.

## Global Architecture

The application composition starts in [`src/app.js`](../../src/app.js). `SpectraEditor` creates the Redux store, starts the root saga, wraps the editor in the Redux `Provider`, applies Material UI style injection, and renders `LayerInit`.

![Application Composition](../diagrams/generated/application-composition.svg)

### Main Layers

| Layer | File | Responsibility |
|---|---|---|
| `SpectraEditor` | [`src/app.js`](../../src/app.js) | Public component boundary, Redux provider setup, saga startup, helper export through `FN`. |
| `LayerInit` | [`src/layer_init.js`](../../src/layer_init.js) | Converts host props into Redux initialization actions and chooses between the single-spectrum and multi-spectrum branches. |
| `LayerPrism` | [`src/layer_prism.js`](../../src/layer_prism.js) | Main single-entity workspace. It composes the command bar, content viewer, and side panels. |
| `LayerContent` | [`src/layer_content.js`](../../src/layer_content.js) | Selects `ForecastViewer` when `forecast` is non-empty and the layout supports prediction (NMR, IR, UV/VIS, XRD); otherwise `ViewerRect` for MS or `ViewerLine` for other layouts. |
| `MultiJcampsViewer` | [`src/components/multi_jcamps_viewer.js`](../../src/components/multi_jcamps_viewer.js) | Multi-entity and cyclic voltammetry workspace. It composes the command bar, `ViewerMulti`, cyclic voltammetry panel, and side panels. |
| `CmdBar` | [`src/components/cmd_bar/index.js`](../../src/components/cmd_bar/index.js) | Central command surface for editing and display actions. |
| `PanelViewer` | [`src/components/panel/index.js`](../../src/components/panel/index.js) | Side-panel system for metadata, peaks, multiplicity, comparisons, graph selection, and CV data. |
| D3 viewers | [`src/components/d3_line`](../../src/components/d3_line), [`src/components/d3_rect`](../../src/components/d3_rect), [`src/components/d3_multi`](../../src/components/d3_multi) | Rendering branches for line spectra, MS spectra, and multi-spectrum/CV views. |

Redux crosses the full tree. Components derive render data from Redux and props, dispatch actions from UI interactions, and rely on sagas to coordinate cross-slice workflows.

## Rendering Architecture

Rendering is split between React composition and D3-managed SVG drawing. [`src/layer_content.js`](../../src/layer_content.js) selects the viewer branch from the active layout and forecast state.

![Rendering Branches](../diagrams/generated/rendering-branches.svg)

| Branch | Viewer | Used for |
|---|---|---|
| Line | [`ViewerLine`](../../src/components/d3_line/index.js) | Line-chart layouts (NMR, IR, UV/VIS, XRD, Raman, and related types) |
| MS | [`ViewerRect`](../../src/components/d3_rect/index.js) | Mass spectrometry bar charts |
| Multi | [`ViewerMulti`](../../src/components/d3_multi/index.js) | `multiEntities` overlays and cyclic voltammetry |

React mounts containers and passes Redux-derived inputs; D3 focus classes own the SVG lifecycle (`create` / `update`, brush, overlays). See [Frontend Architecture: Rendering Pipeline](frontend-architecture.md#rendering-pipeline-architecture) for the full pipeline, helpers, and debugging notes.

## State Management

Redux and Redux Saga coordinate editor-wide state from [`src/reducers/index.js`](../../src/reducers/index.js) and [`src/sagas/index.js`](../../src/sagas/index.js). Undoable editing applies to peaks, integrations, and multiplicities. `LayerInit` initializes state from host props; D3 viewers dispatch `resetAll(feature)` to stay aligned with the active feature.

See [Frontend Architecture](frontend-architecture.md) for reducer domains, saga modules, the data transformation pipeline, multi-curve/CV behavior, and runtime synchronization flows.

## Related Documentation

- [Frontend Architecture](frontend-architecture.md): Redux, sagas, pipelines, host contracts, and synchronization
- [Diagram Generation](../diagram.md): maintain architecture diagrams
129 changes: 129 additions & 0 deletions docs/diagram.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
# Diagram Generation

Developer reference for maintaining documentation diagrams in `docs/diagrams/`.

## Purpose

Documentation diagrams are generated automatically from Mermaid source files. The source files are versioned so diagrams can be reviewed and edited as code, while generated image files are used by Markdown documentation.

## Folder Structure

```text
docs/diagrams/
config/
mermaid-config.json
generate.sh
generated/
application-composition.svg
data-transformation-pipeline.svg
frontend-context-map.svg
multi-curve-architecture.svg
redux-architecture.svg
rendering-branches.svg
rendering-pipeline.svg
runtime-synchronization-flow.svg
saga-orchestration.svg
src/
application-composition.mmd
data-transformation-pipeline.mmd
frontend-context-map.mmd
multi-curve-architecture.mmd
redux-architecture.mmd
rendering-branches.mmd
rendering-pipeline.mmd
runtime-synchronization-flow.mmd
saga-orchestration.mmd
```

`docs/diagrams/src/` contains Mermaid source files (`.mmd`). Edit these files when a diagram needs to change.

`docs/diagrams/generated/` contains generated SVG diagrams. Every Mermaid source is generated as SVG.

`docs/diagrams/config/mermaid-config.json` defines shared Mermaid theme settings (fonts, colors, flowchart spacing) applied to every generated diagram.

## How to Generate Diagrams

Run this command from the repository root:

```bash
bash docs/diagrams/generate.sh
```

Or:

```bash
yarn docs:diagrams
```

This regenerates all SVG diagrams from every `.mmd` file in `docs/diagrams/src/`.

## How It Works

- The generation script uses Mermaid CLI through `npx`.
- Mermaid CLI is downloaded and run on demand; it is not a project dependency.
- The script keeps npm and Puppeteer caches outside the repository under `~/.cache/react-spectra-editor/` (override with `REACT_SPECTRA_EDITOR_CACHE`).
- Shared styling is applied through `docs/diagrams/config/mermaid-config.json`.

Equivalent manual command pattern:

```bash
for file in docs/diagrams/src/*.mmd; do
npx --yes --package @mermaid-js/mermaid-cli mmdc \
-i "$file" \
-o "docs/diagrams/generated/$(basename "${file%.mmd}.svg")" \
-c docs/diagrams/config/mermaid-config.json
done
```

## How to Add or Modify a Diagram

1. Create or edit a `.mmd` file in `docs/diagrams/src/`.
2. Run the generation script:

```bash
bash docs/diagrams/generate.sh
```

3. Reference the generated image in Markdown under `docs/architecture/`.

Use centered HTML image tags for large architecture diagrams. Keep diagrams fluid, readable on narrow screens, and capped in height:

```html
<div align="center" style="overflow-x: auto;">
<img src="../diagrams/generated/redux-architecture.svg" alt="Redux Architecture" width="100%" style="width: 100%; min-width: 1000px; max-height: 840px; height: auto; object-fit: contain;">
</div>
```

For simpler overview diagrams, standard Markdown image syntax is also used:

```markdown
![Application Composition](../diagrams/generated/application-composition.svg)
```

Use PNG only when targeting tools that do not reliably render SVG. This repository currently references SVG diagrams only; do not add PNG files unless Markdown documentation needs them.

## Rules

- Do not manually edit generated images.
- Always modify `.mmd` source files.
- Add new documentation diagrams as `.mmd` files in `docs/diagrams/src/`.
- Regenerate SVG files after changing any `.mmd` source.
- Center large diagrams in architecture pages and include `width="100%"` as the GitHub fallback. Keep `width: 100%; min-width: 1000px; max-height: 840px; height: auto; object-fit: contain;` for local previews that preserve inline styles.
- Do not keep generated PNG files unless Markdown documentation references them.
- Do not add `@mermaid-js/mermaid-cli` as a project dependency; generation stays on-demand through `npx`.
- Keep diagrams simple and readable.
- Mark unconfirmed behavior in the Mermaid source as `TODO: Confirm <specific behavior, integration, or deployment detail>`.

## Diagram Usage in Documentation

| Diagram | Referenced in |
|---|---|
| `frontend-context-map` | [high-level-overview.md](architecture/high-level-overview.md) |
| `application-composition` | [high-level-overview.md](architecture/high-level-overview.md) |
| `rendering-branches` | [high-level-overview.md](architecture/high-level-overview.md) |
| `redux-architecture` | [frontend-architecture.md](architecture/frontend-architecture.md) |
| `saga-orchestration` | [frontend-architecture.md](architecture/frontend-architecture.md) |
| `rendering-pipeline` | [frontend-architecture.md](architecture/frontend-architecture.md) |
| `data-transformation-pipeline` | [frontend-architecture.md](architecture/frontend-architecture.md) |
| `multi-curve-architecture` | [frontend-architecture.md](architecture/frontend-architecture.md) |
| `runtime-synchronization-flow` | [frontend-architecture.md](architecture/frontend-architecture.md) |
23 changes: 23 additions & 0 deletions docs/diagrams/config/mermaid-config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"theme": "base",
"fontFamily": "Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif",
"themeVariables": {
"background": "#ffffff",
"primaryColor": "#f8fafc",
"primaryTextColor": "#0f172a",
"primaryBorderColor": "#64748b",
"lineColor": "#475569",
"secondaryColor": "#eef2ff",
"tertiaryColor": "#f1f5f9",
"clusterBkg": "#f8fafc",
"clusterBorder": "#cbd5e1",
"fontSize": "16px"
},
"flowchart": {
"htmlLabels": true,
"nodeSpacing": 44,
"rankSpacing": 64,
"padding": 16,
"curve": "linear"
}
}
Loading
Loading