@acta-dev/web 1.0.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/LICENSE +21 -0
- package/astro.config.mjs +31 -0
- package/package.json +62 -0
- package/public/favicon.png +0 -0
- package/src/components/DocumentSearchList.astro +150 -0
- package/src/components/DocumentView.astro +198 -0
- package/src/components/LanguageSwitcher.tsx +115 -0
- package/src/components/SidebarToggle.tsx +42 -0
- package/src/components/ThemeToggle.tsx +129 -0
- package/src/components/graph/DocumentGraphIsland.tsx +226 -0
- package/src/components/graph/GraphContext.ts +15 -0
- package/src/components/graph/graph.css +330 -0
- package/src/components/graph/layout.ts +48 -0
- package/src/components/graph/nodes.tsx +80 -0
- package/src/components/ui/Button.astro +105 -0
- package/src/components/ui/Chip.astro +147 -0
- package/src/components/ui/Field.astro +29 -0
- package/src/components/ui/Input.astro +34 -0
- package/src/components/ui/Pill.astro +71 -0
- package/src/components/ui/SegmentedControl.astro +105 -0
- package/src/components/ui/Select.astro +41 -0
- package/src/components/ui/Tooltip.astro +94 -0
- package/src/layouts/BaseLayout.astro +147 -0
- package/src/lib/documents.test.ts +175 -0
- package/src/lib/documents.ts +156 -0
- package/src/lib/i18n-client.ts +32 -0
- package/src/lib/i18n.ts +92 -0
- package/src/lib/project.test.ts +24 -0
- package/src/lib/project.ts +120 -0
- package/src/lib/search-client.ts +192 -0
- package/src/lib/search.test.ts +94 -0
- package/src/lib/search.ts +153 -0
- package/src/locales/en/common.json +6 -0
- package/src/locales/en/dashboard.json +8 -0
- package/src/locales/en/documents.json +63 -0
- package/src/locales/en/graph.json +19 -0
- package/src/locales/en/search.json +7 -0
- package/src/locales/en/sidebar.json +25 -0
- package/src/locales/en/validation.json +13 -0
- package/src/locales/ru/common.json +6 -0
- package/src/locales/ru/dashboard.json +8 -0
- package/src/locales/ru/documents.json +63 -0
- package/src/locales/ru/graph.json +19 -0
- package/src/locales/ru/search.json +7 -0
- package/src/locales/ru/sidebar.json +25 -0
- package/src/locales/ru/validation.json +13 -0
- package/src/pages/documents/[id]/index.astro +39 -0
- package/src/pages/graph.astro +54 -0
- package/src/pages/index.astro +41 -0
- package/src/pages/ru/documents/[id]/index.astro +39 -0
- package/src/pages/ru/graph.astro +54 -0
- package/src/pages/ru/index.astro +41 -0
- package/src/pages/ru/search-index-full.json.ts +1 -0
- package/src/pages/ru/search.astro +27 -0
- package/src/pages/ru/validation.astro +63 -0
- package/src/pages/search-index-full.json.ts +12 -0
- package/src/pages/search-index.json.ts +12 -0
- package/src/pages/search.astro +27 -0
- package/src/pages/validation.astro +63 -0
- package/src/styles/global.css +1391 -0
- package/src/styles/themes/dark.css +61 -0
- package/src/styles/themes/light.css +63 -0
- package/src/styles/tokens/primitives.css +32 -0
- package/src/styles/tokens/semantic.css +34 -0
- package/src/styles/tokens/typography.css +28 -0
- package/tsconfig.json +11 -0
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"brand": {
|
|
3
|
+
"subtitle": "ADR and Specs"
|
|
4
|
+
},
|
|
5
|
+
"nav": {
|
|
6
|
+
"documents": "Documents",
|
|
7
|
+
"graph": "Graph",
|
|
8
|
+
"validation": "Validation"
|
|
9
|
+
},
|
|
10
|
+
"theme": {
|
|
11
|
+
"legend": "Theme",
|
|
12
|
+
"system": "System",
|
|
13
|
+
"light": "Light",
|
|
14
|
+
"dark": "Dark"
|
|
15
|
+
},
|
|
16
|
+
"sidebar": {
|
|
17
|
+
"collapse": "Collapse sidebar",
|
|
18
|
+
"expand": "Expand sidebar"
|
|
19
|
+
},
|
|
20
|
+
"language": {
|
|
21
|
+
"legend": "Language",
|
|
22
|
+
"en": "English",
|
|
23
|
+
"ru": "Russian"
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"tab": "Acta validation",
|
|
3
|
+
"meta": "Acta validation results",
|
|
4
|
+
"eyebrow": "Repository health",
|
|
5
|
+
"header": "Validation",
|
|
6
|
+
"counts": "{{errors}} errors, {{warnings}} warnings",
|
|
7
|
+
"empty": "No validation issues.",
|
|
8
|
+
"severity": {
|
|
9
|
+
"error": "error",
|
|
10
|
+
"warning": "warning",
|
|
11
|
+
"info": "info"
|
|
12
|
+
}
|
|
13
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
{
|
|
2
|
+
"tab": "Acta — документы",
|
|
3
|
+
"meta": "Просмотр ADR и спецификаций Acta",
|
|
4
|
+
"eyebrow": "Просмотр репозитория",
|
|
5
|
+
"header": "Документы",
|
|
6
|
+
"counts": "{{count}} документов, {{adrs}} ADR, {{specs}} спецификаций",
|
|
7
|
+
"issuesPill": "{{errors}} ошибок · {{warnings}} предупреждений"
|
|
8
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
{
|
|
2
|
+
"filters": {
|
|
3
|
+
"legend": "Фильтры документов",
|
|
4
|
+
"search": "Поиск",
|
|
5
|
+
"searchPlaceholder": "Заголовок, тег, владелец, раздел...",
|
|
6
|
+
"kind": "Тип",
|
|
7
|
+
"status": "Статус",
|
|
8
|
+
"tag": "Тег",
|
|
9
|
+
"component": "Компонент",
|
|
10
|
+
"sort": "Сортировка",
|
|
11
|
+
"sortNewest": "Сначала новые",
|
|
12
|
+
"sortDependency": "По зависимостям",
|
|
13
|
+
"searchContent": "Искать в содержимом",
|
|
14
|
+
"searchingContent": "Идет поиск по содержимому..."
|
|
15
|
+
},
|
|
16
|
+
"empty": "Нет подходящих документов.",
|
|
17
|
+
"showMore": "Показать ещё",
|
|
18
|
+
"detail": {
|
|
19
|
+
"file": "Файл",
|
|
20
|
+
"owners": "Владельцы",
|
|
21
|
+
"tags": "Теги",
|
|
22
|
+
"components": "Компоненты",
|
|
23
|
+
"validation": "Валидация",
|
|
24
|
+
"links": "Ссылки",
|
|
25
|
+
"backlinks": "Обратные ссылки",
|
|
26
|
+
"externalReferences": "Внешние ссылки",
|
|
27
|
+
"noOutgoing": "Нет исходящих внутренних ссылок.",
|
|
28
|
+
"noBacklinks": "Нет обратных ссылок.",
|
|
29
|
+
"back": "К списку документов"
|
|
30
|
+
},
|
|
31
|
+
"linkTypes": {
|
|
32
|
+
"tooltipOutgoing": "Что значит \"{{key}}\"?",
|
|
33
|
+
"tooltipIncoming": "Что значит \"{{key}}\" (входящие)?",
|
|
34
|
+
"related": {
|
|
35
|
+
"outgoing": "Свободная семантическая связь — общий контекст, без зависимости.",
|
|
36
|
+
"incoming": "Другие документы, отмечающие этот как связанный контекст."
|
|
37
|
+
},
|
|
38
|
+
"supersedes": {
|
|
39
|
+
"outgoing": "Этот документ заменяет указанные.",
|
|
40
|
+
"incoming": "Документы, заменяющие этот (этот устарел)."
|
|
41
|
+
},
|
|
42
|
+
"replacedBy": {
|
|
43
|
+
"outgoing": "Указанные документы заменяют этот.",
|
|
44
|
+
"incoming": "Документы, которые заменяет этот."
|
|
45
|
+
},
|
|
46
|
+
"decidedBy": {
|
|
47
|
+
"outgoing": "Решения (ADR), определяющие этот документ.",
|
|
48
|
+
"incoming": "Документы, определяемые решением, зафиксированным здесь."
|
|
49
|
+
},
|
|
50
|
+
"dependsOn": {
|
|
51
|
+
"outgoing": "Документы, от которых зависит этот.",
|
|
52
|
+
"incoming": "Документы, зависящие от этого."
|
|
53
|
+
},
|
|
54
|
+
"validates": {
|
|
55
|
+
"outgoing": "Документы, которые проверяет этот (например, тесты/спеки подтверждают решения).",
|
|
56
|
+
"incoming": "Документы, проверяющие этот."
|
|
57
|
+
},
|
|
58
|
+
"references": {
|
|
59
|
+
"outgoing": "Внешние URL, упоминаемые в этом документе.",
|
|
60
|
+
"incoming": "Внешние ссылки, указывающие сюда."
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"tab": "Acta — граф",
|
|
3
|
+
"meta": "Исследуйте связи между документами Acta",
|
|
4
|
+
"eyebrow": "Просмотр репозитория",
|
|
5
|
+
"header": "Граф",
|
|
6
|
+
"counts": "{{nodes}} узлов, {{edges}} связей",
|
|
7
|
+
"filters": {
|
|
8
|
+
"legend": "Фильтры графа",
|
|
9
|
+
"kind": "Тип",
|
|
10
|
+
"status": "Статус"
|
|
11
|
+
},
|
|
12
|
+
"areaLabel": "Граф связей документов",
|
|
13
|
+
"legend": {
|
|
14
|
+
"label": "Легенда графа",
|
|
15
|
+
"dependency": "Зависимость",
|
|
16
|
+
"related": "Связано",
|
|
17
|
+
"supersession": "Замещение"
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"brand": {
|
|
3
|
+
"subtitle": "ADR и спецификации"
|
|
4
|
+
},
|
|
5
|
+
"nav": {
|
|
6
|
+
"documents": "Документы",
|
|
7
|
+
"graph": "Граф",
|
|
8
|
+
"validation": "Валидация"
|
|
9
|
+
},
|
|
10
|
+
"theme": {
|
|
11
|
+
"legend": "Тема",
|
|
12
|
+
"system": "Системная",
|
|
13
|
+
"light": "Светлая",
|
|
14
|
+
"dark": "Тёмная"
|
|
15
|
+
},
|
|
16
|
+
"sidebar": {
|
|
17
|
+
"collapse": "Свернуть боковую панель",
|
|
18
|
+
"expand": "Развернуть боковую панель"
|
|
19
|
+
},
|
|
20
|
+
"language": {
|
|
21
|
+
"legend": "Язык",
|
|
22
|
+
"en": "Английский",
|
|
23
|
+
"ru": "Русский"
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"tab": "Acta — валидация",
|
|
3
|
+
"meta": "Результаты валидации Acta",
|
|
4
|
+
"eyebrow": "Состояние репозитория",
|
|
5
|
+
"header": "Валидация",
|
|
6
|
+
"counts": "{{errors}} ошибок, {{warnings}} предупреждений",
|
|
7
|
+
"empty": "Проблем валидации нет.",
|
|
8
|
+
"severity": {
|
|
9
|
+
"error": "ошибка",
|
|
10
|
+
"warning": "предупреждение",
|
|
11
|
+
"info": "инфо"
|
|
12
|
+
}
|
|
13
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { renderMarkdown } from "@acta-dev/renderer";
|
|
3
|
+
import BaseLayout from "../../../layouts/BaseLayout.astro";
|
|
4
|
+
import DocumentView from "../../../components/DocumentView.astro";
|
|
5
|
+
import { getIssuesForDocument } from "@lib/documents.js";
|
|
6
|
+
import { loadActaWebData } from "@lib/project.js";
|
|
7
|
+
import { defaultLocale, isLocale, type Locale } from "@lib/i18n.js";
|
|
8
|
+
|
|
9
|
+
export async function getStaticPaths() {
|
|
10
|
+
const { project, validation } = await loadActaWebData();
|
|
11
|
+
|
|
12
|
+
return Promise.all(
|
|
13
|
+
project.documents.map(async (document) => ({
|
|
14
|
+
params: { id: document.id },
|
|
15
|
+
props: {
|
|
16
|
+
document,
|
|
17
|
+
documents: project.documents,
|
|
18
|
+
issues: getIssuesForDocument(validation.issues, document),
|
|
19
|
+
rendered: await renderMarkdown(document.body),
|
|
20
|
+
},
|
|
21
|
+
})),
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const { document, documents, issues, rendered } = Astro.props;
|
|
26
|
+
|
|
27
|
+
const rawLocale = Astro.currentLocale ?? defaultLocale;
|
|
28
|
+
const locale: Locale = isLocale(rawLocale) ? rawLocale : defaultLocale;
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
<BaseLayout title={`${document.id} · ${document.title}`} description={document.summary}>
|
|
32
|
+
<DocumentView
|
|
33
|
+
document={document}
|
|
34
|
+
documents={documents}
|
|
35
|
+
issues={issues}
|
|
36
|
+
rendered={rendered}
|
|
37
|
+
locale={locale}
|
|
38
|
+
/>
|
|
39
|
+
</BaseLayout>
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
---
|
|
2
|
+
import BaseLayout from "../layouts/BaseLayout.astro";
|
|
3
|
+
import { buildDocumentHref, collectFilterOptions } from "@lib/documents.js";
|
|
4
|
+
import { loadActaWebData } from "@lib/project.js";
|
|
5
|
+
import { defaultLocale, getT, isLocale, localizedHref, type Locale } from "@lib/i18n.js";
|
|
6
|
+
import DocumentGraphIsland from "../components/graph/DocumentGraphIsland.tsx";
|
|
7
|
+
|
|
8
|
+
const { project } = await loadActaWebData();
|
|
9
|
+
const documents = project.documents;
|
|
10
|
+
const filterOptions = collectFilterOptions(documents);
|
|
11
|
+
|
|
12
|
+
const rawLocale = Astro.currentLocale ?? defaultLocale;
|
|
13
|
+
const locale: Locale = isLocale(rawLocale) ? rawLocale : defaultLocale;
|
|
14
|
+
const t = await getT(locale);
|
|
15
|
+
|
|
16
|
+
const hrefForId = Object.fromEntries(
|
|
17
|
+
documents.map((d) => [d.id, localizedHref(locale, buildDocumentHref(d.id))]),
|
|
18
|
+
);
|
|
19
|
+
|
|
20
|
+
const tg = (key: string, params?: Record<string, unknown>) => t(`graph:${key}`, params);
|
|
21
|
+
const tc = (key: string) => t(`common:${key}`);
|
|
22
|
+
|
|
23
|
+
const graphLabels = {
|
|
24
|
+
filtersLegend: tg("filters.legend"),
|
|
25
|
+
filterKind: tg("filters.kind"),
|
|
26
|
+
filterStatus: tg("filters.status"),
|
|
27
|
+
all: tc("all"),
|
|
28
|
+
areaLabel: tg("areaLabel"),
|
|
29
|
+
legendLabel: tg("legend.label"),
|
|
30
|
+
legendDependency: tg("legend.dependency"),
|
|
31
|
+
legendRelated: tg("legend.related"),
|
|
32
|
+
legendSupersession: tg("legend.supersession"),
|
|
33
|
+
};
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
<BaseLayout title={tg("tab")} description={tg("meta")}>
|
|
37
|
+
<section class="page-header">
|
|
38
|
+
<div class="crumbs">
|
|
39
|
+
<span>{tg("eyebrow")}</span>
|
|
40
|
+
</div>
|
|
41
|
+
<h1>{tg("header")}<span class="accent-period">.</span></h1>
|
|
42
|
+
<p class="page-sub">
|
|
43
|
+
{tg("counts", { nodes: project.graph.nodes.length, edges: project.graph.edges.length })}
|
|
44
|
+
</p>
|
|
45
|
+
</section>
|
|
46
|
+
|
|
47
|
+
<DocumentGraphIsland
|
|
48
|
+
client:load
|
|
49
|
+
graph={project.graph}
|
|
50
|
+
filterOptions={filterOptions}
|
|
51
|
+
hrefForId={hrefForId}
|
|
52
|
+
labels={graphLabels}
|
|
53
|
+
/>
|
|
54
|
+
</BaseLayout>
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
---
|
|
2
|
+
import BaseLayout from "../layouts/BaseLayout.astro";
|
|
3
|
+
import DocumentSearchList from "../components/DocumentSearchList.astro";
|
|
4
|
+
import Pill from "../components/ui/Pill.astro";
|
|
5
|
+
import { loadActaWebData } from "@lib/project.js";
|
|
6
|
+
import { defaultLocale, getT, isLocale, localizedHref, type Locale } from "@lib/i18n.js";
|
|
7
|
+
|
|
8
|
+
const { project, validation } = await loadActaWebData();
|
|
9
|
+
const documents = project.documents;
|
|
10
|
+
const adrCount = documents.filter((document) => document.kind === "adr").length;
|
|
11
|
+
const specCount = documents.filter((document) => document.kind === "spec").length;
|
|
12
|
+
|
|
13
|
+
const rawLocale = Astro.currentLocale ?? defaultLocale;
|
|
14
|
+
const locale: Locale = isLocale(rawLocale) ? rawLocale : defaultLocale;
|
|
15
|
+
const t = await getT(locale);
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
<BaseLayout title={t("dashboard:tab")} description={t("dashboard:meta")}>
|
|
19
|
+
<section class="page-header">
|
|
20
|
+
<div class="crumbs">
|
|
21
|
+
<span>{t("dashboard:eyebrow")}</span>
|
|
22
|
+
<span class="grow"></span>
|
|
23
|
+
<Pill
|
|
24
|
+
as="a"
|
|
25
|
+
href={localizedHref(locale, "/validation/")}
|
|
26
|
+
tone={validation.valid ? "success" : "danger"}
|
|
27
|
+
>
|
|
28
|
+
{t("dashboard:issuesPill", { errors: validation.errorCount, warnings: validation.warningCount })}
|
|
29
|
+
</Pill>
|
|
30
|
+
</div>
|
|
31
|
+
<h1>{t("dashboard:header")}<span class="accent-period">.</span></h1>
|
|
32
|
+
<p class="page-sub">
|
|
33
|
+
{t("dashboard:counts", { count: documents.length, adrs: adrCount, specs: specCount })}
|
|
34
|
+
</p>
|
|
35
|
+
</section>
|
|
36
|
+
|
|
37
|
+
<DocumentSearchList
|
|
38
|
+
documents={documents}
|
|
39
|
+
dependencyDocumentIds={project.ordering.documentIds}
|
|
40
|
+
/>
|
|
41
|
+
</BaseLayout>
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { renderMarkdown } from "@acta-dev/renderer";
|
|
3
|
+
import BaseLayout from "../../../../layouts/BaseLayout.astro";
|
|
4
|
+
import DocumentView from "../../../../components/DocumentView.astro";
|
|
5
|
+
import { getIssuesForDocument } from "@lib/documents.js";
|
|
6
|
+
import { loadActaWebData } from "@lib/project.js";
|
|
7
|
+
import { defaultLocale, isLocale, type Locale } from "@lib/i18n.js";
|
|
8
|
+
|
|
9
|
+
export async function getStaticPaths() {
|
|
10
|
+
const { project, validation } = await loadActaWebData();
|
|
11
|
+
|
|
12
|
+
return Promise.all(
|
|
13
|
+
project.documents.map(async (document) => ({
|
|
14
|
+
params: { id: document.id },
|
|
15
|
+
props: {
|
|
16
|
+
document,
|
|
17
|
+
documents: project.documents,
|
|
18
|
+
issues: getIssuesForDocument(validation.issues, document),
|
|
19
|
+
rendered: await renderMarkdown(document.body),
|
|
20
|
+
},
|
|
21
|
+
})),
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const { document, documents, issues, rendered } = Astro.props;
|
|
26
|
+
|
|
27
|
+
const rawLocale = Astro.currentLocale ?? defaultLocale;
|
|
28
|
+
const locale: Locale = isLocale(rawLocale) ? rawLocale : defaultLocale;
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
<BaseLayout title={`${document.id} · ${document.title}`} description={document.summary}>
|
|
32
|
+
<DocumentView
|
|
33
|
+
document={document}
|
|
34
|
+
documents={documents}
|
|
35
|
+
issues={issues}
|
|
36
|
+
rendered={rendered}
|
|
37
|
+
locale={locale}
|
|
38
|
+
/>
|
|
39
|
+
</BaseLayout>
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
---
|
|
2
|
+
import BaseLayout from "../../layouts/BaseLayout.astro";
|
|
3
|
+
import { buildDocumentHref, collectFilterOptions } from "@lib/documents.js";
|
|
4
|
+
import { loadActaWebData } from "@lib/project.js";
|
|
5
|
+
import { defaultLocale, getT, isLocale, localizedHref, type Locale } from "@lib/i18n.js";
|
|
6
|
+
import DocumentGraphIsland from "../../components/graph/DocumentGraphIsland.tsx";
|
|
7
|
+
|
|
8
|
+
const { project } = await loadActaWebData();
|
|
9
|
+
const documents = project.documents;
|
|
10
|
+
const filterOptions = collectFilterOptions(documents);
|
|
11
|
+
|
|
12
|
+
const rawLocale = Astro.currentLocale ?? defaultLocale;
|
|
13
|
+
const locale: Locale = isLocale(rawLocale) ? rawLocale : defaultLocale;
|
|
14
|
+
const t = await getT(locale);
|
|
15
|
+
|
|
16
|
+
const hrefForId = Object.fromEntries(
|
|
17
|
+
documents.map((d) => [d.id, localizedHref(locale, buildDocumentHref(d.id))]),
|
|
18
|
+
);
|
|
19
|
+
|
|
20
|
+
const tg = (key: string, params?: Record<string, unknown>) => t(`graph:${key}`, params);
|
|
21
|
+
const tc = (key: string) => t(`common:${key}`);
|
|
22
|
+
|
|
23
|
+
const graphLabels = {
|
|
24
|
+
filtersLegend: tg("filters.legend"),
|
|
25
|
+
filterKind: tg("filters.kind"),
|
|
26
|
+
filterStatus: tg("filters.status"),
|
|
27
|
+
all: tc("all"),
|
|
28
|
+
areaLabel: tg("areaLabel"),
|
|
29
|
+
legendLabel: tg("legend.label"),
|
|
30
|
+
legendDependency: tg("legend.dependency"),
|
|
31
|
+
legendRelated: tg("legend.related"),
|
|
32
|
+
legendSupersession: tg("legend.supersession"),
|
|
33
|
+
};
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
<BaseLayout title={tg("tab")} description={tg("meta")}>
|
|
37
|
+
<section class="page-header">
|
|
38
|
+
<div class="crumbs">
|
|
39
|
+
<span>{tg("eyebrow")}</span>
|
|
40
|
+
</div>
|
|
41
|
+
<h1>{tg("header")}<span class="accent-period">.</span></h1>
|
|
42
|
+
<p class="page-sub">
|
|
43
|
+
{tg("counts", { nodes: project.graph.nodes.length, edges: project.graph.edges.length })}
|
|
44
|
+
</p>
|
|
45
|
+
</section>
|
|
46
|
+
|
|
47
|
+
<DocumentGraphIsland
|
|
48
|
+
client:load
|
|
49
|
+
graph={project.graph}
|
|
50
|
+
filterOptions={filterOptions}
|
|
51
|
+
hrefForId={hrefForId}
|
|
52
|
+
labels={graphLabels}
|
|
53
|
+
/>
|
|
54
|
+
</BaseLayout>
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
---
|
|
2
|
+
import BaseLayout from "../../layouts/BaseLayout.astro";
|
|
3
|
+
import DocumentSearchList from "../../components/DocumentSearchList.astro";
|
|
4
|
+
import Pill from "../../components/ui/Pill.astro";
|
|
5
|
+
import { loadActaWebData } from "@lib/project.js";
|
|
6
|
+
import { defaultLocale, getT, isLocale, localizedHref, type Locale } from "@lib/i18n.js";
|
|
7
|
+
|
|
8
|
+
const { project, validation } = await loadActaWebData();
|
|
9
|
+
const documents = project.documents;
|
|
10
|
+
const adrCount = documents.filter((document) => document.kind === "adr").length;
|
|
11
|
+
const specCount = documents.filter((document) => document.kind === "spec").length;
|
|
12
|
+
|
|
13
|
+
const rawLocale = Astro.currentLocale ?? defaultLocale;
|
|
14
|
+
const locale: Locale = isLocale(rawLocale) ? rawLocale : defaultLocale;
|
|
15
|
+
const t = await getT(locale);
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
<BaseLayout title={t("dashboard:tab")} description={t("dashboard:meta")}>
|
|
19
|
+
<section class="page-header">
|
|
20
|
+
<div class="crumbs">
|
|
21
|
+
<span>{t("dashboard:eyebrow")}</span>
|
|
22
|
+
<span class="grow"></span>
|
|
23
|
+
<Pill
|
|
24
|
+
as="a"
|
|
25
|
+
href={localizedHref(locale, "/validation/")}
|
|
26
|
+
tone={validation.valid ? "success" : "danger"}
|
|
27
|
+
>
|
|
28
|
+
{t("dashboard:issuesPill", { errors: validation.errorCount, warnings: validation.warningCount })}
|
|
29
|
+
</Pill>
|
|
30
|
+
</div>
|
|
31
|
+
<h1>{t("dashboard:header")}<span class="accent-period">.</span></h1>
|
|
32
|
+
<p class="page-sub">
|
|
33
|
+
{t("dashboard:counts", { count: documents.length, adrs: adrCount, specs: specCount })}
|
|
34
|
+
</p>
|
|
35
|
+
</section>
|
|
36
|
+
|
|
37
|
+
<DocumentSearchList
|
|
38
|
+
documents={documents}
|
|
39
|
+
dependencyDocumentIds={project.ordering.documentIds}
|
|
40
|
+
/>
|
|
41
|
+
</BaseLayout>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { GET } from "../search-index-full.json";
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
---
|
|
2
|
+
import DocumentSearchList from "../../components/DocumentSearchList.astro";
|
|
3
|
+
import BaseLayout from "../../layouts/BaseLayout.astro";
|
|
4
|
+
import { loadActaWebData } from "@lib/project.js";
|
|
5
|
+
import { defaultLocale, getT, isLocale, type Locale } from "@lib/i18n.js";
|
|
6
|
+
|
|
7
|
+
const { project } = await loadActaWebData();
|
|
8
|
+
|
|
9
|
+
const rawLocale = Astro.currentLocale ?? defaultLocale;
|
|
10
|
+
const locale: Locale = isLocale(rawLocale) ? rawLocale : defaultLocale;
|
|
11
|
+
const t = await getT(locale);
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
<BaseLayout title={t("search:tab")} description={t("search:meta")}>
|
|
15
|
+
<section class="page-header">
|
|
16
|
+
<div>
|
|
17
|
+
<p class="eyebrow">{t("search:eyebrow")}</p>
|
|
18
|
+
<h1>{t("search:header")}</h1>
|
|
19
|
+
<p class="muted">{t("search:counts", { count: project.documents.length })}</p>
|
|
20
|
+
</div>
|
|
21
|
+
</section>
|
|
22
|
+
|
|
23
|
+
<DocumentSearchList
|
|
24
|
+
documents={project.documents}
|
|
25
|
+
dependencyDocumentIds={project.ordering.documentIds}
|
|
26
|
+
/>
|
|
27
|
+
</BaseLayout>
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
---
|
|
2
|
+
import BaseLayout from "../../layouts/BaseLayout.astro";
|
|
3
|
+
import Pill from "../../components/ui/Pill.astro";
|
|
4
|
+
import { buildDocumentHref } from "@lib/documents.js";
|
|
5
|
+
import { loadActaWebData } from "@lib/project.js";
|
|
6
|
+
import { defaultLocale, getT, isLocale, localizedHref, type Locale } from "@lib/i18n.js";
|
|
7
|
+
|
|
8
|
+
const { project, validation } = await loadActaWebData();
|
|
9
|
+
const documentsById = new Map(project.documents.map((document) => [document.id, document]));
|
|
10
|
+
|
|
11
|
+
const rawLocale = Astro.currentLocale ?? defaultLocale;
|
|
12
|
+
const locale: Locale = isLocale(rawLocale) ? rawLocale : defaultLocale;
|
|
13
|
+
const t = await getT(locale);
|
|
14
|
+
const severityLabel = (sev: string) => t(`validation:severity.${sev}`);
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
<BaseLayout title={t("validation:tab")} description={t("validation:meta")}>
|
|
18
|
+
<section class="page-header">
|
|
19
|
+
<div class="crumbs">
|
|
20
|
+
<span>{t("validation:eyebrow")}</span>
|
|
21
|
+
<span class="grow"></span>
|
|
22
|
+
<Pill
|
|
23
|
+
as="a"
|
|
24
|
+
href={localizedHref(locale, "/validation/")}
|
|
25
|
+
tone={validation.valid ? "success" : "danger"}
|
|
26
|
+
>
|
|
27
|
+
{validation.valid ? t("common:valid") : t("common:needsAttention")}
|
|
28
|
+
</Pill>
|
|
29
|
+
</div>
|
|
30
|
+
<h1>{t("validation:header")}<span class="accent-period">.</span></h1>
|
|
31
|
+
<p class="page-sub">
|
|
32
|
+
{t("validation:counts", { errors: validation.errorCount, warnings: validation.warningCount })}
|
|
33
|
+
</p>
|
|
34
|
+
</section>
|
|
35
|
+
|
|
36
|
+
{
|
|
37
|
+
validation.issues.length === 0 ? (
|
|
38
|
+
<p class="empty-state">{t("validation:empty")}</p>
|
|
39
|
+
) : (
|
|
40
|
+
<section class="issue-list">
|
|
41
|
+
{validation.issues.map((issue) => {
|
|
42
|
+
const document = issue.documentId ? documentsById.get(issue.documentId) : undefined;
|
|
43
|
+
return (
|
|
44
|
+
<article class={`issue severity-${issue.severity}`}>
|
|
45
|
+
<div>
|
|
46
|
+
<strong>{severityLabel(issue.severity)}</strong>
|
|
47
|
+
<span>{issue.ruleId}</span>
|
|
48
|
+
</div>
|
|
49
|
+
<p>{issue.message}</p>
|
|
50
|
+
{document ? (
|
|
51
|
+
<a href={localizedHref(locale, buildDocumentHref(document.id))}>
|
|
52
|
+
{document.id} · {document.title}
|
|
53
|
+
</a>
|
|
54
|
+
) : (
|
|
55
|
+
issue.path && <span class="muted">{issue.path}</span>
|
|
56
|
+
)}
|
|
57
|
+
</article>
|
|
58
|
+
);
|
|
59
|
+
})}
|
|
60
|
+
</section>
|
|
61
|
+
)
|
|
62
|
+
}
|
|
63
|
+
</BaseLayout>
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { buildFullSearchIndex } from "@acta-dev/core";
|
|
2
|
+
import { loadActaWebData } from "@lib/project.js";
|
|
3
|
+
|
|
4
|
+
export async function GET() {
|
|
5
|
+
const { project } = await loadActaWebData();
|
|
6
|
+
|
|
7
|
+
return new Response(JSON.stringify(buildFullSearchIndex(project.documents)), {
|
|
8
|
+
headers: {
|
|
9
|
+
"content-type": "application/json; charset=utf-8",
|
|
10
|
+
},
|
|
11
|
+
});
|
|
12
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { buildSearchIndex } from "@acta-dev/core";
|
|
2
|
+
import { loadActaWebData } from "@lib/project.js";
|
|
3
|
+
|
|
4
|
+
export async function GET() {
|
|
5
|
+
const { project } = await loadActaWebData();
|
|
6
|
+
|
|
7
|
+
return new Response(JSON.stringify(buildSearchIndex(project.documents)), {
|
|
8
|
+
headers: {
|
|
9
|
+
"content-type": "application/json; charset=utf-8",
|
|
10
|
+
},
|
|
11
|
+
});
|
|
12
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
---
|
|
2
|
+
import DocumentSearchList from "../components/DocumentSearchList.astro";
|
|
3
|
+
import BaseLayout from "../layouts/BaseLayout.astro";
|
|
4
|
+
import { loadActaWebData } from "@lib/project.js";
|
|
5
|
+
import { defaultLocale, getT, isLocale, type Locale } from "@lib/i18n.js";
|
|
6
|
+
|
|
7
|
+
const { project } = await loadActaWebData();
|
|
8
|
+
|
|
9
|
+
const rawLocale = Astro.currentLocale ?? defaultLocale;
|
|
10
|
+
const locale: Locale = isLocale(rawLocale) ? rawLocale : defaultLocale;
|
|
11
|
+
const t = await getT(locale);
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
<BaseLayout title={t("search:tab")} description={t("search:meta")}>
|
|
15
|
+
<section class="page-header">
|
|
16
|
+
<div>
|
|
17
|
+
<p class="eyebrow">{t("search:eyebrow")}</p>
|
|
18
|
+
<h1>{t("search:header")}</h1>
|
|
19
|
+
<p class="muted">{t("search:counts", { count: project.documents.length })}</p>
|
|
20
|
+
</div>
|
|
21
|
+
</section>
|
|
22
|
+
|
|
23
|
+
<DocumentSearchList
|
|
24
|
+
documents={project.documents}
|
|
25
|
+
dependencyDocumentIds={project.ordering.documentIds}
|
|
26
|
+
/>
|
|
27
|
+
</BaseLayout>
|