plant: private Cargill Gouda tracker (/trackers/cargill)
All checks were successful
Deploy production / deploy (push) Successful in 1m19s

Owner-only tracker for learning the Cargill Bioindustrial plant in Gouda:
schema plant (entries, links with confidence, pending refs), plant.apply_entries
bulk import, overview with clusters and flow diagram, kind tabs, glossary,
questions, detail pages and owner inline editing. Docs in docs/plant-tracker.md.
This commit is contained in:
2026-10-26 13:42:37 +00:00
parent fda21554cc
commit e24ee7f95d
26 changed files with 48481 additions and 3 deletions

79
src/lib/plant.test.ts Normal file
View File

@@ -0,0 +1,79 @@
import { describe, expect, it } from 'vitest';
import {
KIND_TAB,
PLANT_KINDS,
entryHref,
kindFromSegment,
kindFromTab,
layoutFlow,
matches,
slugify,
tabHref
} from './plant';
describe('plant tracker', () => {
it('lays the flow out top to bottom, ignoring dashed loops', () => {
// oil → clean → split → col → dimer, dimer ⇢ col (dashed), clean ⇢ ester, col → ester
const nodes = [1, 2, 3, 4, 5, 6].map((id) => ({ id, sort: id }));
const edges = [
{ from: 1, to: 2, dashed: false },
{ from: 2, to: 3, dashed: false },
{ from: 3, to: 4, dashed: false },
{ from: 4, to: 5, dashed: false },
{ from: 5, to: 4, dashed: true },
{ from: 2, to: 6, dashed: true },
{ from: 4, to: 6, dashed: false }
];
const { placed, width, height } = layoutFlow(nodes, edges);
const layer = Object.fromEntries(placed.map((p) => [p.id, p.layer]));
expect(layer).toEqual({ 1: 0, 2: 1, 3: 2, 4: 3, 5: 4, 6: 4 });
expect(width).toBeGreaterThan(0);
expect(height).toBeGreaterThan(0);
});
it('survives a solid cycle', () => {
const { placed } = layoutFlow(
[
{ id: 1, sort: 0 },
{ id: 2, sort: 1 }
],
[
{ from: 1, to: 2, dashed: false },
{ from: 2, to: 1, dashed: false }
]
);
expect(placed.map((p) => p.layer)).toEqual([0, 1]);
});
it('maps kinds to URLs and back', () => {
expect(entryHref({ kind: 'process_step', slug: 'splitting' })).toBe(
'/trackers/cargill/process-step/splitting'
);
expect(kindFromSegment('process-step')).toBe('process_step');
expect(kindFromSegment('nope')).toBeNull();
expect(slugify('Lab (QC) – Ëster')).toBe('lab-qc-ester');
});
});
describe('tabs and search', () => {
it('maps kinds to tabs and back', () => {
for (const k of PLANT_KINDS) expect(kindFromTab(KIND_TAB[k])).toBe(k);
expect(kindFromTab('nope')).toBeNull();
expect(kindFromTab(null)).toBeNull();
expect(tabHref('process_step')).toBe('/trackers/cargill?tab=process');
expect(tabHref(null)).toBe('/trackers/cargill');
});
it('matches all words, ignoring case and accents', () => {
const e = {
title: 'Dimer acids',
slug: 'dimer-acids',
summary: 'Twee vetzuren',
body: null,
tags: ['product']
};
expect(matches(e, 'DIMER twee')).toBe(true);
expect(matches(e, 'dimer ester')).toBe(false);
expect(matches({ ...e, title: 'Crème' }, 'creme')).toBe(true);
expect(matches(e, ' ')).toBe(true);
});
});