mirror of
https://github.com/DeNNiiInc/dbgate.git
synced 2026-04-28 16:26:00 +00:00
form view - loading, navigation
This commit is contained in:
@@ -3,9 +3,18 @@ import _ from 'lodash';
|
||||
import { GridDisplay, ChangeCacheFunc, DisplayColumn, DisplayedColumnInfo, ChangeConfigFunc } from './GridDisplay';
|
||||
import { TableInfo, EngineDriver, ViewInfo, ColumnInfo, NamedObjectInfo, DatabaseInfo } from 'dbgate-types';
|
||||
import { GridConfig, GridCache, createGridCache } from './GridConfig';
|
||||
import { Expression, Select, treeToSql, dumpSqlSelect, mergeConditions, Condition } from 'dbgate-sqltree';
|
||||
import {
|
||||
Expression,
|
||||
Select,
|
||||
treeToSql,
|
||||
dumpSqlSelect,
|
||||
mergeConditions,
|
||||
Condition,
|
||||
OrderByExpression,
|
||||
} from 'dbgate-sqltree';
|
||||
import { filterName } from './filterName';
|
||||
import { TableGridDisplay } from './TableGridDisplay';
|
||||
import stableStringify from 'json-stable-stringify';
|
||||
|
||||
export class TableFormViewDisplay extends FormViewDisplay {
|
||||
public table: TableInfo;
|
||||
@@ -28,7 +37,7 @@ export class TableFormViewDisplay extends FormViewDisplay {
|
||||
this.columns = this.gridDisplay.columns;
|
||||
}
|
||||
|
||||
getPrimaryKeyCondition(): Condition {
|
||||
getPrimaryKeyEqualCondition(): Condition {
|
||||
if (!this.config.formViewKey) return null;
|
||||
return {
|
||||
conditionType: 'and',
|
||||
@@ -50,12 +59,130 @@ export class TableFormViewDisplay extends FormViewDisplay {
|
||||
};
|
||||
}
|
||||
|
||||
getCurrentRowQuery() {
|
||||
getPrimaryKeyOperatorCondition(operator): Condition {
|
||||
if (!this.config.formViewKey) return null;
|
||||
const conditions = [];
|
||||
|
||||
const { primaryKey } = this.gridDisplay.baseTable;
|
||||
for (let index = 0; index < primaryKey.columns.length; index++) {
|
||||
conditions.push({
|
||||
conditionType: 'and',
|
||||
conditions: [
|
||||
...primaryKey.columns.slice(0, index).map(({ columnName }) => ({
|
||||
conditionType: 'binary',
|
||||
operator: '=',
|
||||
left: {
|
||||
exprType: 'column',
|
||||
columnName,
|
||||
source: {
|
||||
alias: 'basetbl',
|
||||
},
|
||||
},
|
||||
right: {
|
||||
exprType: 'value',
|
||||
value: this.config.formViewKey[columnName],
|
||||
},
|
||||
})),
|
||||
...primaryKey.columns.slice(index).map(({ columnName }) => ({
|
||||
conditionType: 'binary',
|
||||
operator: operator,
|
||||
left: {
|
||||
exprType: 'column',
|
||||
columnName,
|
||||
source: {
|
||||
alias: 'basetbl',
|
||||
},
|
||||
},
|
||||
right: {
|
||||
exprType: 'value',
|
||||
value: this.config.formViewKey[columnName],
|
||||
},
|
||||
})),
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
if (conditions.length == 1) {
|
||||
return conditions[0];
|
||||
}
|
||||
|
||||
return {
|
||||
conditionType: 'or',
|
||||
conditions,
|
||||
};
|
||||
}
|
||||
|
||||
getSelect() {
|
||||
if (!this.driver) return null;
|
||||
const select = this.gridDisplay.createSelect();
|
||||
if (!select) return null;
|
||||
select.topRecords = 1;
|
||||
select.where = mergeConditions(select.where, this.getPrimaryKeyCondition());
|
||||
return select;
|
||||
}
|
||||
|
||||
getCurrentRowQuery() {
|
||||
const select = this.getSelect();
|
||||
if (!select) return null;
|
||||
|
||||
select.where = mergeConditions(select.where, this.getPrimaryKeyEqualCondition());
|
||||
const sql = treeToSql(this.driver, select, dumpSqlSelect);
|
||||
return sql;
|
||||
}
|
||||
|
||||
extractKey(row) {
|
||||
const formViewKey = _.pick(
|
||||
row,
|
||||
this.gridDisplay.baseTable.primaryKey.columns.map((x) => x.columnName)
|
||||
);
|
||||
return formViewKey;
|
||||
}
|
||||
|
||||
navigate(row) {
|
||||
const formViewKey = this.extractKey(row);
|
||||
this.setConfig((cfg) => ({
|
||||
...cfg,
|
||||
formViewKey,
|
||||
}));
|
||||
}
|
||||
|
||||
isLoadedCurrentRow(row) {
|
||||
if (!row) return false;
|
||||
const formViewKey = this.extractKey(row);
|
||||
return stableStringify(formViewKey) == stableStringify(this.config.formViewKey);
|
||||
}
|
||||
|
||||
navigateRowQuery(commmand: 'begin' | 'previous' | 'next' | 'end') {
|
||||
if (!this.driver) return null;
|
||||
const select = this.gridDisplay.createSelect();
|
||||
if (!select) return null;
|
||||
const { primaryKey } = this.gridDisplay.baseTable;
|
||||
|
||||
function getOrderBy(direction): OrderByExpression[] {
|
||||
return primaryKey.columns.map(({ columnName }) => ({
|
||||
exprType: 'column',
|
||||
columnName,
|
||||
direction,
|
||||
}));
|
||||
}
|
||||
|
||||
select.topRecords = 1;
|
||||
switch (commmand) {
|
||||
case 'begin':
|
||||
select.orderBy = getOrderBy('ASC');
|
||||
break;
|
||||
case 'end':
|
||||
select.orderBy = getOrderBy('DESC');
|
||||
break;
|
||||
case 'previous':
|
||||
select.orderBy = getOrderBy('DESC');
|
||||
select.where = mergeConditions(select.where, this.getPrimaryKeyOperatorCondition('<'));
|
||||
break;
|
||||
case 'next':
|
||||
select.orderBy = getOrderBy('ASC');
|
||||
select.where = mergeConditions(select.where, this.getPrimaryKeyOperatorCondition('>'));
|
||||
break;
|
||||
}
|
||||
|
||||
const sql = treeToSql(this.driver, select, dumpSqlSelect);
|
||||
return sql;
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@ const NullSpan = styled.span`
|
||||
`;
|
||||
|
||||
export default function FormView(props) {
|
||||
const { rowData, toolbarPortalRef, tabVisible, config, setConfig } = props;
|
||||
const { rowData, toolbarPortalRef, tabVisible, config, setConfig, onNavigate } = props;
|
||||
/** @type {import('dbgate-datalib').FormViewDisplay} */
|
||||
const formDisplay = props.formDisplay;
|
||||
const theme = useTheme();
|
||||
@@ -81,7 +81,10 @@ export default function FormView(props) {
|
||||
toolbarPortalRef &&
|
||||
toolbarPortalRef.current &&
|
||||
tabVisible &&
|
||||
ReactDOM.createPortal(<FormViewToolbar switchToTable={handleSwitchToTable} />, toolbarPortalRef.current);
|
||||
ReactDOM.createPortal(
|
||||
<FormViewToolbar switchToTable={handleSwitchToTable} onNavigate={onNavigate} />,
|
||||
toolbarPortalRef.current
|
||||
);
|
||||
|
||||
// console.log('display', display);
|
||||
|
||||
|
||||
@@ -1,12 +1,24 @@
|
||||
import React from 'react';
|
||||
import ToolbarButton from '../widgets/ToolbarButton';
|
||||
|
||||
export default function FormViewToolbar({ switchToTable }) {
|
||||
export default function FormViewToolbar({ switchToTable, onNavigate }) {
|
||||
return (
|
||||
<>
|
||||
<ToolbarButton onClick={switchToTable} icon="icon table">
|
||||
Table view
|
||||
</ToolbarButton>
|
||||
<ToolbarButton onClick={() => onNavigate('begin')} icon="icon arrow-begin">
|
||||
First
|
||||
</ToolbarButton>
|
||||
<ToolbarButton onClick={() => onNavigate('previous')} icon="icon arrow-left">
|
||||
Previous
|
||||
</ToolbarButton>
|
||||
<ToolbarButton onClick={() => onNavigate('next')} icon="icon arrow-right">
|
||||
Next
|
||||
</ToolbarButton>
|
||||
<ToolbarButton onClick={() => onNavigate('end')} icon="icon arrow-end">
|
||||
Last
|
||||
</ToolbarButton>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -6,11 +6,10 @@ import useExtensions from '../utility/useExtensions';
|
||||
import FormView from './FormView';
|
||||
import axios from '../utility/axios';
|
||||
|
||||
async function loadCurrentRow(props) {
|
||||
const { formDisplay, conid, database } = props;
|
||||
async function loadRow(props, sql) {
|
||||
const { conid, database } = props;
|
||||
/** @type {import('dbgate-datalib').TableFormViewDisplay} */
|
||||
|
||||
const sql = formDisplay.getCurrentRowQuery();
|
||||
const formDisplay = props.formDisplay;
|
||||
|
||||
const response = await axios.request({
|
||||
url: 'database-connections/query-data',
|
||||
@@ -31,12 +30,22 @@ export default function SqlFormView(props) {
|
||||
const [rowData, setRowData] = React.useState(null);
|
||||
|
||||
const handleLoadCurrentRow = async () => {
|
||||
const row = await loadCurrentRow(props);
|
||||
const row = await loadRow(props, formDisplay.getCurrentRowQuery());
|
||||
if (row) setRowData(row);
|
||||
};
|
||||
|
||||
const handleNavigate = async (command) => {
|
||||
const row = await loadRow(props, formDisplay.navigateRowQuery(command));
|
||||
if (row) {
|
||||
setRowData(row);
|
||||
formDisplay.navigate(row);
|
||||
}
|
||||
};
|
||||
|
||||
React.useEffect(() => {
|
||||
handleLoadCurrentRow();
|
||||
if (formDisplay && !formDisplay.isLoadedCurrentRow(rowData)) {
|
||||
handleLoadCurrentRow();
|
||||
}
|
||||
}, [formDisplay]);
|
||||
|
||||
// const { config, setConfig, cache, setCache, schemaName, pureName, conid, database } = props;
|
||||
@@ -67,5 +76,5 @@ export default function SqlFormView(props) {
|
||||
// setDisplay(newDisplay);
|
||||
// }, [config, cache, conid, database, schemaName, pureName, dbinfo, extensions]);
|
||||
|
||||
return <FormView {...props} rowData={rowData} />;
|
||||
return <FormView {...props} rowData={rowData} onNavigate={handleNavigate} />;
|
||||
}
|
||||
|
||||
@@ -39,6 +39,8 @@ const iconNames = {
|
||||
'icon arrow-up': 'mdi mdi-arrow-up',
|
||||
'icon arrow-down': 'mdi mdi-arrow-down',
|
||||
'icon arrow-left': 'mdi mdi-arrow-left',
|
||||
'icon arrow-begin': 'mdi mdi-arrow-collapse-left',
|
||||
'icon arrow-end': 'mdi mdi-arrow-collapse-right',
|
||||
'icon arrow-right': 'mdi mdi-arrow-right',
|
||||
'icon format-code': 'mdi mdi-code-tags-check',
|
||||
'icon show-wizard': 'mdi mdi-comment-edit',
|
||||
|
||||
Reference in New Issue
Block a user