mirror of
https://github.com/DeNNiiInc/dbgate.git
synced 2026-04-22 23:56:00 +00:00
form view infrastructure, loading row from DB
This commit is contained in:
23
packages/datalib/src/FormViewDisplay.ts
Normal file
23
packages/datalib/src/FormViewDisplay.ts
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
import _ from 'lodash';
|
||||||
|
import { GridConfig, GridCache, GridConfigColumns, createGridCache, GroupFunc } from './GridConfig';
|
||||||
|
import { ForeignKeyInfo, TableInfo, ColumnInfo, EngineDriver, NamedObjectInfo, DatabaseInfo } from 'dbgate-types';
|
||||||
|
import { parseFilter, getFilterType } from 'dbgate-filterparser';
|
||||||
|
import { filterName } from './filterName';
|
||||||
|
import { ChangeSetFieldDefinition, ChangeSetRowDefinition } from './ChangeSet';
|
||||||
|
import { Expression, Select, treeToSql, dumpSqlSelect, Condition } from 'dbgate-sqltree';
|
||||||
|
import { isTypeLogical } from 'dbgate-tools';
|
||||||
|
import { ChangeCacheFunc, ChangeConfigFunc, DisplayColumn } from './GridDisplay';
|
||||||
|
|
||||||
|
export class FormViewDisplay {
|
||||||
|
isLoadedCorrectly = true;
|
||||||
|
columns: DisplayColumn[];
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
public config: GridConfig,
|
||||||
|
protected setConfig: ChangeConfigFunc,
|
||||||
|
public cache: GridCache,
|
||||||
|
protected setCache: ChangeCacheFunc,
|
||||||
|
public driver?: EngineDriver,
|
||||||
|
public dbinfo: DatabaseInfo = null
|
||||||
|
) {}
|
||||||
|
}
|
||||||
@@ -29,6 +29,8 @@ export interface GridConfig extends GridConfigColumns {
|
|||||||
grouping: { [uniqueName: string]: GroupFunc };
|
grouping: { [uniqueName: string]: GroupFunc };
|
||||||
childConfig?: GridConfig;
|
childConfig?: GridConfig;
|
||||||
reference?: GridReferenceDefinition;
|
reference?: GridReferenceDefinition;
|
||||||
|
isFormView?: boolean;
|
||||||
|
formViewKey?: { [uniqueName: string]: string };
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface GridCache {
|
export interface GridCache {
|
||||||
|
|||||||
@@ -518,4 +518,20 @@ export abstract class GridDisplay {
|
|||||||
conditions,
|
conditions,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
switchToFormView(rowData) {
|
||||||
|
if (!this.baseTable) return;
|
||||||
|
const { primaryKey } = this.baseTable;
|
||||||
|
if (!primaryKey) return;
|
||||||
|
const { columns } = primaryKey;
|
||||||
|
|
||||||
|
this.setConfig((cfg) => ({
|
||||||
|
...cfg,
|
||||||
|
isFormView: true,
|
||||||
|
formViewKey: _.pick(
|
||||||
|
rowData,
|
||||||
|
columns.map((x) => x.columnName)
|
||||||
|
),
|
||||||
|
}));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
62
packages/datalib/src/TableFormViewDisplay.ts
Normal file
62
packages/datalib/src/TableFormViewDisplay.ts
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
import { FormViewDisplay } from './FormViewDisplay';
|
||||||
|
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 { filterName } from './filterName';
|
||||||
|
import { TableGridDisplay } from './TableGridDisplay';
|
||||||
|
|
||||||
|
export class TableFormViewDisplay extends FormViewDisplay {
|
||||||
|
public table: TableInfo;
|
||||||
|
// use utility functions from GridDisplay and publish result in FromViewDisplat interface
|
||||||
|
private gridDisplay: TableGridDisplay;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
public tableName: NamedObjectInfo,
|
||||||
|
driver: EngineDriver,
|
||||||
|
config: GridConfig,
|
||||||
|
setConfig: ChangeConfigFunc,
|
||||||
|
cache: GridCache,
|
||||||
|
setCache: ChangeCacheFunc,
|
||||||
|
dbinfo: DatabaseInfo
|
||||||
|
) {
|
||||||
|
super(config, setConfig, cache, setCache, driver, dbinfo);
|
||||||
|
this.gridDisplay = new TableGridDisplay(tableName, driver, config, setConfig, cache, setCache, dbinfo);
|
||||||
|
|
||||||
|
this.isLoadedCorrectly = this.gridDisplay.isLoadedCorrectly;
|
||||||
|
this.columns = this.gridDisplay.columns;
|
||||||
|
}
|
||||||
|
|
||||||
|
getPrimaryKeyCondition(): Condition {
|
||||||
|
if (!this.config.formViewKey) return null;
|
||||||
|
return {
|
||||||
|
conditionType: 'and',
|
||||||
|
conditions: _.keys(this.config.formViewKey).map((columnName) => ({
|
||||||
|
conditionType: 'binary',
|
||||||
|
operator: '=',
|
||||||
|
left: {
|
||||||
|
exprType: 'column',
|
||||||
|
columnName,
|
||||||
|
source: {
|
||||||
|
alias: 'basetbl',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
right: {
|
||||||
|
exprType: 'value',
|
||||||
|
value: this.config.formViewKey[columnName],
|
||||||
|
},
|
||||||
|
})),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
getCurrentRowQuery() {
|
||||||
|
if (!this.driver) return null;
|
||||||
|
const select = this.gridDisplay.createSelect();
|
||||||
|
if (!select) return null;
|
||||||
|
select.topRecords = 1;
|
||||||
|
select.where = mergeConditions(select.where, this.getPrimaryKeyCondition());
|
||||||
|
const sql = treeToSql(this.driver, select, dumpSqlSelect);
|
||||||
|
return sql;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,11 +1,13 @@
|
|||||||
export * from "./GridDisplay";
|
export * from './GridDisplay';
|
||||||
export * from "./GridConfig";
|
export * from './GridConfig';
|
||||||
export * from "./TableGridDisplay";
|
export * from './TableGridDisplay';
|
||||||
export * from "./ViewGridDisplay";
|
export * from './ViewGridDisplay';
|
||||||
export * from "./JslGridDisplay";
|
export * from './JslGridDisplay';
|
||||||
export * from "./ChangeSet";
|
export * from './ChangeSet';
|
||||||
export * from "./filterName";
|
export * from './filterName';
|
||||||
export * from "./FreeTableGridDisplay";
|
export * from './FreeTableGridDisplay';
|
||||||
export * from "./FreeTableModel";
|
export * from './FreeTableModel';
|
||||||
export * from "./MacroDefinition";
|
export * from './MacroDefinition';
|
||||||
export * from "./runMacro";
|
export * from './runMacro';
|
||||||
|
export * from './FormViewDisplay';
|
||||||
|
export * from './TableFormViewDisplay';
|
||||||
|
|||||||
@@ -21,17 +21,13 @@ const DataGridContainer = styled.div`
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
export default function DataGrid(props) {
|
export default function DataGrid(props) {
|
||||||
const { GridCore, FormView } = props;
|
const { GridCore, FormView, config, formDisplay } = props;
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const [managerSize, setManagerSize] = React.useState(0);
|
const [managerSize, setManagerSize] = React.useState(0);
|
||||||
const [selection, setSelection] = React.useState([]);
|
const [selection, setSelection] = React.useState([]);
|
||||||
const [grider, setGrider] = React.useState(null);
|
const [grider, setGrider] = React.useState(null);
|
||||||
const [formViewData, setFormViewData] = React.useState(null);
|
// const [formViewData, setFormViewData] = React.useState(null);
|
||||||
const isFormView = !!formViewData;
|
const isFormView = !!(config && config.isFormView);
|
||||||
|
|
||||||
const handleSetFormView = (rowData) => {
|
|
||||||
setFormViewData(rowData);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<HorizontalSplitter initialValue="300px" size={managerSize} setSize={setManagerSize}>
|
<HorizontalSplitter initialValue="300px" size={managerSize} setSize={setManagerSize}>
|
||||||
@@ -57,13 +53,13 @@ export default function DataGrid(props) {
|
|||||||
|
|
||||||
<DataGridContainer>
|
<DataGridContainer>
|
||||||
{isFormView ? (
|
{isFormView ? (
|
||||||
<FormView {...props} rowData={formViewData} onSetTableView={() => setFormViewData(null)} />
|
<FormView {...props} />
|
||||||
) : (
|
) : (
|
||||||
<GridCore
|
<GridCore
|
||||||
{...props}
|
{...props}
|
||||||
onSelectionChanged={setSelection}
|
onSelectionChanged={setSelection}
|
||||||
onChangeGrider={setGrider}
|
onChangeGrider={setGrider}
|
||||||
onSetFormView={FormView ? handleSetFormView : null}
|
formViewAvailable={!!FormView && !!formDisplay}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</DataGridContainer>
|
</DataGridContainer>
|
||||||
|
|||||||
@@ -116,7 +116,7 @@ export default function DataGridCore(props) {
|
|||||||
onSelectionChanged,
|
onSelectionChanged,
|
||||||
frameSelection,
|
frameSelection,
|
||||||
onKeyDown,
|
onKeyDown,
|
||||||
onSetFormView,
|
formViewAvailable,
|
||||||
} = props;
|
} = props;
|
||||||
// console.log('RENDER GRID', display.baseTable.pureName);
|
// console.log('RENDER GRID', display.baseTable.pureName);
|
||||||
const columns = React.useMemo(() => display.allColumns, [display]);
|
const columns = React.useMemo(() => display.allColumns, [display]);
|
||||||
@@ -943,6 +943,13 @@ export default function DataGridCore(props) {
|
|||||||
display.clearFilters();
|
display.clearFilters();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleSetFormView =
|
||||||
|
formViewAvailable && display.baseTable && display.baseTable.primaryKey
|
||||||
|
? (rowData) => {
|
||||||
|
display.switchToFormView(rowData);
|
||||||
|
}
|
||||||
|
: null;
|
||||||
|
|
||||||
// console.log('visibleRealColumnIndexes', visibleRealColumnIndexes);
|
// console.log('visibleRealColumnIndexes', visibleRealColumnIndexes);
|
||||||
// console.log(
|
// console.log(
|
||||||
// 'gridScrollAreaWidth / columnSizes.getVisibleScrollSizeSum()',
|
// 'gridScrollAreaWidth / columnSizes.getVisibleScrollSizeSum()',
|
||||||
@@ -1048,7 +1055,7 @@ export default function DataGridCore(props) {
|
|||||||
display={display}
|
display={display}
|
||||||
focusedColumn={display.focusedColumn}
|
focusedColumn={display.focusedColumn}
|
||||||
frameSelection={frameSelection}
|
frameSelection={frameSelection}
|
||||||
onSetFormView={onSetFormView}
|
onSetFormView={handleSetFormView}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import React from 'react';
|
|||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import DataGrid from './DataGrid';
|
import DataGrid from './DataGrid';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
import { TableGridDisplay, createGridConfig, createGridCache } from 'dbgate-datalib';
|
import { TableGridDisplay, TableFormViewDisplay, createGridConfig, createGridCache } from 'dbgate-datalib';
|
||||||
import { getFilterValueExpression } from 'dbgate-filterparser';
|
import { getFilterValueExpression } from 'dbgate-filterparser';
|
||||||
import { findEngineDriver } from 'dbgate-tools';
|
import { findEngineDriver } from 'dbgate-tools';
|
||||||
import { useConnectionInfo, getTableInfo, useDatabaseInfo } from '../utility/metadataLoaders';
|
import { useConnectionInfo, getTableInfo, useDatabaseInfo } from '../utility/metadataLoaders';
|
||||||
@@ -88,7 +88,22 @@ export default function TableDataGrid({
|
|||||||
: null;
|
: null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function createFormDisplay() {
|
||||||
|
return connection
|
||||||
|
? new TableFormViewDisplay(
|
||||||
|
{ schemaName, pureName },
|
||||||
|
findEngineDriver(connection, extensions),
|
||||||
|
config,
|
||||||
|
setConfig,
|
||||||
|
cache || myCache,
|
||||||
|
setCache || setMyCache,
|
||||||
|
dbinfo
|
||||||
|
)
|
||||||
|
: null;
|
||||||
|
}
|
||||||
|
|
||||||
const [display, setDisplay] = React.useState(createDisplay());
|
const [display, setDisplay] = React.useState(createDisplay());
|
||||||
|
const [formDisplay, setFormDisplay] = React.useState(createFormDisplay());
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
setRefReloadToken((v) => v + 1);
|
setRefReloadToken((v) => v + 1);
|
||||||
@@ -102,6 +117,13 @@ export default function TableDataGrid({
|
|||||||
setDisplay(newDisplay);
|
setDisplay(newDisplay);
|
||||||
}, [connection, config, cache || myCache, conid, database, schemaName, pureName, dbinfo, extensions]);
|
}, [connection, config, cache || myCache, conid, database, schemaName, pureName, dbinfo, extensions]);
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
const newDisplay = createFormDisplay();
|
||||||
|
if (!newDisplay) return;
|
||||||
|
if (formDisplay && formDisplay.isLoadedCorrectly && !newDisplay.isLoadedCorrectly) return;
|
||||||
|
setFormDisplay(newDisplay);
|
||||||
|
}, [connection, config, cache || myCache, conid, database, schemaName, pureName, dbinfo, extensions]);
|
||||||
|
|
||||||
const handleDatabaseStructureChanged = React.useCallback(() => {
|
const handleDatabaseStructureChanged = React.useCallback(() => {
|
||||||
(setCache || setMyCache)(createGridCache());
|
(setCache || setMyCache)(createGridCache());
|
||||||
}, []);
|
}, []);
|
||||||
@@ -159,9 +181,12 @@ export default function TableDataGrid({
|
|||||||
<VerticalSplitter>
|
<VerticalSplitter>
|
||||||
<DataGrid
|
<DataGrid
|
||||||
// key={`${conid}, ${database}, ${schemaName}, ${pureName}`}
|
// key={`${conid}, ${database}, ${schemaName}, ${pureName}`}
|
||||||
|
config={config}
|
||||||
|
setConfig={setConfig}
|
||||||
conid={conid}
|
conid={conid}
|
||||||
database={database}
|
database={database}
|
||||||
display={display}
|
display={display}
|
||||||
|
formDisplay={formDisplay}
|
||||||
tabVisible={tabVisible}
|
tabVisible={tabVisible}
|
||||||
changeSetState={changeSetState}
|
changeSetState={changeSetState}
|
||||||
dispatchChangeSet={dispatchChangeSet}
|
dispatchChangeSet={dispatchChangeSet}
|
||||||
@@ -174,9 +199,9 @@ export default function TableDataGrid({
|
|||||||
GridCore={SqlDataGridCore}
|
GridCore={SqlDataGridCore}
|
||||||
FormView={SqlFormView}
|
FormView={SqlFormView}
|
||||||
isDetailView={isDetailView}
|
isDetailView={isDetailView}
|
||||||
tableInfo={
|
// tableInfo={
|
||||||
dbinfo && dbinfo.tables && dbinfo.tables.find((x) => x.pureName == pureName && x.schemaName == schemaName)
|
// dbinfo && dbinfo.tables && dbinfo.tables.find((x) => x.pureName == pureName && x.schemaName == schemaName)
|
||||||
}
|
// }
|
||||||
/>
|
/>
|
||||||
{reference && (
|
{reference && (
|
||||||
<ReferenceContainer>
|
<ReferenceContainer>
|
||||||
|
|||||||
@@ -61,15 +61,34 @@ const NullSpan = styled.span`
|
|||||||
font-style: italic;
|
font-style: italic;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export default function FormView({ tableInfo, rowData, toolbarPortalRef, tabVisible, onSetTableView }) {
|
export default function FormView(props) {
|
||||||
|
const { rowData, toolbarPortalRef, tabVisible, config, setConfig } = props;
|
||||||
|
/** @type {import('dbgate-datalib').FormViewDisplay} */
|
||||||
|
const formDisplay = props.formDisplay;
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const [headerRowRef, { height: rowHeight }] = useDimensions();
|
const [headerRowRef, { height: rowHeight }] = useDimensions();
|
||||||
const [wrapperRef, { height: wrapperHeight }] = useDimensions();
|
const [wrapperRef, { height: wrapperHeight }] = useDimensions();
|
||||||
|
|
||||||
if (!tableInfo || !rowData) return null;
|
const handleSwitchToTable = () => {
|
||||||
|
setConfig((cfg) => ({
|
||||||
|
...cfg,
|
||||||
|
isFormView: false,
|
||||||
|
formViewKey: null,
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
|
||||||
|
const toolbar =
|
||||||
|
toolbarPortalRef &&
|
||||||
|
toolbarPortalRef.current &&
|
||||||
|
tabVisible &&
|
||||||
|
ReactDOM.createPortal(<FormViewToolbar switchToTable={handleSwitchToTable} />, toolbarPortalRef.current);
|
||||||
|
|
||||||
|
// console.log('display', display);
|
||||||
|
|
||||||
|
if (!formDisplay || !formDisplay.isLoadedCorrectly) return toolbar;
|
||||||
|
|
||||||
const rowCount = Math.floor((wrapperHeight - 20) / rowHeight);
|
const rowCount = Math.floor((wrapperHeight - 20) / rowHeight);
|
||||||
const columnChunks = _.chunk(tableInfo.columns, rowCount);
|
const columnChunks = _.chunk(formDisplay.columns, rowCount);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Wrapper ref={wrapperRef}>
|
<Wrapper ref={wrapperRef}>
|
||||||
@@ -78,18 +97,15 @@ export default function FormView({ tableInfo, rowData, toolbarPortalRef, tabVisi
|
|||||||
{chunk.map((col) => (
|
{chunk.map((col) => (
|
||||||
<TableRow key={col.columnName} theme={theme} ref={headerRowRef} style={{ height: `${rowHeight}px` }}>
|
<TableRow key={col.columnName} theme={theme} ref={headerRowRef} style={{ height: `${rowHeight}px` }}>
|
||||||
<TableHeaderCell theme={theme}>
|
<TableHeaderCell theme={theme}>
|
||||||
<ColumnLabel {...col} foreignKey={findForeignKeyForColumn(tableInfo, col)} />
|
<ColumnLabel {...col} />
|
||||||
</TableHeaderCell>
|
</TableHeaderCell>
|
||||||
<TableBodyCell theme={theme}>{rowData[col.columnName]}</TableBodyCell>
|
<TableBodyCell theme={theme}>{rowData && rowData[col.columnName]}</TableBodyCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
))}
|
))}
|
||||||
</Table>
|
</Table>
|
||||||
))}
|
))}
|
||||||
|
|
||||||
{toolbarPortalRef &&
|
{toolbar}
|
||||||
toolbarPortalRef.current &&
|
|
||||||
tabVisible &&
|
|
||||||
ReactDOM.createPortal(<FormViewToolbar switchToTable={onSetTableView} />, toolbarPortalRef.current)}
|
|
||||||
</Wrapper>
|
</Wrapper>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,71 @@
|
|||||||
|
import { TableFormViewDisplay } from 'dbgate-datalib';
|
||||||
|
import { findEngineDriver } from 'dbgate-tools';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import { useConnectionInfo, useDatabaseInfo } from '../utility/metadataLoaders';
|
||||||
|
import useExtensions from '../utility/useExtensions';
|
||||||
import FormView from './FormView';
|
import FormView from './FormView';
|
||||||
|
import axios from '../utility/axios';
|
||||||
|
|
||||||
|
async function loadCurrentRow(props) {
|
||||||
|
const { formDisplay, conid, database } = props;
|
||||||
|
/** @type {import('dbgate-datalib').TableFormViewDisplay} */
|
||||||
|
|
||||||
|
const sql = formDisplay.getCurrentRowQuery();
|
||||||
|
|
||||||
|
const response = await axios.request({
|
||||||
|
url: 'database-connections/query-data',
|
||||||
|
method: 'post',
|
||||||
|
params: {
|
||||||
|
conid,
|
||||||
|
database,
|
||||||
|
},
|
||||||
|
data: { sql },
|
||||||
|
});
|
||||||
|
|
||||||
|
if (response.data.errorMessage) return response.data;
|
||||||
|
return response.data.rows[0];
|
||||||
|
}
|
||||||
|
|
||||||
export default function SqlFormView(props) {
|
export default function SqlFormView(props) {
|
||||||
return <FormView {...props} />;
|
const { formDisplay } = props;
|
||||||
|
const [rowData, setRowData] = React.useState(null);
|
||||||
|
|
||||||
|
const handleLoadCurrentRow = async () => {
|
||||||
|
const row = await loadCurrentRow(props);
|
||||||
|
if (row) setRowData(row);
|
||||||
|
};
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
handleLoadCurrentRow();
|
||||||
|
}, [formDisplay]);
|
||||||
|
|
||||||
|
// const { config, setConfig, cache, setCache, schemaName, pureName, conid, database } = props;
|
||||||
|
// const { formViewKey } = config;
|
||||||
|
|
||||||
|
// const [display, setDisplay] = React.useState(null);
|
||||||
|
|
||||||
|
// const connection = useConnectionInfo({ conid });
|
||||||
|
// const dbinfo = useDatabaseInfo({ conid, database });
|
||||||
|
// const extensions = useExtensions();
|
||||||
|
|
||||||
|
// console.log('SqlFormView.props', props);
|
||||||
|
|
||||||
|
// React.useEffect(() => {
|
||||||
|
// const newDisplay = connection
|
||||||
|
// ? new TableFormViewDisplay(
|
||||||
|
// { schemaName, pureName },
|
||||||
|
// findEngineDriver(connection, extensions),
|
||||||
|
// config,
|
||||||
|
// setConfig,
|
||||||
|
// cache,
|
||||||
|
// setCache,
|
||||||
|
// dbinfo
|
||||||
|
// )
|
||||||
|
// : null;
|
||||||
|
// if (!newDisplay) return;
|
||||||
|
// if (display && display.isLoadedCorrectly && !newDisplay.isLoadedCorrectly) return;
|
||||||
|
// setDisplay(newDisplay);
|
||||||
|
// }, [config, cache, conid, database, schemaName, pureName, dbinfo, extensions]);
|
||||||
|
|
||||||
|
return <FormView {...props} rowData={rowData} />;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user