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