feat(grid): add current page sorting
This commit is contained in:
1 parent
9621f277bf
commit
829f6dc7eb
17 files changed
+337
-39
No files matched your search
@@ -60,6 +60,7 @@ import {
|
||||
PanelBottom,
|
||||
PanelRight,
|
||||
TableProperties,
|
||||
Database,
|
||||
} from "@lucide/vue";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import QueryLoadingState from "@/components/common/QueryLoadingState.vue";
|
||||
@@ -139,7 +140,7 @@ import { useCellDetailEditor, type UseCellDetailEditorReturn } from "@/composabl
|
||||
import { useTheme } from "@/composables/useTheme";
|
||||
import { useConnectionStore } from "@/stores/connectionStore";
|
||||
import { useSettingsStore } from "@/stores/settingsStore";
|
||||
import type { DataGridSortDirection } from "@/lib/dataGridSort";
|
||||
import type { DataGridSortDirection, DataGridSortMode } from "@/lib/dataGridSort";
|
||||
import { getTableMetadataCapabilities } from "@/lib/tableMetadataCapabilities";
|
||||
import { forgetDataGridConditionHistory, loadDataGridConditionHistory, rememberDataGridConditionHistory } from "@/lib/dataGridConditionHistory";
|
||||
import { caretPositionInsideInsertedSqlSingleQuotes, insertedSqlSingleQuoteAtCaret } from "@/lib/sqlQuoteCaret";
|
||||
@@ -173,7 +174,7 @@ type ConditionSuggestion = {
|
||||
kind: "column" | "history";
|
||||
};
|
||||
|
||||
type SortMenuValue = "asc" | "desc" | "clear";
|
||||
type SortMenuValue = "local-asc" | "local-desc" | "database-asc" | "database-desc" | "clear";
|
||||
|
||||
const props = defineProps<{
|
||||
result: QueryResult;
|
||||
@@ -190,6 +191,7 @@ const props = defineProps<{
|
||||
sortColumn?: string;
|
||||
sortColumnIndex?: number;
|
||||
sortDirection?: DataGridSortDirection;
|
||||
sortMode?: DataGridSortMode;
|
||||
tableMeta?: {
|
||||
schema?: string;
|
||||
tableName: string;
|
||||
@@ -217,7 +219,7 @@ const dataGridElapsed = () => `${Math.round(performance.now() - dataGridCreatedA
|
||||
const emit = defineEmits<{
|
||||
reload: [sql?: string, searchText?: string, whereInput?: string, orderBy?: string, limit?: number, offset?: number];
|
||||
paginate: [offset: number, limit: number, whereInput?: string, orderBy?: string];
|
||||
sort: [column: string, columnIndex: number, direction: "asc" | "desc" | null, whereInput?: string];
|
||||
sort: [column: string, columnIndex: number, direction: "asc" | "desc" | null, whereInput?: string, mode?: DataGridSortMode];
|
||||
"update:whereInput": [value: string];
|
||||
"update:orderByInput": [value: string];
|
||||
}>();
|
||||
@@ -354,16 +356,29 @@ function columnIsSorted(column: string, columnIndex: number): boolean {
|
||||
function sortMenuItems(column: string, columnIndex: number) {
|
||||
return [
|
||||
{
|
||||
label: t("grid.sortAscending"),
|
||||
value: "asc",
|
||||
label: t("grid.sortCurrentPageAscending"),
|
||||
value: "local-asc",
|
||||
icon: ArrowUp,
|
||||
checked: columnIsSorted(column, columnIndex) && sortDir.value === "asc",
|
||||
checked: columnIsSorted(column, columnIndex) && sortDir.value === "asc" && sortMode.value === "local",
|
||||
},
|
||||
{
|
||||
label: t("grid.sortDescending"),
|
||||
value: "desc",
|
||||
label: t("grid.sortCurrentPageDescending"),
|
||||
value: "local-desc",
|
||||
icon: ArrowDown,
|
||||
checked: columnIsSorted(column, columnIndex) && sortDir.value === "desc",
|
||||
checked: columnIsSorted(column, columnIndex) && sortDir.value === "desc" && sortMode.value === "local",
|
||||
},
|
||||
{
|
||||
label: t("grid.sortDatabaseAscending"),
|
||||
value: "database-asc",
|
||||
icon: Database,
|
||||
checked: columnIsSorted(column, columnIndex) && sortDir.value === "asc" && sortMode.value === "database",
|
||||
separatorBefore: true,
|
||||
},
|
||||
{
|
||||
label: t("grid.sortDatabaseDescending"),
|
||||
value: "database-desc",
|
||||
icon: Database,
|
||||
checked: columnIsSorted(column, columnIndex) && sortDir.value === "desc" && sortMode.value === "database",
|
||||
},
|
||||
{
|
||||
label: t("grid.clearSort"),
|
||||
@@ -376,7 +391,7 @@ function sortMenuItems(column: string, columnIndex: number) {
|
||||
}
|
||||
|
||||
function selectedSortMenuValue(column: string, columnIndex: number): SortMenuValue | undefined {
|
||||
return columnIsSorted(column, columnIndex) ? sortDir.value : undefined;
|
||||
return columnIsSorted(column, columnIndex) ? (`${sortMode.value}-${sortDir.value}` as SortMenuValue) : undefined;
|
||||
}
|
||||
|
||||
function typeColorClass(t: string): string {
|
||||
@@ -429,6 +444,7 @@ const transposeViewportWidth = ref(0);
|
||||
const sortCol = ref<string | null>(null);
|
||||
const sortColIndex = ref<number | null>(null);
|
||||
const sortDir = ref<DataGridSortDirection>("asc");
|
||||
const sortMode = ref<DataGridSortMode>("database");
|
||||
const searchText = ref("");
|
||||
const deferredClientSearchText = ref("");
|
||||
const searchOverlayVisible = ref(false);
|
||||
@@ -2454,14 +2470,15 @@ function syncOrderByInputWithSort(column: string | null, direction: "asc" | "des
|
||||
}
|
||||
|
||||
watch(
|
||||
() => [props.sortColumn, props.sortColumnIndex, props.sortDirection] as const,
|
||||
([column, columnIndex, direction], previous) => {
|
||||
() => [props.sortColumn, props.sortColumnIndex, props.sortDirection, props.sortMode] as const,
|
||||
([column, columnIndex, direction, mode], previous) => {
|
||||
const wasControlledSort = !!previous?.[0] && !!previous?.[2];
|
||||
const isControlledSort = !!column && !!direction;
|
||||
sortCol.value = column && direction ? column : null;
|
||||
sortColIndex.value = typeof columnIndex === "number" && direction ? columnIndex : null;
|
||||
sortDir.value = direction ?? "asc";
|
||||
if (isControlledSort) {
|
||||
sortMode.value = mode ?? "database";
|
||||
if (isControlledSort && sortMode.value === "database") {
|
||||
syncOrderByInputWithSort(sortCol.value, sortDir.value);
|
||||
} else if (wasControlledSort) {
|
||||
syncOrderByInputWithSort(null, null);
|
||||
@@ -3740,7 +3757,7 @@ function setDetailNull() {
|
||||
detailCell.value = { ...detailCell.value! };
|
||||
}
|
||||
|
||||
function applyColumnSort(column: string, columnIndex: number, direction: "asc" | "desc" | null) {
|
||||
function applyColumnSort(column: string, columnIndex: number, direction: "asc" | "desc" | null, mode: DataGridSortMode = "database") {
|
||||
if (getIsResizing()) return;
|
||||
currentPage.value = 1;
|
||||
resetGridVerticalScroll(true);
|
||||
@@ -3748,23 +3765,34 @@ function applyColumnSort(column: string, columnIndex: number, direction: "asc" |
|
||||
sortCol.value = column;
|
||||
sortColIndex.value = columnIndex;
|
||||
sortDir.value = direction;
|
||||
syncOrderByInputWithSort(column, direction);
|
||||
sortMode.value = mode;
|
||||
if (mode === "database") {
|
||||
syncOrderByInputWithSort(column, direction);
|
||||
} else {
|
||||
syncOrderByInputWithSort(null, null);
|
||||
}
|
||||
} else {
|
||||
sortCol.value = null;
|
||||
sortColIndex.value = null;
|
||||
sortDir.value = "asc";
|
||||
sortMode.value = "database";
|
||||
syncOrderByInputWithSort(null, null);
|
||||
}
|
||||
emit("sort", column, columnIndex, direction, currentWhereInput());
|
||||
emit("sort", column, columnIndex, direction, currentWhereInput(), mode);
|
||||
}
|
||||
|
||||
function selectHeaderSort(value: string, column: string, columnIndex: number) {
|
||||
applyColumnSort(column, columnIndex, value === "clear" ? null : (value as DataGridSortDirection));
|
||||
if (value === "clear") {
|
||||
applyColumnSort(column, columnIndex, null, sortMode.value);
|
||||
return;
|
||||
}
|
||||
const [mode, direction] = value.split("-") as [DataGridSortMode, DataGridSortDirection];
|
||||
applyColumnSort(column, columnIndex, direction, mode);
|
||||
}
|
||||
|
||||
function applyContextSort(direction: "asc" | "desc" | null) {
|
||||
function applyContextSort(direction: "asc" | "desc" | null, mode: DataGridSortMode = "database") {
|
||||
if (!contextColumn.value || !contextCell.value) return;
|
||||
applyColumnSort(contextColumn.value, contextCell.value.col, direction);
|
||||
applyColumnSort(contextColumn.value, contextCell.value.col, direction, mode);
|
||||
}
|
||||
|
||||
async function contextFilterCondition(mode: FilterMode): Promise<string | null> {
|
||||
@@ -6366,9 +6394,15 @@ const gridContextMenuItems = computed<ContextMenuItem[]>(() => {
|
||||
|
||||
// 2. Column sort & filter
|
||||
if (contextColumn.value) {
|
||||
items.push({ label: t("grid.sortAscending"), action: () => applyContextSort("asc"), icon: ArrowUp }, { label: t("grid.sortDescending"), action: () => applyContextSort("desc"), icon: ArrowDown });
|
||||
items.push(
|
||||
{ label: t("grid.sortCurrentPageAscending"), action: () => applyContextSort("asc", "local"), icon: ArrowUp },
|
||||
{ label: t("grid.sortCurrentPageDescending"), action: () => applyContextSort("desc", "local"), icon: ArrowDown },
|
||||
{ label: "", separator: true },
|
||||
{ label: t("grid.sortDatabaseAscending"), action: () => applyContextSort("asc", "database"), icon: Database },
|
||||
{ label: t("grid.sortDatabaseDescending"), action: () => applyContextSort("desc", "database"), icon: Database },
|
||||
);
|
||||
if (sortCol.value) {
|
||||
items.push({ label: t("grid.clearSort"), action: () => applyContextSort(null), icon: ArrowUpDown });
|
||||
items.push({ label: t("grid.clearSort"), action: () => applyContextSort(null, sortMode.value), icon: ArrowUpDown });
|
||||
}
|
||||
if (canUseWhereSearch.value) {
|
||||
items.push({ label: "", separator: true });
|
||||
|
||||
@@ -58,6 +58,7 @@ import { formatShortcut } from "@/lib/shortcutRegistry";
|
||||
import { effectiveDatabaseTypeForConnection } from "@/lib/jdbcDialect";
|
||||
import { chartableColumnIndexes } from "@/lib/chartData";
|
||||
import type { SqlExecutionOverride } from "@/lib/sqlExecutionTarget";
|
||||
import type { DataGridSortMode } from "@/lib/dataGridSort";
|
||||
import { useTabScroll } from "@/composables/useTabScroll";
|
||||
import type { QueryTab, ConnectionConfig, TableInfoTab } from "@/types/database";
|
||||
import type { SqlFormatDialect } from "@/lib/sqlFormatter";
|
||||
@@ -119,7 +120,7 @@ const emit = defineEmits<{
|
||||
formatError: [];
|
||||
reload: [sql?: string, searchText?: string, whereInput?: string, orderBy?: string, limit?: number, offset?: number];
|
||||
paginate: [offset: number, limit: number, whereInput?: string, orderBy?: string];
|
||||
sort: [column: string, columnIndex: number, direction: "asc" | "desc" | null, whereInput?: string];
|
||||
sort: [column: string, columnIndex: number, direction: "asc" | "desc" | null, whereInput?: string, mode?: DataGridSortMode];
|
||||
executeSql: [sql: string];
|
||||
clickTable: [tableName: string];
|
||||
viewTableData: [tableName: string];
|
||||
@@ -764,6 +765,7 @@ defineExpose({ focusSearch, refreshData, handleModRTarget, requestQueryEditorExe
|
||||
:sort-column="activeTab.resultSortColumn"
|
||||
:sort-column-index="activeTab.resultSortColumnIndex"
|
||||
:sort-direction="activeTab.resultSortDirection"
|
||||
:sort-mode="activeTab.resultSortMode"
|
||||
:initial-order-by-input="activeTab.orderByInput"
|
||||
:sql="activeTab.lastExecutedSql || activeTab.sql"
|
||||
:loading="activeTab.isExecuting"
|
||||
@@ -787,7 +789,7 @@ defineExpose({ focusSearch, refreshData, handleModRTarget, requestQueryEditorExe
|
||||
@update:order-by-input="(v: string) => (activeTab.orderByInput = v)"
|
||||
@reload="(sql?: string, searchText?: string, whereInput?: string, orderBy?: string, limit?: number, offset?: number) => emit('reload', sql, searchText, whereInput, orderBy, limit, offset)"
|
||||
@paginate="(offset: number, limit: number, whereInput?: string, orderBy?: string) => emit('paginate', offset, limit, whereInput, orderBy)"
|
||||
@sort="(column: string, columnIndex: number, direction: 'asc' | 'desc' | null, whereInput?: string) => emit('sort', column, columnIndex, direction, whereInput)"
|
||||
@sort="(column: string, columnIndex: number, direction: 'asc' | 'desc' | null, whereInput?: string, mode?: DataGridSortMode) => emit('sort', column, columnIndex, direction, whereInput, mode)"
|
||||
>
|
||||
<template v-if="activeTab.result?.columns.includes('Error')" #error-actions="{ errorMessage }">
|
||||
<Button variant="outline" size="sm" class="h-7 gap-1.5 px-2.5 text-xs" @click="emit('fixWithAi', String(errorMessage))">
|
||||
@@ -959,6 +961,7 @@ defineExpose({ focusSearch, refreshData, handleModRTarget, requestQueryEditorExe
|
||||
:sort-column="activeTab.resultSortColumn"
|
||||
:sort-column-index="activeTab.resultSortColumnIndex"
|
||||
:sort-direction="activeTab.resultSortDirection"
|
||||
:sort-mode="activeTab.resultSortMode"
|
||||
:initial-order-by-input="activeTab.orderByInput"
|
||||
:sql="activeTab.sql"
|
||||
:loading="activeTab.isExecuting"
|
||||
@@ -978,7 +981,7 @@ defineExpose({ focusSearch, refreshData, handleModRTarget, requestQueryEditorExe
|
||||
@update:order-by-input="(v: string) => (activeTab.orderByInput = v)"
|
||||
@reload="(sql?: string, searchText?: string, whereInput?: string, orderBy?: string, limit?: number, offset?: number) => emit('reload', sql, searchText, whereInput, orderBy, limit, offset)"
|
||||
@paginate="(offset: number, limit: number, whereInput?: string, orderBy?: string) => emit('paginate', offset, limit, whereInput, orderBy)"
|
||||
@sort="(column: string, columnIndex: number, direction: 'asc' | 'desc' | null, whereInput?: string) => emit('sort', column, columnIndex, direction, whereInput)"
|
||||
@sort="(column: string, columnIndex: number, direction: 'asc' | 'desc' | null, whereInput?: string, mode?: DataGridSortMode) => emit('sort', column, columnIndex, direction, whereInput, mode)"
|
||||
/>
|
||||
<QueryLoadingState v-else-if="activeTab.isExecuting" class="h-full" :label-key="queryExecutionLabelKey(activeTab)" :elapsed-seconds="queryRunningElapsedSeconds" show-cancel :cancel-disabled="!canCancelQueryExecution(activeTab)" :cancelling="activeTab.isCancelling" @cancel="emit('cancel')" />
|
||||
<div v-else class="h-full flex flex-col items-center justify-center gap-3 text-muted-foreground text-sm">
|
||||
|
||||
@@ -897,6 +897,8 @@ async function openData() {
|
||||
existing.resultSortColumn = undefined;
|
||||
existing.resultSortColumnIndex = undefined;
|
||||
existing.resultSortDirection = undefined;
|
||||
existing.resultSortMode = undefined;
|
||||
existing.resultLocalSortOriginalRows = undefined;
|
||||
existing.resultSortedSql = undefined;
|
||||
queryStore.activeTabId = existing.id;
|
||||
return existing.id;
|
||||
|
||||
Reference in new issue
Block a user