@allurereport/web-awesome 3.8.2 → 3.10.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 (227) hide show
  1. package/README.md +112 -0
  2. package/allurerc-dev.mjs +10 -0
  3. package/dist/multi/121.app-b18cce138691927e8759.js +1 -0
  4. package/dist/multi/173.app-b18cce138691927e8759.js +1 -0
  5. package/dist/multi/174.app-b18cce138691927e8759.js +1 -0
  6. package/dist/multi/252.app-b18cce138691927e8759.js +1 -0
  7. package/dist/multi/282.app-b18cce138691927e8759.js +1 -0
  8. package/dist/multi/29.app-b18cce138691927e8759.js +1 -0
  9. package/dist/multi/310.app-b18cce138691927e8759.js +1 -0
  10. package/dist/multi/416.app-b18cce138691927e8759.js +1 -0
  11. package/dist/multi/507.app-b18cce138691927e8759.js +1 -0
  12. package/dist/multi/527.app-b18cce138691927e8759.js +1 -0
  13. package/dist/multi/600.app-b18cce138691927e8759.js +1 -0
  14. package/dist/multi/605.app-b18cce138691927e8759.js +1 -0
  15. package/dist/multi/638.app-b18cce138691927e8759.js +1 -0
  16. package/dist/multi/672.app-b18cce138691927e8759.js +1 -0
  17. package/dist/multi/686.app-b18cce138691927e8759.js +1 -0
  18. package/dist/multi/725.app-b18cce138691927e8759.js +1 -0
  19. package/dist/multi/741.app-b18cce138691927e8759.js +1 -0
  20. package/dist/multi/749.app-b18cce138691927e8759.js +1 -0
  21. package/dist/multi/755.app-b18cce138691927e8759.js +1 -0
  22. package/dist/multi/779.app-b18cce138691927e8759.js +1 -0
  23. package/dist/multi/894.app-b18cce138691927e8759.js +1 -0
  24. package/dist/multi/943.app-b18cce138691927e8759.js +1 -0
  25. package/dist/multi/980.app-b18cce138691927e8759.js +1 -0
  26. package/dist/multi/app-b18cce138691927e8759.js +2 -0
  27. package/dist/multi/manifest.json +26 -23
  28. package/dist/multi/styles-212da6c68fa0beb4c6c5.css +1 -0
  29. package/dist/multi/styles-5c882b14b6f3112e40c4.css +1 -0
  30. package/dist/multi/styles-a4f65de86208f79dd2be.css +58 -0
  31. package/dist/single/app-733f473da7b51f98876d.js +2 -0
  32. package/dist/single/manifest.json +1 -1
  33. package/package.json +19 -14
  34. package/src/assets/scss/_common.scss +2 -2
  35. package/src/assets/scss/index.scss +8 -6
  36. package/src/components/BaseLayout/index.tsx +14 -2
  37. package/src/components/BaseLayout/styles.scss +5 -5
  38. package/src/components/Categories/CategoryHeaderItem/styles.scss +2 -2
  39. package/src/components/Categories/CategoryTreeItem/styles.scss +2 -2
  40. package/src/components/Categories/GroupTreeItem/styles.scss +4 -5
  41. package/src/components/Categories/HistoryTreeItem/styles.scss +2 -2
  42. package/src/components/Categories/LabelTreeItem/styles.scss +2 -2
  43. package/src/components/Categories/MessageTreeItem/index.tsx +1 -1
  44. package/src/components/Categories/MessageTreeItem/styles.scss +18 -18
  45. package/src/components/Categories/sticky.ts +1 -1
  46. package/src/components/Footer/FooterVersion.tsx +5 -10
  47. package/src/components/Footer/index.tsx +7 -1
  48. package/src/components/Footer/styles.scss +8 -2
  49. package/src/components/Header/CiInfo/index.tsx +17 -13
  50. package/src/components/Header/CiInfo/styles.scss +1 -1
  51. package/src/components/Header/styles.scss +2 -2
  52. package/src/components/HeaderControls/index.tsx +1 -3
  53. package/src/components/HotkeysProvider/index.tsx +556 -0
  54. package/src/components/KeyboardShortcuts/index.tsx +73 -0
  55. package/src/components/KeyboardShortcuts/shortcutsConfig.ts +91 -0
  56. package/src/components/KeyboardShortcuts/styles.scss +69 -0
  57. package/src/components/MainReport/index.tsx +89 -72
  58. package/src/components/MainReport/styles.scss +20 -5
  59. package/src/components/Metadata/index.tsx +27 -6
  60. package/src/components/Metadata/styles.scss +21 -9
  61. package/src/components/MetadataButton/index.tsx +2 -0
  62. package/src/components/MetadataButton/styles.scss +1 -1
  63. package/src/components/NavTabs/styles.scss +8 -8
  64. package/src/components/ReportBody/styles.scss +3 -4
  65. package/src/components/ReportCategories/styles.scss +1 -1
  66. package/src/components/ReportFilters/styles.scss +1 -1
  67. package/src/components/ReportGlobalAttachments/styles.scss +1 -1
  68. package/src/components/ReportGlobalErrors/styles.scss +1 -1
  69. package/src/components/ReportHeader/index.tsx +25 -13
  70. package/src/components/ReportHeader/styles.scss +2 -2
  71. package/src/components/ReportMetadata/index.tsx +44 -15
  72. package/src/components/ReportMetadata/styles.scss +6 -6
  73. package/src/components/ReportQualityGateResults/styles.scss +2 -2
  74. package/src/components/ReportSearch/index.tsx +1 -5
  75. package/src/components/ReportTabs/styles.scss +9 -9
  76. package/src/components/SectionSwitcher/index.tsx +87 -10
  77. package/src/components/SideBySide/index.tsx +20 -2
  78. package/src/components/SideBySide/styles.scss +9 -1
  79. package/src/components/SplitLayout/index.tsx +11 -2
  80. package/src/components/SplitLayout/styles.scss +23 -4
  81. package/src/components/TestResult/TestStepsEmpty/styles.scss +1 -1
  82. package/src/components/TestResult/TrDescription/styles.scss +1 -1
  83. package/src/components/TestResult/TrDropdown/index.tsx +2 -2
  84. package/src/components/TestResult/TrDropdown/styles.scss +1 -1
  85. package/src/components/TestResult/TrEmpty/styles.scss +1 -1
  86. package/src/components/TestResult/TrEnvironmentItem/styles.scss +4 -4
  87. package/src/components/TestResult/TrError/index.tsx +32 -7
  88. package/src/components/TestResult/TrError/styles.scss +23 -23
  89. package/src/components/TestResult/TrHeader/styles.scss +2 -2
  90. package/src/components/TestResult/TrHistory/styles.scss +6 -6
  91. package/src/components/TestResult/TrInfo/styles.scss +8 -8
  92. package/src/components/TestResult/TrLinks/index.tsx +2 -2
  93. package/src/components/TestResult/TrLinks/styles.scss +2 -2
  94. package/src/components/TestResult/TrMetadata/index.tsx +1 -1
  95. package/src/components/TestResult/TrMetadata/styles.scss +1 -1
  96. package/src/components/TestResult/TrNavigation/index.tsx +1 -1
  97. package/src/components/TestResult/TrNavigation/styles.scss +2 -2
  98. package/src/components/TestResult/TrOverview.tsx +2 -0
  99. package/src/components/TestResult/TrParameters/index.tsx +1 -1
  100. package/src/components/TestResult/TrParameters/styles.scss +1 -1
  101. package/src/components/TestResult/TrPrevStatuses/styles.scss +8 -8
  102. package/src/components/TestResult/TrPwTraces/styles.scss +1 -1
  103. package/src/components/TestResult/TrRetriesView/TrRetriesItem.tsx +27 -1
  104. package/src/components/TestResult/TrRetriesView/styles.scss +20 -10
  105. package/src/components/TestResult/TrSetup/index.tsx +10 -4
  106. package/src/components/TestResult/TrSeverity/styles.scss +7 -7
  107. package/src/components/TestResult/TrStatus/styles.scss +2 -35
  108. package/src/components/TestResult/TrSteps/TrAttachment.tsx +79 -43
  109. package/src/components/TestResult/TrSteps/TrAttachmentInfo.tsx +44 -17
  110. package/src/components/TestResult/TrSteps/TrBodyItems.tsx +5 -2
  111. package/src/components/TestResult/TrSteps/TrErrorStep.tsx +3 -0
  112. package/src/components/TestResult/TrSteps/TrStep.tsx +15 -6
  113. package/src/components/TestResult/TrSteps/TrStepHeader.tsx +8 -5
  114. package/src/components/TestResult/TrSteps/index.tsx +7 -5
  115. package/src/components/TestResult/TrSteps/stepTreeExpansion.ts +27 -9
  116. package/src/components/TestResult/TrSteps/styles.scss +80 -20
  117. package/src/components/TestResult/TrTeardown/index.tsx +10 -4
  118. package/src/components/TestResult/bodyItems.ts +1 -1
  119. package/src/components/TestResult/index.tsx +8 -2
  120. package/src/components/TestResult/styles.scss +10 -1
  121. package/src/components/TestResult/trOverviewFocus.scss +4 -0
  122. package/src/components/Timeline/styles.scss +6 -6
  123. package/src/components/Tree/index.tsx +79 -5
  124. package/src/components/Tree/styles.scss +55 -35
  125. package/src/hooks/useTestResultOverviewFocusScroll.ts +23 -0
  126. package/src/index.html +30 -33
  127. package/src/index.tsx +12 -6
  128. package/src/locales/ar.json +62 -1
  129. package/src/locales/az.json +62 -1
  130. package/src/locales/de.json +62 -1
  131. package/src/locales/en.json +62 -1
  132. package/src/locales/es.json +62 -1
  133. package/src/locales/fr.json +62 -1
  134. package/src/locales/he.json +62 -1
  135. package/src/locales/hy.json +62 -1
  136. package/src/locales/it.json +62 -1
  137. package/src/locales/ja.json +62 -1
  138. package/src/locales/ka.json +62 -1
  139. package/src/locales/kr.json +62 -1
  140. package/src/locales/nl.json +62 -1
  141. package/src/locales/pl.json +62 -1
  142. package/src/locales/pt.json +62 -1
  143. package/src/locales/ru.json +62 -1
  144. package/src/locales/sv.json +62 -1
  145. package/src/locales/tr.json +62 -1
  146. package/src/locales/uk.json +62 -1
  147. package/src/locales/zh-TW.json +62 -1
  148. package/src/locales/zh.json +62 -1
  149. package/src/stores/keyboard.ts +371 -0
  150. package/src/stores/keyboardActions.ts +769 -0
  151. package/src/stores/locale.ts +5 -2
  152. package/src/stores/reportEnvSections.ts +6 -0
  153. package/src/stores/reportRootTabs.ts +95 -0
  154. package/src/stores/search.ts +147 -0
  155. package/src/stores/testResultOverviewNav.ts +119 -0
  156. package/src/stores/testResultTabs.ts +62 -0
  157. package/src/stores/timeline.ts +1 -1
  158. package/src/stores/tree.ts +42 -4
  159. package/src/stores/treeFilters/store.ts +3 -36
  160. package/src/stores/treeSort.ts +7 -1
  161. package/src/styles/_pane-active.scss +8 -0
  162. package/src/styles.scss +1 -1
  163. package/src/utils/atSeparator.ts +4 -0
  164. package/src/utils/flattenTestResultOverview.ts +182 -0
  165. package/src/utils/time.ts +2 -1
  166. package/src/utils/trOverviewFocus.ts +18 -0
  167. package/src/utils/treeFilters.ts +15 -4
  168. package/test/components/EnvironmentPicker.test.tsx +21 -3
  169. package/test/components/Footer.test.tsx +26 -0
  170. package/test/components/Header/CiInfo.test.tsx +56 -0
  171. package/test/components/Header.test.tsx +8 -0
  172. package/test/components/HeaderControls.test.tsx +28 -0
  173. package/test/components/ReportGlobals.test.tsx +9 -1
  174. package/test/components/ReportHeader.test.tsx +77 -0
  175. package/test/components/ReportMetadata.test.tsx +131 -0
  176. package/test/components/TestResult/PwTraceButton.test.tsx +8 -0
  177. package/test/components/TestResult/TrErrorStep.test.tsx +8 -0
  178. package/test/components/TestResult/TrOverview.test.tsx +30 -10
  179. package/test/components/TestResult/TrRetriesItem.test.tsx +163 -0
  180. package/test/components/TestResult/TrSteps.test.tsx +108 -0
  181. package/test/components/TestResult/bodyItems.test.ts +9 -1
  182. package/test/components/TestResult/openPwTraceInNewTab.test.ts +8 -0
  183. package/test/components/TestResult/stepTreeExpansion.test.ts +10 -2
  184. package/test/components/Timeline.test.tsx +15 -7
  185. package/test/stores/keyboard/keyboardActions.test.ts +615 -0
  186. package/test/stores/search.test.ts +143 -0
  187. package/test/stores/treeFilters/actions.test.ts +8 -0
  188. package/test/stores/treeSort.test.ts +58 -0
  189. package/test/utils/flattenTestResultOverview.test.ts +57 -0
  190. package/test/utils/ownerAddress.test.ts +9 -1
  191. package/test/utils/time.test.ts +52 -0
  192. package/test/utils/treeFilters.test.ts +113 -1
  193. package/types.d.ts +39 -0
  194. package/webpack.config.js +12 -7
  195. package/CONTRIBUTING.md +0 -34
  196. package/dist/multi/173.app-f008fb8342025f2b1ace.js +0 -1
  197. package/dist/multi/174.app-f008fb8342025f2b1ace.js +0 -1
  198. package/dist/multi/252.app-f008fb8342025f2b1ace.js +0 -1
  199. package/dist/multi/282.app-f008fb8342025f2b1ace.js +0 -1
  200. package/dist/multi/29.app-f008fb8342025f2b1ace.js +0 -1
  201. package/dist/multi/310.app-f008fb8342025f2b1ace.js +0 -1
  202. package/dist/multi/416.app-f008fb8342025f2b1ace.js +0 -1
  203. package/dist/multi/507.app-f008fb8342025f2b1ace.js +0 -1
  204. package/dist/multi/527.app-f008fb8342025f2b1ace.js +0 -1
  205. package/dist/multi/600.app-f008fb8342025f2b1ace.js +0 -1
  206. package/dist/multi/605.app-f008fb8342025f2b1ace.js +0 -1
  207. package/dist/multi/638.app-f008fb8342025f2b1ace.js +0 -1
  208. package/dist/multi/672.app-f008fb8342025f2b1ace.js +0 -1
  209. package/dist/multi/686.app-f008fb8342025f2b1ace.js +0 -1
  210. package/dist/multi/725.app-f008fb8342025f2b1ace.js +0 -1
  211. package/dist/multi/741.app-f008fb8342025f2b1ace.js +0 -1
  212. package/dist/multi/749.app-f008fb8342025f2b1ace.js +0 -1
  213. package/dist/multi/755.app-f008fb8342025f2b1ace.js +0 -1
  214. package/dist/multi/894.app-f008fb8342025f2b1ace.js +0 -1
  215. package/dist/multi/943.app-f008fb8342025f2b1ace.js +0 -1
  216. package/dist/multi/980.app-f008fb8342025f2b1ace.js +0 -1
  217. package/dist/multi/app-f008fb8342025f2b1ace.js +0 -2
  218. package/dist/multi/styles-9f7a23a0c8b79fa76981.css +0 -58
  219. package/dist/single/app-07332238da9897064301.js +0 -2
  220. package/src/assets/scss/day.scss +0 -53
  221. package/src/assets/scss/fonts.scss +0 -3
  222. package/src/assets/scss/night.scss +0 -63
  223. package/src/assets/scss/palette.scss +0 -393
  224. package/src/assets/scss/theme.scss +0 -330
  225. package/src/assets/scss/vars.scss +0 -11
  226. /package/dist/multi/{app-f008fb8342025f2b1ace.js.LICENSE.txt → app-b18cce138691927e8759.js.LICENSE.txt} +0 -0
  227. /package/dist/single/{app-07332238da9897064301.js.LICENSE.txt → app-733f473da7b51f98876d.js.LICENSE.txt} +0 -0
@@ -0,0 +1,91 @@
1
+ import { formatHotkey, type HotkeyBinding } from "@allurereport/web-commons";
2
+
3
+ export type ShortcutGroupId = "global" | "tree" | "testResult";
4
+
5
+ export type ShortcutItem = {
6
+ binding: Pick<HotkeyBinding, "key" | "code" | "modifiers">;
7
+ labelKey: string;
8
+ };
9
+
10
+ export type ShortcutGroup = {
11
+ id: ShortcutGroupId;
12
+ titleKey: string;
13
+ items: ShortcutItem[];
14
+ };
15
+
16
+ export const shortcutGroups: ShortcutGroup[] = [
17
+ {
18
+ id: "global",
19
+ titleKey: "groups.global",
20
+ items: [
21
+ { binding: { key: "?", code: "Slash", modifiers: { shift: true } }, labelKey: "items.toggleHelp" },
22
+ { binding: { key: "s", code: "KeyS" }, labelKey: "items.focusSearch" },
23
+ { binding: { key: "Escape" }, labelKey: "items.blurSearch" },
24
+ { binding: { key: "[", code: "BracketLeft" }, labelKey: "items.focusTree" },
25
+ { binding: { key: "]", code: "BracketRight" }, labelKey: "items.focusTestResult" },
26
+ { binding: { key: "l", code: "KeyL", modifiers: { shift: true } }, labelKey: "items.toggleLayout" },
27
+ { binding: { key: "\\", code: "Backslash", modifiers: { ctrlOrMeta: true } }, labelKey: "items.toggleLayoutAlt" },
28
+ { binding: { key: "1" }, labelKey: "items.reportTabResults" },
29
+ { binding: { key: "2" }, labelKey: "items.reportTabCategories" },
30
+ { binding: { key: "3" }, labelKey: "items.reportTabQualityGate" },
31
+ { binding: { key: "4" }, labelKey: "items.reportTabGlobalAttachments" },
32
+ { binding: { key: "5" }, labelKey: "items.reportTabGlobalErrors" },
33
+ { binding: { key: "Tab" }, labelKey: "items.reportTabNext" },
34
+ { binding: { key: "Tab", modifiers: { shift: true } }, labelKey: "items.reportTabPrev" },
35
+ ],
36
+ },
37
+ {
38
+ id: "tree",
39
+ titleKey: "groups.tree",
40
+ items: [
41
+ { binding: { key: "j", code: "KeyJ" }, labelKey: "items.moveDown" },
42
+ { binding: { key: "k", code: "KeyK" }, labelKey: "items.moveUp" },
43
+ { binding: { key: "h", code: "KeyH" }, labelKey: "items.collapse" },
44
+ { binding: { key: "l", code: "KeyL" }, labelKey: "items.expand" },
45
+ { binding: { key: "p", code: "KeyP" }, labelKey: "items.parent" },
46
+ { binding: { key: "u", code: "KeyU" }, labelKey: "items.parentAlt" },
47
+ { binding: { key: "o", code: "KeyO" }, labelKey: "items.openNode" },
48
+ { binding: { key: "-", code: "Minus" }, labelKey: "items.collapseNode" },
49
+ { binding: { key: "+", code: "Equal", modifiers: { shift: true } }, labelKey: "items.expandNode" },
50
+ { binding: { key: "C", code: "KeyC" }, labelKey: "items.collapseAll" },
51
+ { binding: { key: "A", code: "KeyA" }, labelKey: "items.expandAll" },
52
+ { binding: { key: ">", code: "Period", modifiers: { shift: true } }, labelKey: "items.subtreeCycle" },
53
+ { binding: { key: "C", code: "KeyC", modifiers: { shift: true } }, labelKey: "items.subtreeCollapse" },
54
+ { binding: { key: "f", code: "KeyF" }, labelKey: "items.subtreeFirstLevel" },
55
+ { binding: { key: "A", code: "KeyA", modifiers: { shift: true } }, labelKey: "items.subtreeExpand" },
56
+ { binding: { key: " " }, labelKey: "items.toggleNode" },
57
+ { binding: { key: "Enter" }, labelKey: "items.openTest" },
58
+ { binding: { key: "g" }, labelKey: "items.firstTest" },
59
+ { binding: { key: "G", modifiers: { shift: true } }, labelKey: "items.lastTest" },
60
+ { binding: { key: "Home" }, labelKey: "items.treeTop" },
61
+ { binding: { key: "z", code: "KeyZ" }, labelKey: "items.scrollTreeTop" },
62
+ { binding: { key: "V", code: "KeyV" }, labelKey: "items.toggleReportVariables" },
63
+ { binding: { key: "M", code: "KeyM" }, labelKey: "items.toggleReportMetadata" },
64
+ ],
65
+ },
66
+ {
67
+ id: "testResult",
68
+ titleKey: "groups.testResult",
69
+ items: [
70
+ { binding: { key: "n", code: "KeyN" }, labelKey: "items.nextTest" },
71
+ { binding: { key: "ArrowDown" }, labelKey: "items.nextTest" },
72
+ { binding: { key: "j", code: "KeyJ" }, labelKey: "items.nextTest" },
73
+ { binding: { key: "N", code: "KeyN", modifiers: { shift: true } }, labelKey: "items.prevTest" },
74
+ { binding: { key: "ArrowUp" }, labelKey: "items.prevTest" },
75
+ { binding: { key: "k", code: "KeyK" }, labelKey: "items.prevTest" },
76
+ { binding: { key: "Tab" }, labelKey: "items.testTabNext" },
77
+ { binding: { key: "Tab", modifiers: { shift: true } }, labelKey: "items.testTabPrev" },
78
+ { binding: { key: "1" }, labelKey: "items.tabOverview" },
79
+ { binding: { key: "2" }, labelKey: "items.tabHistory" },
80
+ { binding: { key: "3" }, labelKey: "items.tabRetries" },
81
+ { binding: { key: "4" }, labelKey: "items.tabAttachments" },
82
+ { binding: { key: "5" }, labelKey: "items.tabEnvironments" },
83
+ { binding: { key: "l", code: "KeyL" }, labelKey: "items.toggleLabels" },
84
+ { binding: { key: "p", code: "KeyP" }, labelKey: "items.toggleParameters" },
85
+ { binding: { key: "i", code: "KeyI" }, labelKey: "items.toggleLinks" },
86
+ { binding: { key: "Escape" }, labelKey: "items.backToTree" },
87
+ ],
88
+ },
89
+ ];
90
+
91
+ export const formatShortcut = (binding: Pick<HotkeyBinding, "key" | "code" | "modifiers">) => formatHotkey(binding);
@@ -0,0 +1,69 @@
1
+ .shortcuts {
2
+ position: fixed;
3
+ right: 16px;
4
+ bottom: 16px;
5
+ z-index: 1000;
6
+ display: flex;
7
+ flex-direction: column;
8
+ align-items: flex-end;
9
+ gap: 8px;
10
+ pointer-events: none;
11
+ }
12
+
13
+ .trigger {
14
+ pointer-events: auto;
15
+ box-shadow: var(--box-shadow, 0 2px 8px rgb(0 0 0 / 12%));
16
+ }
17
+
18
+ .panel {
19
+ pointer-events: auto;
20
+ width: min(360px, calc(100vw - 32px));
21
+ max-height: min(480px, calc(100vh - 96px));
22
+ overflow: auto;
23
+ padding: 12px 16px;
24
+ border-radius: 8px;
25
+ border: 1px solid var(--color-border-default);
26
+ background: var(--color-bg-raised);
27
+ box-shadow: 0 8px 24px rgb(0 0 0 / 16%);
28
+ }
29
+
30
+ .header {
31
+ display: flex;
32
+ align-items: center;
33
+ justify-content: space-between;
34
+ gap: 8px;
35
+ margin-bottom: 12px;
36
+ }
37
+
38
+ .group {
39
+ &:not(:last-child) {
40
+ margin-bottom: 12px;
41
+ }
42
+ }
43
+
44
+ .groupTitle {
45
+ margin-bottom: 6px;
46
+ color: var(--color-text-secondary);
47
+ }
48
+
49
+ .item {
50
+ display: flex;
51
+ align-items: center;
52
+ justify-content: space-between;
53
+ gap: 12px;
54
+ padding: 4px 0;
55
+ }
56
+
57
+ .keys {
58
+ flex-shrink: 0;
59
+ font-family: var(--font-family-mono);
60
+ font-size: var(--font-size-xs);
61
+ color: var(--color-text-secondary);
62
+ background: var(--color-bg-neutral);
63
+ border-radius: 4px;
64
+ padding: 2px 6px;
65
+ }
66
+
67
+ .label {
68
+ text-align: right;
69
+ }
@@ -13,6 +13,7 @@ import { reportStatsStore, useI18n } from "@/stores";
13
13
  import { categoriesStore } from "@/stores/categories";
14
14
  import { currentEnvironment } from "@/stores/env";
15
15
  import { globalsStore } from "@/stores/globals";
16
+ import { activePane, focusTreePane } from "@/stores/keyboard";
16
17
  import { isSplitMode } from "@/stores/layout";
17
18
  import { qualityGateStore } from "@/stores/qualityGate";
18
19
  import {
@@ -84,6 +85,7 @@ const MainReport = () => {
84
85
  if (isCurrentTab) {
85
86
  return;
86
87
  }
88
+ focusTreePane();
87
89
  setCurrentTab(id);
88
90
  if (id === ReportRootTab.Results) {
89
91
  if (currentTrId.value) {
@@ -127,83 +129,98 @@ const MainReport = () => {
127
129
  return null;
128
130
  };
129
131
 
132
+ const treePaneActive = isSplitMode.value && activePane.value === "tree";
133
+
130
134
  return (
131
- <div className={clsx(styles.content, isSplitMode.value ? styles["scroll-inside"] : "")}>
132
- <ReportHeader />
135
+ <div
136
+ className={clsx(
137
+ styles.content,
138
+ isSplitMode.value && styles["scroll-inside"],
139
+ treePaneActive && styles["pane-active"],
140
+ )}
141
+ onMouseDown={() => focusTreePane()}
142
+ >
143
+ <div className={styles["main-report-header"]}>
144
+ <ReportHeader />
145
+ </div>
133
146
  <div className={styles["main-report-tabs"]}>
134
147
  <NavTabs initialTab={initialTab}>
135
148
  <RootTabRouteSync />
136
- <NavTabsList>
137
- <Loadable
138
- source={reportStatsStore}
139
- renderData={(stats) => (
140
- <RootTab id={ReportRootTab.Results}>
141
- {t("results")} <Counter count={stats?.total ?? 0} />
142
- </RootTab>
143
- )}
144
- />
145
- <Loadable
146
- source={categoriesStore}
147
- renderData={(categories) => {
148
- if (!categories || !categories.roots?.length) {
149
- return null;
150
- }
151
- return (
152
- <>
153
- <RootTab id={ReportRootTab.Categories}>
154
- {t("categories")} <Counter count={categories.roots?.length} />
155
- </RootTab>
156
- </>
157
- );
158
- }}
159
- />
160
- <Loadable
161
- source={qualityGateStore}
162
- renderData={(results) => {
163
- const currentEnvResults = currentEnvironment.value
164
- ? (results[currentEnvironment.value] ?? [])
165
- : Object.values(results).flatMap((envResults) => envResults);
166
-
167
- return (
168
- <RootTab id={ReportRootTab.QualityGate}>
169
- {t("qualityGates")}{" "}
170
- <Counter
171
- status={currentEnvResults.length > 0 ? "failed" : undefined}
172
- count={currentEnvResults.length}
173
- />
174
- </RootTab>
175
- );
176
- }}
177
- />
178
- <Loadable
179
- source={globalsStore}
180
- renderData={({ attachments = [], attachmentsByEnv = {}, errors = [], errorsByEnv = {} }) => {
181
- const currentEnvAttachments = currentEnvironment.value
182
- ? (attachmentsByEnv[currentEnvironment.value] ?? [])
183
- : attachments;
184
- const currentEnvErrors = currentEnvironment.value
185
- ? (errorsByEnv[currentEnvironment.value] ?? [])
186
- : errors;
187
-
188
- return (
189
- <>
190
- <RootTab id={ReportRootTab.GlobalAttachments}>
191
- {t("globalAttachments")} <Counter count={currentEnvAttachments.length} />
149
+ <div className={styles["main-report-tabs-layout"]}>
150
+ <div className={styles["main-report-tabs-nav"]}>
151
+ <NavTabsList>
152
+ <Loadable
153
+ source={reportStatsStore}
154
+ renderData={(stats) => (
155
+ <RootTab id={ReportRootTab.Results}>
156
+ {t("results")} <Counter count={stats?.total ?? 0} />
192
157
  </RootTab>
193
- <RootTab id={ReportRootTab.GlobalErrors}>
194
- {t("globalErrors")}{" "}
195
- <Counter
196
- status={currentEnvErrors.length > 0 ? "failed" : undefined}
197
- count={currentEnvErrors.length}
198
- />
199
- </RootTab>
200
- </>
201
- );
202
- }}
203
- />
204
- </NavTabsList>
205
- <div className={styles["main-report-tabs-content"]}>
206
- <MainReportContent />
158
+ )}
159
+ />
160
+ <Loadable
161
+ source={categoriesStore}
162
+ renderData={(categories) => {
163
+ if (!categories || !categories.roots?.length) {
164
+ return null;
165
+ }
166
+ return (
167
+ <>
168
+ <RootTab id={ReportRootTab.Categories}>
169
+ {t("categories")} <Counter count={categories.roots?.length} />
170
+ </RootTab>
171
+ </>
172
+ );
173
+ }}
174
+ />
175
+ <Loadable
176
+ source={qualityGateStore}
177
+ renderData={(results) => {
178
+ const currentEnvResults = currentEnvironment.value
179
+ ? (results[currentEnvironment.value] ?? [])
180
+ : Object.values(results).flatMap((envResults) => envResults);
181
+
182
+ return (
183
+ <RootTab id={ReportRootTab.QualityGate}>
184
+ {t("qualityGates")}{" "}
185
+ <Counter
186
+ status={currentEnvResults.length > 0 ? "failed" : undefined}
187
+ count={currentEnvResults.length}
188
+ />
189
+ </RootTab>
190
+ );
191
+ }}
192
+ />
193
+ <Loadable
194
+ source={globalsStore}
195
+ renderData={({ attachments = [], attachmentsByEnv = {}, errors = [], errorsByEnv = {} }) => {
196
+ const currentEnvAttachments = currentEnvironment.value
197
+ ? (attachmentsByEnv[currentEnvironment.value] ?? [])
198
+ : attachments;
199
+ const currentEnvErrors = currentEnvironment.value
200
+ ? (errorsByEnv[currentEnvironment.value] ?? [])
201
+ : errors;
202
+
203
+ return (
204
+ <>
205
+ <RootTab id={ReportRootTab.GlobalAttachments}>
206
+ {t("globalAttachments")} <Counter count={currentEnvAttachments.length} />
207
+ </RootTab>
208
+ <RootTab id={ReportRootTab.GlobalErrors}>
209
+ {t("globalErrors")}{" "}
210
+ <Counter
211
+ status={currentEnvErrors.length > 0 ? "failed" : undefined}
212
+ count={currentEnvErrors.length}
213
+ />
214
+ </RootTab>
215
+ </>
216
+ );
217
+ }}
218
+ />
219
+ </NavTabsList>
220
+ </div>
221
+ <div className={styles["main-report-tabs-content"]}>
222
+ <MainReportContent />
223
+ </div>
207
224
  </div>
208
225
  </NavTabs>
209
226
  </div>
@@ -1,21 +1,36 @@
1
+ @use "../../styles/pane-active" as paneActive;
2
+
1
3
  .content {
4
+ position: relative;
2
5
  box-shadow: var(--shadow-small);
3
- background: var(--bg-base-primary);
6
+ background: var(--color-bg-primary);
4
7
  border-radius: 12px;
5
8
  width: 100%;
6
9
  }
7
10
 
8
11
  .scroll-inside {
9
- overflow: auto;
10
- height: 100%;
12
+ display: flex;
13
+ flex-direction: column;
11
14
  border-radius: 0;
12
- scrollbar-width: thin;
15
+ @include paneActive.split-pane-indicator;
16
+
17
+ &.pane-active {
18
+ @include paneActive.split-pane-indicator-active;
19
+ }
20
+ }
21
+
22
+ .main-report-header {
23
+ flex-shrink: 0;
13
24
  }
14
25
 
15
26
  .main-report-tabs {
16
27
  padding: 0 24px;
17
28
  }
18
29
 
30
+ .main-report-tabs-nav {
31
+ flex-shrink: 0;
32
+ }
33
+
19
34
  .main-report-tabs-content {
20
- border-top: 1px solid var(--on-border-primary);
35
+ border-top: 1px solid var(--color-border-default);
21
36
  }
@@ -1,4 +1,5 @@
1
- import { Button, ButtonLink, Menu, Text, allureIcons } from "@allurereport/web-components";
1
+ import { sanitizeExternalUrl } from "@allurereport/core-api";
2
+ import { Button, ButtonLink, Menu, SvgIcon, Text, allureIcons } from "@allurereport/web-components";
2
3
  import clsx from "clsx";
3
4
  import type { FunctionalComponent } from "preact";
4
5
  import { useState } from "preact/hooks";
@@ -23,8 +24,8 @@ export const MetadataList: FunctionalComponent<MetadataProps & { columns?: numbe
23
24
  style={{ gridTemplateColumns: `repeat(${columns}, ${100 / columns - 5}%)` }}
24
25
  data-testid={"metadata-list"}
25
26
  >
26
- {envInfo?.map(({ name, values, value }) => (
27
- <MetadataKeyValue key={name} size={size} title={name} value={value} values={values} />
27
+ {envInfo?.map(({ name, values, value, url }, index) => (
28
+ <MetadataKeyValue key={`${name}-${index}`} size={size} title={name} value={value} values={values} url={url} />
28
29
  ))}
29
30
  </div>
30
31
  );
@@ -160,12 +161,31 @@ const MetaDataOwnerLabel: FunctionalComponent<{
160
161
  const MetaDataKeyLabel: FunctionalComponent<{
161
162
  name: string;
162
163
  size?: "s" | "m";
164
+ url?: string;
163
165
  value: string;
164
- }> = ({ name, size = "s", value }) => {
166
+ }> = ({ name, size = "s", url, value }) => {
165
167
  if (name === "owner") {
166
168
  return <MetaDataOwnerLabel value={value} size={size} />;
167
169
  }
168
170
 
171
+ const safeUrl = sanitizeExternalUrl(url);
172
+
173
+ if (safeUrl) {
174
+ return (
175
+ <a
176
+ className={clsx(styles["report-metadata-keyvalue-wrapper"], styles["report-metadata-keyvalue-link"])}
177
+ href={safeUrl}
178
+ target="_blank"
179
+ rel="noopener noreferrer"
180
+ >
181
+ <Text type={"ui"} size={size} bold className={styles["report-metadata-keyvalue-value"]}>
182
+ {value}
183
+ </Text>
184
+ <SvgIcon id={allureIcons.lineGeneralLinkExternal} size="s" />
185
+ </a>
186
+ );
187
+ }
188
+
169
189
  return (
170
190
  <Menu
171
191
  size="xl"
@@ -186,10 +206,11 @@ const MetaDataKeyLabel: FunctionalComponent<{
186
206
 
187
207
  const MetadataKeyValue: FunctionalComponent<{
188
208
  title: string;
209
+ url?: string;
189
210
  value?: string;
190
211
  values?: string[];
191
212
  size?: "s" | "m";
192
- }> = ({ title, value, values, size = "m" }) => {
213
+ }> = ({ title, url, value, values, size = "m" }) => {
193
214
  return (
194
215
  <div className={styles["report-metadata-keyvalue"]} data-testid={"metadata-item"}>
195
216
  <Text
@@ -208,7 +229,7 @@ const MetadataKeyValue: FunctionalComponent<{
208
229
  </div>
209
230
  ) : (
210
231
  <div className={styles["report-metadata-values"]} data-testid={"metadata-item-value"}>
211
- <MetaDataKeyLabel value={value ?? ""} name={title} />
232
+ <MetaDataKeyLabel value={value ?? ""} name={title} url={url} />
212
233
  </div>
213
234
  )}
214
235
  </div>
@@ -6,7 +6,7 @@
6
6
  }
7
7
 
8
8
  .report-metadata-separator {
9
- border-left: 1px solid var(--on-border-primary);
9
+ border-left: 1px solid var(--color-border-default);
10
10
  height: 24px;
11
11
  margin: 11px 0;
12
12
  }
@@ -22,8 +22,8 @@
22
22
  justify-content: space-between;
23
23
  align-items: baseline;
24
24
  padding: 16px 0;
25
- border-top: 1px solid var(--on-border-primary);
26
- border-bottom: 1px solid var(--on-border-primary);
25
+ border-top: 1px solid var(--color-border-default);
26
+ border-bottom: 1px solid var(--color-border-default);
27
27
  width: 100%;
28
28
  }
29
29
 
@@ -35,7 +35,7 @@
35
35
  }
36
36
 
37
37
  .metadata-item-title {
38
- color: var(--on-text-secondary);
38
+ color: var(--color-text-secondary);
39
39
  margin-bottom: 6px;
40
40
  }
41
41
 
@@ -45,7 +45,7 @@
45
45
 
46
46
  .report-metadata {
47
47
  padding: 16px 0;
48
- border-bottom: 1px solid var(--on-border-primary);
48
+ border-bottom: 1px solid var(--color-border-default);
49
49
  }
50
50
 
51
51
  .report-metadata-keyvalue {
@@ -77,7 +77,7 @@
77
77
  }
78
78
 
79
79
  .report-metadata-keyvalue-wrapper {
80
- background: var(--on-border-primary);
80
+ background: var(--color-border-default);
81
81
  border-radius: 4px;
82
82
  text-overflow: ellipsis;
83
83
  overflow: hidden;
@@ -85,6 +85,18 @@
85
85
  line-height: 16px;
86
86
  }
87
87
 
88
+ .report-metadata-keyvalue-link {
89
+ display: inline-flex;
90
+ align-items: center;
91
+ gap: 4px;
92
+ color: inherit;
93
+ text-decoration: none;
94
+
95
+ &:hover {
96
+ text-decoration: underline;
97
+ }
98
+ }
99
+
88
100
  .report-metadata-keyvalue-value {
89
101
  width: max-content;
90
102
  height: max-content;
@@ -118,7 +130,7 @@
118
130
  width: 4px;
119
131
  height: 12px;
120
132
  border-radius: 2px;
121
- background: var(--on-text-secondary);
133
+ background: var(--color-text-secondary);
122
134
  margin-right: 8px;
123
135
  align-self: center;
124
136
  @include status-bg-and-text;
@@ -131,7 +143,7 @@
131
143
 
132
144
  .metadata-icon {
133
145
  margin-right: 8px;
134
- color: var(--on-icon-secondary);
146
+ color: var(--color-icon-secondary);
135
147
  }
136
148
 
137
149
  .metadata-tooltip {
@@ -145,7 +157,7 @@
145
157
  .metadata-tooltip-value {
146
158
  flex: 1 1 auto;
147
159
  min-width: 320px;
148
- background: var(--bg-base-secondary);
160
+ background: var(--color-bg-secondary);
149
161
  max-height: 238px;
150
162
  padding: 8px 16px;
151
163
  overflow: hidden;
@@ -20,6 +20,7 @@ export const MetadataButton: FunctionalComponent<MetadataButtonProps> = ({
20
20
  title,
21
21
  titleTooltipText,
22
22
  truncateTitle = false,
23
+ className,
23
24
  ...rest
24
25
  }) => {
25
26
  const { ref: titleRef, isTruncated: isTitleTruncated } = useElementTruncation<HTMLSpanElement>([title], {
@@ -41,6 +42,7 @@ export const MetadataButton: FunctionalComponent<MetadataButtonProps> = ({
41
42
  styles["report-metadata-header"],
42
43
  truncateTitle && styles["report-metadata-header-truncated"],
43
44
  isOpened && styles["report-metadata-header-opened"],
45
+ className,
44
46
  )}
45
47
  type={"button"}
46
48
  onClick={() => setIsOpen(!isOpened)}
@@ -40,7 +40,7 @@
40
40
 
41
41
  &:hover {
42
42
  &:after {
43
- background-color: var(--bg-control-flat-medium);
43
+ background-color: var(--color-control-bg-ghost-hover);
44
44
  }
45
45
 
46
46
  .report-metadata-header-arrow {
@@ -11,13 +11,13 @@
11
11
  }
12
12
 
13
13
  .tab {
14
- color: var(--on-text-primary);
14
+ color: var(--color-text-primary);
15
15
  cursor: pointer;
16
16
  user-select: none;
17
17
  flex-shrink: 0;
18
18
  transform: scale(1);
19
19
  outline: none;
20
- background-color: var(--bg-base-primary);
20
+ background-color: var(--color-bg-primary);
21
21
  padding: 8px;
22
22
  border: none;
23
23
  border-radius: 4px;
@@ -38,11 +38,11 @@
38
38
  }
39
39
 
40
40
  &[aria-current] {
41
- background-color: var(--bg-base-primary);
41
+ background-color: var(--color-bg-primary);
42
42
  cursor: default;
43
43
 
44
44
  &:after {
45
- border-bottom: 2px solid var(--on-support-aldebaran);
45
+ border-bottom: 2px solid var(--color-intent-primary-text);
46
46
  }
47
47
 
48
48
  span {
@@ -51,11 +51,11 @@
51
51
  }
52
52
 
53
53
  &:hover:not([aria-current]) {
54
- background-color: var(--bg-control-flat-medium);
54
+ background-color: var(--color-control-bg-ghost-hover);
55
55
  }
56
56
 
57
57
  &:active:not([aria-current]) {
58
- background-color: var(--bg-control-flat-heavy);
58
+ background-color: var(--color-control-bg-ghost-active);
59
59
  transform: scale(0.94);
60
60
  }
61
61
 
@@ -64,10 +64,10 @@
64
64
  }
65
65
 
66
66
  &:focus-visible {
67
- outline: 0 solid var(--ad-other-focus);
67
+ outline: 0 solid var(--color-focus-ring);
68
68
 
69
69
  &:not([aria-current]) {
70
- background-color: var(--bg-control-flat-medium);
70
+ background-color: var(--color-control-bg-ghost-hover);
71
71
  }
72
72
  }
73
73
  }
@@ -6,8 +6,7 @@
6
6
  position: sticky;
7
7
  left: 0;
8
8
  top: 0;
9
- left: 0;
10
- background: var(--bg-base-primary);
9
+ background: var(--color-bg-primary);
11
10
  z-index: 10;
12
11
  }
13
12
 
@@ -37,7 +36,7 @@
37
36
  /* This is a hack because button do not have this state */
38
37
  .filtersBtnWithFilters > button::after {
39
38
  content: "";
40
- background-color: var(--bg-support-aldebaran);
39
+ background-color: var(--color-intent-primary-bg);
41
40
  width: 6px;
42
41
  height: 6px;
43
42
  border-radius: 100px;
@@ -51,7 +50,7 @@
51
50
  }
52
51
 
53
52
  .sortByText {
54
- color: var(--on-text-secondary);
53
+ color: var(--color-text-secondary);
55
54
  }
56
55
 
57
56
  .sortByBtnWrap {
@@ -35,7 +35,7 @@
35
35
  .report-categories-result-icon {
36
36
  flex: 0 0 auto;
37
37
  margin-top: 3px;
38
- color: var(--bg-support-capella);
38
+ color: var(--color-status-failed-chart);
39
39
  }
40
40
 
41
41
  .report-categories-result-content {