diff --git a/frontend/src/components/__tests__/datasets/ParquetViewer.spec.js b/frontend/src/components/__tests__/datasets/ParquetViewer.spec.js index b0a32f35a..7dd25f9ea 100644 --- a/frontend/src/components/__tests__/datasets/ParquetViewer.spec.js +++ b/frontend/src/components/__tests__/datasets/ParquetViewer.spec.js @@ -96,4 +96,21 @@ describe("ParquetViewer", () => { await flushPromises(); expect(wrapper.vm.split).toBe("train"); }); + + it("renders column headers with formatted column type badges", async () => { + await flushPromises(); + const headerText = wrapper.find('.el-table__header-wrapper').text(); + expect(headerText).toContain("id"); + expect(headerText).toContain("int"); + expect(headerText).toContain("text"); + expect(headerText).toContain("str"); + expect(headerText).toContain("label"); + }); + + it("sorts numeric columns numerically instead of lexicographically", () => { + const sortFn = wrapper.vm.getSortMethod("id", 0); + expect(sortFn({ id: "2" }, { id: "10" })).toBeLessThan(0); + expect(sortFn({ id: "10" }, { id: "2" })).toBeGreaterThan(0); + expect(sortFn({ id: "2" }, { id: "2" })).toBe(0); + }); }); diff --git a/frontend/src/components/datasets/ParquetViewer.vue b/frontend/src/components/datasets/ParquetViewer.vue index 594dbb148..cb8d7229e 100644 --- a/frontend/src/components/datasets/ParquetViewer.vue +++ b/frontend/src/components/datasets/ParquetViewer.vue @@ -98,11 +98,22 @@ class="w-full rounded-md mb-4" row-class-name="row-item-clamp cursor-pointer" cell-class-name="!align-top"> - + sortable + :sort-method="getSortMethod(column, idx)" + min-width="180"> + + + {{ column }} + + {{ formatColumnType(getColumnType(idx)) }} + + + + { + return previewData.value?.columns_type?.[index] || '' + } + + const formatColumnType = (type) => { + if (!type) return '' + const lower = type.toLowerCase() + if (lower === 'string') return 'str' + if (lower.includes('int')) return lower + if (lower.includes('float')) return 'float' + if (lower.includes('bool')) return 'bool' + if (lower.includes('list') || lower.includes('array')) return 'list' + if (lower.includes('dict') || lower.includes('struct')) return 'dict' + return type + } + + const getSortMethod = (column, index) => { + const colType = getColumnType(index) + const lower = (colType || '').toLowerCase() + const isNumeric = lower.includes('int') || lower.includes('float') || lower.includes('number') + + return (a, b) => { + const valA = a[column] + const valB = b[column] + if (valA === valB) return 0 + if (valA === undefined || valA === null) return -1 + if (valB === undefined || valB === null) return 1 + + if (isNumeric) { + const numA = Number(valA) + const numB = Number(valB) + if (!isNaN(numA) && !isNaN(numB)) { + return numA - numB + } + } + return String(valA).localeCompare(String(valB)) + } + } + const showRows = computed(() => { let result = '' if (Rows.value >= 1000000) {