@allurereport/web-awesome 3.0.0-beta.8 → 3.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.
Files changed (282) hide show
  1. package/dist/multi/173.app-9931797d1602fc52db5b.js +1 -0
  2. package/dist/multi/174.app-9931797d1602fc52db5b.js +1 -0
  3. package/dist/multi/252.app-9931797d1602fc52db5b.js +1 -0
  4. package/dist/multi/282.app-9931797d1602fc52db5b.js +1 -0
  5. package/dist/multi/29.app-9931797d1602fc52db5b.js +1 -0
  6. package/dist/multi/416.app-9931797d1602fc52db5b.js +1 -0
  7. package/dist/multi/527.app-9931797d1602fc52db5b.js +1 -0
  8. package/dist/multi/600.app-9931797d1602fc52db5b.js +1 -0
  9. package/dist/multi/605.app-9931797d1602fc52db5b.js +1 -0
  10. package/dist/multi/638.app-9931797d1602fc52db5b.js +1 -0
  11. package/dist/multi/672.app-9931797d1602fc52db5b.js +1 -0
  12. package/dist/multi/686.app-9931797d1602fc52db5b.js +1 -0
  13. package/dist/multi/725.app-9931797d1602fc52db5b.js +1 -0
  14. package/dist/multi/741.app-9931797d1602fc52db5b.js +1 -0
  15. package/dist/multi/755.app-9931797d1602fc52db5b.js +1 -0
  16. package/dist/multi/894.app-9931797d1602fc52db5b.js +1 -0
  17. package/dist/multi/91.app-9931797d1602fc52db5b.js +1 -0
  18. package/dist/multi/943.app-9931797d1602fc52db5b.js +1 -0
  19. package/dist/multi/980.app-9931797d1602fc52db5b.js +1 -0
  20. package/dist/multi/app-9931797d1602fc52db5b.js +2 -0
  21. package/dist/multi/app-9931797d1602fc52db5b.js.LICENSE.txt +10 -0
  22. package/dist/multi/manifest.json +25 -24
  23. package/dist/multi/styles-8fe37354d1c2270c691e.css +48 -0
  24. package/dist/single/app-6199dc1c2fd3bddc2526.js +2 -0
  25. package/dist/single/app-6199dc1c2fd3bddc2526.js.LICENSE.txt +10 -0
  26. package/dist/single/manifest.json +1 -1
  27. package/package.json +30 -17
  28. package/src/assets/scss/day.scss +2 -0
  29. package/src/assets/scss/index.scss +1 -3
  30. package/src/assets/scss/night.scss +2 -0
  31. package/src/assets/scss/palette.scss +391 -391
  32. package/src/assets/scss/theme.scss +292 -79
  33. package/src/components/BaseLayout/index.tsx +10 -31
  34. package/src/components/BaseLayout/styles.scss +14 -4
  35. package/src/components/Charts/index.tsx +245 -0
  36. package/src/components/Charts/styles.scss +27 -0
  37. package/src/components/EnvironmentPicker/index.tsx +60 -0
  38. package/src/components/EnvironmentPicker/styles.scss +9 -0
  39. package/src/components/Footer/FooterLogo.tsx +1 -2
  40. package/src/components/Footer/FooterVersion.tsx +7 -3
  41. package/src/components/Footer/index.tsx +6 -2
  42. package/src/components/Header/CiInfo/index.tsx +67 -0
  43. package/src/components/Header/CiInfo/styles.scss +7 -0
  44. package/src/components/Header/index.tsx +21 -8
  45. package/src/components/Header/styles.scss +9 -1
  46. package/src/components/HeaderControls/index.tsx +20 -0
  47. package/src/components/MainReport/index.tsx +84 -6
  48. package/src/components/MainReport/styles.scss +20 -0
  49. package/src/components/Metadata/index.tsx +6 -4
  50. package/src/components/MetadataButton/index.tsx +14 -6
  51. package/src/components/MetadataButton/styles.scss +3 -0
  52. package/src/components/Modal/index.tsx +15 -167
  53. package/src/components/NavTabs/index.tsx +70 -0
  54. package/src/components/{TestResult/TestResultTabs → NavTabs}/styles.scss +0 -3
  55. package/src/components/Report/index.tsx +7 -0
  56. package/src/components/ReportBody/Filters.tsx +45 -66
  57. package/src/components/ReportBody/index.tsx +29 -17
  58. package/src/components/ReportBody/styles.scss +9 -3
  59. package/src/components/ReportGlobalAttachments/index.tsx +34 -0
  60. package/src/components/ReportGlobalAttachments/styles.scss +11 -0
  61. package/src/components/ReportGlobalErrors/index.tsx +30 -0
  62. package/src/components/ReportGlobalErrors/styles.scss +12 -0
  63. package/src/components/ReportHeader/ReportHeaderLogo.tsx +6 -2
  64. package/src/components/ReportHeader/ReportHeaderPie.tsx +1 -2
  65. package/src/components/ReportHeader/index.tsx +38 -12
  66. package/src/components/ReportHeader/styles.scss +9 -1
  67. package/src/components/ReportMetadata/MetadataSummary.tsx +57 -65
  68. package/src/components/ReportMetadata/MetadataWithIcon.tsx +11 -13
  69. package/src/components/ReportMetadata/index.tsx +50 -3
  70. package/src/components/ReportMetadata/styles.scss +0 -2
  71. package/src/components/ReportQualityGateResults/index.tsx +42 -0
  72. package/src/components/ReportQualityGateResults/styles.scss +44 -0
  73. package/src/components/SectionPicker/index.tsx +55 -0
  74. package/src/components/SectionPicker/styles.scss +5 -0
  75. package/src/components/SectionSwitcher/index.tsx +16 -0
  76. package/src/components/SectionSwitcher/styles.scss +4 -0
  77. package/src/components/SectionTabs/index.tsx +0 -0
  78. package/src/components/SideBySide/index.tsx +52 -0
  79. package/src/components/SideBySide/styles.scss +64 -0
  80. package/src/components/SplitLayout/index.tsx +73 -0
  81. package/src/components/SplitLayout/styles.scss +84 -0
  82. package/src/components/Tabs/index.tsx +5 -0
  83. package/src/components/TestResult/TestStepsEmpty/index.tsx +23 -0
  84. package/src/components/TestResult/TestStepsEmpty/styles.scss +25 -0
  85. package/src/components/TestResult/TrAttachmentsView/index.tsx +29 -0
  86. package/src/components/TestResult/{TestResultDescription → TrDescription}/index.tsx +5 -5
  87. package/src/components/TestResult/{TestResultDropdown → TrDropdown}/index.tsx +7 -5
  88. package/src/components/TestResult/{TestResultEmpty → TrEmpty}/index.tsx +10 -9
  89. package/src/components/TestResult/TrEnvironmentItem/index.tsx +82 -0
  90. package/src/components/TestResult/TrEnvironmentItem/styles.scss +60 -0
  91. package/src/components/TestResult/TrEnvironmentsView/index.tsx +64 -0
  92. package/src/components/TestResult/TrEnvironmentsView/styles.scss +11 -0
  93. package/src/components/TestResult/TrError/TrDiff.tsx +121 -0
  94. package/src/components/TestResult/TrError/index.tsx +104 -0
  95. package/src/components/TestResult/TrError/styles.scss +223 -0
  96. package/src/components/TestResult/TrHeader/TrBreadcrumbs.tsx +44 -0
  97. package/src/components/TestResult/TrHeader/index.tsx +15 -0
  98. package/src/components/TestResult/{TestResultHeader → TrHeader}/styles.scss +7 -2
  99. package/src/components/TestResult/TrHistory/TrHistoryItem.tsx +94 -0
  100. package/src/components/TestResult/TrHistory/index.tsx +26 -0
  101. package/src/components/TestResult/{TestResultHistory → TrHistory}/styles.scss +2 -1
  102. package/src/components/TestResult/{TestResultInfo/TestResultInfoStatuses.tsx → TrInfo/TrInfoStatuses.tsx} +6 -4
  103. package/src/components/TestResult/TrInfo/index.tsx +99 -0
  104. package/src/components/TestResult/{TestResultInfo → TrInfo}/styles.scss +18 -0
  105. package/src/components/TestResult/{TestResultLinks → TrLinks}/index.tsx +8 -8
  106. package/src/components/TestResult/{TestResultMetadata → TrMetadata}/index.tsx +6 -6
  107. package/src/components/TestResult/{TestResultNavigation → TrNavigation}/index.tsx +7 -9
  108. package/src/components/TestResult/TrOverview.tsx +46 -0
  109. package/src/components/TestResult/{TestResultParameters → TrParameters}/index.tsx +4 -4
  110. package/src/components/TestResult/TrPrevStatuses/index.tsx +63 -0
  111. package/src/components/TestResult/TrPwTraces/PwTrace.tsx +34 -0
  112. package/src/components/TestResult/TrPwTraces/PwTraceButton.tsx +32 -0
  113. package/src/components/TestResult/TrPwTraces/index.tsx +32 -0
  114. package/src/components/TestResult/TrPwTraces/styles.scss +20 -0
  115. package/src/components/TestResult/TrRetriesView/TrRetriesItem.tsx +70 -0
  116. package/src/components/TestResult/TrRetriesView/index.tsx +29 -0
  117. package/src/components/TestResult/{TestResultSetup → TrSetup}/index.tsx +24 -15
  118. package/src/components/TestResult/{TestResultSeverity → TrSeverity}/index.tsx +2 -2
  119. package/src/components/TestResult/{TestResultStatus → TrStatus}/index.tsx +5 -5
  120. package/src/components/TestResult/TrSteps/TrAttachment.tsx +118 -0
  121. package/src/components/TestResult/{TestResultSteps/testResultAttachmentInfo.tsx → TrSteps/TrAttachmentInfo.tsx} +11 -11
  122. package/src/components/TestResult/TrSteps/TrStep.tsx +98 -0
  123. package/src/components/TestResult/TrSteps/TrStepInfo.tsx +90 -0
  124. package/src/components/TestResult/TrSteps/index.tsx +58 -0
  125. package/src/components/TestResult/{TestResultSteps → TrSteps}/styles.scss +49 -10
  126. package/src/components/TestResult/{TestResultSteps → TrSteps}/wrongAttachment.tsx +1 -1
  127. package/src/components/TestResult/TrTabs/index.tsx +42 -0
  128. package/src/components/TestResult/{TestResultTeardown → TrTeardown}/index.tsx +25 -15
  129. package/src/components/TestResult/index.tsx +54 -38
  130. package/src/components/TestResult/styles.scss +12 -0
  131. package/src/components/Timeline/index.tsx +100 -0
  132. package/src/components/Timeline/styles.scss +45 -0
  133. package/src/components/ToggleLayout/index.tsx +17 -0
  134. package/src/components/Tree/index.tsx +122 -16
  135. package/src/components/Tree/styles.scss +23 -5
  136. package/src/index.html +23 -6
  137. package/src/index.tsx +91 -20
  138. package/src/locales/az.json +376 -0
  139. package/src/locales/de.json +376 -0
  140. package/src/locales/en.json +376 -0
  141. package/src/locales/es.json +376 -0
  142. package/src/locales/fr.json +376 -0
  143. package/src/locales/he.json +376 -0
  144. package/src/locales/hy.json +376 -0
  145. package/src/locales/it.json +376 -0
  146. package/src/locales/ja.json +376 -0
  147. package/src/locales/ka.json +376 -0
  148. package/src/locales/kr.json +376 -0
  149. package/src/locales/nl.json +376 -0
  150. package/src/locales/pl.json +384 -0
  151. package/src/locales/pt.json +376 -0
  152. package/src/locales/ru.json +384 -0
  153. package/src/locales/sv.json +376 -0
  154. package/src/locales/tr.json +376 -0
  155. package/src/locales/ua.json +327 -0
  156. package/src/locales/zh.json +376 -0
  157. package/src/stores/chart.ts +41 -6
  158. package/src/stores/env.ts +88 -0
  159. package/src/stores/envInfo.ts +2 -2
  160. package/src/stores/globals.ts +28 -0
  161. package/src/stores/layout.ts +36 -0
  162. package/src/stores/locale.ts +77 -29
  163. package/src/stores/modal.ts +22 -0
  164. package/src/stores/qualityGate.ts +28 -0
  165. package/src/stores/router.ts +108 -0
  166. package/src/stores/sections.ts +63 -0
  167. package/src/stores/stats.ts +52 -7
  168. package/src/stores/testResults.ts +13 -9
  169. package/src/stores/theme.ts +15 -18
  170. package/src/stores/timeline.ts +39 -0
  171. package/src/stores/tree.ts +101 -31
  172. package/src/stores/variables.ts +40 -0
  173. package/src/styles.scss +66 -0
  174. package/src/utils/loadFromLocalStorage.ts +8 -0
  175. package/src/utils/time.ts +1 -0
  176. package/src/utils/tree.ts +23 -0
  177. package/src/utils/treeFilters.ts +27 -21
  178. package/test/components/Header/CiInfo.test.tsx +177 -0
  179. package/test/components/Header.test.tsx +122 -0
  180. package/test/utils/treeFilters.test.ts +44 -44
  181. package/tsconfig.json +7 -2
  182. package/tsconfig.node.json +8 -0
  183. package/types.d.ts +53 -21
  184. package/vitest.config.ts +15 -2
  185. package/vitest.setup.ts +1 -0
  186. package/webpack.config.js +37 -5
  187. package/dist/multi/141.app-4375537b.js +0 -1
  188. package/dist/multi/222.app-4375537b.js +0 -1
  189. package/dist/multi/335.app-4375537b.js +0 -1
  190. package/dist/multi/34.app-4375537b.js +0 -1
  191. package/dist/multi/349.app-4375537b.js +0 -1
  192. package/dist/multi/378.app-4375537b.js +0 -1
  193. package/dist/multi/406.app-4375537b.js +0 -1
  194. package/dist/multi/476.app-4375537b.js +0 -1
  195. package/dist/multi/53.app-4375537b.js +0 -1
  196. package/dist/multi/584.app-4375537b.js +0 -1
  197. package/dist/multi/690.app-4375537b.js +0 -1
  198. package/dist/multi/747.app-4375537b.js +0 -1
  199. package/dist/multi/767.app-4375537b.js +0 -1
  200. package/dist/multi/816.app-4375537b.js +0 -1
  201. package/dist/multi/83.app-4375537b.js +0 -1
  202. package/dist/multi/873.app-4375537b.js +0 -1
  203. package/dist/multi/920.app-4375537b.js +0 -1
  204. package/dist/multi/991.app-4375537b.js +0 -1
  205. package/dist/multi/app-4375537b.js +0 -2
  206. package/dist/multi/app-4375537b.js.LICENSE.txt +0 -16
  207. package/dist/multi/styles-4375537b.css +0 -283
  208. package/dist/single/app-f16f6693.js +0 -2
  209. package/dist/single/app-f16f6693.js.LICENSE.txt +0 -16
  210. package/src/assets/scss/code.scss +0 -71
  211. package/src/assets/scss/typography.scss +0 -218
  212. package/src/components/ArrowButton/index.tsx +0 -36
  213. package/src/components/ArrowButton/styles.scss +0 -35
  214. package/src/components/LanguagePicker/index.tsx +0 -40
  215. package/src/components/Modal/styles.scss +0 -126
  216. package/src/components/ReportLogo/index.tsx +0 -16
  217. package/src/components/ReportLogo/styles.scss +0 -20
  218. package/src/components/ReportLogoFull/index.tsx +0 -20
  219. package/src/components/ReportLogoFull/styles.scss +0 -7
  220. package/src/components/TestResult/TestResultAttachmentsView/index.tsx +0 -27
  221. package/src/components/TestResult/TestResultError/index.tsx +0 -59
  222. package/src/components/TestResult/TestResultError/styles.scss +0 -51
  223. package/src/components/TestResult/TestResultHeader/index.tsx +0 -55
  224. package/src/components/TestResult/TestResultHistory/TestResultHistoryItem.tsx +0 -67
  225. package/src/components/TestResult/TestResultHistory/index.tsx +0 -26
  226. package/src/components/TestResult/TestResultInfo/index.tsx +0 -79
  227. package/src/components/TestResult/TestResultOverview.tsx +0 -40
  228. package/src/components/TestResult/TestResultPrevStatuses/index.tsx +0 -49
  229. package/src/components/TestResult/TestResultRetriesView/TestResultRetriesItem.tsx +0 -52
  230. package/src/components/TestResult/TestResultRetriesView/index.tsx +0 -24
  231. package/src/components/TestResult/TestResultSteps/HtmlAttachmentPreview.tsx +0 -12
  232. package/src/components/TestResult/TestResultSteps/attachment.tsx +0 -68
  233. package/src/components/TestResult/TestResultSteps/attachmentCode.tsx +0 -20
  234. package/src/components/TestResult/TestResultSteps/attachmentImage.tsx +0 -32
  235. package/src/components/TestResult/TestResultSteps/attachmentVideo.tsx +0 -15
  236. package/src/components/TestResult/TestResultSteps/index.tsx +0 -49
  237. package/src/components/TestResult/TestResultSteps/testResultAttachment.tsx +0 -77
  238. package/src/components/TestResult/TestResultSteps/testResultStep.tsx +0 -78
  239. package/src/components/TestResult/TestResultSteps/testResultStepInfo.tsx +0 -30
  240. package/src/components/TestResult/TestResultTabs/index.tsx +0 -59
  241. package/src/components/ThemeButton/ThemeButton.tsx +0 -20
  242. package/src/components/Tree/Tree.tsx +0 -68
  243. package/src/components/Tree/TreeHeader.tsx +0 -82
  244. package/src/components/Tree/TreeItem.tsx +0 -35
  245. package/src/components/Tree/TreeItemIcon.tsx +0 -32
  246. package/src/i18n/constants.ts +0 -124
  247. package/src/i18n/locales/am.json +0 -118
  248. package/src/i18n/locales/az.json +0 -118
  249. package/src/i18n/locales/de.json +0 -118
  250. package/src/i18n/locales/en.json +0 -119
  251. package/src/i18n/locales/es.json +0 -118
  252. package/src/i18n/locales/fr.json +0 -118
  253. package/src/i18n/locales/he.json +0 -118
  254. package/src/i18n/locales/it.json +0 -118
  255. package/src/i18n/locales/ja.json +0 -118
  256. package/src/i18n/locales/ka.json +0 -118
  257. package/src/i18n/locales/kr.json +0 -118
  258. package/src/i18n/locales/nl.json +0 -118
  259. package/src/i18n/locales/pl.json +0 -116
  260. package/src/i18n/locales/pt.json +0 -118
  261. package/src/i18n/locales/ru.json +0 -116
  262. package/src/i18n/locales/sv.json +0 -118
  263. package/src/i18n/locales/tr.json +0 -118
  264. package/src/i18n/locales/zh.json +0 -118
  265. package/src/utils/attachments.ts +0 -156
  266. package/src/utils/capitalize.ts +0 -6
  267. /package/dist/multi/{JetBrainsMono_vf-b9a9c326..woff → JetBrainsMono_vf.woff} +0 -0
  268. /package/dist/multi/{JetBrainsMono_vf-9e9649b6..woff2 → JetBrainsMono_vf.woff2} +0 -0
  269. /package/dist/multi/{pt-root-ui_vf-22fe60ca..woff → pt-root-ui_vf.woff} +0 -0
  270. /package/dist/multi/{pt-root-ui_vf-9d251e8b..woff2 → pt-root-ui_vf.woff2} +0 -0
  271. /package/src/components/TestResult/{TestResultAttachmentsView → TrAttachmentsView}/styles.scss +0 -0
  272. /package/src/components/TestResult/{TestResultDescription → TrDescription}/styles.scss +0 -0
  273. /package/src/components/TestResult/{TestResultDropdown → TrDropdown}/styles.scss +0 -0
  274. /package/src/components/TestResult/{TestResultEmpty → TrEmpty}/styles.scss +0 -0
  275. /package/src/components/TestResult/{TestResultLinks → TrLinks}/styles.scss +0 -0
  276. /package/src/components/TestResult/{TestResultMetadata → TrMetadata}/styles.scss +0 -0
  277. /package/src/components/TestResult/{TestResultNavigation → TrNavigation}/styles.scss +0 -0
  278. /package/src/components/TestResult/{TestResultParameters → TrParameters}/styles.scss +0 -0
  279. /package/src/components/TestResult/{TestResultPrevStatuses → TrPrevStatuses}/styles.scss +0 -0
  280. /package/src/components/TestResult/{TestResultRetriesView → TrRetriesView}/styles.scss +0 -0
  281. /package/src/components/TestResult/{TestResultSeverity → TrSeverity}/styles.scss +0 -0
  282. /package/src/components/TestResult/{TestResultStatus → TrStatus}/styles.scss +0 -0
@@ -1,15 +1,14 @@
1
- import { getReportOptions } from "@allurereport/web-commons";
1
+ import { formatDuration } from "@allurereport/core-api";
2
+ import { DEFAULT_LOCALE, LANG_LOCALE, type LangLocale, getReportOptions } from "@allurereport/web-commons";
2
3
  import { computed, signal } from "@preact/signals";
3
4
  import i18next, { type TOptions } from "i18next";
4
- import { DEFAULT_LOCALE, LANG_LOCALE, type LangLocale } from "@/i18n/constants";
5
- import type { AllureAwesomeReportOptions } from "../../types.js";
6
-
7
- const { reportLanguage } = getReportOptions<AllureAwesomeReportOptions>() ?? {};
5
+ import type { AwesomeReportOptions } from "types";
8
6
 
9
7
  const namespaces = [
10
8
  "empty",
11
9
  "execution",
12
10
  "filters",
11
+ "filters.description",
13
12
  "search",
14
13
  "severity",
15
14
  "sort-by",
@@ -22,31 +21,36 @@ const namespaces = [
22
21
  "welcome",
23
22
  "controls",
24
23
  "errors",
25
- ];
24
+ "split",
25
+ "modal",
26
+ "environments",
27
+ "charts",
28
+ "sections",
29
+ "timeline",
30
+ "transitions",
31
+ ] as const;
26
32
 
27
33
  export const currentLocale = signal<LangLocale>("en" as LangLocale);
34
+ export const currentLocaleIso = computed(() => LANG_LOCALE[currentLocale.value]?.iso ?? LANG_LOCALE.en.iso);
35
+ export const currentLocaleIsRTL = computed(() => ["ar", "he", "fa"].includes(currentLocale.value));
28
36
 
29
- export const currentLocaleIso = computed(() => {
30
- const locale = currentLocale.value;
31
-
32
- return LANG_LOCALE[locale].iso;
33
- });
34
-
35
- export const currentLocaleIsRTL = computed(() => {
36
- return ["ar", "he", "fa"].includes(currentLocale.value as string);
37
- });
38
-
39
- export const getLocale = () => {
37
+ export const getLocale = async () => {
38
+ const { reportLanguage } = getReportOptions<AwesomeReportOptions>() ?? {};
40
39
  const locale = localStorage.getItem("currentLocale") || reportLanguage || DEFAULT_LOCALE;
41
- setLocale(locale as LangLocale);
40
+
41
+ await setLocale(locale as LangLocale);
42
42
  };
43
43
 
44
- i18next
44
+ export const waitForI18next = i18next
45
45
  .use({
46
46
  type: "backend",
47
- async read(language: LangLocale, namespace: string, callback: (errorValue: unknown, translations: null) => void) {
48
- await import(`@/i18n/locales/${language}.json`)
49
- .then((resources) => {
47
+ read: async (
48
+ language: LangLocale,
49
+ namespace: string,
50
+ callback: (errorValue: unknown, translations: null) => void,
51
+ ) => {
52
+ await import(`@/locales/${language}.json`)
53
+ .then((resources: Record<string, null>) => {
50
54
  callback(null, resources[namespace]);
51
55
  })
52
56
  .catch((error) => {
@@ -58,13 +62,57 @@ i18next
58
62
  lng: currentLocale.value,
59
63
  fallbackLng: "en",
60
64
  ns: namespaces,
61
- interpolation: {
62
- escapeValue: false,
63
- },
65
+ interpolation: { escapeValue: false },
66
+ })
67
+ .then(() => {
68
+ i18next.services.formatter.add("capitalize", (value) => {
69
+ return value.charAt(0).toLocaleUpperCase() + value.slice(1);
70
+ });
71
+ i18next.services.formatter.add("timestamp_date", (value: number, lng, options) => {
72
+ const formatter = new Intl.DateTimeFormat(lng, {
73
+ ...options,
74
+ month: "numeric",
75
+ day: "numeric",
76
+ year: "numeric",
77
+ });
78
+ return formatter.format(value);
79
+ });
80
+ i18next.services.formatter.add("timestamp_long", (value: number, lng, options) => {
81
+ const formatter = new Intl.DateTimeFormat(lng, {
82
+ ...options,
83
+ month: "numeric",
84
+ day: "numeric",
85
+ year: "numeric",
86
+ hour: "numeric",
87
+ minute: "numeric",
88
+ second: "numeric",
89
+ hour12: false,
90
+ });
91
+ return formatter.format(value).replace(",", ` ${i18next.t("ui:at")}`);
92
+ });
93
+ i18next.services.formatter.add("timestamp_long_no_seconds", (value: number, lng, options) => {
94
+ const formatter = new Intl.DateTimeFormat(lng, {
95
+ ...options,
96
+ month: "numeric",
97
+ day: "numeric",
98
+ year: "numeric",
99
+ hour: "numeric",
100
+ minute: "numeric",
101
+ hour12: false,
102
+ });
103
+ return formatter.format(value).replace(",", ` ${i18next.t("ui:at")}`);
104
+ });
105
+ i18next.services.formatter.add("format_duration", (value: number) => {
106
+ return formatDuration(value);
107
+ });
64
108
  });
65
109
 
66
- export const useI18n = (namespace?: string) => {
67
- const t = computed(() => (key: string, options?: TOptions) => i18next.t(key, { ns: namespace, ...options }));
110
+ export const useI18n = (namespace: (typeof namespaces)[number]) => {
111
+ const t = computed(
112
+ () =>
113
+ (key: string, options: TOptions = {}) =>
114
+ i18next.t(key, { ns: namespace, ...options }),
115
+ );
68
116
 
69
117
  return {
70
118
  t: t.value,
@@ -73,7 +121,7 @@ export const useI18n = (namespace?: string) => {
73
121
  };
74
122
 
75
123
  export const setLocale = async (locale: LangLocale) => {
76
- await i18next.changeLanguage(locale);
77
- localStorage.setItem("currentLocale", locale);
124
+ await i18next.changeLanguage(locale as string);
125
+ localStorage.setItem("currentLocale", locale as string);
78
126
  currentLocale.value = locale;
79
127
  };
@@ -0,0 +1,22 @@
1
+ import type { ModalDataProps } from "@allurereport/web-components";
2
+ import { signal } from "@preact/signals";
3
+
4
+ export const isModalOpen = signal(false);
5
+
6
+ export const modalData = signal<ModalDataProps>({
7
+ data: null,
8
+ preview: false,
9
+ component: null,
10
+ isModalOpen: isModalOpen.value,
11
+ closeModal: null,
12
+ title: "",
13
+ });
14
+
15
+ export const openModal = (props: ModalDataProps) => {
16
+ modalData.value = { ...props };
17
+ isModalOpen.value = true;
18
+ };
19
+
20
+ export const closeModal = () => {
21
+ isModalOpen.value = false;
22
+ };
@@ -0,0 +1,28 @@
1
+ import { QualityGateValidationResult } from "@allurereport/plugin-api";
2
+ import { fetchReportJsonData } from "@allurereport/web-commons";
3
+ import { signal } from "@preact/signals";
4
+ import { type StoreSignalState } from "./types";
5
+
6
+ export const qualityGateStore = signal<StoreSignalState<QualityGateValidationResult[]>>({
7
+ loading: true,
8
+ error: undefined,
9
+ data: undefined,
10
+ });
11
+
12
+ export const fetchQualityGateResults = async () => {
13
+ try {
14
+ const data = await fetchReportJsonData<QualityGateValidationResult[]>("widgets/quality-gate.json");
15
+
16
+ qualityGateStore.value = {
17
+ data,
18
+ error: undefined,
19
+ loading: false,
20
+ };
21
+ } catch (err) {
22
+ qualityGateStore.value = {
23
+ ...qualityGateStore.value,
24
+ error: err.message,
25
+ loading: false,
26
+ };
27
+ }
28
+ };
@@ -0,0 +1,108 @@
1
+ import { computed, signal } from "@preact/signals";
2
+
3
+ type NavigateToObject = {
4
+ category?: string;
5
+ params?: {
6
+ testResultId?: string | null;
7
+ subTab?: string | null;
8
+ };
9
+ };
10
+
11
+ type Route = {
12
+ category?: string;
13
+ params?: {
14
+ testResultId?: string | null;
15
+ subTab?: string | null;
16
+ };
17
+ };
18
+
19
+ export const parseHash = (): Route => {
20
+ const hash = globalThis.location.hash.replace(/^#/, "").trim();
21
+ const parts = hash.split("/").filter(Boolean);
22
+ const [first, second] = parts;
23
+
24
+ if (parts.length === 0) {
25
+ return {};
26
+ }
27
+
28
+ if (parts.length === 1) {
29
+ if (/^[a-f0-9]{32,}$/.test(first)) {
30
+ return { params: { testResultId: first } };
31
+ }
32
+ return { category: first || "", params: { testResultId: second } };
33
+ }
34
+
35
+ if (parts.length === 2) {
36
+ if (/^[a-f0-9]{32,}$/.test(first)) {
37
+ return {
38
+ params: {
39
+ testResultId: first,
40
+ subTab: second,
41
+ },
42
+ };
43
+ }
44
+
45
+ return {
46
+ category: first,
47
+ params: {
48
+ testResultId: second,
49
+ },
50
+ };
51
+ }
52
+
53
+ if (parts.length === 3) {
54
+ const [category, testResultId, subTab] = parts;
55
+ return { category, params: { testResultId, subTab } };
56
+ }
57
+
58
+ return {};
59
+ };
60
+
61
+ export const route = signal<Route>(parseHash());
62
+
63
+ export const handleHashChange = () => {
64
+ const newRoute = parseHash();
65
+
66
+ if (
67
+ newRoute.category !== route.value?.category ||
68
+ newRoute.params?.testResultId !== route.value.params?.testResultId ||
69
+ newRoute.params?.subTab !== route.value.params?.subTab
70
+ ) {
71
+ route.value = { ...newRoute };
72
+ }
73
+ };
74
+
75
+ export const navigateTo = (path: NavigateToObject | string) => {
76
+ let newHash = "";
77
+
78
+ if (typeof path === "string") {
79
+ newHash = path.startsWith("#") ? path.slice(1) : path;
80
+ } else {
81
+ const { category, params = {} } = path;
82
+ const parts: string[] = [];
83
+
84
+ if (category) {
85
+ parts.push(category);
86
+ }
87
+
88
+ if (params.testResultId) {
89
+ parts.push(params.testResultId);
90
+ }
91
+
92
+ if (params.subTab) {
93
+ parts.push(params.subTab);
94
+ }
95
+
96
+ newHash = parts.join("/");
97
+ }
98
+
99
+ history.pushState(null, "", `#${newHash}`);
100
+ handleHashChange();
101
+ };
102
+
103
+ export const openInNewTab = (path: string) => {
104
+ window.open(`#${path}`, "_blank");
105
+ };
106
+
107
+ export const activeTab = computed(() => route.value.category || "");
108
+ export const activeSubTab = computed(() => route.value.params?.subTab || "overview");
@@ -0,0 +1,63 @@
1
+ import { getReportOptions } from "@allurereport/web-commons";
2
+ import { effect, signal } from "@preact/signals";
3
+ import { navigateTo, parseHash, route } from "@/stores/router";
4
+ import type { AwesomeReportOptions } from "../../types.js";
5
+
6
+ const DEFAULT_SECTION = "default";
7
+ type Section = string;
8
+
9
+ export const currentSection = signal<Section>("");
10
+ export const availableSections = signal<Section[]>([]);
11
+
12
+ const updateSectionState = (section: Section): void => {
13
+ currentSection.value = section;
14
+ document.documentElement.setAttribute("data-section", section);
15
+ globalThis.localStorage.setItem("chosenSection", section);
16
+ };
17
+
18
+ export const setSection = (chosenSection: Section): void => {
19
+ const isDefaultSection = chosenSection === DEFAULT_SECTION;
20
+ const isValidSection = availableSections.value?.includes(chosenSection);
21
+ const isSectionChanged = currentSection.value !== chosenSection;
22
+
23
+ updateSectionState(chosenSection);
24
+
25
+ if (isDefaultSection) {
26
+ navigateTo({ category: "" });
27
+ return;
28
+ }
29
+
30
+ if (isSectionChanged && isValidSection) {
31
+ navigateTo({ category: chosenSection });
32
+ }
33
+ };
34
+
35
+ export const getSection = () => {
36
+ const { category } = parseHash();
37
+ availableSections.value = getReportOptions<AwesomeReportOptions>()?.sections ?? [];
38
+ const defaultSectionFromReportOptions = getReportOptions<AwesomeReportOptions>()?.defaultSection ?? "";
39
+ const sectionFromUrl = parseHash().category;
40
+ const sectionFromLS =
41
+ globalThis.localStorage.getItem("chosenSection") === ""
42
+ ? ""
43
+ : globalThis.localStorage.getItem("chosenSection") || defaultSectionFromReportOptions;
44
+ currentSection.value = sectionFromUrl || sectionFromLS;
45
+
46
+ if (category) {
47
+ setSection(category);
48
+ return;
49
+ }
50
+
51
+ if (sectionFromLS) {
52
+ setSection(sectionFromLS);
53
+ return;
54
+ }
55
+
56
+ setSection("");
57
+ };
58
+
59
+ effect(() => {
60
+ const category = route.value.category;
61
+
62
+ setSection(category || "");
63
+ });
@@ -2,8 +2,9 @@ import type { Statistic } from "@allurereport/core-api";
2
2
  import { fetchReportJsonData } from "@allurereport/web-commons";
3
3
  import { signal } from "@preact/signals";
4
4
  import type { StoreSignalState } from "@/stores/types";
5
+ import type { AwesomeTree } from "../../types";
5
6
 
6
- export const statsStore = signal<StoreSignalState<Statistic>>({
7
+ export const reportStatsStore = signal<StoreSignalState<Statistic>>({
7
8
  loading: true,
8
9
  error: undefined,
9
10
  data: {
@@ -11,26 +12,70 @@ export const statsStore = signal<StoreSignalState<Statistic>>({
11
12
  },
12
13
  });
13
14
 
14
- export const fetchStats = async () => {
15
- statsStore.value = {
16
- ...statsStore.value,
15
+ export const statsByEnvStore = signal<StoreSignalState<Record<string, Statistic>>>({
16
+ loading: true,
17
+ error: undefined,
18
+ data: {},
19
+ });
20
+
21
+ export const fetchReportStats = async () => {
22
+ reportStatsStore.value = {
23
+ ...reportStatsStore.value,
17
24
  loading: true,
18
25
  error: undefined,
19
26
  };
20
27
 
21
28
  try {
22
- const res = await fetchReportJsonData<Statistic>("widgets/allure_statistic.json");
29
+ const res = await fetchReportJsonData<Statistic>("widgets/statistic.json", { bustCache: true });
23
30
 
24
- statsStore.value = {
31
+ reportStatsStore.value = {
25
32
  data: res,
26
33
  error: undefined,
27
34
  loading: false,
28
35
  };
29
36
  } catch (err) {
30
- statsStore.value = {
37
+ reportStatsStore.value = {
31
38
  data: { total: 0 },
32
39
  error: err.message,
33
40
  loading: false,
34
41
  };
35
42
  }
36
43
  };
44
+
45
+ export const fetchEnvStats = async (envs: string[]) => {
46
+ const envsToFetch = envs.filter((env) => !statsByEnvStore.value.data?.[env]);
47
+
48
+ // all envs have already been fetched
49
+ if (envsToFetch.length === 0) {
50
+ return;
51
+ }
52
+
53
+ statsByEnvStore.value = {
54
+ ...statsByEnvStore.value,
55
+ loading: true,
56
+ error: undefined,
57
+ };
58
+
59
+ try {
60
+ const data = await Promise.all(
61
+ envsToFetch.map((env) => fetchReportJsonData<AwesomeTree>(`widgets/${env}/statistic.json`, { bustCache: true })),
62
+ );
63
+
64
+ statsByEnvStore.value = {
65
+ data: envs.reduce((acc, env, index) => {
66
+ return {
67
+ ...acc,
68
+ [env]: data[index],
69
+ };
70
+ }, {}),
71
+ loading: false,
72
+ error: undefined,
73
+ };
74
+ } catch (err) {
75
+ statsByEnvStore.value = {
76
+ ...statsByEnvStore.value,
77
+ error: err.message,
78
+ loading: false,
79
+ };
80
+ }
81
+ };
@@ -1,27 +1,29 @@
1
1
  import { fetchReportJsonData } from "@allurereport/web-commons";
2
2
  import { signal } from "@preact/signals";
3
- import { type AllureAwesomeTestResult } from "../../types";
3
+ import { type AwesomeTestResult } from "../../types";
4
4
  import { type StoreSignalState } from "./types";
5
5
 
6
- export type TestResultsStoreState = Record<string, AllureAwesomeTestResult>;
6
+ export type TrStoreState = Record<string, AwesomeTestResult>;
7
7
 
8
- export type TestResultNavStoreState = string[];
8
+ export type TrNavStoreState = string[];
9
9
 
10
- export const testResultStore = signal<StoreSignalState<TestResultsStoreState>>({
10
+ export const testResultStore = signal<StoreSignalState<TrStoreState>>({
11
11
  loading: true,
12
12
  error: undefined,
13
13
  data: undefined,
14
14
  });
15
15
 
16
- export const testResultNavStore = signal<StoreSignalState<TestResultNavStoreState>>({
16
+ export const testResultNavStore = signal<StoreSignalState<TrNavStoreState>>({
17
17
  loading: true,
18
18
  error: undefined,
19
19
  data: undefined,
20
20
  });
21
21
 
22
- export const fetchTestResultNav = async () => {
22
+ export const fetchTestResultNav = async (env?: string) => {
23
23
  try {
24
- const data = await fetchReportJsonData<string[]>("widgets/nav.json");
24
+ const data = await fetchReportJsonData<string[]>(env ? `widgets/${env}/nav.json` : "widgets/nav.json", {
25
+ bustCache: true,
26
+ });
25
27
 
26
28
  testResultNavStore.value = {
27
29
  data,
@@ -38,7 +40,7 @@ export const fetchTestResultNav = async () => {
38
40
  };
39
41
 
40
42
  export const fetchTestResult = async (testResultId: string) => {
41
- if (!testResultId) {
43
+ if (!testResultId || (testResultStore.value.data && testResultId in testResultStore.value.data)) {
42
44
  return;
43
45
  }
44
46
 
@@ -49,7 +51,9 @@ export const fetchTestResult = async (testResultId: string) => {
49
51
  };
50
52
 
51
53
  try {
52
- const data = await fetchReportJsonData<AllureAwesomeTestResult>(`data/test-results/${testResultId}.json`);
54
+ const data = await fetchReportJsonData<AwesomeTestResult>(`data/test-results/${testResultId}.json`, {
55
+ bustCache: true,
56
+ });
53
57
 
54
58
  testResultStore.value = {
55
59
  data: { ...testResultStore.value.data, [testResultId]: data },
@@ -1,33 +1,30 @@
1
1
  import { getReportOptions } from "@allurereport/web-commons";
2
+ import type { Theme } from "@allurereport/web-components";
2
3
  import { signal } from "@preact/signals";
3
- import type { AllureAwesomeReportOptions } from "../../types.js";
4
+ import type { AwesomeReportOptions } from "../../types.js";
4
5
 
5
- type Theme = "light" | "dark";
6
+ export const themeStore = signal<Theme>("auto");
6
7
 
7
- const { theme } = getReportOptions<AllureAwesomeReportOptions>() ?? {};
8
+ export const setTheme = (mode: "light" | "dark" | "auto") => {
9
+ themeStore.value = mode;
8
10
 
9
- export const themeStore = signal<Theme>("light");
11
+ try {
12
+ window.localStorage.setItem("theme", mode);
13
+ } catch {}
10
14
 
11
- export const setTheme = (newTheme: Theme): void => {
12
- themeStore.value = newTheme;
13
- document.documentElement.setAttribute("data-theme", newTheme);
14
- window.localStorage.setItem("theme", newTheme);
15
+ document.documentElement.setAttribute("data-theme", mode);
15
16
  };
16
17
 
17
18
  export const toggleTheme = () => {
18
- setTheme(themeStore.value === "light" ? "dark" : "light");
19
+ const order = ["light", "dark", "auto"];
20
+ const current = themeStore.value;
21
+ const next = order[(order.indexOf(current) + 1) % order.length] as Theme;
22
+ setTheme(next);
19
23
  };
20
24
 
21
25
  export const getTheme = () => {
26
+ const { theme } = getReportOptions<AwesomeReportOptions>() ?? {};
22
27
  const themeFromLS = (window.localStorage.getItem("theme") as Theme | null) || (theme as Theme);
23
28
 
24
- if (themeFromLS) {
25
- setTheme(themeFromLS);
26
- return;
27
- }
28
-
29
- const prefersDarkScheme = window.matchMedia("(prefers-color-scheme: dark)").matches;
30
- const initialTheme = prefersDarkScheme ? "dark" : "light";
31
-
32
- setTheme(initialTheme);
29
+ setTheme(themeFromLS);
33
30
  };
@@ -0,0 +1,39 @@
1
+ import type { TestResult } from "@allurereport/core-api";
2
+ import { fetchReportJsonData } from "@allurereport/web-commons";
3
+ import { signal } from "@preact/signals";
4
+ import type { StoreSignalState } from "@/stores/types";
5
+
6
+ export type TimlineTr = Pick<
7
+ TestResult,
8
+ "id" | "name" | "status" | "flaky" | "hidden" | "labels" | "environment" | "start" | "stop" | "duration"
9
+ >;
10
+
11
+ export const timelineStore = signal<StoreSignalState<TimlineTr[]>>({
12
+ loading: true,
13
+ error: undefined,
14
+ data: undefined,
15
+ });
16
+
17
+ export const fetchTimelineData = async () => {
18
+ timelineStore.value = {
19
+ ...timelineStore.value,
20
+ loading: true,
21
+ error: undefined,
22
+ };
23
+
24
+ try {
25
+ const res = await fetchReportJsonData<TimlineTr[]>("widgets/timeline.json", { bustCache: true });
26
+
27
+ timelineStore.value = {
28
+ data: res,
29
+ error: undefined,
30
+ loading: false,
31
+ };
32
+ } catch (err) {
33
+ timelineStore.value = {
34
+ data: undefined,
35
+ error: err.message,
36
+ loading: false,
37
+ };
38
+ }
39
+ };