@allurereport/web-awesome 3.2.0 → 3.3.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/dist/multi/173.app-8be6acc0a596a2197dbf.js +1 -0
- package/dist/multi/174.app-8be6acc0a596a2197dbf.js +1 -0
- package/dist/multi/252.app-8be6acc0a596a2197dbf.js +1 -0
- package/dist/multi/282.app-8be6acc0a596a2197dbf.js +1 -0
- package/dist/multi/29.app-8be6acc0a596a2197dbf.js +1 -0
- package/dist/multi/416.app-8be6acc0a596a2197dbf.js +1 -0
- package/dist/multi/527.app-8be6acc0a596a2197dbf.js +1 -0
- package/dist/multi/600.app-8be6acc0a596a2197dbf.js +1 -0
- package/dist/multi/605.app-8be6acc0a596a2197dbf.js +1 -0
- package/dist/multi/638.app-8be6acc0a596a2197dbf.js +1 -0
- package/dist/multi/672.app-8be6acc0a596a2197dbf.js +1 -0
- package/dist/multi/686.app-8be6acc0a596a2197dbf.js +1 -0
- package/dist/multi/725.app-8be6acc0a596a2197dbf.js +1 -0
- package/dist/multi/741.app-8be6acc0a596a2197dbf.js +1 -0
- package/dist/multi/749.app-8be6acc0a596a2197dbf.js +1 -0
- package/dist/multi/755.app-8be6acc0a596a2197dbf.js +1 -0
- package/dist/multi/894.app-8be6acc0a596a2197dbf.js +1 -0
- package/dist/multi/943.app-8be6acc0a596a2197dbf.js +1 -0
- package/dist/multi/980.app-8be6acc0a596a2197dbf.js +1 -0
- package/dist/multi/app-8be6acc0a596a2197dbf.js +2 -0
- package/dist/multi/manifest.json +21 -21
- package/dist/multi/{styles-13107bbe6906beabc50f.css → styles-0b84e1ef76554ad2db9a.css} +15 -6
- package/dist/single/app-8221eb856e47b4ef50d6.js +2 -0
- package/dist/single/manifest.json +1 -1
- package/package.json +6 -6
- package/src/components/BaseLayout/index.tsx +5 -4
- package/src/components/Categories/CategoriesTree/index.tsx +14 -0
- package/src/components/Categories/CategoriesTree/styles.scss +14 -0
- package/src/components/Categories/CategoryHeaderItem/index.tsx +50 -0
- package/src/components/Categories/CategoryHeaderItem/styles.scss +32 -0
- package/src/components/Categories/CategoryTreeItem/index.tsx +309 -0
- package/src/components/Categories/CategoryTreeItem/styles.scss +47 -0
- package/src/components/Categories/GroupTreeItem/index.tsx +76 -0
- package/src/components/Categories/GroupTreeItem/styles.scss +47 -0
- package/src/components/Categories/HistoryTreeItem/index.tsx +71 -0
- package/src/components/Categories/HistoryTreeItem/styles.scss +53 -0
- package/src/components/Categories/LabelTreeItem/index.tsx +150 -0
- package/src/components/Categories/LabelTreeItem/styles.scss +102 -0
- package/src/components/Categories/MessageTreeItem/index.tsx +107 -0
- package/src/components/Categories/MessageTreeItem/styles.scss +178 -0
- package/src/components/Categories/SeverityTreeItem/index.tsx +50 -0
- package/src/components/Categories/SeverityTreeItem/styles.scss +12 -0
- package/src/components/Categories/sticky.ts +12 -0
- package/src/components/Header/index.tsx +4 -2
- package/src/components/MainReport/index.tsx +106 -10
- package/src/components/ReportBody/styles.scss +1 -1
- package/src/components/ReportCategories/index.tsx +26 -0
- package/src/components/ReportCategories/styles.scss +55 -0
- package/src/components/ReportFilters/CategoriesFilter.tsx +41 -0
- package/src/components/ReportFilters/index.tsx +12 -1
- package/src/components/SplitLayout/index.tsx +4 -2
- package/src/components/SplitLayout/styles.scss +1 -0
- package/src/components/TestResult/TrInfo/index.tsx +8 -1
- package/src/components/TestResult/TrInfo/styles.scss +4 -0
- package/src/components/TestResult/TrSeverity/index.tsx +13 -4
- package/src/components/TestResult/TrSeverity/styles.scss +1 -0
- package/src/components/TestResult/TrTabs/index.tsx +5 -0
- package/src/index.tsx +6 -2
- package/src/locales/az.json +106 -78
- package/src/locales/de.json +23 -3
- package/src/locales/en.json +23 -3
- package/src/locales/es.json +23 -3
- package/src/locales/fr.json +23 -3
- package/src/locales/he.json +23 -3
- package/src/locales/hy.json +23 -3
- package/src/locales/it.json +23 -3
- package/src/locales/ja.json +23 -3
- package/src/locales/ka.json +23 -3
- package/src/locales/kr.json +23 -3
- package/src/locales/nl.json +23 -3
- package/src/locales/pl.json +23 -3
- package/src/locales/pt.json +23 -3
- package/src/locales/ru.json +23 -3
- package/src/locales/sv.json +23 -3
- package/src/locales/tr.json +23 -3
- package/src/locales/uk.json +23 -3
- package/src/locales/zh.json +23 -3
- package/src/stores/categories.ts +44 -0
- package/src/stores/router.ts +55 -3
- package/src/stores/testResult.ts +14 -3
- package/src/stores/treeFilters/actions.ts +10 -1
- package/src/stores/treeFilters/constants.ts +1 -0
- package/src/stores/treeFilters/model.ts +2 -0
- package/src/stores/treeFilters/store.ts +45 -0
- package/src/stores/treeFilters/utils.ts +10 -0
- package/src/stores/treeSwitcher.ts +9 -0
- package/src/utils/treeFilters.ts +16 -9
- package/test/utils/treeFilters.test.ts +39 -0
- package/types.d.ts +1 -0
- package/dist/multi/173.app-d0210ed2e64d38a2ee8e.js +0 -1
- package/dist/multi/174.app-d0210ed2e64d38a2ee8e.js +0 -1
- package/dist/multi/252.app-d0210ed2e64d38a2ee8e.js +0 -1
- package/dist/multi/282.app-d0210ed2e64d38a2ee8e.js +0 -1
- package/dist/multi/29.app-d0210ed2e64d38a2ee8e.js +0 -1
- package/dist/multi/416.app-d0210ed2e64d38a2ee8e.js +0 -1
- package/dist/multi/527.app-d0210ed2e64d38a2ee8e.js +0 -1
- package/dist/multi/600.app-d0210ed2e64d38a2ee8e.js +0 -1
- package/dist/multi/605.app-d0210ed2e64d38a2ee8e.js +0 -1
- package/dist/multi/638.app-d0210ed2e64d38a2ee8e.js +0 -1
- package/dist/multi/672.app-d0210ed2e64d38a2ee8e.js +0 -1
- package/dist/multi/686.app-d0210ed2e64d38a2ee8e.js +0 -1
- package/dist/multi/725.app-d0210ed2e64d38a2ee8e.js +0 -1
- package/dist/multi/741.app-d0210ed2e64d38a2ee8e.js +0 -1
- package/dist/multi/749.app-d0210ed2e64d38a2ee8e.js +0 -1
- package/dist/multi/755.app-d0210ed2e64d38a2ee8e.js +0 -1
- package/dist/multi/894.app-d0210ed2e64d38a2ee8e.js +0 -1
- package/dist/multi/943.app-d0210ed2e64d38a2ee8e.js +0 -1
- package/dist/multi/980.app-d0210ed2e64d38a2ee8e.js +0 -1
- package/dist/multi/app-d0210ed2e64d38a2ee8e.js +0 -2
- package/dist/single/app-01fed10ad5f9083fd39c.js +0 -2
- package/src/components/SectionTabs/index.tsx +0 -0
- /package/dist/multi/{app-d0210ed2e64d38a2ee8e.js.LICENSE.txt → app-8be6acc0a596a2197dbf.js.LICENSE.txt} +0 -0
- /package/dist/single/{app-01fed10ad5f9083fd39c.js.LICENSE.txt → app-8221eb856e47b4ef50d6.js.LICENSE.txt} +0 -0
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
type StickyOverrides = Partial<Record<`--${string}`, string>>;
|
|
2
|
+
|
|
3
|
+
export const createCategoriesStickyStyle = (depth: number, overrides: StickyOverrides = {}) =>
|
|
4
|
+
({
|
|
5
|
+
"--categories-sticky-depth": `${depth}`,
|
|
6
|
+
"--tree-section-position": "sticky",
|
|
7
|
+
"--tree-section-top": `calc(${depth} * var(--categories-sticky-step))`,
|
|
8
|
+
"--tree-section-z": `${100 - depth}`,
|
|
9
|
+
"--tree-section-bg": "var(--bg-base-primary)",
|
|
10
|
+
"--tree-section-min-height": "var(--categories-sticky-step)",
|
|
11
|
+
...overrides,
|
|
12
|
+
}) as Record<string, string>;
|
|
@@ -4,7 +4,7 @@ import clsx from "clsx";
|
|
|
4
4
|
import { HeaderControls } from "@/components/HeaderControls";
|
|
5
5
|
import { SectionPicker } from "@/components/SectionPicker";
|
|
6
6
|
import { TrBreadcrumbs } from "@/components/TestResult/TrHeader/TrBreadcrumbs";
|
|
7
|
-
import { testResultRoute } from "@/stores/router";
|
|
7
|
+
import { rootTabRoute, testResultRoute } from "@/stores/router";
|
|
8
8
|
import { currentTrId } from "@/stores/testResult";
|
|
9
9
|
import { testResultStore } from "@/stores/testResults";
|
|
10
10
|
import { CiInfo } from "./CiInfo";
|
|
@@ -14,7 +14,9 @@ interface HeaderProps {
|
|
|
14
14
|
className?: ClassValue;
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
const isTestResultRoute = computed(
|
|
17
|
+
const isTestResultRoute = computed(
|
|
18
|
+
() => testResultRoute.value.matches || Boolean(rootTabRoute.value.params.testResultId),
|
|
19
|
+
);
|
|
18
20
|
const testResult = computed(() => testResultStore.value?.data?.[currentTrId.value]);
|
|
19
21
|
|
|
20
22
|
export const Header = ({ className }: HeaderProps) => {
|
|
@@ -1,24 +1,36 @@
|
|
|
1
1
|
import { Counter, Loadable } from "@allurereport/web-components";
|
|
2
2
|
import clsx from "clsx";
|
|
3
|
+
import { useEffect } from "preact/hooks";
|
|
3
4
|
import { NavTab, NavTabs, NavTabsList, useNavTabsContext } from "@/components/NavTabs";
|
|
4
5
|
import { ReportBody } from "@/components/ReportBody";
|
|
6
|
+
import { ReportCategories } from "@/components/ReportCategories";
|
|
5
7
|
import { ReportGlobalAttachments } from "@/components/ReportGlobalAttachments";
|
|
6
8
|
import { ReportGlobalErrors } from "@/components/ReportGlobalErrors";
|
|
7
9
|
import { ReportHeader } from "@/components/ReportHeader";
|
|
8
10
|
import { ReportMetadata } from "@/components/ReportMetadata";
|
|
9
11
|
import { reportStatsStore, useI18n } from "@/stores";
|
|
12
|
+
import { categoriesStore } from "@/stores/categories";
|
|
10
13
|
import { currentEnvironment } from "@/stores/env";
|
|
11
14
|
import { globalsStore } from "@/stores/globals";
|
|
12
15
|
import { isSplitMode } from "@/stores/layout";
|
|
13
16
|
import { qualityGateStore } from "@/stores/qualityGate";
|
|
17
|
+
import {
|
|
18
|
+
navigateToPlainTestResult,
|
|
19
|
+
navigateToRoot,
|
|
20
|
+
navigateToRootTabRoot,
|
|
21
|
+
navigateToRootTabTestResult,
|
|
22
|
+
rootTabRoute,
|
|
23
|
+
} from "@/stores/router";
|
|
24
|
+
import { currentTrId, trCurrentTab } from "@/stores/testResult";
|
|
14
25
|
import { ReportQualityGateResults } from "../ReportQualityGateResults";
|
|
15
26
|
import * as styles from "./styles.scss";
|
|
16
27
|
|
|
17
|
-
enum ReportRootTab {
|
|
28
|
+
export enum ReportRootTab {
|
|
18
29
|
Results = "results",
|
|
19
30
|
QualityGate = "qualityGate",
|
|
20
31
|
GlobalAttachments = "globalAttachments",
|
|
21
32
|
GlobalErrors = "globalErrors",
|
|
33
|
+
Categories = "categories",
|
|
22
34
|
}
|
|
23
35
|
|
|
24
36
|
const viewsByTab = {
|
|
@@ -31,6 +43,7 @@ const viewsByTab = {
|
|
|
31
43
|
[ReportRootTab.GlobalAttachments]: () => <ReportGlobalAttachments />,
|
|
32
44
|
[ReportRootTab.GlobalErrors]: () => <ReportGlobalErrors />,
|
|
33
45
|
[ReportRootTab.QualityGate]: () => <ReportQualityGateResults />,
|
|
46
|
+
[ReportRootTab.Categories]: () => <ReportCategories />,
|
|
34
47
|
};
|
|
35
48
|
|
|
36
49
|
const MainReportContent = () => {
|
|
@@ -43,21 +56,104 @@ const MainReportContent = () => {
|
|
|
43
56
|
|
|
44
57
|
const MainReport = () => {
|
|
45
58
|
const { t } = useI18n("tabs");
|
|
59
|
+
const rootTabToReportTab: Record<string, ReportRootTab> = {
|
|
60
|
+
categories: ReportRootTab.Categories,
|
|
61
|
+
qualityGate: ReportRootTab.QualityGate,
|
|
62
|
+
globalAttachments: ReportRootTab.GlobalAttachments,
|
|
63
|
+
globalErrors: ReportRootTab.GlobalErrors,
|
|
64
|
+
};
|
|
65
|
+
const reportTabToRootTab: Partial<Record<ReportRootTab, string>> = {
|
|
66
|
+
[ReportRootTab.Categories]: "categories",
|
|
67
|
+
[ReportRootTab.QualityGate]: "qualityGate",
|
|
68
|
+
[ReportRootTab.GlobalAttachments]: "globalAttachments",
|
|
69
|
+
[ReportRootTab.GlobalErrors]: "globalErrors",
|
|
70
|
+
};
|
|
71
|
+
const initialTab = rootTabRoute.value.matches
|
|
72
|
+
? (rootTabToReportTab[rootTabRoute.value.params.rootTab] ?? ReportRootTab.Results)
|
|
73
|
+
: ReportRootTab.Results;
|
|
74
|
+
|
|
75
|
+
const RootTab = (props: { id: ReportRootTab; children: any }) => {
|
|
76
|
+
const { id, children } = props;
|
|
77
|
+
const { currentTab, setCurrentTab } = useNavTabsContext();
|
|
78
|
+
const isCurrentTab = currentTab === id;
|
|
79
|
+
|
|
80
|
+
const handleClick = () => {
|
|
81
|
+
if (isCurrentTab) {
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
setCurrentTab(id);
|
|
85
|
+
if (id === ReportRootTab.Results) {
|
|
86
|
+
if (currentTrId.value) {
|
|
87
|
+
navigateToPlainTestResult({ testResultId: currentTrId.value, tab: trCurrentTab.value });
|
|
88
|
+
} else {
|
|
89
|
+
navigateToRoot();
|
|
90
|
+
}
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
const rootTab = reportTabToRootTab[id];
|
|
94
|
+
if (rootTab) {
|
|
95
|
+
if (currentTrId.value) {
|
|
96
|
+
navigateToRootTabTestResult({ rootTab, testResultId: currentTrId.value, tab: trCurrentTab.value });
|
|
97
|
+
} else {
|
|
98
|
+
navigateToRootTabRoot({ rootTab });
|
|
99
|
+
}
|
|
100
|
+
} else {
|
|
101
|
+
navigateToRoot();
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
return (
|
|
106
|
+
<NavTab id={id} onClick={handleClick} isCurrentTab={isCurrentTab}>
|
|
107
|
+
{children}
|
|
108
|
+
</NavTab>
|
|
109
|
+
);
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
// @ts-ignore
|
|
113
|
+
const RootTabRouteSync = () => {
|
|
114
|
+
const { currentTab, setCurrentTab } = useNavTabsContext();
|
|
115
|
+
const routeKey = rootTabRoute.value.matches ? (rootTabRoute.value.params.rootTab ?? "") : "";
|
|
116
|
+
useEffect(() => {
|
|
117
|
+
const routeMatches = rootTabRoute.value.matches;
|
|
118
|
+
const routeTab = routeMatches ? rootTabRoute.value.params.rootTab : undefined;
|
|
119
|
+
const mapped = routeMatches ? (rootTabToReportTab[routeTab] ?? ReportRootTab.Results) : ReportRootTab.Results;
|
|
120
|
+
if (currentTab !== mapped) {
|
|
121
|
+
setCurrentTab(mapped);
|
|
122
|
+
}
|
|
123
|
+
}, [currentTab, setCurrentTab, routeKey]);
|
|
124
|
+
return null;
|
|
125
|
+
};
|
|
46
126
|
|
|
47
127
|
return (
|
|
48
128
|
<div className={clsx(styles.content, isSplitMode.value ? styles["scroll-inside"] : "")}>
|
|
49
129
|
<ReportHeader />
|
|
50
130
|
<div className={styles["main-report-tabs"]}>
|
|
51
|
-
<NavTabs initialTab={
|
|
131
|
+
<NavTabs initialTab={initialTab}>
|
|
132
|
+
<RootTabRouteSync />
|
|
52
133
|
<NavTabsList>
|
|
53
134
|
<Loadable
|
|
54
135
|
source={reportStatsStore}
|
|
55
136
|
renderData={(stats) => (
|
|
56
|
-
<
|
|
137
|
+
<RootTab id={ReportRootTab.Results}>
|
|
57
138
|
{t("results")} <Counter count={stats?.total ?? 0} />
|
|
58
|
-
</
|
|
139
|
+
</RootTab>
|
|
59
140
|
)}
|
|
60
141
|
/>
|
|
142
|
+
<Loadable
|
|
143
|
+
source={categoriesStore}
|
|
144
|
+
renderData={(categories) => {
|
|
145
|
+
if (!categories || !categories.roots?.length) {
|
|
146
|
+
return null;
|
|
147
|
+
}
|
|
148
|
+
return (
|
|
149
|
+
<>
|
|
150
|
+
<RootTab id={ReportRootTab.Categories}>
|
|
151
|
+
{t("categories")} <Counter count={categories.roots?.length} />
|
|
152
|
+
</RootTab>
|
|
153
|
+
</>
|
|
154
|
+
);
|
|
155
|
+
}}
|
|
156
|
+
/>
|
|
61
157
|
<Loadable
|
|
62
158
|
source={qualityGateStore}
|
|
63
159
|
renderData={(results) => {
|
|
@@ -66,13 +162,13 @@ const MainReport = () => {
|
|
|
66
162
|
: Object.values(results).flatMap((envResults) => envResults);
|
|
67
163
|
|
|
68
164
|
return (
|
|
69
|
-
<
|
|
165
|
+
<RootTab id={ReportRootTab.QualityGate}>
|
|
70
166
|
{t("qualityGates")}{" "}
|
|
71
167
|
<Counter
|
|
72
168
|
status={currentEnvResults.length > 0 ? "failed" : undefined}
|
|
73
169
|
count={currentEnvResults.length}
|
|
74
170
|
/>
|
|
75
|
-
</
|
|
171
|
+
</RootTab>
|
|
76
172
|
);
|
|
77
173
|
}}
|
|
78
174
|
/>
|
|
@@ -80,13 +176,13 @@ const MainReport = () => {
|
|
|
80
176
|
source={globalsStore}
|
|
81
177
|
renderData={({ attachments = [], errors = [] }) => (
|
|
82
178
|
<>
|
|
83
|
-
<
|
|
179
|
+
<RootTab id={ReportRootTab.GlobalAttachments}>
|
|
84
180
|
{t("globalAttachments")} <Counter count={attachments.length} />
|
|
85
|
-
</
|
|
86
|
-
<
|
|
181
|
+
</RootTab>
|
|
182
|
+
<RootTab id={ReportRootTab.GlobalErrors}>
|
|
87
183
|
{t("globalErrors")}{" "}
|
|
88
184
|
<Counter status={errors.length > 0 ? "failed" : undefined} count={errors.length} />
|
|
89
|
-
</
|
|
185
|
+
</RootTab>
|
|
90
186
|
</>
|
|
91
187
|
)}
|
|
92
188
|
/>
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { Loadable, PageLoader } from "@allurereport/web-components";
|
|
2
|
+
import { CategoriesTree } from "@/components/Categories/CategoriesTree";
|
|
3
|
+
import { useI18n } from "@/stores";
|
|
4
|
+
import { categoriesStore } from "@/stores/categories";
|
|
5
|
+
import * as styles from "./styles.scss";
|
|
6
|
+
|
|
7
|
+
export const ReportCategories = () => {
|
|
8
|
+
const { t } = useI18n("empty");
|
|
9
|
+
|
|
10
|
+
return (
|
|
11
|
+
<Loadable
|
|
12
|
+
source={categoriesStore}
|
|
13
|
+
renderLoader={() => (
|
|
14
|
+
<div className={styles["report-categories-loader"]}>
|
|
15
|
+
<PageLoader />
|
|
16
|
+
</div>
|
|
17
|
+
)}
|
|
18
|
+
renderData={(store) => {
|
|
19
|
+
if (!categoriesStore.value.data?.roots?.length) {
|
|
20
|
+
return <div className={styles["report-categories-results-empty"]}>{t("no-categories-results")}</div>;
|
|
21
|
+
}
|
|
22
|
+
return <CategoriesTree store={store} />;
|
|
23
|
+
}}
|
|
24
|
+
/>
|
|
25
|
+
);
|
|
26
|
+
};
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
@import "~@allurereport/web-components/mixins.scss";
|
|
2
|
+
|
|
3
|
+
.report-categories-results {
|
|
4
|
+
padding: 20px 0;
|
|
5
|
+
|
|
6
|
+
& > li + li {
|
|
7
|
+
margin-top: 12px;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
.report-categories-results-empty {
|
|
12
|
+
display: flex;
|
|
13
|
+
padding: 48px 0;
|
|
14
|
+
width: 100%;
|
|
15
|
+
justify-content: center;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
.report-categories-loader {
|
|
19
|
+
display: flex;
|
|
20
|
+
padding: 48px 0;
|
|
21
|
+
width: 100%;
|
|
22
|
+
justify-content: center;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
.report-categories-result {
|
|
26
|
+
display: flex;
|
|
27
|
+
align-items: flex-start;
|
|
28
|
+
gap: 0 8px;
|
|
29
|
+
|
|
30
|
+
b {
|
|
31
|
+
font-weight: 700;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
.report-categories-result-icon {
|
|
36
|
+
flex: 0 0 auto;
|
|
37
|
+
margin-top: 3px;
|
|
38
|
+
color: var(--bg-support-capella);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
.report-categories-result-content {
|
|
42
|
+
flex: 1 1 auto;
|
|
43
|
+
|
|
44
|
+
& > * + * {
|
|
45
|
+
margin-top: 4px;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.report-categories-result-error {
|
|
50
|
+
margin-top: 8px;
|
|
51
|
+
}
|
|
52
|
+
.tree-item-category {
|
|
53
|
+
font-size: 24px;
|
|
54
|
+
margin-bottom: 16px;
|
|
55
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { computed } from "@preact/signals";
|
|
2
|
+
import { useI18n } from "@/stores";
|
|
3
|
+
import { treeCategories } from "@/stores/treeFilters/store";
|
|
4
|
+
import type { AwesomeArrayFieldFilter } from "../../stores/treeFilters/model";
|
|
5
|
+
import { ArrayFieldFilter } from "./BaseFilters";
|
|
6
|
+
|
|
7
|
+
const options = computed(() => {
|
|
8
|
+
return treeCategories.value.map((category) => ({ key: category, label: category }));
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
export const CategoriesFilter = (props: {
|
|
12
|
+
filter: AwesomeArrayFieldFilter;
|
|
13
|
+
onChange: (filter: AwesomeArrayFieldFilter) => void;
|
|
14
|
+
}) => {
|
|
15
|
+
const { filter, onChange } = props;
|
|
16
|
+
const { t } = useI18n("filters");
|
|
17
|
+
|
|
18
|
+
if (options.value.length === 0) {
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
return (
|
|
23
|
+
<ArrayFieldFilter
|
|
24
|
+
filter={filter}
|
|
25
|
+
onChange={onChange}
|
|
26
|
+
options={options.value}
|
|
27
|
+
label={t("categories")}
|
|
28
|
+
description={t("description.categories")}
|
|
29
|
+
counter
|
|
30
|
+
onClear={() =>
|
|
31
|
+
onChange({
|
|
32
|
+
...filter,
|
|
33
|
+
value: {
|
|
34
|
+
...filter.value,
|
|
35
|
+
value: [],
|
|
36
|
+
},
|
|
37
|
+
})
|
|
38
|
+
}
|
|
39
|
+
/>
|
|
40
|
+
);
|
|
41
|
+
};
|
|
@@ -1,8 +1,15 @@
|
|
|
1
1
|
import { For } from "@preact/signals/utils";
|
|
2
2
|
import type { AwesomeFilter } from "@/stores/treeFilters/model";
|
|
3
3
|
import { setTreeFilter, treeQuickFilters } from "@/stores/treeFilters/store";
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
isCategoryFilter,
|
|
6
|
+
isFlakyFilter,
|
|
7
|
+
isRetryFilter,
|
|
8
|
+
isTagFilter,
|
|
9
|
+
isTransitionFilter,
|
|
10
|
+
} from "@/stores/treeFilters/utils";
|
|
5
11
|
import { BooleanFieldFilter } from "./BaseFilters";
|
|
12
|
+
import { CategoriesFilter } from "./CategoriesFilter";
|
|
6
13
|
import { RetryFlakyFilter } from "./RetryFlaky";
|
|
7
14
|
import { TagsFilter } from "./TagsFilter";
|
|
8
15
|
import { TransitionFilter } from "./TransitionFilter";
|
|
@@ -28,6 +35,10 @@ const Filter = (props: { filter: AwesomeFilter; onChange: (filter: AwesomeFilter
|
|
|
28
35
|
return <TagsFilter filter={filter} onChange={onChange} />;
|
|
29
36
|
}
|
|
30
37
|
|
|
38
|
+
if (isCategoryFilter(filter)) {
|
|
39
|
+
return <CategoriesFilter filter={filter} onChange={onChange} />;
|
|
40
|
+
}
|
|
41
|
+
|
|
31
42
|
return null;
|
|
32
43
|
};
|
|
33
44
|
|
|
@@ -6,7 +6,7 @@ import MainReport from "@/components/MainReport";
|
|
|
6
6
|
import SideBySide from "@/components/SideBySide";
|
|
7
7
|
import TestResult from "@/components/TestResult";
|
|
8
8
|
import { useI18n } from "@/stores";
|
|
9
|
-
import { testResultRoute } from "@/stores/router";
|
|
9
|
+
import { rootTabRoute, testResultRoute } from "@/stores/router";
|
|
10
10
|
import { currentTrId } from "@/stores/testResult";
|
|
11
11
|
import { testResultStore } from "@/stores/testResults";
|
|
12
12
|
import { treeStore } from "@/stores/tree";
|
|
@@ -30,7 +30,9 @@ const Loader = () => {
|
|
|
30
30
|
);
|
|
31
31
|
};
|
|
32
32
|
|
|
33
|
-
const isTestResultRoute = computed(
|
|
33
|
+
const isTestResultRoute = computed(
|
|
34
|
+
() => testResultRoute.value.matches || Boolean(rootTabRoute.value.params.testResultId),
|
|
35
|
+
);
|
|
34
36
|
|
|
35
37
|
export const SplitLayout = () => {
|
|
36
38
|
const testResultId = currentTrId.value;
|
|
@@ -21,10 +21,12 @@ export type TrInfoProps = {
|
|
|
21
21
|
};
|
|
22
22
|
|
|
23
23
|
export const TrInfo: FunctionalComponent<TrInfoProps> = ({ testResult }) => {
|
|
24
|
-
const { name, status, muted, flaky, known, duration, labels, history, retries, attachments, stop } =
|
|
24
|
+
const { name, status, muted, flaky, known, duration, labels, history, retries, attachments, stop, categories } =
|
|
25
|
+
testResult ?? {};
|
|
25
26
|
const formattedDuration = formatDuration(duration as number);
|
|
26
27
|
const fullDate = stop && timestampToDate(stop);
|
|
27
28
|
const severity = labels?.find((label) => label.name === "severity")?.value ?? "normal";
|
|
29
|
+
const categoryName = categories?.[0]?.name;
|
|
28
30
|
const { t } = useI18n("ui");
|
|
29
31
|
const statuses = Object.entries({ flaky, muted, known }).filter(([, value]) => value);
|
|
30
32
|
|
|
@@ -41,6 +43,11 @@ export const TrInfo: FunctionalComponent<TrInfoProps> = ({ testResult }) => {
|
|
|
41
43
|
{Boolean(history?.length) && <TrPrevStatuses history={history} />}
|
|
42
44
|
<TrSeverity severity={severity} />
|
|
43
45
|
{Boolean(statuses.length) && <TrInfoStatuses statuses={statuses} />}
|
|
46
|
+
{categoryName && (
|
|
47
|
+
<Text tag={"div"} size={"s"} className={styles["test-result-category"]}>
|
|
48
|
+
{t("category")}: {categoryName}
|
|
49
|
+
</Text>
|
|
50
|
+
)}
|
|
44
51
|
<TooltipWrapper tooltipText={fullDate}>
|
|
45
52
|
<Text tag={"div"} size={"s"} bold className={styles["test-result-duration"]}>
|
|
46
53
|
{formattedDuration}
|
|
@@ -10,17 +10,26 @@ const icons: Record<string, string> = {
|
|
|
10
10
|
normal: allureIcons.lineGeneralEqual,
|
|
11
11
|
minor: allureIcons.lineArrowsChevronDown,
|
|
12
12
|
trivial: allureIcons.lineArrowsChevronDownDouble,
|
|
13
|
+
none: allureIcons.lineGeneralXClose,
|
|
13
14
|
};
|
|
14
15
|
|
|
15
|
-
export const TrSeverity = ({
|
|
16
|
+
export const TrSeverity = ({
|
|
17
|
+
severity = "normal",
|
|
18
|
+
text = "",
|
|
19
|
+
size = "s",
|
|
20
|
+
}: {
|
|
21
|
+
severity?: string;
|
|
22
|
+
text?: string;
|
|
23
|
+
size?: "s" | "m";
|
|
24
|
+
}) => {
|
|
16
25
|
const { t } = useI18n("severity");
|
|
17
26
|
const statusClass = clsx(styles[`severity-${severity}`]);
|
|
18
27
|
|
|
19
28
|
return (
|
|
20
29
|
<div className={styles["test-result-severity"]}>
|
|
21
|
-
<SvgIcon className={statusClass} id={icons[severity]} />
|
|
22
|
-
<Text size={
|
|
23
|
-
{capitalize(t(severity))}
|
|
30
|
+
<SvgIcon className={statusClass} id={icons[severity]} size={size} />
|
|
31
|
+
<Text size={size} bold className={styles["test-result-severity-text"]}>
|
|
32
|
+
{text || capitalize(t(severity))}
|
|
24
33
|
</Text>
|
|
25
34
|
</div>
|
|
26
35
|
);
|
|
@@ -15,6 +15,11 @@ export const TrTab = (props: { id: string; children: ComponentChildren }) => {
|
|
|
15
15
|
return;
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
+
if (id === "overview") {
|
|
19
|
+
navigateToTestResultTab({ testResultId: currentTrId.value, tab: "" });
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
|
|
18
23
|
navigateToTestResultTab({ testResultId: currentTrId.value, tab: id });
|
|
19
24
|
};
|
|
20
25
|
|
package/src/index.tsx
CHANGED
|
@@ -11,6 +11,7 @@ import { Header } from "@/components/Header";
|
|
|
11
11
|
import { ModalComponent } from "@/components/Modal";
|
|
12
12
|
import { SectionSwitcher } from "@/components/SectionSwitcher";
|
|
13
13
|
import { fetchEnvStats, fetchReportStats, getLocale, waitForI18next } from "@/stores";
|
|
14
|
+
import { fetchCategoriesData } from "@/stores/categories";
|
|
14
15
|
import { fetchPieChartData } from "@/stores/chart";
|
|
15
16
|
import { currentEnvironment, environmentsStore, fetchEnvironments } from "@/stores/env";
|
|
16
17
|
import { fetchEnvInfo } from "@/stores/envInfo";
|
|
@@ -20,7 +21,7 @@ import { fetchTestResult, fetchTestResultNav } from "@/stores/testResults";
|
|
|
20
21
|
import { fetchEnvTreesData } from "@/stores/tree";
|
|
21
22
|
import { isMac } from "@/utils/isMac";
|
|
22
23
|
import { fetchQualityGateResults } from "./stores/qualityGate";
|
|
23
|
-
import { testResultRoute } from "./stores/router";
|
|
24
|
+
import { rootTabRoute, testResultRoute } from "./stores/router";
|
|
24
25
|
import { currentSection } from "./stores/sections";
|
|
25
26
|
import { currentTrId } from "./stores/testResult";
|
|
26
27
|
import { fetchTreeFiltersData } from "./stores/treeFilters/actions";
|
|
@@ -36,7 +37,9 @@ const Loader = () => {
|
|
|
36
37
|
);
|
|
37
38
|
};
|
|
38
39
|
|
|
39
|
-
const isTestResultRoute = computed(
|
|
40
|
+
const isTestResultRoute = computed(
|
|
41
|
+
() => testResultRoute.value.matches || Boolean(rootTabRoute.value.params.testResultId),
|
|
42
|
+
);
|
|
40
43
|
|
|
41
44
|
const App = () => {
|
|
42
45
|
const className = styles[`layout-${currentSection.value !== "default" ? currentSection.value : layoutStore.value}`];
|
|
@@ -51,6 +54,7 @@ const App = () => {
|
|
|
51
54
|
fetchEnvInfo,
|
|
52
55
|
fetchGlobals,
|
|
53
56
|
fetchQualityGateResults,
|
|
57
|
+
fetchCategoriesData,
|
|
54
58
|
];
|
|
55
59
|
|
|
56
60
|
if (globalThis) {
|