From a41538b452959f75cd536df0d60c847e24077cff Mon Sep 17 00:00:00 2001 From: Jan Prochazka Date: Sun, 10 May 2020 18:52:14 +0200 Subject: [PATCH] columns resize --- packages/datalib/src/GridConfig.ts | 2 + packages/datalib/src/GridDisplay.ts | 76 ++++++++++++------- packages/datalib/src/JslGridDisplay.ts | 4 +- packages/datalib/src/TableGridDisplay.ts | 3 +- packages/datalib/src/ViewGridDisplay.ts | 4 +- .../web/src/datagrid/ColumnHeaderControl.js | 14 +++- packages/web/src/datagrid/ColumnLabel.js | 1 + packages/web/src/datagrid/DataGridCore.js | 3 + packages/web/src/datagrid/gridutil.ts | 24 ++++-- 9 files changed, 90 insertions(+), 41 deletions(-) diff --git a/packages/datalib/src/GridConfig.ts b/packages/datalib/src/GridConfig.ts index 36636022..27093858 100644 --- a/packages/datalib/src/GridConfig.ts +++ b/packages/datalib/src/GridConfig.ts @@ -19,6 +19,7 @@ export interface GridReferenceDefinition { export interface GridConfig extends GridConfigColumns { filters: { [uniqueName: string]: string }; focusedColumn?: string; + columnWidths: { [uniqueName: string]: number }; sort: { uniqueName: string; order: 'ASC' | 'DESC'; @@ -37,6 +38,7 @@ export function createGridConfig(): GridConfig { expandedColumns: [], addedColumns: [], filters: {}, + columnWidths: {}, sort: [], focusedColumn: null, }; diff --git a/packages/datalib/src/GridDisplay.ts b/packages/datalib/src/GridDisplay.ts index b56a6658..eb0018bc 100644 --- a/packages/datalib/src/GridDisplay.ts +++ b/packages/datalib/src/GridDisplay.ts @@ -38,12 +38,13 @@ export function combineReferenceActions(a: ReferenceActionResult, b: ReferenceAc return 'noAction'; } -export type ChangeCacheFunc = (changeFunc: (config: GridCache) => GridCache) => void; +export type ChangeCacheFunc = (changeFunc: (cache: GridCache) => GridCache) => void; +export type ChangeConfigFunc = (changeFunc: (config: GridConfig) => GridConfig) => void; export abstract class GridDisplay { constructor( public config: GridConfig, - protected setConfig: (config: GridConfig) => void, + protected setConfig: ChangeConfigFunc, public cache: GridCache, protected setCache: ChangeCacheFunc, public driver?: EngineDriver @@ -67,10 +68,10 @@ export abstract class GridDisplay { } focusColumn(uniqueName: string) { - this.setConfig({ - ...this.config, + this.setConfig((cfg) => ({ + ...cfg, focusedColumn: uniqueName, - }); + })); } get focusedColumn() { @@ -96,30 +97,30 @@ export abstract class GridDisplay { includeInColumnSet(field: keyof GridConfigColumns, uniqueName: string, isIncluded: boolean) { // console.log('includeInColumnSet', field, uniqueName, isIncluded); if (isIncluded) { - this.setConfig({ - ...this.config, - [field]: [...(this.config[field] || []), uniqueName], - }); + this.setConfig((cfg) => ({ + ...cfg, + [field]: [...(cfg[field] || []), uniqueName], + })); } else { - this.setConfig({ - ...this.config, - [field]: (this.config[field] || []).filter((x) => x != uniqueName), - }); + this.setConfig((cfg) => ({ + ...cfg, + [field]: (cfg[field] || []).filter((x) => x != uniqueName), + })); } } showAllColumns() { - this.setConfig({ - ...this.config, + this.setConfig((cfg) => ({ + ...cfg, hiddenColumns: [], - }); + })); } hideAllColumns() { - this.setConfig({ - ...this.config, + this.setConfig((cfg) => ({ + ...cfg, hiddenColumns: this.columns.map((x) => x.uniqueName), - }); + })); } get hiddenColumnIndexes() { @@ -203,21 +204,21 @@ export abstract class GridDisplay { } setFilter(uniqueName, value) { - this.setConfig({ - ...this.config, + this.setConfig((cfg) => ({ + ...cfg, filters: { - ...this.config.filters, + ...cfg.filters, [uniqueName]: value, }, - }); + })); this.reload(); } setSort(uniqueName, order) { - this.setConfig({ - ...this.config, + this.setConfig((cfg) => ({ + ...cfg, sort: [{ uniqueName, order }], - }); + })); this.reload(); } @@ -230,10 +231,10 @@ export abstract class GridDisplay { } clearFilters() { - this.setConfig({ - ...this.config, + this.setConfig((cfg) => ({ + ...cfg, filters: {}, - }); + })); this.reload(); } @@ -314,6 +315,23 @@ export abstract class GridDisplay { return sql; } + resizeColumn(uniqueName: string, computedSize: number, diff: number) { + this.setConfig((cfg) => { + const columnWidths = { + ...cfg.columnWidths, + }; + if (columnWidths[uniqueName]) { + columnWidths[uniqueName] += diff; + } else { + columnWidths[uniqueName] = computedSize + diff; + } + return { + ...cfg, + columnWidths, + }; + }); + } + getCountQuery() { const select = this.createSelect(); select.columns = [ diff --git a/packages/datalib/src/JslGridDisplay.ts b/packages/datalib/src/JslGridDisplay.ts index 98272561..7d900a63 100644 --- a/packages/datalib/src/JslGridDisplay.ts +++ b/packages/datalib/src/JslGridDisplay.ts @@ -1,4 +1,4 @@ -import { GridDisplay, ChangeCacheFunc } from './GridDisplay'; +import { GridDisplay, ChangeCacheFunc, ChangeConfigFunc } from './GridDisplay'; import { QueryResultColumn } from '@dbgate/types'; import { GridConfig, GridCache } from './GridConfig'; @@ -7,7 +7,7 @@ export class JslGridDisplay extends GridDisplay { jslid, columns: QueryResultColumn[], config: GridConfig, - setConfig: (config: GridConfig) => void, + setConfig: ChangeConfigFunc, cache: GridCache, setCache: ChangeCacheFunc ) { diff --git a/packages/datalib/src/TableGridDisplay.ts b/packages/datalib/src/TableGridDisplay.ts index 52ef3f22..1770d485 100644 --- a/packages/datalib/src/TableGridDisplay.ts +++ b/packages/datalib/src/TableGridDisplay.ts @@ -6,6 +6,7 @@ import { DisplayColumn, ReferenceActionResult, DisplayedColumnInfo, + ChangeConfigFunc, } from './GridDisplay'; import { TableInfo, EngineDriver, ViewInfo, ColumnInfo, NamedObjectInfo } from '@dbgate/types'; import { GridConfig, GridCache, createGridCache } from './GridConfig'; @@ -19,7 +20,7 @@ export class TableGridDisplay extends GridDisplay { public tableName: NamedObjectInfo, driver: EngineDriver, config: GridConfig, - setConfig: (config: GridConfig) => void, + setConfig: ChangeConfigFunc, cache: GridCache, setCache: ChangeCacheFunc, protected getTableInfo: ({ schemaName, pureName }) => Promise diff --git a/packages/datalib/src/ViewGridDisplay.ts b/packages/datalib/src/ViewGridDisplay.ts index ee7cf084..36cd7246 100644 --- a/packages/datalib/src/ViewGridDisplay.ts +++ b/packages/datalib/src/ViewGridDisplay.ts @@ -1,5 +1,5 @@ import _ from 'lodash'; -import { GridDisplay, ChangeCacheFunc } from './GridDisplay'; +import { GridDisplay, ChangeCacheFunc, ChangeConfigFunc } from './GridDisplay'; import { EngineDriver, ViewInfo, ColumnInfo } from '@dbgate/types'; import { GridConfig, GridCache } from './GridConfig'; @@ -8,7 +8,7 @@ export class ViewGridDisplay extends GridDisplay { public view: ViewInfo, driver: EngineDriver, config: GridConfig, - setConfig: (config: GridConfig) => void, + setConfig: ChangeConfigFunc, cache: GridCache, setCache: ChangeCacheFunc ) { diff --git a/packages/web/src/datagrid/ColumnHeaderControl.js b/packages/web/src/datagrid/ColumnHeaderControl.js index ff9f6b84..28a659fe 100644 --- a/packages/web/src/datagrid/ColumnHeaderControl.js +++ b/packages/web/src/datagrid/ColumnHeaderControl.js @@ -3,10 +3,12 @@ import styled from 'styled-components'; import ColumnLabel from './ColumnLabel'; import DropDownButton from '../widgets/DropDownButton'; import { DropDownMenuItem } from '../modals/DropDownMenu'; +import { useSplitterDrag } from '../widgets/Splitter'; import { FontIcon } from '../icons'; const HeaderDiv = styled.div` display: flex; + flex-wrap: nowrap; `; const LabelDiv = styled.div` @@ -15,13 +17,22 @@ const LabelDiv = styled.div` // padding-left: 2px; padding: 2px; margin: auto; + white-space: nowrap; `; const IconWrapper = styled.span` margin-left: 3px; `; -export default function ColumnHeaderControl({ column, setSort, order }) { +const ResizeHandle = styled.div` + background-color: #ccc; + width: 2px; + cursor: col-resize; + z-index: 1; +`; + +export default function ColumnHeaderControl({ column, setSort, onResize, order }) { + const onResizeDown = useSplitterDrag('clientX', onResize); return ( @@ -43,6 +54,7 @@ export default function ColumnHeaderControl({ column, setSort, order }) { setSort('DESC')}>Sort descending )} + ); } diff --git a/packages/web/src/datagrid/ColumnLabel.js b/packages/web/src/datagrid/ColumnLabel.js index 4ca1f81f..9e7891a9 100644 --- a/packages/web/src/datagrid/ColumnLabel.js +++ b/packages/web/src/datagrid/ColumnLabel.js @@ -6,6 +6,7 @@ import { SequenceIcon, ForeignKeyIcon } from '../icons'; const Label = styled.span` font-weight: ${props => (props.notNull ? 'bold' : 'normal')}; + white-space: nowrap; `; /** @param column {import('@dbgate/datalib').DisplayColumn|import('@dbgate/types').ColumnInfo} */ diff --git a/packages/web/src/datagrid/DataGridCore.js b/packages/web/src/datagrid/DataGridCore.js index 1d4594a8..a4acaed7 100644 --- a/packages/web/src/datagrid/DataGridCore.js +++ b/packages/web/src/datagrid/DataGridCore.js @@ -509,7 +509,9 @@ export default function DataGridCore(props) { function handleGridMouseDown(event) { if (event.target.closest('.buttonLike')) return; + if (event.target.closest('.resizeHandleControl')) return; if (event.target.closest('input')) return; + // event.target.closest('table').focus(); event.preventDefault(); // @ts-ignore @@ -1044,6 +1046,7 @@ export default function DataGridCore(props) { column={col} setSort={display.sortable ? (order) => display.setSort(col.uniqueName, order) : null} order={display.getSortOrder(col.uniqueName)} + onResize={(diff) => display.resizeColumn(col.uniqueName, col.widthNumber, diff)} /> ))} diff --git a/packages/web/src/datagrid/gridutil.ts b/packages/web/src/datagrid/gridutil.ts index edeabfdc..57d57a1b 100644 --- a/packages/web/src/datagrid/gridutil.ts +++ b/packages/web/src/datagrid/gridutil.ts @@ -1,8 +1,9 @@ import _ from 'lodash'; import { SeriesSizes } from './SeriesSizes'; import { CellAddress } from './selection'; +import { GridDisplay } from '@dbgate/datalib'; -export function countColumnSizes(loadedRows, columns, containerWidth, display) { +export function countColumnSizes(loadedRows, columns, containerWidth, display: GridDisplay) { const columnSizes = new SeriesSizes(); if (!loadedRows || !columns) return columnSizes; @@ -25,12 +26,17 @@ export function countColumnSizes(loadedRows, columns, containerWidth, display) { //this.columnSizes.PutSizeOverride(col, this.columns[col].Name.length * 8); const column = columns[colIndex]; + if (display.config.columnWidths[column.uniqueName]) { + columnSizes.putSizeOverride(colIndex, display.config.columnWidths[column.uniqueName]); + continue; + } + // if (column.columnClientObject != null && column.columnClientObject.notNull) context.font = "bold 14px Helvetica"; // else context.font = "14px Helvetica"; context.font = 'bold 14px Helvetica'; - let text = column.headerText; - let headerWidth = context.measureText(text).width + 64; + const text = column.headerText; + const headerWidth = context.measureText(text).width + 64; // if (column.columnClientObject != null && column.columnClientObject.icon != null) headerWidth += 16; // if (this.getFilterOnColumn(column.uniquePath)) headerWidth += 16; @@ -47,9 +53,14 @@ export function countColumnSizes(loadedRows, columns, containerWidth, display) { context.font = '14px Helvetica'; for (let row of loadedRows.slice(0, 20)) { for (let colIndex = 0; colIndex < columns.length; colIndex++) { - let uqName = columns[colIndex].uniqueName; - let text = row[uqName]; - let width = context.measureText(text).width + 8; + const uqName = columns[colIndex].uniqueName; + + if (display.config.columnWidths[uqName]) { + continue; + } + + const text = row[uqName]; + const width = context.measureText(text).width + 8; // console.log('colName', colName, text, width); columnSizes.putSizeOverride(colIndex, width); // let colName = this.columns[colIndex].uniquePath; @@ -103,6 +114,7 @@ export function countVisibleRealColumns(columnSizes, firstVisibleColumnScrollInd realColumns.push({ ...col, colIndex, + widthNumber, widthPx: `${widthNumber}px`, }); }