mirror of
https://github.com/DeNNiiInc/dbgate.git
synced 2026-04-23 23:05:59 +00:00
formview - basic display
This commit is contained in:
@@ -21,31 +21,51 @@ const DataGridContainer = styled.div`
|
||||
`;
|
||||
|
||||
export default function DataGrid(props) {
|
||||
const { GridCore } = props;
|
||||
const { GridCore, FormView } = props;
|
||||
const theme = useTheme();
|
||||
const [managerSize, setManagerSize] = React.useState(0);
|
||||
const [selection, setSelection] = React.useState([]);
|
||||
const [grider, setGrider] = React.useState(null);
|
||||
const [formViewData, setFormViewData] = React.useState(null);
|
||||
const isFormView = !!formViewData;
|
||||
|
||||
const handleSetFormView = (rowData) => {
|
||||
setFormViewData(rowData);
|
||||
};
|
||||
|
||||
return (
|
||||
<HorizontalSplitter initialValue="300px" size={managerSize} setSize={setManagerSize}>
|
||||
<LeftContainer theme={theme}>
|
||||
<WidgetColumnBar>
|
||||
<WidgetColumnBarItem title="Columns" name="columns" height={props.showReferences ? '40%' : '60%'}>
|
||||
<ColumnManager {...props} managerSize={managerSize} />
|
||||
</WidgetColumnBarItem>
|
||||
{!isFormView && (
|
||||
<WidgetColumnBarItem title="Columns" name="columns" height={props.showReferences ? '40%' : '60%'}>
|
||||
<ColumnManager {...props} managerSize={managerSize} />
|
||||
</WidgetColumnBarItem>
|
||||
)}
|
||||
{props.showReferences && props.display.hasReferences && (
|
||||
<WidgetColumnBarItem title="References" name="references" height="30%" collapsed={props.isDetailView}>
|
||||
<ReferenceManager {...props} managerSize={managerSize} />
|
||||
</WidgetColumnBarItem>
|
||||
)}
|
||||
<WidgetColumnBarItem title="Cell data" name="cellData" collapsed={props.isDetailView}>
|
||||
<CellDataView selection={selection} grider={grider} />
|
||||
</WidgetColumnBarItem>
|
||||
{!isFormView && (
|
||||
<WidgetColumnBarItem title="Cell data" name="cellData" collapsed={props.isDetailView}>
|
||||
<CellDataView selection={selection} grider={grider} />
|
||||
</WidgetColumnBarItem>
|
||||
)}
|
||||
</WidgetColumnBar>
|
||||
</LeftContainer>
|
||||
|
||||
<DataGridContainer>
|
||||
<GridCore {...props} onSelectionChanged={setSelection} onChangeGrider={setGrider} />
|
||||
{isFormView ? (
|
||||
<FormView {...props} rowData={formViewData} />
|
||||
) : (
|
||||
<GridCore
|
||||
{...props}
|
||||
onSelectionChanged={setSelection}
|
||||
onChangeGrider={setGrider}
|
||||
onSetFormView={FormView ? handleSetFormView : null}
|
||||
/>
|
||||
)}
|
||||
</DataGridContainer>
|
||||
</HorizontalSplitter>
|
||||
);
|
||||
|
||||
@@ -116,6 +116,7 @@ export default function DataGridCore(props) {
|
||||
onSelectionChanged,
|
||||
frameSelection,
|
||||
onKeyDown,
|
||||
onSetFormView,
|
||||
} = props;
|
||||
// console.log('RENDER GRID', display.baseTable.pureName);
|
||||
const columns = React.useMemo(() => display.allColumns, [display]);
|
||||
@@ -1047,6 +1048,7 @@ export default function DataGridCore(props) {
|
||||
display={display}
|
||||
focusedColumn={display.focusedColumn}
|
||||
frameSelection={frameSelection}
|
||||
onSetFormView={onSetFormView}
|
||||
/>
|
||||
)
|
||||
)}
|
||||
|
||||
@@ -7,6 +7,7 @@ import InplaceEditor from './InplaceEditor';
|
||||
import { cellIsSelected } from './gridutil';
|
||||
import { isTypeLogical } from 'dbgate-tools';
|
||||
import useTheme from '../theme/useTheme';
|
||||
import { FontIcon } from '../icons';
|
||||
|
||||
const TableBodyCell = styled.td`
|
||||
font-weight: normal;
|
||||
@@ -114,6 +115,7 @@ const TableHeaderCell = styled.td`
|
||||
padding: 2px;
|
||||
background-color: ${(props) => props.theme.gridheader_background};
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
`;
|
||||
|
||||
const AutoFillPoint = styled.div`
|
||||
@@ -127,6 +129,16 @@ const AutoFillPoint = styled.div`
|
||||
cursor: crosshair;
|
||||
`;
|
||||
|
||||
const ShowFormButton = styled.div`
|
||||
position: absolute;
|
||||
right: 2px;
|
||||
top: 2px;
|
||||
&:hover {
|
||||
background-color: ${(props) => props.theme.gridheader_background_blue[4]};
|
||||
border: 1px solid ${(props) => props.theme.border};
|
||||
}
|
||||
`;
|
||||
|
||||
function makeBulletString(value) {
|
||||
return _.pad('', value.length, '•');
|
||||
}
|
||||
@@ -167,6 +179,33 @@ function CellFormattedValue({ value, dataType }) {
|
||||
return value.toString();
|
||||
}
|
||||
|
||||
function RowHeaderCell({ rowIndex, theme, onSetFormView, rowData }) {
|
||||
const [mouseIn, setMouseIn] = React.useState(false);
|
||||
|
||||
return (
|
||||
<TableHeaderCell
|
||||
data-row={rowIndex}
|
||||
data-col="header"
|
||||
theme={theme}
|
||||
onMouseEnter={onSetFormView ? () => setMouseIn(true) : null}
|
||||
onMouseLeave={onSetFormView ? () => setMouseIn(false) : null}
|
||||
>
|
||||
{rowIndex + 1}
|
||||
{!!onSetFormView && mouseIn && (
|
||||
<ShowFormButton
|
||||
theme={theme}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
onSetFormView(rowData);
|
||||
}}
|
||||
>
|
||||
<FontIcon icon="icon form" />
|
||||
</ShowFormButton>
|
||||
)}
|
||||
</TableHeaderCell>
|
||||
);
|
||||
}
|
||||
|
||||
/** @param props {import('./types').DataGridProps} */
|
||||
function DataGridRow(props) {
|
||||
const {
|
||||
@@ -181,6 +220,7 @@ function DataGridRow(props) {
|
||||
focusedColumn,
|
||||
grider,
|
||||
frameSelection,
|
||||
onSetFormView,
|
||||
} = props;
|
||||
// usePropsCompare({
|
||||
// rowHeight,
|
||||
@@ -217,9 +257,8 @@ function DataGridRow(props) {
|
||||
|
||||
return (
|
||||
<TableBodyRow style={{ height: `${rowHeight}px` }} theme={theme}>
|
||||
<TableHeaderCell data-row={rowIndex} data-col="header" theme={theme}>
|
||||
{rowIndex + 1}
|
||||
</TableHeaderCell>
|
||||
<RowHeaderCell rowIndex={rowIndex} theme={theme} onSetFormView={onSetFormView} rowData={rowData} />
|
||||
|
||||
{visibleRealColumns.map((col) => (
|
||||
<TableBodyCell
|
||||
key={col.uniqueName}
|
||||
|
||||
@@ -12,6 +12,7 @@ import stableStringify from 'json-stable-stringify';
|
||||
import ReferenceHeader from './ReferenceHeader';
|
||||
import SqlDataGridCore from './SqlDataGridCore';
|
||||
import useExtensions from '../utility/useExtensions';
|
||||
import SqlFormView from '../formview/SqlFormView';
|
||||
|
||||
const ReferenceContainer = styled.div`
|
||||
position: absolute;
|
||||
@@ -171,7 +172,11 @@ export default function TableDataGrid({
|
||||
refReloadToken={refReloadToken.toString()}
|
||||
masterLoadedTime={masterLoadedTime}
|
||||
GridCore={SqlDataGridCore}
|
||||
FormView={SqlFormView}
|
||||
isDetailView={isDetailView}
|
||||
tableInfo={
|
||||
dbinfo && dbinfo.tables && dbinfo.tables.find((x) => x.pureName == pureName && x.schemaName == schemaName)
|
||||
}
|
||||
/>
|
||||
{reference && (
|
||||
<ReferenceContainer>
|
||||
|
||||
88
packages/web/src/formview/FormView.js
Normal file
88
packages/web/src/formview/FormView.js
Normal file
@@ -0,0 +1,88 @@
|
||||
import _ from 'lodash';
|
||||
import React from 'react';
|
||||
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';
|
||||
|
||||
const Table = styled.table`
|
||||
border-collapse: collapse;
|
||||
outline: none;
|
||||
`;
|
||||
|
||||
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;
|
||||
`;
|
||||
|
||||
const TableBodyCell = styled.td`
|
||||
font-weight: normal;
|
||||
border: 1px solid ${(props) => props.theme.border};
|
||||
// border-collapse: collapse;
|
||||
padding: 2px;
|
||||
white-space: nowrap;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
`;
|
||||
|
||||
const HintSpan = styled.span`
|
||||
color: gray;
|
||||
margin-left: 5px;
|
||||
`;
|
||||
const NullSpan = styled.span`
|
||||
color: gray;
|
||||
font-style: italic;
|
||||
`;
|
||||
|
||||
export default function FormView({ tableInfo, rowData }) {
|
||||
const theme = useTheme();
|
||||
const [headerRowRef, { height: rowHeight }] = useDimensions();
|
||||
const [wrapperRef, { height: wrapperHeight }] = useDimensions();
|
||||
|
||||
if (!tableInfo || !rowData) return null;
|
||||
|
||||
const rowCount = Math.floor((wrapperHeight - 20) / rowHeight);
|
||||
const columnChunks = _.chunk(tableInfo.columns, rowCount);
|
||||
|
||||
return (
|
||||
<Wrapper ref={wrapperRef}>
|
||||
{columnChunks.map((chunk, index) => (
|
||||
<Table key={index}>
|
||||
{chunk.map((col) => (
|
||||
<TableRow key={col.columnName} theme={theme} ref={headerRowRef} style={{ height: `${rowHeight}px` }}>
|
||||
<TableHeaderCell theme={theme}>
|
||||
<ColumnLabel {...col} foreignKey={findForeignKeyForColumn(tableInfo, col)} />
|
||||
</TableHeaderCell>
|
||||
<TableBodyCell theme={theme}>{rowData[col.columnName]}</TableBodyCell>
|
||||
</TableRow>
|
||||
))}
|
||||
</Table>
|
||||
))}
|
||||
</Wrapper>
|
||||
);
|
||||
}
|
||||
6
packages/web/src/formview/SqlFormView.js
Normal file
6
packages/web/src/formview/SqlFormView.js
Normal file
@@ -0,0 +1,6 @@
|
||||
import React from 'react';
|
||||
import FormView from './FormView';
|
||||
|
||||
export default function SqlFormView({ rowData, tableInfo }) {
|
||||
return <FormView rowData={rowData} tableInfo={tableInfo} />;
|
||||
}
|
||||
@@ -32,6 +32,7 @@ const iconNames = {
|
||||
'icon web': 'mdi mdi-web',
|
||||
'icon home': 'mdi mdi-home',
|
||||
'icon query-design': 'mdi mdi-vector-polyline-edit',
|
||||
'icon form': 'mdi mdi-form-select',
|
||||
|
||||
'icon edit': 'mdi mdi-pencil',
|
||||
'icon delete': 'mdi mdi-delete',
|
||||
|
||||
Reference in New Issue
Block a user