mirror of
https://github.com/DeNNiiInc/dbgate.git
synced 2026-04-19 07:16:01 +00:00
remove web
This commit is contained in:
@@ -1,93 +0,0 @@
|
||||
import {
|
||||
ChangeSet,
|
||||
changeSetContainsChanges,
|
||||
changeSetInsertNewRow,
|
||||
createChangeSet,
|
||||
deleteChangeSetRows,
|
||||
findExistingChangeSetItem,
|
||||
getChangeSetInsertedRows,
|
||||
TableFormViewDisplay,
|
||||
revertChangeSetRowChanges,
|
||||
setChangeSetValue,
|
||||
ChangeSetRowDefinition,
|
||||
} from 'dbgate-datalib';
|
||||
import Former from './Former';
|
||||
|
||||
export default class ChangeSetFormer extends Former {
|
||||
public changeSet: ChangeSet;
|
||||
public setChangeSet: Function;
|
||||
private batchChangeSet: ChangeSet;
|
||||
public rowDefinition: ChangeSetRowDefinition;
|
||||
public rowStatus;
|
||||
|
||||
constructor(
|
||||
public sourceRow: any,
|
||||
public changeSetState,
|
||||
public dispatchChangeSet,
|
||||
public display: TableFormViewDisplay
|
||||
) {
|
||||
super();
|
||||
this.changeSet = changeSetState && changeSetState.value;
|
||||
this.setChangeSet = value => dispatchChangeSet({ type: 'set', value });
|
||||
this.batchChangeSet = null;
|
||||
this.rowDefinition = display.getChangeSetRow(sourceRow);
|
||||
const [matchedField, matchedChangeSetItem] = findExistingChangeSetItem(this.changeSet, this.rowDefinition);
|
||||
this.rowData = matchedChangeSetItem ? { ...sourceRow, ...matchedChangeSetItem.fields } : sourceRow;
|
||||
let status = 'regular';
|
||||
if (matchedChangeSetItem && matchedField == 'updates') status = 'updated';
|
||||
if (matchedField == 'deletes') status = 'deleted';
|
||||
this.rowStatus = {
|
||||
status,
|
||||
modifiedFields:
|
||||
matchedChangeSetItem && matchedChangeSetItem.fields ? new Set(Object.keys(matchedChangeSetItem.fields)) : null,
|
||||
};
|
||||
}
|
||||
|
||||
applyModification(changeSetReducer) {
|
||||
if (this.batchChangeSet) {
|
||||
this.batchChangeSet = changeSetReducer(this.batchChangeSet);
|
||||
} else {
|
||||
this.setChangeSet(changeSetReducer(this.changeSet));
|
||||
}
|
||||
}
|
||||
|
||||
setCellValue(uniqueName: string, value: any) {
|
||||
const row = this.sourceRow;
|
||||
const definition = this.display.getChangeSetField(row, uniqueName);
|
||||
this.applyModification(chs => setChangeSetValue(chs, definition, value));
|
||||
}
|
||||
|
||||
deleteRow(index: number) {
|
||||
this.applyModification(chs => deleteChangeSetRows(chs, this.rowDefinition));
|
||||
}
|
||||
|
||||
beginUpdate() {
|
||||
this.batchChangeSet = this.changeSet;
|
||||
}
|
||||
endUpdate() {
|
||||
this.setChangeSet(this.batchChangeSet);
|
||||
this.batchChangeSet = null;
|
||||
}
|
||||
|
||||
revertRowChanges() {
|
||||
this.applyModification(chs => revertChangeSetRowChanges(chs, this.rowDefinition));
|
||||
}
|
||||
revertAllChanges() {
|
||||
this.applyModification(chs => createChangeSet());
|
||||
}
|
||||
undo() {
|
||||
this.dispatchChangeSet({ type: 'undo' });
|
||||
}
|
||||
redo() {
|
||||
this.dispatchChangeSet({ type: 'redo' });
|
||||
}
|
||||
get canUndo() {
|
||||
return this.changeSetState.canUndo;
|
||||
}
|
||||
get canRedo() {
|
||||
return this.changeSetState.canRedo;
|
||||
}
|
||||
get containsChanges() {
|
||||
return changeSetContainsChanges(this.changeSet);
|
||||
}
|
||||
}
|
||||
@@ -1,583 +0,0 @@
|
||||
// @ts-nocheck
|
||||
|
||||
import _ from 'lodash';
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import ColumnLabel from '../datagrid/ColumnLabel';
|
||||
import { findForeignKeyForColumn } from 'dbgate-tools';
|
||||
import styled from 'styled-components';
|
||||
import useTheme from '../theme/useTheme';
|
||||
import useDimensions from '../utility/useDimensions';
|
||||
import FormViewToolbar from './FormViewToolbar';
|
||||
import { useShowMenu } from '../modals/showMenu';
|
||||
import FormViewContextMenu from './FormViewContextMenu';
|
||||
import keycodes from '../utility/keycodes';
|
||||
import { CellFormattedValue, ShowFormButton } from '../datagrid/DataGridRow';
|
||||
import { cellFromEvent } from '../datagrid/selection';
|
||||
import InplaceEditor from '../datagrid/InplaceEditor';
|
||||
import { copyTextToClipboard } from '../utility/clipboard';
|
||||
import { ExpandIcon, FontIcon } from '../icons';
|
||||
import openReferenceForm from './openReferenceForm';
|
||||
import useOpenNewTab from '../utility/useOpenNewTab';
|
||||
import LoadingInfo from '../widgets/LoadingInfo';
|
||||
|
||||
const Table = styled.table`
|
||||
border-collapse: collapse;
|
||||
outline: none;
|
||||
`;
|
||||
|
||||
const OuterWrapper = styled.div`
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
`;
|
||||
|
||||
const Wrapper = styled.div`
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
display: flex;
|
||||
overflow-x: scroll;
|
||||
`;
|
||||
|
||||
const TableRow = styled.tr`
|
||||
background-color: ${props => props.theme.gridbody_background};
|
||||
&:nth-child(6n + 3) {
|
||||
background-color: ${props => props.theme.gridbody_background_alt2};
|
||||
}
|
||||
&:nth-child(6n + 6) {
|
||||
background-color: ${props => props.theme.gridbody_background_alt3};
|
||||
}
|
||||
`;
|
||||
|
||||
const TableHeaderCell = styled.td`
|
||||
border: 1px solid ${props => props.theme.border};
|
||||
text-align: left;
|
||||
padding: 2px;
|
||||
background-color: ${props => props.theme.gridheader_background};
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
|
||||
${props =>
|
||||
props.isSelected &&
|
||||
`
|
||||
background: initial;
|
||||
background-color: ${props.theme.gridbody_selection[4]};
|
||||
color: ${props.theme.gridbody_invfont1};`}
|
||||
`;
|
||||
|
||||
const TableBodyCell = styled.td`
|
||||
font-weight: normal;
|
||||
border: 1px solid ${props => props.theme.border};
|
||||
// border-collapse: collapse;
|
||||
padding: 2px;
|
||||
white-space: nowrap;
|
||||
position: relative;
|
||||
max-width: 500px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
|
||||
${props =>
|
||||
props.isSelected &&
|
||||
`
|
||||
background: initial;
|
||||
background-color: ${props.theme.gridbody_selection[4]};
|
||||
color: ${props.theme.gridbody_invfont1};`}
|
||||
|
||||
${props =>
|
||||
!props.isSelected &&
|
||||
props.isModifiedCell &&
|
||||
`
|
||||
background-color: ${props.theme.gridbody_background_orange[1]};`}
|
||||
`;
|
||||
|
||||
const FocusField = styled.input`
|
||||
// visibility: hidden
|
||||
position: absolute;
|
||||
left: -1000px;
|
||||
top: -1000px;
|
||||
`;
|
||||
|
||||
const RowCountLabel = styled.div`
|
||||
position: absolute;
|
||||
background-color: ${props => props.theme.gridbody_background_yellow[1]};
|
||||
right: 40px;
|
||||
bottom: 20px;
|
||||
`;
|
||||
|
||||
const HintSpan = styled.span`
|
||||
color: gray;
|
||||
margin-left: 5px;
|
||||
margin-right: 16px;
|
||||
`;
|
||||
|
||||
const ColumnLabelMargin = styled(ColumnLabel)`
|
||||
margin-right: 16px;
|
||||
`;
|
||||
|
||||
function isDataCell(cell) {
|
||||
return cell[1] % 2 == 1;
|
||||
}
|
||||
|
||||
export default function FormView(props) {
|
||||
const {
|
||||
toolbarPortalRef,
|
||||
tabVisible,
|
||||
config,
|
||||
setConfig,
|
||||
onNavigate,
|
||||
former,
|
||||
onSave,
|
||||
conid,
|
||||
database,
|
||||
onReload,
|
||||
onReconnect,
|
||||
allRowCount,
|
||||
rowCountBefore,
|
||||
onSelectionChanged,
|
||||
isLoading,
|
||||
} = props;
|
||||
/** @type {import('dbgate-datalib').FormViewDisplay} */
|
||||
const formDisplay = props.formDisplay;
|
||||
const theme = useTheme();
|
||||
const [headerRowRef, { height: rowHeight }] = useDimensions();
|
||||
const [wrapperRef, { height: wrapperHeight }] = useDimensions();
|
||||
const showMenu = useShowMenu();
|
||||
const focusFieldRef = React.useRef(null);
|
||||
const [currentCell, setCurrentCell] = React.useState([0, 0]);
|
||||
const cellRefs = React.useRef({});
|
||||
const openNewTab = useOpenNewTab();
|
||||
|
||||
const rowCount = Math.floor((wrapperHeight - 20) / rowHeight);
|
||||
const columnChunks = _.chunk(formDisplay.columns, rowCount);
|
||||
|
||||
const { rowData, rowStatus } = former;
|
||||
|
||||
const handleSwitchToTable = () => {
|
||||
setConfig(cfg => ({
|
||||
...cfg,
|
||||
isFormView: false,
|
||||
formViewKey: null,
|
||||
}));
|
||||
};
|
||||
|
||||
const handleFilterThisValue = isDataCell(currentCell)
|
||||
? () => formDisplay.filterCellValue(getCellColumn(currentCell), rowData)
|
||||
: null;
|
||||
|
||||
const handleContextMenu = event => {
|
||||
event.preventDefault();
|
||||
showMenu(
|
||||
event.pageX,
|
||||
event.pageY,
|
||||
<FormViewContextMenu
|
||||
switchToTable={handleSwitchToTable}
|
||||
onNavigate={onNavigate}
|
||||
addToFilter={() => formDisplay.addFilterColumn(getCellColumn(currentCell))}
|
||||
filterThisValue={handleFilterThisValue}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
const setCellRef = (row, col, element) => {
|
||||
cellRefs.current[`${row},${col}`] = element;
|
||||
};
|
||||
|
||||
React.useEffect(() => {
|
||||
if (tabVisible) {
|
||||
if (focusFieldRef.current) focusFieldRef.current.focus();
|
||||
}
|
||||
}, [tabVisible, focusFieldRef.current]);
|
||||
|
||||
React.useEffect(() => {
|
||||
if (!onSelectionChanged || !rowData) return;
|
||||
const col = getCellColumn(currentCell);
|
||||
if (!col) return;
|
||||
onSelectionChanged(rowData[col.uniqueName]);
|
||||
}, [onSelectionChanged, currentCell, rowData]);
|
||||
|
||||
const checkMoveCursorBounds = (row, col) => {
|
||||
if (row < 0) row = 0;
|
||||
if (col < 0) col = 0;
|
||||
if (col >= columnChunks.length * 2) col = columnChunks.length * 2 - 1;
|
||||
const chunk = columnChunks[Math.floor(col / 2)];
|
||||
if (chunk && row >= chunk.length) row = chunk.length - 1;
|
||||
return [row, col];
|
||||
};
|
||||
|
||||
const handleCursorMove = event => {
|
||||
if (event.ctrlKey) {
|
||||
switch (event.keyCode) {
|
||||
case keycodes.leftArrow:
|
||||
return checkMoveCursorBounds(currentCell[0], 0);
|
||||
case keycodes.rightArrow:
|
||||
return checkMoveCursorBounds(currentCell[0], columnChunks.length * 2 - 1);
|
||||
}
|
||||
}
|
||||
switch (event.keyCode) {
|
||||
case keycodes.leftArrow:
|
||||
return checkMoveCursorBounds(currentCell[0], currentCell[1] - 1);
|
||||
case keycodes.rightArrow:
|
||||
return checkMoveCursorBounds(currentCell[0], currentCell[1] + 1);
|
||||
case keycodes.upArrow:
|
||||
return checkMoveCursorBounds(currentCell[0] - 1, currentCell[1]);
|
||||
case keycodes.downArrow:
|
||||
return checkMoveCursorBounds(currentCell[0] + 1, currentCell[1]);
|
||||
case keycodes.pageUp:
|
||||
return checkMoveCursorBounds(0, currentCell[1]);
|
||||
case keycodes.pageDown:
|
||||
return checkMoveCursorBounds(rowCount - 1, currentCell[1]);
|
||||
case keycodes.home:
|
||||
return checkMoveCursorBounds(0, 0);
|
||||
case keycodes.end:
|
||||
return checkMoveCursorBounds(rowCount - 1, columnChunks.length * 2 - 1);
|
||||
}
|
||||
};
|
||||
|
||||
const handleKeyNavigation = event => {
|
||||
if (event.ctrlKey) {
|
||||
switch (event.keyCode) {
|
||||
case keycodes.upArrow:
|
||||
return 'previous';
|
||||
case keycodes.downArrow:
|
||||
return 'next';
|
||||
case keycodes.home:
|
||||
return 'begin';
|
||||
case keycodes.end:
|
||||
return 'end';
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function handleSave() {
|
||||
if (inplaceEditorState.cell) {
|
||||
// @ts-ignore
|
||||
dispatchInsplaceEditor({ type: 'shouldSave' });
|
||||
return;
|
||||
}
|
||||
if (onSave) onSave();
|
||||
}
|
||||
|
||||
function getCellColumn(cell) {
|
||||
const chunk = columnChunks[Math.floor(cell[1] / 2)];
|
||||
if (!chunk) return;
|
||||
const column = chunk[cell[0]];
|
||||
return column;
|
||||
}
|
||||
|
||||
function setCellValue(cell, value) {
|
||||
const column = getCellColumn(cell);
|
||||
if (!column) return;
|
||||
former.setCellValue(column.uniqueName, value);
|
||||
}
|
||||
|
||||
function setNull() {
|
||||
if (isDataCell(currentCell)) {
|
||||
setCellValue(currentCell, null);
|
||||
}
|
||||
}
|
||||
|
||||
const scrollIntoView = cell => {
|
||||
const element = cellRefs.current[`${cell[0]},${cell[1]}`];
|
||||
if (element) element.scrollIntoView();
|
||||
};
|
||||
|
||||
React.useEffect(() => {
|
||||
scrollIntoView(currentCell);
|
||||
}, [rowData]);
|
||||
|
||||
const moveCurrentCell = (row, col) => {
|
||||
const moved = checkMoveCursorBounds(row, col);
|
||||
setCurrentCell(moved);
|
||||
scrollIntoView(moved);
|
||||
};
|
||||
|
||||
function copyToClipboard() {
|
||||
const column = getCellColumn(currentCell);
|
||||
if (!column) return;
|
||||
const text = currentCell[1] % 2 == 1 ? rowData[column.uniqueName] : column.columnName;
|
||||
copyTextToClipboard(text);
|
||||
}
|
||||
|
||||
const handleKeyDown = event => {
|
||||
const navigation = handleKeyNavigation(event);
|
||||
if (navigation) {
|
||||
event.preventDefault();
|
||||
onNavigate(navigation);
|
||||
return;
|
||||
}
|
||||
const moved = handleCursorMove(event);
|
||||
if (moved) {
|
||||
setCurrentCell(moved);
|
||||
scrollIntoView(moved);
|
||||
event.preventDefault();
|
||||
return;
|
||||
}
|
||||
if (event.keyCode == keycodes.s && event.ctrlKey) {
|
||||
event.preventDefault();
|
||||
handleSave();
|
||||
// this.saveAndFocus();
|
||||
}
|
||||
|
||||
if (event.keyCode == keycodes.n0 && event.ctrlKey) {
|
||||
event.preventDefault();
|
||||
setNull();
|
||||
}
|
||||
|
||||
if (event.keyCode == keycodes.r && event.ctrlKey) {
|
||||
event.preventDefault();
|
||||
former.revertRowChanges();
|
||||
}
|
||||
|
||||
// if (event.keyCode == keycodes.f && event.ctrlKey) {
|
||||
// event.preventDefault();
|
||||
// filterSelectedValue();
|
||||
// }
|
||||
|
||||
if (event.keyCode == keycodes.z && event.ctrlKey) {
|
||||
event.preventDefault();
|
||||
former.undo();
|
||||
}
|
||||
|
||||
if (event.keyCode == keycodes.y && event.ctrlKey) {
|
||||
event.preventDefault();
|
||||
former.redo();
|
||||
}
|
||||
|
||||
if (event.keyCode == keycodes.c && event.ctrlKey) {
|
||||
event.preventDefault();
|
||||
copyToClipboard();
|
||||
}
|
||||
|
||||
if (event.keyCode == keycodes.f && event.ctrlKey) {
|
||||
event.preventDefault();
|
||||
if (handleFilterThisValue) handleFilterThisValue();
|
||||
}
|
||||
|
||||
if (event.keyCode == keycodes.f5) {
|
||||
event.preventDefault();
|
||||
onReload();
|
||||
}
|
||||
|
||||
if (event.keyCode == keycodes.f4) {
|
||||
event.preventDefault();
|
||||
handleSwitchToTable();
|
||||
}
|
||||
|
||||
if (
|
||||
rowData &&
|
||||
!event.ctrlKey &&
|
||||
!event.altKey &&
|
||||
((event.keyCode >= keycodes.a && event.keyCode <= keycodes.z) ||
|
||||
(event.keyCode >= keycodes.n0 && event.keyCode <= keycodes.n9) ||
|
||||
event.keyCode == keycodes.dash)
|
||||
) {
|
||||
// @ts-ignore
|
||||
dispatchInsplaceEditor({ type: 'show', text: event.nativeEvent.key, cell: currentCell });
|
||||
return;
|
||||
}
|
||||
if (rowData && event.keyCode == keycodes.f2) {
|
||||
// @ts-ignore
|
||||
dispatchInsplaceEditor({ type: 'show', cell: currentCell, selectAll: true });
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
const handleTableMouseDown = event => {
|
||||
event.preventDefault();
|
||||
if (focusFieldRef.current) focusFieldRef.current.focus();
|
||||
|
||||
if (event.target.closest('.buttonLike')) return;
|
||||
if (event.target.closest('.resizeHandleControl')) return;
|
||||
if (event.target.closest('input')) return;
|
||||
|
||||
// event.target.closest('table').focus();
|
||||
event.preventDefault();
|
||||
if (focusFieldRef.current) focusFieldRef.current.focus();
|
||||
const cell = cellFromEvent(event);
|
||||
|
||||
if (isDataCell(cell) && !_.isEqual(cell, inplaceEditorState.cell) && _.isEqual(cell, currentCell)) {
|
||||
// @ts-ignore
|
||||
if (rowData) {
|
||||
dispatchInsplaceEditor({ type: 'show', cell, selectAll: true });
|
||||
}
|
||||
} else if (!_.isEqual(cell, inplaceEditorState.cell)) {
|
||||
// @ts-ignore
|
||||
dispatchInsplaceEditor({ type: 'close' });
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
setCurrentCell(cell);
|
||||
};
|
||||
|
||||
const getCellWidth = (row, col) => {
|
||||
const element = cellRefs.current[`${row},${col}`];
|
||||
if (element) return element.getBoundingClientRect().width;
|
||||
return 100;
|
||||
};
|
||||
|
||||
const rowCountInfo = React.useMemo(() => {
|
||||
if (rowData == null) return 'No data';
|
||||
if (allRowCount == null || rowCountBefore == null) return 'Loading row count...';
|
||||
return `Row: ${(rowCountBefore + 1).toLocaleString()} / ${allRowCount.toLocaleString()}`;
|
||||
}, [rowCountBefore, allRowCount]);
|
||||
|
||||
const [inplaceEditorState, dispatchInsplaceEditor] = React.useReducer((state, action) => {
|
||||
switch (action.type) {
|
||||
case 'show': {
|
||||
const column = getCellColumn(action.cell);
|
||||
if (!column) return state;
|
||||
if (column.uniquePath.length > 1) return state;
|
||||
|
||||
// if (!grider.editable) return {};
|
||||
return {
|
||||
cell: action.cell,
|
||||
text: action.text,
|
||||
selectAll: action.selectAll,
|
||||
};
|
||||
}
|
||||
case 'close': {
|
||||
const [row, col] = currentCell || [];
|
||||
if (focusFieldRef.current) focusFieldRef.current.focus();
|
||||
// @ts-ignore
|
||||
if (action.mode == 'enter' && row) setTimeout(() => moveCurrentCell(row + 1, col), 0);
|
||||
// if (action.mode == 'save') setTimeout(handleSave, 0);
|
||||
return {};
|
||||
}
|
||||
case 'shouldSave': {
|
||||
return {
|
||||
...state,
|
||||
shouldSave: true,
|
||||
};
|
||||
}
|
||||
}
|
||||
return {};
|
||||
}, {});
|
||||
|
||||
const toolbar =
|
||||
toolbarPortalRef &&
|
||||
toolbarPortalRef.current &&
|
||||
tabVisible &&
|
||||
ReactDOM.createPortal(
|
||||
<FormViewToolbar
|
||||
switchToTable={handleSwitchToTable}
|
||||
onNavigate={onNavigate}
|
||||
reload={onReload}
|
||||
reconnect={onReconnect}
|
||||
save={handleSave}
|
||||
former={former}
|
||||
/>,
|
||||
toolbarPortalRef.current
|
||||
);
|
||||
|
||||
if (isLoading) {
|
||||
return (
|
||||
<>
|
||||
<LoadingInfo wrapper message="Loading data" />
|
||||
{toolbar}
|
||||
</>
|
||||
);
|
||||
}
|
||||
if (!formDisplay || !formDisplay.isLoadedCorrectly) return toolbar;
|
||||
|
||||
return (
|
||||
<OuterWrapper>
|
||||
<Wrapper ref={wrapperRef} onContextMenu={handleContextMenu}>
|
||||
{columnChunks.map((chunk, chunkIndex) => (
|
||||
<Table key={chunkIndex} onMouseDown={handleTableMouseDown}>
|
||||
{chunk.map((col, rowIndex) => (
|
||||
<TableRow key={col.uniqueName} theme={theme} ref={headerRowRef} style={{ height: `${rowHeight}px` }}>
|
||||
<TableHeaderCell
|
||||
theme={theme}
|
||||
data-row={rowIndex}
|
||||
data-col={chunkIndex * 2}
|
||||
// @ts-ignore
|
||||
isSelected={currentCell[0] == rowIndex && currentCell[1] == chunkIndex * 2}
|
||||
ref={element => setCellRef(rowIndex, chunkIndex * 2, element)}
|
||||
>
|
||||
<ColumnLabelMargin
|
||||
{...col}
|
||||
headerText={col.columnName}
|
||||
style={{ marginLeft: (col.uniquePath.length - 1) * 20 }}
|
||||
extInfo={col.foreignKey ? ` -> ${col.foreignKey.refTableName}` : null}
|
||||
/>
|
||||
|
||||
{col.foreignKey && (
|
||||
<ShowFormButton
|
||||
theme={theme}
|
||||
className="buttonLike"
|
||||
onClick={e => {
|
||||
e.stopPropagation();
|
||||
formDisplay.toggleExpandedColumn(col.uniqueName);
|
||||
}}
|
||||
>
|
||||
<ExpandIcon isExpanded={formDisplay.isExpandedColumn(col.uniqueName)} />
|
||||
</ShowFormButton>
|
||||
)}
|
||||
</TableHeaderCell>
|
||||
<TableBodyCell
|
||||
theme={theme}
|
||||
data-row={rowIndex}
|
||||
data-col={chunkIndex * 2 + 1}
|
||||
// @ts-ignore
|
||||
isSelected={currentCell[0] == rowIndex && currentCell[1] == chunkIndex * 2 + 1}
|
||||
isModifiedCell={rowStatus.modifiedFields && rowStatus.modifiedFields.has(col.uniqueName)}
|
||||
ref={element => setCellRef(rowIndex, chunkIndex * 2 + 1, element)}
|
||||
>
|
||||
{inplaceEditorState.cell &&
|
||||
rowIndex == inplaceEditorState.cell[0] &&
|
||||
chunkIndex * 2 + 1 == inplaceEditorState.cell[1] ? (
|
||||
<InplaceEditor
|
||||
widthPx={getCellWidth(rowIndex, chunkIndex * 2 + 1)}
|
||||
inplaceEditorState={inplaceEditorState}
|
||||
dispatchInsplaceEditor={dispatchInsplaceEditor}
|
||||
cellValue={rowData[col.uniqueName]}
|
||||
onSetValue={value => {
|
||||
former.setCellValue(col.uniqueName, value);
|
||||
}}
|
||||
// grider={grider}
|
||||
// rowIndex={rowIndex}
|
||||
// uniqueName={col.uniqueName}
|
||||
/>
|
||||
) : (
|
||||
<>
|
||||
{rowData && (
|
||||
<CellFormattedValue value={rowData[col.uniqueName]} dataType={col.dataType} theme={theme} />
|
||||
)}
|
||||
{!!col.hintColumnName &&
|
||||
rowData &&
|
||||
!(rowStatus.modifiedFields && rowStatus.modifiedFields.has(col.uniqueName)) && (
|
||||
<HintSpan>{rowData[col.hintColumnName]}</HintSpan>
|
||||
)}
|
||||
{col.foreignKey && rowData && rowData[col.uniqueName] && (
|
||||
<ShowFormButton
|
||||
theme={theme}
|
||||
className="buttonLike"
|
||||
onClick={e => {
|
||||
e.stopPropagation();
|
||||
openReferenceForm(rowData, col, openNewTab, conid, database);
|
||||
}}
|
||||
>
|
||||
<FontIcon icon="icon form" />
|
||||
</ShowFormButton>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</TableBodyCell>
|
||||
</TableRow>
|
||||
))}
|
||||
</Table>
|
||||
))}
|
||||
|
||||
<FocusField type="text" ref={focusFieldRef} onKeyDown={handleKeyDown} />
|
||||
|
||||
{toolbar}
|
||||
</Wrapper>
|
||||
{rowCountInfo && <RowCountLabel theme={theme}>{rowCountInfo}</RowCountLabel>}
|
||||
</OuterWrapper>
|
||||
);
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
import React from 'react';
|
||||
import { DropDownMenuItem, DropDownMenuDivider } from '../modals/DropDownMenu';
|
||||
|
||||
export default function FormViewContextMenu({ switchToTable, onNavigate, addToFilter, filterThisValue }) {
|
||||
return (
|
||||
<>
|
||||
<DropDownMenuItem onClick={switchToTable} keyText="F4">
|
||||
Table view
|
||||
</DropDownMenuItem>
|
||||
{addToFilter && <DropDownMenuItem onClick={addToFilter}>Add to filter</DropDownMenuItem>}
|
||||
{filterThisValue && (
|
||||
<DropDownMenuItem onClick={filterThisValue} keyText="Ctrl+F">
|
||||
Filter this value
|
||||
</DropDownMenuItem>
|
||||
)}
|
||||
<DropDownMenuDivider />
|
||||
<DropDownMenuItem onClick={() => onNavigate('begin')} keyText="Ctrl+Home">
|
||||
Navigate to begin
|
||||
</DropDownMenuItem>
|
||||
<DropDownMenuItem onClick={() => onNavigate('previous')} keyText="Ctrl+Up">
|
||||
Navigate to previous
|
||||
</DropDownMenuItem>
|
||||
<DropDownMenuItem onClick={() => onNavigate('next')} keyText="Ctrl+Down">
|
||||
Navigate to next
|
||||
</DropDownMenuItem>
|
||||
<DropDownMenuItem onClick={() => onNavigate('end')} keyText="Ctrl+End">
|
||||
Navigate to end
|
||||
</DropDownMenuItem>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -1,116 +0,0 @@
|
||||
import React from 'react';
|
||||
import _ from 'lodash';
|
||||
import { ManagerInnerContainer } from '../datagrid/ManagerStyles';
|
||||
import styled from 'styled-components';
|
||||
import ColumnLabel from '../datagrid/ColumnLabel';
|
||||
import { TextField } from '../utility/inputs';
|
||||
import { getFilterType } from 'dbgate-filterparser';
|
||||
import DataFilterControl from '../datagrid/DataFilterControl';
|
||||
import InlineButton from '../widgets/InlineButton';
|
||||
import { FontIcon } from '../icons';
|
||||
import keycodes from '../utility/keycodes';
|
||||
|
||||
const ColumnWrapper = styled.div`
|
||||
margin: 5px;
|
||||
`;
|
||||
const ColumnNameWrapper = styled.div`
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
`;
|
||||
|
||||
const TextFieldWrapper = styled.div`
|
||||
display: flex;
|
||||
`;
|
||||
const StyledTextField = styled(TextField)`
|
||||
flex: 1;
|
||||
`;
|
||||
|
||||
function PrimaryKeyFilterEditor({ column, baseTable, formDisplay }) {
|
||||
const value = formDisplay.getKeyValue(column.columnName);
|
||||
const editorRef = React.useRef(null);
|
||||
|
||||
React.useEffect(() => {
|
||||
if (editorRef.current) {
|
||||
editorRef.current.value = value;
|
||||
}
|
||||
}, [value, editorRef.current]);
|
||||
|
||||
const applyFilter = () => {
|
||||
formDisplay.requestKeyValue(column.columnName, editorRef.current.value);
|
||||
};
|
||||
|
||||
const cancelFilter = () => {
|
||||
formDisplay.cancelRequestKey();
|
||||
formDisplay.reload();
|
||||
};
|
||||
|
||||
const handleKeyDown = ev => {
|
||||
if (ev.keyCode == keycodes.enter) {
|
||||
applyFilter();
|
||||
}
|
||||
if (ev.keyCode == keycodes.escape) {
|
||||
cancelFilter();
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<ColumnWrapper>
|
||||
<ColumnNameWrapper>
|
||||
<div>
|
||||
<FontIcon icon="img primary-key" />
|
||||
<ColumnLabel {...baseTable.columns.find(x => x.columnName == column.columnName)} />
|
||||
</div>
|
||||
{formDisplay.config.formViewKeyRequested && (
|
||||
<InlineButton square onClick={cancelFilter}>
|
||||
<FontIcon icon="icon delete" />
|
||||
</InlineButton>
|
||||
)}
|
||||
</ColumnNameWrapper>
|
||||
<TextFieldWrapper>
|
||||
<StyledTextField editorRef={editorRef} onBlur={applyFilter} onKeyDown={handleKeyDown} />
|
||||
</TextFieldWrapper>
|
||||
</ColumnWrapper>
|
||||
);
|
||||
}
|
||||
|
||||
export default function FormViewFilters(props) {
|
||||
const { formDisplay } = props;
|
||||
if (!formDisplay || !formDisplay.baseTable || !formDisplay.baseTable.primaryKey) return null;
|
||||
const { baseTable } = formDisplay;
|
||||
const { formFilterColumns, filters } = formDisplay.config || {};
|
||||
|
||||
const allFilterNames = _.union(_.keys(filters || {}), formFilterColumns || []);
|
||||
|
||||
return (
|
||||
<ManagerInnerContainer style={{ maxWidth: props.managerSize }}>
|
||||
{baseTable.primaryKey.columns.map(col => (
|
||||
<PrimaryKeyFilterEditor key={col.columnName} baseTable={baseTable} column={col} formDisplay={formDisplay} />
|
||||
))}
|
||||
{allFilterNames.map(uniqueName => {
|
||||
const column = formDisplay.columns.find(x => x.uniqueName == uniqueName)
|
||||
// const column = baseTable.columns.find(x => x.columnName == columnName);
|
||||
if (!column) return null;
|
||||
return (
|
||||
<ColumnWrapper key={uniqueName}>
|
||||
<ColumnNameWrapper>
|
||||
<ColumnLabel {...column} />
|
||||
<InlineButton
|
||||
square
|
||||
onClick={() => {
|
||||
formDisplay.removeFilter(column.uniqueName);
|
||||
}}
|
||||
>
|
||||
<FontIcon icon="icon delete" />
|
||||
</InlineButton>
|
||||
</ColumnNameWrapper>
|
||||
<DataFilterControl
|
||||
filterType={getFilterType(column.dataType)}
|
||||
filter={filters[column.uniqueName]}
|
||||
setFilter={value => formDisplay.setFilter(column.uniqueName, value)}
|
||||
/>
|
||||
</ColumnWrapper>
|
||||
);
|
||||
})}
|
||||
</ManagerInnerContainer>
|
||||
);
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
import React from 'react';
|
||||
import ToolbarButton from '../widgets/ToolbarButton';
|
||||
|
||||
export default function FormViewToolbar({ switchToTable, onNavigate, reload, reconnect, former, save }) {
|
||||
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>
|
||||
<ToolbarButton onClick={reload} icon="icon reload">
|
||||
Refresh
|
||||
</ToolbarButton>
|
||||
<ToolbarButton onClick={reconnect} icon="icon connection">
|
||||
Reconnect
|
||||
</ToolbarButton>
|
||||
<ToolbarButton disabled={!former.canUndo} onClick={() => former.undo()} icon="icon undo">
|
||||
Undo
|
||||
</ToolbarButton>
|
||||
<ToolbarButton disabled={!former.canRedo} onClick={() => former.redo()} icon="icon redo">
|
||||
Redo
|
||||
</ToolbarButton>
|
||||
<ToolbarButton disabled={!former.allowSave} onClick={save} icon="icon save">
|
||||
Save
|
||||
</ToolbarButton>
|
||||
<ToolbarButton disabled={!former.containsChanges} onClick={() => former.revertAllChanges()} icon="icon close">
|
||||
Revert
|
||||
</ToolbarButton>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
// export interface GriderRowStatus {
|
||||
// status: 'regular' | 'updated' | 'deleted' | 'inserted';
|
||||
// modifiedFields?: Set<string>;
|
||||
// insertedFields?: Set<string>;
|
||||
// deletedFields?: Set<string>;
|
||||
// }
|
||||
|
||||
export default abstract class Former {
|
||||
public rowData: any;
|
||||
|
||||
// getRowStatus(index): GriderRowStatus {
|
||||
// const res: GriderRowStatus = {
|
||||
// status: 'regular',
|
||||
// };
|
||||
// return res;
|
||||
// }
|
||||
beginUpdate() {}
|
||||
endUpdate() {}
|
||||
setCellValue(uniqueName: string, value: any) {}
|
||||
revertRowChanges() {}
|
||||
revertAllChanges() {}
|
||||
undo() {}
|
||||
redo() {}
|
||||
get editable() {
|
||||
return false;
|
||||
}
|
||||
get canInsert() {
|
||||
return false;
|
||||
}
|
||||
get allowSave() {
|
||||
return this.containsChanges;
|
||||
}
|
||||
get canUndo() {
|
||||
return false;
|
||||
}
|
||||
get canRedo() {
|
||||
return false;
|
||||
}
|
||||
get containsChanges() {
|
||||
return false;
|
||||
}
|
||||
get disableLoadNextPage() {
|
||||
return false;
|
||||
}
|
||||
get errors() {
|
||||
return null;
|
||||
}
|
||||
updateRow(changeObject) {
|
||||
for (const key of Object.keys(changeObject)) {
|
||||
this.setCellValue(key, changeObject[key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,294 +0,0 @@
|
||||
import { changeSetToSql, createChangeSet, TableFormViewDisplay } from 'dbgate-datalib';
|
||||
import { findEngineDriver } from 'dbgate-tools';
|
||||
import React from 'react';
|
||||
import { useConnectionInfo, useDatabaseInfo } from '../utility/metadataLoaders';
|
||||
import useExtensions from '../utility/useExtensions';
|
||||
import FormView from './FormView';
|
||||
import axios from '../utility/axios';
|
||||
import ChangeSetFormer from './ChangeSetFormer';
|
||||
import ConfirmSqlModal from '../modals/ConfirmSqlModal';
|
||||
import ErrorMessageModal from '../modals/ErrorMessageModal';
|
||||
import { scriptToSql } from 'dbgate-sqltree';
|
||||
import useModalState from '../modals/useModalState';
|
||||
import useShowModal from '../modals/showModal';
|
||||
import stableStringify from 'json-stable-stringify';
|
||||
|
||||
async function loadRow(props, sql) {
|
||||
const { conid, database } = props;
|
||||
|
||||
if (!sql) return null;
|
||||
|
||||
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) {
|
||||
// console.log('SqlFormView', props);
|
||||
const {
|
||||
formDisplay,
|
||||
changeSetState,
|
||||
dispatchChangeSet,
|
||||
conid,
|
||||
database,
|
||||
onReferenceSourceChanged,
|
||||
refReloadToken,
|
||||
} = props;
|
||||
// const [rowData, setRowData] = React.useState(null);
|
||||
// const [reloadToken, setReloadToken] = React.useState(0);
|
||||
// const [rowCountInfo, setRowCountInfo] = React.useState(null);
|
||||
// const [isLoading, setIsLoading] = React.useState(false);
|
||||
// const loadedFiltersRef = React.useRef('');
|
||||
|
||||
const confirmSqlModalState = useModalState();
|
||||
const [confirmSql, setConfirmSql] = React.useState('');
|
||||
const showModal = useShowModal();
|
||||
|
||||
const changeSet = changeSetState && changeSetState.value;
|
||||
const changeSetRef = React.useRef(changeSet);
|
||||
changeSetRef.current = changeSet;
|
||||
|
||||
const [loadProps, setLoadProps] = React.useState({
|
||||
isLoadingData: false,
|
||||
isLoadedData: false,
|
||||
rowData: null,
|
||||
isLoadingCount: false,
|
||||
isLoadedCount: false,
|
||||
loadedTime: new Date().getTime(),
|
||||
allRowCount: null,
|
||||
rowCountBefore: null,
|
||||
errorMessage: null,
|
||||
});
|
||||
const {
|
||||
isLoadingData,
|
||||
rowData,
|
||||
isLoadedData,
|
||||
isLoadingCount,
|
||||
isLoadedCount,
|
||||
loadedTime,
|
||||
allRowCount,
|
||||
rowCountBefore,
|
||||
errorMessage,
|
||||
} = loadProps;
|
||||
|
||||
const handleLoadCurrentRow = async () => {
|
||||
if (isLoadingData) return;
|
||||
let newLoadedRow = false;
|
||||
if (formDisplay.config.formViewKeyRequested || formDisplay.config.formViewKey) {
|
||||
setLoadProps(oldLoadProps => ({
|
||||
...oldLoadProps,
|
||||
isLoadingData: true,
|
||||
}));
|
||||
const row = await loadRow(props, formDisplay.getCurrentRowQuery());
|
||||
setLoadProps(oldLoadProps => ({
|
||||
...oldLoadProps,
|
||||
isLoadingData: false,
|
||||
isLoadedData: true,
|
||||
rowData: row,
|
||||
loadedTime: new Date().getTime(),
|
||||
}));
|
||||
newLoadedRow = row;
|
||||
}
|
||||
if (formDisplay.config.formViewKeyRequested && newLoadedRow) {
|
||||
formDisplay.cancelRequestKey(newLoadedRow);
|
||||
}
|
||||
if (!newLoadedRow && !formDisplay.config.formViewKeyRequested) {
|
||||
await handleNavigate('first');
|
||||
}
|
||||
};
|
||||
|
||||
const handleLoadRowCount = async () => {
|
||||
setLoadProps(oldLoadProps => ({
|
||||
...oldLoadProps,
|
||||
isLoadingCount: true,
|
||||
}));
|
||||
const countRow = await loadRow(props, formDisplay.getCountQuery());
|
||||
const countBeforeRow = await loadRow(props, formDisplay.getBeforeCountQuery());
|
||||
|
||||
setLoadProps(oldLoadProps => ({
|
||||
...oldLoadProps,
|
||||
isLoadedCount: true,
|
||||
isLoadingCount: false,
|
||||
allRowCount: countRow ? parseInt(countRow.count) : null,
|
||||
rowCountBefore: countBeforeRow ? parseInt(countBeforeRow.count) : null,
|
||||
}));
|
||||
};
|
||||
|
||||
const handleNavigate = async command => {
|
||||
setLoadProps(oldLoadProps => ({
|
||||
...oldLoadProps,
|
||||
isLoadingData: true,
|
||||
}));
|
||||
const row = await loadRow(props, formDisplay.navigateRowQuery(command));
|
||||
if (row) {
|
||||
formDisplay.navigate(row);
|
||||
}
|
||||
setLoadProps(oldLoadProps => ({
|
||||
...oldLoadProps,
|
||||
isLoadingData: false,
|
||||
isLoadedData: true,
|
||||
isLoadedCount: false,
|
||||
allRowCount: null,
|
||||
rowCountBefore: null,
|
||||
rowData: row,
|
||||
loadedTime: new Date().getTime(),
|
||||
}));
|
||||
};
|
||||
|
||||
React.useEffect(() => {
|
||||
if (onReferenceSourceChanged && rowData) onReferenceSourceChanged([rowData], loadedTime);
|
||||
}, [onReferenceSourceChanged, rowData, refReloadToken]);
|
||||
|
||||
React.useEffect(() => {
|
||||
if (!formDisplay.isLoadedCorrectly) return;
|
||||
if (!isLoadedData && !isLoadingData) handleLoadCurrentRow();
|
||||
if (isLoadedData && !isLoadingCount && !isLoadedCount) handleLoadRowCount();
|
||||
});
|
||||
|
||||
// React.useEffect(() => {
|
||||
// loadedFiltersRef.current = formDisplay ? stableStringify(formDisplay.config) : null;
|
||||
// }, [rowData]);
|
||||
|
||||
// React.useEffect(() => {
|
||||
// if (formDisplay) handleLoadCurrentRow();
|
||||
// setRowCountInfo(null);
|
||||
// handleLoadRowCount();
|
||||
// }, [reloadToken]);
|
||||
|
||||
// React.useEffect(() => {
|
||||
// if (!formDisplay.isLoadedCorrectly) return;
|
||||
|
||||
// if (
|
||||
// formDisplay &&
|
||||
// (!formDisplay.isLoadedCurrentRow(rowData) ||
|
||||
// loadedFiltersRef.current != stableStringify(formDisplay.config.filters))
|
||||
// ) {
|
||||
// handleLoadCurrentRow();
|
||||
// }
|
||||
// setRowCountInfo(null);
|
||||
// handleLoadRowCount();
|
||||
// }, [formDisplay]);
|
||||
|
||||
const reload = () => {
|
||||
setLoadProps({
|
||||
isLoadingData: false,
|
||||
isLoadedData: false,
|
||||
isLoadingCount: false,
|
||||
isLoadedCount: false,
|
||||
rowData: null,
|
||||
loadedTime: new Date().getTime(),
|
||||
allRowCount: null,
|
||||
rowCountBefore: null,
|
||||
errorMessage: null,
|
||||
});
|
||||
};
|
||||
|
||||
React.useEffect(() => {
|
||||
if (props.masterLoadedTime && props.masterLoadedTime > loadedTime) {
|
||||
formDisplay.reload();
|
||||
}
|
||||
if (formDisplay.cache.refreshTime > loadedTime) {
|
||||
reload();
|
||||
}
|
||||
});
|
||||
|
||||
const former = React.useMemo(() => new ChangeSetFormer(rowData, changeSetState, dispatchChangeSet, formDisplay), [
|
||||
rowData,
|
||||
changeSetState,
|
||||
dispatchChangeSet,
|
||||
formDisplay,
|
||||
]);
|
||||
|
||||
function handleSave() {
|
||||
const script = changeSetToSql(changeSetRef.current, formDisplay.dbinfo);
|
||||
const sql = scriptToSql(formDisplay.driver, script);
|
||||
setConfirmSql(sql);
|
||||
confirmSqlModalState.open();
|
||||
}
|
||||
|
||||
async function handleConfirmSql() {
|
||||
const resp = await axios.request({
|
||||
url: 'database-connections/query-data',
|
||||
method: 'post',
|
||||
params: {
|
||||
conid,
|
||||
database,
|
||||
},
|
||||
data: { sql: confirmSql },
|
||||
});
|
||||
const { errorMessage } = resp.data || {};
|
||||
if (errorMessage) {
|
||||
showModal(modalState => (
|
||||
<ErrorMessageModal modalState={modalState} message={errorMessage} title="Error when saving" />
|
||||
));
|
||||
} else {
|
||||
dispatchChangeSet({ type: 'reset', value: createChangeSet() });
|
||||
setConfirmSql(null);
|
||||
formDisplay.reload();
|
||||
// setReloadToken((x) => x + 1);
|
||||
}
|
||||
}
|
||||
|
||||
// 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}
|
||||
onNavigate={handleNavigate}
|
||||
former={former}
|
||||
onSave={handleSave}
|
||||
isLoading={isLoadingData}
|
||||
onReload={() => formDisplay.reload()}
|
||||
onReconnect={async () => {
|
||||
await axios.post('database-connections/refresh', { conid, database });
|
||||
formDisplay.reload();
|
||||
}}
|
||||
allRowCount={allRowCount}
|
||||
rowCountBefore={rowCountBefore}
|
||||
/>
|
||||
<ConfirmSqlModal
|
||||
modalState={confirmSqlModalState}
|
||||
sql={confirmSql}
|
||||
engine={formDisplay.engine}
|
||||
onConfirm={handleConfirmSql}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
import _ from 'lodash';
|
||||
|
||||
export default function openReferenceForm(rowData, column, openNewTab, conid, database) {
|
||||
const formViewKey = _.fromPairs(
|
||||
column.foreignKey.columns.map(({ refColumnName, columnName }) => [refColumnName, rowData[columnName]])
|
||||
);
|
||||
openNewTab(
|
||||
{
|
||||
title: column.foreignKey.refTableName,
|
||||
icon: 'img table',
|
||||
tabComponent: 'TableDataTab',
|
||||
props: {
|
||||
schemaName: column.foreignKey.refSchemaName,
|
||||
pureName: column.foreignKey.refTableName,
|
||||
conid,
|
||||
database,
|
||||
objectTypeField: 'tables',
|
||||
},
|
||||
},
|
||||
{
|
||||
grid: {
|
||||
isFormView: true,
|
||||
formViewKey,
|
||||
},
|
||||
},
|
||||
{
|
||||
forceNewTab: true,
|
||||
}
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user