diff --git a/src/views/dashboard/related/trace/Content.vue b/src/views/dashboard/related/trace/Content.vue index 072fd45e..4972db85 100644 --- a/src/views/dashboard/related/trace/Content.vue +++ b/src/views/dashboard/related/trace/Content.vue @@ -16,7 +16,15 @@ limitations under the License. --> @@ -48,6 +56,7 @@ limitations under the License. --> import type { LayoutConfig } from "@/types/dashboard"; import { mutationObserver } from "@/utils/mutation"; import TraceQuery from "./components/TraceQuery/Index.vue"; + import { QueryOrders } from "@/views/dashboard/data"; /*global defineProps */ const props = defineProps({ data: { @@ -64,6 +73,7 @@ limitations under the License. --> const currentWidth = ref(280); const needQuery = ref(true); const isDrag = ref(false); + const queryOrder = ref(QueryOrders[0].value); const limit = ref(PageSize); const defaultWidth = 280; const minArrowLeftWidth = 120; @@ -77,7 +87,11 @@ limitations under the License. --> paging: { pageNum: 1, pageSize: val }, }); } - + function changeQueryOrder() { + traceStore.setTraceCondition({ + queryOrder: queryOrder.value, + }); + } // When click the arrow, the width of the segment list is determined by the direction it points to. function triggerArrow() { currentWidth.value = isLeft.value ? 0 : defaultWidth; diff --git a/src/views/dashboard/related/trace/components/TraceQuery/TracesTable.vue b/src/views/dashboard/related/trace/components/TraceQuery/TracesTable.vue index 2d21326c..0c717f1f 100644 --- a/src/views/dashboard/related/trace/components/TraceQuery/TracesTable.vue +++ b/src/views/dashboard/related/trace/components/TraceQuery/TracesTable.vue @@ -16,14 +16,7 @@ limitations under the License. -->
{{ filteredTraces.length }} of {{ totalTraces }} Results
- + :default-sort="{ prop: 'duration', order: 'descending' }" style="width: 100%" v-loading="traceStore.loading" + @sort-change="handleSortChange" > - + @@ -137,6 +131,9 @@ limitations under the License. --> const loading = ref(false); const loadMoreThreshold = 100; // pixels from bottom to trigger load + // Sort state for infinite scroll + const currentSort = ref<{ prop: string; order: string } | null>({ prop: "duration", order: "descending" }); + // Calculate max duration for progress bar scaling const maxDuration = computed(() => { if (!traceStore.traceList.length) return 1; @@ -161,7 +158,26 @@ limitations under the License. --> }); const filteredTraces = computed(() => { - return allFilteredTraces.value.slice(0, loadedItemsCount.value); + let sortedTraces = [...allFilteredTraces.value]; + + // Apply sorting if there's a current sort + if (currentSort.value) { + sortedTraces.sort((a, b) => { + const { prop, order } = currentSort.value!; + + if (prop === "start") { + const result = sortByStartTime(a, b); + return order === "ascending" ? result : -result; + } else if (prop === "duration") { + const result = a.duration - b.duration; + return order === "ascending" ? result : -result; + } + + return 0; + }); + } + + return sortedTraces.slice(0, loadedItemsCount.value); }); const totalTraces = computed(() => allFilteredTraces.value.length); @@ -208,6 +224,47 @@ limitations under the License. --> return Math.round((duration / maxDuration.value) * 100); } + function sortByStartTime(a: Trace, b: Trace): number { + // Convert start time strings to Date objects for comparison + const dateA = new Date(a.start); + const dateB = new Date(b.start); + + // Handle invalid dates + if (isNaN(dateA.getTime()) && isNaN(dateB.getTime())) return 0; + if (isNaN(dateA.getTime())) return 1; + if (isNaN(dateB.getTime())) return -1; + + return dateA.getTime() - dateB.getTime(); + } + + function applyExpandState() { + nextTick(() => { + if (tableRef.value) { + const visibleItems = filteredTraces.value; + for (const row of visibleItems) { + tableRef.value.toggleRowExpansion(row, expandAll.value); + } + } + }); + } + + function handleSortChange(sortInfo: { prop: string; order: string | null }) { + if (sortInfo.order) { + currentSort.value = { + prop: sortInfo.prop, + order: sortInfo.order, + }; + } else { + currentSort.value = null; + } + + // Reset loaded items count when sort changes + loadedItemsCount.value = PageSize; + + // Preserve expand state when sorting changes + applyExpandState(); + } + function toggleServiceTags(serviceName: string, row: Trace) { selectedServiceNames.value = selectedServiceNames.value.includes(serviceName) ? selectedServiceNames.value.filter((name) => name !== serviceName) @@ -224,7 +281,6 @@ limitations under the License. --> function changeServiceFilters(selected: Option[]) { selectedServiceNames.value = selected.map((o) => String(o.value)); } - // Infinite scroll handlers function loadMoreItems() { if (loading.value || !hasMoreItems.value) return; @@ -235,17 +291,7 @@ limitations under the License. --> setTimeout(() => { const nextBatch = Math.min(PageSize, allFilteredTraces.value.length - loadedItemsCount.value); loadedItemsCount.value += nextBatch; - - // Apply current expand state to all currently visible items - nextTick(() => { - if (tableRef.value) { - const allVisibleItems = filteredTraces.value; - for (const row of allVisibleItems) { - tableRef.value.toggleRowExpansion(row, expandAll.value); - } - } - }); - + applyExpandState(); loading.value = false; }, 300); } @@ -265,25 +311,13 @@ limitations under the License. --> loadedItemsCount.value = PageSize; // Apply expand state to newly visible items after filter change nextTick(() => { - if (tableRef.value) { - const visibleItems = filteredTraces.value; - for (const row of visibleItems) { - tableRef.value.toggleRowExpansion(row, expandAll.value); - } - } + applyExpandState(); }); }); // Watch for expandAll state changes to apply to all visible items watch(expandAll, () => { - nextTick(() => { - if (tableRef.value) { - const visibleItems = filteredTraces.value; - for (const row of visibleItems) { - tableRef.value.toggleRowExpansion(row, expandAll.value); - } - } - }); + applyExpandState(); }); // Watch for trace list changes (when new query is executed) to reapply expand state @@ -294,14 +328,7 @@ limitations under the License. --> loadedItemsCount.value = PageSize; // Reapply expand state to newly loaded traces - nextTick(() => { - if (tableRef.value) { - const visibleItems = filteredTraces.value; - for (const row of visibleItems) { - tableRef.value.toggleRowExpansion(row, expandAll.value); - } - } - }); + applyExpandState(); }, { deep: true }, ); @@ -320,12 +347,6 @@ limitations under the License. --> tableContainer.removeEventListener("scroll", handleScroll); } }); - - // Toggle all table row expansions (only for loaded items) - function toggleAllExpansion() { - // The expandAll watcher will handle applying the state to all visible items - // This function just needs to trigger the change - }