formview - basic display

This commit is contained in:
Jan Prochazka
2021-01-09 16:35:36 +01:00
parent bdb8f44895
commit 03c7bbb7af
7 changed files with 172 additions and 11 deletions

View File

@@ -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>
);

View File

@@ -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}
/>
)
)}

View File

@@ -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}

View File

@@ -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>

View 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>
);
}

View 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} />;
}

View File

@@ -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',