Skip to content

Commit

Permalink
feat: add ag-grid
Browse files Browse the repository at this point in the history
  • Loading branch information
Michael Ionov committed Jan 5, 2024
1 parent 11fab6e commit c2e01a1
Show file tree
Hide file tree
Showing 10 changed files with 107 additions and 50 deletions.
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
"@solid-primitives/keyboard": "^1.2.5",
"@tauri-apps/api": "^1.4.0",
"@uiw/codemirror-theme-dracula": "^4.21.7",
"ag-grid-community": "^31.0.1",
"ag-grid-solid": "^31.0.1",
"codemirror": "^6.0.1",
"fuse.js": "^6.6.2",
"i18next": "^23.1.0",
Expand Down
19 changes: 19 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import 'utils/i18n';
import 'tabulator-tables/dist/css/tabulator_midnight.min.css';
import 'ag-grid-community/styles/ag-grid.css';
import 'ag-grid-community/styles/ag-theme-alpine.css';
import 'ag-grid-community/styles/ag-theme-quartz.css';
import './index.css';
import { Main } from 'components/Screens/Main';
import { Loader } from 'components/UI';
import { onMount, Switch, Match } from 'solid-js';
Expand Down
6 changes: 1 addition & 5 deletions src/components/Screens/Console/Content/DataTab/DataTab.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
import { Results } from '../QueryTab/Results';

const DataTab = () => {
return (
<div id="results">
<Results />
</div>
);
return <Results />;
};

export { DataTab };
96 changes: 63 additions & 33 deletions src/components/Screens/Console/Content/QueryTab/Results.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { createEffect, createSignal, on } from 'solid-js';
import { createEffect, createResource, createSignal, on } from 'solid-js';
import { dracula } from '@uiw/codemirror-theme-dracula';
import { search } from '@codemirror/search';
import { basicSetup, EditorView } from 'codemirror';
Expand All @@ -7,13 +7,30 @@ import { createCodeMirror, createEditorControlledValue } from 'solid-codemirror'
import { Pagination } from './components/Pagination';
import { useAppSelector } from 'services/Context';
import { Row } from 'interfaces';
import { Table } from './components/Table';
import { createStore } from 'solid-js/store';

import { ColDef } from 'ag-grid-community';
import AgGridSolid from 'ag-grid-solid';
import { ContentTabData } from 'services/Connections';
import { NoResults } from './components/NoResults';
import { Loader } from 'components/UI';
import Keymaps from 'components/UI/Keymaps';

const getColumnDefs = (rows: Row[]): ColDef[] => {
if (!rows || rows.length === 0) {
return [];
}
return Object.keys(rows[0]).map((field) => ({
editable: true,
filter: true,
field,
headerName: field,
}));
};

export const Results = () => {
const {
connections: { queryIdx, getContentData, contentStore },
backend: { getQueryResults },
connections: { queryIdx, contentStore },
backend: { getQueryResults, pageSize },
} = useAppSelector();
const [code, setCode] = createSignal('');
const { ref, editorView, createExtension } = createCodeMirror({
Expand All @@ -27,51 +44,53 @@ export const Results = () => {
const lineWrapping = EditorView.lineWrapping;
createExtension(lineWrapping);

const [rows, setRows] = createStore<Row[]>([]);
// const [loaded, setLoaded] = createSignal(false);
const [page, setPage] = createSignal(0);
const [loading, setLoading] = createSignal(false);

const updateRows = async () => {
try {
setLoading(true);
// setLoaded(false);
const result_set = getContentData('Query').result_sets[queryIdx()];
if (result_set?.rows) {
setRows(result_set.rows);
return;
const [data] = createResource(
() =>
[
page(),
queryIdx(),
pageSize(),
(contentStore.tabs[contentStore.idx].data as ContentTabData['Query']).result_sets,
] as const,
async ([pageVal, queryIdxVal, pageSizeVal, result_sets]) => {
// Reruns when either signal updates
const result_set = result_sets[queryIdxVal];
console.log('rerun', { result_set: result_set?.id });
if (!result_set || result_set?.status !== 'Completed') {
return { rows: [], columns: [], exhausted: true, notReady: true };
}
if (result_set?.status !== 'Completed') {
setRows([]);
return;
if (result_set.rows) {
// check this exhausted prop
const columns = getColumnDefs(result_set.rows);
return { rows: result_set.rows, columns, exhausted: true };
}
const _rows = await getQueryResults(result_set.path!, page());
setRows(_rows);
// setLoaded(true);
} finally {
setLoading(false);
const rows = await getQueryResults(result_set.path!, pageVal, pageSizeVal);
const columns = getColumnDefs(rows);
return { rows, columns, exhausted: rows.length < pageSizeVal };
}
};
);

// on initial render, this update rows is called twice
createEffect(
on(queryIdx, () => {
setPage(0);
updateRows();
})
);

createEffect(updateRows, contentStore.idx);

const onNextPage = async () => {
if (data()?.exhausted) return;
setPage(page() + 1);
updateRows();
};

const onPrevPage = async () => {
if (page() === 0) return;
setPage(page() - 1);
updateRows();
};

const defaultColDef: ColDef = {
flex: 1,
minWidth: 320,
};

return (
Expand All @@ -86,8 +105,19 @@ export const Results = () => {
<button>close</button>
</form>
</dialog>
<Pagination {...{ page, onNextPage, onPrevPage, loading, setPage }} />
<Table rows={rows} />
<Pagination {...{ page, onNextPage, onPrevPage, loading: data.loading, setPage }} />
<div class="ag-theme-alpine-dark" style={{ height: '100%' }}>
<AgGridSolid
noRowsOverlayComponent={() => (data()?.notReady ? <Keymaps /> : <NoResults />)}
loadingOverlayComponent={() => <Loader />}
onCellContextMenu={(e) => {
console.log(e);
}}
columnDefs={data()?.columns}
rowData={data()?.rows}
defaultColDef={defaultColDef}
/>
</div>
</div>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { ResultSet } from 'interfaces';

type PaginationProps = {
page: Accessor<number>;
loading: Accessor<boolean>;
loading: boolean;
setPage: (n: number) => void;
onPrevPage: () => void;
onNextPage: () => void;
Expand Down Expand Up @@ -83,16 +83,16 @@ export const Pagination = (props: PaginationProps) => {
</select>
</div>
<div class="tooltip tooltip-primary tooltip-left" data-tip={t('console.actions.previous_page')}>
<button class="join-item btn btn-sm" disabled={props.loading() || !props.page()} onClick={props.onPrevPage}>
<button class="join-item btn btn-sm" disabled={props.loading || !props.page()} onClick={props.onPrevPage}>
<ChevronLeft />
</button>
</div>
<button disabled class="join-item btn btn-sm btn-disabled !text-base-content w-[50px]">
<Switch>
<Match when={props.loading()}>
<Match when={props.loading}>
<span class="loading text-primary loading-bars loading-xs"></span>
</Match>
<Match when={!props.loading()}>
<Match when={!props.loading}>
<span>{props.page() + 1}</span>
</Match>
</Switch>
Expand All @@ -101,7 +101,7 @@ export const Pagination = (props: PaginationProps) => {
<div class="tooltip tooltip-primary tooltip-left" data-tip={t('console.actions.next_page')}>
<button
class="join-item btn btn-sm"
disabled={props.loading() || props.page() * pageSize() + pageSize() >= (resultSet?.count ?? 0)}
disabled={props.loading || props.page() * pageSize() + pageSize() >= (resultSet?.count ?? 0)}
onClick={props.onNextPage}>
<ChevronRight />
</button>
Expand Down
7 changes: 7 additions & 0 deletions src/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -199,3 +199,10 @@ dialog {
.tooltip::before {
@apply z-50;
}


/* ag-grid */
.ag-theme-alpine, .ag-theme-alpine-dark {
--ag-grid-size: 5px;
--ag-list-item-height: 20px;
}
1 change: 0 additions & 1 deletion src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { render } from 'solid-js/web';
import 'solid-contextmenu/dist/style.css';
import { ErrorBoundary } from 'solid-js';

import './index.css';
import App from './App';
import { StoreProvider } from 'services/Context';
import { Error } from 'components/Error';
Expand Down
10 changes: 5 additions & 5 deletions src/services/Backend.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,11 @@ export const BackendService = () => {
params: { path, page, page_size },
});
const rows = JSON.parse('[' + res + ']') as unknown as Row[];
if (rows.length > 0 && rows.length < page_size) {
// pad the results with empty rows
const empty_rows = Array(page_size - rows.length).fill({});
rows.push(...empty_rows);
}
// if (rows.length > 0 && rows.length < page_size) {
// // pad the results with empty rows
// const empty_rows = Array(page_size - rows.length).fill({});
// rows.push(...empty_rows);
// }
return rows;
};

Expand Down
2 changes: 1 addition & 1 deletion src/services/Connections.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export const ContentTab = {

type ContentComponentKeys = keyof typeof ContentTab;

type ContentTabData = {
export type ContentTabData = {
[ContentTab.Query]: QueryContentTabData;
[ContentTab.TableStructure]: TableStructureContentTabData;
[ContentTab.Data]: DataContentTabData;
Expand Down

0 comments on commit c2e01a1

Please sign in to comment.