u
This commit is contained in:
@@ -1,19 +1,20 @@
|
||||
# `categoryAutomat`
|
||||
|
||||
> **Source File**: [`src/automats/categoryAutomat.js`](file:///home/seb/src/dashfront/src/automats/categoryAutomat.js)
|
||||
> **Registration Key**: `'category'` (`Automat.get('category')` / `window.__AUTOMATS__.get('category')`)
|
||||
> **Registration Key**: `'category'` (`Automat.get('category')` / `window.__AUTOMATS__.get('category')`)
|
||||
> **Related**: [`categoryViewAutomat`](./categoryViewAutomat.md) — the keyed per-category article views, extracted into their own module.
|
||||
|
||||
---
|
||||
|
||||
## 1. Overview & Purpose
|
||||
|
||||
`categoryAutomat` manages the hierarchical category catalog tree for the active company (`/kategorien/*`), category breadcrumbs, category images, POS category visibility flags, and dynamic per-route category article view automats.
|
||||
`categoryAutomat` manages the hierarchical category catalog tree for the active company (`/kategorien/*`), category breadcrumbs, category images and POS category visibility flags. It owns the tree and all category/article **mutations**; the per-category *article views* live in [`categoryViewAutomat.js`](../src/automats/categoryViewAutomat.js) and are attached to this automat via `attachCategoryTree()`.
|
||||
|
||||
### Core Responsibilities
|
||||
- **Hierarchical Category Tree**: Normalized `id → node` dictionary (`categories`) representing the parent-child relational tree.
|
||||
- **Dynamic Per-Route Category View Automats**: Instantiates lightweight route-scoped automats (`category-view:<slug>`) that load category articles on-demand with automatic cache cleanup and disposal.
|
||||
- **Bulk View Preload**: after `GET /api/category/tree` succeeds, it triggers `loadAllCategoryViews()` so every category's articles are already cached when a route mounts.
|
||||
- **Mutations & Tree Reordering**: Category creation, batch creation, sibling reordering (`sort`), drag-and-drop hierarchy moves, and in-place renaming.
|
||||
- **Article Insertion & Synchronous UI Reflection**: When articles are created within a category, `categoryAutomat` immediately patches the active route automat's article list.
|
||||
- **Article Insertion & Synchronous UI Reflection**: When articles are created within a category, `categoryAutomat` immediately patches the matching category views' article lists.
|
||||
- **Media Management**: Uploading and deleting category cover images and updating AVIF full and thumbnail hashes (`fullHash`, `thumbHash`).
|
||||
- **POS Integration**: Toggling POS visibility and hardware terminal IDs per category.
|
||||
|
||||
@@ -50,6 +51,8 @@ interface CategoryState {
|
||||
treeStatus: 'idle' | 'loading' | 'succeeded' | 'failed';
|
||||
/** Last tree error message. */
|
||||
error: string | null;
|
||||
/** True while the post-tree preload of all category views is running. */
|
||||
viewsLoading: boolean;
|
||||
}
|
||||
```
|
||||
|
||||
@@ -63,29 +66,35 @@ const initialState = {
|
||||
renameMode: false,
|
||||
treeStatus: 'idle',
|
||||
error: null,
|
||||
viewsLoading: false,
|
||||
};
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. Dynamic Category View Automats (`KeyedAutomat`)
|
||||
## 3. Category View Automats (delegated)
|
||||
|
||||
Category views are powered by a `KeyedAutomat` instance (`categoryViews`) indexed by route **slug path** (e.g. `''` for root, `'getraenke'`, `'getraenke/softdrinks'`).
|
||||
The keyed per-category article views are **no longer defined in this file**. They are implemented in [`categoryViewAutomat.js`](../src/automats/categoryViewAutomat.js) and re-exported here for backward compatibility:
|
||||
|
||||
| Symbol | Source |
|
||||
|---|---|
|
||||
| `categoryViews` | `categoryViewAutomat.js` |
|
||||
| `getOrCreateCategoryAutomat({ slugPath })` | `categoryViewAutomat.js` |
|
||||
| `invalidateAllCategoryViews()` | `categoryViewAutomat.js` |
|
||||
| `disposeAllCategoryViewAutomats()` | `categoryViewAutomat.js` |
|
||||
|
||||
The following facades remain on the tree automat and delegate to `categoryViews`:
|
||||
|
||||
### `categoryAutomat.key(slugPath): KeyHandle`
|
||||
Returns a scoped `KeyHandle` proxy for the given route slug.
|
||||
- **Loader**: Resolves `slugPath` → `categoryId` from the tree, fetches articles via `GET /api/category/:id/articles`, and derives `childCategories` (all child categories having the current as their root/parent).
|
||||
- **Loader**: Resolves `slugPath` → `categoryId` from the tree, fetches articles via `GET /api/category/:id/articles`, and derives `childCategories`.
|
||||
- **Handle State**: `{ data: { slug, categoryId, articles, childCategories }, loaded: boolean, loading: boolean, error: string | null }`.
|
||||
- **`handle.load(options?)`**: Deduplicated background fetch across concurrent mounts.
|
||||
- **`handle.read()`**: React Suspense-compatible read (throws in-flight promise if unready).
|
||||
- **`handle.reload()`**: Re-fetches articles and child categories.
|
||||
- **`handle.subscribe(target, selector)`**: Fine-grained subscription to this slug view with zero cross-talk between different category routes.
|
||||
|
||||
### `invalidateAllCategoryViews(): void`
|
||||
Triggers `reload()` across all active slug view handles.
|
||||
|
||||
### `disposeAllCategoryViewAutomats(): void`
|
||||
Clears all active view handles and frees memory on company switch or logout.
|
||||
See [categoryViewAutomat.md](./categoryViewAutomat.md) for the full view API, including `loadAllCategoryViews()`.
|
||||
|
||||
---
|
||||
|
||||
@@ -94,7 +103,8 @@ Clears all active view handles and frees memory on company switch or logout.
|
||||
Access actions via `categoryAutomat.actions.<method>()`.
|
||||
|
||||
### Tree Operations
|
||||
- **`loadTree(): Promise<void>`**: Reads `rootCategoryId` from `companyAutomat`, queries `GET /api/category/tree`, parses the response into a normalized dictionary, and updates state.
|
||||
- **`loadTree(): Promise<void>`**: Reads `rootCategoryId` from `companyAutomat`, queries `GET /api/category/tree`, parses the response into a normalized dictionary, updates state, and then **awaits `loadAllCategoryViews()`** with `viewsLoading: true → false`. Individual category failures are logged as a warning and do not fail the tree load.
|
||||
- **`loadAllCategoryViews(): Promise<{ loaded: number, failed: Array<{ slug, error }> }>`**: Re-runs the bulk view preload on demand (idempotent — already cached views resolve immediately).
|
||||
- **`setRenameMode(enabled: boolean): void`**: Toggles inline renaming mode for the category explorer.
|
||||
- **`reset(): void`**: Disposes all route automats and resets tree state to `initialState`.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user