diff --git a/packages/datalib/src/GridConfig.ts b/packages/datalib/src/GridConfig.ts
index f94ec0332..ec0f29a42 100644
--- a/packages/datalib/src/GridConfig.ts
+++ b/packages/datalib/src/GridConfig.ts
@@ -1,12 +1,16 @@
import { DisplayColumn } from './GridDisplay';
import { TableInfo } from '@dbgate/types';
-export interface GridConfig {
+export interface GridConfigColumns {
hiddenColumns: string[];
expandedColumns: string[];
addedColumns: string[];
}
+export interface GridConfig extends GridConfigColumns {
+ filters: { [uniqueName: string]: string };
+}
+
export interface GridCache {
tables: { [uniqueName: string]: TableInfo };
refreshTime: number;
@@ -17,6 +21,7 @@ export function createGridConfig(): GridConfig {
hiddenColumns: [],
expandedColumns: [],
addedColumns: [],
+ filters: {},
};
}
diff --git a/packages/datalib/src/GridDisplay.ts b/packages/datalib/src/GridDisplay.ts
index f03e94412..600532b13 100644
--- a/packages/datalib/src/GridDisplay.ts
+++ b/packages/datalib/src/GridDisplay.ts
@@ -1,5 +1,5 @@
import _ from 'lodash';
-import { GridConfig, GridCache } from './GridConfig';
+import { GridConfig, GridCache, GridConfigColumns } from './GridConfig';
import { ForeignKeyInfo, TableInfo, ColumnInfo } from '@dbgate/types';
import { filterName } from './filterName';
import { Select } from '@dbgate/sqltree';
@@ -54,7 +54,7 @@ export abstract class GridDisplay {
});
}
- includeInColumnSet(field: keyof GridConfig, uniqueName: string, isIncluded: boolean) {
+ includeInColumnSet(field: keyof GridConfigColumns, uniqueName: string, isIncluded: boolean) {
if (isIncluded) {
this.setConfig({
...this.config,
@@ -248,13 +248,15 @@ export abstract class GridDisplay {
}
getDisplayColumns(table: TableInfo, parentPath: string[]) {
- return table?.columns
- ?.map(col => this.getDisplayColumn(table, col, parentPath))
- ?.map(col => ({
- ...col,
- isChecked: this.isColumnChecked(col),
- hintColumnName: col.foreignKey ? `hint_${col.uniqueName}` : null,
- }));
+ return (
+ table?.columns
+ ?.map(col => this.getDisplayColumn(table, col, parentPath))
+ ?.map(col => ({
+ ...col,
+ isChecked: this.isColumnChecked(col),
+ hintColumnName: col.foreignKey ? `hint_${col.uniqueName}` : null,
+ })) || []
+ );
}
getColumns(columnFilter) {
@@ -272,4 +274,19 @@ export abstract class GridDisplay {
toggleExpandedColumn(uniqueName: string) {
this.includeInColumnSet('expandedColumns', uniqueName, !this.isExpandedColumn(uniqueName));
}
+
+ getFilter(uniqueName: string) {
+ return this.config.filters[uniqueName];
+ }
+
+ setFilter(uniqueName, value) {
+ this.setConfig({
+ ...this.config,
+ filters: {
+ ...this.config.filters,
+ [uniqueName]: value,
+ },
+ });
+ this.reload();
+ }
}
diff --git a/packages/datalib/src/TableGridDisplay.ts b/packages/datalib/src/TableGridDisplay.ts
index c9a1b3278..bc28f3897 100644
--- a/packages/datalib/src/TableGridDisplay.ts
+++ b/packages/datalib/src/TableGridDisplay.ts
@@ -18,6 +18,7 @@ export class TableGridDisplay extends GridDisplay {
}
createSelect() {
+ if (!this.table.columns) return null;
const orderColumnName = this.table.columns[0].columnName;
const select: Select = {
commandType: 'select',
diff --git a/packages/web/src/datagrid/DataFilterControl.js b/packages/web/src/datagrid/DataFilterControl.js
new file mode 100644
index 000000000..340078bea
--- /dev/null
+++ b/packages/web/src/datagrid/DataFilterControl.js
@@ -0,0 +1,401 @@
+import React from 'react';
+import { DropDownMenuItem, DropDownMenuDivider, showMenu } from '../modals/DropDownMenu';
+import styled from 'styled-components';
+import keycodes from '../utility/keycodes';
+// import { $ } from '../../Utility/jquery';
+// import autobind from 'autobind-decorator';
+// import * as React from 'react';
+
+// import { createMultiLineFilter } from '../../DataLib/FilterTools';
+// import { ModalDialog } from '../Dialogs';
+// import { FilterDialog } from '../Dialogs/FilterDialog';
+// import { FilterMultipleValuesDialog } from '../Dialogs/FilterMultipleValuesDialog';
+// import { IconSpan } from '../Navigation/NavUtils';
+// import { KeyCodes } from '../ReactDataGrid/KeyCodes';
+// import { DropDownMenu, DropDownMenuDivider, DropDownMenuItem, DropDownSubmenuItem } from './DropDownMenu';
+// import { FilterParserType } from '../../SwaggerClients';
+// import { IFilterHolder } from '../CommonControls';
+// import { GrayFilterIcon } from '../Icons';
+
+// export interface IDataFilterControlProps {
+// filterType: FilterParserType;
+// getFilter: Function;
+// setFilter: Function;
+// width: number;
+// onControlKey?: Function;
+// isReadOnly?: boolean;
+// inputElementId?: string;
+// }
+
+const FilterDiv = styled.div`
+ display: flex;
+`;
+const FilterInput = styled.input`
+ flex: 1;
+ width: 10px;
+`;
+const FilterButton = styled.button`
+ color: gray;
+`;
+
+function DropDownContent({ filterType, setFilter, filterMultipleValues, openFilterWindow }) {
+ switch (filterType) {
+ case 'number':
+ return (
+ <>
+ setFilter('')}>Clear Filter
+ filterMultipleValues()}>Filter multiple values
+ openFilterWindow('=')}>Equals...
+ openFilterWindow('<>')}>Does Not Equal...
+ setFilter('NULL')}>Is Null
+ setFilter('NOT NULL')}>Is Not Null
+ openFilterWindow('>')}>Greater Than...
+ openFilterWindow('>=')}>Greater Than Or Equal To...
+ openFilterWindow('<')}>Less Than...
+ openFilterWindow('<=')}>Less Than Or Equal To...
+ >
+ );
+ case 'logical':
+ return (
+ <>
+ setFilter('')}>Clear Filter
+ filterMultipleValues()}>Filter multiple values
+ setFilter('NULL')}>Is Null
+ setFilter('NOT NULL')}>Is Not Null
+ setFilter('TRUE')}>Is True
+ setFilter('FALSE')}>Is False
+ setFilter('TRUE, NULL')}>Is True or NULL
+ setFilter('FALSE, NULL')}>Is False or NULL
+ >
+ );
+ case 'datetime':
+ return (
+ <>
+ setFilter('')}>Clear Filter
+ filterMultipleValues()}>Filter multiple values
+ setFilter('NULL')}>Is Null
+ setFilter('NOT NULL')}>Is Not Null
+
+
+
+ openFilterWindow('<=')}>Before...
+ openFilterWindow('>=')}>After...
+ openFilterWindow('>=;<=')}>Between...
+
+
+
+ setFilter('TOMORROW')}>Tomorrow
+ setFilter('TODAY')}>Today
+ setFilter('YESTERDAY')}>Yesterday
+
+
+
+ setFilter('NEXT WEEK')}>Next Week
+ setFilter('THIS WEEK')}>This Week
+ setFilter('LAST WEEK')}>Last Week
+
+
+
+ setFilter('NEXT MONTH')}>Next Month
+ setFilter('THIS MONTH')}>This Month
+ setFilter('LAST MONTH')}>Last Month
+
+
+
+ setFilter('NEXT YEAR')}>Next Year
+ setFilter('THIS YEAR')}>This Year
+ setFilter('LAST YEAR')}>Last Year
+
+
+
+ {/*
+ setFilter('JAN')}>January
+ setFilter('FEB')}>February
+ setFilter('MAR')}>March
+ setFilter('APR')}>April
+ setFilter('JUN')}>June
+ setFilter('JUL')}>July
+ setFilter('AUG')}>August
+ setFilter('SEP')}>September
+ setFilter('OCT')}>October
+ setFilter('NOV')}>November
+ setFilter('DEC')}>December
+
+
+
+ setFilter('MON')}>Monday
+ setFilter('TUE')}>Tuesday
+ setFilter('WED')}>Wednesday
+ setFilter('THU')}>Thursday
+ setFilter('FRI')}>Friday
+ setFilter('SAT')}>Saturday
+ setFilter('SUN')}>Sunday
+ */}
+ >
+ );
+ case 'string':
+ return (
+ <>
+ setFilter('')}>Clear Filter
+ filterMultipleValues()}>Filter multiple values
+
+ openFilterWindow('=')}>Equals...
+ openFilterWindow('<>')}>Does Not Equal...
+ setFilter('NULL')}>Is Null
+ setFilter('NOT NULL')}>Is Not Null
+ setFilter('EMPTY, NULL')}>Is Empty Or Null
+ setFilter('NOT EMPTY NOT NULL')}>Has Not Empty Value
+
+
+
+ openFilterWindow('+')}>Contains...
+ openFilterWindow('~')}>Does Not Contain...
+ openFilterWindow('^')}>Begins With...
+ openFilterWindow('!^')}>Does Not Begin With...
+ openFilterWindow('$')}>Ends With...
+ openFilterWindow('!$')}>Does Not End With...
+ >
+ );
+ }
+}
+
+export default function DataFilterControl({ isReadOnly = false, filterType, filter, setFilter }) {
+ const setFilterText = filter => {
+ setFilter(filter);
+ editorRef.current.value = filter || '';
+ };
+ const applyFilter = () => {
+ setFilter(editorRef.current.value);
+ };
+ const filterMultipleValues = () => {};
+ const openFilterWindow = operator => {};
+ const buttonRef = React.createRef();
+ const editorRef = React.createRef();
+
+ const handleKeyDown = ev => {
+ if (isReadOnly) return;
+ if (ev.keyCode == keycodes.enter) {
+ applyFilter();
+ }
+ if (ev.keyCode == keycodes.escape) {
+ setFilterText('');
+ }
+ // if (ev.keyCode == KeyCodes.DownArrow || ev.keyCode == KeyCodes.UpArrow) {
+ // if (this.props.onControlKey) this.props.onControlKey(ev.keyCode);
+ // }
+ };
+
+ const handleShowMenu = () => {
+ const rect = buttonRef.current.getBoundingClientRect();
+ showMenu(
+ rect.left,
+ rect.bottom,
+
+ );
+ };
+
+ return (
+
+
+
+
+
+
+ );
+}
+// domEditor: Element;
+
+// @autobind
+// applyFilter() {
+// this.props.setFilter($(this.domEditor).val());
+// }
+
+// @autobind
+// clearFilter() {
+// $(this.domEditor).val('');
+// this.applyFilter();
+// }
+
+// setFilter(value: string) {
+// $(this.domEditor).val(value);
+// this.applyFilter();
+// return false;
+// }
+
+// render() {
+// let dropDownContent = null;
+
+// let filterIconSpan = ;
+// //filterIconSpan = null;
+
+// if (this.props.filterType == 'Number') {
+// dropDownContent =
+// this.setFilter('')}>Clear Filter
+// this.filterMultipleValues()}>Filter multiple values
+// this.openFilterWindow('=')}>Equals...
+// this.openFilterWindow('<>')}>Does Not Equal...
+// this.setFilter('NULL')}>Is Null
+// this.setFilter('NOT NULL')}>Is Not Null
+// this.openFilterWindow('>')}>Greater Than...
+// this.openFilterWindow('>=')}>Greater Than Or Equal To...
+// this.openFilterWindow('<')}>Less Than...
+// this.openFilterWindow('<=')}>Less Than Or Equal To...
+// ;
+// }
+
+// if (this.props.filterType == 'Logical') {
+// dropDownContent =
+// this.setFilter('')}>Clear Filter
+// this.filterMultipleValues()}>Filter multiple values
+// this.setFilter('NULL')}>Is Null
+// this.setFilter('NOT NULL')}>Is Not Null
+// this.setFilter('TRUE')}>Is True
+// this.setFilter('FALSE')}>Is False
+// this.setFilter('TRUE, NULL')}>Is True or NULL
+// this.setFilter('FALSE, NULL')}>Is False or NULL
+// ;
+// }
+
+// if (this.props.filterType == 'DateTime') {
+// dropDownContent =
+// this.setFilter('')}>Clear Filter
+// this.filterMultipleValues()}>Filter multiple values
+// this.setFilter('NULL')}>Is Null
+// this.setFilter('NOT NULL')}>Is Not Null
+
+//
+
+// this.openFilterWindow('<=')}>Before...
+// this.openFilterWindow('>=')}>After...
+// this.openFilterWindow('>=;<=')}>Between...
+
+//
+
+// this.setFilter('TOMORROW')}>Tomorrow
+// this.setFilter('TODAY')}>Today
+// this.setFilter('YESTERDAY')}>Yesterday
+
+//
+
+// this.setFilter('NEXT WEEK')}>Next Week
+// this.setFilter('THIS WEEK')}>This Week
+// this.setFilter('LAST WEEK')}>Last Week
+
+//
+
+// this.setFilter('NEXT MONTH')}>Next Month
+// this.setFilter('THIS MONTH')}>This Month
+// this.setFilter('LAST MONTH')}>Last Month
+
+//
+
+// this.setFilter('NEXT YEAR')}>Next Year
+// this.setFilter('THIS YEAR')}>This Year
+// this.setFilter('LAST YEAR')}>Last Year
+
+//
+
+//
+
+// this.setFilter('JAN')}>January
+// this.setFilter('FEB')}>February
+// this.setFilter('MAR')}>March
+// this.setFilter('APR')}>April
+// this.setFilter('JUN')}>June
+// this.setFilter('JUL')}>July
+// this.setFilter('AUG')}>August
+// this.setFilter('SEP')}>September
+// this.setFilter('OCT')}>October
+// this.setFilter('NOV')}>November
+// this.setFilter('DEC')}>December
+
+//
+
+// this.setFilter('MON')}>Monday
+// this.setFilter('TUE')}>Tuesday
+// this.setFilter('WED')}>Wednesday
+// this.setFilter('THU')}>Thursday
+// this.setFilter('FRI')}>Friday
+// this.setFilter('SAT')}>Saturday
+// this.setFilter('SUN')}>Sunday
+
+//
+// ;
+// }
+
+// if (this.props.filterType == 'String') {
+// dropDownContent =
+// this.setFilter('')}>Clear Filter
+// this.filterMultipleValues()}>Filter multiple values
+
+// this.openFilterWindow('=')}>Equals...
+// this.openFilterWindow('<>')}>Does Not Equal...
+// this.setFilter('NULL')}>Is Null
+// this.setFilter('NOT NULL')}>Is Not Null
+// this.setFilter('EMPTY, NULL')}>Is Empty Or Null
+// this.setFilter('NOT EMPTY NOT NULL')}>Has Not Empty Value
+
+//
+
+// this.openFilterWindow('+')}>Contains...
+// this.openFilterWindow('~')}>Does Not Contain...
+// this.openFilterWindow('^')}>Begins With...
+// this.openFilterWindow('!^')}>Does Not Begin With...
+// this.openFilterWindow('$')}>Ends With...
+// this.openFilterWindow('!$')}>Does Not End With...
+// ;
+// }
+
+// if (this.props.isReadOnly) {
+// dropDownContent = ;
+// }
+
+// return
+// this.setDomEditor(x)} onKeyDown={this.editorKeyDown} placeholder='Search' >
+
+// {dropDownContent}
+//
;
+// }
+
+// async filterMultipleValues() {
+// let result = await ModalDialog.run();
+// if (!result) return;
+// let { mode, text } = result;
+// let filter = createMultiLineFilter(mode, text);
+// this.setFilter(filter);
+// }
+
+// openFilterWindow(selectedOperator: string) {
+// FilterDialog.runFilter(this, this.props.filterType, selectedOperator);
+// return false;
+// }
+
+// setDomEditor(editor) {
+// this.domEditor = editor;
+// $(editor).val(this.props.getFilter());
+// }
+
+// @autobind
+// editorKeyDown(ev) {
+// if (this.props.isReadOnly) return;
+// if (ev.keyCode == KeyCodes.Enter) {
+// this.applyFilter();
+// }
+// if (ev.keyCode == KeyCodes.Escape) {
+// this.clearFilter();
+// }
+// if (ev.keyCode == KeyCodes.DownArrow || ev.keyCode == KeyCodes.UpArrow) {
+// if (this.props.onControlKey) this.props.onControlKey(ev.keyCode);
+// }
+// }
+
+// focus() {
+// $(this.domEditor).focus();
+// }
+// }
diff --git a/packages/web/src/datagrid/DataGridCore.js b/packages/web/src/datagrid/DataGridCore.js
index 14969ae16..7e1614890 100644
--- a/packages/web/src/datagrid/DataGridCore.js
+++ b/packages/web/src/datagrid/DataGridCore.js
@@ -7,6 +7,7 @@ import useDimensions from '../utility/useDimensions';
import { SeriesSizes } from './SeriesSizes';
import axios from '../utility/axios';
import ColumnLabel from './ColumnLabel';
+import DataFilterControl from './DataFilterControl';
const GridContainer = styled.div`
position: absolute;
@@ -40,10 +41,10 @@ const TableHeaderRow = styled.tr`
const TableBodyRow = styled.tr`
// height: 35px;
background-color: #ffffff;
- &:nth-child(6n + 4) {
+ &:nth-child(6n + 3) {
background-color: #ebebeb;
}
- &:nth-child(6n + 7) {
+ &:nth-child(6n + 6) {
background-color: #ebf5ff;
}
`;
@@ -56,6 +57,12 @@ const TableHeaderCell = styled.td`
background-color: #f6f7f9;
overflow: hidden;
`;
+const TableFilterCell = styled.td`
+ text-align: left;
+ overflow: hidden;
+ margin: 0;
+ padding: 0;
+`;
const TableBodyCell = styled.td`
font-weight: normal;
border: 1px solid #c0c0c0;
@@ -308,6 +315,20 @@ export default function DataGridCore(props) {
))}
+
+ {realColumns.map(col => (
+
+ display.setFilter(col.uniqueName, value)}
+ />
+
+ ))}
+
{loadedRows
diff --git a/packages/web/src/modals/DropDownMenu.js b/packages/web/src/modals/DropDownMenu.js
index eb126981b..b3651f2a5 100644
--- a/packages/web/src/modals/DropDownMenu.js
+++ b/packages/web/src/modals/DropDownMenu.js
@@ -39,6 +39,12 @@ const StyledLink = styled.a`
}
`;
+export const DropDownMenuDivider = styled.li`
+ margin: 9px 0px 9px 0px;
+ border-top: 1px solid #f2f2f2;
+ border-bottom: 1px solid #fff;
+`;
+
export function DropDownMenuItem({ children, keyText = undefined, onClick }) {
const handleMouseEnter = () => {
// if (this.context.parentMenu) this.context.parentMenu.closeSubmenu();
@@ -90,7 +96,7 @@ export function DropDownMenuItem({ children, keyText = undefined, onClick }) {
// // }
// export function DropDownMenuDivider(props: {}) {
-// return ;
+// return ;
// }
// export class DropDownSubmenuItem extends React.Component {
diff --git a/packages/web/src/utility/keycodes.js b/packages/web/src/utility/keycodes.js
new file mode 100644
index 000000000..db92af3b0
--- /dev/null
+++ b/packages/web/src/utility/keycodes.js
@@ -0,0 +1,99 @@
+export default {
+ backspace: 8,
+ tab: 9,
+ enter: 13,
+ shift: 16,
+ ctrl: 17,
+ alt: 18,
+ pauseBreak: 19,
+ capsLock: 20,
+ escape: 27,
+ pageUp: 33,
+ pageDown: 34,
+ end: 35,
+ home: 36,
+ leftArrow: 37,
+ ppArrow: 38,
+ rightArrow: 39,
+ downArrow: 40,
+ insert: 45,
+ delete: 46,
+ n0: 48,
+ n1: 49,
+ n2: 50,
+ n3: 51,
+ n4: 52,
+ n5: 53,
+ n6: 54,
+ n7: 55,
+ n8: 56,
+ n9: 57,
+ a: 65,
+ b: 66,
+ c: 67,
+ d: 68,
+ e: 69,
+ f: 70,
+ g: 71,
+ h: 72,
+ i: 73,
+ j: 74,
+ k: 75,
+ l: 76,
+ m: 77,
+ n: 78,
+ o: 79,
+ p: 80,
+ q: 81,
+ r: 82,
+ s: 83,
+ t: 84,
+ u: 85,
+ v: 86,
+ w: 87,
+ x: 88,
+ y: 89,
+ z: 90,
+ leftWindowKey: 91,
+ rightWindowKey: 92,
+ selectKey: 93,
+ numPad0: 96,
+ numPad1: 97,
+ numPad2: 98,
+ numPad3: 99,
+ numPad4: 100,
+ numPad5: 101,
+ numPad6: 102,
+ numPad7: 103,
+ numPad8: 104,
+ numPad9: 105,
+ multiply: 106,
+ add: 107,
+ subtract: 109,
+ decimalPoint: 110,
+ divide: 111,
+ f1: 112,
+ f2: 113,
+ f3: 114,
+ f4: 115,
+ f5: 116,
+ f6: 117,
+ f7: 118,
+ f8: 119,
+ f9: 120,
+ f10: 121,
+ f12: 123,
+ numLock: 144,
+ scrollLock: 145,
+ semiColon: 186,
+ equalSign: 187,
+ comma: 188,
+ dash: 189,
+ period: 190,
+ forwardSlash: 191,
+ graveAccent: 192,
+ openBracket: 219,
+ backSlash: 220,
+ closeBracket: 221,
+ singleQuote: 222,
+};