feat(grid): add configurable table search mode
This commit is contained in:
1 parent
4f8fb1068d
commit
d8047a77b4
6 files changed
+108
-25
No files matched your search
@@ -341,6 +341,7 @@ const showColumnCommentsInHeader = computed(() => settingsStore.editorSettings.s
|
||||
const showColumnTypesInHeader = computed(() => settingsStore.editorSettings.showColumnTypesInHeader);
|
||||
const compactColumnHeaderActions = computed(() => settingsStore.editorSettings.compactColumnHeaderActions);
|
||||
const dataGridRenderMode = computed(() => settingsStore.editorSettings.dataGridRenderMode);
|
||||
const dataGridSearchMode = computed(() => settingsStore.editorSettings.dataGridSearchMode);
|
||||
const compactDataGridToolbar = computed(() => dataGridTopbarWidth.value > 0 && dataGridTopbarWidth.value < DATA_GRID_COMPACT_TOPBAR_WIDTH);
|
||||
const infiniteScrollEnabled = computed(() => settingsStore.editorSettings.infiniteScroll);
|
||||
const infiniteScrollMaxRows = computed(() => settingsStore.editorSettings.infiniteScrollMaxRows);
|
||||
@@ -3926,7 +3927,8 @@ function addRow() {
|
||||
const sortedRows = computed(() => {
|
||||
let indices = localFilteredRows.value;
|
||||
const q = deferredClientSearchText.value;
|
||||
if (q) {
|
||||
if (q && dataGridSearchMode.value === "filter") {
|
||||
// Preserve the legacy Ctrl+F behavior when the user chooses row filtering.
|
||||
const rows = props.result.rows;
|
||||
indices = indices.filter((sourceIndex) => {
|
||||
const data = rows[sourceIndex];
|
||||
@@ -4186,7 +4188,7 @@ const exportContextCell = computed(() => {
|
||||
const deleteRowDetails = computed(() => (props.tableMeta?.tableName ? t("dangerDialog.deleteRowDetails", { table: props.tableMeta.tableName }) : t("dangerDialog.deleteRowDetailsNoTable")));
|
||||
|
||||
const hasVisibleRows = computed(() => displayRowCount.value > 0);
|
||||
const hasActiveFilter = computed(() => !!deferredClientSearchText.value || rowStatusFilter.value !== "all" || hasLocalColumnFilters.value);
|
||||
const hasActiveFilter = computed(() => (dataGridSearchMode.value === "filter" && !!deferredClientSearchText.value) || rowStatusFilter.value !== "all" || hasLocalColumnFilters.value);
|
||||
const emptyTitle = computed(() => (hasActiveFilter.value ? t("grid.noFilteredRows") : t("grid.noRows")));
|
||||
const emptyDescription = computed(() => (hasActiveFilter.value ? t("grid.noFilteredRowsDescription") : t("grid.noRowsDescription")));
|
||||
watch(
|
||||
|
||||
@@ -51,7 +51,7 @@ const ExplainPlanViewer = defineAsyncComponent(() => import("@/components/explai
|
||||
const QueryChart = defineAsyncComponent(() => import("@/components/chart/QueryChart.vue"));
|
||||
import { useQueryStore } from "@/stores/queryStore";
|
||||
import { useConnectionStore } from "@/stores/connectionStore";
|
||||
import { TABLE_FONT_SIZE_MAX, TABLE_FONT_SIZE_MIN, useSettingsStore } from "@/stores/settingsStore";
|
||||
import { TABLE_FONT_SIZE_MAX, TABLE_FONT_SIZE_MIN, useSettingsStore, type DataGridSearchMode } from "@/stores/settingsStore";
|
||||
import { useToast } from "@/composables/useToast";
|
||||
import { canCancelQueryExecution, queryExecutionLabelKey } from "@/lib/queryExecutionState";
|
||||
import { databaseDisplayNameForTab, executionSummaryItems, nextExecutionSummaryView, resultGridCacheKey, resultRunItems, tabularResultItems } from "@/lib/tabPresentation";
|
||||
@@ -180,6 +180,7 @@ const resultTabsScrollerRef = ref<HTMLElement | null>(null);
|
||||
const columnVisibilitySearch = ref("");
|
||||
const columnVisibilityOptions = computed(() => dataGridRef.value?.filteredColumnVisibilityOptions(columnVisibilitySearch.value) ?? []);
|
||||
const dataGridRenderMode = computed(() => settingsStore.editorSettings.dataGridRenderMode);
|
||||
const dataGridSearchMode = computed(() => settingsStore.editorSettings.dataGridSearchMode);
|
||||
const tableFontSize = computed(() => settingsStore.editorSettings.tableFontSize);
|
||||
const redisKeyBrowserRef = ref<SearchableBrowserHandle>();
|
||||
|
||||
@@ -209,6 +210,10 @@ function setDataGridRenderMode(value: "canvas" | "dom") {
|
||||
settingsStore.updateEditorSettings({ dataGridRenderMode: value });
|
||||
}
|
||||
|
||||
function setDataGridSearchMode(value: DataGridSearchMode) {
|
||||
settingsStore.updateEditorSettings({ dataGridSearchMode: value });
|
||||
}
|
||||
|
||||
function setTableFontSize(value: number) {
|
||||
settingsStore.updateEditorSettings({ tableFontSize: value });
|
||||
}
|
||||
@@ -801,7 +806,7 @@ defineExpose({ focusSearch, refreshData, handleModRTarget, requestQueryEditorExe
|
||||
<div class="border-b bg-muted/40 px-3 py-2">
|
||||
<div class="text-xs font-semibold">{{ t("grid.viewOptions") }}</div>
|
||||
</div>
|
||||
<div class="flex items-center justify-between gap-3 px-3 py-2 text-xs">
|
||||
<div class="flex items-center justify-between gap-3 px-3 py-1.5 text-xs">
|
||||
<div class="min-w-0 flex items-center gap-2 font-medium">
|
||||
<SquareDashed class="h-3.5 w-3.5 shrink-0 text-muted-foreground" />
|
||||
<span>{{ t("grid.renderMode") }}</span>
|
||||
@@ -810,7 +815,7 @@ defineExpose({ focusSearch, refreshData, handleModRTarget, requestQueryEditorExe
|
||||
<div class="grid w-32 grid-cols-2 rounded-md border bg-muted/40 p-0.5">
|
||||
<button
|
||||
type="button"
|
||||
class="h-6 min-w-0 truncate whitespace-nowrap rounded-[5px] px-2 text-xs transition-colors"
|
||||
class="h-5 min-w-0 truncate whitespace-nowrap rounded-[5px] px-2 text-xs transition-colors"
|
||||
:class="dataGridRenderMode === 'canvas' ? 'bg-background font-semibold text-foreground shadow-sm' : 'text-muted-foreground hover:text-foreground'"
|
||||
@click="setDataGridRenderMode('canvas')"
|
||||
>
|
||||
@@ -818,7 +823,7 @@ defineExpose({ focusSearch, refreshData, handleModRTarget, requestQueryEditorExe
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="h-6 min-w-0 truncate whitespace-nowrap rounded-[5px] px-2 text-xs transition-colors"
|
||||
class="h-5 min-w-0 truncate whitespace-nowrap rounded-[5px] px-2 text-xs transition-colors"
|
||||
:class="dataGridRenderMode === 'dom' ? 'bg-background font-semibold text-foreground shadow-sm' : 'text-muted-foreground hover:text-foreground'"
|
||||
@click="setDataGridRenderMode('dom')"
|
||||
>
|
||||
@@ -827,15 +832,15 @@ defineExpose({ focusSearch, refreshData, handleModRTarget, requestQueryEditorExe
|
||||
</div>
|
||||
</LightTooltip>
|
||||
</div>
|
||||
<div class="flex items-center justify-between gap-3 px-3 py-2 text-xs">
|
||||
<div class="flex items-center justify-between gap-3 px-3 py-1.5 text-xs">
|
||||
<div class="min-w-0 flex items-center gap-2 font-medium">
|
||||
<span class="flex h-3.5 w-3.5 shrink-0 items-center justify-center text-[11px] font-semibold text-muted-foreground">A</span>
|
||||
<span>{{ t("grid.tableFontSize") }}</span>
|
||||
</div>
|
||||
<div class="flex h-7 w-32 items-center rounded-md border bg-muted/40 p-0.5">
|
||||
<div class="flex h-6 w-32 items-center rounded-md border bg-muted/40 p-0.5">
|
||||
<button
|
||||
type="button"
|
||||
class="flex h-6 w-8 items-center justify-center rounded-[5px] bg-background text-foreground shadow-sm transition-colors hover:text-foreground disabled:pointer-events-none disabled:bg-muted/40 disabled:text-muted-foreground disabled:opacity-50 disabled:shadow-none"
|
||||
class="flex h-5 w-8 items-center justify-center rounded-[5px] bg-background text-foreground shadow-sm transition-colors hover:text-foreground disabled:pointer-events-none disabled:bg-muted/40 disabled:text-muted-foreground disabled:opacity-50 disabled:shadow-none"
|
||||
:disabled="tableFontSize <= TABLE_FONT_SIZE_MIN"
|
||||
:aria-label="t('common.decrease')"
|
||||
@click="decreaseTableFontSize"
|
||||
@@ -845,7 +850,7 @@ defineExpose({ focusSearch, refreshData, handleModRTarget, requestQueryEditorExe
|
||||
<span class="flex-1 text-center text-xs font-semibold tabular-nums">{{ tableFontSize }}</span>
|
||||
<button
|
||||
type="button"
|
||||
class="flex h-6 w-8 items-center justify-center rounded-[5px] bg-background text-foreground shadow-sm transition-colors hover:text-foreground disabled:pointer-events-none disabled:bg-muted/40 disabled:text-muted-foreground disabled:opacity-50 disabled:shadow-none"
|
||||
class="flex h-5 w-8 items-center justify-center rounded-[5px] bg-background text-foreground shadow-sm transition-colors hover:text-foreground disabled:pointer-events-none disabled:bg-muted/40 disabled:text-muted-foreground disabled:opacity-50 disabled:shadow-none"
|
||||
:disabled="tableFontSize >= TABLE_FONT_SIZE_MAX"
|
||||
:aria-label="t('common.increase')"
|
||||
@click="increaseTableFontSize"
|
||||
@@ -854,7 +859,33 @@ defineExpose({ focusSearch, refreshData, handleModRTarget, requestQueryEditorExe
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center justify-between gap-3 px-3 py-2 text-xs">
|
||||
<div class="flex items-center justify-between gap-3 px-3 py-1.5 text-xs">
|
||||
<div class="min-w-0 flex items-center gap-2 font-medium">
|
||||
<Search class="h-3.5 w-3.5 shrink-0 text-muted-foreground" />
|
||||
<span>{{ t("grid.searchMode") }}</span>
|
||||
</div>
|
||||
<LightTooltip :text="t('grid.searchModeHint')" side="left" :side-offset="6" :delay="0" :open-on-focus="false">
|
||||
<div class="grid w-32 grid-cols-2 rounded-md border bg-muted/40 p-0.5">
|
||||
<button
|
||||
type="button"
|
||||
class="h-5 min-w-0 truncate whitespace-nowrap rounded-[5px] px-2 text-xs transition-colors"
|
||||
:class="dataGridSearchMode === 'filter' ? 'bg-background font-semibold text-foreground shadow-sm' : 'text-muted-foreground hover:text-foreground'"
|
||||
@click="setDataGridSearchMode('filter')"
|
||||
>
|
||||
{{ t("grid.searchModeFilter") }}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="h-5 min-w-0 truncate whitespace-nowrap rounded-[5px] px-2 text-xs transition-colors"
|
||||
:class="dataGridSearchMode === 'highlight' ? 'bg-background font-semibold text-foreground shadow-sm' : 'text-muted-foreground hover:text-foreground'"
|
||||
@click="setDataGridSearchMode('highlight')"
|
||||
>
|
||||
{{ t("grid.searchModeHighlight") }}
|
||||
</button>
|
||||
</div>
|
||||
</LightTooltip>
|
||||
</div>
|
||||
<div class="flex items-center justify-between gap-3 px-3 py-1.5 text-xs">
|
||||
<div class="min-w-0 flex items-center gap-2 font-medium">
|
||||
<Rows3 class="h-3.5 w-3.5 shrink-0 text-muted-foreground" />
|
||||
<span>{{ t("grid.transposeMultiRowToggle") }}</span>
|
||||
@@ -863,7 +894,7 @@ defineExpose({ focusSearch, refreshData, handleModRTarget, requestQueryEditorExe
|
||||
<div class="grid w-32 grid-cols-2 rounded-md border bg-muted/40 p-0.5">
|
||||
<button
|
||||
type="button"
|
||||
class="h-6 min-w-0 truncate whitespace-nowrap rounded-[5px] px-2 text-xs transition-colors"
|
||||
class="h-5 min-w-0 truncate whitespace-nowrap rounded-[5px] px-2 text-xs transition-colors"
|
||||
:class="!dataGridRef?.multiRowTranspose ? 'bg-background font-semibold text-foreground shadow-sm' : 'text-muted-foreground hover:text-foreground'"
|
||||
@click="dataGridRef?.setMultiRowTranspose(false)"
|
||||
>
|
||||
@@ -871,7 +902,7 @@ defineExpose({ focusSearch, refreshData, handleModRTarget, requestQueryEditorExe
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="h-6 min-w-0 truncate whitespace-nowrap rounded-[5px] px-2 text-xs transition-colors"
|
||||
class="h-5 min-w-0 truncate whitespace-nowrap rounded-[5px] px-2 text-xs transition-colors"
|
||||
:class="dataGridRef?.multiRowTranspose ? 'bg-background font-semibold text-foreground shadow-sm' : 'text-muted-foreground hover:text-foreground'"
|
||||
@click="dataGridRef?.setMultiRowTranspose(true)"
|
||||
>
|
||||
@@ -880,7 +911,7 @@ defineExpose({ focusSearch, refreshData, handleModRTarget, requestQueryEditorExe
|
||||
</div>
|
||||
</LightTooltip>
|
||||
</div>
|
||||
<div class="flex items-center justify-between gap-3 px-3 py-2 text-xs" :class="{ 'opacity-60': !dataGridRef?.canToggleAllNullColumns }">
|
||||
<div class="flex items-center justify-between gap-3 px-3 py-1.5 text-xs" :class="{ 'opacity-60': !dataGridRef?.canToggleAllNullColumns }">
|
||||
<span class="min-w-0 flex items-center gap-2 font-medium">
|
||||
<EyeOff class="h-3.5 w-3.5 shrink-0 text-muted-foreground" />
|
||||
{{ t("grid.hideNullColumns") }}
|
||||
@@ -1115,7 +1146,7 @@ defineExpose({ focusSearch, refreshData, handleModRTarget, requestQueryEditorExe
|
||||
<div class="border-b bg-muted/40 px-3 py-2">
|
||||
<div class="text-xs font-semibold">{{ t("grid.viewOptions") }}</div>
|
||||
</div>
|
||||
<div class="flex items-center justify-between gap-3 px-3 py-2 text-xs">
|
||||
<div class="flex items-center justify-between gap-3 px-3 py-1.5 text-xs">
|
||||
<div class="min-w-0 flex items-center gap-2 font-medium">
|
||||
<SquareDashed class="h-3.5 w-3.5 shrink-0 text-muted-foreground" />
|
||||
<span>{{ t("grid.renderMode") }}</span>
|
||||
@@ -1124,7 +1155,7 @@ defineExpose({ focusSearch, refreshData, handleModRTarget, requestQueryEditorExe
|
||||
<div class="grid w-32 grid-cols-2 rounded-md border bg-muted/40 p-0.5">
|
||||
<button
|
||||
type="button"
|
||||
class="h-6 min-w-0 truncate whitespace-nowrap rounded-[5px] px-2 text-xs transition-colors"
|
||||
class="h-5 min-w-0 truncate whitespace-nowrap rounded-[5px] px-2 text-xs transition-colors"
|
||||
:class="dataGridRenderMode === 'canvas' ? 'bg-background font-semibold text-foreground shadow-sm' : 'text-muted-foreground hover:text-foreground'"
|
||||
@click="setDataGridRenderMode('canvas')"
|
||||
>
|
||||
@@ -1132,7 +1163,7 @@ defineExpose({ focusSearch, refreshData, handleModRTarget, requestQueryEditorExe
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="h-6 min-w-0 truncate whitespace-nowrap rounded-[5px] px-2 text-xs transition-colors"
|
||||
class="h-5 min-w-0 truncate whitespace-nowrap rounded-[5px] px-2 text-xs transition-colors"
|
||||
:class="dataGridRenderMode === 'dom' ? 'bg-background font-semibold text-foreground shadow-sm' : 'text-muted-foreground hover:text-foreground'"
|
||||
@click="setDataGridRenderMode('dom')"
|
||||
>
|
||||
@@ -1141,15 +1172,15 @@ defineExpose({ focusSearch, refreshData, handleModRTarget, requestQueryEditorExe
|
||||
</div>
|
||||
</LightTooltip>
|
||||
</div>
|
||||
<div class="flex items-center justify-between gap-3 px-3 py-2 text-xs">
|
||||
<div class="flex items-center justify-between gap-3 px-3 py-1.5 text-xs">
|
||||
<div class="min-w-0 flex items-center gap-2 font-medium">
|
||||
<span class="flex h-3.5 w-3.5 shrink-0 items-center justify-center text-[11px] font-semibold text-muted-foreground">A</span>
|
||||
<span>{{ t("grid.tableFontSize") }}</span>
|
||||
</div>
|
||||
<div class="flex h-7 w-32 items-center rounded-md border bg-muted/40 p-0.5">
|
||||
<div class="flex h-6 w-32 items-center rounded-md border bg-muted/40 p-0.5">
|
||||
<button
|
||||
type="button"
|
||||
class="flex h-6 w-8 items-center justify-center rounded-[5px] bg-background text-foreground shadow-sm transition-colors hover:text-foreground disabled:pointer-events-none disabled:bg-muted/40 disabled:text-muted-foreground disabled:opacity-50 disabled:shadow-none"
|
||||
class="flex h-5 w-8 items-center justify-center rounded-[5px] bg-background text-foreground shadow-sm transition-colors hover:text-foreground disabled:pointer-events-none disabled:bg-muted/40 disabled:text-muted-foreground disabled:opacity-50 disabled:shadow-none"
|
||||
:disabled="tableFontSize <= TABLE_FONT_SIZE_MIN"
|
||||
:aria-label="t('common.decrease')"
|
||||
@click="decreaseTableFontSize"
|
||||
@@ -1159,7 +1190,7 @@ defineExpose({ focusSearch, refreshData, handleModRTarget, requestQueryEditorExe
|
||||
<span class="flex-1 text-center text-xs font-semibold tabular-nums">{{ tableFontSize }}</span>
|
||||
<button
|
||||
type="button"
|
||||
class="flex h-6 w-8 items-center justify-center rounded-[5px] bg-background text-foreground shadow-sm transition-colors hover:text-foreground disabled:pointer-events-none disabled:bg-muted/40 disabled:text-muted-foreground disabled:opacity-50 disabled:shadow-none"
|
||||
class="flex h-5 w-8 items-center justify-center rounded-[5px] bg-background text-foreground shadow-sm transition-colors hover:text-foreground disabled:pointer-events-none disabled:bg-muted/40 disabled:text-muted-foreground disabled:opacity-50 disabled:shadow-none"
|
||||
:disabled="tableFontSize >= TABLE_FONT_SIZE_MAX"
|
||||
:aria-label="t('common.increase')"
|
||||
@click="increaseTableFontSize"
|
||||
@@ -1168,7 +1199,33 @@ defineExpose({ focusSearch, refreshData, handleModRTarget, requestQueryEditorExe
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center justify-between gap-3 px-3 py-2 text-xs">
|
||||
<div class="flex items-center justify-between gap-3 px-3 py-1.5 text-xs">
|
||||
<div class="min-w-0 flex items-center gap-2 font-medium">
|
||||
<Search class="h-3.5 w-3.5 shrink-0 text-muted-foreground" />
|
||||
<span>{{ t("grid.searchMode") }}</span>
|
||||
</div>
|
||||
<LightTooltip :text="t('grid.searchModeHint')" side="left" :side-offset="6" :delay="0" :open-on-focus="false">
|
||||
<div class="grid w-32 grid-cols-2 rounded-md border bg-muted/40 p-0.5">
|
||||
<button
|
||||
type="button"
|
||||
class="h-5 min-w-0 truncate whitespace-nowrap rounded-[5px] px-2 text-xs transition-colors"
|
||||
:class="dataGridSearchMode === 'filter' ? 'bg-background font-semibold text-foreground shadow-sm' : 'text-muted-foreground hover:text-foreground'"
|
||||
@click="setDataGridSearchMode('filter')"
|
||||
>
|
||||
{{ t("grid.searchModeFilter") }}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="h-5 min-w-0 truncate whitespace-nowrap rounded-[5px] px-2 text-xs transition-colors"
|
||||
:class="dataGridSearchMode === 'highlight' ? 'bg-background font-semibold text-foreground shadow-sm' : 'text-muted-foreground hover:text-foreground'"
|
||||
@click="setDataGridSearchMode('highlight')"
|
||||
>
|
||||
{{ t("grid.searchModeHighlight") }}
|
||||
</button>
|
||||
</div>
|
||||
</LightTooltip>
|
||||
</div>
|
||||
<div class="flex items-center justify-between gap-3 px-3 py-1.5 text-xs">
|
||||
<div class="min-w-0 flex items-center gap-2 font-medium">
|
||||
<Rows3 class="h-3.5 w-3.5 shrink-0 text-muted-foreground" />
|
||||
<span>{{ t("grid.transposeMultiRowToggle") }}</span>
|
||||
@@ -1177,7 +1234,7 @@ defineExpose({ focusSearch, refreshData, handleModRTarget, requestQueryEditorExe
|
||||
<div class="grid w-32 grid-cols-2 rounded-md border bg-muted/40 p-0.5">
|
||||
<button
|
||||
type="button"
|
||||
class="h-6 min-w-0 truncate whitespace-nowrap rounded-[5px] px-2 text-xs transition-colors"
|
||||
class="h-5 min-w-0 truncate whitespace-nowrap rounded-[5px] px-2 text-xs transition-colors"
|
||||
:class="!dataGridRef?.multiRowTranspose ? 'bg-background font-semibold text-foreground shadow-sm' : 'text-muted-foreground hover:text-foreground'"
|
||||
@click="dataGridRef?.setMultiRowTranspose(false)"
|
||||
>
|
||||
@@ -1185,7 +1242,7 @@ defineExpose({ focusSearch, refreshData, handleModRTarget, requestQueryEditorExe
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="h-6 min-w-0 truncate whitespace-nowrap rounded-[5px] px-2 text-xs transition-colors"
|
||||
class="h-5 min-w-0 truncate whitespace-nowrap rounded-[5px] px-2 text-xs transition-colors"
|
||||
:class="dataGridRef?.multiRowTranspose ? 'bg-background font-semibold text-foreground shadow-sm' : 'text-muted-foreground hover:text-foreground'"
|
||||
@click="dataGridRef?.setMultiRowTranspose(true)"
|
||||
>
|
||||
@@ -1194,7 +1251,7 @@ defineExpose({ focusSearch, refreshData, handleModRTarget, requestQueryEditorExe
|
||||
</div>
|
||||
</LightTooltip>
|
||||
</div>
|
||||
<div class="flex items-center justify-between gap-3 px-3 py-2 text-xs" :class="{ 'opacity-60': !dataGridRef?.canToggleAllNullColumns }">
|
||||
<div class="flex items-center justify-between gap-3 px-3 py-1.5 text-xs" :class="{ 'opacity-60': !dataGridRef?.canToggleAllNullColumns }">
|
||||
<span class="min-w-0 flex items-center gap-2 font-medium">
|
||||
<EyeOff class="h-3.5 w-3.5 shrink-0 text-muted-foreground" />
|
||||
{{ t("grid.hideNullColumns") }}
|
||||
|
||||
Reference in new issue
Block a user