Skip to content

Commit

Permalink
Split "TableLayout" in multiple files
Browse files Browse the repository at this point in the history
  • Loading branch information
jdeniau committed Mar 4, 2024
1 parent e5e718d commit 49d8798
Show file tree
Hide file tree
Showing 4 changed files with 172 additions and 175 deletions.
175 changes: 0 additions & 175 deletions src/component/TableLayout.tsx

This file was deleted.

94 changes: 94 additions & 0 deletions src/component/TableLayout/TableLayout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import { ReactElement, useCallback, useEffect, useState } from 'react';
import type { FieldPacket, RowDataPacket } from 'mysql2/promise';
import { useDatabaseContext } from '../../contexts/DatabaseContext';
import TableGrid from '../TableGrid';
import WhereFilter from '../Query/WhereFilter';
import { useTranslation } from '../../i18n';
import { Button, Flex } from 'antd';
import { useTableHeight } from './useTableHeight';

interface TableNameProps {
tableName: string;
database: string;
primaryKeys: Array<string>;
}
const DEFAULT_LIMIT = 100;

export function TableLayout({
tableName,
database,
primaryKeys,
}: TableNameProps): ReactElement {
const { t } = useTranslation();
const { executeQuery } = useDatabaseContext();
const [result, setResult] = useState<null | RowDataPacket[]>(null);
const [fields, setFields] = useState<null | FieldPacket[]>(null);
const [error, setError] = useState<null | Error>(null);
const [currentOffset, setCurrentOffset] = useState<number>(0);
const [where, setWhere] = useState<string>('');

const [yTableScroll, resizeRef] = useTableHeight();

const fetchTableData = useCallback(
(offset: number) => {
const query = `SELECT * FROM ${database}.${tableName} ${
where ? ` WHERE ${where}` : ''
} LIMIT ${DEFAULT_LIMIT} OFFSET ${offset};`;

executeQuery<RowDataPacket[]>(query)
.then(([result, fields]) => {
setCurrentOffset(offset);
setFields(fields || null);
setResult((prev) =>
offset > 0 && prev ? prev.concat(result) : result
);
})
.catch((err) => {
setError(err);
});
},
[database, tableName, where, executeQuery]
);

useEffect(() => {
fetchTableData(currentOffset);
}, [fetchTableData, currentOffset]);

if (error) {
return <div>{error.message}</div>;
}

return (
<Flex vertical gap="small" style={{ height: '100%' }}>
<div>
<h3>{tableName}</h3>

<WhereFilter
defaultValue={where}
onSubmit={(where) => {
setCurrentOffset(0);
setWhere(where);
}}
/>
</div>

<div style={{ overflow: 'auto', flex: '1' }} ref={resizeRef}>
<TableGrid
fields={fields}
result={result}
primaryKeys={primaryKeys}
yTableScroll={yTableScroll}
/>
</div>

<Flex justify="center" align="center">
<Button
onClick={() => fetchTableData(currentOffset + DEFAULT_LIMIT)}
type="primary"
>
{t('table.rows.loadMore')}
</Button>
</Flex>
</Flex>
);
}
38 changes: 38 additions & 0 deletions src/component/TableLayout/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { useEffect } from 'react';
import { useParams } from 'react-router-dom';
import { useConfiguration } from '../../contexts/ConfigurationContext';
import { useDatabaseContext } from '../../contexts/DatabaseContext';
import { useConnectionContext } from '../../contexts/ConnectionContext';
import invariant from 'tiny-invariant';
import { TableLayout } from './TableLayout';

type Props = { primaryKeys: Array<string> };

function TableLayoutPageContent({ primaryKeys }: Props) {
const { currentConnectionName } = useConnectionContext();
const { database } = useDatabaseContext();
const { tableName } = useParams();
const { updateConnectionState } = useConfiguration();

useEffect(() => {
invariant(currentConnectionName, 'Connection name is required');
invariant(tableName, 'Table name is required');

updateConnectionState(currentConnectionName, 'openedTable', tableName);
}, [currentConnectionName, tableName, updateConnectionState]);

if (!currentConnectionName || !database || !tableName) {
return null;
}

return (
<TableLayout
key={`${currentConnectionName}|${database}|${tableName}`}
tableName={tableName}
database={database}
primaryKeys={primaryKeys}
/>
);
}

export default TableLayoutPageContent;
40 changes: 40 additions & 0 deletions src/component/TableLayout/useTableHeight.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { useEffect, useMemo, useRef, useState } from 'react';

export function useTableHeight(): [number, React.RefObject<HTMLDivElement>] {
const [yTableScroll, setYTableScroll] = useState<number>(0);
const resizeRef = useRef<HTMLDivElement | null>(null);

const resizeObserver = useMemo(
() =>
new ResizeObserver((entries) => {
const entry = entries[0];
const divHeight = entry.borderBoxSize[0].blockSize;

const tableHeader =
resizeRef.current?.querySelector('.ant-table-header');

const tableHeaderHeight =
tableHeader?.getBoundingClientRect().height ?? 0;

// I don't know why we need to subtract 1 from the height, but if not, the div will have a scrollbar
setYTableScroll(divHeight - tableHeaderHeight - 1);
}),
[]
);

useEffect(() => {
const resizeRefCurrent = resizeRef.current;

if (resizeRefCurrent) {
resizeObserver.observe(resizeRefCurrent);
}

return () => {
if (resizeRefCurrent) {
resizeObserver.unobserve(resizeRefCurrent);
}
};
}, [resizeObserver]);

return [yTableScroll, resizeRef];
}

0 comments on commit 49d8798

Please sign in to comment.