@crvouga/atlas 0.10.2 → 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/README.md +7 -0
- package/dist/reports/src/catalog-health.d.ts +142 -0
- package/dist/reports/src/catalog-health.js +257 -0
- package/dist/reports/src/test-catalog.d.ts +8 -0
- package/dist/reports/src/test-catalog.js +5 -1
- package/dist/schema/src/api.d.ts +79 -0
- package/dist/schema/src/api.js +50 -0
- package/dist/server/src/app.js +9 -0
- package/dist/server/src/llms.js +1 -0
- package/dist/server/src/openapi.js +18 -2
- package/dist/server/src/settings-page.d.ts +4 -4
- package/dist/server/src/settings-page.js +17 -78
- package/docs/reference/http-api.md +34 -0
- package/docs/reference/reports.md +224 -0
- package/docs/reference/schema.md +10 -0
- package/docs/reference/server.md +4 -4
- package/docs/server.md +10 -0
- package/docs/ui.md +142 -0
- package/docs/workspaces.md +130 -0
- package/llms-full.txt +322 -0
- package/llms.txt +2 -0
- package/package.json +17 -10
- package/packages/schema/schemas/catalog-health.schema.json +400 -0
- package/packages/server/openapi.json +596 -0
- package/packages/visualizer/src/admin/SettingsPage.tsx +456 -0
- package/packages/visualizer/src/admin/main.tsx +11 -0
- package/packages/visualizer/src/app/AppShell.tsx +62 -38
- package/packages/visualizer/src/app/gazetteer.tsx +90 -83
- package/packages/visualizer/src/app/router.tsx +33 -15
- package/packages/visualizer/src/components/ActivityIndicator.tsx +4 -5
- package/packages/visualizer/src/components/DataIssues.tsx +36 -54
- package/packages/visualizer/src/components/Header.tsx +197 -125
- package/packages/visualizer/src/components/Legend.tsx +13 -41
- package/packages/visualizer/src/components/ProjectPicker.tsx +61 -26
- package/packages/visualizer/src/components/Screen.tsx +80 -71
- package/packages/visualizer/src/components/SpecLogo.tsx +15 -0
- package/packages/visualizer/src/components/Status.tsx +20 -34
- package/packages/visualizer/src/components/labels.tsx +8 -3
- package/packages/visualizer/src/components/spec-logos/APACHE-2.0.txt +206 -0
- package/packages/visualizer/src/components/spec-logos/CAMUNDA-MIT.txt +21 -0
- package/packages/visualizer/src/components/spec-logos/FILE-ICONS-ISC.txt +13 -0
- package/packages/visualizer/src/components/spec-logos/README.md +23 -0
- package/packages/visualizer/src/components/spec-logos/SIMPLE-ICONS-CC0.txt +30 -0
- package/packages/visualizer/src/components/spec-logos/alloy.svg +1 -0
- package/packages/visualizer/src/components/spec-logos/dmn.svg +3 -0
- package/packages/visualizer/src/components/spec-logos/gherkin.svg +1 -0
- package/packages/visualizer/src/components/spec-logos/openslo.svg +63 -0
- package/packages/visualizer/src/components/spec-logos/quint.svg +1 -0
- package/packages/visualizer/src/evidence/artifacts.tsx +263 -110
- package/packages/visualizer/src/evidence/chart-source.tsx +18 -0
- package/packages/visualizer/src/evidence/check-detail.tsx +283 -139
- package/packages/visualizer/src/evidence/decision-table.tsx +35 -26
- package/packages/visualizer/src/evidence/document-page.tsx +51 -29
- package/packages/visualizer/src/evidence/feature-page.tsx +121 -53
- package/packages/visualizer/src/evidence/marks.tsx +112 -79
- package/packages/visualizer/src/evidence/model-page.tsx +77 -46
- package/packages/visualizer/src/evidence/model-trace.tsx +55 -35
- package/packages/visualizer/src/evidence/overview.tsx +137 -69
- package/packages/visualizer/src/evidence/recording-page.tsx +70 -31
- package/packages/visualizer/src/evidence/recording.tsx +135 -68
- package/packages/visualizer/src/evidence/snapshot.tsx +99 -43
- package/packages/visualizer/src/evidence/source-text.tsx +33 -0
- package/packages/visualizer/src/evidence/sources-panel.tsx +138 -144
- package/packages/visualizer/src/evidence/spec-header.tsx +52 -36
- package/packages/visualizer/src/evidence/spec-index.tsx +61 -32
- package/packages/visualizer/src/evidence/spec-page.tsx +56 -25
- package/packages/visualizer/src/evidence/test-filter.tsx +38 -14
- package/packages/visualizer/src/explorer/Explorer.tsx +688 -261
- package/packages/visualizer/src/explorer/ExplorerIndex.tsx +136 -68
- package/packages/visualizer/src/explorer/RunsView.tsx +307 -94
- package/packages/visualizer/src/explorer/TestDetail.tsx +393 -118
- package/packages/visualizer/src/explorer/parts.tsx +35 -13
- package/packages/visualizer/src/find/Finder.tsx +106 -90
- package/packages/visualizer/src/find/open.ts +17 -20
- package/packages/visualizer/src/live/test-progress.tsx +60 -22
- package/packages/visualizer/src/looks/Stage.tsx +223 -110
- package/packages/visualizer/src/main.tsx +9 -11
- package/packages/visualizer/src/map/ChartMap.tsx +125 -69
- package/packages/visualizer/src/map/EventEdge.tsx +59 -37
- package/packages/visualizer/src/map/map.module.css +12 -546
- package/packages/visualizer/src/map/nodes.tsx +124 -70
- package/packages/visualizer/src/reachable.test.ts +3 -2
- package/packages/visualizer/src/spec-kind.ts +2 -2
- package/packages/visualizer/src/ui/grammars/ALLOY-MIT.txt +21 -0
- package/packages/visualizer/src/ui/grammars/QUINT-APACHE-2.0.txt +206 -0
- package/packages/visualizer/src/ui/grammars/README.md +14 -0
- package/packages/visualizer/src/ui/grammars/alloy.json +71 -0
- package/packages/visualizer/src/ui/grammars/quint.json +152 -0
- package/packages/visualizer/src/ui/highlight.ts +50 -0
- package/packages/visualizer/src/ui/theme.tsx +109 -0
- package/packages/visualizer/src/views/ChartPage.tsx +46 -26
- package/packages/visualizer/src/views/ChartTests.tsx +59 -22
- package/packages/visualizer/src/views/ProductPage.tsx +16 -15
- package/packages/visualizer/src/views/SidePanel.tsx +241 -131
- package/packages/visualizer/src/app/gazetteer.module.css +0 -107
- package/packages/visualizer/src/components/ActivityIndicator.module.css +0 -4
- package/packages/visualizer/src/components/DataIssues.module.css +0 -136
- package/packages/visualizer/src/components/Header.module.css +0 -114
- package/packages/visualizer/src/components/Legend.module.css +0 -84
- package/packages/visualizer/src/components/Screen.module.css +0 -312
- package/packages/visualizer/src/components/Status.module.css +0 -116
- package/packages/visualizer/src/components/icons.tsx +0 -156
- package/packages/visualizer/src/evidence/artifacts.module.css +0 -213
- package/packages/visualizer/src/evidence/evidence.module.css +0 -907
- package/packages/visualizer/src/evidence/recording.module.css +0 -460
- package/packages/visualizer/src/evidence/sources.module.css +0 -168
- package/packages/visualizer/src/evidence/spec-snapshot.tsx +0 -26
- package/packages/visualizer/src/explorer/explorer.module.css +0 -1238
- package/packages/visualizer/src/find/Finder.module.css +0 -168
- package/packages/visualizer/src/looks/stage.module.css +0 -300
- package/packages/visualizer/src/styles/global.css +0 -105
- package/packages/visualizer/src/styles/tokens.css +0 -80
- package/packages/visualizer/src/views/views.module.css +0 -546
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import { SpecLogo } from '../components/SpecLogo';
|
|
2
|
+
import { IconChevronDown, IconChevronRight } from '@tabler/icons-react';
|
|
3
|
+
import { ActionIcon, Badge, Box, Group, NavLink, Stack, Title } from '@mantine/core';
|
|
1
4
|
/**
|
|
2
5
|
* @module Project index
|
|
3
6
|
*
|
|
@@ -7,34 +10,39 @@
|
|
|
7
10
|
import type { StatusCounts } from '@crvouga/atlas/reports/evidence-types';
|
|
8
11
|
import { Link } from '@tanstack/react-router';
|
|
9
12
|
import { useMemo, useState } from 'react';
|
|
10
|
-
|
|
11
|
-
import evidenceStyles from '../evidence/evidence.module.css';
|
|
12
13
|
import { useEvidence } from '../evidence/evidence-context';
|
|
13
14
|
import { StatusMark } from '../evidence/marks';
|
|
14
15
|
import { SPEC_KINDS } from '../spec-kind';
|
|
15
16
|
import { useTestCatalog } from './catalog';
|
|
16
|
-
import styles from './explorer.module.css';
|
|
17
17
|
import { patched, useExplorerSearch } from './navigate';
|
|
18
18
|
import { values } from './search';
|
|
19
|
-
|
|
20
19
|
/** Domains start open when the index has at most this many specs. */
|
|
21
20
|
const OPEN_SPECS = 80;
|
|
22
|
-
|
|
23
21
|
function statusOf(counts: StatusCounts) {
|
|
24
22
|
return counts.failed ? 'failed' : counts.running ? 'running' : counts.passed ? 'passed' : 'not-run';
|
|
25
23
|
}
|
|
26
|
-
|
|
27
24
|
/** A tally for an index row: failures in red, otherwise how many tests, quietly. */
|
|
28
25
|
function Tally({ counts, tests }: { counts: StatusCounts; tests: number }) {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
26
|
+
return (
|
|
27
|
+
<Badge size="xs" color={counts.failed ? 'red' : counts.running ? 'blue' : counts.passed === tests ? 'green' : 'gray'}>
|
|
28
|
+
{counts.failed
|
|
29
|
+
? `${counts.failed} failed`
|
|
30
|
+
: counts.running
|
|
31
|
+
? 'Running'
|
|
32
|
+
: counts.passed === tests
|
|
33
|
+
? `${tests} passed`
|
|
34
|
+
: `${counts.passed}/${tests}`}
|
|
35
|
+
</Badge>
|
|
36
|
+
);
|
|
32
37
|
}
|
|
33
|
-
|
|
34
38
|
function add(a: StatusCounts, b: StatusCounts): StatusCounts {
|
|
35
|
-
return {
|
|
39
|
+
return {
|
|
40
|
+
passed: a.passed + b.passed,
|
|
41
|
+
failed: a.failed + b.failed,
|
|
42
|
+
running: a.running + b.running,
|
|
43
|
+
'not-run': a['not-run'] + b['not-run']
|
|
44
|
+
};
|
|
36
45
|
}
|
|
37
|
-
|
|
38
46
|
/** The index beside the explorer. */
|
|
39
47
|
export function ProjectIndex() {
|
|
40
48
|
const { files } = useEvidence();
|
|
@@ -42,7 +50,14 @@ export function ProjectIndex() {
|
|
|
42
50
|
const search = useExplorerSearch();
|
|
43
51
|
const kinds = SPEC_KINDS.filter((kind) => files.some(kind.accepts));
|
|
44
52
|
const domains = useMemo(() => {
|
|
45
|
-
const byDomain = new Map<
|
|
53
|
+
const byDomain = new Map<
|
|
54
|
+
string,
|
|
55
|
+
{
|
|
56
|
+
specs: NonNullable<typeof model>['facets']['specs'][number][];
|
|
57
|
+
counts: StatusCounts;
|
|
58
|
+
tests: number;
|
|
59
|
+
}
|
|
60
|
+
>();
|
|
46
61
|
for (const spec of model?.facets.specs ?? []) {
|
|
47
62
|
const domain = spec.domain || '(no domain)';
|
|
48
63
|
const entry = byDomain.get(domain) ?? { specs: [], counts: { passed: 0, failed: 0, running: 0, 'not-run': 0 }, tests: 0 };
|
|
@@ -57,64 +72,117 @@ export function ProjectIndex() {
|
|
|
57
72
|
const chosenSpecs = values(search.spec);
|
|
58
73
|
const chosenDomains = values(search.domain);
|
|
59
74
|
const [toggled, setToggled] = useState<ReadonlyMap<string, boolean>>(new Map());
|
|
60
|
-
const isOpen = (
|
|
75
|
+
const isOpen = (
|
|
76
|
+
domain: string,
|
|
77
|
+
specs: readonly {
|
|
78
|
+
path: string;
|
|
79
|
+
}[]
|
|
80
|
+
) =>
|
|
81
|
+
toggled.get(domain) ??
|
|
82
|
+
(specCount <= OPEN_SPECS || chosenDomains.includes(domain) || specs.some((spec) => chosenSpecs.includes(spec.path)));
|
|
61
83
|
const everything = !search.spec && !search.domain;
|
|
62
84
|
return (
|
|
63
|
-
<
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
<
|
|
67
|
-
|
|
85
|
+
<Box component="nav" aria-label="Project specs" p="md">
|
|
86
|
+
<Stack gap="lg">
|
|
87
|
+
{kinds.length > 0 && (
|
|
88
|
+
<Stack gap="xs">
|
|
89
|
+
<Title order={3} c="dimmed">
|
|
90
|
+
Specs
|
|
91
|
+
</Title>
|
|
68
92
|
{kinds.map((kind) => (
|
|
69
|
-
<
|
|
70
|
-
|
|
71
|
-
|
|
93
|
+
<NavLink
|
|
94
|
+
key={kind.id}
|
|
95
|
+
label={kind.label}
|
|
96
|
+
leftSection={<SpecLogo kind={kind} />}
|
|
97
|
+
renderRoot={(props) => <Link {...props} to="/specs/$kind" params={{ kind: kind.id }} search={{}} />}
|
|
98
|
+
/>
|
|
72
99
|
))}
|
|
73
|
-
</
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
<
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
100
|
+
</Stack>
|
|
101
|
+
)}
|
|
102
|
+
{domains.length > 0 && (
|
|
103
|
+
<Box component="section" aria-label="Tests by spec">
|
|
104
|
+
<Title order={3} c="dimmed" mb="sm">
|
|
105
|
+
Tests
|
|
106
|
+
</Title>
|
|
107
|
+
<NavLink
|
|
108
|
+
label="All tests"
|
|
109
|
+
active={everything}
|
|
110
|
+
rightSection={model && <Tally counts={model.summary.counts} tests={model.summary.tests} />}
|
|
111
|
+
aria-current={everything ? 'page' : undefined}
|
|
112
|
+
renderRoot={(props) => (
|
|
113
|
+
<Link
|
|
114
|
+
{...props}
|
|
115
|
+
to="/"
|
|
116
|
+
search={patched({ spec: undefined, domain: undefined, tab: undefined })}
|
|
117
|
+
resetScroll={false}
|
|
118
|
+
activeOptions={{ exact: true }}
|
|
119
|
+
/>
|
|
120
|
+
)}
|
|
121
|
+
/>
|
|
122
|
+
{domains.map(([domain, entry]) => {
|
|
123
|
+
const open = isOpen(domain, entry.specs);
|
|
124
|
+
const chosen = chosenDomains.length === 1 && chosenDomains[0] === domain && !search.spec;
|
|
125
|
+
return (
|
|
126
|
+
<Box key={domain} mt="sm">
|
|
127
|
+
<Group wrap="nowrap" gap={0}>
|
|
128
|
+
<ActionIcon
|
|
129
|
+
color="gray"
|
|
130
|
+
aria-expanded={open}
|
|
131
|
+
aria-label={`${open ? 'Collapse' : 'Expand'} ${domain}`}
|
|
132
|
+
onClick={() => setToggled(new Map(toggled).set(domain, !open))}
|
|
133
|
+
>
|
|
134
|
+
{open ? <IconChevronDown size={16} aria-hidden="true" /> : <IconChevronRight size={16} aria-hidden="true" />}
|
|
135
|
+
</ActionIcon>
|
|
136
|
+
<NavLink
|
|
137
|
+
flex={1}
|
|
138
|
+
label={domain}
|
|
139
|
+
active={chosen}
|
|
140
|
+
rightSection={<Tally counts={entry.counts} tests={entry.tests} />}
|
|
141
|
+
aria-current={chosen ? 'page' : undefined}
|
|
142
|
+
renderRoot={(props) => (
|
|
143
|
+
<Link
|
|
144
|
+
{...props}
|
|
145
|
+
to="/"
|
|
146
|
+
search={patched({ domain, spec: undefined, tab: undefined })}
|
|
147
|
+
resetScroll={false}
|
|
148
|
+
activeOptions={{ exact: true }}
|
|
149
|
+
/>
|
|
150
|
+
)}
|
|
151
|
+
/>
|
|
152
|
+
</Group>
|
|
153
|
+
{open && (
|
|
154
|
+
<Box pl="sm">
|
|
155
|
+
{entry.specs.map((spec) => {
|
|
156
|
+
const chosen = chosenSpecs.length === 1 && chosenSpecs[0] === spec.path;
|
|
157
|
+
return (
|
|
158
|
+
<NavLink
|
|
159
|
+
key={spec.path}
|
|
160
|
+
label={spec.title}
|
|
161
|
+
title={spec.path}
|
|
162
|
+
active={chosen}
|
|
163
|
+
leftSection={<StatusMark status={statusOf(spec.counts)} size={14} />}
|
|
164
|
+
rightSection={<Tally counts={spec.counts} tests={spec.tests} />}
|
|
165
|
+
aria-current={chosen ? 'page' : undefined}
|
|
166
|
+
renderRoot={(props) => (
|
|
167
|
+
<Link
|
|
168
|
+
{...props}
|
|
169
|
+
to="/"
|
|
170
|
+
search={patched({ spec: spec.path, domain: undefined, tab: undefined })}
|
|
171
|
+
resetScroll={false}
|
|
172
|
+
activeOptions={{ exact: true }}
|
|
173
|
+
/>
|
|
174
|
+
)}
|
|
175
|
+
/>
|
|
176
|
+
);
|
|
177
|
+
})}
|
|
178
|
+
</Box>
|
|
179
|
+
)}
|
|
180
|
+
</Box>
|
|
181
|
+
);
|
|
182
|
+
})}
|
|
183
|
+
</Box>
|
|
184
|
+
)}
|
|
185
|
+
</Stack>
|
|
186
|
+
</Box>
|
|
119
187
|
);
|
|
120
188
|
}
|