mirror of
https://github.com/DeNNiiInc/dbgate.git
synced 2026-04-18 00:56:02 +00:00
Add column filter/search to Table cell data view
Adds a search input at the top of the Table view that filters columns by name with regex support.
This commit is contained in:
@@ -9,6 +9,9 @@
|
|||||||
import EditCellDataModal from '../modals/EditCellDataModal.svelte';
|
import EditCellDataModal from '../modals/EditCellDataModal.svelte';
|
||||||
import ShowFormButton from '../formview/ShowFormButton.svelte';
|
import ShowFormButton from '../formview/ShowFormButton.svelte';
|
||||||
import { openJsonDocument } from '../tabs/JsonTab.svelte';
|
import { openJsonDocument } from '../tabs/JsonTab.svelte';
|
||||||
|
import SearchBoxWrapper from '../elements/SearchBoxWrapper.svelte';
|
||||||
|
import SearchInput from '../elements/SearchInput.svelte';
|
||||||
|
import CloseSearchButton from '../buttons/CloseSearchButton.svelte';
|
||||||
|
|
||||||
export let selection;
|
export let selection;
|
||||||
|
|
||||||
@@ -20,6 +23,8 @@
|
|||||||
$: realColumnUniqueNames = selection?.realColumnUniqueNames || [];
|
$: realColumnUniqueNames = selection?.realColumnUniqueNames || [];
|
||||||
$: setCellValue = selection?.setCellValue;
|
$: setCellValue = selection?.setCellValue;
|
||||||
|
|
||||||
|
let filter = '';
|
||||||
|
|
||||||
$: orderedFields = realColumnUniqueNames
|
$: orderedFields = realColumnUniqueNames
|
||||||
.map(colName => {
|
.map(colName => {
|
||||||
const col = columns.find(c => c.uniqueName === colName);
|
const col = columns.find(c => c.uniqueName === colName);
|
||||||
@@ -34,6 +39,16 @@
|
|||||||
})
|
})
|
||||||
.filter(Boolean);
|
.filter(Boolean);
|
||||||
|
|
||||||
|
$: filteredFields = orderedFields.filter(field => {
|
||||||
|
if (!filter) return true;
|
||||||
|
try {
|
||||||
|
const regex = new RegExp(filter, 'i');
|
||||||
|
return regex.test(field.columnName);
|
||||||
|
} catch (e) {
|
||||||
|
return field.columnName.toLowerCase().includes(filter.toLowerCase());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
let editingColumn = null;
|
let editingColumn = null;
|
||||||
let editValue = '';
|
let editValue = '';
|
||||||
let domEditor = null;
|
let domEditor = null;
|
||||||
@@ -102,12 +117,12 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function moveToNextField(field, reverse) {
|
function moveToNextField(field, reverse) {
|
||||||
const currentIndex = orderedFields.findIndex(f => f.uniqueName === field.uniqueName);
|
const currentIndex = filteredFields.findIndex(f => f.uniqueName === field.uniqueName);
|
||||||
const nextIndex = reverse ? currentIndex - 1 : currentIndex + 1;
|
const nextIndex = reverse ? currentIndex - 1 : currentIndex + 1;
|
||||||
if (nextIndex < 0 || nextIndex >= orderedFields.length) return;
|
if (nextIndex < 0 || nextIndex >= filteredFields.length) return;
|
||||||
|
|
||||||
tick().then(() => {
|
tick().then(() => {
|
||||||
const nextField = orderedFields[nextIndex];
|
const nextField = filteredFields[nextIndex];
|
||||||
if (isJsonValue(nextField.value)) {
|
if (isJsonValue(nextField.value)) {
|
||||||
openEditModal(nextField);
|
openEditModal(nextField);
|
||||||
} else {
|
} else {
|
||||||
@@ -116,6 +131,14 @@
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function handleSearchKeyDown(e) {
|
||||||
|
if (e.keyCode === keycodes.backspace && (e.metaKey || e.ctrlKey)) {
|
||||||
|
filter = '';
|
||||||
|
e.stopPropagation();
|
||||||
|
e.preventDefault();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function handleBlur(field) {
|
function handleBlur(field) {
|
||||||
if (isChangedRef.get()) {
|
if (isChangedRef.get()) {
|
||||||
saveValue(field);
|
saveValue(field);
|
||||||
@@ -152,11 +175,19 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="outer">
|
<div class="outer">
|
||||||
|
{#if rowData}
|
||||||
|
<div class="search-wrapper" on:keydown={handleSearchKeyDown}>
|
||||||
|
<SearchBoxWrapper noMargin>
|
||||||
|
<SearchInput placeholder="Filter columns (regex)" bind:value={filter} />
|
||||||
|
<CloseSearchButton bind:filter />
|
||||||
|
</SearchBoxWrapper>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
<div class="inner">
|
<div class="inner">
|
||||||
{#if !rowData}
|
{#if !rowData}
|
||||||
<div class="no-data">No data selected</div>
|
<div class="no-data">No data selected</div>
|
||||||
{:else}
|
{:else}
|
||||||
{#each orderedFields as field (field.uniqueName)}
|
{#each filteredFields as field (field.uniqueName)}
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<div class="field-name">{field.columnName}</div>
|
<div class="field-name">{field.columnName}</div>
|
||||||
<div
|
<div
|
||||||
@@ -210,15 +241,17 @@
|
|||||||
.outer {
|
.outer {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-wrapper {
|
||||||
|
padding: 4px 4px 0 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.inner {
|
.inner {
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
position: absolute;
|
flex: 1;
|
||||||
left: 0;
|
|
||||||
top: 0;
|
|
||||||
right: 0;
|
|
||||||
bottom: 0;
|
|
||||||
padding: 4px;
|
padding: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user