diff --git a/apps/desktop/src/components/grid/DataGrid.vue b/apps/desktop/src/components/grid/DataGrid.vue index 9813f65c33..511817496d 100644 --- a/apps/desktop/src/components/grid/DataGrid.vue +++ b/apps/desktop/src/components/grid/DataGrid.vue @@ -136,7 +136,7 @@ import { useSqlHighlighter } from "@/composables/useSqlHighlighter"; import { useCellDetailEditor, type UseCellDetailEditorReturn } from "@/composables/useCellDetailEditor"; import { useTheme } from "@/composables/useTheme"; import { useSettingsStore } from "@/stores/settingsStore"; -import { nextDataGridSortState, type DataGridSortDirection } from "@/lib/dataGridSort"; +import type { DataGridSortDirection } from "@/lib/dataGridSort"; import { getTableMetadataCapabilities } from "@/lib/tableMetadataCapabilities"; import { forgetDataGridConditionHistory, loadDataGridConditionHistory, rememberDataGridConditionHistory } from "@/lib/dataGridConditionHistory"; @@ -167,6 +167,8 @@ type ConditionSuggestion = { kind: "column" | "history"; }; +type SortMenuValue = "asc" | "desc" | "clear"; + const props = defineProps<{ result: QueryResult; sql?: string; @@ -349,6 +351,38 @@ function headerColumnSortable(actualColIdx: number): boolean { return resolved !== undefined ? resolved : true; } +function columnIsSorted(column: string, columnIndex: number): boolean { + return sortCol.value === column && sortColIndex.value === columnIndex; +} + +function sortMenuItems(column: string, columnIndex: number) { + return [ + { + label: t("grid.sortAscending"), + value: "asc", + icon: ArrowUp, + checked: columnIsSorted(column, columnIndex) && sortDir.value === "asc", + }, + { + label: t("grid.sortDescending"), + value: "desc", + icon: ArrowDown, + checked: columnIsSorted(column, columnIndex) && sortDir.value === "desc", + }, + { + label: t("grid.clearSort"), + value: "clear", + icon: ArrowUpDown, + disabled: !columnIsSorted(column, columnIndex), + separatorBefore: true, + }, + ]; +} + +function selectedSortMenuValue(column: string, columnIndex: number): SortMenuValue | undefined { + return columnIsSorted(column, columnIndex) ? sortDir.value : undefined; +} + function typeColorClass(t: string): string { // Strip precision/scale suffix like (20,6) const base = t.replace(/\(.*\)$/, "").toLowerCase(); @@ -476,6 +510,7 @@ type StructuredFilterRule = { const localColumnFilters = ref>>({}); const localFilterOpenColumn = ref(null); const headerActionMenuOpenColumn = ref(null); +const headerSortMenuOpenColumn = ref(null); const headerPanelDismissGuardUntil = ref(0); const localFilterSearch = ref(""); const localFilterDraft = ref(null); @@ -3485,23 +3520,10 @@ function setDetailNull() { detailCell.value = { ...detailCell.value! }; } -function toggleSort(colName: string, colIdx: number) { +function applyColumnSort(column: string, columnIndex: number, direction: "asc" | "desc" | null) { if (getIsResizing()) return; currentPage.value = 1; resetGridVerticalScroll(true); - const next = nextDataGridSortState({ column: sortCol.value, columnIndex: sortColIndex.value, direction: sortDir.value }, colName, colIdx); - sortCol.value = next.column; - sortColIndex.value = next.columnIndex; - sortDir.value = next.direction; - syncOrderByInputWithSort(next.column, next.column ? next.direction : null); - emit("sort", colName, colIdx, next.column ? next.direction : null, currentWhereInput()); -} - -function applyContextSort(direction: "asc" | "desc" | null) { - if (!contextColumn.value || !contextCell.value) return; - const column = contextColumn.value; - const columnIndex = contextCell.value.col; - currentPage.value = 1; if (direction) { sortCol.value = column; sortColIndex.value = columnIndex; @@ -3516,6 +3538,15 @@ function applyContextSort(direction: "asc" | "desc" | null) { emit("sort", column, columnIndex, direction, currentWhereInput()); } +function selectHeaderSort(value: string, column: string, columnIndex: number) { + applyColumnSort(column, columnIndex, value === "clear" ? null : (value as DataGridSortDirection)); +} + +function applyContextSort(direction: "asc" | "desc" | null) { + if (!contextColumn.value || !contextCell.value) return; + applyColumnSort(contextColumn.value, contextCell.value.col, direction); +} + async function contextFilterCondition(mode: FilterMode): Promise { if (!contextColumn.value) return null; return ( @@ -6808,18 +6839,35 @@ const gridContextMenuItems = computed(() => { {{ headerColumnComment(col.name) }} - + +