Files
dashfront/docs/README.md
2026-09-23 17:24:33 +02:00

5.8 KiB

Dashfront Automats Documentation

This directory contains reference documentation for all state automats in dashfront (src/automats/), powered by react-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 to automatically bootstrap on login, switch data when the active company changes, and reset on logout.

Automats Directory

Automat State File Documentation Description
artikelAutomat src/automats/artikelAutomat.js artikelAutomat.md Cache and reactive distributor for single article detail payloads (GET /api/article/:sku) with inflight request deduplication.
authAutomat src/automats/authAutomat.js authAutomat.md Manages authentication lifecycle, session bootstrap, Google One Tap login, and multi-tenant company selection.
brandAutomat src/automats/brandAutomat.js brandAutomat.md Company-scoped catalog brands / manufacturers list (GET /api/brand, upsert). Auto-loads on company auth.
categoryAutomat src/automats/categoryAutomat.js categoryAutomat.md Hierarchical category tree (id → node map), route view article automats, tree ordering, drag-and-drop moves, and image uploads.
companyAutomat src/automats/companyAutomat.js companyAutomat.md Active company configuration, tax rates (standard, reduced), root category ID, and company profile info.
deliveryEditorAutomat src/automats/deliveryEditorAutomat.js deliveryEditorAutomat.md Multi-line inbound delivery editor, OCR/PDF receipt reconciliation, supplier article auto-matching, and draft badge tracking.
navigationAutomat src/automats/navigationAutomat.js navigationAutomat.md Tracks and restores last visited article SKU and delivery paths across top-level section navigation.
posterminalAutomat src/automats/posterminalAutomat.js posterminalAutomat.md Point-of-Sale hardware terminals and enabled category assignments per terminal.
supplierAutomat src/automats/supplierAutomat.js supplierAutomat.md Company-scoped supplier directory (GET /api/supplier, create, update, delete) with inflight deduplication.
unitAutomat src/automats/unitAutomat.js 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 userSettingsAutomat.md Client-side user UI preferences (e.g. viewer docking position). Persisted to IndexedDB (persist: true).

Canonical PureComponent Consumption Pattern

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.