table structure tab WIP

This commit is contained in:
Jan Prochazka
2020-02-02 11:31:41 +01:00
parent d22058382f
commit af80a2799f
18 changed files with 318 additions and 57 deletions

View File

@@ -17,11 +17,13 @@ const IconWrap = styled.span`
`;
export function AppObjectCore({ title, Icon, Menu, data, makeAppObj, onClick }) {
const setOpenedTabs = useSetOpenedTabs();
const handleContextMenu = event => {
if (!Menu) return;
event.preventDefault();
showMenu(event.pageX, event.pageY, <Menu data={data} makeAppObj={makeAppObj} />);
showMenu(event.pageX, event.pageY, <Menu data={data} makeAppObj={makeAppObj} setOpenedTabs={setOpenedTabs} />);
};
return (

View File

@@ -0,0 +1,17 @@
import React from 'react';
import { TableIcon } from '../icons';
import { DropDownMenuItem } from '../modals/DropDownMenu';
import showModal from '../modals/showModal';
import ConnectionModal from '../modals/ConnectionModal';
import axios from '../utility/axios';
import { openNewTab } from '../utility/common';
import { useSetOpenedTabs } from '../utility/globalState';
/** @param columnProps {import('@dbgate/lib').ColumnInfo} */
export default function columnAppObject(columnProps, { setOpenedTabs }) {
const title = columnProps.columnName;
const key = title;
const Icon = TableIcon;
return { title, key, Icon };
}

View File

@@ -5,18 +5,33 @@ import showModal from '../modals/showModal';
import ConnectionModal from '../modals/ConnectionModal';
import axios from '../utility/axios';
import { openNewTab } from '../utility/common';
import { useSetOpenedTabs } from '../utility/globalState';
function Menu({ data, makeAppObj }) {
const handleEdit = () => {
showModal(modalState => <ConnectionModal modalState={modalState} connection={data} />);
function openTableDetail(setOpenedTabs, tabComponent, { schemaName, pureName, conid, database }) {
openNewTab(setOpenedTabs, {
title: pureName,
icon: 'table2.svg',
tabComponent,
props: {
schemaName,
pureName,
conid,
database,
},
});
}
function Menu({ data, makeAppObj, setOpenedTabs }) {
const handleOpenData = () => {
openTableDetail(setOpenedTabs, 'TableDataTab', data);
};
const handleDelete = () => {
axios.post('connections/delete', data);
const handleOpenStructure = () => {
openTableDetail(setOpenedTabs, 'TableStructureTab', data);
};
return (
<>
<DropDownMenuItem onClick={handleEdit}>Edit</DropDownMenuItem>
<DropDownMenuItem onClick={handleDelete}>Delete</DropDownMenuItem>
<DropDownMenuItem onClick={handleOpenData}>Open data</DropDownMenuItem>
<DropDownMenuItem onClick={handleOpenStructure}>Open structure</DropDownMenuItem>
</>
);
}
@@ -26,16 +41,11 @@ export default function tableAppObject({ conid, database, pureName, schemaName }
const key = title;
const Icon = TableIcon;
const onClick = ({ schemaName, pureName }) => {
openNewTab(setOpenedTabs, {
title: pureName,
icon: 'table2.svg',
tabComponent: 'TableDataTab',
props: {
schemaName,
pureName,
conid,
database,
},
openTableDetail(setOpenedTabs, 'TableDataTab', {
schemaName,
pureName,
conid,
database,
});
};

View File

@@ -1,7 +1,10 @@
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
font-family: -apple-system,BlinkMacSystemFont,Segoe WPC,Segoe UI,HelveticaNeue-Light,Ubuntu,Droid Sans,sans-serif;
font-size: 14px;
/* font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
sans-serif;
sans-serif;
*/
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}

View File

@@ -0,0 +1,78 @@
import React from 'react';
import useFetch from '../utility/useFetch';
import styled from 'styled-components';
import theme from '../theme';
import ObjectListControl from '../utility/ObjectListControl';
import { TableColumn } from '../utility/TableControl';
const WhitePage = styled.div`
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
background-color: white;
`;
export default function TableStructureTab({ conid, database, schemaName, pureName }) {
/** @type {import('@dbgate/lib').TableInfo} */
const tableInfo = useFetch({
url: 'tables/table-info',
params: { conid, database, schemaName, pureName },
});
if (!tableInfo) return null;
return (
<WhitePage>
<ObjectListControl
collection={tableInfo.columns.map((x, index) => ({ ...x, ordinal: index + 1 }))}
title="Columns"
>
<TableColumn
fieldName="notNull"
header="Not NULL"
sortable={true}
formatter={row => (row.notNull ? 'YES' : 'NO')}
/>
<TableColumn fieldName="dataType" header="Data Type" sortable={true} />
<TableColumn fieldName="defaultValue" header="Default value" sortable={true} />
<TableColumn
fieldName="isSparse"
header="Is Sparse"
sortable={true}
formatter={row => (row.isSparse ? 'YES' : 'NO')}
/>
<TableColumn fieldName="computedExpression" header="Computed Expression" sortable={true} />
<TableColumn
fieldName="isPersisted"
header="Is Persisted"
sortable={true}
formatter={row => (row.isPersisted ? 'YES' : 'NO')}
/>
{/* {_.includes(dbCaps.columnListOptionalColumns, 'referencedTableNamesFormatted') && (
<TableColumn fieldName="referencedTableNamesFormatted" header="References" sortable={true} />
)}
<TableColumn
fieldName="actions"
header=""
formatter={row => (
<span>
<Link
linkElementId={encodeHtmlId(`button_delete_column_${row.column.name}`)}
onClick={() => this.deleteColumn(row)}
>
Delete
</Link>{' '}
|{' '}
<Link
linkElementId={encodeHtmlId(`button_edit_column__${row.column.name}`)}
onClick={() => this.editColumn(row)}
>
Edit
</Link>
</span>
)}
/> */}
</ObjectListControl>
</WhitePage>
);
}

View File

@@ -1,5 +1,7 @@
import TableDataTab from './TableDataTab';
import TableStructureTab from './TableStructureTab';
export default {
TableDataTab,
TableStructureTab,
};

View File

@@ -0,0 +1,41 @@
import React from 'react';
import useFetch from '../utility/useFetch';
import styled from 'styled-components';
import theme from '../theme';
import TableControl from './TableControl';
const ObjectListWrapper = styled.div`
margin-bottom: 20px;
`;
const ObjectListHeader = styled.div`
background-color: #ebedef;
padding: 5px;
`;
const ObjectListHeaderTitle = styled.span`
font-weight: bold;
margin-left: 5px;
`;
const ObjectListBody = styled.div`
margin: 20px;
// margin-left: 20px;
// margin-right: 20px;
// margin-top: 3px;
`;
export default function ObjectListControl({ collection = [], title, showIfEmpty = false, children }) {
if (collection.length == 0 && !showIfEmpty) return null;
return (
<ObjectListWrapper>
<ObjectListHeader>
<ObjectListHeaderTitle>{title}</ObjectListHeaderTitle>
</ObjectListHeader>
<ObjectListBody>
<TableControl rows={collection}>{children}</TableControl>
</ObjectListBody>
</ObjectListWrapper>
);
}

View File

@@ -0,0 +1,59 @@
import React from 'react';
import useFetch from '../utility/useFetch';
import styled from 'styled-components';
import theme from '../theme';
const Table = styled.table`
border-collapse: collapse;
width: 100%;
`;
const TableHead = styled.thead``;
const TableBody = styled.tbody``;
const TableHeaderRow = styled.tr``;
const TableBodyRow = styled.tr``;
const TableHeaderCell = styled.td`
border: 1px solid #e8eef4;
background-color: #e8eef4;
padding: 5px;
`;
const TableBodyCell = styled.td`
border: 1px solid #e8eef4;
padding: 5px;
`;
export function TableColumn({ fieldName, header, sortable, formatter = undefined }) {
return <></>;
}
function format(row, col) {
const { formatter, fieldName } = col;
if (formatter) return formatter(row);
return row[fieldName];
}
export default function TableControl({ rows = [], children }) {
const columns = (children instanceof Array ? children : [children])
.filter(child => child != null)
.map(child => child.props);
return (
<Table>
<TableHead>
<TableHeaderRow>
{columns.map(x => (
<TableHeaderCell key={x.fieldName}>{x.header}</TableHeaderCell>
))}
</TableHeaderRow>
</TableHead>
<TableBody>
{rows.map((row, index) => (
<TableBodyRow key={index}>
{columns.map(col => (
<TableBodyCell key={col.fieldName}>{format(row, col)}</TableBodyCell>
))}
</TableBodyRow>
))}
</TableBody>
</Table>
);
}