mirror of
https://github.com/DeNNiiInc/dbgate.git
synced 2026-04-29 11:03:57 +00:00
column manager
This commit is contained in:
28
packages/web/src/datagrid/ColumnManager.svelte
Normal file
28
packages/web/src/datagrid/ColumnManager.svelte
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { filterName, GridDisplay } from 'dbgate-datalib';
|
||||||
|
|
||||||
|
import InlineButton from '../elements/InlineButton.svelte';
|
||||||
|
import ManagerInnerContainer from '../elements/ManagerInnerContainer.svelte';
|
||||||
|
|
||||||
|
import SearchBoxWrapper from '../elements/SearchBoxWrapper.svelte';
|
||||||
|
import SearchInput from '../elements/SearchInput.svelte';
|
||||||
|
import ColumnManagerRow from './ColumnManagerRow.svelte';
|
||||||
|
|
||||||
|
export let managerSize;
|
||||||
|
export let display: GridDisplay;
|
||||||
|
|
||||||
|
let columnFilter;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<SearchBoxWrapper>
|
||||||
|
<SearchInput placeholder="Search columns" bind:value={columnFilter} />
|
||||||
|
<InlineButton on:click={() => display.hideAllColumns()}>Hide</InlineButton>
|
||||||
|
<InlineButton on:click={() => display.showAllColumns()}>Show</InlineButton>
|
||||||
|
</SearchBoxWrapper>
|
||||||
|
<ManagerInnerContainer width={managerSize}>
|
||||||
|
{#each display
|
||||||
|
.getColumns(columnFilter)
|
||||||
|
.filter(column => filterName(columnFilter, column.columnName)) as column (column.uniqueName)}
|
||||||
|
<ColumnManagerRow {display} {column} />
|
||||||
|
{/each}
|
||||||
|
</ManagerInnerContainer>
|
||||||
44
packages/web/src/datagrid/ColumnManagerRow.svelte
Normal file
44
packages/web/src/datagrid/ColumnManagerRow.svelte
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { plusExpandIcon } from '../icons/expandIcons';
|
||||||
|
|
||||||
|
import FontIcon from '../icons/FontIcon.svelte';
|
||||||
|
import ColumnLabel from './ColumnLabel.svelte';
|
||||||
|
|
||||||
|
export let column;
|
||||||
|
export let display;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div
|
||||||
|
class="row"
|
||||||
|
on:click={e => {
|
||||||
|
// @ts-ignore
|
||||||
|
if (e.target.closest('.expandColumnIcon')) return;
|
||||||
|
display.focusColumn(column.uniqueName);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<span class="expandColumnIcon">
|
||||||
|
<FontIcon
|
||||||
|
icon={column.foreignKey ? plusExpandIcon(display.isExpandedColumn(column.uniqueName)) : 'icon invisible-box'}
|
||||||
|
on:click={() => display.toggleExpandedColumn(column.uniqueName)}
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
style={`margin-left: ${5 + (column.uniquePath.length - 1) * 10}px`}
|
||||||
|
checked={column.isChecked}
|
||||||
|
on:change={() => display.setColumnVisibility(column.uniquePath, !column.isChecked)}
|
||||||
|
/>
|
||||||
|
<ColumnLabel {...column} />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.row {
|
||||||
|
margin-left: 5px;
|
||||||
|
margin-right: 5px;
|
||||||
|
cursor: pointer;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
.row:hover {
|
||||||
|
background: var(--theme-bg-hover);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -2,16 +2,20 @@
|
|||||||
import HorizontalSplitter from '../elements/HorizontalSplitter.svelte';
|
import HorizontalSplitter from '../elements/HorizontalSplitter.svelte';
|
||||||
import WidgetColumnBar from '../widgets/WidgetColumnBar.svelte';
|
import WidgetColumnBar from '../widgets/WidgetColumnBar.svelte';
|
||||||
import WidgetColumnBarItem from '../widgets/WidgetColumnBarItem.svelte';
|
import WidgetColumnBarItem from '../widgets/WidgetColumnBarItem.svelte';
|
||||||
|
import ColumnManager from './ColumnManager.svelte';
|
||||||
|
|
||||||
export let config;
|
export let config;
|
||||||
export let gridCoreComponent;
|
export let gridCoreComponent;
|
||||||
export let showReferences = true;
|
export let showReferences = true;
|
||||||
|
|
||||||
|
let managerSize;
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<HorizontalSplitter initialValue="300px">
|
<HorizontalSplitter initialValue="300px" bind:size={managerSize}>
|
||||||
<div class="left" slot="1">
|
<div class="left" slot="1">
|
||||||
<WidgetColumnBar>
|
<WidgetColumnBar>
|
||||||
<WidgetColumnBarItem title="Columns" name="columns" height={showReferences ? '40%' : '60%'} />
|
<WidgetColumnBarItem title="Columns" name="columns" height={showReferences ? '40%' : '60%'} />
|
||||||
|
<ColumnManager {...$$props} {managerSize} />
|
||||||
</WidgetColumnBar>
|
</WidgetColumnBar>
|
||||||
</div>
|
</div>
|
||||||
<div slot="2">
|
<div slot="2">
|
||||||
|
|||||||
@@ -32,6 +32,7 @@
|
|||||||
export let isInserted = false;
|
export let isInserted = false;
|
||||||
export let isDeleted = false;
|
export let isDeleted = false;
|
||||||
export let isAutofillSelected = false;
|
export let isAutofillSelected = false;
|
||||||
|
export let isFocusedColumn = false;
|
||||||
|
|
||||||
$: value = (rowData || {})[col.uniqueName];
|
$: value = (rowData || {})[col.uniqueName];
|
||||||
</script>
|
</script>
|
||||||
@@ -46,6 +47,7 @@
|
|||||||
class:isInserted
|
class:isInserted
|
||||||
class:isDeleted
|
class:isDeleted
|
||||||
class:isAutofillSelected
|
class:isAutofillSelected
|
||||||
|
class:isFocusedColumn
|
||||||
style={`width:${col.width}px; min-width:${col.width}px; max-width:${col.width}px`}
|
style={`width:${col.width}px; min-width:${col.width}px; max-width:${col.width}px`}
|
||||||
>
|
>
|
||||||
{#if value == null}
|
{#if value == null}
|
||||||
@@ -107,6 +109,9 @@
|
|||||||
outline: 3px solid var(--theme-bg-selected);
|
outline: 3px solid var(--theme-bg-selected);
|
||||||
outline-offset: -3px;
|
outline-offset: -3px;
|
||||||
}
|
}
|
||||||
|
td.isFocusedColumn {
|
||||||
|
background: var(--theme-bg-alt);
|
||||||
|
}
|
||||||
td.isModifiedRow {
|
td.isModifiedRow {
|
||||||
background: var(--theme-bg-gold);
|
background: var(--theme-bg-gold);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,6 +46,7 @@
|
|||||||
import ColumnHeaderControl from './ColumnHeaderControl.svelte';
|
import ColumnHeaderControl from './ColumnHeaderControl.svelte';
|
||||||
import DataGridRow from './DataGridRow.svelte';
|
import DataGridRow from './DataGridRow.svelte';
|
||||||
import { getFilterType, getFilterValueExpression } from 'dbgate-filterparser';
|
import { getFilterType, getFilterValueExpression } from 'dbgate-filterparser';
|
||||||
|
import { tick } from 'svelte';
|
||||||
import {
|
import {
|
||||||
cellIsSelected,
|
cellIsSelected,
|
||||||
countColumnSizes,
|
countColumnSizes,
|
||||||
@@ -135,6 +136,51 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$: {
|
||||||
|
if (display && display.focusedColumn) {
|
||||||
|
const invMap = _.invert(realColumnUniqueNames);
|
||||||
|
const colIndex = invMap[display.focusedColumn];
|
||||||
|
if (colIndex) {
|
||||||
|
scrollIntoView([null, colIndex]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function scrollIntoView(cell) {
|
||||||
|
const [row, col] = cell;
|
||||||
|
|
||||||
|
if (row != null) {
|
||||||
|
let newRow = null;
|
||||||
|
const rowCount = grider.rowCount;
|
||||||
|
if (rowCount == 0) return;
|
||||||
|
|
||||||
|
if (row < firstVisibleRowScrollIndex) newRow = row;
|
||||||
|
else if (row + 1 >= firstVisibleRowScrollIndex + visibleRowCountLowerBound)
|
||||||
|
newRow = row - visibleRowCountLowerBound + 2;
|
||||||
|
|
||||||
|
if (newRow < 0) newRow = 0;
|
||||||
|
if (newRow >= rowCount) newRow = rowCount - 1;
|
||||||
|
|
||||||
|
if (newRow != null) {
|
||||||
|
firstVisibleRowScrollIndex = newRow;
|
||||||
|
domVerticalScroll.scroll(newRow);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (col != null) {
|
||||||
|
if (col >= columnSizes.frozenCount) {
|
||||||
|
let newColumn = columnSizes.scrollInView(
|
||||||
|
firstVisibleColumnScrollIndex,
|
||||||
|
col - columnSizes.frozenCount,
|
||||||
|
gridScrollAreaWidth
|
||||||
|
);
|
||||||
|
firstVisibleColumnScrollIndex = newColumn;
|
||||||
|
|
||||||
|
domHorizontalScroll.scroll(newColumn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function handleGridMouseDown(event) {
|
function handleGridMouseDown(event) {
|
||||||
if (event.target.closest('.buttonLike')) return;
|
if (event.target.closest('.buttonLike')) return;
|
||||||
if (event.target.closest('.resizeHandleControl')) return;
|
if (event.target.closest('.resizeHandleControl')) return;
|
||||||
@@ -341,6 +387,7 @@
|
|||||||
{autofillSelectedCells}
|
{autofillSelectedCells}
|
||||||
selectedCells={filterCellsForRow(selectedCells, rowIndex)}
|
selectedCells={filterCellsForRow(selectedCells, rowIndex)}
|
||||||
autofillMarkerCell={filterCellForRow(autofillMarkerCell, rowIndex)}
|
autofillMarkerCell={filterCellForRow(autofillMarkerCell, rowIndex)}
|
||||||
|
focusedColumn={display.focusedColumn}
|
||||||
{frameSelection}
|
{frameSelection}
|
||||||
/>
|
/>
|
||||||
{/each}
|
{/each}
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
export let selectedCells = undefined;
|
export let selectedCells = undefined;
|
||||||
export let autofillSelectedCells = undefined;
|
export let autofillSelectedCells = undefined;
|
||||||
export let autofillMarkerCell = undefined;
|
export let autofillMarkerCell = undefined;
|
||||||
|
export let focusedColumn = undefined;
|
||||||
|
|
||||||
$: rowData = grider.getRowData(rowIndex);
|
$: rowData = grider.getRowData(rowIndex);
|
||||||
$: rowStatus = grider.getRowStatus(rowIndex);
|
$: rowStatus = grider.getRowStatus(rowIndex);
|
||||||
@@ -36,6 +37,7 @@
|
|||||||
isSelected={frameSelection ? false : cellIsSelected(rowIndex, col.colIndex, selectedCells)}
|
isSelected={frameSelection ? false : cellIsSelected(rowIndex, col.colIndex, selectedCells)}
|
||||||
isFrameSelected={frameSelection ? cellIsSelected(rowIndex, col.colIndex, selectedCells) : false}
|
isFrameSelected={frameSelection ? cellIsSelected(rowIndex, col.colIndex, selectedCells) : false}
|
||||||
isAutofillSelected={cellIsSelected(rowIndex, col.colIndex, autofillSelectedCells)}
|
isAutofillSelected={cellIsSelected(rowIndex, col.colIndex, autofillSelectedCells)}
|
||||||
|
isFocusedColumn={col.uniqueName == focusedColumn}
|
||||||
/>
|
/>
|
||||||
{/each}
|
{/each}
|
||||||
</tr>
|
</tr>
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
export let isSplitter = true;
|
export let isSplitter = true;
|
||||||
export let initialValue = undefined;
|
export let initialValue = undefined;
|
||||||
|
|
||||||
let size = 0;
|
export let size = 0;
|
||||||
let clientWidth;
|
let clientWidth;
|
||||||
|
|
||||||
$: size = computeSplitterSize(initialValue, clientWidth);
|
$: size = computeSplitterSize(initialValue, clientWidth);
|
||||||
|
|||||||
15
packages/web/src/elements/ManagerInnerContainer.svelte
Normal file
15
packages/web/src/elements/ManagerInnerContainer.svelte
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
export let width;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div style={`max-width: ${width}px`}>
|
||||||
|
<slot />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
div {
|
||||||
|
flex: 1 1;
|
||||||
|
overflow-y: auto;
|
||||||
|
overflow-x: auto;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -3,6 +3,7 @@
|
|||||||
<style>
|
<style>
|
||||||
div {
|
div {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
border-bottom: 1px solid var(--theme-border);
|
||||||
margin-bottom: 5px;
|
margin-bottom: 5px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
Reference in New Issue
Block a user