diff --git a/packages/plugin-api/src/utils/tree.ts b/packages/plugin-api/src/utils/tree.ts index 30a3fd7..dddad90 100644 --- a/packages/plugin-api/src/utils/tree.ts +++ b/packages/plugin-api/src/utils/tree.ts @@ -122,6 +122,12 @@ export const createTreeByLabels = (data: TestResult[], labelNames: string[]) => ); }; +/** + * Mutates the given tree by sorting leaves in each group. + * Returns the link to the same tree. + * @param tree + * @param comparator + */ export const sortTree = (tree: TreeData, comparator: Comparator>) => { const { root, leavesById, groupsById } = tree; const sortGroupLeaves = (group: TreeGroup) => { @@ -152,6 +158,12 @@ export const sortTree = (tree: TreeData, comparator: Comparator( tree: TreeData, transformer: (leaf: TreeLeaf, idx: number) => TreeLeaf, diff --git a/packages/web-awesome/src/components/app/Tree/index.tsx b/packages/web-awesome/src/components/app/Tree/index.tsx index 15dc8ac..940f2b0 100644 --- a/packages/web-awesome/src/components/app/Tree/index.tsx +++ b/packages/web-awesome/src/components/app/Tree/index.tsx @@ -1,11 +1,12 @@ import { useEffect } from "preact/hooks"; import { useTabsContext } from "@/components/app/Tabs"; import Tree from "@/components/app/Tree/Tree"; +import { Button } from "@/components/commons/Button"; import { Loadable } from "@/components/commons/Loadable"; import { PageLoader } from "@/components/commons/PageLoader"; import { Text } from "@/components/commons/Typography"; import { useI18n } from "@/stores/locale"; -import { filteredTree, setTreeStatus, treeStore } from "@/stores/tree"; +import { clearTreeFilters, filteredTree, noTests, noTestsFound, setTreeStatus, treeStore } from "@/stores/tree"; import type { AllureAwesomeStatus } from "../../../../types"; import * as styles from "./styles.scss"; @@ -21,10 +22,8 @@ export const TreeList = () => { } - renderData={(treeData) => { - const { groups, leaves } = treeData?.root ?? {}; - - if (!groups && !leaves) { + renderData={() => { + if (noTests.value) { return (
@@ -34,6 +33,26 @@ export const TreeList = () => { ); } + if (noTestsFound.value) { + return ( +
+
+ + {t("no-tests-found")} + +
+
+ ); + } + return (
diff --git a/packages/web-awesome/src/components/app/Tree/styles.scss b/packages/web-awesome/src/components/app/Tree/styles.scss index 0a49833..95d60d7 100644 --- a/packages/web-awesome/src/components/app/Tree/styles.scss +++ b/packages/web-awesome/src/components/app/Tree/styles.scss @@ -159,16 +159,18 @@ } .tree-empty-results { - display: flex; padding: 44px 24px; - align-items: center; - justify-content: center; + text-align: center; } .tree-empty-results-title { color: var(--on-text-secondary); } +.tree-empty-results-clear-button { + margin-top: 4px; +} + .order { user-select: none; } diff --git a/packages/web-awesome/src/components/commons/SearchBox/index.tsx b/packages/web-awesome/src/components/commons/SearchBox/index.tsx index 9efe399..bfa3dac 100644 --- a/packages/web-awesome/src/components/commons/SearchBox/index.tsx +++ b/packages/web-awesome/src/components/commons/SearchBox/index.tsx @@ -1,5 +1,5 @@ import { clsx } from "clsx"; -import { useState } from "preact/hooks"; +import {useEffect, useState} from "preact/hooks"; import searchIcon from "@/assets/svg/line-general-search-md.svg"; import closeIcon from "@/assets/svg/line-general-x-close.svg"; import { useDebouncedCallback } from "@/hooks/useDebouncedCallback"; @@ -20,25 +20,27 @@ type Props = { export const SearchBox = (props: Props) => { const { placeholder, value, onChange, changeDebounce = 300 } = props; const [localValue, setLocalValue] = useState(value); - const onChangeDebounced = useDebouncedCallback(onChange, changeDebounce); - const handleChange = (e: Event) => { const newValue = (e.target as HTMLInputElement).value; setLocalValue(newValue); onChangeDebounced(newValue); }; - const handleClear = (e: PointerEvent) => { e.preventDefault(); e.stopPropagation(); setLocalValue(""); onChangeDebounced(""); }; - const showClear = !!localValue; + useEffect(() => { + if (localValue !== value) { + setLocalValue(value); + } + }, [value]); + return ( diff --git a/packages/web-awesome/src/i18n/locales/am.json b/packages/web-awesome/src/i18n/locales/am.json index 3939cae..e9eb0e4 100644 --- a/packages/web-awesome/src/i18n/locales/am.json +++ b/packages/web-awesome/src/i18n/locales/am.json @@ -60,7 +60,9 @@ "status-desc-short": "Հակադարձված" }, "empty": { - "no-results": "Արդյունքներ չեն գտնվել", + "no-results": "Ոչ մի արդյունք", + "no-tests-found": "Արդյունքներ չեն գտնվել", + "clear-filters": "Մաքրել ֆիլտրները", "no-attachments-results": "Կցորդների մասին տեղեկություններ չկան", "no-history-results": "Պատմության մասին տեղեկություններ չկան", "no-retries-results": "Կրկնությունների մասին տեղեկություններ չկան" diff --git a/packages/web-awesome/src/i18n/locales/az.json b/packages/web-awesome/src/i18n/locales/az.json index 9ec871e..d191677 100644 --- a/packages/web-awesome/src/i18n/locales/az.json +++ b/packages/web-awesome/src/i18n/locales/az.json @@ -61,6 +61,8 @@ }, "empty": { "no-results": "Nəticə tapılmadı", + "no-tests-found": "Nəticə tapılmadı", + "clear-filters": "Filtrləri təmizlə", "no-attachments-results": "Əlavə məlumatı mövcud deyil", "no-history-results": "Tarixçə məlumatı mövcud deyil", "no-retries-results": "Təkrar məlumatı mövcud deyil" diff --git a/packages/web-awesome/src/i18n/locales/de.json b/packages/web-awesome/src/i18n/locales/de.json index cf14426..fef6c9d 100644 --- a/packages/web-awesome/src/i18n/locales/de.json +++ b/packages/web-awesome/src/i18n/locales/de.json @@ -60,7 +60,9 @@ "status-desc-short": "Umgekehrt" }, "empty": { - "no-results": "Keine Ergebnisse gefunden", + "no-results": "Keine Ergebnisse", + "no-tests-found": "Keine Ergebnisse gefunden", + "clear-filters": "Filter löschen", "no-attachments-results": "Keine Anhängeinformationen verfügbar", "no-history-results": "Keine Verlaufsinformationen verfügbar", "no-retries-results": "Keine Wiederholungsinformationen verfügbar" diff --git a/packages/web-awesome/src/i18n/locales/en.json b/packages/web-awesome/src/i18n/locales/en.json index d34987c..cd5d57f 100644 --- a/packages/web-awesome/src/i18n/locales/en.json +++ b/packages/web-awesome/src/i18n/locales/en.json @@ -60,7 +60,9 @@ "status-desc-short": "Reversed" }, "empty": { - "no-results": "No results found", + "no-results": "No results", + "no-tests-found": "No results found", + "clear-filters": "Clear filters", "no-attachments-results": "No attachments information available", "no-history-results": "No history information available", "no-retries-results": "No retries information available" diff --git a/packages/web-awesome/src/i18n/locales/es.json b/packages/web-awesome/src/i18n/locales/es.json index 9871320..2394338 100644 --- a/packages/web-awesome/src/i18n/locales/es.json +++ b/packages/web-awesome/src/i18n/locales/es.json @@ -60,6 +60,9 @@ "status-desc-short": "Invertido" }, "empty": { + "no-results": "Sin resultados", + "no-tests-found": "No se encontraron resultados", + "clear-filters": "Limpiar filtros", "no-attachments-results": "No hay información de adjuntos disponible", "no-history-results": "No hay información de historial disponible", "no-retries-results": "No hay información de reintentos disponible" diff --git a/packages/web-awesome/src/i18n/locales/fr.json b/packages/web-awesome/src/i18n/locales/fr.json index b14880f..edbb94f 100644 --- a/packages/web-awesome/src/i18n/locales/fr.json +++ b/packages/web-awesome/src/i18n/locales/fr.json @@ -60,7 +60,9 @@ "status-desc-short": "Inversé" }, "empty": { - "no-results": "Aucun résultat trouvé", + "no-results": "Aucun résultat", + "no-tests-found": "Aucun résultat trouvé", + "clear-filters": "Effacer les filtres", "no-attachments-results": "Aucune information sur les pièces jointes disponible", "no-history-results": "Aucune information sur l'historique disponible", "no-retries-results": "Aucune information sur les réessais disponible" diff --git a/packages/web-awesome/src/i18n/locales/he.json b/packages/web-awesome/src/i18n/locales/he.json index 570ff3b..468de90 100644 --- a/packages/web-awesome/src/i18n/locales/he.json +++ b/packages/web-awesome/src/i18n/locales/he.json @@ -60,7 +60,9 @@ "status-desc-short": "הפוך" }, "empty": { - "no-results": "לא נמצאו תוצאות", + "no-results": "אין תוצאות", + "no-tests-found": "לא נמצאו תוצאות", + "clear-filters": "נקה מסננים", "no-attachments-results": "לא נמצאה מידע על קבצים מצורפים", "no-history-results": "לא נמצאה מידע על היסטוריה", "no-retries-results": "לא נמצאה מידע על נסיונות חוזרים" diff --git a/packages/web-awesome/src/i18n/locales/it.json b/packages/web-awesome/src/i18n/locales/it.json index 9fc842a..21ee6f3 100644 --- a/packages/web-awesome/src/i18n/locales/it.json +++ b/packages/web-awesome/src/i18n/locales/it.json @@ -60,7 +60,9 @@ "status-desc-short": "Invertito" }, "empty": { - "no-results": "Nessun risultato trovato", + "no-results": "Nessun risultato", + "no-tests-found": "Nessun risultato trovato", + "clear-filters": "Cancella i filtri", "no-attachments-results": "Nessuna informazione sugli allegati disponibile", "no-history-results": "Nessuna informazione sulla cronologia disponibile", "no-retries-results": "Nessuna informazione sui ritentativi disponibile" diff --git a/packages/web-awesome/src/i18n/locales/ja.json b/packages/web-awesome/src/i18n/locales/ja.json index 3f7a0b8..421b9b6 100644 --- a/packages/web-awesome/src/i18n/locales/ja.json +++ b/packages/web-awesome/src/i18n/locales/ja.json @@ -60,7 +60,9 @@ "status-desc-short": "逆順" }, "empty": { - "no-results": "結果が見つかりません", + "no-results": "結果がありません", + "no-tests-found": "結果が見つかりません", + "clear-filters": "フィルターをクリア", "no-attachments-results": "添付ファイル情報が利用できません", "no-history-results": "履歴情報が利用できません", "no-retries-results": "再試行情報が利用できません" diff --git a/packages/web-awesome/src/i18n/locales/ka.json b/packages/web-awesome/src/i18n/locales/ka.json index 38893c7..f0284ea 100644 --- a/packages/web-awesome/src/i18n/locales/ka.json +++ b/packages/web-awesome/src/i18n/locales/ka.json @@ -60,7 +60,9 @@ "status-desc-short": "შებრუნებული" }, "empty": { - "no-results": "შედეგები არ მოიძებნა", + "no-results": "შედეგები არ არის", + "no-tests-found": "შედეგები არ მოიძებნა", + "clear-filters": "ფილტრების გასუფთავება", "no-attachments-results": "დანართების ინფორმაცია არ არის ხელმისაწვდომი", "no-history-results": "ისტორიის ინფორმაცია არ არის ხელმისაწვდომი", "no-retries-results": "ხელახალი ცდების ინფორმ���ცია არ არის ხელმისაწვდომი" diff --git a/packages/web-awesome/src/i18n/locales/kr.json b/packages/web-awesome/src/i18n/locales/kr.json index b26c105..7c43a57 100644 --- a/packages/web-awesome/src/i18n/locales/kr.json +++ b/packages/web-awesome/src/i18n/locales/kr.json @@ -60,7 +60,9 @@ "status-desc-short": "역순" }, "empty": { - "no-results": "결과를 찾을 수 없습니다", + "no-results": "결과 없음", + "no-tests-found": "결과를 찾을 수 없음", + "clear-filters": "필터 지우기", "no-attachments-results": "첨부파일 정보를 사용할 수 없습니다", "no-history-results": "기록 정보를 사용할 수 없습니다", "no-retries-results": "재시도 정보를 사용할 수 없습니다" diff --git a/packages/web-awesome/src/i18n/locales/nl.json b/packages/web-awesome/src/i18n/locales/nl.json index 80b5182..4a76a3b 100644 --- a/packages/web-awesome/src/i18n/locales/nl.json +++ b/packages/web-awesome/src/i18n/locales/nl.json @@ -60,7 +60,9 @@ "status-desc-short": "Omgekeerd" }, "empty": { - "no-results": "Geen resultaten gevonden", + "no-results": "Geen resultaten", + "no-tests-found": "Geen resultaten gevonden", + "clear-filters": "Filters wissen", "no-attachments-results": "Geen bijlageninformatie beschikbaar", "no-history-results": "Geen geschiedenisinformatie beschikbaar", "no-retries-results": "Geen herhalingsinformatie beschikbaar" diff --git a/packages/web-awesome/src/i18n/locales/pl.json b/packages/web-awesome/src/i18n/locales/pl.json index a378b74..708f601 100644 --- a/packages/web-awesome/src/i18n/locales/pl.json +++ b/packages/web-awesome/src/i18n/locales/pl.json @@ -57,7 +57,9 @@ "status-desc-short": "Domyślnie" }, "empty": { - "no-results": "Nie znaleziono wyników", + "no-results": "Brak wyników", + "no-tests-found": "Nie znaleziono wyników", + "clear-filters": "Wyczyść filtry", "no-attachments-results": "Brak dostępnych informacji o załącznikach", "no-history-results": "Brak dostępnych informacji o historii", "no-retries-results": "Brak dostępnych informacji o ponownych próbach" diff --git a/packages/web-awesome/src/i18n/locales/pt.json b/packages/web-awesome/src/i18n/locales/pt.json index f124ce9..3998866 100644 --- a/packages/web-awesome/src/i18n/locales/pt.json +++ b/packages/web-awesome/src/i18n/locales/pt.json @@ -60,7 +60,9 @@ "status-desc-short": "Invertido" }, "empty": { - "no-results": "Nenhum resultado encontrado", + "no-results": "Sem resultados", + "no-tests-found": "Nenhum resultado encontrado", + "clear-filters": "Limpar filtros", "no-attachments-results": "Nenhuma informação de anexos disponível", "no-history-results": "Nenhuma informação de histórico disponível", "no-retries-results": "Nenhuma informação de repetições disponível" diff --git a/packages/web-awesome/src/i18n/locales/ru.json b/packages/web-awesome/src/i18n/locales/ru.json index 8f48dc0..3b69942 100644 --- a/packages/web-awesome/src/i18n/locales/ru.json +++ b/packages/web-awesome/src/i18n/locales/ru.json @@ -57,7 +57,9 @@ "status-desc-short": "По обычному" }, "empty": { - "no-results": "Результатов не найдено", + "no-results": "Нет результатов", + "no-tests-found": "Результаты не найдены", + "clear-filters": "Очистить фильтры", "no-attachments-results": "Информация о вложениях отсутствует", "no-history-results": "Информация об истории отсутствует", "no-retries-results": "Информация о перезапусках отсутствует" diff --git a/packages/web-awesome/src/i18n/locales/sv.json b/packages/web-awesome/src/i18n/locales/sv.json index abf5683..1aebcfe 100644 --- a/packages/web-awesome/src/i18n/locales/sv.json +++ b/packages/web-awesome/src/i18n/locales/sv.json @@ -60,7 +60,9 @@ "status-desc-short": "Omvänd" }, "empty": { - "no-results": "Inga resultat hittades", + "no-results": "Inga resultat", + "no-tests-found": "Inga resultat hittades", + "clear-filters": "Rensa filter", "no-attachments-results": "Ingen bilaga information tillgänglig", "no-history-results": "Ingen historik information tillgänglig", "no-retries-results": "Ingen omtagningar information tillgänglig" diff --git a/packages/web-awesome/src/i18n/locales/tr.json b/packages/web-awesome/src/i18n/locales/tr.json index 93d6410..42dbea0 100644 --- a/packages/web-awesome/src/i18n/locales/tr.json +++ b/packages/web-awesome/src/i18n/locales/tr.json @@ -60,7 +60,9 @@ "status-desc-short": "Ters" }, "empty": { - "no-results": "Sonuç bulunamadı", + "no-results": "Sonuç yok", + "no-tests-found": "Sonuç bulunamadı", + "clear-filters": "Filtreleri temizle", "no-attachments-results": "Ek bilgisi mevcut değil", "no-history-results": "Geçmiş bilgisi mevcut değil", "no-retries-results": "Tekrar deneme bilgisi mevcut değil" diff --git a/packages/web-awesome/src/i18n/locales/zh.json b/packages/web-awesome/src/i18n/locales/zh.json index 45ac155..7e0b8f4 100644 --- a/packages/web-awesome/src/i18n/locales/zh.json +++ b/packages/web-awesome/src/i18n/locales/zh.json @@ -60,7 +60,9 @@ "status-desc-short": "反转" }, "empty": { - "no-results": "未找到结果", + "no-results": "没有结果", + "no-tests-found": "未找到结果", + "clear-filters": "清除过滤器", "no-attachments-results": "没有附件信息", "no-history-results": "没有历史信息", "no-retries-results": "没有重试信息" diff --git a/packages/web-awesome/src/stores/tree.ts b/packages/web-awesome/src/stores/tree.ts index 37f1e6b..a66590e 100644 --- a/packages/web-awesome/src/stores/tree.ts +++ b/packages/web-awesome/src/stores/tree.ts @@ -1,7 +1,7 @@ import { fetchReportJsonData } from "@allurereport/web-commons"; import { computed, signal } from "@preact/signals"; import type { StoreSignalState } from "@/stores/types"; -import { fillTree } from "@/utils/treeFilters"; +import { fillTree, isFilledTreeEmpty } from "@/utils/treeFilters"; import type { AllureAwesomeStatus } from "../../types"; export type TreeSortBy = "order" | "duration" | "status" | "alphabet"; @@ -21,6 +21,8 @@ export const treeStore = signal>({ data: undefined, }); +export const noTests = computed(() => !Object.keys(treeStore?.value?.data?.leavesById).length); + export const treeFiltersStore = signal({ query: "", status: "total", @@ -33,6 +35,35 @@ export const treeFiltersStore = signal({ direction: "asc", }); +export const filteredTree = computed(() => { + const { root, leavesById, groupsById } = treeStore.value.data; + + return fillTree({ + group: root, + leavesById, + groupsById, + filterOptions: treeFiltersStore.value, + }); +}); + +export const noTestsFound = computed(() => { + return isFilledTreeEmpty(filteredTree.value); +}); + +export const clearTreeFilters = () => { + treeFiltersStore.value = { + query: "", + status: "total", + filter: { + flaky: false, + retry: false, + new: false, + }, + sortBy: "order", + direction: "asc", + }; +}; + export const setTreeQuery = (query: string) => { treeFiltersStore.value = { ...treeFiltersStore.value, @@ -71,17 +102,6 @@ export const setTreeFilter = (filterKey: TreeFilters, value: boolean) => { }; }; -export const filteredTree = computed(() => { - const { root, leavesById, groupsById } = treeStore.value.data; - - return fillTree({ - group: root, - leavesById, - groupsById, - filterOptions: treeFiltersStore.value, - }); -}); - export const fetchTreeData = async (treeName: string) => { treeStore.value = { ...treeStore.value, diff --git a/packages/web-awesome/src/utils/treeFilters.ts b/packages/web-awesome/src/utils/treeFilters.ts index 7a25acd..721ad29 100644 --- a/packages/web-awesome/src/utils/treeFilters.ts +++ b/packages/web-awesome/src/utils/treeFilters.ts @@ -1,11 +1,5 @@ -import { compareBy, nullsLast, ordinal, reverse } from "@allurereport/core-api"; import type { TreeFiltersState } from "@/stores/tree"; -import type { - AllureAwesomeOrderedTree, - AllureAwesomeTree, - AllureAwesomeTreeGroup, - AllureAwesomeTreeLeaf, -} from "../../types"; +import type { AllureAwesomeOrderedTree, AllureAwesomeTree, AllureAwesomeTreeGroup } from "../../types"; const statusOrder = { failed: 1, @@ -87,3 +81,15 @@ export const fillTree = (payload: { ), }; }; + +export const isFilledTreeEmpty = (tree: AllureAwesomeTreeGroup) => { + if (!tree.groups?.length && !tree.leaves?.length) { + return true; + } + + if (tree.leaves?.length) { + return false; + } + + return tree.groups?.every((group) => isFilledTreeEmpty(group)); +};