diff --git a/packages/filterparser/src/parseFilter.ts b/packages/filterparser/src/parseFilter.ts
index 1154311a5..53151c6e2 100644
--- a/packages/filterparser/src/parseFilter.ts
+++ b/packages/filterparser/src/parseFilter.ts
@@ -1,4 +1,5 @@
import P from 'parsimmon';
+import moment from 'moment';
import { FilterType } from './types';
import { Condition } from 'dbgate-sqltree';
import { TransformType } from 'dbgate-types';
@@ -34,7 +35,7 @@ function interpretEscapes(str) {
});
}
-const binaryCondition = (operator) => (value) => ({
+const binaryCondition = operator => value => ({
conditionType: 'binary',
operator,
left: {
@@ -46,7 +47,7 @@ const binaryCondition = (operator) => (value) => ({
},
});
-const likeCondition = (conditionType, likeString) => (value) => ({
+const likeCondition = (conditionType, likeString) => value => ({
conditionType,
left: {
exprType: 'placeholder',
@@ -57,7 +58,7 @@ const likeCondition = (conditionType, likeString) => (value) => ({
},
});
-const compoudCondition = (conditionType) => (conditions) => {
+const compoudCondition = conditionType => conditions => {
if (conditions.length == 1) return conditions[0];
return {
conditionType,
@@ -65,7 +66,7 @@ const compoudCondition = (conditionType) => (conditions) => {
};
};
-const unaryCondition = (conditionType) => () => {
+const unaryCondition = conditionType => () => {
return {
conditionType,
expr: {
@@ -74,7 +75,7 @@ const unaryCondition = (conditionType) => () => {
};
};
-const binaryFixedValueCondition = (value) => () => {
+const binaryFixedValueCondition = value => () => {
return {
conditionType: 'binary',
operator: '=',
@@ -88,7 +89,7 @@ const binaryFixedValueCondition = (value) => () => {
};
};
-const negateCondition = (condition) => {
+const negateCondition = condition => {
return {
conditionType: 'not',
condition,
@@ -113,11 +114,11 @@ function getTransformCondition(transform: TransformType, value) {
};
}
-const yearCondition = () => (value) => {
+const yearCondition = () => value => {
return getTransformCondition('YEAR', value);
};
-const yearMonthCondition = () => (value) => {
+const yearMonthCondition = () => value => {
const m = value.match(/(\d\d\d\d)-(\d\d?)/);
return {
@@ -126,7 +127,7 @@ const yearMonthCondition = () => (value) => {
};
};
-const yearMonthDayCondition = () => (value) => {
+const yearMonthDayCondition = () => value => {
const m = value.match(/(\d\d\d\d)-(\d\d?)-(\d\d?)/);
return {
@@ -139,6 +140,43 @@ const yearMonthDayCondition = () => (value) => {
};
};
+const fixedIntervalCondition = (start, end) => () => {
+ return {
+ conditionType: 'and',
+ conditions: [
+ {
+ conditionType: 'binary',
+ operator: '>=',
+ left: {
+ exprType: 'placeholder',
+ },
+ right: {
+ exprType: 'value',
+ value: start,
+ },
+ },
+ {
+ conditionType: 'binary',
+ operator: '<',
+ left: {
+ exprType: 'placeholder',
+ },
+ right: {
+ exprType: 'value',
+ value: end,
+ },
+ },
+ ],
+ };
+};
+
+const fixedMomentIntervalCondition = (intervalType, diff) => {
+ return fixedIntervalCondition(
+ moment().add(intervalType, diff).startOf(intervalType).toISOString(),
+ moment().add(intervalType, diff).endOf(intervalType).toISOString()
+ );
+};
+
const createParser = (filterType: FilterType) => {
const langDef = {
string1: () =>
@@ -172,36 +210,60 @@ const createParser = (filterType: FilterType) => {
yearMonthNum: () => P.regexp(/\d\d\d\d-\d\d?/).map(yearMonthCondition()),
yearMonthDayNum: () => P.regexp(/\d\d\d\d-\d\d?-\d\d?/).map(yearMonthDayCondition()),
- value: (r) => P.alt(...allowedValues.map((x) => r[x])),
- valueTestEq: (r) => r.value.map(binaryCondition('=')),
- valueTestStr: (r) => r.value.map(likeCondition('like', '%#VALUE#%')),
+ value: r => P.alt(...allowedValues.map(x => r[x])),
+ valueTestEq: r => r.value.map(binaryCondition('=')),
+ valueTestStr: r => r.value.map(likeCondition('like', '%#VALUE#%')),
comma: () => word(','),
not: () => word('NOT'),
- notNull: (r) => r.not.then(r.null).map(unaryCondition('isNotNull')),
+ notNull: r => r.not.then(r.null).map(unaryCondition('isNotNull')),
null: () => word('NULL').map(unaryCondition('isNull')),
empty: () => word('EMPTY').map(unaryCondition('isEmpty')),
- notEmpty: (r) => r.not.then(r.empty).map(unaryCondition('isNotEmpty')),
+ notEmpty: r => r.not.then(r.empty).map(unaryCondition('isNotEmpty')),
true: () => word('TRUE').map(binaryFixedValueCondition(1)),
false: () => word('FALSE').map(binaryFixedValueCondition(0)),
trueNum: () => word('1').map(binaryFixedValueCondition(1)),
falseNum: () => word('0').map(binaryFixedValueCondition(0)),
- eq: (r) => word('=').then(r.value).map(binaryCondition('=')),
- ne: (r) => word('!=').then(r.value).map(binaryCondition('<>')),
- lt: (r) => word('<').then(r.value).map(binaryCondition('<')),
- gt: (r) => word('>').then(r.value).map(binaryCondition('>')),
- le: (r) => word('<=').then(r.value).map(binaryCondition('<=')),
- ge: (r) => word('>=').then(r.value).map(binaryCondition('>=')),
- startsWith: (r) => word('^').then(r.value).map(likeCondition('like', '#VALUE#%')),
- endsWith: (r) => word('$').then(r.value).map(likeCondition('like', '%#VALUE#')),
- contains: (r) => word('+').then(r.value).map(likeCondition('like', '%#VALUE#%')),
- startsWithNot: (r) => word('!^').then(r.value).map(likeCondition('like', '#VALUE#%')).map(negateCondition),
- endsWithNot: (r) => word('!$').then(r.value).map(likeCondition('like', '%#VALUE#')).map(negateCondition),
- containsNot: (r) => word('~').then(r.value).map(likeCondition('like', '%#VALUE#%')).map(negateCondition),
- element: (r) => P.alt(...allowedElements.map((x) => r[x])).trim(whitespace),
- factor: (r) => r.element.sepBy(whitespace).map(compoudCondition('and')),
- list: (r) => r.factor.sepBy(r.comma).map(compoudCondition('or')),
+ this: () => word('THIS'),
+ last: () => word('LAST'),
+ next: () => word('NEXT'),
+ week: () => word('WEEK'),
+ month: () => word('MONTH'),
+ year: () => word('YEAR'),
+
+ yesterday: () => word('YESTERDAY').map(fixedMomentIntervalCondition('day', -1)),
+ today: () => word('TODAY').map(fixedMomentIntervalCondition('day', 0)),
+ tomorrow: () => word('TOMORROW').map(fixedMomentIntervalCondition('day', 1)),
+
+ lastWeek: r => r.last.then(r.week).map(fixedMomentIntervalCondition('week', -1)),
+ thisWeek: r => r.this.then(r.week).map(fixedMomentIntervalCondition('week', 0)),
+ nextWeek: r => r.next.then(r.week).map(fixedMomentIntervalCondition('week', 1)),
+
+ lastMonth: r => r.last.then(r.month).map(fixedMomentIntervalCondition('month', -1)),
+ thisMonth: r => r.this.then(r.month).map(fixedMomentIntervalCondition('month', 0)),
+ nextMonth: r => r.next.then(r.month).map(fixedMomentIntervalCondition('month', 1)),
+
+ lastYear: r => r.last.then(r.year).map(fixedMomentIntervalCondition('year', -1)),
+ thisYear: r => r.this.then(r.year).map(fixedMomentIntervalCondition('year', 0)),
+ nextYear: r => r.next.then(r.year).map(fixedMomentIntervalCondition('year', 1)),
+
+ eq: r => word('=').then(r.value).map(binaryCondition('=')),
+ ne: r => word('!=').then(r.value).map(binaryCondition('<>')),
+ lt: r => word('<').then(r.value).map(binaryCondition('<')),
+ gt: r => word('>').then(r.value).map(binaryCondition('>')),
+ le: r => word('<=').then(r.value).map(binaryCondition('<=')),
+ ge: r => word('>=').then(r.value).map(binaryCondition('>=')),
+ startsWith: r => word('^').then(r.value).map(likeCondition('like', '#VALUE#%')),
+ endsWith: r => word('$').then(r.value).map(likeCondition('like', '%#VALUE#')),
+ contains: r => word('+').then(r.value).map(likeCondition('like', '%#VALUE#%')),
+ startsWithNot: r => word('!^').then(r.value).map(likeCondition('like', '#VALUE#%')).map(negateCondition),
+ endsWithNot: r => word('!$').then(r.value).map(likeCondition('like', '%#VALUE#')).map(negateCondition),
+ containsNot: r => word('~').then(r.value).map(likeCondition('like', '%#VALUE#%')).map(negateCondition),
+
+ element: r => P.alt(...allowedElements.map(x => r[x])).trim(whitespace),
+ factor: r => r.element.sepBy(whitespace).map(compoudCondition('and')),
+ list: r => r.factor.sepBy(r.comma).map(compoudCondition('or')),
};
const allowedValues = []; // 'string1', 'string2', 'number', 'noQuotedString'];
@@ -222,7 +284,24 @@ const createParser = (filterType: FilterType) => {
'containsNot'
);
if (filterType == 'logical') allowedElements.push('true', 'false', 'trueNum', 'falseNum');
- if (filterType == 'datetime') allowedElements.push('yearMonthDayNum', 'yearMonthNum', 'yearNum');
+ if (filterType == 'datetime')
+ allowedElements.push(
+ 'yearMonthDayNum',
+ 'yearMonthNum',
+ 'yearNum',
+ 'yesterday',
+ 'today',
+ 'tomorrow',
+ 'lastWeek',
+ 'thisWeek',
+ 'nextWeek',
+ 'lastMonth',
+ 'thisMonth',
+ 'nextMonth',
+ 'lastYear',
+ 'thisYear',
+ 'nextYear'
+ );
// must be last
if (filterType == 'string') allowedElements.push('valueTestStr');
@@ -240,5 +319,6 @@ const parsers = {
export function parseFilter(value: string, filterType: FilterType): Condition {
const ast = parsers[filterType].list.tryParse(value);
+ // console.log('AST', ast);
return ast;
}
diff --git a/packages/web/src/datagrid/DataFilterControl.js b/packages/web/src/datagrid/DataFilterControl.js
index abcdc4b23..8a09d4191 100644
--- a/packages/web/src/datagrid/DataFilterControl.js
+++ b/packages/web/src/datagrid/DataFilterControl.js
@@ -42,7 +42,7 @@ const FilterDiv = styled.div`
const FilterInput = styled.input`
flex: 1;
min-width: 10px;
- background-color: ${(props) =>
+ background-color: ${props =>
props.state == 'ok'
? props.theme.input_background_green[1]
: props.state == 'error'
@@ -58,68 +58,68 @@ function DropDownContent({ filterType, setFilter, filterMultipleValues, openFilt
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...
+ 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
+ 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
+ setFilter('')}>Clear Filter
+ filterMultipleValues()}>Filter multiple values
+ setFilter('NULL')}>Is Null
+ setFilter('NOT NULL')}>Is Not Null
- openFilterWindow('<=')}>Before...
- openFilterWindow('>=')}>After...
- openFilterWindow('>=;<=')}>Between...
+ openFilterWindow('<=')}>Before...
+ openFilterWindow('>=')}>After...
+ openFilterWindow('>=;<=')}>Between...
- setFilter('TOMORROW')}>Tomorrow
- setFilter('TODAY')}>Today
- setFilter('YESTERDAY')}>Yesterday
+ 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 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 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('NEXT YEAR')}>Next Year
+ setFilter('THIS YEAR')}>This Year
+ setFilter('LAST YEAR')}>Last Year
@@ -151,24 +151,24 @@ function DropDownContent({ filterType, setFilter, filterMultipleValues, openFilt
case 'string':
return (
<>
- setFilter('')}>Clear Filter
- filterMultipleValues()}>Filter multiple values
+ 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('=')}>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...
+ openFilterWindow('+')}>Contains...
+ openFilterWindow('~')}>Does Not Contain...
+ openFilterWindow('^')}>Begins With...
+ openFilterWindow('!^')}>Does Not Begin With...
+ openFilterWindow('$')}>Ends With...
+ openFilterWindow('!$')}>Does Not End With...
>
);
}
@@ -186,7 +186,7 @@ export default function DataFilterControl({
const showMenu = useShowMenu();
const theme = useTheme();
const [filterState, setFilterState] = React.useState('empty');
- const setFilterText = (filter) => {
+ const setFilterText = filter => {
setFilter(filter);
editorRef.current.value = filter || '';
updateFilterState();
@@ -196,19 +196,19 @@ export default function DataFilterControl({
setFilter(editorRef.current.value);
};
const filterMultipleValues = () => {
- showModal((modalState) => (
+ showModal(modalState => (
setFilterText(createMultiLineFilter(mode, text))}
/>
));
};
- const openFilterWindow = (operator) => {
- showModal((modalState) => (
+ const openFilterWindow = operator => {
+ showModal(modalState => (
setFilterText(text)}
+ onFilter={text => setFilterText(text)}
condition1={operator}
/>
));
@@ -220,7 +220,7 @@ export default function DataFilterControl({
if (focusIndex) editorRef.current.focus();
}, [focusIndex]);
- const handleKeyDown = (ev) => {
+ const handleKeyDown = ev => {
if (isReadOnly) return;
if (ev.keyCode == keycodes.enter) {
applyFilter();
@@ -248,6 +248,7 @@ export default function DataFilterControl({
setFilterState('empty');
}
} catch (err) {
+ // console.log('PARSE ERROR', err);
setFilterState('error');
}
};
diff --git a/packages/web/src/datagrid/SqlDataGridCore.js b/packages/web/src/datagrid/SqlDataGridCore.js
index ed8a0ec82..62c02ec85 100644
--- a/packages/web/src/datagrid/SqlDataGridCore.js
+++ b/packages/web/src/datagrid/SqlDataGridCore.js
@@ -78,7 +78,7 @@ export default function SqlDataGridCore(props) {
initialValues.sourceDatabaseName = database;
initialValues.sourceSql = display.getExportQuery();
initialValues.sourceList = display.baseTable ? [display.baseTable.pureName] : [];
- showModal((modalState) => );
+ showModal(modalState => );
}
function openActiveChart() {
openNewTab(
@@ -94,7 +94,7 @@ export default function SqlDataGridCore(props) {
{
editor: {
config: { chartType: 'bar' },
- sql: display.getExportQuery((select) => {
+ sql: display.getExportQuery(select => {
select.orderBy = null;
}),
},
@@ -102,18 +102,22 @@ export default function SqlDataGridCore(props) {
);
}
function openQuery() {
- openNewTab({
- title: 'Query',
- icon: 'img sql-file',
- tabComponent: 'QueryTab',
- props: {
- initialScript: display.getExportQuery(),
- schemaName: display.baseTable.schemaName,
- pureName: display.baseTable.pureName,
- conid,
- database,
+ openNewTab(
+ {
+ title: 'Query',
+ icon: 'img sql-file',
+ tabComponent: 'QueryTab',
+ props: {
+ schemaName: display.baseTable.schemaName,
+ pureName: display.baseTable.pureName,
+ conid,
+ database,
+ },
},
- });
+ {
+ editor: display.getExportQuery(),
+ }
+ );
}
function handleSave() {
@@ -135,7 +139,7 @@ export default function SqlDataGridCore(props) {
});
const { errorMessage } = resp.data || {};
if (errorMessage) {
- showModal((modalState) => (
+ showModal(modalState => (
));
} else {