diff --git a/package.json b/package.json
index e7152eeba..cb6d3247f 100644
--- a/package.json
+++ b/package.json
@@ -8,8 +8,11 @@
"start:api": "yarn workspace @dbgate/api start",
"start:web": "yarn workspace @dbgate/web start",
"start:sqltree": "yarn workspace @dbgate/sqltree start",
+ "start:datalib": "yarn workspace @dbgate/datalib start",
"start": "concurrently --kill-others-on-fail \"yarn start:api\" \"yarn start:web\"",
+ "lib": "concurrently --kill-others-on-fail \"yarn start:sqltree\" \"yarn start:datalib\"",
+
"ts:api": "yarn workspace @dbgate/api ts",
"ts:web": "yarn workspace @dbgate/web ts",
"ts": "yarn ts:api && yarn ts:web"
diff --git a/packages/datalib/src/GridConfig.ts b/packages/datalib/src/GridConfig.ts
index dc569cd49..fe311711f 100644
--- a/packages/datalib/src/GridConfig.ts
+++ b/packages/datalib/src/GridConfig.ts
@@ -1,4 +1,4 @@
export default interface GridConfig {
- hiddenColumns: number[];
+ hiddenColumns: string[];
}
diff --git a/packages/datalib/src/GridDisplay.ts b/packages/datalib/src/GridDisplay.ts
index f96832626..1f7203af1 100644
--- a/packages/datalib/src/GridDisplay.ts
+++ b/packages/datalib/src/GridDisplay.ts
@@ -1,14 +1,38 @@
-import GridConfig from "./GridConfig";
+import _ from 'lodash';
+import GridConfig from './GridConfig';
+import { ForeignKeyInfo } from '@dbgate/types';
export interface DisplayColumn {
columnName: string;
+ headerText: string;
+ uniqueName: string;
+ uniquePath: string[];
+ notNull: boolean;
+ autoIncrement: boolean;
+ isPrimaryKey: boolean;
+ foreignKey: ForeignKeyInfo;
+ isChecked: boolean;
}
export default abstract class GridDisplay {
- constructor(
- public config: GridConfig,
- protected setConfig: (configh: GridConfig) => void
- ) {}
+ constructor(public config: GridConfig, protected setConfig: (config: GridConfig) => void) {}
abstract getPageQuery(offset: number, count: number): string;
columns: DisplayColumn[];
+ setColumnVisibility(uniqueName, isVisible) {
+ if (isVisible) {
+ this.setConfig({
+ ...this.config,
+ hiddenColumns: (this.config.hiddenColumns || []).filter(x => x != uniqueName),
+ });
+ } else {
+ this.setConfig({
+ ...this.config,
+ hiddenColumns: [...(this.config.hiddenColumns || []), uniqueName],
+ });
+ }
+ }
+
+ get hiddenColumnIndexes() {
+ return (this.config.hiddenColumns || []).map(x => _.findIndex(this.columns, y => y.uniqueName == x));
+ }
}
diff --git a/packages/datalib/src/TableGridDisplay.ts b/packages/datalib/src/TableGridDisplay.ts
index 840566b9f..6aa58586f 100644
--- a/packages/datalib/src/TableGridDisplay.ts
+++ b/packages/datalib/src/TableGridDisplay.ts
@@ -8,10 +8,19 @@ export default class TableGridDisplay extends GridDisplay {
public table: TableInfo,
public driver: EngineDriver,
config: GridConfig,
- setConfig: (configh: GridConfig) => void
+ setConfig: (config: GridConfig) => void
) {
super(config, setConfig);
- this.columns = table.columns;
+ this.columns = table.columns.map(col => ({
+ ...col,
+ headerText: col.columnName,
+ uniqueName: col.columnName,
+ uniquePath: [col.columnName],
+ isPrimaryKey: table.primaryKey && !!table.primaryKey.columns.find(x => x.columnName == col.columnName),
+ foreignKey:
+ table.foreignKeys && table.foreignKeys.find(fk => fk.columns.find(x => x.columnName == col.columnName)),
+ isChecked: !(config.hiddenColumns && config.hiddenColumns.includes(col.columnName)),
+ }));
}
createSelect() {
@@ -19,7 +28,7 @@ export default class TableGridDisplay extends GridDisplay {
const select: Select = {
commandType: 'select',
from: { name: this.table },
- columns: this.table.columns.map(col => ({ exprType: 'column', ...col })),
+ columns: this.table.columns.map(col => ({ exprType: 'column', alias: col.columnName, ...col })),
orderBy: [
{
exprType: 'column',
diff --git a/packages/datalib/tsconfig.json b/packages/datalib/tsconfig.json
index 4dfd0a5f7..0d17d2171 100644
--- a/packages/datalib/tsconfig.json
+++ b/packages/datalib/tsconfig.json
@@ -4,7 +4,9 @@
"module": "commonjs",
"declaration": true,
"skipLibCheck": true,
- "outDir": "lib"
+ "outDir": "lib",
+ "esModuleInterop": true,
+ "preserveWatchOutput": true
},
"include": [
"src/**/*"
diff --git a/packages/sqltree/src/dumpSqlCommand.ts b/packages/sqltree/src/dumpSqlCommand.ts
index ae8d19e03..d1a3b2a37 100644
--- a/packages/sqltree/src/dumpSqlCommand.ts
+++ b/packages/sqltree/src/dumpSqlCommand.ts
@@ -19,7 +19,7 @@ export function dumpSqlSelect(dmp: SqlDumper, select: Select) {
dmp.put('&>&n');
dmp.putCollection(',&n', select.columns, fld => {
dumpSqlExpression(dmp, fld);
- if (fld.alias) dmp.put(' %i', fld.alias);
+ if (fld.alias) dmp.put(' ^as %i', fld.alias);
});
dmp.put('&n&<');
}
diff --git a/packages/sqltree/tsconfig.json b/packages/sqltree/tsconfig.json
index 4dfd0a5f7..9792007a6 100644
--- a/packages/sqltree/tsconfig.json
+++ b/packages/sqltree/tsconfig.json
@@ -4,7 +4,8 @@
"module": "commonjs",
"declaration": true,
"skipLibCheck": true,
- "outDir": "lib"
+ "outDir": "lib",
+ "preserveWatchOutput": true
},
"include": [
"src/**/*"
diff --git a/packages/web/src/datagrid/ColumnLabel.js b/packages/web/src/datagrid/ColumnLabel.js
new file mode 100644
index 000000000..baf6d81ee
--- /dev/null
+++ b/packages/web/src/datagrid/ColumnLabel.js
@@ -0,0 +1,20 @@
+//@ts-nocheck
+
+import React from 'react';
+import styled from 'styled-components';
+import { SequenceIcon } from '../icons';
+
+const Label = styled.span`
+ font-weight: ${props => (props.notNull ? 'bold' : 'normal')};
+`;
+
+/** @param column {import('@dbgate/datalib').DisplayColumn|import('@dbgate/types').ColumnInfo} */
+export default function ColumnLabel(column) {
+ let Icon = null;
+ if (column.autoIncrement) Icon = SequenceIcon;
+ return (
+
+ );
+}
diff --git a/packages/web/src/datagrid/ColumnManager.js b/packages/web/src/datagrid/ColumnManager.js
new file mode 100644
index 000000000..4dc1e521a
--- /dev/null
+++ b/packages/web/src/datagrid/ColumnManager.js
@@ -0,0 +1,31 @@
+import React from 'react';
+import styled from 'styled-components';
+import ColumnLabel from './ColumnLabel';
+
+const Row = styled.div`
+ margin-left: 5px;
+ margin-right: 5px;
+ cursor: pointer;
+ &:hover {
+ background-color: lightblue;
+ }
+`;
+
+/** @param props {import('./types').DataGridProps} */
+export default function ColumnManager(props) {
+ const { display } = props;
+ return (
+
+ {display.columns.map(item => (
+
+ display.setColumnVisibility(item.uniqueName, !item.isChecked)}
+ >
+
+
+ ))}
+
+ );
+}
diff --git a/packages/web/src/datagrid/DataGrid.js b/packages/web/src/datagrid/DataGrid.js
index 4b5d8dd4e..e3cfe73a2 100644
--- a/packages/web/src/datagrid/DataGrid.js
+++ b/packages/web/src/datagrid/DataGrid.js
@@ -1,327 +1,37 @@
import React from 'react';
-import useFetch from '../utility/useFetch';
import styled from 'styled-components';
-import theme from '../theme';
-import { HorizontalScrollBar, VerticalScrollBar } from './ScrollBars';
-import useDimensions from '../utility/useDimensions';
-import { SeriesSizes } from './SeriesSizes';
-import axios from '../utility/axios';
+import DataGridCore from './DataGridCore';
+import ColumnManager from './ColumnManager';
-const GridContainer = styled.div`
+const MainContainer = styled.div`
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
+ display: flex;
`;
-const Table = styled.table`
- position: absolute;
- left: 0;
- top: 0;
- bottom: 20px;
- right: 20px;
- overflow: scroll;
- border-collapse: collapse;
-`;
-const TableHead = styled.thead`
- // display: block;
- // width: 300px;
-`;
-const TableBody = styled.tbody`
- // display: block;
- // overflow: auto;
- // height: 100px;
-`;
-const TableHeaderRow = styled.tr`
- // height: 35px;
-`;
-const TableBodyRow = styled.tr`
- // height: 35px;
- background-color: #ffffff;
- &:nth-child(6n + 4) {
- background-color: #ebebeb;
- }
- &:nth-child(6n + 7) {
- background-color: #ebf5ff;
- }
-`;
-const TableHeaderCell = styled.td`
- font-weight: bold;
- border: 1px solid #c0c0c0;
- // border-collapse: collapse;
- text-align: left;
- padding: 2px;
- background-color: #f6f7f9;
- overflow: hidden;
-`;
-const TableBodyCell = styled.td`
- font-weight: normal;
- border: 1px solid #c0c0c0;
- // border-collapse: collapse;
- padding: 2px;
- white-space: nowrap;
- overflow: hidden;
+const ColumnManagerContainer = styled.div`
+ background-color: white;
+ padding-top: 5px;
`;
-/**
- * @param {object} props
- * @param {number} props.conid
- * @param {string} props.database
- * @param {import('@dbgate/datalib').GridDisplay} props.display
- */
+const DataGridContainer = styled.div`
+ position: relative;
+ flex-grow: 1;
+`;
+
+/** @param props {import('./types').DataGridProps} */
export default function DataGrid(props) {
- const { conid, database, display } = props;
- const columns = display.columns;
-
- // console.log(`GRID, conid=${conid}, database=${database}, sql=${sql}`);
- const [loadProps, setLoadProps] = React.useState({
- isLoading: false,
- loadedRows: [],
- isLoadedAll: false,
- loadedTime: new Date().getTime(),
- });
- const { isLoading, loadedRows, isLoadedAll, loadedTime } = loadProps;
-
- const loadedTimeRef = React.useRef(0);
-
- const loadNextData = async () => {
- if (isLoading) return;
- setLoadProps({
- ...loadProps,
- isLoading: true,
- });
- const loadStart = new Date().getTime();
- loadedTimeRef.current = loadStart;
-
- const sql = display.getPageQuery(loadedRows.length, 100);
-
- let response = await axios.request({
- url: 'database-connections/query-data',
- method: 'post',
- params: {
- conid,
- database,
- },
- data: { sql },
- });
- if (loadedTimeRef.current !== loadStart) {
- // new load was dispatched
- return;
- }
- // if (!_.isArray(nextRows)) {
- // console.log('Error loading data from server', nextRows);
- // nextRows = [];
- // }
- const { rows: nextRows } = response.data;
- console.log('nextRows',nextRows)
- const loadedInfo = {
- loadedRows: [...loadedRows, ...nextRows],
- loadedTime,
- isLoadedAll: nextRows.length === 0,
- };
- setLoadProps({
- ...loadProps,
- isLoading: false,
- ...loadedInfo,
- });
- };
-
- // const data = useFetch({
- // url: 'database-connections/query-data',
- // method: 'post',
- // params: {
- // conid,
- // database,
- // },
- // data: { sql },
- // });
- // const { rows, columns } = data || {};
- const [firstVisibleRowScrollIndex, setFirstVisibleRowScrollIndex] = React.useState(0);
- const [firstVisibleColumnScrollIndex, setFirstVisibleColumnScrollIndex] = React.useState(0);
-
- const [headerRowRef, { height: rowHeight }] = useDimensions();
- const [tableBodyRef] = useDimensions();
- const [containerRef, { height: containerHeight, width: containerWidth }] = useDimensions();
-
- const columnSizes = React.useMemo(() => countColumnSizes(), [loadedRows, containerWidth]);
-
- console.log('containerWidth', containerWidth);
-
- const gridScrollAreaHeight = containerHeight - 2 * rowHeight;
- const gridScrollAreaWidth = containerWidth - columnSizes.frozenSize;
-
- const visibleRowCountUpperBound = Math.ceil(gridScrollAreaHeight / Math.floor(rowHeight));
- const visibleRowCountLowerBound = Math.floor(gridScrollAreaHeight / Math.ceil(rowHeight));
- // const visibleRowCountUpperBound = 20;
- // const visibleRowCountLowerBound = 20;
-
- React.useEffect(() => {
- if (!isLoadedAll && firstVisibleRowScrollIndex + visibleRowCountUpperBound >= loadedRows.length) {
- loadNextData();
- }
- });
-
- if (!loadedRows || !columns) return null;
- const rowCountNewIncluded = loadedRows.length;
-
- const handleRowScroll = value => {
- setFirstVisibleRowScrollIndex(value);
- };
-
- const handleColumnScroll = value => {
- setFirstVisibleColumnScrollIndex(value);
- };
-
- function countColumnSizes() {
- let canvas = document.createElement('canvas');
- let context = canvas.getContext('2d');
-
- //return this.context.measureText(txt).width;
- const columnSizes = new SeriesSizes();
- if (!loadedRows || !columns) return columnSizes;
-
- console.log('countColumnSizes', loadedRows.length, containerWidth);
-
- columnSizes.maxSize = (containerWidth * 2) / 3;
- columnSizes.count = columns.length;
-
- // columnSizes.setExtraordinaryIndexes(this.getHiddenColumnIndexes(), this.getFrozenColumnIndexes());
- columnSizes.setExtraordinaryIndexes([], []);
-
- for (let colIndex = 0; colIndex < columns.length; colIndex++) {
- //this.columnSizes.PutSizeOverride(col, this.columns[col].Name.length * 8);
- let column = columns[colIndex];
-
- // 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.columnName;
- let headerWidth = context.measureText(text).width + 32;
-
- // if (column.columnClientObject != null && column.columnClientObject.icon != null) headerWidth += 16;
- // if (this.getFilterOnColumn(column.uniquePath)) headerWidth += 16;
- // if (this.getSortOrder(column.uniquePath)) headerWidth += 16;
-
- columnSizes.putSizeOverride(colIndex, headerWidth);
- }
-
- // let headerWidth = this.rowHeaderWidthDefault;
- // if (this.rowCount) headerWidth = context.measureText(this.rowCount.toString()).width + 8;
- // this.rowHeaderWidth = this.rowHeaderWidthDefault;
- // if (headerWidth > this.rowHeaderWidth) this.rowHeaderWidth = headerWidth;
-
- context.font = '14px Helvetica';
- for (let row of loadedRows) {
- for (let colIndex = 0; colIndex < columns.length; colIndex++) {
- let colName = columns[colIndex].columnName;
- let text = row[colName];
- let width = context.measureText(text).width + 8;
- // console.log('colName', colName, text, width);
- columnSizes.putSizeOverride(colIndex, width);
- // let colName = this.columns[colIndex].uniquePath;
- // let text: string = row[colName].gridText;
- // let width = context.measureText(text).width + 8;
- // if (row[colName].dataPrefix) width += context.measureText(row[colName].dataPrefix).width + 3;
- // this.columnSizes.putSizeOverride(colIndex, width);
- }
- }
-
- // for (let modelIndex = 0; modelIndex < this.columns.length; modelIndex++) {
- // let width = getHashValue(this.widthHashPrefix + this.columns[modelIndex].uniquePath);
- // if (width) this.columnSizes.putSizeOverride(modelIndex, _.toNumber(width), true);
- // }
-
- columnSizes.buildIndex();
- return columnSizes;
- }
-
- // console.log('visibleRowCountUpperBound', visibleRowCountUpperBound);
- // console.log('gridScrollAreaHeight', gridScrollAreaHeight);
- // console.log('containerHeight', containerHeight);
-
- const visibleColumnCount = columnSizes.getVisibleScrollCount(firstVisibleColumnScrollIndex, gridScrollAreaWidth);
- console.log('visibleColumnCount', visibleColumnCount);
-
- const visibleRealColumnIndexes = [];
- const modelIndexes = {};
- /** @type {(import('@dbgate/datalib').DisplayColumn & {widthPx: string})[]} */
- const realColumns = [];
-
- // frozen columns
- for (let colIndex = 0; colIndex < columnSizes.frozenCount; colIndex++) {
- visibleRealColumnIndexes.push(colIndex);
- }
- // scroll columns
- for (
- let colIndex = firstVisibleColumnScrollIndex;
- colIndex < firstVisibleColumnScrollIndex + visibleColumnCount;
- colIndex++
- ) {
- visibleRealColumnIndexes.push(colIndex + columnSizes.frozenCount);
- }
-
- // real columns
- for (let colIndex of visibleRealColumnIndexes) {
- let modelColumnIndex = columnSizes.realToModel(colIndex);
- modelIndexes[colIndex] = modelColumnIndex;
-
- let col = columns[modelColumnIndex];
- if (!col) continue;
- const widthNumber = columnSizes.getSizeByRealIndex(colIndex);
- realColumns.push({
- ...col,
- widthPx: `${widthNumber}px`,
- });
- }
-
- console.log('visibleRealColumnIndexes', visibleRealColumnIndexes);
-
return (
-
-
-
-
- {realColumns.map(col => (
-
- {col.columnName}
-
- ))}
-
-
-
- {loadedRows
- .slice(firstVisibleRowScrollIndex, firstVisibleRowScrollIndex + visibleRowCountUpperBound)
- .map((row, index) => (
-
- {realColumns.map(col => (
-
- {row[col.columnName]}
-
- ))}
-
- ))}
-
-
-
-
-
+
+
+
+
+
+
+
+
);
}
diff --git a/packages/web/src/datagrid/DataGridCore.js b/packages/web/src/datagrid/DataGridCore.js
new file mode 100644
index 000000000..471074bb5
--- /dev/null
+++ b/packages/web/src/datagrid/DataGridCore.js
@@ -0,0 +1,325 @@
+import React from 'react';
+import useFetch from '../utility/useFetch';
+import styled from 'styled-components';
+import theme from '../theme';
+import { HorizontalScrollBar, VerticalScrollBar } from './ScrollBars';
+import useDimensions from '../utility/useDimensions';
+import { SeriesSizes } from './SeriesSizes';
+import axios from '../utility/axios';
+import ColumnLabel from './ColumnLabel';
+
+const GridContainer = styled.div`
+ position: absolute;
+ left: 0;
+ top: 0;
+ right: 0;
+ bottom: 0;
+`;
+
+const Table = styled.table`
+ position: absolute;
+ left: 0;
+ top: 0;
+ bottom: 20px;
+ right: 20px;
+ overflow: scroll;
+ border-collapse: collapse;
+`;
+const TableHead = styled.thead`
+ // display: block;
+ // width: 300px;
+`;
+const TableBody = styled.tbody`
+ // display: block;
+ // overflow: auto;
+ // height: 100px;
+`;
+const TableHeaderRow = styled.tr`
+ // height: 35px;
+`;
+const TableBodyRow = styled.tr`
+ // height: 35px;
+ background-color: #ffffff;
+ &:nth-child(6n + 4) {
+ background-color: #ebebeb;
+ }
+ &:nth-child(6n + 7) {
+ background-color: #ebf5ff;
+ }
+`;
+const TableHeaderCell = styled.td`
+ // font-weight: bold;
+ border: 1px solid #c0c0c0;
+ // border-collapse: collapse;
+ text-align: left;
+ padding: 2px;
+ background-color: #f6f7f9;
+ overflow: hidden;
+`;
+const TableBodyCell = styled.td`
+ font-weight: normal;
+ border: 1px solid #c0c0c0;
+ // border-collapse: collapse;
+ padding: 2px;
+ white-space: nowrap;
+ overflow: hidden;
+`;
+
+/** @param props {import('./types').DataGridProps} */
+export default function DataGridCore(props) {
+ const { conid, database, display } = props;
+ const columns = display.columns;
+
+ // console.log(`GRID, conid=${conid}, database=${database}, sql=${sql}`);
+ const [loadProps, setLoadProps] = React.useState({
+ isLoading: false,
+ loadedRows: [],
+ isLoadedAll: false,
+ loadedTime: new Date().getTime(),
+ });
+ const { isLoading, loadedRows, isLoadedAll, loadedTime } = loadProps;
+
+ const loadedTimeRef = React.useRef(0);
+
+ const loadNextData = async () => {
+ if (isLoading) return;
+ setLoadProps({
+ ...loadProps,
+ isLoading: true,
+ });
+ const loadStart = new Date().getTime();
+ loadedTimeRef.current = loadStart;
+
+ const sql = display.getPageQuery(loadedRows.length, 100);
+
+ let response = await axios.request({
+ url: 'database-connections/query-data',
+ method: 'post',
+ params: {
+ conid,
+ database,
+ },
+ data: { sql },
+ });
+ if (loadedTimeRef.current !== loadStart) {
+ // new load was dispatched
+ return;
+ }
+ // if (!_.isArray(nextRows)) {
+ // console.log('Error loading data from server', nextRows);
+ // nextRows = [];
+ // }
+ const { rows: nextRows } = response.data;
+ console.log('nextRows', nextRows);
+ const loadedInfo = {
+ loadedRows: [...loadedRows, ...nextRows],
+ loadedTime,
+ isLoadedAll: nextRows.length === 0,
+ };
+ setLoadProps({
+ ...loadProps,
+ isLoading: false,
+ ...loadedInfo,
+ });
+ };
+
+ // const data = useFetch({
+ // url: 'database-connections/query-data',
+ // method: 'post',
+ // params: {
+ // conid,
+ // database,
+ // },
+ // data: { sql },
+ // });
+ // const { rows, columns } = data || {};
+ const [firstVisibleRowScrollIndex, setFirstVisibleRowScrollIndex] = React.useState(0);
+ const [firstVisibleColumnScrollIndex, setFirstVisibleColumnScrollIndex] = React.useState(0);
+
+ const [headerRowRef, { height: rowHeight }] = useDimensions();
+ const [tableBodyRef] = useDimensions();
+ const [containerRef, { height: containerHeight, width: containerWidth }] = useDimensions();
+
+ const columnSizes = React.useMemo(() => countColumnSizes(), [loadedRows, containerWidth, display]);
+
+ console.log('containerWidth', containerWidth);
+
+ const gridScrollAreaHeight = containerHeight - 2 * rowHeight;
+ const gridScrollAreaWidth = containerWidth - columnSizes.frozenSize;
+
+ const visibleRowCountUpperBound = Math.ceil(gridScrollAreaHeight / Math.floor(rowHeight));
+ const visibleRowCountLowerBound = Math.floor(gridScrollAreaHeight / Math.ceil(rowHeight));
+ // const visibleRowCountUpperBound = 20;
+ // const visibleRowCountLowerBound = 20;
+
+ React.useEffect(() => {
+ if (!isLoadedAll && firstVisibleRowScrollIndex + visibleRowCountUpperBound >= loadedRows.length) {
+ loadNextData();
+ }
+ });
+
+ if (!loadedRows || !columns) return null;
+ const rowCountNewIncluded = loadedRows.length;
+
+ const handleRowScroll = value => {
+ setFirstVisibleRowScrollIndex(value);
+ };
+
+ const handleColumnScroll = value => {
+ setFirstVisibleColumnScrollIndex(value);
+ };
+
+ function countColumnSizes() {
+ let canvas = document.createElement('canvas');
+ let context = canvas.getContext('2d');
+
+ //return this.context.measureText(txt).width;
+ const columnSizes = new SeriesSizes();
+ if (!loadedRows || !columns) return columnSizes;
+
+ console.log('countColumnSizes', loadedRows.length, containerWidth);
+
+ columnSizes.maxSize = (containerWidth * 2) / 3;
+ columnSizes.count = columns.length;
+
+ // columnSizes.setExtraordinaryIndexes(this.getHiddenColumnIndexes(), this.getFrozenColumnIndexes());
+ console.log('display.hiddenColumnIndexes', display.hiddenColumnIndexes)
+
+ columnSizes.setExtraordinaryIndexes(display.hiddenColumnIndexes, []);
+
+ for (let colIndex = 0; colIndex < columns.length; colIndex++) {
+ //this.columnSizes.PutSizeOverride(col, this.columns[col].Name.length * 8);
+ const column = columns[colIndex];
+
+ // 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 + 32;
+
+ // if (column.columnClientObject != null && column.columnClientObject.icon != null) headerWidth += 16;
+ // if (this.getFilterOnColumn(column.uniquePath)) headerWidth += 16;
+ // if (this.getSortOrder(column.uniquePath)) headerWidth += 16;
+
+ columnSizes.putSizeOverride(colIndex, headerWidth);
+ }
+
+ // let headerWidth = this.rowHeaderWidthDefault;
+ // if (this.rowCount) headerWidth = context.measureText(this.rowCount.toString()).width + 8;
+ // this.rowHeaderWidth = this.rowHeaderWidthDefault;
+ // if (headerWidth > this.rowHeaderWidth) this.rowHeaderWidth = headerWidth;
+
+ context.font = '14px Helvetica';
+ for (let row of loadedRows) {
+ for (let colIndex = 0; colIndex < columns.length; colIndex++) {
+ let uqName = columns[colIndex].uniqueName;
+ let text = row[uqName];
+ let width = context.measureText(text).width + 8;
+ // console.log('colName', colName, text, width);
+ columnSizes.putSizeOverride(colIndex, width);
+ // let colName = this.columns[colIndex].uniquePath;
+ // let text: string = row[colName].gridText;
+ // let width = context.measureText(text).width + 8;
+ // if (row[colName].dataPrefix) width += context.measureText(row[colName].dataPrefix).width + 3;
+ // this.columnSizes.putSizeOverride(colIndex, width);
+ }
+ }
+
+ // for (let modelIndex = 0; modelIndex < this.columns.length; modelIndex++) {
+ // let width = getHashValue(this.widthHashPrefix + this.columns[modelIndex].uniquePath);
+ // if (width) this.columnSizes.putSizeOverride(modelIndex, _.toNumber(width), true);
+ // }
+
+ columnSizes.buildIndex();
+ return columnSizes;
+ }
+
+ // console.log('visibleRowCountUpperBound', visibleRowCountUpperBound);
+ // console.log('gridScrollAreaHeight', gridScrollAreaHeight);
+ // console.log('containerHeight', containerHeight);
+
+ const visibleColumnCount = columnSizes.getVisibleScrollCount(firstVisibleColumnScrollIndex, gridScrollAreaWidth);
+ console.log('visibleColumnCount', visibleColumnCount);
+
+ const visibleRealColumnIndexes = [];
+ const modelIndexes = {};
+ /** @type {(import('@dbgate/datalib').DisplayColumn & {widthPx: string})[]} */
+ const realColumns = [];
+
+ // frozen columns
+ for (let colIndex = 0; colIndex < columnSizes.frozenCount; colIndex++) {
+ visibleRealColumnIndexes.push(colIndex);
+ }
+ // scroll columns
+ for (
+ let colIndex = firstVisibleColumnScrollIndex;
+ colIndex < firstVisibleColumnScrollIndex + visibleColumnCount;
+ colIndex++
+ ) {
+ visibleRealColumnIndexes.push(colIndex + columnSizes.frozenCount);
+ }
+
+ // real columns
+ for (let colIndex of visibleRealColumnIndexes) {
+ let modelColumnIndex = columnSizes.realToModel(colIndex);
+ modelIndexes[colIndex] = modelColumnIndex;
+
+ let col = columns[modelColumnIndex];
+ if (!col) continue;
+ const widthNumber = columnSizes.getSizeByRealIndex(colIndex);
+ realColumns.push({
+ ...col,
+ widthPx: `${widthNumber}px`,
+ });
+ }
+
+ console.log('visibleRealColumnIndexes', visibleRealColumnIndexes);
+
+ return (
+
+
+
+
+ {realColumns.map(col => (
+
+
+
+ ))}
+
+
+
+ {loadedRows
+ .slice(firstVisibleRowScrollIndex, firstVisibleRowScrollIndex + visibleRowCountUpperBound)
+ .map((row, index) => (
+
+ {realColumns.map(col => (
+
+ {row[col.columnName]}
+
+ ))}
+
+ ))}
+
+
+
+
+
+ );
+}
diff --git a/packages/web/src/datagrid/SeriesSizes.js b/packages/web/src/datagrid/SeriesSizes.js
index df96d5e38..5cc319161 100644
--- a/packages/web/src/datagrid/SeriesSizes.js
+++ b/packages/web/src/datagrid/SeriesSizes.js
@@ -219,12 +219,12 @@ export class SeriesSizes {
let index = firstVisibleIndex;
let count = 0;
while (res < viewportSize && index <= this.scrollCount) {
- console.log('this.getSizeByScrollIndex(index)', this.getSizeByScrollIndex(index));
+ // console.log('this.getSizeByScrollIndex(index)', this.getSizeByScrollIndex(index));
res += this.getSizeByScrollIndex(index);
index++;
count++;
}
- console.log('getVisibleScrollCount', firstVisibleIndex, viewportSize, count);
+ // console.log('getVisibleScrollCount', firstVisibleIndex, viewportSize, count);
return count;
}
getVisibleScrollCountReversed(lastVisibleIndex, viewportSize) {
diff --git a/packages/web/src/datagrid/types.ts b/packages/web/src/datagrid/types.ts
new file mode 100644
index 000000000..8b22c2514
--- /dev/null
+++ b/packages/web/src/datagrid/types.ts
@@ -0,0 +1,7 @@
+import { GridDisplay } from '@dbgate/datalib';
+
+export interface DataGridProps {
+ conid: number;
+ database: string;
+ display: GridDisplay;
+}