diff --git a/packages/datalib/src/FreeTableGridDisplay.ts b/packages/datalib/src/FreeTableGridDisplay.ts new file mode 100644 index 000000000..9652790d8 --- /dev/null +++ b/packages/datalib/src/FreeTableGridDisplay.ts @@ -0,0 +1,45 @@ +import _ from 'lodash'; +import { EngineDriver, ViewInfo, ColumnInfo } from '@dbgate/types'; +import { GridDisplay, ChangeCacheFunc, ChangeConfigFunc } from './GridDisplay'; +import { GridConfig, GridCache } from './GridConfig'; +import { FreeTableModel } from './FreeTableModel'; + +export class FreeTableGridDisplay extends GridDisplay { + constructor( + public model: FreeTableModel, + config: GridConfig, + setConfig: ChangeConfigFunc, + cache: GridCache, + setCache: ChangeCacheFunc + ) { + super(config, setConfig, cache, setCache); + this.columns = this.getDisplayColumns(model); + this.filterable = true; + this.sortable = true; + this.editable = true; + } + + getDisplayColumns(model: FreeTableModel) { + return ( + model?.structure?.columns + ?.map((col) => this.getDisplayColumn(col)) + ?.map((col) => ({ + ...col, + isChecked: this.isColumnChecked(col), + })) || [] + ); + } + + getDisplayColumn( col: ColumnInfo) { + const uniquePath = [col.columnName]; + const uniqueName = uniquePath.join('.'); + return { + ...col, + pureName: 'data', + schemaName: '', + headerText: col.columnName, + uniqueName, + uniquePath, + }; + } +} diff --git a/packages/datalib/src/FreeTableModel.ts b/packages/datalib/src/FreeTableModel.ts new file mode 100644 index 000000000..515df3c67 --- /dev/null +++ b/packages/datalib/src/FreeTableModel.ts @@ -0,0 +1,27 @@ +import { TableInfo } from '@dbgate/types'; + +export interface FreeTableModel { + structure: TableInfo; + rows: any[]; +} + +export function createFreeTableModel() { + return { + structure: { + columns: [ + { + columnName: 'col1', + }, + ], + foreignKeys: [], + }, + rows: [ + { + col1: 'val1', + }, + { + col1: 'val2', + }, + ], + }; +} diff --git a/packages/datalib/src/index.ts b/packages/datalib/src/index.ts index 96252dcce..3a293d13e 100644 --- a/packages/datalib/src/index.ts +++ b/packages/datalib/src/index.ts @@ -5,3 +5,5 @@ export * from "./ViewGridDisplay"; export * from "./JslGridDisplay"; export * from "./ChangeSet"; export * from "./filterName"; +export * from "./FreeTableGridDisplay"; +export * from "./FreeTableModel"; diff --git a/packages/web/public/icons/freetable.svg b/packages/web/public/icons/freetable.svg new file mode 100644 index 000000000..e57ea5140 --- /dev/null +++ b/packages/web/public/icons/freetable.svg @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/packages/web/src/datagrid/Grider.ts b/packages/web/src/datagrid/Grider.ts index d0c5d18c2..dcd5807d3 100644 --- a/packages/web/src/datagrid/Grider.ts +++ b/packages/web/src/datagrid/Grider.ts @@ -7,10 +7,6 @@ export default abstract class Grider { abstract getRowData(index): any; abstract get rowCount(): number; - getRowsSample() { - return [this.getRowData(0)]; - } - getRowStatus(index): GriderRowStatus { const res: GriderRowStatus = { status: 'regular', diff --git a/packages/web/src/datagrid/RowsArrayGrider.ts b/packages/web/src/datagrid/RowsArrayGrider.ts index 7f2ac9581..76a9e140d 100644 --- a/packages/web/src/datagrid/RowsArrayGrider.ts +++ b/packages/web/src/datagrid/RowsArrayGrider.ts @@ -17,7 +17,4 @@ export default class RowsArrayGrider extends Grider { static factoryDeps({ sourceRows }) { return [sourceRows]; } - getRowsSample() { - return this.rows; - } } diff --git a/packages/web/src/freetable/FreeTableGrid.js b/packages/web/src/freetable/FreeTableGrid.js new file mode 100644 index 000000000..8d060eb5f --- /dev/null +++ b/packages/web/src/freetable/FreeTableGrid.js @@ -0,0 +1,37 @@ +import React from 'react'; +import styled from 'styled-components'; + +import { ManagerMainContainer, ManagerOuterContainerFull } from '../datagrid/ManagerStyles'; +import { HorizontalSplitter } from '../widgets/Splitter'; +import FreeTableGridCore from './FreeTableGridCore'; + +const LeftContainer = styled.div` + background-color: white; + display: flex; + flex: 1; +`; + +const DataGridContainer = styled.div` + position: relative; + flex-grow: 1; +`; + +export default function FreeTableGrid(props) { + const [managerSize, setManagerSize] = React.useState(0); + return ( + + + + + COLUMNS + {/* */} + + + + + + + + + ); +} diff --git a/packages/web/src/freetable/FreeTableGridCore.js b/packages/web/src/freetable/FreeTableGridCore.js new file mode 100644 index 000000000..6857cd10e --- /dev/null +++ b/packages/web/src/freetable/FreeTableGridCore.js @@ -0,0 +1,17 @@ +import { createGridCache, FreeTableGridDisplay } from '@dbgate/datalib'; +import React from 'react'; +import DataGridCore from '../datagrid/DataGridCore'; +import FreeTableGrider from './FreeTableGrider'; + +export default function FreeTableGridCore(props) { + const { modelState, dispatchModel, config, setConfig } = props; + const grider = React.useMemo(() => FreeTableGrider.factory(props), FreeTableGrider.factoryDeps(props)); + const [cache, setCache] = React.useState(createGridCache()); + const display = React.useMemo(() => new FreeTableGridDisplay(modelState.value, config, setConfig, cache, setCache), [ + modelState.value, + config, + cache, + ]); + + return ; +} diff --git a/packages/web/src/freetable/FreeTableGrider.ts b/packages/web/src/freetable/FreeTableGrider.ts new file mode 100644 index 000000000..283c7c0a1 --- /dev/null +++ b/packages/web/src/freetable/FreeTableGrider.ts @@ -0,0 +1,25 @@ +import { FreeTableModel } from '@dbgate/datalib'; +import Grider, { GriderRowStatus } from '../datagrid/Grider'; + +export default class FreeTableGrider extends Grider { + public model: FreeTableModel; + public rows: any[]; + constructor(public modelState, public dispatchModel) { + super(); + this.model = modelState && modelState.value; + this.rows = this.model.rows; + } + getRowData(index: any) { + return this.rows[index]; + } + get rowCount() { + return this.rows.length; + } + + static factory({ modelState, dispatchModel }): FreeTableGrider { + return new FreeTableGrider(modelState, dispatchModel); + } + static factoryDeps({ modelState, dispatchModel }) { + return [modelState, dispatchModel]; + } +} diff --git a/packages/web/src/freetable/useNewFreeTable.js b/packages/web/src/freetable/useNewFreeTable.js new file mode 100644 index 000000000..37a667110 --- /dev/null +++ b/packages/web/src/freetable/useNewFreeTable.js @@ -0,0 +1,15 @@ +import _ from 'lodash'; +import { useSetOpenedTabs, useCurrentDatabase } from '../utility/globalState'; +import { openNewTab } from '../utility/common'; + +export default function useNewFreeTable() { + const setOpenedTabs = useSetOpenedTabs(); + + return ({ title = undefined, ...props } = {}) => + openNewTab(setOpenedTabs, { + title: title || 'Table', + icon: 'freetable.svg', + tabComponent: 'FreeTableTab', + props: {}, + }); +} diff --git a/packages/web/src/icons.js b/packages/web/src/icons.js index b4215c53e..757b10904 100644 --- a/packages/web/src/icons.js +++ b/packages/web/src/icons.js @@ -57,6 +57,7 @@ export function ExpandIcon({ } export const TableIcon = (props) => getIconImage('table2.svg', props); +export const FreeTableIcon = (props) => getIconImage('freetable.svg', props); export const ViewIcon = (props) => getIconImage('view2.svg', props); export const ArchiveTableIcon = (props) => getIconImage('archtable.svg', props); export const DatabaseIcon = (props) => getIconImage('database.svg', props); diff --git a/packages/web/src/tabs/FreeTableTab.js b/packages/web/src/tabs/FreeTableTab.js new file mode 100644 index 000000000..f90400398 --- /dev/null +++ b/packages/web/src/tabs/FreeTableTab.js @@ -0,0 +1,25 @@ +import React from 'react'; +import { createGridCache, createChangeSet, createGridConfig, createFreeTableModel } from '@dbgate/datalib'; +import useUndoReducer from '../utility/useUndoReducer'; +import usePropsCompare from '../utility/usePropsCompare'; +import { useUpdateDatabaseForTab } from '../utility/globalState'; +import TableDataGrid from '../datagrid/TableDataGrid'; +import useGridConfig from '../utility/useGridConfig'; +import FreeTableGrid from '../freetable/FreeTableGrid'; + +export default function FreeDataTab({ conid, database, schemaName, pureName, tabVisible, toolbarPortalRef, tabid }) { + const [config, setConfig] = useGridConfig(tabid); + const [modelState, dispatchModel] = useUndoReducer(createFreeTableModel()); + + return ( + + ); +} diff --git a/packages/web/src/tabs/index.js b/packages/web/src/tabs/index.js index 262a7ee2d..97d46acd6 100644 --- a/packages/web/src/tabs/index.js +++ b/packages/web/src/tabs/index.js @@ -5,6 +5,7 @@ import QueryTab from './QueryTab'; import ShellTab from './ShellTab'; import InfoPageTab from './InfoPageTab'; import ArchiveFileTab from './ArchiveFileTab'; +import FreeTableTab from './FreeTableTab'; export default { TableDataTab, @@ -14,4 +15,5 @@ export default { InfoPageTab, ShellTab, ArchiveFileTab, + FreeTableTab, }; diff --git a/packages/web/src/widgets/Toolbar.js b/packages/web/src/widgets/Toolbar.js index 5be65cd54..7bca16900 100644 --- a/packages/web/src/widgets/Toolbar.js +++ b/packages/web/src/widgets/Toolbar.js @@ -7,6 +7,7 @@ import useNewQuery from '../query/useNewQuery'; import { useConfig } from '../utility/metadataLoaders'; import { useSetOpenedTabs, useOpenedTabs } from '../utility/globalState'; import { openNewTab } from '../utility/common'; +import useNewFreeTable from '../freetable/useNewFreeTable'; const ToolbarContainer = styled.div` display: flex; @@ -16,6 +17,7 @@ const ToolbarContainer = styled.div` export default function ToolBar({ toolbarPortalRef }) { const modalState = useModalState(); const newQuery = useNewQuery(); + const newFreeTable = useNewFreeTable(); const config = useConfig(); const toolbar = config.toolbar || []; const setOpenedTabs = useSetOpenedTabs(); @@ -74,6 +76,9 @@ export default function ToolBar({ toolbarPortalRef }) { New Query + + Free table editor + );