mirror of
https://github.com/DeNNiiInc/dbgate.git
synced 2026-04-29 19:13:59 +00:00
master detail view
This commit is contained in:
@@ -33,7 +33,7 @@ function interpretEscapes(str) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const binaryCondition = operator => value => ({
|
const binaryCondition = (operator) => (value) => ({
|
||||||
conditionType: 'binary',
|
conditionType: 'binary',
|
||||||
operator,
|
operator,
|
||||||
left: {
|
left: {
|
||||||
@@ -45,7 +45,7 @@ const binaryCondition = operator => value => ({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const likeCondition = (conditionType, likeString) => value => ({
|
const likeCondition = (conditionType, likeString) => (value) => ({
|
||||||
conditionType,
|
conditionType,
|
||||||
left: {
|
left: {
|
||||||
exprType: 'placeholder',
|
exprType: 'placeholder',
|
||||||
@@ -56,7 +56,7 @@ const likeCondition = (conditionType, likeString) => value => ({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const compoudCondition = conditionType => conditions => {
|
const compoudCondition = (conditionType) => (conditions) => {
|
||||||
if (conditions.length == 1) return conditions[0];
|
if (conditions.length == 1) return conditions[0];
|
||||||
return {
|
return {
|
||||||
conditionType,
|
conditionType,
|
||||||
@@ -64,7 +64,7 @@ const compoudCondition = conditionType => conditions => {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
const unaryCondition = conditionType => () => {
|
const unaryCondition = (conditionType) => () => {
|
||||||
return {
|
return {
|
||||||
conditionType,
|
conditionType,
|
||||||
expr: {
|
expr: {
|
||||||
@@ -73,7 +73,7 @@ const unaryCondition = conditionType => () => {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
const binaryFixedValueCondition = value => () => {
|
const binaryFixedValueCondition = (value) => () => {
|
||||||
return {
|
return {
|
||||||
conditionType: 'binary',
|
conditionType: 'binary',
|
||||||
operator: '=',
|
operator: '=',
|
||||||
@@ -87,7 +87,7 @@ const binaryFixedValueCondition = value => () => {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
const negateCondition = condition => {
|
const negateCondition = (condition) => {
|
||||||
return {
|
return {
|
||||||
conditionType: 'not',
|
conditionType: 'not',
|
||||||
condition,
|
condition,
|
||||||
@@ -106,6 +106,16 @@ const createParser = (filterType: FilterType) => {
|
|||||||
.map(interpretEscapes)
|
.map(interpretEscapes)
|
||||||
.desc('string quoted'),
|
.desc('string quoted'),
|
||||||
|
|
||||||
|
string1Num: () =>
|
||||||
|
token(P.regexp(/"-?(0|[1-9][0-9]*)([.][0-9]+)?([eE][+-]?[0-9]+)?"/, 1))
|
||||||
|
.map(Number)
|
||||||
|
.desc('numer quoted'),
|
||||||
|
|
||||||
|
string2Num: () =>
|
||||||
|
token(P.regexp(/'-?(0|[1-9][0-9]*)([.][0-9]+)?([eE][+-]?[0-9]+)?'/, 1))
|
||||||
|
.map(Number)
|
||||||
|
.desc('numer quoted'),
|
||||||
|
|
||||||
number: () =>
|
number: () =>
|
||||||
token(P.regexp(/-?(0|[1-9][0-9]*)([.][0-9]+)?([eE][+-]?[0-9]+)?/))
|
token(P.regexp(/-?(0|[1-9][0-9]*)([.][0-9]+)?([eE][+-]?[0-9]+)?/))
|
||||||
.map(Number)
|
.map(Number)
|
||||||
@@ -113,78 +123,39 @@ const createParser = (filterType: FilterType) => {
|
|||||||
|
|
||||||
noQuotedString: () => P.regexp(/[^\s^,^'^"]+/).desc('string unquoted'),
|
noQuotedString: () => P.regexp(/[^\s^,^'^"]+/).desc('string unquoted'),
|
||||||
|
|
||||||
value: r => P.alt(...allowedValues.map(x => r[x])),
|
value: (r) => P.alt(...allowedValues.map((x) => r[x])),
|
||||||
valueTestEq: r => r.value.map(binaryCondition('=')),
|
valueTestEq: (r) => r.value.map(binaryCondition('=')),
|
||||||
valueTestStr: r => r.value.map(likeCondition('like', '%#VALUE#%')),
|
valueTestStr: (r) => r.value.map(likeCondition('like', '%#VALUE#%')),
|
||||||
|
|
||||||
comma: () => word(','),
|
comma: () => word(','),
|
||||||
not: () => word('NOT'),
|
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')),
|
null: () => word('NULL').map(unaryCondition('isNull')),
|
||||||
empty: () => word('EMPTY').map(unaryCondition('isEmpty')),
|
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)),
|
true: () => word('TRUE').map(binaryFixedValueCondition(1)),
|
||||||
false: () => word('FALSE').map(binaryFixedValueCondition(0)),
|
false: () => word('FALSE').map(binaryFixedValueCondition(0)),
|
||||||
eq: r =>
|
eq: (r) => word('=').then(r.value).map(binaryCondition('=')),
|
||||||
word('=')
|
ne: (r) => word('!=').then(r.value).map(binaryCondition('<>')),
|
||||||
.then(r.value)
|
lt: (r) => word('<').then(r.value).map(binaryCondition('<')),
|
||||||
.map(binaryCondition('=')),
|
gt: (r) => word('>').then(r.value).map(binaryCondition('>')),
|
||||||
ne: r =>
|
le: (r) => word('<=').then(r.value).map(binaryCondition('<=')),
|
||||||
word('!=')
|
ge: (r) => word('>=').then(r.value).map(binaryCondition('>=')),
|
||||||
.then(r.value)
|
startsWith: (r) => word('^').then(r.value).map(likeCondition('like', '#VALUE#%')),
|
||||||
.map(binaryCondition('<>')),
|
endsWith: (r) => word('$').then(r.value).map(likeCondition('like', '%#VALUE#')),
|
||||||
lt: r =>
|
contains: (r) => word('+').then(r.value).map(likeCondition('like', '%#VALUE#%')),
|
||||||
word('<')
|
startsWithNot: (r) => word('!^').then(r.value).map(likeCondition('like', '#VALUE#%')).map(negateCondition),
|
||||||
.then(r.value)
|
endsWithNot: (r) => word('!$').then(r.value).map(likeCondition('like', '%#VALUE#')).map(negateCondition),
|
||||||
.map(binaryCondition('<')),
|
containsNot: (r) => word('~').then(r.value).map(likeCondition('like', '%#VALUE#%')).map(negateCondition),
|
||||||
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),
|
element: (r) => P.alt(...allowedElements.map((x) => r[x])).trim(whitespace),
|
||||||
factor: r => r.element.sepBy(whitespace).map(compoudCondition('and')),
|
factor: (r) => r.element.sepBy(whitespace).map(compoudCondition('and')),
|
||||||
list: r => r.factor.sepBy(r.comma).map(compoudCondition('or')),
|
list: (r) => r.factor.sepBy(r.comma).map(compoudCondition('or')),
|
||||||
};
|
};
|
||||||
|
|
||||||
const allowedValues = []; // 'string1', 'string2', 'number', 'noQuotedString'];
|
const allowedValues = []; // 'string1', 'string2', 'number', 'noQuotedString'];
|
||||||
if (filterType == 'string') allowedValues.push('string1', 'string2', 'noQuotedString');
|
if (filterType == 'string') allowedValues.push('string1', 'string2', 'noQuotedString');
|
||||||
if (filterType == 'number') allowedValues.push('number');
|
if (filterType == 'number') allowedValues.push('string1Num', 'string2Num', 'number');
|
||||||
|
|
||||||
const allowedElements = ['null', 'notNull', 'eq', 'ne'];
|
const allowedElements = ['null', 'notNull', 'eq', 'ne'];
|
||||||
if (filterType == 'number' || filterType == 'datetime') allowedElements.push('lt', 'gt', 'le', 'ge');
|
if (filterType == 'number' || filterType == 'datetime') allowedElements.push('lt', 'gt', 'le', 'ge');
|
||||||
|
|||||||
@@ -426,8 +426,10 @@ export default function DataGridCore(props) {
|
|||||||
}, [jslid]);
|
}, [jslid]);
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
if (props.onSelectedRowsChanged) props.onSelectedRowsChanged(getSelectedRowData())
|
if (props.onRefSourceRowsChanged) {
|
||||||
}, [selectedCells]);
|
props.onRefSourceRowsChanged(getSelectedRowData());
|
||||||
|
}
|
||||||
|
}, [selectedCells, props.refReloadToken]);
|
||||||
|
|
||||||
// const handleCloseInplaceEditor = React.useCallback(
|
// const handleCloseInplaceEditor = React.useCallback(
|
||||||
// mode => {
|
// mode => {
|
||||||
|
|||||||
@@ -27,10 +27,15 @@ export default function TableDataGrid({
|
|||||||
const [childConfig, setChildConfig] = React.useState(createGridConfig());
|
const [childConfig, setChildConfig] = React.useState(createGridConfig());
|
||||||
const [myCache, setMyCache] = React.useState(createGridCache());
|
const [myCache, setMyCache] = React.useState(createGridCache());
|
||||||
const [childCache, setChildCache] = React.useState(createGridCache());
|
const [childCache, setChildCache] = React.useState(createGridCache());
|
||||||
|
const [refReloadToken, setRefReloadToken] = React.useState(0);
|
||||||
|
|
||||||
const connection = useConnectionInfo({ conid });
|
const connection = useConnectionInfo({ conid });
|
||||||
const [reference, setReference] = React.useState(null);
|
const [reference, setReference] = React.useState(null);
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
setRefReloadToken((v) => v + 1);
|
||||||
|
}, [reference]);
|
||||||
|
|
||||||
const display = React.useMemo(
|
const display = React.useMemo(
|
||||||
() =>
|
() =>
|
||||||
connection
|
connection
|
||||||
@@ -64,27 +69,31 @@ export default function TableDataGrid({
|
|||||||
}
|
}
|
||||||
}, [conid, database, display]);
|
}, [conid, database, display]);
|
||||||
|
|
||||||
const handleSelectedRowsChanged = (selectedRows) => {
|
const handleRefSourcedRowsChanged = React.useCallback(
|
||||||
const filters = {
|
(selectedRows) => {
|
||||||
...(config || myConfig).filters,
|
if (!reference) return;
|
||||||
..._.fromPairs(
|
const filters = {
|
||||||
reference.columns.map((col) => [
|
...(config || myConfig).filters,
|
||||||
col.refName,
|
..._.fromPairs(
|
||||||
selectedRows.map((x) => getFilterValueExpression(x[col.baseName])).join(','),
|
reference.columns.map((col) => [
|
||||||
])
|
col.refName,
|
||||||
),
|
selectedRows.map((x) => getFilterValueExpression(x[col.baseName])).join(','),
|
||||||
};
|
])
|
||||||
if (stableStringify(filters) != stableStringify((config || myConfig).filters)) {
|
),
|
||||||
setChildConfig((cfg) => ({
|
};
|
||||||
...cfg,
|
if (stableStringify(filters) != stableStringify((config || childConfig).filters)) {
|
||||||
filters,
|
setChildConfig((cfg) => ({
|
||||||
}));
|
...cfg,
|
||||||
setChildCache((ca) => ({
|
filters,
|
||||||
...ca,
|
}));
|
||||||
refreshTime: new Date().getTime(),
|
setChildCache((ca) => ({
|
||||||
}));
|
...ca,
|
||||||
}
|
refreshTime: new Date().getTime(),
|
||||||
};
|
}));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[config || childConfig, reference]
|
||||||
|
);
|
||||||
|
|
||||||
if (!display) return null;
|
if (!display) return null;
|
||||||
|
|
||||||
@@ -101,7 +110,8 @@ export default function TableDataGrid({
|
|||||||
toolbarPortalRef={toolbarPortalRef}
|
toolbarPortalRef={toolbarPortalRef}
|
||||||
showReferences
|
showReferences
|
||||||
onReferenceClick={setReference}
|
onReferenceClick={setReference}
|
||||||
onSelectedRowsChanged={reference ? handleSelectedRowsChanged : null}
|
onRefSourceRowsChanged={reference ? handleRefSourcedRowsChanged : null}
|
||||||
|
refReloadToken={refReloadToken.toString()}
|
||||||
/>
|
/>
|
||||||
{reference && (
|
{reference && (
|
||||||
<TableDataGrid
|
<TableDataGrid
|
||||||
|
|||||||
@@ -11,5 +11,6 @@ export interface DataGridProps {
|
|||||||
jslid?: string;
|
jslid?: string;
|
||||||
showReferences?: boolean;
|
showReferences?: boolean;
|
||||||
onReferenceClick?: (def: GridReferenceDefinition) => void;
|
onReferenceClick?: (def: GridReferenceDefinition) => void;
|
||||||
onSelectedRowsChanged?: Function;
|
onRefSourceRowsChanged?: Function;
|
||||||
|
refReloadToken?: string;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user