92 lines
6.3 KiB
Markdown
92 lines
6.3 KiB
Markdown
# Dashfront Automats Documentation
|
|
|
|
This directory contains reference documentation for all state automats in `dashfront` (`src/automats/`), powered by [`react-automat`](https://github.com/sebgreen/automat).
|
|
|
|
---
|
|
|
|
## Architecture Overview
|
|
|
|
In `dashfront`, state is managed outside the React component lifecycle using **Automats**. An Automat is an observable, fine-grained state store living in module scope.
|
|
|
|
### Core Principles
|
|
|
|
1. **Module Scope**: State persists across route changes and component mount/unmount cycles.
|
|
2. **Synchronous Reads**: Components read state synchronously in their `constructor` (or initial state) — zero loading flicker or blank frames.
|
|
3. **Fine-Grained Subscriptions**: React `PureComponent` instances subscribe in `componentDidMount` with selector functions or key lists, skipping unnecessary re-renders.
|
|
4. **Explicit Cleanup**: Every subscription returns an `unsub()` function called in `componentWillUnmount()`.
|
|
5. **No Context / No Hooks in PureComponents**: Automats bypass React Context providers and hooks, eliminating reconciliation cascades.
|
|
6. **Automatic Coordination**: Domain and configuration automats subscribe to [`authAutomat`](./authAutomat.md) to automatically bootstrap on login, switch data when the active company changes, and reset on logout.
|
|
|
|
## Domain & Data Model Guides
|
|
|
|
- [**Artikeltypen-Matrix**](./article-types-matrix.md): Spezifikation und Matrix für non-standard Artikeltypen (*Stückliste, Variations-Vater, Variations-Kind, Varianten-Baum*).
|
|
|
|
---
|
|
|
|
## Automats Directory
|
|
|
|
| Automat | State File | Documentation | Description |
|
|
|---|---|---|---|
|
|
| **`artikelAutomat`** | [`src/automats/artikelAutomat.js`](file:///home/seb/src/dashfront/src/automats/artikelAutomat.js) | [artikelAutomat.md](./artikelAutomat.md) | Cache and reactive distributor for single article detail payloads (`GET /api/article/:sku`) with inflight request deduplication. |
|
|
| **`authAutomat`** | [`src/automats/authAutomat.js`](file:///home/seb/src/dashfront/src/automats/authAutomat.js) | [authAutomat.md](./authAutomat.md) | Manages authentication lifecycle, session bootstrap, Google One Tap login, and multi-tenant company selection. |
|
|
| **`brandAutomat`** | [`src/automats/brandAutomat.js`](file:///home/seb/src/dashfront/src/automats/brandAutomat.js) | [brandAutomat.md](./brandAutomat.md) | Company-scoped catalog brands / manufacturers list (`GET /api/brand`, upsert). Auto-loads on company auth. |
|
|
| **`categoryAutomat`** | [`src/automats/categoryAutomat.js`](file:///home/seb/src/dashfront/src/automats/categoryAutomat.js) | [categoryAutomat.md](./categoryAutomat.md) | Hierarchical category tree (id → node map), tree ordering, drag-and-drop moves, and image uploads. Triggers the bulk category-view preload once the tree succeeds. |
|
|
| **`categoryViewAutomat`** | [`src/automats/categoryViewAutomat.js`](file:///home/seb/src/dashfront/src/automats/categoryViewAutomat.js) | [categoryViewAutomat.md](./categoryViewAutomat.md) | Per-category article views (`KeyedAutomat`) keyed by slug path; all views are warmed right after the tree loads. |
|
|
| **`companyAutomat`** | [`src/automats/companyAutomat.js`](file:///home/seb/src/dashfront/src/automats/companyAutomat.js) | [companyAutomat.md](./companyAutomat.md) | Active company configuration, tax rates (standard, reduced), root category ID, and company profile info. |
|
|
| **`deliveryEditorAutomat`** | [`src/automats/deliveryEditorAutomat.js`](file:///home/seb/src/dashfront/src/automats/deliveryEditorAutomat.js) | [deliveryEditorAutomat.md](./deliveryEditorAutomat.md) | Multi-line inbound delivery editor, OCR/PDF receipt reconciliation, supplier article auto-matching, and draft badge tracking. |
|
|
| **`navigationAutomat`** | [`src/automats/navigationAutomat.js`](file:///home/seb/src/dashfront/src/automats/navigationAutomat.js) | [navigationAutomat.md](./navigationAutomat.md) | Tracks and restores last visited article SKU and delivery paths across top-level section navigation. |
|
|
| **`posterminalAutomat`** | [`src/automats/posterminalAutomat.js`](file:///home/seb/src/dashfront/src/automats/posterminalAutomat.js) | [posterminalAutomat.md](./posterminalAutomat.md) | Point-of-Sale hardware terminals and enabled category assignments per terminal. |
|
|
| **`supplierAutomat`** | [`src/automats/supplierAutomat.js`](file:///home/seb/src/dashfront/src/automats/supplierAutomat.js) | [supplierAutomat.md](./supplierAutomat.md) | Company-scoped supplier directory (`GET /api/supplier`, create, update, delete) with inflight deduplication. |
|
|
| **`unitAutomat`** | [`src/automats/unitAutomat.js`](file:///home/seb/src/dashfront/src/automats/unitAutomat.js) | [unitAutomat.md](./unitAutomat.md) | Standard units of measure (Stück, kg, Liter, etc.) for the active company (`GET /api/unit`, upsert, delete). |
|
|
| **`userSettingsAutomat`** | [`src/automats/userSettingsAutomat.js`](file:///home/seb/src/dashfront/src/automats/userSettingsAutomat.js) | [userSettingsAutomat.md](./userSettingsAutomat.md) | Client-side user UI preferences (e.g. viewer docking position). Persisted to IndexedDB (`persist: true`). |
|
|
|
|
---
|
|
|
|
## Canonical PureComponent Consumption Pattern
|
|
|
|
```jsx
|
|
import { PureComponent } from 'react';
|
|
import { artikelAutomat, createArticleSelector, getArticle } from '../automats';
|
|
|
|
class ArticleHeader extends PureComponent {
|
|
constructor(props) {
|
|
super(props);
|
|
// 1. Synchronous read — no initial flash of empty state
|
|
this.state = {
|
|
article: getArticle(props.sku),
|
|
};
|
|
}
|
|
|
|
componentDidMount() {
|
|
// 2. Subscribe with fine-grained selector
|
|
this.unsub = artikelAutomat.subscribe(this, createArticleSelector(this.props.sku));
|
|
}
|
|
|
|
componentDidUpdate(prevProps) {
|
|
// 3. Re-subscribe if props change
|
|
if (prevProps.sku !== this.props.sku) {
|
|
this.unsub?.();
|
|
this.setState({ article: getArticle(this.props.sku) });
|
|
this.unsub = artikelAutomat.subscribe(this, createArticleSelector(this.props.sku));
|
|
}
|
|
}
|
|
|
|
componentWillUnmount() {
|
|
// 4. Always unsubscribe
|
|
this.unsub?.();
|
|
}
|
|
|
|
render() {
|
|
const { article } = this.state;
|
|
if (!article) return <div>Lädt...</div>;
|
|
return <h1>{article.name}</h1>;
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Debugging
|
|
|
|
All registered automats are available on `window.__AUTOMATS__` and accessible via `Automat.get(name)`. In development mode, the docked **AutomatInspector** (`src/devtools/AutomatInspector.jsx`) renders live state, subscriber counts, and action triggers.
|