diff --git a/packages/web/.eslintrc.js b/packages/web/.eslintrc.js
deleted file mode 100644
index a53d0ca70..000000000
--- a/packages/web/.eslintrc.js
+++ /dev/null
@@ -1,28 +0,0 @@
-module.exports = {
- "env": {
- "browser": true,
- "es6": true
- },
- "extends": [
- "eslint:recommended",
- "plugin:react/recommended"
- ],
- "globals": {
- "Atomics": "readonly",
- "SharedArrayBuffer": "readonly"
- },
- "parserOptions": {
- "ecmaFeatures": {
- "jsx": true
- },
- "ecmaVersion": 2018,
- "sourceType": "module"
- },
- "plugins": [
- "react"
- ],
- "rules": {
- "react/prop-types": "off",
- "no-unused-vars": "warn"
- }
-};
\ No newline at end of file
diff --git a/packages/web/package.json b/packages/web/package.json
deleted file mode 100644
index 77b431d6c..000000000
--- a/packages/web/package.json
+++ /dev/null
@@ -1,69 +0,0 @@
-{
- "name": "dbgate-web",
- "version": "3.9.5",
- "files": [
- "build"
- ],
- "scripts": {
- "start": "cross-env BROWSER=none PORT=5000 react-scripts start",
- "build:docker": "cross-env CI=false REACT_APP_API_URL=ORIGIN react-scripts build",
- "build:app": "cross-env PUBLIC_URL=. CI=false react-scripts build",
- "build": "cross-env CI=false REACT_APP_API_URL=ORIGIN react-scripts build",
- "prepublishOnly": "yarn build",
- "test": "react-scripts test",
- "eject": "react-scripts eject",
- "ts": "tsc"
- },
- "browserslist": {
- "production": [
- ">0.2%",
- "not dead",
- "not op_mini all"
- ],
- "development": [
- "last 1 chrome version",
- "last 1 firefox version",
- "last 1 safari version"
- ]
- },
- "devDependencies": {
- "@types/react": "^16.9.17",
- "@types/styled-components": "^4.4.2",
- "dbgate-types": "^3.9.5",
- "typescript": "^3.7.4",
- "@ant-design/colors": "^5.0.0",
- "@mdi/font": "^5.8.55",
- "@testing-library/jest-dom": "^4.2.4",
- "@testing-library/react": "^9.3.2",
- "@testing-library/user-event": "^7.1.2",
- "ace-builds": "^1.4.8",
- "axios": "^0.19.0",
- "chart.js": "^2.9.4",
- "compare-versions": "^3.6.0",
- "cross-env": "^6.0.3",
- "dbgate-datalib": "^3.9.5",
- "dbgate-sqltree": "^3.9.5",
- "dbgate-tools": "^3.9.5",
- "eslint": "^6.8.0",
- "eslint-plugin-react": "^7.17.0",
- "json-stable-stringify": "^1.0.1",
- "localforage": "^1.9.0",
- "markdown-to-jsx": "^7.1.0",
- "randomcolor": "^0.6.2",
- "react": "^16.12.0",
- "react-ace": "^8.0.0",
- "react-chartjs-2": "^2.11.1",
- "react-dom": "^16.12.0",
- "react-dropzone": "^11.2.3",
- "react-helmet": "^6.1.0",
- "react-json-view": "^1.19.1",
- "react-modal": "^3.11.1",
- "react-scripts": "3.3.0",
- "react-select": "^3.1.0",
- "resize-observer-polyfill": "^1.5.1",
- "socket.io-client": "^2.3.0",
- "sql-formatter": "^2.3.3",
- "styled-components": "^4.4.1",
- "uuid": "^3.4.0"
- }
-}
\ No newline at end of file
diff --git a/packages/web/public/favicon.ico b/packages/web/public/favicon.ico
deleted file mode 100644
index dd0ba6487..000000000
Binary files a/packages/web/public/favicon.ico and /dev/null differ
diff --git a/packages/web/public/index.html b/packages/web/public/index.html
deleted file mode 100644
index 94e81e72b..000000000
--- a/packages/web/public/index.html
+++ /dev/null
@@ -1,44 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
- DbGate
-
-
-
- You need to enable JavaScript to run this app.
- Loading DbGate...
-
-
-
-
\ No newline at end of file
diff --git a/packages/web/public/logo192.png b/packages/web/public/logo192.png
deleted file mode 100644
index 56d4efb81..000000000
Binary files a/packages/web/public/logo192.png and /dev/null differ
diff --git a/packages/web/public/logo512.png b/packages/web/public/logo512.png
deleted file mode 100644
index 44ece81d3..000000000
Binary files a/packages/web/public/logo512.png and /dev/null differ
diff --git a/packages/web/public/manifest.json b/packages/web/public/manifest.json
deleted file mode 100644
index 63c397bd1..000000000
--- a/packages/web/public/manifest.json
+++ /dev/null
@@ -1,25 +0,0 @@
-{
- "short_name": "DbGate",
- "name": "DbGate database tool",
- "icons": [
- {
- "src": "favicon.ico",
- "sizes": "64x64 32x32 24x24 16x16",
- "type": "image/x-icon"
- },
- {
- "src": "logo192.png",
- "type": "image/png",
- "sizes": "192x192"
- },
- {
- "src": "logo512.png",
- "type": "image/png",
- "sizes": "512x512"
- }
- ],
- "start_url": ".",
- "display": "standalone",
- "theme_color": "#000000",
- "background_color": "#ffffff"
-}
diff --git a/packages/web/public/robots.txt b/packages/web/public/robots.txt
deleted file mode 100644
index 01b0f9a10..000000000
--- a/packages/web/public/robots.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-# https://www.robotstxt.org/robotstxt.html
-User-agent: *
diff --git a/packages/web/public/splash.css b/packages/web/public/splash.css
deleted file mode 100644
index 3bc0c720f..000000000
--- a/packages/web/public/splash.css
+++ /dev/null
@@ -1,16 +0,0 @@
-body {
- background: #666;
-}
-
-div {
- color: white;
- font-size: 25pt;
- position: absolute;
- left: 0;
- top: 0;
- right: 0;
- bottom: 0;
- text-align: center;
- font-family: Arial, Helvetica, sans-serif;
- margin-top: 40px;
-}
diff --git a/packages/web/public/splash.html b/packages/web/public/splash.html
deleted file mode 100644
index 486dce245..000000000
--- a/packages/web/public/splash.html
+++ /dev/null
@@ -1,12 +0,0 @@
-
-
-
-
-
-
-
-
- Starting DbGate...
-
-
-
\ No newline at end of file
diff --git a/packages/web/public/unknown.svg b/packages/web/public/unknown.svg
deleted file mode 100644
index ff30dd8cf..000000000
--- a/packages/web/public/unknown.svg
+++ /dev/null
@@ -1,15 +0,0 @@
-
-
-
-
-
-
-
- image/svg+xml
-
-
-
-
-
- ?
-
\ No newline at end of file
diff --git a/packages/web/src/App.css b/packages/web/src/App.css
deleted file mode 100644
index 74b5e0534..000000000
--- a/packages/web/src/App.css
+++ /dev/null
@@ -1,38 +0,0 @@
-.App {
- text-align: center;
-}
-
-.App-logo {
- height: 40vmin;
- pointer-events: none;
-}
-
-@media (prefers-reduced-motion: no-preference) {
- .App-logo {
- animation: App-logo-spin infinite 20s linear;
- }
-}
-
-.App-header {
- background-color: #282c34;
- min-height: 100vh;
- display: flex;
- flex-direction: column;
- align-items: center;
- justify-content: center;
- font-size: calc(10px + 2vmin);
- color: white;
-}
-
-.App-link {
- color: #61dafb;
-}
-
-@keyframes App-logo-spin {
- from {
- transform: rotate(0deg);
- }
- to {
- transform: rotate(360deg);
- }
-}
diff --git a/packages/web/src/App.js b/packages/web/src/App.js
deleted file mode 100644
index b325a80ae..000000000
--- a/packages/web/src/App.js
+++ /dev/null
@@ -1,57 +0,0 @@
-import React from 'react';
-import './index.css';
-import Screen from './Screen';
-import {
- CurrentWidgetProvider,
- CurrentDatabaseProvider,
- OpenedTabsProvider,
- OpenedConnectionsProvider,
- LeftPanelWidthProvider,
- CurrentArchiveProvider,
- CurrentThemeProvider,
-} from './utility/globalState';
-import { SocketProvider } from './utility/SocketProvider';
-import ConnectionsPinger from './utility/ConnectionsPinger';
-import { ModalLayerProvider } from './modals/showModal';
-import UploadsProvider from './utility/UploadsProvider';
-import ThemeHelmet from './themes/ThemeHelmet';
-import PluginsProvider from './plugins/PluginsProvider';
-import { ExtensionsProvider } from './utility/useExtensions';
-import { MenuLayerProvider } from './modals/showMenu';
-
-function App() {
- return (
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- );
-}
-
-export default App;
diff --git a/packages/web/src/App.test.js b/packages/web/src/App.test.js
deleted file mode 100644
index f50f6952c..000000000
--- a/packages/web/src/App.test.js
+++ /dev/null
@@ -1,11 +0,0 @@
-// @ts-nocheck
-
-import React from 'react';
-import { render } from '@testing-library/react';
-import App from './App';
-
-test('renders learn react link', () => {
- const { getByText } = render( );
- const linkElement = getByText(/learn react/i);
- expect(linkElement).toBeInTheDocument();
-});
diff --git a/packages/web/src/DragAndDropFileTarget.js b/packages/web/src/DragAndDropFileTarget.js
deleted file mode 100644
index 5741ca470..000000000
--- a/packages/web/src/DragAndDropFileTarget.js
+++ /dev/null
@@ -1,62 +0,0 @@
-import React from 'react';
-import styled from 'styled-components';
-import { FontIcon } from './icons';
-import useTheme from './theme/useTheme';
-import getElectron from './utility/getElectron';
-import useExtensions from './utility/useExtensions';
-
-const TargetStyled = styled.div`
- position: fixed;
- display: flex;
- top: 0;
- left: 0;
- right: 0;
- bottom: 0;
- background: ${props => props.theme.main_background_blue[3]};
- align-items: center;
- justify-content: space-around;
- z-index: 1000;
-`;
-
-const InfoBox = styled.div``;
-
-const IconWrapper = styled.div`
- display: flex;
- justify-content: space-around;
- font-size: 50px;
- margin-bottom: 20px;
-`;
-
-const InfoWrapper = styled.div`
- display: flex;
- justify-content: space-around;
- margin-top: 10px;
-`;
-
-const TitleWrapper = styled.div`
- font-size: 30px;
- display: flex;
- justify-content: space-around;
-`;
-
-export default function DragAndDropFileTarget({ isDragActive, inputProps }) {
- const theme = useTheme();
- const { fileFormats } = useExtensions();
- const electron = getElectron();
- const fileTypeNames = fileFormats.filter(x => x.readerFunc).map(x => x.name);
- if (electron) fileTypeNames.push('SQL');
- return (
- !!isDragActive && (
-
-
-
-
-
- Drop the files to upload to DbGate
- Supported file types: {fileTypeNames.join(', ')}
-
-
-
- )
- );
-}
diff --git a/packages/web/src/Screen.js b/packages/web/src/Screen.js
deleted file mode 100644
index 8299dce9f..000000000
--- a/packages/web/src/Screen.js
+++ /dev/null
@@ -1,147 +0,0 @@
-// @ts-nocheck
-
-import React from 'react';
-import dimensions from './theme/dimensions';
-import styled from 'styled-components';
-import TabsPanel from './TabsPanel';
-import TabContent from './TabContent';
-import WidgetIconPanel from './widgets/WidgetIconPanel';
-import { useCurrentWidget, useLeftPanelWidth, useSetLeftPanelWidth } from './utility/globalState';
-import WidgetContainer from './widgets/WidgetContainer';
-import ToolBar from './widgets/Toolbar';
-import StatusBar from './widgets/StatusBar';
-import { useSplitterDrag, HorizontalSplitHandle } from './widgets/Splitter';
-import { ModalLayer } from './modals/showModal';
-import DragAndDropFileTarget from './DragAndDropFileTarget';
-import { useUploadsZone } from './utility/UploadsProvider';
-import useTheme from './theme/useTheme';
-import { MenuLayer } from './modals/showMenu';
-import ErrorBoundary, { ErrorBoundaryTest } from './utility/ErrorBoundary';
-
-const BodyDiv = styled.div`
- position: fixed;
- top: ${dimensions.tabsPanel.height + dimensions.toolBar.height}px;
- left: ${props => props.contentLeft}px;
- bottom: ${dimensions.statusBar.height}px;
- right: 0;
- background-color: ${props => props.theme.content_background};
-`;
-
-const ToolBarDiv = styled.div`
- position: fixed;
- top: 0;
- left: 0;
- right: 0;
- background-color: ${props => props.theme.toolbar_background};
- height: ${dimensions.toolBar.height}px;
-`;
-
-const IconBar = styled.div`
- position: fixed;
- top: ${dimensions.toolBar.height}px;
- left: 0;
- bottom: ${dimensions.statusBar.height}px;
- width: ${dimensions.widgetMenu.iconSize}px;
- background-color: ${props => props.theme.widget_background};
-`;
-
-const LeftPanel = styled.div`
- position: fixed;
- top: ${dimensions.toolBar.height}px;
- left: ${dimensions.widgetMenu.iconSize}px;
- bottom: ${dimensions.statusBar.height}px;
- background-color: ${props => props.theme.left_background};
- display: flex;
-`;
-
-const TabsPanelContainer = styled.div`
- display: flex;
- position: fixed;
- top: ${dimensions.toolBar.height}px;
- left: ${props => props.contentLeft}px;
- height: ${dimensions.tabsPanel.height}px;
- right: 0;
- background-color: ${props => props.theme.tabs_background2};
- border-top: 1px solid ${props => props.theme.border};
-
- overflow-x: auto;
-
- ::-webkit-scrollbar {
- height: 7px;
- }
-}
-`;
-
-const StausBarContainer = styled.div`
- position: fixed;
- height: ${dimensions.statusBar.height}px;
- left: 0;
- right: 0;
- bottom: 0;
- background-color: ${props => props.theme.statusbar_background};
-`;
-
-const ScreenHorizontalSplitHandle = styled(HorizontalSplitHandle)`
- position: absolute;
- top: ${dimensions.toolBar.height}px;
- bottom: ${dimensions.statusBar.height}px;
-`;
-
-// const StyledRoot = styled.div`
-// // color: ${(props) => props.theme.fontColor};
-// `;
-
-export default function Screen() {
- const theme = useTheme();
- const currentWidget = useCurrentWidget();
- const leftPanelWidth = useLeftPanelWidth();
- const setLeftPanelWidth = useSetLeftPanelWidth();
- const contentLeft = currentWidget
- ? dimensions.widgetMenu.iconSize + leftPanelWidth + dimensions.splitter.thickness
- : dimensions.widgetMenu.iconSize;
- const toolbarPortalRef = React.useRef();
- const statusbarPortalRef = React.useRef();
- const onSplitDown = useSplitterDrag('clientX', diff => setLeftPanelWidth(v => v + diff));
-
- const { getRootProps, getInputProps, isDragActive } = useUploadsZone();
-
- return (
-
-
-
-
-
-
-
-
- {!!currentWidget && (
-
-
-
-
-
- )}
- {!!currentWidget && (
-
- )}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- );
-}
diff --git a/packages/web/src/TabContent.js b/packages/web/src/TabContent.js
deleted file mode 100644
index f90da055f..000000000
--- a/packages/web/src/TabContent.js
+++ /dev/null
@@ -1,98 +0,0 @@
-import React from 'react';
-import _ from 'lodash';
-import styled from 'styled-components';
-import tabs from './tabs';
-import { useOpenedTabs } from './utility/globalState';
-import ErrorBoundary from './utility/ErrorBoundary';
-
-const TabContainerStyled = styled.div`
- position: absolute;
- left: 0;
- top: 0;
- right: 0;
- bottom: 0;
- display: flex;
- visibility: ${props =>
- // @ts-ignore
- props.tabVisible ? 'visible' : 'hidden'};
-`;
-
-function TabContainer({ TabComponent, ...props }) {
- const { tabVisible, tabid, toolbarPortalRef, statusbarPortalRef } = props;
- return (
- // @ts-ignore
-
-
-
-
-
- );
-}
-
-const TabContainerMemo = React.memo(TabContainer);
-
-function createTabComponent(selectedTab) {
- const TabComponent = tabs[selectedTab.tabComponent];
- if (TabComponent) {
- return {
- TabComponent,
- props: selectedTab.props,
- };
- }
- return null;
-}
-
-export default function TabContent({ toolbarPortalRef, statusbarPortalRef }) {
- const files = useOpenedTabs();
-
- const [mountedTabs, setMountedTabs] = React.useState({});
-
- const selectedTab = files.find(x => x.selected && x.closedTime == null);
-
- React.useEffect(() => {
- // cleanup closed tabs
-
- if (
- _.difference(
- _.keys(mountedTabs),
- _.map(
- files.filter(x => x.closedTime == null),
- 'tabid'
- )
- ).length > 0
- ) {
- setMountedTabs(_.pickBy(mountedTabs, (v, k) => files.find(x => x.tabid == k && x.closedTime == null)));
- }
-
- if (selectedTab) {
- const { tabid } = selectedTab;
- if (tabid && !mountedTabs[tabid])
- setMountedTabs({
- ...mountedTabs,
- [tabid]: createTabComponent(selectedTab),
- });
- }
- }, [mountedTabs, files]);
-
- return _.keys(mountedTabs).map(tabid => {
- const { TabComponent, props } = mountedTabs[tabid];
- const tabVisible = tabid == (selectedTab && selectedTab.tabid);
- return (
-
- );
- });
-}
diff --git a/packages/web/src/TabsPanel.js b/packages/web/src/TabsPanel.js
deleted file mode 100644
index 37c3e121d..000000000
--- a/packages/web/src/TabsPanel.js
+++ /dev/null
@@ -1,300 +0,0 @@
-import _ from 'lodash';
-import React from 'react';
-import styled from 'styled-components';
-import { DropDownMenuItem, DropDownMenuDivider } from './modals/DropDownMenu';
-
-import { useOpenedTabs, useSetOpenedTabs, useCurrentDatabase, useSetCurrentDatabase } from './utility/globalState';
-import { getConnectionInfo } from './utility/metadataLoaders';
-import { FontIcon } from './icons';
-import useTheme from './theme/useTheme';
-import usePropsCompare from './utility/usePropsCompare';
-import { useShowMenu } from './modals/showMenu';
-import { setSelectedTabFunc } from './utility/common';
-import getElectron from './utility/getElectron';
-
-// const files = [
-// { name: 'app.js' },
-// { name: 'BranchCategory', type: 'table', selected: true },
-// { name: 'ApplicationList' },
-// ];
-
-const DbGroupHandler = styled.div`
- display: flex;
- flex: 1;
- align-content: stretch;
-`;
-
-const DbWrapperHandler = styled.div`
- display: flex;
- flex-direction: column;
- align-items: stretch;
-`;
-
-const DbNameWrapper = styled.div`
- text-align: center;
- font-size: 8pt;
- border-bottom: 1px solid ${props => props.theme.border};
- border-right: 1px solid ${props => props.theme.border};
- cursor: pointer;
- user-select: none;
- padding: 1px;
- position: relative;
- white-space: nowrap;
-
- overflow: hidden;
- text-overflow: ellipsis;
- // height: 15px;
-
- &:hover {
- background-color: ${props => props.theme.tabs_background3};
- }
- background-color: ${props =>
- // @ts-ignore
- props.selected ? props.theme.tabs_background1 : 'inherit'};
-`;
-
-// const DbNameWrapperInner = styled.div`
-// position: absolute;
-// white-space: nowrap;
-// `;
-
-const FileTabItem = styled.div`
- border-right: 1px solid ${props => props.theme.border};
- padding-left: 15px;
- padding-right: 15px;
- flex-shrink: 1;
- flex-grow: 1;
- min-width: 10px;
- display: flex;
- align-items: center;
- cursor: pointer;
- user-select: none;
- &:hover {
- color: ${props => props.theme.tabs_font_hover};
- }
- background-color: ${props =>
- // @ts-ignore
- props.selected ? props.theme.tabs_background1 : 'inherit'};
-`;
-
-const FileNameWrapper = styled.span`
- margin-left: 5px;
-`;
-
-const CloseButton = styled(FontIcon)`
- margin-left: 5px;
- color: gray;
- &:hover {
- color: ${props => props.theme.tabs_font2};
- }
-`;
-
-function TabContextMenu({ close, closeAll, closeOthers, closeWithSameDb, closeWithOtherDb, props }) {
- const { database } = props || {};
- const { conid } = props || {};
- return (
- <>
- Close
- Close all
- Close others
- {conid && database && (
- Close with same DB - {database}
- )}
- {conid && database && (
- Close with other DB than {database}
- )}
- >
- );
-}
-
-function getTabDbName(tab) {
- if (tab.props && tab.props.conid && tab.props.database) return tab.props.database;
- if (tab.props && tab.props.archiveFolder) return tab.props.archiveFolder;
- return '(no DB)';
-}
-
-function getTabDbKey(tab) {
- if (tab.props && tab.props.conid && tab.props.database) return `database://${tab.props.database}-${tab.props.conid}`;
- if (tab.props && tab.props.archiveFolder) return `archive://${tab.props.archiveFolder}`;
- return '_no';
-}
-
-function getDbIcon(key) {
- if (key.startsWith('database://')) return 'icon database';
- if (key.startsWith('archive://')) return 'icon archive';
- return 'icon file';
-}
-
-function buildTooltip(tab) {
- let res = tab.tooltip;
- if (tab.props && tab.props.savedFilePath) {
- if (res) res += '\n';
- res += tab.props.savedFilePath;
- }
- return res;
-}
-
-export default function TabsPanel() {
- // const formatDbKey = (conid, database) => `${database}-${conid}`;
- const theme = useTheme();
- const showMenu = useShowMenu();
-
- const tabs = useOpenedTabs();
- const setOpenedTabs = useSetOpenedTabs();
- const currentDb = useCurrentDatabase();
- const setCurrentDb = useSetCurrentDatabase();
-
- const { name, connection } = currentDb || {};
- const currentDbKey = name && connection ? `database://${name}-${connection._id}` : '_no';
-
- const handleTabClick = (e, tabid) => {
- if (e.target.closest('.tabCloseButton')) {
- return;
- }
- setOpenedTabs(files => setSelectedTabFunc(files, tabid));
- };
- const closeTabFunc = closeCondition => tabid => {
- setOpenedTabs(files => {
- const active = files.find(x => x.tabid == tabid);
- if (!active) return files;
-
- const newFiles = files.map(x => ({
- ...x,
- closedTime: x.closedTime || (closeCondition(x, active) ? new Date().getTime() : undefined),
- }));
-
- if (newFiles.find(x => x.selected && x.closedTime == null)) {
- return newFiles;
- }
-
- const selectedIndex = _.findLastIndex(newFiles, x => x.closedTime == null);
-
- return newFiles.map((x, index) => ({
- ...x,
- selected: index == selectedIndex,
- }));
- });
- };
-
- const closeTab = closeTabFunc((x, active) => x.tabid == active.tabid);
- const closeAll = () => {
- const closedTime = new Date().getTime();
- setOpenedTabs(tabs =>
- tabs.map(tab => ({
- ...tab,
- closedTime: tab.closedTime || closedTime,
- selected: false,
- }))
- );
- };
- const closeWithSameDb = closeTabFunc(
- (x, active) =>
- _.get(x, 'props.conid') == _.get(active, 'props.conid') &&
- _.get(x, 'props.database') == _.get(active, 'props.database')
- );
- const closeWithOtherDb = closeTabFunc(
- (x, active) =>
- _.get(x, 'props.conid') != _.get(active, 'props.conid') ||
- _.get(x, 'props.database') != _.get(active, 'props.database')
- );
- const closeOthers = closeTabFunc((x, active) => x.tabid != active.tabid);
- const handleMouseUp = (e, tabid) => {
- if (e.button == 1) {
- e.preventDefault();
- closeTab(tabid);
- }
- };
- const handleContextMenu = (event, tabid, props) => {
- event.preventDefault();
- showMenu(
- event.pageX,
- event.pageY,
- closeTab(tabid)}
- closeAll={closeAll}
- closeOthers={() => closeOthers(tabid)}
- closeWithSameDb={() => closeWithSameDb(tabid)}
- closeWithOtherDb={() => closeWithOtherDb(tabid)}
- props={props}
- />
- );
- };
-
- React.useEffect(() => {
- const electron = getElectron();
- if (electron) {
- const { ipcRenderer } = electron;
- const activeTab = tabs.find(x => x.selected);
- window['dbgate_activeTabId'] = activeTab ? activeTab.tabid : null;
- ipcRenderer.send('update-menu');
- }
- }, [tabs]);
-
- // console.log(
- // 't',
- // tabs.map(x => x.tooltip)
- // );
- const tabsWithDb = tabs
- .filter(x => !x.closedTime)
- .map(tab => ({
- ...tab,
- tabDbName: getTabDbName(tab),
- tabDbKey: getTabDbKey(tab),
- }));
- const tabsByDb = _.groupBy(tabsWithDb, 'tabDbKey');
- const dbKeys = _.keys(tabsByDb).sort();
-
- const handleSetDb = async props => {
- const { conid, database } = props || {};
- if (conid) {
- const connection = await getConnectionInfo({ conid, database });
- if (connection) {
- setCurrentDb({ connection, name: database });
- return;
- }
- }
- setCurrentDb(null);
- };
-
- return (
- <>
- {dbKeys.map(dbKey => (
-
- handleSetDb(tabsByDb[dbKey][0].props)}
- theme={theme}
- >
- {tabsByDb[dbKey][0].tabDbName}
-
-
- {_.sortBy(tabsByDb[dbKey], ['title', 'tabid']).map(tab => (
- handleTabClick(e, tab.tabid)}
- onMouseUp={e => handleMouseUp(e, tab.tabid)}
- onContextMenu={e => handleContextMenu(e, tab.tabid, tab.props)}
- >
- { }
- {tab.title}
- {
- e.preventDefault();
- closeTab(tab.tabid);
- }}
- />
-
- ))}
-
-
- ))}
- >
- );
-}
diff --git a/packages/web/src/appobj/AppObjectCore.js b/packages/web/src/appobj/AppObjectCore.js
deleted file mode 100644
index 58efa6b2d..000000000
--- a/packages/web/src/appobj/AppObjectCore.js
+++ /dev/null
@@ -1,97 +0,0 @@
-// @ts-nocheck
-
-import _ from 'lodash';
-import React from 'react';
-import styled from 'styled-components';
-import { FontIcon } from '../icons';
-import { useShowMenu } from '../modals/showMenu';
-import useTheme from '../theme/useTheme';
-
-const AppObjectDiv = styled.div`
- padding: 5px;
- ${props =>
- !props.disableHover &&
- `
- &:hover {
- background-color: ${props.theme.left_background_blue[1]};
- }
- `}
- cursor: pointer;
- white-space: nowrap;
- font-weight: ${props => (props.isBold ? 'bold' : 'normal')};
-`;
-
-const IconWrap = styled.span`
- margin-right: 5px;
-`;
-
-const StatusIconWrap = styled.span`
- margin-left: 5px;
-`;
-
-const ExtInfoWrap = styled.span`
- font-weight: normal;
- margin-left: 5px;
- color: ${props => props.theme.left_font3};
-`;
-
-export function AppObjectCore({
- title,
- icon,
- data,
- onClick = undefined,
- onClick2 = undefined,
- onClick3 = undefined,
- isBold = undefined,
- isBusy = undefined,
- prefix = undefined,
- statusIcon = undefined,
- extInfo = undefined,
- statusTitle = undefined,
- disableHover = false,
- children = null,
- Menu = undefined,
- ...other
-}) {
- const theme = useTheme();
- const showMenu = useShowMenu();
-
- const handleContextMenu = event => {
- if (!Menu) return;
-
- event.preventDefault();
- showMenu(event.pageX, event.pageY, );
- };
-
- return (
- <>
- {
- if (onClick) onClick(data);
- if (onClick2) onClick2(data);
- if (onClick3) onClick3(data);
- }}
- theme={theme}
- isBold={isBold}
- draggable
- onDragStart={e => {
- e.dataTransfer.setData('app_object_drag_data', JSON.stringify(data));
- }}
- disableHover={disableHover}
- {...other}
- >
- {prefix}
- {isBusy ? : }
- {title}
- {statusIcon && (
-
-
-
- )}
- {extInfo && {extInfo} }
-
- {children}
- >
- );
-}
diff --git a/packages/web/src/appobj/AppObjectList.js b/packages/web/src/appobj/AppObjectList.js
deleted file mode 100644
index 7f6ac8556..000000000
--- a/packages/web/src/appobj/AppObjectList.js
+++ /dev/null
@@ -1,164 +0,0 @@
-import React from 'react';
-import _ from 'lodash';
-import styled from 'styled-components';
-import { ExpandIcon } from '../icons';
-import useTheme from '../theme/useTheme';
-
-const SubItemsDiv = styled.div`
- margin-left: 28px;
-`;
-
-const ExpandIconHolder2 = styled.span`
- margin-right: 3px;
- // position: relative;
- // top: -3px;
-`;
-
-const ExpandIconHolder = styled.span`
- margin-right: 5px;
-`;
-
-const GroupDiv = styled.div`
- user-select: none;
- padding: 5px;
- &:hover {
- background-color: ${props => props.theme.left_background_blue[1]};
- }
- cursor: pointer;
- white-space: nowrap;
- font-weight: bold;
-`;
-
-function AppObjectListItem({
- AppObjectComponent,
- data,
- filter,
- onObjectClick,
- isExpandable,
- SubItems,
- getCommonProps,
- expandOnClick,
- ExpandIconComponent,
-}) {
- const [isExpanded, setIsExpanded] = React.useState(false);
-
- const expandable = data && isExpandable && isExpandable(data);
-
- React.useEffect(() => {
- if (!expandable) {
- setIsExpanded(false);
- }
- }, [expandable]);
-
- let commonProps = {
- prefix: SubItems ? (
-
- {expandable ? (
- {
- setIsExpanded(v => !v);
- e.stopPropagation();
- }}
- />
- ) : (
-
- )}
-
- ) : null,
- };
-
- if (SubItems && expandOnClick) {
- commonProps.onClick2 = () => setIsExpanded(v => !v);
- }
- if (onObjectClick) {
- commonProps.onClick3 = onObjectClick;
- }
-
- if (getCommonProps) {
- commonProps = { ...commonProps, ...getCommonProps(data) };
- }
-
- let res = ;
- if (SubItems && isExpanded) {
- res = (
- <>
- {res}
-
-
-
- >
- );
- }
- return res;
-}
-
-function AppObjectGroup({ group, items }) {
- const [isExpanded, setIsExpanded] = React.useState(true);
- const theme = useTheme();
- const filtered = items.filter(x => x.component);
- let countText = filtered.length.toString();
- if (filtered.length < items.length) countText += `/${items.length}`;
-
- return (
- <>
- setIsExpanded(!isExpanded)} theme={theme}>
-
-
-
- {group} {items && `(${countText})`}
-
- {isExpanded && filtered.map(x => x.component)}
- >
- );
-}
-
-export function AppObjectList({
- list,
- AppObjectComponent,
- SubItems = undefined,
- onObjectClick = undefined,
- filter = undefined,
- groupFunc = undefined,
- groupOrdered = undefined,
- isExpandable = undefined,
- getCommonProps = undefined,
- expandOnClick = false,
- ExpandIconComponent = ExpandIcon,
-}) {
- const createComponent = data => (
-
- );
-
- if (groupFunc) {
- const listGrouped = _.compact(
- (list || []).map(data => {
- const matcher = AppObjectComponent.createMatcher && AppObjectComponent.createMatcher(data);
- const component = matcher && !matcher(filter) ? null : createComponent(data);
- const group = groupFunc(data);
- return { group, data, component };
- })
- );
- const groups = _.groupBy(listGrouped, 'group');
- return (groupOrdered || _.keys(groups)).map(group => (
-
- ));
- }
-
- return (list || []).map(data => {
- const matcher = AppObjectComponent.createMatcher && AppObjectComponent.createMatcher(data);
- if (matcher && !matcher(filter)) return null;
- return createComponent(data);
- });
-}
diff --git a/packages/web/src/appobj/ArchiveFileAppObject.js b/packages/web/src/appobj/ArchiveFileAppObject.js
deleted file mode 100644
index 3fed3ba7c..000000000
--- a/packages/web/src/appobj/ArchiveFileAppObject.js
+++ /dev/null
@@ -1,75 +0,0 @@
-import React from 'react';
-import { DropDownMenuItem } from '../modals/DropDownMenu';
-import { filterName } from 'dbgate-datalib';
-import axios from '../utility/axios';
-import { AppObjectCore } from './AppObjectCore';
-import useOpenNewTab from '../utility/useOpenNewTab';
-
-function openArchive(openNewTab, fileName, folderName) {
- openNewTab({
- title: fileName,
- icon: 'img archive',
- tooltip: `${folderName}\n${fileName}`,
- tabComponent: 'ArchiveFileTab',
- props: {
- archiveFile: fileName,
- archiveFolder: folderName,
- },
- });
-}
-
-function Menu({ data }) {
- const openNewTab = useOpenNewTab();
- const handleDelete = () => {
- axios.post('archive/delete-file', { file: data.fileName, folder: data.folderName });
- // setOpenedTabs((tabs) => tabs.filter((x) => x.tabid != data.tabid));
- };
- const handleOpenRead = () => {
- openArchive(openNewTab, data.fileName, data.folderName);
- };
- const handleOpenWrite = async () => {
- // const resp = await axios.post('archive/load-free-table', { file: data.fileName, folder: data.folderName });
-
- openNewTab({
- title: data.fileName,
- icon: 'img archive',
- tabComponent: 'FreeTableTab',
- props: {
- initialArgs: {
- functionName: 'archiveReader',
- props: {
- fileName: data.fileName,
- folderName: data.folderName,
- },
- },
- archiveFile: data.fileName,
- archiveFolder: data.folderName,
- },
- });
- };
-
- return (
- <>
- Open (readonly)
- Open in free table editor
- Delete
- >
- );
-}
-
-function ArchiveFileAppObject({ data, commonProps }) {
- const { fileName, folderName } = data;
- const openNewTab = useOpenNewTab();
- const onClick = () => {
- openArchive(openNewTab, fileName, folderName);
- };
-
- return (
-
- );
-}
-
-ArchiveFileAppObject.extractKey = data => data.fileName;
-ArchiveFileAppObject.createMatcher = ({ fileName }) => filter => filterName(filter, fileName);
-
-export default ArchiveFileAppObject;
diff --git a/packages/web/src/appobj/ArchiveFolderAppObject.js b/packages/web/src/appobj/ArchiveFolderAppObject.js
deleted file mode 100644
index bcfced98e..000000000
--- a/packages/web/src/appobj/ArchiveFolderAppObject.js
+++ /dev/null
@@ -1,34 +0,0 @@
-import React from 'react';
-import { DropDownMenuItem } from '../modals/DropDownMenu';
-import axios from '../utility/axios';
-import { filterName } from 'dbgate-datalib';
-import { AppObjectCore } from './AppObjectCore';
-import { useCurrentArchive } from '../utility/globalState';
-
-function Menu({ data }) {
- const handleDelete = () => {
- axios.post('archive/delete-folder', { folder: data.name });
- };
- return <>{data.name != 'default' && Delete }>;
-}
-
-function ArchiveFolderAppObject({ data, commonProps }) {
- const { name } = data;
- const currentArchive = useCurrentArchive();
-
- return (
-
- );
-}
-
-ArchiveFolderAppObject.extractKey = data => data.name;
-ArchiveFolderAppObject.createMatcher = data => filter => filterName(filter, data.name);
-
-export default ArchiveFolderAppObject;
diff --git a/packages/web/src/appobj/ClosedTabAppObject.js b/packages/web/src/appobj/ClosedTabAppObject.js
deleted file mode 100644
index 0ef7e11b9..000000000
--- a/packages/web/src/appobj/ClosedTabAppObject.js
+++ /dev/null
@@ -1,73 +0,0 @@
-import React from 'react';
-import _ from 'lodash';
-import moment from 'moment';
-import { DropDownMenuItem } from '../modals/DropDownMenu';
-import { useSetOpenedTabs } from '../utility/globalState';
-import { AppObjectCore } from './AppObjectCore';
-import { setSelectedTabFunc } from '../utility/common';
-import styled from 'styled-components';
-import { FontIcon } from '../icons';
-import useTheme from '../theme/useTheme';
-
-const InfoDiv = styled.div`
- margin-left: 30px;
- color: ${props => props.theme.left_font3};
-`;
-
-function Menu({ data }) {
- const setOpenedTabs = useSetOpenedTabs();
- const handleDelete = () => {
- setOpenedTabs(tabs => tabs.filter(x => x.tabid != data.tabid));
- };
- const handleDeleteOlder = () => {
- setOpenedTabs(tabs => tabs.filter(x => !x.closedTime || x.closedTime >= data.closedTime));
- };
- return (
- <>
- Delete
- Delete older
- >
- );
-}
-
-function ClosedTabAppObject({ data, commonProps }) {
- const { tabid, props, selected, icon, title, closedTime, busy } = data;
- const setOpenedTabs = useSetOpenedTabs();
- const theme = useTheme();
-
- const onClick = () => {
- setOpenedTabs(files =>
- setSelectedTabFunc(
- files.map(x => ({
- ...x,
- closedTime: x.tabid == tabid ? undefined : x.closedTime,
- })),
- tabid
- )
- );
- };
-
- return (
-
- {data.props && data.props.database && (
-
- {data.props.database}
-
- )}
- {data.contentPreview && {data.contentPreview} }
-
- );
-}
-
-ClosedTabAppObject.extractKey = data => data.tabid;
-
-export default ClosedTabAppObject;
diff --git a/packages/web/src/appobj/ConnectionAppObject.js b/packages/web/src/appobj/ConnectionAppObject.js
deleted file mode 100644
index 4e5c7c3b0..000000000
--- a/packages/web/src/appobj/ConnectionAppObject.js
+++ /dev/null
@@ -1,119 +0,0 @@
-import _ from 'lodash';
-import React from 'react';
-import { DropDownMenuItem } from '../modals/DropDownMenu';
-import ConnectionModal from '../modals/ConnectionModal';
-import axios from '../utility/axios';
-import { filterName } from 'dbgate-datalib';
-import ConfirmModal from '../modals/ConfirmModal';
-import CreateDatabaseModal from '../modals/CreateDatabaseModal';
-import { useCurrentDatabase, useOpenedConnections, useSetOpenedConnections } from '../utility/globalState';
-import { AppObjectCore } from './AppObjectCore';
-import useShowModal from '../modals/showModal';
-import { useConfig } from '../utility/metadataLoaders';
-import useExtensions from '../utility/useExtensions';
-
-function Menu({ data }) {
- const openedConnections = useOpenedConnections();
- const setOpenedConnections = useSetOpenedConnections();
- const showModal = useShowModal();
- const config = useConfig();
-
- const handleEdit = () => {
- showModal(modalState => );
- };
- const handleDelete = () => {
- showModal(modalState => (
- axios.post('connections/delete', data)}
- />
- ));
- };
- const handleCreateDatabase = () => {
- showModal(modalState => );
- };
- const handleRefresh = () => {
- axios.post('server-connections/refresh', { conid: data._id });
- };
- const handleDisconnect = () => {
- setOpenedConnections(list => list.filter(x => x != data._id));
- };
- const handleConnect = () => {
- setOpenedConnections(list => _.uniq([...list, data._id]));
- };
- return (
- <>
- {config.runAsPortal == false && (
- <>
- Edit
- Delete
- >
- )}
- {!openedConnections.includes(data._id) && Connect }
- {openedConnections.includes(data._id) && data.status && (
- Refresh
- )}
- {openedConnections.includes(data._id) && (
- Disconnect
- )}
- {openedConnections.includes(data._id) && (
- Create database
- )}
- >
- );
-}
-
-function ConnectionAppObject({ data, commonProps }) {
- const { _id, server, displayName, engine, status } = data;
- const openedConnections = useOpenedConnections();
- const setOpenedConnections = useSetOpenedConnections();
- const currentDatabase = useCurrentDatabase();
- const extensions = useExtensions();
-
- const isBold = _.get(currentDatabase, 'connection._id') == _id;
- const onClick = () => setOpenedConnections(c => _.uniq([...c, _id]));
-
- let statusIcon = null;
- let statusTitle = null;
-
- let extInfo = null;
- if (extensions.drivers.find(x => x.engine == engine)) {
- const match = (engine || '').match(/^([^@]*)@/);
- extInfo = match ? match[1] : engine;
- } else {
- extInfo = engine;
- statusIcon = 'img warn';
- statusTitle = `Engine driver ${engine} not found, review installed plugins and change engine in edit connection dialog`;
- }
-
- if (openedConnections.includes(_id)) {
- if (!status) statusIcon = 'icon loading';
- else if (status.name == 'pending') statusIcon = 'icon loading';
- else if (status.name == 'ok') statusIcon = 'img ok';
- else statusIcon = 'img error';
- if (status && status.name == 'error') {
- statusTitle = status.message;
- }
- }
-
- return (
-
- );
-}
-
-ConnectionAppObject.extractKey = data => data._id;
-ConnectionAppObject.createMatcher = ({ displayName, server }) => filter => filterName(filter, displayName, server);
-
-export default ConnectionAppObject;
diff --git a/packages/web/src/appobj/DatabaseAppObject.js b/packages/web/src/appobj/DatabaseAppObject.js
deleted file mode 100644
index 04cef6bd9..000000000
--- a/packages/web/src/appobj/DatabaseAppObject.js
+++ /dev/null
@@ -1,90 +0,0 @@
-import React from 'react';
-import _ from 'lodash';
-import { DropDownMenuItem } from '../modals/DropDownMenu';
-import ImportExportModal from '../modals/ImportExportModal';
-import { getDefaultFileFormat } from '../utility/fileformats';
-import { useCurrentDatabase } from '../utility/globalState';
-import { AppObjectCore } from './AppObjectCore';
-import useShowModal from '../modals/showModal';
-import useExtensions from '../utility/useExtensions';
-import useOpenNewTab from '../utility/useOpenNewTab';
-
-function Menu({ data }) {
- const { connection, name } = data;
- const openNewTab = useOpenNewTab();
-
- const extensions = useExtensions();
- const showModal = useShowModal();
-
- const tooltip = `${connection.displayName || connection.server}\n${name}`;
-
- const handleNewQuery = () => {
- openNewTab({
- title: 'Query #',
- icon: 'img sql-file',
- tooltip,
- tabComponent: 'QueryTab',
- props: {
- conid: connection._id,
- database: name,
- },
- });
- };
-
- const handleImport = () => {
- showModal(modalState => (
-
- ));
- };
-
- const handleExport = () => {
- showModal(modalState => (
-
- ));
- };
-
- return (
- <>
- New query
- Import
- Export
- >
- );
-}
-
-function DatabaseAppObject({ data, commonProps }) {
- const { name, connection } = data;
- const currentDatabase = useCurrentDatabase();
- return (
-
- );
-}
-
-DatabaseAppObject.extractKey = props => props.name;
-
-export default DatabaseAppObject;
diff --git a/packages/web/src/appobj/DatabaseObjectAppObject.js b/packages/web/src/appobj/DatabaseObjectAppObject.js
deleted file mode 100644
index dbf5bff84..000000000
--- a/packages/web/src/appobj/DatabaseObjectAppObject.js
+++ /dev/null
@@ -1,325 +0,0 @@
-import _ from 'lodash';
-import React from 'react';
-import { DropDownMenuDivider, DropDownMenuItem } from '../modals/DropDownMenu';
-import { getConnectionInfo } from '../utility/metadataLoaders';
-import fullDisplayName from '../utility/fullDisplayName';
-import { filterName } from 'dbgate-datalib';
-import ImportExportModal from '../modals/ImportExportModal';
-import { useSetOpenedTabs } from '../utility/globalState';
-import { AppObjectCore } from './AppObjectCore';
-import useShowModal from '../modals/showModal';
-import { findEngineDriver } from 'dbgate-tools';
-import useExtensions from '../utility/useExtensions';
-import useOpenNewTab from '../utility/useOpenNewTab';
-import uuidv1 from 'uuid/v1';
-import { AppObjectList } from './AppObjectList';
-
-const icons = {
- tables: 'img table',
- views: 'img view',
- procedures: 'img procedure',
- functions: 'img function',
-};
-
-const menus = {
- tables: [
- {
- label: 'Open data',
- tab: 'TableDataTab',
- forceNewTab: true,
- },
- {
- label: 'Open form',
- tab: 'TableDataTab',
- forceNewTab: true,
- initialData: {
- grid: {
- isFormView: true,
- },
- },
- },
- {
- label: 'Open structure',
- tab: 'TableStructureTab',
- },
- {
- label: 'Query designer',
- isQueryDesigner: true,
- },
- {
- isDivider: true,
- },
- {
- label: 'Export',
- isExport: true,
- },
- {
- label: 'Open in free table editor',
- isOpenFreeTable: true,
- },
- {
- label: 'Open active chart',
- isActiveChart: true,
- },
- {
- isDivider: true,
- },
- {
- label: 'SQL: CREATE TABLE',
- sqlTemplate: 'CREATE TABLE',
- },
- ],
- views: [
- {
- label: 'Open data',
- tab: 'ViewDataTab',
- forceNewTab: true,
- },
- {
- label: 'Open structure',
- tab: 'TableStructureTab',
- },
- {
- label: 'Query designer',
- isQueryDesigner: true,
- },
- {
- isDivider: true,
- },
- {
- label: 'Export',
- isExport: true,
- },
- {
- label: 'Open in free table editor',
- isOpenFreeTable: true,
- },
- {
- label: 'Open active chart',
- isActiveChart: true,
- },
- {
- isDivider: true,
- },
- {
- label: 'SQL: CREATE VIEW',
- sqlTemplate: 'CREATE OBJECT',
- },
- {
- label: 'SQL: CREATE TABLE',
- sqlTemplate: 'CREATE TABLE',
- },
- ],
- procedures: [
- {
- label: 'SQL: CREATE PROCEDURE',
- sqlTemplate: 'CREATE OBJECT',
- },
- {
- label: 'SQL: EXECUTE',
- sqlTemplate: 'EXECUTE PROCEDURE',
- },
- ],
- functions: [
- {
- label: 'SQL: CREATE FUNCTION',
- sqlTemplate: 'CREATE OBJECT',
- },
- ],
-};
-
-const defaultTabs = {
- tables: 'TableDataTab',
- views: 'ViewDataTab',
-};
-
-export async function openDatabaseObjectDetail(
- openNewTab,
- tabComponent,
- sqlTemplate,
- { schemaName, pureName, conid, database, objectTypeField },
- forceNewTab,
- initialData
-) {
- const connection = await getConnectionInfo({ conid });
- const tooltip = `${connection.displayName || connection.server}\n${database}\n${fullDisplayName({
- schemaName,
- pureName,
- })}`;
-
- openNewTab(
- {
- title: sqlTemplate ? 'Query #' : pureName,
- tooltip,
- icon: sqlTemplate ? 'img sql-file' : icons[objectTypeField],
- tabComponent: sqlTemplate ? 'QueryTab' : tabComponent,
- props: {
- schemaName,
- pureName,
- conid,
- database,
- objectTypeField,
- initialArgs: sqlTemplate ? { sqlTemplate } : null,
- },
- },
- initialData,
- { forceNewTab }
- );
-}
-
-function Menu({ data }) {
- const showModal = useShowModal();
- const openNewTab = useOpenNewTab();
- const extensions = useExtensions();
-
- const getDriver = async () => {
- const conn = await getConnectionInfo(data);
- if (!conn) return;
- const driver = findEngineDriver(conn, extensions);
- return driver;
- };
-
- return (
- <>
- {menus[data.objectTypeField].map(menu =>
- menu.isDivider ? (
-
- ) : (
- {
- if (menu.isExport) {
- showModal(modalState => (
-
- ));
- } else if (menu.isOpenFreeTable) {
- const coninfo = await getConnectionInfo(data);
- openNewTab({
- title: data.pureName,
- icon: 'img free-table',
- tabComponent: 'FreeTableTab',
- props: {
- initialArgs: {
- functionName: 'tableReader',
- props: {
- connection: {
- ...coninfo,
- database: data.database,
- },
- schemaName: data.schemaName,
- pureName: data.pureName,
- },
- },
- },
- });
- } else if (menu.isActiveChart) {
- const driver = await getDriver();
- const dmp = driver.createDumper();
- dmp.put('^select * from %f', data);
- openNewTab(
- {
- title: data.pureName,
- icon: 'img chart',
- tabComponent: 'ChartTab',
- props: {
- conid: data.conid,
- database: data.database,
- },
- },
- {
- editor: {
- config: { chartType: 'bar' },
- sql: dmp.s,
- },
- }
- );
- } else if (menu.isQueryDesigner) {
- openNewTab(
- {
- title: 'Query #',
- icon: 'img query-design',
- tabComponent: 'QueryDesignTab',
- props: {
- conid: data.conid,
- database: data.database,
- },
- },
- {
- editor: {
- tables: [
- {
- ...data,
- designerId: uuidv1(),
- left: 50,
- top: 50,
- },
- ],
- },
- }
- );
- } else {
- openDatabaseObjectDetail(
- openNewTab,
- menu.tab,
- menu.sqlTemplate,
- data,
- menu.forceNewTab,
- menu.initialData
- );
- }
- }}
- >
- {menu.label}
-
- )
- )}
- >
- );
-}
-
-function DatabaseObjectAppObject({ data, commonProps }) {
- const { conid, database, pureName, schemaName, objectTypeField } = data;
- const openNewTab = useOpenNewTab();
- const onClick = ({ schemaName, pureName }) => {
- openDatabaseObjectDetail(
- openNewTab,
- defaultTabs[objectTypeField],
- defaultTabs[objectTypeField] ? null : 'CREATE OBJECT',
- {
- schemaName,
- pureName,
- conid,
- database,
- objectTypeField,
- },
- false
- );
- };
-
- return (
-
- );
-}
-
-DatabaseObjectAppObject.extractKey = ({ schemaName, pureName }) =>
- schemaName ? `${schemaName}.${pureName}` : pureName;
-
-DatabaseObjectAppObject.createMatcher = ({ pureName }) => filter => filterName(filter, pureName);
-
-export default DatabaseObjectAppObject;
diff --git a/packages/web/src/appobj/FavoriteFileAppObject.js b/packages/web/src/appobj/FavoriteFileAppObject.js
deleted file mode 100644
index d9136a0f5..000000000
--- a/packages/web/src/appobj/FavoriteFileAppObject.js
+++ /dev/null
@@ -1,104 +0,0 @@
-import React from 'react';
-import { DropDownMenuItem } from '../modals/DropDownMenu';
-import FavoriteModal from '../modals/FavoriteModal';
-import useShowModal from '../modals/showModal';
-import axios from '../utility/axios';
-import { copyTextToClipboard } from '../utility/clipboard';
-import getElectron from '../utility/getElectron';
-import useOpenNewTab from '../utility/useOpenNewTab';
-import { SavedFileAppObjectBase } from './SavedFileAppObject';
-
-export function useOpenFavorite() {
- const openNewTab = useOpenNewTab();
-
- const openFavorite = React.useCallback(
- async favorite => {
- const { icon, tabComponent, title, props, tabdata } = favorite;
- let tabdataNew = tabdata;
- if (props.savedFile) {
- const resp = await axios.post('files/load', {
- folder: props.savedFolder,
- file: props.savedFile,
- format: props.savedFormat,
- });
- tabdataNew = {
- ...tabdata,
- editor: resp.data,
- };
- }
- openNewTab(
- {
- title,
- icon: icon || 'img favorite',
- props,
- tabComponent,
- },
- tabdataNew
- );
- },
- [openNewTab]
- );
-
- return openFavorite;
-}
-
-export function FavoriteFileAppObject({ data, commonProps }) {
- const { icon, tabComponent, title, props, tabdata, urlPath } = data;
- const openNewTab = useOpenNewTab();
- const showModal = useShowModal();
- const openFavorite = useOpenFavorite();
- const electron = getElectron();
-
- const editFavorite = () => {
- showModal(modalState => );
- };
-
- const editFavoriteJson = async () => {
- const resp = await axios.post('files/load', {
- folder: 'favorites',
- file: data.file,
- format: 'text',
- });
-
- openNewTab(
- {
- icon: 'icon favorite',
- title,
- tabComponent: 'FavoriteEditorTab',
- props: {
- savedFile: data.file,
- savedFormat: 'text',
- savedFolder: 'favorites',
- },
- },
- { editor: JSON.stringify(JSON.parse(resp.data), null, 2) }
- );
- };
-
- const copyLink = () => {
- copyTextToClipboard(`${document.location.origin}#favorite=${urlPath}`);
- };
-
- return (
- {
- openFavorite(data);
- }}
- menuExt={
- <>
- Edit
- Edit JSON definition
- {!electron && urlPath && Copy link }
- >
- }
- />
- );
-}
-
-FavoriteFileAppObject.extractKey = data => data.file;
diff --git a/packages/web/src/appobj/MacroAppObject.js b/packages/web/src/appobj/MacroAppObject.js
deleted file mode 100644
index 4a59e6c35..000000000
--- a/packages/web/src/appobj/MacroAppObject.js
+++ /dev/null
@@ -1,15 +0,0 @@
-import _ from 'lodash';
-import React from 'react';
-import { filterName } from 'dbgate-datalib';
-import { AppObjectCore } from './AppObjectCore';
-
-function MacroAppObject({ data, commonProps }) {
- const { name, type, title, group } = data;
-
- return ;
-}
-
-MacroAppObject.extractKey = data => data.name;
-MacroAppObject.createMatcher = ({ name, title }) => filter => filterName(filter, name, title);
-
-export default MacroAppObject;
diff --git a/packages/web/src/appobj/SavedFileAppObject.js b/packages/web/src/appobj/SavedFileAppObject.js
deleted file mode 100644
index 3feb1e9fb..000000000
--- a/packages/web/src/appobj/SavedFileAppObject.js
+++ /dev/null
@@ -1,314 +0,0 @@
-import React from 'react';
-import axios from '../utility/axios';
-import _ from 'lodash';
-import { DropDownMenuItem } from '../modals/DropDownMenu';
-import { AppObjectCore } from './AppObjectCore';
-import useNewQuery from '../query/useNewQuery';
-import { useCurrentDatabase } from '../utility/globalState';
-import ScriptWriter from '../impexp/ScriptWriter';
-import { extractPackageName } from 'dbgate-tools';
-import useShowModal from '../modals/showModal';
-import InputTextModal from '../modals/InputTextModal';
-import useHasPermission from '../utility/useHasPermission';
-import useOpenNewTab from '../utility/useOpenNewTab';
-import ConfirmModal from '../modals/ConfirmModal';
-
-function Menu({ data, menuExt = null, title = undefined, disableRename = false }) {
- const hasPermission = useHasPermission();
- const showModal = useShowModal();
- const handleDelete = () => {
- showModal(modalState => (
- {
- axios.post('files/delete', data);
- }}
- />
- ));
- };
- const handleRename = () => {
- showModal(modalState => (
- {
- axios.post('files/rename', { ...data, newFile });
- }}
- />
- ));
- };
- return (
- <>
- {hasPermission(`files/${data.folder}/write`) && (
- Delete
- )}
- {hasPermission(`files/${data.folder}/write`) && !disableRename && (
- Rename
- )}
- {menuExt}
- >
- );
-}
-
-export function SavedFileAppObjectBase({
- data,
- commonProps,
- format,
- icon,
- onLoad,
- title = undefined,
- menuExt = null,
- disableRename = false,
-}) {
- const { file, folder } = data;
-
- const onClick = async () => {
- const resp = await axios.post('files/load', { folder, file, format });
- onLoad(resp.data);
- };
-
- return (
- }
- />
- );
-}
-
-export function SavedSqlFileAppObject({ data, commonProps }) {
- const { file, folder } = data;
- const newQuery = useNewQuery();
- const currentDatabase = useCurrentDatabase();
- const openNewTab = useOpenNewTab();
-
- const connection = _.get(currentDatabase, 'connection');
- const database = _.get(currentDatabase, 'name');
-
- const handleGenerateExecute = () => {
- const script = new ScriptWriter();
- const conn = {
- ..._.omit(connection, ['displayName', '_id']),
- database,
- };
- script.put(`const sql = await dbgateApi.loadFile('${folder}/${file}');`);
- script.put(`await dbgateApi.executeQuery({ sql, connection: ${JSON.stringify(conn)} });`);
- // @ts-ignore
- script.requirePackage(extractPackageName(conn.engine));
-
- openNewTab(
- {
- title: 'Shell #',
- icon: 'img shell',
- tabComponent: 'ShellTab',
- },
- { editor: script.getScript() }
- );
- };
-
- return (
- Generate shell execute
- ) : null
- }
- onLoad={data => {
- newQuery({
- title: file,
- initialData: data,
- // @ts-ignore
- savedFile: file,
- savedFolder: 'sql',
- savedFormat: 'text',
- });
- }}
- />
- );
-}
-
-export function SavedShellFileAppObject({ data, commonProps }) {
- const { file, folder } = data;
- const openNewTab = useOpenNewTab();
-
- return (
- {
- openNewTab(
- {
- title: file,
- icon: 'img shell',
- tabComponent: 'ShellTab',
- props: {
- savedFile: file,
- savedFolder: 'shell',
- savedFormat: 'text',
- },
- },
- { editor: data }
- );
- }}
- />
- );
-}
-
-export function SavedChartFileAppObject({ data, commonProps }) {
- const { file, folder } = data;
- const openNewTab = useOpenNewTab();
-
- const currentDatabase = useCurrentDatabase();
-
- const connection = _.get(currentDatabase, 'connection') || {};
- const database = _.get(currentDatabase, 'name');
-
- const tooltip = `${connection.displayName || connection.server}\n${database}`;
-
- return (
- {
- openNewTab(
- {
- title: file,
- icon: 'img chart',
- tooltip,
- props: {
- conid: connection._id,
- database,
- savedFile: file,
- savedFolder: 'charts',
- savedFormat: 'json',
- },
- tabComponent: 'ChartTab',
- },
- { editor: data }
- );
- }}
- />
- );
-}
-
-export function SavedQueryFileAppObject({ data, commonProps }) {
- const { file, folder } = data;
- const openNewTab = useOpenNewTab();
-
- const currentDatabase = useCurrentDatabase();
-
- const connection = _.get(currentDatabase, 'connection') || {};
- const database = _.get(currentDatabase, 'name');
-
- const tooltip = `${connection.displayName || connection.server}\n${database}`;
-
- return (
- {
- openNewTab(
- {
- title: file,
- icon: 'img query-design',
- tooltip,
- props: {
- conid: connection._id,
- database,
- savedFile: file,
- savedFolder: 'query',
- savedFormat: 'json',
- },
- tabComponent: 'QueryDesignTab',
- },
- { editor: data }
- );
- }}
- />
- );
-}
-
-export function SavedMarkdownFileAppObject({ data, commonProps }) {
- const { file, folder } = data;
- const openNewTab = useOpenNewTab();
-
- const showPage = () => {
- openNewTab({
- title: file,
- icon: 'img markdown',
- tabComponent: 'MarkdownViewTab',
- props: {
- savedFile: file,
- savedFolder: 'markdown',
- savedFormat: 'text',
- },
- });
- };
- return (
- {
- openNewTab(
- {
- title: file,
- icon: 'img markdown',
- tabComponent: 'MarkdownEditorTab',
- props: {
- savedFile: file,
- savedFolder: 'markdown',
- savedFormat: 'text',
- },
- },
- { editor: data }
- );
- }}
- menuExt={Show page }
- />
- );
-}
-
-export function SavedFileAppObject({ data, commonProps }) {
- const { folder } = data;
- const folderTypes = {
- sql: SavedSqlFileAppObject,
- shell: SavedShellFileAppObject,
- charts: SavedChartFileAppObject,
- markdown: SavedMarkdownFileAppObject,
- query: SavedQueryFileAppObject,
- };
- const AppObject = folderTypes[folder];
- if (AppObject) {
- return ;
- }
- return null;
-}
-
-[
- SavedSqlFileAppObject,
- SavedShellFileAppObject,
- SavedChartFileAppObject,
- SavedMarkdownFileAppObject,
- SavedFileAppObject,
-].forEach(fn => {
- // @ts-ignore
- fn.extractKey = data => data.file;
-});
diff --git a/packages/web/src/appobj/SubColumnParamList.js b/packages/web/src/appobj/SubColumnParamList.js
deleted file mode 100644
index 792b915d8..000000000
--- a/packages/web/src/appobj/SubColumnParamList.js
+++ /dev/null
@@ -1,36 +0,0 @@
-import { findForeignKeyForColumn } from 'dbgate-tools';
-import React from 'react';
-import { getColumnIcon } from '../datagrid/ColumnLabel';
-import { AppObjectCore } from './AppObjectCore';
-import { AppObjectList } from './AppObjectList';
-
-function ColumnAppObject({ data, commonProps }) {
- const { columnName, dataType, foreignKey } = data;
- let extInfo = dataType;
- if (foreignKey) extInfo += ` -> ${foreignKey.refTableName}`;
- return (
-
- );
-}
-ColumnAppObject.extractKey = ({ columnName }) => columnName;
-
-export default function SubColumnParamList({ data }) {
- const { columns } = data;
-
- return (
- ({
- ...col,
- foreignKey: findForeignKeyForColumn(data, col),
- }))}
- AppObjectComponent={ColumnAppObject}
- />
- );
-}
diff --git a/packages/web/src/celldata/CellDataView.js b/packages/web/src/celldata/CellDataView.js
deleted file mode 100644
index bea7c6ec5..000000000
--- a/packages/web/src/celldata/CellDataView.js
+++ /dev/null
@@ -1,99 +0,0 @@
-import React from 'react';
-import _ from 'lodash';
-import { SelectField } from '../utility/inputs';
-import ErrorInfo from '../widgets/ErrorInfo';
-import styled from 'styled-components';
-import { TextCellViewWrap, TextCellViewNoWrap } from './TextCellView';
-import JsonCellView from './JsonCellDataView';
-import useTheme from '../theme/useTheme';
-
-const Toolbar = styled.div`
- display: flex;
- background: ${props => props.theme.toolbar_background};
- align-items: center;
-`;
-
-const MainWrapper = styled.div`
- display: flex;
- flex: 1;
- flex-direction: column;
-`;
-
-const DataWrapper = styled.div`
- display: flex;
- flex: 1;
-`;
-
-const formats = [
- {
- type: 'textWrap',
- title: 'Text (wrap)',
- Component: TextCellViewWrap,
- single: true,
- },
- {
- type: 'text',
- title: 'Text (no wrap)',
- Component: TextCellViewNoWrap,
- single: true,
- },
- {
- type: 'json',
- title: 'Json',
- Component: JsonCellView,
- single: true,
- },
-];
-
-function autodetect(selection, grider, value) {
- if (_.isString(value)) {
- if (value.startsWith('[') || value.startsWith('{')) return 'json';
- }
- return 'textWrap';
-}
-
-export default function CellDataView({ selection = undefined, grider = undefined, selectedValue = undefined }) {
- const [selectedFormatType, setSelectedFormatType] = React.useState('autodetect');
- const theme = useTheme();
- let value = null;
- if (grider && selection && selection.length == 1) {
- const rowData = grider.getRowData(selection[0].row);
- const { column } = selection[0];
- if (rowData) value = rowData[column];
- }
- if (selectedValue) {
- value = selectedValue;
- }
- const autodetectFormatType = React.useMemo(() => autodetect(selection, grider, value), [selection, grider, value]);
- const autodetectFormat = formats.find(x => x.type == autodetectFormatType);
-
- const usedFormatType = selectedFormatType == 'autodetect' ? autodetectFormatType : selectedFormatType;
- const usedFormat = formats.find(x => x.type == usedFormatType);
-
- const { Component } = usedFormat || {};
-
- return (
-
-
- Format:
- setSelectedFormatType(e.target.value)}>
- Autodetect - {autodetectFormat.title}
-
- {formats.map(fmt => (
-
- {fmt.title}
-
- ))}
-
-
-
-
- {usedFormat == null || (usedFormat.single && value == null) ? (
-
- ) : (
-
- )}
-
-
- );
-}
diff --git a/packages/web/src/celldata/JsonCellDataView.js b/packages/web/src/celldata/JsonCellDataView.js
deleted file mode 100644
index 3987fc456..000000000
--- a/packages/web/src/celldata/JsonCellDataView.js
+++ /dev/null
@@ -1,35 +0,0 @@
-import React from 'react';
-import styled from 'styled-components';
-import ReactJson from 'react-json-view';
-import ErrorInfo from '../widgets/ErrorInfo';
-import useTheme from '../theme/useTheme';
-
-const OuterWrapper = styled.div`
- flex: 1;
- position: relative;
-`;
-
-const InnerWrapper = styled.div`
- overflow: scroll;
- position: absolute;
- left: 0;
- top: 0;
- right: 0;
- bottom: 0;
-`;
-
-export default function JsonCellView({ value }) {
- const theme = useTheme();
- try {
- const json = React.useMemo(() => JSON.parse(value), [value]);
- return (
-
-
-
-
-
- );
- } catch (err) {
- return ;
- }
-}
diff --git a/packages/web/src/celldata/TextCellView.js b/packages/web/src/celldata/TextCellView.js
deleted file mode 100644
index dc9bc4882..000000000
--- a/packages/web/src/celldata/TextCellView.js
+++ /dev/null
@@ -1,22 +0,0 @@
-import React from 'react';
-import styled from 'styled-components';
-
-const StyledInput = styled.textarea`
- flex: 1;
-`;
-
-export function TextCellViewWrap({ value, grider, selection }) {
- return ;
-}
-
-export function TextCellViewNoWrap({ value, grider, selection }) {
- return (
- grider.setCellValue(selection[0].row, selection[0].column, e.target.value)}
- />
- );
-}
diff --git a/packages/web/src/charts/ChartEditor.js b/packages/web/src/charts/ChartEditor.js
deleted file mode 100644
index 588f740a0..000000000
--- a/packages/web/src/charts/ChartEditor.js
+++ /dev/null
@@ -1,154 +0,0 @@
-import React from 'react';
-import Chart from 'react-chartjs-2';
-import _ from 'lodash';
-import styled from 'styled-components';
-import useTheme from '../theme/useTheme';
-import useDimensions from '../utility/useDimensions';
-import { HorizontalSplitter } from '../widgets/Splitter';
-import WidgetColumnBar, { WidgetColumnBarItem } from '../widgets/WidgetColumnBar';
-import { FormCheckboxField, FormSelectField, FormTextField } from '../utility/forms';
-import DataChart from './DataChart';
-import { FormProviderCore } from '../utility/FormProvider';
-import { loadChartData, loadChartStructure } from './chartDataLoader';
-import useExtensions from '../utility/useExtensions';
-import { getConnectionInfo } from '../utility/metadataLoaders';
-import { findEngineDriver } from 'dbgate-tools';
-import { FormFieldTemplateTiny } from '../utility/formStyle';
-import { ManagerInnerContainer } from '../datagrid/ManagerStyles';
-import { presetPrimaryColors } from '@ant-design/colors';
-import ErrorInfo from '../widgets/ErrorInfo';
-
-const LeftContainer = styled.div`
- background-color: ${props => props.theme.manager_background};
- display: flex;
- flex: 1;
-`;
-
-export default function ChartEditor({ data, config, setConfig, sql, conid, database }) {
- const [managerSize, setManagerSize] = React.useState(0);
- const theme = useTheme();
- const extensions = useExtensions();
- const [error, setError] = React.useState(null);
-
- const [availableColumnNames, setAvailableColumnNames] = React.useState([]);
- const [loadedData, setLoadedData] = React.useState(null);
-
- const getDriver = async () => {
- const conn = await getConnectionInfo({ conid });
- if (!conn) return;
- const driver = findEngineDriver(conn, extensions);
- return driver;
- };
-
- const handleLoadColumns = async () => {
- const driver = await getDriver();
- if (!driver) return;
- try {
- const columns = await loadChartStructure(driver, conid, database, sql);
- setAvailableColumnNames(columns);
- } catch (err) {
- setError(err.message);
- }
- };
-
- const handleLoadData = async () => {
- const driver = await getDriver();
- if (!driver) return;
- const loaded = await loadChartData(driver, conid, database, sql, config);
- if (!loaded) return;
- const { columns, rows } = loaded;
- setLoadedData({
- structure: columns,
- rows,
- });
- };
-
- React.useEffect(() => {
- if (sql && conid && database) {
- handleLoadColumns();
- }
- }, [sql, conid, database, extensions]);
-
- React.useEffect(() => {
- if (data) {
- setAvailableColumnNames(data ? data.structure.columns.map(x => x.columnName) : []);
- }
- }, [data]);
-
- React.useEffect(() => {
- if (config.labelColumn && sql && conid && database) {
- handleLoadData();
- }
- }, [config, sql, conid, database, availableColumnNames]);
-
- if (error) {
- return (
-
-
-
- );
- }
-
- return (
-
-
-
-
-
-
-
- Bar
- Line
- {/* Radar */}
- Pie
- Polar area
- {/* Bubble
- Scatter */}
-
-
-
- Begin
- End (most recent data for datetime)
-
-
-
-
-
-
-
- {availableColumnNames.length > 0 && (
-
-
- {availableColumnNames.map(col => (
-
- {col}
-
- ))}
-
- )}
- {availableColumnNames.map(col => (
-
-
- {config[`dataColumn_${col}`] && (
-
- Random
-
- {_.keys(presetPrimaryColors).map(color => (
-
- {_.startCase(color)}
-
- ))}
-
- )}
-
- ))}
-
-
-
-
-
-
-
-
- );
-}
diff --git a/packages/web/src/charts/ChartToolbar.js b/packages/web/src/charts/ChartToolbar.js
deleted file mode 100644
index 62b3a1aaf..000000000
--- a/packages/web/src/charts/ChartToolbar.js
+++ /dev/null
@@ -1,15 +0,0 @@
-import React from 'react';
-import ToolbarButton from '../widgets/ToolbarButton';
-
-export default function ChartToolbar({ modelState, dispatchModel }) {
- return (
- <>
- dispatchModel({ type: 'undo' })} icon="icon undo">
- Undo
-
- dispatchModel({ type: 'redo' })} icon="icon redo">
- Redo
-
- >
- );
-}
diff --git a/packages/web/src/charts/DataChart.js b/packages/web/src/charts/DataChart.js
deleted file mode 100644
index 6afcf36dc..000000000
--- a/packages/web/src/charts/DataChart.js
+++ /dev/null
@@ -1,165 +0,0 @@
-import React from 'react';
-import _ from 'lodash';
-import Chart from 'react-chartjs-2';
-import randomcolor from 'randomcolor';
-import styled from 'styled-components';
-import useDimensions from '../utility/useDimensions';
-import { useForm } from '../utility/FormProvider';
-import useTheme from '../theme/useTheme';
-import moment from 'moment';
-
-const ChartWrapper = styled.div`
- flex: 1;
- overflow: hidden;
-`;
-
-function getTimeAxis(labels) {
- const res = [];
- for (const label of labels) {
- const parsed = moment(label);
- if (!parsed.isValid()) return null;
- const iso = parsed.toISOString();
- if (iso < '1850-01-01T00:00:00' || iso > '2150-01-01T00:00:00') return null;
- res.push(parsed);
- }
- return res;
-}
-
-function getLabels(labelValues, timeAxis, chartType) {
- if (!timeAxis) return labelValues;
- if (chartType === 'line') return timeAxis.map(x => x.toDate());
- return timeAxis.map(x => x.format('D. M. YYYY'));
-}
-
-function getOptions(timeAxis, chartType) {
- if (timeAxis && chartType === 'line') {
- return {
- scales: {
- xAxes: [
- {
- type: 'time',
- distribution: 'linear',
-
- time: {
- tooltipFormat: 'D. M. YYYY HH:mm',
- displayFormats: {
- millisecond: 'HH:mm:ss.SSS',
- second: 'HH:mm:ss',
- minute: 'HH:mm',
- hour: 'D.M hA',
- day: 'D. M.',
- week: 'D. M. YYYY',
- month: 'MM-YYYY',
- quarter: '[Q]Q - YYYY',
- year: 'YYYY',
- },
- },
- },
- ],
- },
- };
- }
- return {};
-}
-
-function createChartData(freeData, labelColumn, dataColumns, colorSeed, chartType, dataColumnColors, theme) {
- if (!freeData || !labelColumn || !dataColumns || !freeData.rows || dataColumns.length == 0) return [{}, {}];
- const colors = randomcolor({
- count: _.max([freeData.rows.length, dataColumns.length, 1]),
- seed: colorSeed,
- });
- let backgroundColor = null;
- let borderColor = null;
- const labelValues = freeData.rows.map(x => x[labelColumn]);
- const timeAxis = getTimeAxis(labelValues);
- const labels = getLabels(labelValues, timeAxis, chartType);
- const res = {
- labels,
- datasets: dataColumns.map((dataColumn, columnIndex) => {
- if (chartType == 'line' || chartType == 'bar') {
- const color = dataColumnColors[dataColumn];
- if (color) {
- backgroundColor = theme.main_palettes[color][4] + '80';
- borderColor = theme.main_palettes[color][7];
- } else {
- backgroundColor = colors[columnIndex] + '80';
- borderColor = colors[columnIndex];
- }
- } else {
- backgroundColor = colors;
- }
-
- return {
- label: dataColumn,
- data: freeData.rows.map(row => row[dataColumn]),
- backgroundColor,
- borderColor,
- borderWidth: 1,
- };
- }),
- };
-
- const options = getOptions(timeAxis, chartType);
- return [res, options];
-}
-
-export function extractDataColumns(values) {
- const dataColumns = [];
- for (const key in values) {
- if (key.startsWith('dataColumn_') && values[key]) {
- dataColumns.push(key.substring('dataColumn_'.length));
- }
- }
- return dataColumns;
-}
-export function extractDataColumnColors(values, dataColumns) {
- const res = {};
- for (const column of dataColumns) {
- const color = values[`dataColumnColor_${column}`];
- if (color) res[column] = color;
- }
- return res;
-}
-
-export default function DataChart({ data }) {
- const [containerRef, { height: containerHeight, width: containerWidth }] = useDimensions();
- const { values } = useForm();
- const theme = useTheme();
-
- const { labelColumn } = values;
- const dataColumns = extractDataColumns(values);
- const dataColumnColors = extractDataColumnColors(values, dataColumns);
- const [chartData, options] = createChartData(
- data,
- labelColumn,
- dataColumns,
- values.colorSeed || '5',
- values.chartType,
- dataColumnColors,
- theme
- );
-
- return (
-
-
-
- );
-}
diff --git a/packages/web/src/charts/chartDataLoader.ts b/packages/web/src/charts/chartDataLoader.ts
deleted file mode 100644
index 7ee23cadd..000000000
--- a/packages/web/src/charts/chartDataLoader.ts
+++ /dev/null
@@ -1,105 +0,0 @@
-import { dumpSqlSelect, Select } from 'dbgate-sqltree';
-import { EngineDriver } from 'dbgate-types';
-import axios from '../utility/axios';
-import _ from 'lodash';
-import { extractDataColumns } from './DataChart';
-
-export async function loadChartStructure(driver: EngineDriver, conid, database, sql) {
- const select: Select = {
- commandType: 'select',
- selectAll: true,
- topRecords: 1,
- from: {
- subQueryString: sql,
- alias: 'subq',
- },
- };
-
- const dmp = driver.createDumper();
- dumpSqlSelect(dmp, select);
- const resp = await axios.post('database-connections/query-data', { conid, database, sql: dmp.s });
- if (resp.data.errorMessage) throw new Error(resp.data.errorMessage);
- return resp.data.columns.map(x => x.columnName);
-}
-
-export async function loadChartData(driver: EngineDriver, conid, database, sql, config) {
- const dataColumns = extractDataColumns(config);
- const { labelColumn, truncateFrom, truncateLimit, showRelativeValues } = config;
- if (!labelColumn || !dataColumns || dataColumns.length == 0) return null;
-
- const select: Select = {
- commandType: 'select',
-
- columns: [
- {
- exprType: 'column',
- source: { alias: 'subq' },
- columnName: labelColumn,
- alias: labelColumn,
- },
- // @ts-ignore
- ...dataColumns.map(columnName => ({
- exprType: 'call',
- func: 'SUM',
- args: [
- {
- exprType: 'column',
- columnName,
- source: { alias: 'subq' },
- },
- ],
- alias: columnName,
- })),
- ],
- topRecords: truncateLimit || 100,
- from: {
- subQueryString: sql,
- alias: 'subq',
- },
- groupBy: [
- {
- exprType: 'column',
- source: { alias: 'subq' },
- columnName: labelColumn,
- },
- ],
- orderBy: [
- {
- exprType: 'column',
- source: { alias: 'subq' },
- columnName: labelColumn,
- direction: truncateFrom == 'end' ? 'DESC' : 'ASC',
- },
- ],
- };
-
- const dmp = driver.createDumper();
- dumpSqlSelect(dmp, select);
- const resp = await axios.post('database-connections/query-data', { conid, database, sql: dmp.s });
- let { rows, columns } = resp.data;
- if (truncateFrom == 'end' && rows) {
- rows = _.reverse([...rows]);
- }
- if (showRelativeValues) {
- const maxValues = dataColumns.map(col => _.max(rows.map(row => row[col])));
- for (const [col, max] of _.zip(dataColumns, maxValues)) {
- if (!max) continue;
- if (!_.isNumber(max)) continue;
- if (!(max > 0)) continue;
- rows = rows.map(row => ({
- ...row,
- [col]: (row[col] / max) * 100,
- }));
- // columns = columns.map((x) => {
- // if (x.columnName == col) {
- // return { columnName: `${col} %` };
- // }
- // return x;
- // });
- }
- }
- return {
- columns,
- rows,
- };
-}
diff --git a/packages/web/src/datagrid/ChangeSetGrider.ts b/packages/web/src/datagrid/ChangeSetGrider.ts
deleted file mode 100644
index 6aac275b6..000000000
--- a/packages/web/src/datagrid/ChangeSetGrider.ts
+++ /dev/null
@@ -1,164 +0,0 @@
-import {
- ChangeSet,
- changeSetContainsChanges,
- changeSetInsertNewRow,
- createChangeSet,
- deleteChangeSetRows,
- findExistingChangeSetItem,
- getChangeSetInsertedRows,
- GridDisplay,
- revertChangeSetRowChanges,
- setChangeSetValue,
-} from 'dbgate-datalib';
-import Grider, { GriderRowStatus } from './Grider';
-
-export default class ChangeSetGrider extends Grider {
- public insertedRows: any[];
- public changeSet: ChangeSet;
- public setChangeSet: Function;
- private rowCacheIndexes: Set;
- private rowDataCache;
- private rowStatusCache;
- private rowDefinitionsCache;
- private batchChangeSet: ChangeSet;
-
- constructor(public sourceRows: any[], public changeSetState, public dispatchChangeSet, public display: GridDisplay) {
- super();
- this.changeSet = changeSetState && changeSetState.value;
- this.insertedRows = getChangeSetInsertedRows(this.changeSet, display.baseTable);
- this.setChangeSet = value => dispatchChangeSet({ type: 'set', value });
- this.rowCacheIndexes = new Set();
- this.rowDataCache = {};
- this.rowStatusCache = {};
- this.rowDefinitionsCache = {};
- this.batchChangeSet = null;
- }
-
- getRowSource(index: number) {
- if (index < this.sourceRows.length) return this.sourceRows[index];
- return null;
- }
-
- getInsertedRowIndex(index) {
- return index >= this.sourceRows.length ? index - this.sourceRows.length : null;
- }
-
- requireRowCache(index: number) {
- if (this.rowCacheIndexes.has(index)) return;
- const row = this.getRowSource(index);
- const insertedRowIndex = this.getInsertedRowIndex(index);
- const rowDefinition = this.display.getChangeSetRow(row, insertedRowIndex);
- const [matchedField, matchedChangeSetItem] = findExistingChangeSetItem(this.changeSet, rowDefinition);
- const rowUpdated = matchedChangeSetItem ? { ...row, ...matchedChangeSetItem.fields } : row;
- let status = 'regular';
- if (matchedChangeSetItem && matchedField == 'updates') status = 'updated';
- if (matchedField == 'deletes') status = 'deleted';
- if (insertedRowIndex != null) status = 'inserted';
- const rowStatus = {
- status,
- modifiedFields:
- matchedChangeSetItem && matchedChangeSetItem.fields ? new Set(Object.keys(matchedChangeSetItem.fields)) : null,
- };
- this.rowDataCache[index] = rowUpdated;
- this.rowStatusCache[index] = rowStatus;
- this.rowDefinitionsCache[index] = rowDefinition;
- this.rowCacheIndexes.add(index);
- }
-
- get editable() {
- return this.display.editable;
- }
-
- get canInsert() {
- return !!this.display.baseTable;
- }
-
- getRowData(index: number) {
- this.requireRowCache(index);
- return this.rowDataCache[index];
- }
-
- getRowStatus(index): GriderRowStatus {
- this.requireRowCache(index);
- return this.rowStatusCache[index];
- }
-
- get rowCount() {
- return this.sourceRows.length + this.insertedRows.length;
- }
-
- applyModification(changeSetReducer) {
- if (this.batchChangeSet) {
- this.batchChangeSet = changeSetReducer(this.batchChangeSet);
- } else {
- this.setChangeSet(changeSetReducer(this.changeSet));
- }
- }
-
- setCellValue(index: number, uniqueName: string, value: any) {
- const row = this.getRowSource(index);
- const definition = this.display.getChangeSetField(row, uniqueName, this.getInsertedRowIndex(index));
- this.applyModification(chs => setChangeSetValue(chs, definition, value));
- }
-
- deleteRow(index: number) {
- this.requireRowCache(index);
- this.applyModification(chs => deleteChangeSetRows(chs, this.rowDefinitionsCache[index]));
- }
-
- get rowCountInUpdate() {
- if (this.batchChangeSet) {
- const newRows = getChangeSetInsertedRows(this.batchChangeSet, this.display.baseTable);
- return this.sourceRows.length + newRows.length;
- } else {
- return this.rowCount;
- }
- }
-
- insertRow(): number {
- const res = this.rowCountInUpdate;
- this.applyModification(chs => changeSetInsertNewRow(chs, this.display.baseTable));
- return res;
- }
-
- beginUpdate() {
- this.batchChangeSet = this.changeSet;
- }
- endUpdate() {
- this.setChangeSet(this.batchChangeSet);
- this.batchChangeSet = null;
- }
-
- revertRowChanges(index: number) {
- this.requireRowCache(index);
- this.applyModification(chs => revertChangeSetRowChanges(chs, this.rowDefinitionsCache[index]));
- }
- revertAllChanges() {
- this.applyModification(chs => createChangeSet());
- }
- undo() {
- this.dispatchChangeSet({ type: 'undo' });
- }
- redo() {
- this.dispatchChangeSet({ type: 'redo' });
- }
- get canUndo() {
- return this.changeSetState.canUndo;
- }
- get canRedo() {
- return this.changeSetState.canRedo;
- }
- get containsChanges() {
- return changeSetContainsChanges(this.changeSet);
- }
- get disableLoadNextPage() {
- return this.insertedRows.length > 0;
- }
-
- static factory({ sourceRows, changeSetState, dispatchChangeSet, display }): ChangeSetGrider {
- return new ChangeSetGrider(sourceRows, changeSetState, dispatchChangeSet, display);
- }
- static factoryDeps({ sourceRows, changeSetState, dispatchChangeSet, display }) {
- return [sourceRows, changeSetState ? changeSetState.value : null, dispatchChangeSet, display];
- }
-}
diff --git a/packages/web/src/datagrid/ColumnHeaderControl.js b/packages/web/src/datagrid/ColumnHeaderControl.js
deleted file mode 100644
index f0f121409..000000000
--- a/packages/web/src/datagrid/ColumnHeaderControl.js
+++ /dev/null
@@ -1,134 +0,0 @@
-import React from 'react';
-import styled from 'styled-components';
-import ColumnLabel from './ColumnLabel';
-import DropDownButton from '../widgets/DropDownButton';
-import { DropDownMenuItem, DropDownMenuDivider } from '../modals/DropDownMenu';
-import { useSplitterDrag } from '../widgets/Splitter';
-import { isTypeDateTime } from 'dbgate-tools';
-import { openDatabaseObjectDetail } from '../appobj/DatabaseObjectAppObject';
-import { useSetOpenedTabs } from '../utility/globalState';
-import { FontIcon } from '../icons';
-import useTheme from '../theme/useTheme';
-import useOpenNewTab from '../utility/useOpenNewTab';
-
-const HeaderDiv = styled.div`
- display: flex;
- flex-wrap: nowrap;
-`;
-
-const LabelDiv = styled.div`
- flex: 1;
- min-width: 10px;
- // padding-left: 2px;
- padding: 2px;
- margin: auto;
- white-space: nowrap;
-`;
-
-const IconWrapper = styled.span`
- margin-left: 3px;
-`;
-
-const ResizeHandle = styled.div`
- background-color: ${props => props.theme.border};
- width: 2px;
- cursor: col-resize;
- z-index: 1;
-`;
-
-const GroupingLabel = styled.span`
- color: green;
- white-space: nowrap;
-`;
-
-export default function ColumnHeaderControl({
- column,
- setSort,
- onResize,
- order,
- setGrouping,
- grouping,
- conid,
- database,
-}) {
- const onResizeDown = useSplitterDrag('clientX', onResize);
- const { foreignKey } = column;
- const openNewTab = useOpenNewTab();
- const theme = useTheme();
-
- const openReferencedTable = () => {
- openDatabaseObjectDetail(openNewTab, 'TableDataTab', null, {
- schemaName: foreignKey.refSchemaName,
- pureName: foreignKey.refTableName,
- conid,
- database,
- objectTypeField: 'tables',
- });
- // openNewTab(setOpenedTabs, {
- // title: foreignKey.refTableName,
- // tooltip,
- // icon: sqlTemplate ? 'sql.svg' : icons[objectTypeField],
- // tabComponent: sqlTemplate ? 'QueryTab' : tabComponent,
- // props: {
- // schemaName,
- // pureName,
- // conid,
- // database,
- // objectTypeField,
- // initialArgs: sqlTemplate ? { sqlTemplate } : null,
- // },
- // });
- };
- return (
-
-
- {grouping && (
- {grouping == 'COUNT DISTINCT' ? 'distinct' : grouping.toLowerCase()}:
- )}
-
-
- {order == 'ASC' && (
-
-
-
- )}
- {order == 'DESC' && (
-
-
-
- )}
-
- {setSort && (
-
- setSort('ASC')}>Sort ascending
- setSort('DESC')}>Sort descending
-
- {foreignKey && (
-
- Open table {foreignKey.refTableName}
-
- )}
- {foreignKey && }
- setGrouping('GROUP')}>Group by
- setGrouping('MAX')}>MAX
- setGrouping('MIN')}>MIN
- setGrouping('SUM')}>SUM
- setGrouping('AVG')}>AVG
- setGrouping('COUNT')}>COUNT
- setGrouping('COUNT DISTINCT')}>COUNT DISTINCT
- {isTypeDateTime(column.dataType) && (
- <>
-
- setGrouping('GROUP:YEAR')}>Group by YEAR
- setGrouping('GROUP:MONTH')}>Group by MONTH
- setGrouping('GROUP:DAY')}>Group by DAY
- {/* setGrouping('GROUP:HOUR')}>Group by HOUR
- setGrouping('GROUP:MINUTE')}>Group by MINUTE */}
- >
- )}
-
- )}
-
-
- );
-}
diff --git a/packages/web/src/datagrid/ColumnLabel.js b/packages/web/src/datagrid/ColumnLabel.js
deleted file mode 100644
index 89c6eb953..000000000
--- a/packages/web/src/datagrid/ColumnLabel.js
+++ /dev/null
@@ -1,35 +0,0 @@
-//@ts-nocheck
-
-import React from 'react';
-import styled from 'styled-components';
-import { FontIcon } from '../icons';
-import useTheme from '../theme/useTheme';
-
-const Label = styled.span`
- font-weight: ${props => (props.notNull ? 'bold' : 'normal')};
- white-space: nowrap;
-`;
-const ExtInfoWrap = styled.span`
- font-weight: normal;
- margin-left: 5px;
- color: ${props => props.theme.left_font3};
-`;
-
-export function getColumnIcon(column, forceIcon = false) {
- if (column.autoIncrement) return 'img autoincrement';
- if (column.foreignKey) return 'img foreign-key';
- if (forceIcon) return 'img column';
- return null;
-}
-
-/** @param column {import('dbgate-datalib').DisplayColumn|import('dbgate-types').ColumnInfo} */
-export default function ColumnLabel(column) {
- const icon = getColumnIcon(column, column.forceIcon);
- const theme = useTheme();
- return (
-
- {icon ? : null} {column.headerText || column.columnName}
- {column.extInfo ? {column.extInfo} : null}
-
- );
-}
diff --git a/packages/web/src/datagrid/ColumnManager.js b/packages/web/src/datagrid/ColumnManager.js
deleted file mode 100644
index 1ae61b112..000000000
--- a/packages/web/src/datagrid/ColumnManager.js
+++ /dev/null
@@ -1,94 +0,0 @@
-import React from 'react';
-import styled from 'styled-components';
-import ColumnLabel from './ColumnLabel';
-import { filterName } from 'dbgate-datalib';
-import { ExpandIcon } from '../icons';
-import InlineButton from '../widgets/InlineButton';
-import { ManagerInnerContainer } from './ManagerStyles';
-import SearchInput from '../widgets/SearchInput';
-import useTheme from '../theme/useTheme';
-
-const Wrapper = styled.div``;
-
-const Row = styled.div`
- margin-left: 5px;
- margin-right: 5px;
- cursor: pointer;
- white-space: nowrap;
- &:hover {
- background-color: ${props => props.theme.manager_background_blue[1]};
- }
-`;
-
-const SearchBoxWrapper = styled.div`
- display: flex;
- margin-bottom: 5px;
-`;
-
-const Button = styled.button`
- // -webkit-appearance: none;
- // -moz-appearance: none;
- // appearance: none;
- // width: 50px;
-`;
-
-/**
- * @param {object} props
- * @param {import('dbgate-datalib').GridDisplay} props.display
- * @param {import('dbgate-datalib').DisplayColumn} props.column
- */
-function ColumnManagerRow(props) {
- const { display, column } = props;
- const [isHover, setIsHover] = React.useState(false);
- const theme = useTheme();
- return (
- setIsHover(true)}
- onMouseLeave={() => setIsHover(false)}
- theme={theme}
- onClick={e => {
- // @ts-ignore
- if (e.target.closest('.expandColumnIcon')) return;
- display.focusColumn(column.uniqueName);
- }}
- >
- display.toggleExpandedColumn(column.uniqueName)}
- />
- display.setColumnVisibility(column.uniquePath, !column.isChecked)}
- >
-
-
- );
-}
-
-/** @param props {import('./types').DataGridProps} */
-export default function ColumnManager(props) {
- const { display } = props;
- const [columnFilter, setColumnFilter] = React.useState('');
-
- return (
- <>
-
-
- display.hideAllColumns()}>Hide
- display.showAllColumns()}>Show
-
-
- {display
- .getColumns(columnFilter)
- .filter(column => filterName(columnFilter, column.columnName))
- .map(column => (
-
- ))}
-
- >
- );
-}
diff --git a/packages/web/src/datagrid/DataFilterControl.js b/packages/web/src/datagrid/DataFilterControl.js
deleted file mode 100644
index 8a09d4191..000000000
--- a/packages/web/src/datagrid/DataFilterControl.js
+++ /dev/null
@@ -1,501 +0,0 @@
-// @ts-nocheck
-import React from 'react';
-import { DropDownMenuItem, DropDownMenuDivider } from '../modals/DropDownMenu';
-import styled from 'styled-components';
-import keycodes from '../utility/keycodes';
-import { parseFilter, createMultiLineFilter } from 'dbgate-filterparser';
-import InlineButton from '../widgets/InlineButton';
-import useShowModal from '../modals/showModal';
-import FilterMultipleValuesModal from '../modals/FilterMultipleValuesModal';
-import SetFilterModal from '../modals/SetFilterModal';
-import { FontIcon } from '../icons';
-import useTheme from '../theme/useTheme';
-import { useShowMenu } from '../modals/showMenu';
-// import { $ } from '../../Utility/jquery';
-// import autobind from 'autobind-decorator';
-// import * as React from 'react';
-
-// import { createMultiLineFilter } from '../../DataLib/FilterTools';
-// import { ModalDialog } from '../Dialogs';
-// import { FilterDialog } from '../Dialogs/FilterDialog';
-// import { FilterMultipleValuesDialog } from '../Dialogs/FilterMultipleValuesDialog';
-// import { IconSpan } from '../Navigation/NavUtils';
-// import { KeyCodes } from '../ReactDataGrid/KeyCodes';
-// import { DropDownMenu, DropDownMenuDivider, DropDownMenuItem, DropDownSubmenuItem } from './DropDownMenu';
-// import { FilterParserType } from '../../SwaggerClients';
-// import { IFilterHolder } from '../CommonControls';
-// import { GrayFilterIcon } from '../Icons';
-
-// export interface IDataFilterControlProps {
-// filterType: FilterParserType;
-// getFilter: Function;
-// setFilter: Function;
-// width: number;
-// onControlKey?: Function;
-// isReadOnly?: boolean;
-// inputElementId?: string;
-// }
-
-const FilterDiv = styled.div`
- display: flex;
-`;
-const FilterInput = styled.input`
- flex: 1;
- min-width: 10px;
- background-color: ${props =>
- props.state == 'ok'
- ? props.theme.input_background_green[1]
- : props.state == 'error'
- ? props.theme.input_background_red[1]
- : props.theme.input_background};
-`;
-// const FilterButton = styled.button`
-// color: gray;
-// `;
-
-function DropDownContent({ filterType, setFilter, filterMultipleValues, openFilterWindow }) {
- switch (filterType) {
- case 'number':
- return (
- <>
- setFilter('')}>Clear Filter
- filterMultipleValues()}>Filter multiple values
- openFilterWindow('=')}>Equals...
- openFilterWindow('<>')}>Does Not Equal...
- setFilter('NULL')}>Is Null
- setFilter('NOT NULL')}>Is Not Null
- openFilterWindow('>')}>Greater Than...
- openFilterWindow('>=')}>Greater Than Or Equal To...
- openFilterWindow('<')}>Less Than...
- openFilterWindow('<=')}>Less Than Or Equal To...
- >
- );
- case 'logical':
- return (
- <>
- setFilter('')}>Clear Filter
- filterMultipleValues()}>Filter multiple values
- setFilter('NULL')}>Is Null
- setFilter('NOT NULL')}>Is Not Null
- setFilter('TRUE')}>Is True
- setFilter('FALSE')}>Is False
- setFilter('TRUE, NULL')}>Is True or NULL
- setFilter('FALSE, NULL')}>Is False or NULL
- >
- );
- case 'datetime':
- return (
- <>
- setFilter('')}>Clear Filter
- filterMultipleValues()}>Filter multiple values
- setFilter('NULL')}>Is Null
- setFilter('NOT NULL')}>Is Not Null
-
-
-
- openFilterWindow('<=')}>Before...
- openFilterWindow('>=')}>After...
- openFilterWindow('>=;<=')}>Between...
-
-
-
- setFilter('TOMORROW')}>Tomorrow
- setFilter('TODAY')}>Today
- setFilter('YESTERDAY')}>Yesterday
-
-
-
- setFilter('NEXT WEEK')}>Next Week
- setFilter('THIS WEEK')}>This Week
- setFilter('LAST WEEK')}>Last Week
-
-
-
- setFilter('NEXT MONTH')}>Next Month
- setFilter('THIS MONTH')}>This Month
- setFilter('LAST MONTH')}>Last Month
-
-
-
- setFilter('NEXT YEAR')}>Next Year
- setFilter('THIS YEAR')}>This Year
- setFilter('LAST YEAR')}>Last Year
-
-
-
- {/*
- setFilter('JAN')}>January
- setFilter('FEB')}>February
- setFilter('MAR')}>March
- setFilter('APR')}>April
- setFilter('JUN')}>June
- setFilter('JUL')}>July
- setFilter('AUG')}>August
- setFilter('SEP')}>September
- setFilter('OCT')}>October
- setFilter('NOV')}>November
- setFilter('DEC')}>December
-
-
-
- setFilter('MON')}>Monday
- setFilter('TUE')}>Tuesday
- setFilter('WED')}>Wednesday
- setFilter('THU')}>Thursday
- setFilter('FRI')}>Friday
- setFilter('SAT')}>Saturday
- setFilter('SUN')}>Sunday
- */}
- >
- );
- case 'string':
- return (
- <>
- setFilter('')}>Clear Filter
- filterMultipleValues()}>Filter multiple values
-
- openFilterWindow('=')}>Equals...
- openFilterWindow('<>')}>Does Not Equal...
- setFilter('NULL')}>Is Null
- setFilter('NOT NULL')}>Is Not Null
- setFilter('EMPTY, NULL')}>Is Empty Or Null
- setFilter('NOT EMPTY NOT NULL')}>Has Not Empty Value
-
-
-
- openFilterWindow('+')}>Contains...
- openFilterWindow('~')}>Does Not Contain...
- openFilterWindow('^')}>Begins With...
- openFilterWindow('!^')}>Does Not Begin With...
- openFilterWindow('$')}>Ends With...
- openFilterWindow('!$')}>Does Not End With...
- >
- );
- }
-}
-
-export default function DataFilterControl({
- isReadOnly = false,
- filterType,
- filter,
- setFilter,
- focusIndex = 0,
- onFocusGrid = undefined,
-}) {
- const showModal = useShowModal();
- const showMenu = useShowMenu();
- const theme = useTheme();
- const [filterState, setFilterState] = React.useState('empty');
- const setFilterText = filter => {
- setFilter(filter);
- editorRef.current.value = filter || '';
- updateFilterState();
- };
- const applyFilter = () => {
- if ((filter || '') == (editorRef.current.value || '')) return;
- setFilter(editorRef.current.value);
- };
- const filterMultipleValues = () => {
- showModal(modalState => (
- setFilterText(createMultiLineFilter(mode, text))}
- />
- ));
- };
- const openFilterWindow = operator => {
- showModal(modalState => (
- setFilterText(text)}
- condition1={operator}
- />
- ));
- };
- const buttonRef = React.useRef();
- const editorRef = React.useRef();
-
- React.useEffect(() => {
- if (focusIndex) editorRef.current.focus();
- }, [focusIndex]);
-
- const handleKeyDown = ev => {
- if (isReadOnly) return;
- if (ev.keyCode == keycodes.enter) {
- applyFilter();
- }
- if (ev.keyCode == keycodes.escape) {
- setFilterText('');
- }
- if (ev.keyCode == keycodes.downArrow) {
- if (onFocusGrid) onFocusGrid();
- // ev.stopPropagation();
- ev.preventDefault();
- }
- // if (ev.keyCode == KeyCodes.DownArrow || ev.keyCode == KeyCodes.UpArrow) {
- // if (this.props.onControlKey) this.props.onControlKey(ev.keyCode);
- // }
- };
-
- const updateFilterState = () => {
- const value = editorRef.current.value;
- try {
- if (value) {
- parseFilter(value, filterType);
- setFilterState('ok');
- } else {
- setFilterState('empty');
- }
- } catch (err) {
- // console.log('PARSE ERROR', err);
- setFilterState('error');
- }
- };
-
- React.useEffect(() => {
- editorRef.current.value = filter || '';
- updateFilterState();
- }, [filter]);
-
- const handleShowMenu = () => {
- const rect = buttonRef.current.getBoundingClientRect();
- showMenu(
- rect.left,
- rect.bottom,
-
- );
- };
-
- function handlePaste(event) {
- var pastedText = undefined;
- // @ts-ignore
- if (window.clipboardData && window.clipboardData.getData) {
- // IE
- // @ts-ignore
- pastedText = window.clipboardData.getData('Text');
- } else if (event.clipboardData && event.clipboardData.getData) {
- pastedText = event.clipboardData.getData('text/plain');
- }
- if (pastedText && pastedText.includes('\n')) {
- event.preventDefault();
- setFilterText(createMultiLineFilter('is', pastedText));
- }
- }
-
- return (
-
-
-
-
-
-
- );
-}
-// domEditor: Element;
-
-// @autobind
-// applyFilter() {
-// this.props.setFilter($(this.domEditor).val());
-// }
-
-// @autobind
-// clearFilter() {
-// $(this.domEditor).val('');
-// this.applyFilter();
-// }
-
-// setFilter(value: string) {
-// $(this.domEditor).val(value);
-// this.applyFilter();
-// return false;
-// }
-
-// render() {
-// let dropDownContent = null;
-
-// let filterIconSpan = ;
-// //filterIconSpan = null;
-
-// if (this.props.filterType == 'Number') {
-// dropDownContent =
-// this.setFilter('')}>Clear Filter
-// this.filterMultipleValues()}>Filter multiple values
-// this.openFilterWindow('=')}>Equals...
-// this.openFilterWindow('<>')}>Does Not Equal...
-// this.setFilter('NULL')}>Is Null
-// this.setFilter('NOT NULL')}>Is Not Null
-// this.openFilterWindow('>')}>Greater Than...
-// this.openFilterWindow('>=')}>Greater Than Or Equal To...
-// this.openFilterWindow('<')}>Less Than...
-// this.openFilterWindow('<=')}>Less Than Or Equal To...
-// ;
-// }
-
-// if (this.props.filterType == 'Logical') {
-// dropDownContent =
-// this.setFilter('')}>Clear Filter
-// this.filterMultipleValues()}>Filter multiple values
-// this.setFilter('NULL')}>Is Null
-// this.setFilter('NOT NULL')}>Is Not Null
-// this.setFilter('TRUE')}>Is True
-// this.setFilter('FALSE')}>Is False
-// this.setFilter('TRUE, NULL')}>Is True or NULL
-// this.setFilter('FALSE, NULL')}>Is False or NULL
-// ;
-// }
-
-// if (this.props.filterType == 'DateTime') {
-// dropDownContent =
-// this.setFilter('')}>Clear Filter
-// this.filterMultipleValues()}>Filter multiple values
-// this.setFilter('NULL')}>Is Null
-// this.setFilter('NOT NULL')}>Is Not Null
-
-//
-
-// this.openFilterWindow('<=')}>Before...
-// this.openFilterWindow('>=')}>After...
-// this.openFilterWindow('>=;<=')}>Between...
-
-//
-
-// this.setFilter('TOMORROW')}>Tomorrow
-// this.setFilter('TODAY')}>Today
-// this.setFilter('YESTERDAY')}>Yesterday
-
-//
-
-// this.setFilter('NEXT WEEK')}>Next Week
-// this.setFilter('THIS WEEK')}>This Week
-// this.setFilter('LAST WEEK')}>Last Week
-
-//
-
-// this.setFilter('NEXT MONTH')}>Next Month
-// this.setFilter('THIS MONTH')}>This Month
-// this.setFilter('LAST MONTH')}>Last Month
-
-//
-
-// this.setFilter('NEXT YEAR')}>Next Year
-// this.setFilter('THIS YEAR')}>This Year
-// this.setFilter('LAST YEAR')}>Last Year
-
-//
-
-//
-
-// this.setFilter('JAN')}>January
-// this.setFilter('FEB')}>February
-// this.setFilter('MAR')}>March
-// this.setFilter('APR')}>April
-// this.setFilter('JUN')}>June
-// this.setFilter('JUL')}>July
-// this.setFilter('AUG')}>August
-// this.setFilter('SEP')}>September
-// this.setFilter('OCT')}>October
-// this.setFilter('NOV')}>November
-// this.setFilter('DEC')}>December
-
-//
-
-// this.setFilter('MON')}>Monday
-// this.setFilter('TUE')}>Tuesday
-// this.setFilter('WED')}>Wednesday
-// this.setFilter('THU')}>Thursday
-// this.setFilter('FRI')}>Friday
-// this.setFilter('SAT')}>Saturday
-// this.setFilter('SUN')}>Sunday
-
-//
-// ;
-// }
-
-// if (this.props.filterType == 'String') {
-// dropDownContent =
-// this.setFilter('')}>Clear Filter
-// this.filterMultipleValues()}>Filter multiple values
-
-// this.openFilterWindow('=')}>Equals...
-// this.openFilterWindow('<>')}>Does Not Equal...
-// this.setFilter('NULL')}>Is Null
-// this.setFilter('NOT NULL')}>Is Not Null
-// this.setFilter('EMPTY, NULL')}>Is Empty Or Null
-// this.setFilter('NOT EMPTY NOT NULL')}>Has Not Empty Value
-
-//
-
-// this.openFilterWindow('+')}>Contains...
-// this.openFilterWindow('~')}>Does Not Contain...
-// this.openFilterWindow('^')}>Begins With...
-// this.openFilterWindow('!^')}>Does Not Begin With...
-// this.openFilterWindow('$')}>Ends With...
-// this.openFilterWindow('!$')}>Does Not End With...
-// ;
-// }
-
-// if (this.props.isReadOnly) {
-// dropDownContent = ;
-// }
-
-// return
-// this.setDomEditor(x)} onKeyDown={this.editorKeyDown} placeholder='Search' >
-
-// {dropDownContent}
-//
;
-// }
-
-// async filterMultipleValues() {
-// let result = await ModalDialog.run( );
-// if (!result) return;
-// let { mode, text } = result;
-// let filter = createMultiLineFilter(mode, text);
-// this.setFilter(filter);
-// }
-
-// openFilterWindow(selectedOperator: string) {
-// FilterDialog.runFilter(this, this.props.filterType, selectedOperator);
-// return false;
-// }
-
-// setDomEditor(editor) {
-// this.domEditor = editor;
-// $(editor).val(this.props.getFilter());
-// }
-
-// @autobind
-// editorKeyDown(ev) {
-// if (this.props.isReadOnly) return;
-// if (ev.keyCode == KeyCodes.Enter) {
-// this.applyFilter();
-// }
-// if (ev.keyCode == KeyCodes.Escape) {
-// this.clearFilter();
-// }
-// if (ev.keyCode == KeyCodes.DownArrow || ev.keyCode == KeyCodes.UpArrow) {
-// if (this.props.onControlKey) this.props.onControlKey(ev.keyCode);
-// }
-// }
-
-// focus() {
-// $(this.domEditor).focus();
-// }
-// }
diff --git a/packages/web/src/datagrid/DataGrid.js b/packages/web/src/datagrid/DataGrid.js
deleted file mode 100644
index d8cca115a..000000000
--- a/packages/web/src/datagrid/DataGrid.js
+++ /dev/null
@@ -1,83 +0,0 @@
-import React from 'react';
-import styled from 'styled-components';
-import ColumnManager from './ColumnManager';
-import FormViewFilters from '../formview/FormViewFilters';
-
-import ReferenceManager from './ReferenceManager';
-import { HorizontalSplitter } from '../widgets/Splitter';
-import WidgetColumnBar, { WidgetColumnBarItem } from '../widgets/WidgetColumnBar';
-import CellDataView from '../celldata/CellDataView';
-import useTheme from '../theme/useTheme';
-
-const LeftContainer = styled.div`
- background-color: ${props => props.theme.manager_background};
- display: flex;
- flex: 1;
-`;
-
-const DataGridContainer = styled.div`
- position: relative;
- flex-grow: 1;
-`;
-
-export default function DataGrid(props) {
- const { GridCore, FormView, formDisplay } = props;
- const theme = useTheme();
- const [managerSize, setManagerSize] = React.useState(0);
- const [selection, setSelection] = React.useState([]);
- const [formSelection, setFormSelection] = React.useState(null);
- const [grider, setGrider] = React.useState(null);
- const [collapsedWidgets, setCollapsedWidgets] = React.useState([]);
- // const [formViewData, setFormViewData] = React.useState(null);
- const isFormView = !!(formDisplay && formDisplay.config && formDisplay.config.isFormView);
-
- return (
-
-
-
- {!isFormView && (
-
-
-
- )}
- {isFormView && (
-
-
-
- )}
- {props.showReferences && props.display.hasReferences && (
-
-
-
- )}
-
- {isFormView ? (
-
- ) : (
-
- )}
-
-
-
-
-
- {isFormView ? (
-
- ) : (
-
- )}
-
-
- );
-}
diff --git a/packages/web/src/datagrid/DataGridContextMenu.js b/packages/web/src/datagrid/DataGridContextMenu.js
deleted file mode 100644
index f95dbff32..000000000
--- a/packages/web/src/datagrid/DataGridContextMenu.js
+++ /dev/null
@@ -1,68 +0,0 @@
-import React from 'react';
-import { DropDownMenuItem, DropDownMenuDivider } from '../modals/DropDownMenu';
-
-export default function DataGridContextMenu({
- copy,
- revertRowChanges,
- deleteSelectedRows,
- insertNewRow,
- setNull,
- reload,
- exportGrid,
- filterSelectedValue,
- openQuery,
- openFreeTable,
- openChartSelection,
- openActiveChart,
- switchToForm,
-}) {
- return (
- <>
- {!!reload && (
-
- Reload
-
- )}
- {!!reload && }
-
- Copy
-
- {revertRowChanges && (
-
- Revert row changes
-
- )}
- {deleteSelectedRows && (
-
- Delete selected rows
-
- )}
- {insertNewRow && (
-
- Insert new row
-
- )}
-
- {setNull && (
-
- Set NULL
-
- )}
- {exportGrid && Export }
- {filterSelectedValue && (
-
- Filter selected value
-
- )}
- {openQuery && Open query }
- Open selection in free table editor
- Open chart from selection
- {openActiveChart && Open active chart }
- {!!switchToForm && (
-
- Form view
-
- )}
- >
- );
-}
diff --git a/packages/web/src/datagrid/DataGridCore.js b/packages/web/src/datagrid/DataGridCore.js
deleted file mode 100644
index 933089ce7..000000000
--- a/packages/web/src/datagrid/DataGridCore.js
+++ /dev/null
@@ -1,1124 +0,0 @@
-import _ from 'lodash';
-import React from 'react';
-import ReactDOM from 'react-dom';
-import styled from 'styled-components';
-import { HorizontalScrollBar, VerticalScrollBar } from './ScrollBars';
-import useDimensions from '../utility/useDimensions';
-import DataFilterControl from './DataFilterControl';
-import stableStringify from 'json-stable-stringify';
-import { getFilterType, getFilterValueExpression } from 'dbgate-filterparser';
-import { cellFromEvent, getCellRange, topLeftCell, isRegularCell, nullCell, emptyCellArray } from './selection';
-import keycodes from '../utility/keycodes';
-import DataGridRow from './DataGridRow';
-import {
- countColumnSizes,
- countVisibleRealColumns,
- filterCellForRow,
- filterCellsForRow,
- cellIsSelected,
-} from './gridutil';
-import { copyTextToClipboard } from '../utility/clipboard';
-import DataGridToolbar from './DataGridToolbar';
-// import usePropsCompare from '../utility/usePropsCompare';
-import ColumnHeaderControl from './ColumnHeaderControl';
-import InlineButton from '../widgets/InlineButton';
-import DataGridContextMenu from './DataGridContextMenu';
-import LoadingInfo from '../widgets/LoadingInfo';
-import ErrorInfo from '../widgets/ErrorInfo';
-import { useSetOpenedTabs } from '../utility/globalState';
-import { FontIcon } from '../icons';
-import useTheme from '../theme/useTheme';
-import { useShowMenu } from '../modals/showMenu';
-import useOpenNewTab from '../utility/useOpenNewTab';
-import axios from '../utility/axios';
-import openReferenceForm from '../formview/openReferenceForm';
-
-const GridContainer = styled.div`
- position: absolute;
- left: 0;
- top: 0;
- right: 0;
- bottom: 0;
- user-select: none;
-`;
-
-const Table = styled.table`
- position: absolute;
- left: 0;
- top: 0;
- bottom: 20px;
- // right: 20px;
- overflow: scroll;
- border-collapse: collapse;
- outline: none;
-`;
-const TableHead = styled.thead`
- // display: block;
- // width: 300px;
-`;
-const TableBody = styled.tbody`
- // display: block;
- // overflow: auto;
- // height: 100px;
-`;
-const TableHeaderRow = styled.tr`
- // height: 35px;
-`;
-const TableHeaderCell = styled.td`
- // font-weight: bold;
- border: 1px solid ${props => props.theme.border};
- // border-collapse: collapse;
- text-align: left;
- padding: 0;
- // padding: 2px;
- margin: 0;
- background-color: ${props => props.theme.gridheader_background};
- overflow: hidden;
-`;
-const TableFilterCell = styled.td`
- text-align: left;
- overflow: hidden;
- margin: 0;
- padding: 0;
-`;
-const wheelRowCount = 5;
-const FocusField = styled.input`
- // visibility: hidden
- position: absolute;
- left: -1000px;
- top: -1000px;
-`;
-
-const RowCountLabel = styled.div`
- position: absolute;
- background-color: ${props => props.theme.gridbody_background_yellow[1]};
- right: 40px;
- bottom: 20px;
-`;
-
-/** @param props {import('./types').DataGridProps} */
-export default function DataGridCore(props) {
- const {
- display,
- conid,
- database,
- tabVisible,
- loadNextData,
- errorMessage,
- isLoadedAll,
- loadedTime,
- exportGrid,
- openActiveChart,
- allRowCount,
- openQuery,
- onSave,
- isLoading,
- grider,
- onSelectionChanged,
- frameSelection,
- onKeyDown,
- formViewAvailable,
- } = props;
- // console.log('RENDER GRID', display.baseTable.pureName);
- const columns = React.useMemo(() => display.allColumns, [display]);
- const openNewTab = useOpenNewTab();
-
- // usePropsCompare(props);
-
- // console.log(`GRID, conid=${conid}, database=${database}, sql=${sql}`);
-
- const focusFieldRef = React.useRef(null);
-
- const [vScrollValueToSet, setvScrollValueToSet] = React.useState();
- const [vScrollValueToSetDate, setvScrollValueToSetDate] = React.useState(new Date());
-
- const [hScrollValueToSet, sethScrollValueToSet] = React.useState();
- const [hScrollValueToSetDate, sethScrollValueToSetDate] = React.useState(new Date());
-
- const [currentCell, setCurrentCell] = React.useState(topLeftCell);
- const [selectedCells, setSelectedCells] = React.useState([topLeftCell]);
- const [dragStartCell, setDragStartCell] = React.useState(nullCell);
- const [shiftDragStartCell, setShiftDragStartCell] = React.useState(nullCell);
- const [autofillDragStartCell, setAutofillDragStartCell] = React.useState(nullCell);
- const [autofillSelectedCells, setAutofillSelectedCells] = React.useState(emptyCellArray);
- const [focusFilterInputs, setFocusFilterInputs] = React.useState({});
- const showMenu = useShowMenu();
-
- const autofillMarkerCell = React.useMemo(
- () =>
- selectedCells && selectedCells.length > 0 && _.uniq(selectedCells.map(x => x[0])).length == 1
- ? [_.max(selectedCells.map(x => x[0])), _.max(selectedCells.map(x => x[1]))]
- : null,
- [selectedCells]
- );
-
- const [firstVisibleRowScrollIndex, setFirstVisibleRowScrollIndex] = React.useState(0);
- const [firstVisibleColumnScrollIndex, setFirstVisibleColumnScrollIndex] = React.useState(0);
-
- const [headerRowRef, { height: rowHeight }] = useDimensions();
- const [tableBodyRef] = useDimensions();
- const [containerRef, { height: containerHeight, width: containerWidth }] = useDimensions();
-
- const [inplaceEditorState, dispatchInsplaceEditor] = React.useReducer((state, action) => {
- switch (action.type) {
- case 'show':
- if (!grider.editable) return {};
- return {
- cell: action.cell,
- text: action.text,
- selectAll: action.selectAll,
- };
- case 'close': {
- const [row, col] = currentCell || [];
- if (focusFieldRef.current) focusFieldRef.current.focus();
- // @ts-ignore
- if (action.mode == 'enter' && row) setTimeout(() => moveCurrentCell(row + 1, col), 0);
- if (action.mode == 'save') setTimeout(handleSave, 0);
- return {};
- }
- case 'shouldSave': {
- return {
- ...state,
- shouldSave: true,
- };
- }
- }
- return {};
- }, {});
-
- // usePropsCompare({ loadedRows, columns, containerWidth, display });
-
- const columnSizes = React.useMemo(() => countColumnSizes(grider, columns, containerWidth, display), [
- grider,
- columns,
- containerWidth,
- display,
- ]);
- const headerColWidth = 40;
-
- // console.log('containerWidth', containerWidth);
-
- const gridScrollAreaHeight = containerHeight - 2 * rowHeight;
- const gridScrollAreaWidth = containerWidth - columnSizes.frozenSize - headerColWidth - 32;
-
- const visibleRowCountUpperBound = Math.ceil(gridScrollAreaHeight / Math.floor(Math.max(1, rowHeight)));
- const visibleRowCountLowerBound = Math.floor(gridScrollAreaHeight / Math.ceil(Math.max(1, rowHeight)));
- // const visibleRowCountUpperBound = 20;
- // const visibleRowCountLowerBound = 20;
- // console.log('containerHeight', containerHeight);
- // console.log('visibleRowCountUpperBound', visibleRowCountUpperBound);
- // console.log('rowHeight', rowHeight);
-
- React.useEffect(() => {
- if (tabVisible) {
- if (focusFieldRef.current) focusFieldRef.current.focus();
- }
- }, [tabVisible, focusFieldRef.current]);
-
- React.useEffect(() => {
- if (onSelectionChanged) {
- onSelectionChanged(getSelectedCellsPublished());
- }
- }, [onSelectionChanged, selectedCells]);
-
- const maxScrollColumn = React.useMemo(() => {
- let newColumn = columnSizes.scrollInView(0, columns.length - 1 - columnSizes.frozenCount, gridScrollAreaWidth);
- return newColumn;
- }, [columnSizes, gridScrollAreaWidth]);
-
- React.useEffect(() => {
- if (props.onReferenceSourceChanged && (grider.rowCount > 0 || isLoadedAll)) {
- props.onReferenceSourceChanged(getSelectedRowData(), loadedTime);
- }
- }, [props.onReferenceSourceChanged, selectedCells, props.refReloadToken, grider.getRowData(0)]);
-
- // usePropsCompare({ columnSizes, firstVisibleColumnScrollIndex, gridScrollAreaWidth, columns });
-
- const visibleRealColumns = React.useMemo(
- () => countVisibleRealColumns(columnSizes, firstVisibleColumnScrollIndex, gridScrollAreaWidth, columns),
- [columnSizes, firstVisibleColumnScrollIndex, gridScrollAreaWidth, columns]
- );
-
- const realColumnUniqueNames = React.useMemo(
- () =>
- _.range(columnSizes.realCount).map(realIndex => (columns[columnSizes.realToModel(realIndex)] || {}).uniqueName),
- [columnSizes, columns]
- );
-
- React.useEffect(() => {
- if (display && display.focusedColumn) {
- const invMap = _.invert(realColumnUniqueNames);
- const colIndex = invMap[display.focusedColumn];
- if (colIndex) {
- scrollIntoView([null, colIndex]);
- }
- }
- }, [display && display.focusedColumn]);
-
- React.useEffect(() => {
- if (loadNextData && firstVisibleRowScrollIndex + visibleRowCountUpperBound >= grider.rowCount) {
- loadNextData();
- }
- });
-
- React.useEffect(() => {
- if (display.groupColumns && display.baseTable) {
- props.onReferenceClick({
- schemaName: display.baseTable.schemaName,
- pureName: display.baseTable.pureName,
- columns: display.groupColumns.map(col => ({
- baseName: col,
- refName: col,
- dataType: _.get(display.baseTable && display.baseTable.columns.find(x => x.columnName == col), 'dataType'),
- })),
- });
- }
- }, [display.baseTable, stableStringify(display && display.groupColumns)]);
-
- const theme = useTheme();
-
- const rowCountInfo = React.useMemo(() => {
- if (selectedCells.length > 1 && selectedCells.every(x => _.isNumber(x[0]) && _.isNumber(x[1]))) {
- let sum = _.sumBy(selectedCells, cell => {
- const row = grider.getRowData(cell[0]);
- if (row) {
- const colName = realColumnUniqueNames[cell[1]];
- if (colName) {
- const data = row[colName];
- if (!data) return 0;
- let num = +data;
- if (_.isNaN(num)) return 0;
- return num;
- }
- }
- return 0;
- });
- let count = selectedCells.length;
- let rowCount = getSelectedRowData().length;
- return `Rows: ${rowCount.toLocaleString()}, Count: ${count.toLocaleString()}, Sum:${sum.toLocaleString()}`;
- }
- if (allRowCount == null) return 'Loading row count...';
- return `Rows: ${allRowCount.toLocaleString()}`;
- }, [selectedCells, allRowCount, grider, visibleRealColumns]);
-
- const handleSetFormView = React.useMemo(
- () =>
- formViewAvailable && display.baseTable && display.baseTable.primaryKey
- ? (rowData, column) => {
- if (column) {
- openReferenceForm(rowData, column, openNewTab, conid, database);
- } else {
- display.switchToFormView(rowData);
- }
- }
- : null,
- [formViewAvailable, display, openNewTab]
- );
-
- if (!columns || columns.length == 0) return ;
-
- if (errorMessage) {
- return ;
- }
-
- if (grider.errors && grider.errors.length > 0) {
- return (
-
- {grider.errors.map((err, index) => (
-
- ))}
-
- );
- }
-
- const handleRowScroll = value => {
- setFirstVisibleRowScrollIndex(value);
- };
-
- const handleColumnScroll = value => {
- setFirstVisibleColumnScrollIndex(value);
- };
-
- const getSelectedFreeData = () => {
- const columns = getSelectedColumns();
- const rows = getSelectedRowData().map(row => _.pickBy(row, (v, col) => columns.find(x => x.columnName == col)));
- return {
- structure: {
- columns,
- },
- rows,
- };
- };
-
- const handleOpenFreeTable = () => {
- openNewTab(
- {
- title: 'Data #',
- icon: 'img free-table',
- tabComponent: 'FreeTableTab',
- props: {},
- },
- { editor: getSelectedFreeData() }
- );
- };
-
- const handleOpenChart = () => {
- openNewTab(
- {
- title: 'Chart #',
- icon: 'img chart',
- tabComponent: 'ChartTab',
- props: {},
- },
- {
- editor: {
- data: getSelectedFreeData(),
- config: { chartType: 'bar' },
- },
- }
- );
- };
-
- const handleContextMenu = event => {
- event.preventDefault();
- showMenu(
- event.pageX,
- event.pageY,
- display.reload() : null}
- setNull={grider.editable ? setNull : null}
- exportGrid={exportGrid}
- filterSelectedValue={display.filterable ? filterSelectedValue : null}
- openQuery={openQuery}
- openFreeTable={handleOpenFreeTable}
- openChartSelection={handleOpenChart}
- openActiveChart={openActiveChart}
- switchToForm={handleSwitchToFormView}
- />
- );
- };
-
- function handleGridMouseDown(event) {
- if (event.target.closest('.buttonLike')) return;
- if (event.target.closest('.resizeHandleControl')) return;
- if (event.target.closest('input')) return;
-
- // event.target.closest('table').focus();
- event.preventDefault();
- if (focusFieldRef.current) focusFieldRef.current.focus();
- const cell = cellFromEvent(event);
-
- if (event.button == 2 && cell && cellIsSelected(cell[0], cell[1], selectedCells)) return;
-
- const autofill = event.target.closest('div.autofillHandleMarker');
- if (autofill) {
- setAutofillDragStartCell(cell);
- } else {
- setCurrentCell(cell);
-
- if (event.ctrlKey) {
- if (isRegularCell(cell)) {
- if (selectedCells.find(x => x[0] == cell[0] && x[1] == cell[1])) {
- setSelectedCells(selectedCells.filter(x => x[0] != cell[0] || x[1] != cell[1]));
- } else {
- setSelectedCells([...selectedCells, cell]);
- }
- }
- } else {
- setSelectedCells(getCellRange(cell, cell));
- setDragStartCell(cell);
-
- if (isRegularCell(cell) && !_.isEqual(cell, inplaceEditorState.cell) && _.isEqual(cell, currentCell)) {
- // @ts-ignore
- dispatchInsplaceEditor({ type: 'show', cell, selectAll: true });
- } else if (!_.isEqual(cell, inplaceEditorState.cell)) {
- // @ts-ignore
- dispatchInsplaceEditor({ type: 'close' });
- }
- }
- }
-
- if (display.focusedColumn) display.focusColumn(null);
- }
-
- function handleCopy(event) {
- if (event && event.target.localName == 'input') return;
- if (event) event.preventDefault();
- copyToClipboard();
- }
-
- function setCellValue(cell, value) {
- grider.setCellValue(cell[0], realColumnUniqueNames[cell[1]], value);
- }
-
- function handlePaste(event) {
- var pastedText = undefined;
- // @ts-ignore
- if (window.clipboardData && window.clipboardData.getData) {
- // IE
- // @ts-ignore
- pastedText = window.clipboardData.getData('Text');
- } else if (event.clipboardData && event.clipboardData.getData) {
- pastedText = event.clipboardData.getData('text/plain');
- }
- event.preventDefault();
- grider.beginUpdate();
- const pasteRows = pastedText
- .replace(/\r/g, '')
- .split('\n')
- .map(row => row.split('\t'));
- const selectedRegular = cellsToRegularCells(selectedCells);
- if (selectedRegular.length <= 1) {
- const startRow = isRegularCell(currentCell) ? currentCell[0] : grider.rowCount;
- const startCol = isRegularCell(currentCell) ? currentCell[1] : 0;
- let rowIndex = startRow;
- for (const rowData of pasteRows) {
- if (rowIndex >= grider.rowCountInUpdate) {
- grider.insertRow();
- }
- let colIndex = startCol;
- for (const cell of rowData) {
- setCellValue([rowIndex, colIndex], cell == '(NULL)' ? null : cell);
- colIndex += 1;
- }
- rowIndex += 1;
- }
- }
- if (selectedRegular.length > 1) {
- const startRow = _.min(selectedRegular.map(x => x[0]));
- const startCol = _.min(selectedRegular.map(x => x[1]));
- for (const cell of selectedRegular) {
- const [rowIndex, colIndex] = cell;
- const selectionRow = rowIndex - startRow;
- const selectionCol = colIndex - startCol;
- const pasteRow = pasteRows[selectionRow % pasteRows.length];
- const pasteCell = pasteRow[selectionCol % pasteRow.length];
- setCellValue(cell, pasteCell);
- }
- }
- grider.endUpdate();
- }
-
- function setNull() {
- grider.beginUpdate();
- selectedCells.filter(isRegularCell).forEach(cell => {
- setCellValue(cell, null);
- });
- grider.endUpdate();
- }
-
- function cellsToRegularCells(cells) {
- cells = _.flatten(
- cells.map(cell => {
- if (cell[1] == 'header') {
- return _.range(0, columnSizes.count).map(col => [cell[0], col]);
- }
- return [cell];
- })
- );
- cells = _.flatten(
- cells.map(cell => {
- if (cell[0] == 'header') {
- return _.range(0, grider.rowCount).map(row => [row, cell[1]]);
- }
- return [cell];
- })
- );
- return cells.filter(isRegularCell);
- }
-
- function copyToClipboard() {
- const cells = cellsToRegularCells(selectedCells);
- const rowIndexes = _.sortBy(_.uniq(cells.map(x => x[0])));
- const lines = rowIndexes.map(rowIndex => {
- let colIndexes = _.sortBy(cells.filter(x => x[0] == rowIndex).map(x => x[1]));
- const rowData = grider.getRowData(rowIndex);
- if (!rowData) return '';
- const line = colIndexes
- .map(col => realColumnUniqueNames[col])
- .map(col => (rowData[col] == null ? '(NULL)' : rowData[col]))
- .join('\t');
- return line;
- });
- const text = lines.join('\r\n');
- copyTextToClipboard(text);
- }
-
- function handleGridMouseMove(event) {
- if (autofillDragStartCell) {
- const cell = cellFromEvent(event);
- if (isRegularCell(cell) && (cell[0] == autofillDragStartCell[0] || cell[1] == autofillDragStartCell[1])) {
- const autoFillStart = [selectedCells[0][0], _.min(selectedCells.map(x => x[1]))];
- // @ts-ignore
- setAutofillSelectedCells(getCellRange(autoFillStart, cell));
- }
- } else if (dragStartCell) {
- const cell = cellFromEvent(event);
- setCurrentCell(cell);
- setSelectedCells(getCellRange(dragStartCell, cell));
- }
- }
-
- function handleGridMouseUp(event) {
- if (dragStartCell) {
- const cell = cellFromEvent(event);
- setCurrentCell(cell);
- setSelectedCells(getCellRange(dragStartCell, cell));
- setDragStartCell(null);
- }
- if (autofillDragStartCell) {
- const currentRowNumber = currentCell[0];
- if (_.isNumber(currentRowNumber)) {
- const rowIndexes = _.uniq((autofillSelectedCells || []).map(x => x[0])).filter(x => x != currentRowNumber);
- const colNames = selectedCells.map(cell => realColumnUniqueNames[cell[1]]);
- const changeObject = _.pick(grider.getRowData(currentRowNumber), colNames);
- grider.beginUpdate();
- for (const index of rowIndexes) grider.updateRow(index, changeObject);
- grider.endUpdate();
- }
-
- setAutofillDragStartCell(null);
- setAutofillSelectedCells([]);
- setSelectedCells(autofillSelectedCells);
- }
- }
-
- function getSelectedRowIndexes() {
- if (selectedCells.find(x => x[0] == 'header')) return _.range(0, grider.rowCount);
- return _.uniq((selectedCells || []).map(x => x[0])).filter(x => _.isNumber(x));
- }
-
- function getSelectedColumnIndexes() {
- if (selectedCells.find(x => x[1] == 'header')) return _.range(0, realColumnUniqueNames.length);
- return _.uniq((selectedCells || []).map(x => x[1])).filter(x => _.isNumber(x));
- }
-
- function getSelectedCellsPublished() {
- const regular = cellsToRegularCells(selectedCells);
- // @ts-ignore
- return regular
- .map(cell => ({
- row: cell[0],
- column: realColumnUniqueNames[cell[1]],
- }))
- .filter(x => x.column);
-
- // return regular.map((cell) => {
- // const row = cell[0];
- // const column = realColumnUniqueNames[cell[1]];
- // let value = null;
- // if (grider && column) {
- // let rowData = grider.getRowData(row);
- // if (rowData) value = rowData[column];
- // }
- // return {
- // row,
- // column,
- // value,
- // };
- // });
- }
-
- function getSelectedRowData() {
- return _.compact(getSelectedRowIndexes().map(index => grider.getRowData(index)));
- }
-
- function getSelectedColumns() {
- return _.compact(
- getSelectedColumnIndexes().map(index => ({
- columnName: realColumnUniqueNames[index],
- }))
- );
- }
-
- function revertRowChanges() {
- grider.beginUpdate();
- for (const index of getSelectedRowIndexes()) {
- if (_.isNumber(index)) grider.revertRowChanges(index);
- }
- grider.endUpdate();
- }
-
- function filterSelectedValue() {
- const flts = {};
- for (const cell of selectedCells) {
- if (!isRegularCell(cell)) continue;
- const modelIndex = columnSizes.realToModel(cell[1]);
- const columnName = columns[modelIndex].uniqueName;
- let value = grider.getRowData(cell[0])[columnName];
- let svalue = getFilterValueExpression(value, columns[modelIndex].dataType);
- if (_.has(flts, columnName)) flts[columnName] += ',' + svalue;
- else flts[columnName] = svalue;
- }
-
- display.setFilters(flts);
- }
-
- function deleteSelectedRows() {
- grider.beginUpdate();
- for (const index of getSelectedRowIndexes()) {
- if (_.isNumber(index)) grider.deleteRow(index);
- }
- grider.endUpdate();
- }
-
- function handleGridWheel(event) {
- let newFirstVisibleRowScrollIndex = firstVisibleRowScrollIndex;
- if (event.deltaY > 0) {
- newFirstVisibleRowScrollIndex += wheelRowCount;
- }
- if (event.deltaY < 0) {
- newFirstVisibleRowScrollIndex -= wheelRowCount;
- }
- let rowCount = grider.rowCount;
- if (newFirstVisibleRowScrollIndex + visibleRowCountLowerBound > rowCount) {
- newFirstVisibleRowScrollIndex = rowCount - visibleRowCountLowerBound + 1;
- }
- if (newFirstVisibleRowScrollIndex < 0) {
- newFirstVisibleRowScrollIndex = 0;
- }
- setFirstVisibleRowScrollIndex(newFirstVisibleRowScrollIndex);
- // @ts-ignore
- setvScrollValueToSet(newFirstVisibleRowScrollIndex);
- setvScrollValueToSetDate(new Date());
- }
-
- function undo() {
- grider.undo();
- }
- function redo() {
- grider.redo();
- }
-
- function handleSave() {
- if (inplaceEditorState.cell) {
- // @ts-ignore
- dispatchInsplaceEditor({ type: 'shouldSave' });
- return;
- }
- if (onSave) onSave();
- }
-
- const insertNewRow = () => {
- if (grider.canInsert) {
- const rowIndex = grider.insertRow();
- const cell = [rowIndex, (currentCell && currentCell[1]) || 0];
- // @ts-ignore
- setCurrentCell(cell);
- // @ts-ignore
- setSelectedCells([cell]);
- scrollIntoView(cell);
- }
- };
-
- const selectTopmostCell = uniquePath => {
- const modelIndex = columns.findIndex(x => x.uniquePath == uniquePath);
- const realIndex = columnSizes.modelToReal(modelIndex);
- let cell = [firstVisibleRowScrollIndex, realIndex];
- // @ts-ignore
- setCurrentCell(cell);
- // @ts-ignore
- setSelectedCells([cell]);
- focusFieldRef.current.focus();
- };
-
- function handleGridKeyDown(event) {
- if (onKeyDown) {
- onKeyDown(event);
- }
-
- if (event.keyCode == keycodes.f5) {
- event.preventDefault();
- display.reload();
- }
-
- if (event.keyCode == keycodes.f4) {
- event.preventDefault();
- handleSwitchToFormView();
- }
-
- if (event.keyCode == keycodes.s && event.ctrlKey) {
- event.preventDefault();
- handleSave();
- // this.saveAndFocus();
- }
-
- if (event.keyCode == keycodes.n0 && event.ctrlKey) {
- event.preventDefault();
- setNull();
- }
-
- if (event.keyCode == keycodes.r && event.ctrlKey) {
- event.preventDefault();
- revertRowChanges();
- }
-
- if (event.keyCode == keycodes.f && event.ctrlKey) {
- event.preventDefault();
- filterSelectedValue();
- }
-
- if (event.keyCode == keycodes.z && event.ctrlKey) {
- event.preventDefault();
- undo();
- }
-
- if (event.keyCode == keycodes.y && event.ctrlKey) {
- event.preventDefault();
- redo();
- }
-
- if (event.keyCode == keycodes.c && event.ctrlKey) {
- event.preventDefault();
- copyToClipboard();
- }
-
- if (event.keyCode == keycodes.delete && event.ctrlKey) {
- event.preventDefault();
- deleteSelectedRows();
- // this.saveAndFocus();
- }
-
- if (event.keyCode == keycodes.insert && !event.ctrlKey) {
- event.preventDefault();
- insertNewRow();
- // this.saveAndFocus();
- }
-
- if (inplaceEditorState.cell) return;
-
- if (
- !event.ctrlKey &&
- !event.altKey &&
- ((event.keyCode >= keycodes.a && event.keyCode <= keycodes.z) ||
- (event.keyCode >= keycodes.n0 && event.keyCode <= keycodes.n9) ||
- event.keyCode == keycodes.dash)
- ) {
- // @ts-ignore
- dispatchInsplaceEditor({ type: 'show', text: event.nativeEvent.key, cell: currentCell });
- // console.log('event', event.nativeEvent);
- }
-
- if (event.keyCode == keycodes.f2) {
- // @ts-ignore
- dispatchInsplaceEditor({ type: 'show', cell: currentCell, selectAll: true });
- }
-
- const moved = handleCursorMove(event);
-
- if (moved) {
- if (event.shiftKey) {
- if (!isRegularCell(shiftDragStartCell)) {
- setShiftDragStartCell(currentCell);
- }
- } else {
- setShiftDragStartCell(nullCell);
- }
- }
-
- const newCell = handleCursorMove(event);
- if (event.shiftKey && newCell) {
- // @ts-ignore
- setSelectedCells(getCellRange(shiftDragStartCell || currentCell, newCell));
- }
- }
-
- function handleCursorMove(event) {
- if (!isRegularCell(currentCell)) return null;
- let rowCount = grider.rowCount;
- if (event.ctrlKey) {
- switch (event.keyCode) {
- case keycodes.upArrow:
- case keycodes.pageUp:
- return moveCurrentCell(0, currentCell[1], event);
- case keycodes.downArrow:
- case keycodes.pageDown:
- return moveCurrentCell(rowCount - 1, currentCell[1], event);
- case keycodes.leftArrow:
- return moveCurrentCell(currentCell[0], 0, event);
- case keycodes.rightArrow:
- return moveCurrentCell(currentCell[0], columnSizes.realCount - 1, event);
- case keycodes.home:
- return moveCurrentCell(0, 0, event);
- case keycodes.end:
- return moveCurrentCell(rowCount - 1, columnSizes.realCount - 1, event);
- case keycodes.a:
- setSelectedCells([['header', 'header']]);
- event.preventDefault();
- return ['header', 'header'];
- }
- } else {
- switch (event.keyCode) {
- case keycodes.upArrow:
- if (currentCell[0] == 0) return focusFilterEditor(currentCell[1]);
- return moveCurrentCell(currentCell[0] - 1, currentCell[1], event);
- case keycodes.downArrow:
- case keycodes.enter:
- return moveCurrentCell(currentCell[0] + 1, currentCell[1], event);
- case keycodes.leftArrow:
- return moveCurrentCell(currentCell[0], currentCell[1] - 1, event);
- case keycodes.rightArrow:
- return moveCurrentCell(currentCell[0], currentCell[1] + 1, event);
- case keycodes.home:
- return moveCurrentCell(currentCell[0], 0, event);
- case keycodes.end:
- return moveCurrentCell(currentCell[0], columnSizes.realCount - 1, event);
- case keycodes.pageUp:
- return moveCurrentCell(currentCell[0] - visibleRowCountLowerBound, currentCell[1], event);
- case keycodes.pageDown:
- return moveCurrentCell(currentCell[0] + visibleRowCountLowerBound, currentCell[1], event);
- }
- }
- return null;
- }
-
- function focusFilterEditor(columnRealIndex) {
- let modelIndex = columnSizes.realToModel(columnRealIndex);
- setFocusFilterInputs(cols => ({
- ...cols,
- [columns[modelIndex].uniqueName]: (cols[columns[modelIndex].uniqueName] || 0) + 1,
- }));
- // this.headerFilters[this.columns[modelIndex].uniquePath].focus();
- return ['filter', columnRealIndex];
- }
-
- function moveCurrentCell(row, col, event = null) {
- const rowCount = grider.rowCount;
-
- if (row < 0) row = 0;
- if (row >= rowCount) row = rowCount - 1;
- if (col < 0) col = 0;
- if (col >= columnSizes.realCount) col = columnSizes.realCount - 1;
- setCurrentCell([row, col]);
- // setSelectedCells([...(event.ctrlKey ? selectedCells : []), [row, col]]);
- setSelectedCells([[row, col]]);
- scrollIntoView([row, col]);
- // this.selectedCells.push(this.currentCell);
- // this.scrollIntoView(this.currentCell);
-
- if (event) event.preventDefault();
- return [row, col];
- }
-
- function scrollIntoView(cell) {
- const [row, col] = cell;
-
- if (row != null) {
- let newRow = null;
- const rowCount = grider.rowCount;
- if (rowCount == 0) return;
-
- if (row < firstVisibleRowScrollIndex) newRow = row;
- else if (row + 1 >= firstVisibleRowScrollIndex + visibleRowCountLowerBound)
- newRow = row - visibleRowCountLowerBound + 2;
-
- if (newRow < 0) newRow = 0;
- if (newRow >= rowCount) newRow = rowCount - 1;
-
- if (newRow != null) {
- setFirstVisibleRowScrollIndex(newRow);
- // firstVisibleRowScrollIndex = newRow;
- setvScrollValueToSet(newRow);
- setvScrollValueToSetDate(new Date());
- // vscroll.value = newRow;
- }
- //int newRow = _rowSizes.ScrollInView(FirstVisibleRowScrollIndex, cell.Row.Value - _rowSizes.FrozenCount, GridScrollAreaHeight);
- //ScrollContent(newRow, FirstVisibleColumnScrollIndex);
- }
-
- if (col != null) {
- if (col >= columnSizes.frozenCount) {
- let newColumn = columnSizes.scrollInView(
- firstVisibleColumnScrollIndex,
- col - columnSizes.frozenCount,
- gridScrollAreaWidth
- );
- setFirstVisibleColumnScrollIndex(newColumn);
-
- // @ts-ignore
- sethScrollValueToSet(newColumn);
- sethScrollValueToSetDate(new Date());
-
- // firstVisibleColumnScrollIndex = newColumn;
- // hscroll.value = newColumn;
- }
- }
- }
-
- function setGrouping(uniqueName, groupFunc) {
- display.setGrouping(uniqueName, groupFunc);
- }
-
- // console.log('visibleRowCountUpperBound', visibleRowCountUpperBound);
- // console.log('gridScrollAreaHeight', gridScrollAreaHeight);
- // console.log('containerHeight', containerHeight);
-
- const hederColwidthPx = `${headerColWidth}px`;
- const filterCount = display.filterCount;
-
- const handleClearFilters = () => {
- display.clearFilters();
- };
-
- const handleSwitchToFormView =
- formViewAvailable && display.baseTable && display.baseTable.primaryKey
- ? () => {
- const cell = currentCell;
- const rowData = isRegularCell(cell) ? grider.getRowData(cell[0]) : null;
- display.switchToFormView(rowData);
- }
- : null;
-
- // console.log('visibleRealColumnIndexes', visibleRealColumnIndexes);
- // console.log(
- // 'gridScrollAreaWidth / columnSizes.getVisibleScrollSizeSum()',
- // gridScrollAreaWidth,
- // columnSizes.getVisibleScrollSizeSum()
- // );
-
- // const loadedAndInsertedRows = [...loadedRows, ...insertedRows];
-
- // console.log('focusFieldRef.current', focusFieldRef.current);
-
- return (
-
-
-
-
-
-
- {visibleRealColumns.map(col => (
-
- display.setSort(col.uniqueName, order) : null}
- order={display.getSortOrder(col.uniqueName)}
- onResize={diff => display.resizeColumn(col.uniqueName, col.widthNumber, diff)}
- setGrouping={display.sortable ? groupFunc => setGrouping(col.uniqueName, groupFunc) : null}
- grouping={display.getGrouping(col.uniqueName)}
- />
-
- ))}
-
- {display.filterable && (
-
-
- {filterCount > 0 && (
-
-
-
- )}
-
- {visibleRealColumns.map(col => (
-
- display.setFilter(col.uniqueName, value)}
- focusIndex={focusFilterInputs[col.uniqueName]}
- onFocusGrid={() => {
- selectTopmostCell(col.uniqueName);
- // focusFieldRef.current.focus();
- }}
- />
-
- ))}
-
- )}
-
-
- {_.range(firstVisibleRowScrollIndex, firstVisibleRowScrollIndex + visibleRowCountUpperBound).map(rowIndex => (
-
- ))}
-
-
-
-
- {allRowCount && {rowCountInfo} }
- {props.toolbarPortalRef &&
- props.toolbarPortalRef.current &&
- tabVisible &&
- ReactDOM.createPortal(
- display.reload()}
- save={handleSave}
- grider={grider}
- reconnect={async () => {
- await axios.post('database-connections/refresh', { conid, database });
- display.reload();
- }}
- switchToForm={handleSwitchToFormView}
- />,
- props.toolbarPortalRef.current
- )}
- {isLoading && }
-
- );
-}
diff --git a/packages/web/src/datagrid/DataGridRow.js b/packages/web/src/datagrid/DataGridRow.js
deleted file mode 100644
index f468ac252..000000000
--- a/packages/web/src/datagrid/DataGridRow.js
+++ /dev/null
@@ -1,333 +0,0 @@
-// @ts-nocheck
-import moment from 'moment';
-import _ from 'lodash';
-import React from 'react';
-import styled from 'styled-components';
-import InplaceEditor from './InplaceEditor';
-import { cellIsSelected } from './gridutil';
-import { isTypeLogical } from 'dbgate-tools';
-import useTheme from '../theme/useTheme';
-import { FontIcon } from '../icons';
-
-const TableBodyCell = styled.td`
- font-weight: normal;
- border: 1px solid ${props => props.theme.border};
- // border-collapse: collapse;
- padding: 2px;
- white-space: nowrap;
- position: relative;
- overflow: hidden;
- ${props =>
- props.isSelected &&
- !props.isAutofillSelected &&
- !props.isFocusedColumn &&
- `
- background: initial;
- background-color: ${props.theme.gridbody_selection[4]};
- color: ${props.theme.gridbody_invfont1};`}
-
- ${props =>
- props.isFrameSelected &&
- `
- outline: 3px solid ${props.theme.gridbody_selection[4]};
- outline-offset: -3px;`}
-
- ${props =>
- props.isAutofillSelected &&
- !props.isFocusedColumn &&
- `
- outline: 3px solid ${props.theme.gridbody_selection[4]};
- outline-offset: -3px;`}
-
- ${props =>
- props.isModifiedRow &&
- !props.isInsertedRow &&
- !props.isSelected &&
- !props.isAutofillSelected &&
- !props.isModifiedCell &&
- !props.isFocusedColumn &&
- `
- background-color: ${props.theme.gridbody_background_gold[1]};`}
- ${props =>
- !props.isSelected &&
- !props.isAutofillSelected &&
- !props.isInsertedRow &&
- !props.isFocusedColumn &&
- props.isModifiedCell &&
- `
- background-color: ${props.theme.gridbody_background_orange[1]};`}
-
- ${props =>
- !props.isSelected &&
- !props.isAutofillSelected &&
- !props.isFocusedColumn &&
- props.isInsertedRow &&
- `
- background-color: ${props.theme.gridbody_background_green[1]};`}
-
- ${props =>
- !props.isSelected &&
- !props.isAutofillSelected &&
- !props.isFocusedColumn &&
- props.isDeletedRow &&
- `
- background-color: ${props.theme.gridbody_background_volcano[1]};
- `}
-
- ${props =>
- props.isFocusedColumn &&
- `
- background-color: ${props.theme.gridbody_background_yellow[0]};
- `}
-
- ${props =>
- props.isDeletedRow &&
- `
- background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAEElEQVQImWNgIAX8x4KJBAD+agT8INXz9wAAAABJRU5ErkJggg==');
- // from http://www.patternify.com/
- background-repeat: repeat-x;
- background-position: 50% 50%;`}
-`;
-
-const HintSpan = styled.span`
- color: ${props => props.theme.gridbody_font3};
- margin-left: 5px;
-`;
-const NullSpan = styled.span`
- color: ${props => props.theme.gridbody_font3};
- font-style: italic;
-`;
-
-const TableBodyRow = styled.tr`
- // height: 35px;
- background-color: ${props => props.theme.gridbody_background};
- &:nth-child(6n + 3) {
- background-color: ${props => props.theme.gridbody_background_alt2};
- }
- &:nth-child(6n + 6) {
- background-color: ${props => props.theme.gridbody_background_alt3};
- }
-`;
-
-const TableHeaderCell = styled.td`
- border: 1px solid ${props => props.theme.border};
- text-align: left;
- padding: 2px;
- background-color: ${props => props.theme.gridheader_background};
- overflow: hidden;
- position: relative;
-`;
-
-const AutoFillPoint = styled.div`
- width: 8px;
- height: 8px;
- background-color: ${props => props.theme.gridbody_selection[6]};
- position: absolute;
- right: 0px;
- bottom: 0px;
- overflow: visible;
- cursor: crosshair;
-`;
-
-export const ShowFormButton = styled.div`
- position: absolute;
- right: 0px;
- top: 1px;
- color: ${props => props.theme.gridbody_font3};
- background-color: ${props => props.theme.gridheader_background};
- border: 1px solid ${props => props.theme.gridheader_background};
- &:hover {
- color: ${props => props.theme.gridheader_font_hover};
- border: 1px solid ${props => props.theme.border};
- top: 1px;
- right: 0px;
- }
-`;
-
-function makeBulletString(value) {
- return _.pad('', value.length, '•');
-}
-
-function highlightSpecialCharacters(value) {
- value = value.replace(/\n/g, '↲');
- value = value.replace(/\r/g, '');
- value = value.replace(/^(\s+)/, makeBulletString);
- value = value.replace(/(\s+)$/, makeBulletString);
- value = value.replace(/(\s\s+)/g, makeBulletString);
- return value;
-}
-
-const dateTimeRegex = /^\d\d\d\d-\d\d-\d\dT\d\d:\d\d:\d\d(\.\d\d\d)?Z?$/;
-
-export function CellFormattedValue({ value, dataType, theme }) {
- if (value == null) return (NULL) ;
- if (_.isDate(value)) return moment(value).format('YYYY-MM-DD HH:mm:ss');
- if (value === true) return '1';
- if (value === false) return '0';
- if (_.isNumber(value)) {
- if (value >= 10000 || value <= -10000) {
- return value.toLocaleString();
- }
- return value.toString();
- }
- if (_.isString(value)) {
- if (dateTimeRegex.test(value)) return moment(value).format('YYYY-MM-DD HH:mm:ss');
- return highlightSpecialCharacters(value);
- }
- if (_.isPlainObject(value)) {
- if (_.isArray(value.data)) {
- if (value.data.length == 1 && isTypeLogical(dataType)) return value.data[0];
- return ({value.data.length} bytes) ;
- }
- return (RAW) ;
- }
- return value.toString();
-}
-
-function RowHeaderCell({ rowIndex, theme, onSetFormView, rowData }) {
- const [mouseIn, setMouseIn] = React.useState(false);
-
- return (
- setMouseIn(true) : null}
- onMouseLeave={onSetFormView ? () => setMouseIn(false) : null}
- >
- {rowIndex + 1}
- {!!onSetFormView && mouseIn && (
- {
- e.stopPropagation();
- onSetFormView(rowData);
- }}
- >
-
-
- )}
-
- );
-}
-
-/** @param props {import('./types').DataGridProps} */
-function DataGridRow(props) {
- const {
- rowHeight,
- rowIndex,
- visibleRealColumns,
- inplaceEditorState,
- dispatchInsplaceEditor,
- autofillMarkerCell,
- selectedCells,
- autofillSelectedCells,
- focusedColumn,
- grider,
- frameSelection,
- onSetFormView,
- } = props;
- // usePropsCompare({
- // rowHeight,
- // rowIndex,
- // visibleRealColumns,
- // inplaceEditorState,
- // dispatchInsplaceEditor,
- // row,
- // display,
- // changeSet,
- // setChangeSet,
- // insertedRowIndex,
- // autofillMarkerCell,
- // selectedCells,
- // autofillSelectedCells,
- // });
-
- // console.log('RENDER ROW', rowIndex);
-
- const theme = useTheme();
-
- const rowData = grider.getRowData(rowIndex);
- const rowStatus = grider.getRowStatus(rowIndex);
-
- const hintFieldsAllowed = visibleRealColumns
- .filter(col => {
- if (!col.hintColumnName) return false;
- if (rowStatus.modifiedFields && rowStatus.modifiedFields.has(col.uniqueName)) return false;
- return true;
- })
- .map(col => col.uniqueName);
-
- if (!rowData) return null;
-
- return (
-
-
-
- {visibleRealColumns.map(col => (
-
- {inplaceEditorState.cell &&
- rowIndex == inplaceEditorState.cell[0] &&
- col.colIndex == inplaceEditorState.cell[1] ? (
- grider.setCellValue(rowIndex, col.uniqueName, value)}
- />
- ) : (
- <>
-
- {hintFieldsAllowed.includes(col.uniqueName) && (
- {rowData[col.hintColumnName]}
- )}
- {col.foreignKey && rowData[col.uniqueName] && (
- {
- e.stopPropagation();
- onSetFormView(rowData, col);
- }}
- >
-
-
- )}
- >
- )}
- {autofillMarkerCell && autofillMarkerCell[1] == col.colIndex && autofillMarkerCell[0] == rowIndex && (
-
- )}
-
- ))}
-
- );
-}
-
-export default React.memo(DataGridRow);
diff --git a/packages/web/src/datagrid/DataGridToolbar.js b/packages/web/src/datagrid/DataGridToolbar.js
deleted file mode 100644
index 800aa8586..000000000
--- a/packages/web/src/datagrid/DataGridToolbar.js
+++ /dev/null
@@ -1,32 +0,0 @@
-import React from 'react';
-import ToolbarButton from '../widgets/ToolbarButton';
-
-export default function DataGridToolbar({ reload, reconnect, grider, save, switchToForm }) {
- return (
- <>
- {switchToForm && (
-
- Form view
-
- )}
-
- Refresh
-
-
- Reconnect
-
- grider.undo()} icon="icon undo">
- Undo
-
- grider.redo()} icon="icon redo">
- Redo
-
-
- Save
-
- grider.revertAllChanges()} icon="icon close">
- Revert
-
- >
- );
-}
diff --git a/packages/web/src/datagrid/Grider.ts b/packages/web/src/datagrid/Grider.ts
deleted file mode 100644
index 0f24aeea4..000000000
--- a/packages/web/src/datagrid/Grider.ts
+++ /dev/null
@@ -1,61 +0,0 @@
-export interface GriderRowStatus {
- status: 'regular' | 'updated' | 'deleted' | 'inserted';
- modifiedFields?: Set;
- insertedFields?: Set;
- deletedFields?: Set;
-}
-
-export default abstract class Grider {
- abstract getRowData(index): any;
- abstract get rowCount(): number;
-
- getRowStatus(index): GriderRowStatus {
- const res: GriderRowStatus = {
- status: 'regular',
- };
- return res;
- }
- beginUpdate() {}
- endUpdate() {}
- setCellValue(index: number, uniqueName: string, value: any) {}
- deleteRow(index: number) {}
- insertRow(): number {
- return null;
- }
- revertRowChanges(index: number) {}
- revertAllChanges() {}
- undo() {}
- redo() {}
- get editable() {
- return false;
- }
- get canInsert() {
- return false;
- }
- get allowSave() {
- return this.containsChanges;
- }
- get rowCountInUpdate() {
- return this.rowCount;
- }
- get canUndo() {
- return false;
- }
- get canRedo() {
- return false;
- }
- get containsChanges() {
- return false;
- }
- get disableLoadNextPage() {
- return false;
- }
- get errors() {
- return null;
- }
- updateRow(index, changeObject) {
- for (const key of Object.keys(changeObject)) {
- this.setCellValue(index, key, changeObject[key]);
- }
- }
-}
diff --git a/packages/web/src/datagrid/InplaceEditor.js b/packages/web/src/datagrid/InplaceEditor.js
deleted file mode 100644
index e32ab10ed..000000000
--- a/packages/web/src/datagrid/InplaceEditor.js
+++ /dev/null
@@ -1,98 +0,0 @@
-// @ts-nocheck
-
-import _ from 'lodash';
-import React from 'react';
-import styled from 'styled-components';
-import keycodes from '../utility/keycodes';
-
-const StyledInput = styled.input`
- border: 0px solid;
- outline: none;
- margin: 0px;
- padding: 0px;
-`;
-
-export default function InplaceEditor({
- widthPx,
- // rowIndex,
- // uniqueName,
- // grider,
- cellValue,
- inplaceEditorState,
- dispatchInsplaceEditor,
- onSetValue,
-}) {
- const editorRef = React.useRef();
- const widthRef = React.useRef(widthPx);
- const isChangedRef = React.useRef(!!inplaceEditorState.text);
- React.useEffect(() => {
- const editor = editorRef.current;
- editor.value = inplaceEditorState.text || cellValue;
- editor.focus();
- if (inplaceEditorState.selectAll) {
- editor.select();
- }
- }, []);
- function handleBlur() {
- if (isChangedRef.current) {
- const editor = editorRef.current;
- onSetValue(editor.value);
- // grider.setCellValue(rowIndex, uniqueName, editor.value);
- isChangedRef.current = false;
- }
- dispatchInsplaceEditor({ type: 'close' });
- }
- if (inplaceEditorState.shouldSave) {
- const editor = editorRef.current;
- if (isChangedRef.current) {
- onSetValue(editor.value);
- // grider.setCellValue(rowIndex, uniqueName, editor.value);
- isChangedRef.current = false;
- }
- editor.blur();
- dispatchInsplaceEditor({ type: 'close', mode: 'save' });
- }
- function handleKeyDown(event) {
- const editor = editorRef.current;
- switch (event.keyCode) {
- case keycodes.escape:
- isChangedRef.current = false;
- dispatchInsplaceEditor({ type: 'close' });
- break;
- case keycodes.enter:
- if (isChangedRef.current) {
- // grider.setCellValue(rowIndex, uniqueName, editor.value);
- onSetValue(editor.value);
- isChangedRef.current = false;
- }
- editor.blur();
- dispatchInsplaceEditor({ type: 'close', mode: 'enter' });
- break;
- case keycodes.s:
- if (event.ctrlKey) {
- if (isChangedRef.current) {
- onSetValue(editor.value);
- // grider.setCellValue(rowIndex, uniqueName, editor.value);
- isChangedRef.current = false;
- }
- event.preventDefault();
- dispatchInsplaceEditor({ type: 'close', mode: 'save' });
- }
- break;
- }
- }
- return (
- (isChangedRef.current = true)}
- onKeyDown={handleKeyDown}
- style={{
- width: widthRef.current,
- minWidth: widthRef.current,
- maxWidth: widthRef.current,
- }}
- />
- );
-}
diff --git a/packages/web/src/datagrid/JslDataGridCore.js b/packages/web/src/datagrid/JslDataGridCore.js
deleted file mode 100644
index 1ec74e608..000000000
--- a/packages/web/src/datagrid/JslDataGridCore.js
+++ /dev/null
@@ -1,97 +0,0 @@
-import React from 'react';
-import axios from '../utility/axios';
-import { useSetOpenedTabs } from '../utility/globalState';
-import useSocket from '../utility/SocketProvider';
-import useShowModal from '../modals/showModal';
-import ImportExportModal from '../modals/ImportExportModal';
-import LoadingDataGridCore from './LoadingDataGridCore';
-import RowsArrayGrider from './RowsArrayGrider';
-
-async function loadDataPage(props, offset, limit) {
- const { jslid, display } = props;
-
- const response = await axios.post('jsldata/get-rows', {
- jslid,
- offset,
- limit,
- filters: display ? display.compileFilters() : null,
- });
-
- return response.data;
-}
-
-function dataPageAvailable(props) {
- return true;
-}
-
-async function loadRowCount(props) {
- const { jslid } = props;
-
- const response = await axios.request({
- url: 'jsldata/get-stats',
- method: 'get',
- params: {
- jslid,
- },
- });
- return response.data.rowCount;
-}
-
-export default function JslDataGridCore(props) {
- const { jslid } = props;
- const [changeIndex, setChangeIndex] = React.useState(0);
- const [rowCountLoaded, setRowCountLoaded] = React.useState(null);
-
- const showModal = useShowModal();
-
- const setOpenedTabs = useSetOpenedTabs();
- const socket = useSocket();
-
- function exportGrid() {
- const initialValues = {};
- const archiveMatch = jslid.match(/^archive:\/\/([^/]+)\/(.*)$/);
- if (archiveMatch) {
- initialValues.sourceStorageType = 'archive';
- initialValues.sourceArchiveFolder = archiveMatch[1];
- initialValues.sourceList = [archiveMatch[2]];
- } else {
- initialValues.sourceStorageType = 'jsldata';
- initialValues.sourceJslId = jslid;
- initialValues.sourceList = ['query-data'];
- }
- showModal(modalState => );
- }
-
- const handleJslDataStats = React.useCallback(
- stats => {
- if (stats.changeIndex < changeIndex) return;
- setChangeIndex(stats.changeIndex);
- setRowCountLoaded(stats.rowCount);
- },
- [changeIndex]
- );
-
- React.useEffect(() => {
- if (jslid && socket) {
- socket.on(`jsldata-stats-${jslid}`, handleJslDataStats);
- return () => {
- socket.off(`jsldata-stats-${jslid}`, handleJslDataStats);
- };
- }
- }, [jslid]);
-
- return (
- setChangeIndex(0)}
- griderFactory={RowsArrayGrider.factory}
- griderFactoryDeps={RowsArrayGrider.factoryDeps}
- />
- );
-}
diff --git a/packages/web/src/datagrid/LoadingDataGridCore.js b/packages/web/src/datagrid/LoadingDataGridCore.js
deleted file mode 100644
index f3a4f5029..000000000
--- a/packages/web/src/datagrid/LoadingDataGridCore.js
+++ /dev/null
@@ -1,141 +0,0 @@
-import React from 'react';
-import DataGridCore from './DataGridCore';
-
-export default function LoadingDataGridCore(props) {
- const {
- display,
- loadDataPage,
- dataPageAvailable,
- loadRowCount,
- loadNextDataToken,
- onReload,
- exportGrid,
- openQuery,
- griderFactory,
- griderFactoryDeps,
- onChangeGrider,
- rowCountLoaded,
- } = props;
-
- const [loadProps, setLoadProps] = React.useState({
- isLoading: false,
- loadedRows: [],
- isLoadedAll: false,
- loadedTime: new Date().getTime(),
- allRowCount: null,
- errorMessage: null,
- loadNextDataToken: 0,
- });
- const { isLoading, loadedRows, isLoadedAll, loadedTime, allRowCount, errorMessage } = loadProps;
-
- const loadedTimeRef = React.useRef(0);
-
- const handleLoadRowCount = async () => {
- const rowCount = await loadRowCount(props);
- setLoadProps(oldLoadProps => ({
- ...oldLoadProps,
- allRowCount: rowCount,
- }));
- };
-
- const reload = () => {
- setLoadProps({
- allRowCount: null,
- isLoading: false,
- loadedRows: [],
- isLoadedAll: false,
- loadedTime: new Date().getTime(),
- errorMessage: null,
- loadNextDataToken: 0,
- });
- if (onReload) onReload();
- };
-
- React.useEffect(() => {
- if (props.masterLoadedTime && props.masterLoadedTime > loadedTime) {
- display.reload();
- }
- if (display.cache.refreshTime > loadedTime) {
- reload();
- }
- });
-
- const loadNextData = async () => {
- if (isLoading) return;
- setLoadProps(oldLoadProps => ({
- ...oldLoadProps,
- isLoading: true,
- }));
- const loadStart = new Date().getTime();
- loadedTimeRef.current = loadStart;
-
- const nextRows = await loadDataPage(props, loadedRows.length, 100);
- if (loadedTimeRef.current !== loadStart) {
- // new load was dispatched
- return;
- }
- // if (!_.isArray(nextRows)) {
- // console.log('Error loading data from server', nextRows);
- // nextRows = [];
- // }
- // console.log('nextRows', nextRows);
- if (nextRows.errorMessage) {
- setLoadProps(oldLoadProps => ({
- ...oldLoadProps,
- isLoading: false,
- errorMessage: nextRows.errorMessage,
- }));
- } else {
- if (allRowCount == null) handleLoadRowCount();
- const loadedInfo = {
- loadedRows: [...loadedRows, ...nextRows],
- loadedTime,
- };
- setLoadProps(oldLoadProps => ({
- ...oldLoadProps,
- isLoading: false,
- isLoadedAll: oldLoadProps.loadNextDataToken == loadNextDataToken && nextRows.length === 0,
- loadNextDataToken,
- ...loadedInfo,
- }));
- }
- };
-
- React.useEffect(() => {
- setLoadProps(oldProps => ({
- ...oldProps,
- isLoadedAll: false,
- }));
- }, [loadNextDataToken]);
-
- const griderProps = { ...props, sourceRows: loadedRows };
- const grider = React.useMemo(() => griderFactory(griderProps), griderFactoryDeps(griderProps));
-
- React.useEffect(() => {
- if (onChangeGrider) onChangeGrider(grider);
- }, [grider]);
-
- const handleLoadNextData = () => {
- if (!isLoadedAll && !errorMessage && !grider.disableLoadNextPage) {
- if (dataPageAvailable(props)) {
- // If not, callbacks to load missing metadata are dispatched
- loadNextData();
- }
- }
- };
-
- return (
-
- );
-}
diff --git a/packages/web/src/datagrid/ManagerStyles.js b/packages/web/src/datagrid/ManagerStyles.js
deleted file mode 100644
index 6de11af95..000000000
--- a/packages/web/src/datagrid/ManagerStyles.js
+++ /dev/null
@@ -1,7 +0,0 @@
-import styled from 'styled-components';
-
-export const ManagerInnerContainer = styled.div`
- flex: 1 1;
- overflow-y: auto;
- overflow-x: auto;
-`;
diff --git a/packages/web/src/datagrid/ReferenceHeader.js b/packages/web/src/datagrid/ReferenceHeader.js
deleted file mode 100644
index 4f723a320..000000000
--- a/packages/web/src/datagrid/ReferenceHeader.js
+++ /dev/null
@@ -1,46 +0,0 @@
-import React from 'react';
-import ToolbarButton from '../widgets/ToolbarButton';
-import styled from 'styled-components';
-import dimensions from '../theme/dimensions';
-import { FontIcon } from '../icons';
-import useTheme from '../theme/useTheme';
-
-const Container = styled.div`
- display: flex;
- justify-content: space-between;
- align-items: center;
- background: ${props => props.theme.gridheader_background_cyan[0]};
- height: ${dimensions.toolBar.height}px;
- min-height: ${dimensions.toolBar.height}px;
- overflow: hidden;
- border-top: 1px solid ${props => props.theme.border};
- border-bottom: 1px solid ${props => props.theme.border};
-`;
-
-const Header = styled.div`
- font-weight: bold;
- margin-left: 10px;
- display: flex;
-`;
-
-const HeaderText = styled.div`
- margin-left: 10px;
-`;
-
-export default function ReferenceHeader({ reference, onClose }) {
- const theme = useTheme();
- return (
-
-
-
-
- {reference.pureName} [{reference.columns.map(x => x.refName).join(', ')}] = master [
- {reference.columns.map(x => x.baseName).join(', ')}]
-
-
-
- Close
-
-
- );
-}
diff --git a/packages/web/src/datagrid/ReferenceManager.js b/packages/web/src/datagrid/ReferenceManager.js
deleted file mode 100644
index 76b1cfc0e..000000000
--- a/packages/web/src/datagrid/ReferenceManager.js
+++ /dev/null
@@ -1,114 +0,0 @@
-import React from 'react';
-import styled from 'styled-components';
-import { ManagerInnerContainer } from './ManagerStyles';
-import SearchInput from '../widgets/SearchInput';
-import { filterName } from 'dbgate-datalib';
-import { FontIcon } from '../icons';
-import useTheme from '../theme/useTheme';
-
-const SearchBoxWrapper = styled.div`
- display: flex;
- margin-bottom: 5px;
-`;
-
-const Header = styled.div`
- font-weight: bold;
- white-space: nowrap;
-`;
-
-const LinkContainer = styled.div`
- color: ${props => props.theme.manager_font_blue[7]};
- margin: 5px;
- &:hover {
- text-decoration: underline;
- }
- cursor: pointer;
- display: flex;
- flex-wrap: nowrap;
-`;
-
-const NameContainer = styled.div`
- margin-left: 5px;
- white-space: nowrap;
-`;
-
-function ManagerRow({ tableName, columns, icon, onClick }) {
- const theme = useTheme();
- return (
-
-
-
- {tableName} ({columns.map(x => x.columnName).join(', ')})
-
-
- );
-}
-
-/** @param props {import('./types').DataGridProps} */
-export default function ReferenceManager(props) {
- const [filter, setFilter] = React.useState('');
- const { display } = props;
- const { baseTable } = display || {};
- const { foreignKeys } = baseTable || {};
- const { dependencies } = baseTable || {};
-
- return (
- <>
-
-
-
-
- {foreignKeys && foreignKeys.length > 0 && (
- <>
- References tables ({foreignKeys.length})
- {foreignKeys
- .filter(fk => filterName(filter, fk.refTableName))
- .map(fk => (
-
- props.onReferenceClick({
- schemaName: fk.refSchemaName,
- pureName: fk.refTableName,
- columns: fk.columns.map(col => ({
- baseName: col.columnName,
- refName: col.refColumnName,
- })),
- })
- }
- />
- ))}
- >
- )}
- {dependencies && dependencies.length > 0 && (
- <>
- Dependend tables ({dependencies.length})
- {dependencies
- .filter(fk => filterName(filter, fk.pureName))
- .map(fk => (
-
- props.onReferenceClick({
- schemaName: fk.schemaName,
- pureName: fk.pureName,
- columns: fk.columns.map(col => ({
- baseName: col.refColumnName,
- refName: col.columnName,
- })),
- })
- }
- />
- ))}
- >
- )}
-
- >
- );
-}
diff --git a/packages/web/src/datagrid/RowsArrayGrider.ts b/packages/web/src/datagrid/RowsArrayGrider.ts
deleted file mode 100644
index 76a9e140d..000000000
--- a/packages/web/src/datagrid/RowsArrayGrider.ts
+++ /dev/null
@@ -1,20 +0,0 @@
-import Grider, { GriderRowStatus } from './Grider';
-
-export default class RowsArrayGrider extends Grider {
- constructor(private rows: any[]) {
- super();
- }
- getRowData(index: any) {
- return this.rows[index];
- }
- get rowCount() {
- return this.rows.length;
- }
-
- static factory({ sourceRows }): RowsArrayGrider {
- return new RowsArrayGrider(sourceRows);
- }
- static factoryDeps({ sourceRows }) {
- return [sourceRows];
- }
-}
diff --git a/packages/web/src/datagrid/ScrollBars.js b/packages/web/src/datagrid/ScrollBars.js
deleted file mode 100644
index f2880615d..000000000
--- a/packages/web/src/datagrid/ScrollBars.js
+++ /dev/null
@@ -1,222 +0,0 @@
-import _ from 'lodash';
-import React from 'react';
-import styled from 'styled-components';
-import useDimensions from '../utility/useDimensions';
-
-const StyledHorizontalScrollBar = styled.div`
- overflow-x: scroll;
- height: 16px;
- position: absolute;
- bottom: 0;
- //left: 100px;
- // right: 20px;
- right: 0;
- left: 0;
-`;
-
-const StyledHorizontalScrollContent = styled.div``;
-
-const StyledVerticalScrollBar = styled.div`
- overflow-y: scroll;
- width: 20px;
- position: absolute;
- right: 0px;
- width: 20px;
- bottom: 16px;
- // bottom: 0;
- top: 0;
-`;
-
-const StyledVerticalScrollContent = styled.div``;
-
-export function HorizontalScrollBar({
- onScroll = undefined,
- valueToSet = undefined,
- valueToSetDate = undefined,
- minimum,
- maximum,
- viewportRatio = 0.5,
-}) {
- const [ref, { width }, node] = useDimensions();
- const contentSize = Math.round(width / viewportRatio);
-
- React.useEffect(() => {
- const position01 = (valueToSet - minimum) / (maximum - minimum + 1);
- const position = position01 * (contentSize - width);
- if (node) node.scrollLeft = Math.floor(position);
- }, [valueToSetDate]);
-
- const handleScroll = () => {
- const position = node.scrollLeft;
- const ratio = position / (contentSize - width);
- if (ratio < 0) return 0;
- let res = ratio * (maximum - minimum + 1) + minimum;
- onScroll(Math.floor(res + 0.3));
- };
-
- return (
-
-
-
- );
-}
-
-export function VerticalScrollBar({
- onScroll,
- valueToSet = undefined,
- valueToSetDate = undefined,
- minimum,
- maximum,
- viewportRatio = 0.5,
-}) {
- const [ref, { height }, node] = useDimensions();
- const contentSize = Math.round(height / viewportRatio);
-
- React.useEffect(() => {
- const position01 = (valueToSet - minimum) / (maximum - minimum + 1);
- const position = position01 * (contentSize - height);
- if (node) node.scrollTop = Math.floor(position);
- }, [valueToSetDate]);
-
- const handleScroll = () => {
- const position = node.scrollTop;
- const ratio = position / (contentSize - height);
- if (ratio < 0) return 0;
- let res = ratio * (maximum - minimum + 1) + minimum;
- onScroll(Math.floor(res + 0.3));
- };
-
- return (
-
-
-
- );
-}
-
-// export interface IScrollBarProps {
-// viewportRatio: number;
-// minimum: number;
-// maximum: number;
-// containerStyle: any;
-// onScroll?: any;
-// }
-
-// export abstract class ScrollBarBase extends React.Component {
-// domScrollContainer: Element;
-// domScrollContent: Element;
-// contentSize: number;
-// containerResizedBind: any;
-
-// constructor(props) {
-// super(props);
-// this.containerResizedBind = this.containerResized.bind(this);
-// }
-
-// componentDidMount() {
-// $(this.domScrollContainer).scroll(this.onScroll.bind(this));
-// createResizeDetector(this.domScrollContainer, this.containerResized.bind(this));
-// window.addEventListener('resize', this.containerResizedBind);
-// this.updateContentSize();
-// }
-
-// componentWillUnmount() {
-// deleteResizeDetector(this.domScrollContainer);
-// window.removeEventListener('resize', this.containerResizedBind);
-// }
-
-// onScroll() {
-// if (this.props.onScroll) {
-// this.props.onScroll(this.value);
-// }
-// }
-
-// get value(): number {
-// let position = this.getScrollPosition();
-// let ratio = position / (this.contentSize - this.getContainerSize());
-// if (ratio < 0) return 0;
-// let res = ratio * (this.props.maximum - this.props.minimum + 1) + this.props.minimum;
-// return Math.floor(res + 0.3);
-// }
-
-// set value(value: number) {
-// let position01 = (value - this.props.minimum) / (this.props.maximum - this.props.minimum + 1);
-// let position = position01 * (this.contentSize - this.getContainerSize());
-// this.setScrollPosition(Math.floor(position));
-// }
-
-// containerResized() {
-// this.setContentSizeField();
-// this.updateContentSize();
-// }
-
-// setContentSizeField() {
-// let lastContentSize = this.contentSize;
-// this.contentSize = Math.round(this.getContainerSize() / this.props.viewportRatio);
-// if (_.isNaN(this.contentSize)) this.contentSize = 0;
-// if (this.contentSize > 1000000 && detectBrowser() == BrowserType.Firefox) this.contentSize = 1000000;
-// if (lastContentSize != this.contentSize) {
-// this.updateContentSize();
-// }
-// }
-
-// abstract getContainerSize(): number;
-// abstract updateContentSize();
-// abstract getScrollPosition(): number;
-// abstract setScrollPosition(value: number);
-// }
-
-// export class HorizontalScrollBar extends ScrollBarBase {
-// render() {
-// this.setContentSizeField();
-
-// return this.domScrollContainer = x} style={this.props.containerStyle}>
-//
this.domScrollContent = x} style={{ width: this.contentSize }}>
-//
-//
-//
;
-// }
-
-// getContainerSize(): number {
-// return $(this.domScrollContainer).width();
-// }
-
-// updateContentSize() {
-// $(this.domScrollContent).width(this.contentSize);
-// }
-
-// getScrollPosition() {
-// return $(this.domScrollContainer).scrollLeft();
-// }
-
-// setScrollPosition(value: number) {
-// $(this.domScrollContainer).scrollLeft(value);
-// }
-// }
-
-// export class VerticalScrollBar extends ScrollBarBase {
-// render() {
-// this.setContentSizeField();
-
-// return this.domScrollContainer = x} style={this.props.containerStyle}>
-//
this.domScrollContent = x} style={{ height: this.contentSize }}>
-//
-//
-//
;
-// }
-
-// getContainerSize(): number {
-// return $(this.domScrollContainer).height();
-// }
-
-// updateContentSize() {
-// $(this.domScrollContent).height(this.contentSize);
-// }
-
-// getScrollPosition() {
-// return $(this.domScrollContainer).scrollTop();
-// }
-
-// setScrollPosition(value: number) {
-// $(this.domScrollContainer).scrollTop(value);
-// }
-// }
diff --git a/packages/web/src/datagrid/SeriesSizes-old.js b/packages/web/src/datagrid/SeriesSizes-old.js
deleted file mode 100644
index 6c8f98d85..000000000
--- a/packages/web/src/datagrid/SeriesSizes-old.js
+++ /dev/null
@@ -1,340 +0,0 @@
-import _ from 'lodash';
-
-export class SeriesSizeItem {
- constructor() {
- this.scrollIndex = -1;
- this.frozenIndex = -1;
- this.modelIndex = 0;
- this.size = 0;
- this.position = 0;
- }
-
- // modelIndex;
- // size;
- // position;
-
- get endPosition() {
- return this.position + this.size;
- }
-}
-
-export class SeriesSizes {
- constructor() {
- this.scrollItems = [];
- this.sizeOverridesByModelIndex = {};
- this.positions = [];
- this.scrollIndexes = [];
- this.frozenItems = [];
- this.hiddenAndFrozenModelIndexes = null;
- this.frozenModelIndexes = null;
-
- this.count = 0;
- this.maxSize = 1000;
- this.defaultSize = 50;
- }
-
- // private sizeOverridesByModelIndex: { [id] } = {};
- // count;
- // defaultSize;
- // maxSize;
- // private hiddenAndFrozenModelIndexes[] = [];
- // private frozenModelIndexes[] = [];
- // private hiddenModelIndexes[] = [];
- // private scrollItems: SeriesSizeItem[] = [];
- // private positions[] = [];
- // private scrollIndexes[] = [];
- // private frozenItems: SeriesSizeItem[] = [];
-
- get scrollCount() {
- return this.count - (this.hiddenAndFrozenModelIndexes != null ? this.hiddenAndFrozenModelIndexes.length : 0);
- }
- get frozenCount() {
- return this.frozenModelIndexes != null ? this.frozenModelIndexes.length : 0;
- }
- get frozenSize() {
- return _.sumBy(this.frozenItems, x => x.size);
- }
- get realCount() {
- return this.frozenCount + this.scrollCount;
- }
-
- putSizeOverride(modelIndex, size, sizeByUser = false) {
- if (this.maxSize && size > this.maxSize && !sizeByUser) {
- size = this.maxSize;
- }
-
- let currentSize = this.sizeOverridesByModelIndex[modelIndex];
- if (sizeByUser || !currentSize || size > currentSize) {
- this.sizeOverridesByModelIndex[modelIndex] = size;
- }
- // if (!_.has(this.sizeOverridesByModelIndex, modelIndex))
- // this.sizeOverridesByModelIndex[modelIndex] = size;
- // if (size > this.sizeOverridesByModelIndex[modelIndex])
- // this.sizeOverridesByModelIndex[modelIndex] = size;
- }
- buildIndex() {
- this.scrollItems = [];
- this.scrollIndexes = _.filter(
- _.map(this.intKeys(this.sizeOverridesByModelIndex), x => this.modelToReal(x) - this.frozenCount),
- x => x >= 0
- );
- this.scrollIndexes.sort();
- let lastScrollIndex = -1;
- let lastEndPosition = 0;
- this.scrollIndexes.forEach(scrollIndex => {
- let modelIndex = this.realToModel(scrollIndex + this.frozenCount);
- let size = this.sizeOverridesByModelIndex[modelIndex];
- let item = new SeriesSizeItem();
- item.scrollIndex = scrollIndex;
- item.modelIndex = modelIndex;
- item.size = size;
- item.position = lastEndPosition + (scrollIndex - lastScrollIndex - 1) * this.defaultSize;
- this.scrollItems.push(item);
- lastScrollIndex = scrollIndex;
- lastEndPosition = item.endPosition;
- });
- this.positions = _.map(this.scrollItems, x => x.position);
- this.frozenItems = [];
- let lastpos = 0;
- for (let i = 0; i < this.frozenCount; i++) {
- let modelIndex = this.frozenModelIndexes[i];
- let size = this.getSizeByModelIndex(modelIndex);
- let item = new SeriesSizeItem();
- item.frozenIndex = i;
- item.modelIndex = modelIndex;
- item.size = size;
- item.position = lastpos;
- this.frozenItems.push(item);
- lastpos += size;
- }
- }
-
- getScrollIndexOnPosition(position) {
- let itemOrder = _.sortedIndex(this.positions, position);
- if (this.positions[itemOrder] == position) return itemOrder;
- if (itemOrder == 0) return Math.floor(position / this.defaultSize);
- if (position <= this.scrollItems[itemOrder - 1].endPosition) return this.scrollItems[itemOrder - 1].scrollIndex;
- return (
- Math.floor((position - this.scrollItems[itemOrder - 1].position) / this.defaultSize) +
- this.scrollItems[itemOrder - 1].scrollIndex
- );
- }
- getFrozenIndexOnPosition(position) {
- this.frozenItems.forEach(function (item) {
- if (position >= item.position && position <= item.endPosition) return item.frozenIndex;
- });
- return -1;
- }
- // getSizeSum(startScrollIndex, endScrollIndex) {
- // let order1 = _.sortedIndexOf(this.scrollIndexes, startScrollIndex);
- // let order2 = _.sortedIndexOf(this.scrollIndexes, endScrollIndex);
- // let count = endScrollIndex - startScrollIndex;
- // if (order1 < 0)
- // order1 = ~order1;
- // if (order2 < 0)
- // order2 = ~order2;
- // let result = 0;
- // for (let i = order1; i <= order2; i++) {
- // if (i < 0)
- // continue;
- // if (i >= this.scrollItems.length)
- // continue;
- // let item = this.scrollItems[i];
- // if (item.scrollIndex < startScrollIndex)
- // continue;
- // if (item.scrollIndex >= endScrollIndex)
- // continue;
- // result += item.size;
- // count--;
- // }
- // result += count * this.defaultSize;
- // return result;
- // }
- getSizeByModelIndex(modelIndex) {
- if (_.has(this.sizeOverridesByModelIndex, modelIndex)) return this.sizeOverridesByModelIndex[modelIndex];
- return this.defaultSize;
- }
- getSizeByScrollIndex(scrollIndex) {
- return this.getSizeByRealIndex(scrollIndex + this.frozenCount);
- }
- getSizeByRealIndex(realIndex) {
- let modelIndex = this.realToModel(realIndex);
- return this.getSizeByModelIndex(modelIndex);
- }
- removeSizeOverride(realIndex) {
- let modelIndex = this.realToModel(realIndex);
- delete this.sizeOverridesByModelIndex[modelIndex];
- }
- getScroll(sourceScrollIndex, targetScrollIndex) {
- if (sourceScrollIndex < targetScrollIndex) {
- return -_.sum(
- _.map(_.range(sourceScrollIndex, targetScrollIndex - sourceScrollIndex), x => this.getSizeByScrollIndex(x))
- );
- } else {
- return _.sum(
- _.map(_.range(targetScrollIndex, sourceScrollIndex - targetScrollIndex), x => this.getSizeByScrollIndex(x))
- );
- }
- }
- modelIndexIsInScrollArea(modelIndex) {
- let realIndex = this.modelToReal(modelIndex);
- return realIndex >= this.frozenCount;
- }
- getTotalScrollSizeSum() {
- let scrollSizeOverrides = _.map(
- _.filter(this.intKeys(this.sizeOverridesByModelIndex), x => this.modelIndexIsInScrollArea(x)),
- x => this.sizeOverridesByModelIndex[x]
- );
- return _.sum(scrollSizeOverrides) + (this.count - scrollSizeOverrides.length) * this.defaultSize;
- }
- getVisibleScrollSizeSum() {
- let scrollSizeOverrides = _.map(
- _.filter(this.intKeys(this.sizeOverridesByModelIndex), x => !_.includes(this.hiddenAndFrozenModelIndexes, x)),
- x => this.sizeOverridesByModelIndex[x]
- );
- return (
- _.sum(scrollSizeOverrides) +
- (this.count - this.hiddenModelIndexes.length - scrollSizeOverrides.length) * this.defaultSize
- );
- }
- intKeys(value) {
- return _.keys(value).map(x => _.parseInt(x));
- }
- getPositionByRealIndex(realIndex) {
- if (realIndex < 0) return 0;
- if (realIndex < this.frozenCount) return this.frozenItems[realIndex].position;
- return this.getPositionByScrollIndex(realIndex - this.frozenCount);
- }
- getPositionByScrollIndex(scrollIndex) {
- let order = _.sortedIndex(this.scrollIndexes, scrollIndex);
- if (this.scrollIndexes[order] == scrollIndex) return this.scrollItems[order].position;
- order--;
- if (order < 0) return scrollIndex * this.defaultSize;
- return (
- this.scrollItems[order].endPosition + (scrollIndex - this.scrollItems[order].scrollIndex - 1) * this.defaultSize
- );
- }
- getVisibleScrollCount(firstVisibleIndex, viewportSize) {
- let res = 0;
- let index = firstVisibleIndex;
- let count = 0;
- while (res < viewportSize && index <= this.scrollCount) {
- // console.log('this.getSizeByScrollIndex(index)', this.getSizeByScrollIndex(index));
- res += this.getSizeByScrollIndex(index);
- index++;
- count++;
- }
- // console.log('getVisibleScrollCount', firstVisibleIndex, viewportSize, count);
- return count;
- }
- getVisibleScrollCountReversed(lastVisibleIndex, viewportSize) {
- let res = 0;
- let index = lastVisibleIndex;
- let count = 0;
- while (res < viewportSize && index >= 0) {
- res += this.getSizeByScrollIndex(index);
- index--;
- count++;
- }
- return count;
- }
- invalidateAfterScroll(oldFirstVisible, newFirstVisible, invalidate, viewportSize) {
- if (newFirstVisible > oldFirstVisible) {
- let oldVisibleCount = this.getVisibleScrollCount(oldFirstVisible, viewportSize);
- let newVisibleCount = this.getVisibleScrollCount(newFirstVisible, viewportSize);
- for (let i = oldFirstVisible + oldVisibleCount - 1; i <= newFirstVisible + newVisibleCount; i++) {
- invalidate(i + this.frozenCount);
- }
- } else {
- for (let i = newFirstVisible; i <= oldFirstVisible; i++) {
- invalidate(i + this.frozenCount);
- }
- }
- }
- isWholeInView(firstVisibleIndex, index, viewportSize) {
- let res = 0;
- let testedIndex = firstVisibleIndex;
- while (res < viewportSize && testedIndex < this.count) {
- res += this.getSizeByScrollIndex(testedIndex);
- if (testedIndex == index) return res <= viewportSize;
- testedIndex++;
- }
- return false;
- }
- scrollInView(firstVisibleIndex, scrollIndex, viewportSize) {
- if (this.isWholeInView(firstVisibleIndex, scrollIndex, viewportSize)) {
- return firstVisibleIndex;
- }
- if (scrollIndex < firstVisibleIndex) {
- return scrollIndex;
- }
- let res = 0;
- let testedIndex = scrollIndex;
- while (res < viewportSize && testedIndex >= 0) {
- let size = this.getSizeByScrollIndex(testedIndex);
- if (res + size > viewportSize) return testedIndex + 1;
- testedIndex--;
- res += size;
- }
- if (res >= viewportSize && testedIndex < scrollIndex) return testedIndex + 1;
- return firstVisibleIndex;
- }
- resize(realIndex, newSize) {
- if (realIndex < 0) return;
- let modelIndex = this.realToModel(realIndex);
- if (modelIndex < 0) return;
- this.sizeOverridesByModelIndex[modelIndex] = newSize;
- this.buildIndex();
- }
- setExtraordinaryIndexes(hidden, frozen) {
- //this._hiddenAndFrozenModelIndexes = _.clone(hidden);
- hidden = hidden.filter(x => x >= 0);
- frozen = frozen.filter(x => x >= 0);
-
- hidden.sort((a, b) => a - b);
- frozen.sort((a, b) => a - b);
- this.frozenModelIndexes = _.filter(frozen, x => !_.includes(hidden, x));
- this.hiddenModelIndexes = _.filter(hidden, x => !_.includes(frozen, x));
- this.hiddenAndFrozenModelIndexes = _.concat(hidden, this.frozenModelIndexes);
- this.frozenModelIndexes.sort((a, b) => a - b);
- if (this.hiddenAndFrozenModelIndexes.length == 0) this.hiddenAndFrozenModelIndexes = null;
- if (this.frozenModelIndexes.length == 0) this.frozenModelIndexes = null;
- this.buildIndex();
- }
- realToModel(realIndex) {
- if (this.hiddenAndFrozenModelIndexes == null && this.frozenModelIndexes == null) return realIndex;
- if (realIndex < 0) return -1;
- if (realIndex < this.frozenCount && this.frozenModelIndexes != null) return this.frozenModelIndexes[realIndex];
- if (this.hiddenAndFrozenModelIndexes == null) return realIndex;
- realIndex -= this.frozenCount;
- for (let hidItem of this.hiddenAndFrozenModelIndexes) {
- if (realIndex < hidItem) return realIndex;
- realIndex++;
- }
- return realIndex;
- }
- modelToReal(modelIndex) {
- if (this.hiddenAndFrozenModelIndexes == null && this.frozenModelIndexes == null) return modelIndex;
- if (modelIndex < 0) return -1;
- let frozenIndex = this.frozenModelIndexes != null ? _.indexOf(this.frozenModelIndexes, modelIndex) : -1;
- if (frozenIndex >= 0) return frozenIndex;
- if (this.hiddenAndFrozenModelIndexes == null) return modelIndex;
- let hiddenIndex = _.sortedIndex(this.hiddenAndFrozenModelIndexes, modelIndex);
- if (this.hiddenAndFrozenModelIndexes[hiddenIndex] == modelIndex) return -1;
- if (hiddenIndex >= 0) return modelIndex - hiddenIndex + this.frozenCount;
- return modelIndex;
- }
- getFrozenPosition(frozenIndex) {
- return this.frozenItems[frozenIndex].position;
- }
- hasSizeOverride(modelIndex) {
- return _.has(this.sizeOverridesByModelIndex, modelIndex);
- }
- isVisible(testedRealIndex, firstVisibleScrollIndex, viewportSize) {
- if (testedRealIndex < 0) return false;
- if (testedRealIndex >= 0 && testedRealIndex < this.frozenCount) return true;
- let scrollIndex = testedRealIndex - this.frozenCount;
- let onPageIndex = scrollIndex - firstVisibleScrollIndex;
- return onPageIndex >= 0 && onPageIndex < this.getVisibleScrollCount(firstVisibleScrollIndex, viewportSize);
- }
-}
diff --git a/packages/web/src/datagrid/SeriesSizes.ts b/packages/web/src/datagrid/SeriesSizes.ts
deleted file mode 100644
index f221a4c56..000000000
--- a/packages/web/src/datagrid/SeriesSizes.ts
+++ /dev/null
@@ -1,341 +0,0 @@
-import _ from 'lodash';
-
-export class SeriesSizeItem {
- public scrollIndex: number = -1;
- public modelIndex: number;
- public frozenIndex: number = -1;
- public size: number;
- public position: number;
- public get endPosition(): number {
- return this.position + this.size;
- }
-}
-
-export class SeriesSizes {
- private sizeOverridesByModelIndex: { [id: number]: number } = {};
- public count: number = 0;
- public defaultSize: number = 50;
- public maxSize: number = 1000;
- private hiddenAndFrozenModelIndexes: number[] = [];
- private frozenModelIndexes: number[] = [];
- private hiddenModelIndexes: number[] = [];
- private scrollItems: SeriesSizeItem[] = [];
- private positions: number[] = [];
- private scrollIndexes: number[] = [];
- private frozenItems: SeriesSizeItem[] = [];
-
- public get scrollCount(): number {
- return this.count - (this.hiddenAndFrozenModelIndexes != null ? this.hiddenAndFrozenModelIndexes.length : 0);
- }
- public get frozenCount(): number {
- return this.frozenModelIndexes != null ? this.frozenModelIndexes.length : 0;
- }
- public get frozenSize(): number {
- return _.sumBy(this.frozenItems, x => x.size);
- }
- public get realCount(): number {
- return this.frozenCount + this.scrollCount;
- }
-
- // public clear(): void {
- // this.scrollItems = [];
- // this.sizeOverridesByModelIndex = {};
- // this.positions = [];
- // this.scrollIndexes = [];
- // this.frozenItems = [];
- // this.hiddenAndFrozenModelIndexes = null;
- // this.frozenModelIndexes = null;
- // }
- public putSizeOverride(modelIndex: number, size: number, sizeByUser = false): void {
- if (this.maxSize && size > this.maxSize && !sizeByUser) {
- size = this.maxSize;
- }
-
- let currentSize = this.sizeOverridesByModelIndex[modelIndex];
- if (sizeByUser || !currentSize || size > currentSize) {
- this.sizeOverridesByModelIndex[modelIndex] = size;
- }
- // if (!_.has(this.sizeOverridesByModelIndex, modelIndex))
- // this.sizeOverridesByModelIndex[modelIndex] = size;
- // if (size > this.sizeOverridesByModelIndex[modelIndex])
- // this.sizeOverridesByModelIndex[modelIndex] = size;
- }
- public buildIndex(): void {
- this.scrollItems = [];
- this.scrollIndexes = _.filter(
- _.map(_.range(this.count), x => this.modelToReal(x) - this.frozenCount),
- // _.map(this.intKeys(_.keys(this.sizeOverridesByModelIndex)), (x) => this.modelToReal(x) - this.frozenCount),
- x => x >= 0
- );
- this.scrollIndexes.sort();
- let lastScrollIndex: number = -1;
- let lastEndPosition: number = 0;
- this.scrollIndexes.forEach(scrollIndex => {
- let modelIndex: number = this.realToModel(scrollIndex + this.frozenCount);
- let size: number = this.sizeOverridesByModelIndex[modelIndex];
- let item = new SeriesSizeItem();
- item.scrollIndex = scrollIndex;
- item.modelIndex = modelIndex;
- item.size = size;
- item.position = lastEndPosition + (scrollIndex - lastScrollIndex - 1) * this.defaultSize;
- this.scrollItems.push(item);
- lastScrollIndex = scrollIndex;
- lastEndPosition = item.endPosition;
- });
- this.positions = _.map(this.scrollItems, x => x.position);
- this.frozenItems = [];
- let lastpos: number = 0;
- for (let i: number = 0; i < this.frozenCount; i++) {
- let modelIndex: number = this.frozenModelIndexes[i];
- let size: number = this.getSizeByModelIndex(modelIndex);
- let item = new SeriesSizeItem();
- item.frozenIndex = i;
- item.modelIndex = modelIndex;
- item.size = size;
- item.position = lastpos;
- this.frozenItems.push(item);
- lastpos += size;
- }
- }
-
- public getScrollIndexOnPosition(position: number): number {
- let itemOrder: number = _.sortedIndex(this.positions, position);
- if (this.positions[itemOrder] == position) return itemOrder;
- if (itemOrder == 0) return Math.floor(position / this.defaultSize);
- if (position <= this.scrollItems[itemOrder - 1].endPosition) return this.scrollItems[itemOrder - 1].scrollIndex;
- return (
- Math.floor((position - this.scrollItems[itemOrder - 1].position) / this.defaultSize) +
- this.scrollItems[itemOrder - 1].scrollIndex
- );
- }
- public getFrozenIndexOnPosition(position: number): number {
- this.frozenItems.forEach(function (item) {
- if (position >= item.position && position <= item.endPosition) return item.frozenIndex;
- });
- return -1;
- }
- // public getSizeSum(startScrollIndex: number, endScrollIndex: number): number {
- // let order1: number = _.sortedIndexOf(this.scrollIndexes, startScrollIndex);
- // let order2: number = _.sortedIndexOf(this.scrollIndexes, endScrollIndex);
- // let count: number = endScrollIndex - startScrollIndex;
- // if (order1 < 0)
- // order1 = ~order1;
- // if (order2 < 0)
- // order2 = ~order2;
- // let result: number = 0;
- // for (let i: number = order1; i <= order2; i++) {
- // if (i < 0)
- // continue;
- // if (i >= this.scrollItems.length)
- // continue;
- // let item = this.scrollItems[i];
- // if (item.scrollIndex < startScrollIndex)
- // continue;
- // if (item.scrollIndex >= endScrollIndex)
- // continue;
- // result += item.size;
- // count--;
- // }
- // result += count * this.defaultSize;
- // return result;
- // }
- public getSizeByModelIndex(modelIndex: number): number {
- if (_.has(this.sizeOverridesByModelIndex, modelIndex)) return this.sizeOverridesByModelIndex[modelIndex];
- return this.defaultSize;
- }
- public getSizeByScrollIndex(scrollIndex: number): number {
- return this.getSizeByRealIndex(scrollIndex + this.frozenCount);
- }
- public getSizeByRealIndex(realIndex: number): number {
- let modelIndex: number = this.realToModel(realIndex);
- return this.getSizeByModelIndex(modelIndex);
- }
- public removeSizeOverride(realIndex: number): void {
- let modelIndex: number = this.realToModel(realIndex);
- delete this.sizeOverridesByModelIndex[modelIndex];
- }
- public getScroll(sourceScrollIndex: number, targetScrollIndex: number): number {
- if (sourceScrollIndex < targetScrollIndex) {
- return -_.sum(
- _.map(_.range(sourceScrollIndex, targetScrollIndex - sourceScrollIndex), x => this.getSizeByScrollIndex(x))
- );
- } else {
- return _.sum(
- _.map(_.range(targetScrollIndex, sourceScrollIndex - targetScrollIndex), x => this.getSizeByScrollIndex(x))
- );
- }
- }
- public modelIndexIsInScrollArea(modelIndex: number): boolean {
- let realIndex = this.modelToReal(modelIndex);
- return realIndex >= this.frozenCount;
- }
- public getTotalScrollSizeSum(): number {
- let scrollSizeOverrides = _.map(
- _.filter(this.intKeys(this.sizeOverridesByModelIndex), x => this.modelIndexIsInScrollArea(x)),
- x => this.sizeOverridesByModelIndex[x]
- );
- return _.sum(scrollSizeOverrides) + (this.count - scrollSizeOverrides.length) * this.defaultSize;
- }
- public getVisibleScrollSizeSum(): number {
- let scrollSizeOverrides = _.map(
- _.filter(this.intKeys(this.sizeOverridesByModelIndex), x => !_.includes(this.hiddenAndFrozenModelIndexes, x)),
- x => this.sizeOverridesByModelIndex[x]
- );
- return (
- _.sum(scrollSizeOverrides) +
- (this.count - this.hiddenModelIndexes.length - scrollSizeOverrides.length) * this.defaultSize
- );
- }
- private intKeys(value): number[] {
- return _.keys(value).map(x => _.parseInt(x));
- }
- public getPositionByRealIndex(realIndex: number): number {
- if (realIndex < 0) return 0;
- if (realIndex < this.frozenCount) return this.frozenItems[realIndex].position;
- return this.getPositionByScrollIndex(realIndex - this.frozenCount);
- }
- public getPositionByScrollIndex(scrollIndex: number): number {
- let order: number = _.sortedIndex(this.scrollIndexes, scrollIndex);
- if (this.scrollIndexes[order] == scrollIndex) return this.scrollItems[order].position;
- order--;
- if (order < 0) return scrollIndex * this.defaultSize;
- return (
- this.scrollItems[order].endPosition + (scrollIndex - this.scrollItems[order].scrollIndex - 1) * this.defaultSize
- );
- }
- public getVisibleScrollCount(firstVisibleIndex: number, viewportSize: number): number {
- let res: number = 0;
- let index: number = firstVisibleIndex;
- let count: number = 0;
- while (res < viewportSize && index <= this.scrollCount) {
- res += this.getSizeByScrollIndex(index);
- index++;
- count++;
- }
- return count;
- }
- public getVisibleScrollCountReversed(lastVisibleIndex: number, viewportSize: number): number {
- let res: number = 0;
- let index: number = lastVisibleIndex;
- let count: number = 0;
- while (res < viewportSize && index >= 0) {
- res += this.getSizeByScrollIndex(index);
- index--;
- count++;
- }
- return count;
- }
- public invalidateAfterScroll(
- oldFirstVisible: number,
- newFirstVisible: number,
- invalidate: (_: number) => void,
- viewportSize: number
- ): void {
- if (newFirstVisible > oldFirstVisible) {
- let oldVisibleCount: number = this.getVisibleScrollCount(oldFirstVisible, viewportSize);
- let newVisibleCount: number = this.getVisibleScrollCount(newFirstVisible, viewportSize);
- for (let i: number = oldFirstVisible + oldVisibleCount - 1; i <= newFirstVisible + newVisibleCount; i++) {
- invalidate(i + this.frozenCount);
- }
- } else {
- for (let i: number = newFirstVisible; i <= oldFirstVisible; i++) {
- invalidate(i + this.frozenCount);
- }
- }
- }
- public isWholeInView(firstVisibleIndex: number, index: number, viewportSize: number): boolean {
- let res: number = 0;
- let testedIndex: number = firstVisibleIndex;
- while (res < viewportSize && testedIndex < this.count) {
- res += this.getSizeByScrollIndex(testedIndex);
- if (testedIndex == index) return res <= viewportSize;
- testedIndex++;
- }
- return false;
- }
- public scrollInView(firstVisibleIndex: number, scrollIndex: number, viewportSize: number): number {
- if (this.isWholeInView(firstVisibleIndex, scrollIndex, viewportSize)) {
- return firstVisibleIndex;
- }
- if (scrollIndex < firstVisibleIndex) {
- return scrollIndex;
- }
- let testedIndex = firstVisibleIndex + 1;
- while (testedIndex < this.scrollCount) {
- if (this.isWholeInView(testedIndex, scrollIndex, viewportSize)) {
- return testedIndex;
- }
- testedIndex++;
- }
- return this.scrollCount - 1;
-
- // let res: number = 0;
- // let testedIndex: number = scrollIndex;
- // while (res < viewportSize && testedIndex >= 0) {
- // let size: number = this.getSizeByScrollIndex(testedIndex);
- // if (res + size > viewportSize) return testedIndex + 1;
- // testedIndex--;
- // res += size;
- // }
- // if (res >= viewportSize && testedIndex < scrollIndex) return testedIndex + 1;
- // return firstVisibleIndex;
- }
- public resize(realIndex: number, newSize: number): void {
- if (realIndex < 0) return;
- let modelIndex: number = this.realToModel(realIndex);
- if (modelIndex < 0) return;
- this.sizeOverridesByModelIndex[modelIndex] = newSize;
- this.buildIndex();
- }
- public setExtraordinaryIndexes(hidden: number[], frozen: number[]): void {
- //this._hiddenAndFrozenModelIndexes = _.clone(hidden);
- hidden = hidden.filter(x => x >= 0);
- frozen = frozen.filter(x => x >= 0);
-
- hidden.sort((a, b) => a - b);
- frozen.sort((a, b) => a - b);
- this.frozenModelIndexes = _.filter(frozen, x => !_.includes(hidden, x));
- this.hiddenModelIndexes = _.filter(hidden, x => !_.includes(frozen, x));
- this.hiddenAndFrozenModelIndexes = _.concat(hidden, this.frozenModelIndexes);
- this.frozenModelIndexes.sort((a, b) => a - b);
- if (this.hiddenAndFrozenModelIndexes.length == 0) this.hiddenAndFrozenModelIndexes = null;
- if (this.frozenModelIndexes.length == 0) this.frozenModelIndexes = null;
- this.buildIndex();
- }
- public realToModel(realIndex: number): number {
- if (this.hiddenAndFrozenModelIndexes == null && this.frozenModelIndexes == null) return realIndex;
- if (realIndex < 0) return -1;
- if (realIndex < this.frozenCount && this.frozenModelIndexes != null) return this.frozenModelIndexes[realIndex];
- if (this.hiddenAndFrozenModelIndexes == null) return realIndex;
- realIndex -= this.frozenCount;
- for (let hidItem of this.hiddenAndFrozenModelIndexes) {
- if (realIndex < hidItem) return realIndex;
- realIndex++;
- }
- return realIndex;
- }
- public modelToReal(modelIndex: number): number {
- if (this.hiddenAndFrozenModelIndexes == null && this.frozenModelIndexes == null) return modelIndex;
- if (modelIndex < 0) return -1;
- let frozenIndex: number = this.frozenModelIndexes != null ? _.indexOf(this.frozenModelIndexes, modelIndex) : -1;
- if (frozenIndex >= 0) return frozenIndex;
- if (this.hiddenAndFrozenModelIndexes == null) return modelIndex;
- let hiddenIndex: number = _.sortedIndex(this.hiddenAndFrozenModelIndexes, modelIndex);
- if (this.hiddenAndFrozenModelIndexes[hiddenIndex] == modelIndex) return -1;
- if (hiddenIndex >= 0) return modelIndex - hiddenIndex + this.frozenCount;
- return modelIndex;
- }
- public getFrozenPosition(frozenIndex: number): number {
- return this.frozenItems[frozenIndex].position;
- }
- public hasSizeOverride(modelIndex: number): boolean {
- return _.has(this.sizeOverridesByModelIndex, modelIndex);
- }
- public isVisible(testedRealIndex: number, firstVisibleScrollIndex: number, viewportSize: number): boolean {
- if (testedRealIndex < 0) return false;
- if (testedRealIndex >= 0 && testedRealIndex < this.frozenCount) return true;
- let scrollIndex: number = testedRealIndex - this.frozenCount;
- let onPageIndex: number = scrollIndex - firstVisibleScrollIndex;
- return onPageIndex >= 0 && onPageIndex < this.getVisibleScrollCount(firstVisibleScrollIndex, viewportSize);
- }
-}
diff --git a/packages/web/src/datagrid/SqlDataGridCore.js b/packages/web/src/datagrid/SqlDataGridCore.js
deleted file mode 100644
index fd3fc60af..000000000
--- a/packages/web/src/datagrid/SqlDataGridCore.js
+++ /dev/null
@@ -1,177 +0,0 @@
-import React from 'react';
-import axios from '../utility/axios';
-import { useSetOpenedTabs } from '../utility/globalState';
-import DataGridCore from './DataGridCore';
-import useSocket from '../utility/SocketProvider';
-import useShowModal from '../modals/showModal';
-import ImportExportModal from '../modals/ImportExportModal';
-import { changeSetToSql, createChangeSet, getChangeSetInsertedRows } from 'dbgate-datalib';
-import LoadingDataGridCore from './LoadingDataGridCore';
-import ChangeSetGrider from './ChangeSetGrider';
-import { scriptToSql } from 'dbgate-sqltree';
-import useModalState from '../modals/useModalState';
-import ConfirmSqlModal from '../modals/ConfirmSqlModal';
-import ErrorMessageModal from '../modals/ErrorMessageModal';
-import useOpenNewTab from '../utility/useOpenNewTab';
-
-/** @param props {import('./types').DataGridProps} */
-async function loadDataPage(props, offset, limit) {
- const { display, conid, database } = props;
-
- const sql = display.getPageQuery(offset, limit);
-
- const response = await axios.request({
- url: 'database-connections/query-data',
- method: 'post',
- params: {
- conid,
- database,
- },
- data: { sql },
- });
-
- if (response.data.errorMessage) return response.data;
- return response.data.rows;
-}
-
-function dataPageAvailable(props) {
- const { display } = props;
- const sql = display.getPageQuery(0, 1);
- return !!sql;
-}
-
-async function loadRowCount(props) {
- const { display, conid, database } = props;
-
- const sql = display.getCountQuery();
-
- const response = await axios.request({
- url: 'database-connections/query-data',
- method: 'post',
- params: {
- conid,
- database,
- },
- data: { sql },
- });
-
- return parseInt(response.data.rows[0].count);
-}
-
-/** @param props {import('./types').DataGridProps} */
-export default function SqlDataGridCore(props) {
- const { conid, database, display, changeSetState, dispatchChangeSet } = props;
- const showModal = useShowModal();
- const openNewTab = useOpenNewTab();
-
- const confirmSqlModalState = useModalState();
- const [confirmSql, setConfirmSql] = React.useState('');
-
- const changeSet = changeSetState && changeSetState.value;
- const changeSetRef = React.useRef(changeSet);
- changeSetRef.current = changeSet;
-
- function exportGrid() {
- const initialValues = {};
- initialValues.sourceStorageType = 'query';
- initialValues.sourceConnectionId = conid;
- initialValues.sourceDatabaseName = database;
- initialValues.sourceSql = display.getExportQuery();
- initialValues.sourceList = display.baseTable ? [display.baseTable.pureName] : [];
- showModal(modalState => );
- }
- function openActiveChart() {
- openNewTab(
- {
- title: 'Chart #',
- icon: 'img chart',
- tabComponent: 'ChartTab',
- props: {
- conid,
- database,
- },
- },
- {
- editor: {
- config: { chartType: 'bar' },
- sql: display.getExportQuery(select => {
- select.orderBy = null;
- }),
- },
- }
- );
- }
- function openQuery() {
- openNewTab(
- {
- title: 'Query #',
- icon: 'img sql-file',
- tabComponent: 'QueryTab',
- props: {
- schemaName: display.baseTable.schemaName,
- pureName: display.baseTable.pureName,
- conid,
- database,
- },
- },
- {
- editor: display.getExportQuery(),
- }
- );
- }
-
- function handleSave() {
- const script = changeSetToSql(changeSetRef.current, display.dbinfo);
- const sql = scriptToSql(display.driver, script);
- setConfirmSql(sql);
- confirmSqlModalState.open();
- }
-
- async function handleConfirmSql() {
- const resp = await axios.request({
- url: 'database-connections/query-data',
- method: 'post',
- params: {
- conid,
- database,
- },
- data: { sql: confirmSql },
- });
- const { errorMessage } = resp.data || {};
- if (errorMessage) {
- showModal(modalState => (
-
- ));
- } else {
- dispatchChangeSet({ type: 'reset', value: createChangeSet() });
- setConfirmSql(null);
- display.reload();
- }
- }
-
- // const grider = React.useMemo(()=>new ChangeSetGrider())
-
- return (
- <>
-
-
- >
- );
-}
diff --git a/packages/web/src/datagrid/TableDataGrid.js b/packages/web/src/datagrid/TableDataGrid.js
deleted file mode 100644
index e7ab591e8..000000000
--- a/packages/web/src/datagrid/TableDataGrid.js
+++ /dev/null
@@ -1,232 +0,0 @@
-import React from 'react';
-import _ from 'lodash';
-import DataGrid from './DataGrid';
-import styled from 'styled-components';
-import { TableGridDisplay, TableFormViewDisplay, createGridConfig, createGridCache } from 'dbgate-datalib';
-import { getFilterValueExpression } from 'dbgate-filterparser';
-import { findEngineDriver } from 'dbgate-tools';
-import { useConnectionInfo, getTableInfo, useDatabaseInfo } from '../utility/metadataLoaders';
-import useSocket from '../utility/SocketProvider';
-import { VerticalSplitter } from '../widgets/Splitter';
-import stableStringify from 'json-stable-stringify';
-import ReferenceHeader from './ReferenceHeader';
-import SqlDataGridCore from './SqlDataGridCore';
-import useExtensions from '../utility/useExtensions';
-import SqlFormView from '../formview/SqlFormView';
-
-const ReferenceContainer = styled.div`
- position: absolute;
- display: flex;
- flex-direction: column;
- top: 0;
- left: 0;
- right: 0;
- bottom: 0;
-`;
-
-const ReferenceGridWrapper = styled.div`
- position: relative;
- flex: 1;
- display: flex;
-`;
-
-export default function TableDataGrid({
- conid,
- database,
- schemaName,
- pureName,
- tabVisible,
- toolbarPortalRef,
- changeSetState,
- dispatchChangeSet,
- config = undefined,
- setConfig = undefined,
- cache = undefined,
- setCache = undefined,
- masterLoadedTime = undefined,
- isDetailView = false,
-}) {
- // const [childConfig, setChildConfig] = React.useState(createGridConfig());
- const [myCache, setMyCache] = React.useState(createGridCache());
- const [childCache, setChildCache] = React.useState(createGridCache());
- const [refReloadToken, setRefReloadToken] = React.useState(0);
- const [myLoadedTime, setMyLoadedTime] = React.useState(0);
- const extensions = useExtensions();
-
- const { childConfig } = config;
- const setChildConfig = (value, reference = undefined) => {
- if (_.isFunction(value)) {
- setConfig(x => ({
- ...x,
- childConfig: value(x.childConfig),
- }));
- } else {
- setConfig(x => ({
- ...x,
- childConfig: value,
- reference: reference === undefined ? x.reference : reference,
- }));
- }
- };
- const { reference } = config;
-
- const connection = useConnectionInfo({ conid });
- const dbinfo = useDatabaseInfo({ conid, database });
- // const [reference, setReference] = React.useState(null);
-
- function createDisplay() {
- return connection
- ? new TableGridDisplay(
- { schemaName, pureName },
- findEngineDriver(connection, extensions),
- config,
- setConfig,
- cache || myCache,
- setCache || setMyCache,
- dbinfo
- )
- : null;
- }
-
- function createFormDisplay() {
- return connection
- ? new TableFormViewDisplay(
- { schemaName, pureName },
- findEngineDriver(connection, extensions),
- config,
- setConfig,
- cache || myCache,
- setCache || setMyCache,
- dbinfo
- )
- : null;
- }
-
- const [display, setDisplay] = React.useState(createDisplay());
- const [formDisplay, setFormDisplay] = React.useState(createFormDisplay());
-
- React.useEffect(() => {
- setRefReloadToken(v => v + 1);
- if (!reference && display && display.isGrouped) display.clearGrouping();
- }, [reference]);
-
- React.useEffect(() => {
- const newDisplay = createDisplay();
- if (!newDisplay) return;
- if (display && display.isLoadedCorrectly && !newDisplay.isLoadedCorrectly) return;
- setDisplay(newDisplay);
- }, [connection, config, cache || myCache, conid, database, schemaName, pureName, dbinfo, extensions]);
-
- React.useEffect(() => {
- const newDisplay = createFormDisplay();
- if (!newDisplay) return;
- if (formDisplay && formDisplay.isLoadedCorrectly && !newDisplay.isLoadedCorrectly) return;
- setFormDisplay(newDisplay);
- }, [connection, config, cache || myCache, conid, database, schemaName, pureName, dbinfo, extensions]);
-
- const handleDatabaseStructureChanged = React.useCallback(() => {
- (setCache || setMyCache)(createGridCache());
- }, []);
-
- const socket = useSocket();
-
- React.useEffect(() => {
- if (display && !display.isLoadedCorrectly) {
- if (conid && socket) {
- socket.on(`database-structure-changed-${conid}-${database}`, handleDatabaseStructureChanged);
- return () => {
- socket.off(`database-structure-changed-${conid}-${database}`, handleDatabaseStructureChanged);
- };
- }
- }
- }, [conid, database, display]);
-
- const handleReferenceSourceChanged = React.useCallback(
- (selectedRows, loadedTime) => {
- setMyLoadedTime(loadedTime);
- if (!reference) return;
-
- const filtersBase = display && display.isGrouped ? config.filters : childConfig.filters;
-
- const filters = {
- ...filtersBase,
- ..._.fromPairs(
- reference.columns.map(col => [
- col.refName,
- selectedRows.map(x => getFilterValueExpression(x[col.baseName], col.dataType)).join(', '),
- ])
- ),
- };
- if (stableStringify(filters) != stableStringify(childConfig.filters)) {
- setChildConfig(cfg => ({
- ...cfg,
- filters,
- }));
- setChildCache(ca => ({
- ...ca,
- refreshTime: new Date().getTime(),
- }));
- }
- },
- [childConfig, reference]
- );
-
- const handleCloseReference = () => {
- setChildConfig(null, null);
- };
-
- if (!display) return null;
-
- return (
-
- setChildConfig(createGridConfig(), reference)}
- onReferenceSourceChanged={reference ? handleReferenceSourceChanged : null}
- refReloadToken={refReloadToken.toString()}
- masterLoadedTime={masterLoadedTime}
- GridCore={SqlDataGridCore}
- FormView={SqlFormView}
- isDetailView={isDetailView}
- // tableInfo={
- // dbinfo && dbinfo.tables && dbinfo.tables.find((x) => x.pureName == pureName && x.schemaName == schemaName)
- // }
- />
- {reference && (
-
-
-
-
-
-
- )}
-
- );
-}
diff --git a/packages/web/src/datagrid/gridutil.ts b/packages/web/src/datagrid/gridutil.ts
deleted file mode 100644
index bf64c2a94..000000000
--- a/packages/web/src/datagrid/gridutil.ts
+++ /dev/null
@@ -1,144 +0,0 @@
-import _ from 'lodash';
-import { SeriesSizes } from './SeriesSizes';
-import { CellAddress } from './selection';
-import { GridDisplay } from 'dbgate-datalib';
-import Grider from './Grider';
-
-export function countColumnSizes(grider: Grider, columns, containerWidth, display: GridDisplay) {
- const columnSizes = new SeriesSizes();
- if (!grider || !columns) return columnSizes;
-
- let canvas = document.createElement('canvas');
- let context = canvas.getContext('2d');
-
- //return this.context.measureText(txt).width;
-
- // console.log('countColumnSizes', loadedRows.length, containerWidth);
-
- columnSizes.maxSize = (containerWidth * 2) / 3;
- columnSizes.count = columns.length;
-
- // columnSizes.setExtraordinaryIndexes(this.getHiddenColumnIndexes(), this.getFrozenColumnIndexes());
- // console.log('display.hiddenColumnIndexes', display.hiddenColumnIndexes)
-
- columnSizes.setExtraordinaryIndexes(display.hiddenColumnIndexes, []);
-
- for (let colIndex = 0; colIndex < columns.length; colIndex++) {
- //this.columnSizes.PutSizeOverride(col, this.columns[col].Name.length * 8);
- const column = columns[colIndex];
-
- if (display.config.columnWidths[column.uniqueName]) {
- columnSizes.putSizeOverride(colIndex, display.config.columnWidths[column.uniqueName]);
- continue;
- }
-
- // if (column.columnClientObject != null && column.columnClientObject.notNull) context.font = "bold 14px Helvetica";
- // else context.font = "14px Helvetica";
- context.font = 'bold 14px Helvetica';
-
- const text = column.headerText;
- const headerWidth = context.measureText(text).width + 64;
-
- // if (column.columnClientObject != null && column.columnClientObject.icon != null) headerWidth += 16;
- // if (this.getFilterOnColumn(column.uniquePath)) headerWidth += 16;
- // if (this.getSortOrder(column.uniquePath)) headerWidth += 16;
-
- columnSizes.putSizeOverride(colIndex, headerWidth);
- }
-
- // let headerWidth = this.rowHeaderWidthDefault;
- // if (this.rowCount) headerWidth = context.measureText(this.rowCount.toString()).width + 8;
- // this.rowHeaderWidth = this.rowHeaderWidthDefault;
- // if (headerWidth > this.rowHeaderWidth) this.rowHeaderWidth = headerWidth;
-
- context.font = '14px Helvetica';
- for (let rowIndex = 0; rowIndex < Math.min(grider.rowCount, 20); rowIndex += 1) {
- const row = grider.getRowData(rowIndex);
- for (let colIndex = 0; colIndex < columns.length; colIndex++) {
- const uqName = columns[colIndex].uniqueName;
-
- if (display.config.columnWidths[uqName]) {
- continue;
- }
-
- const text = row[uqName];
- const width = context.measureText(text).width + 8;
- // console.log('colName', colName, text, width);
- columnSizes.putSizeOverride(colIndex, width);
- // let colName = this.columns[colIndex].uniquePath;
- // let text: string = row[colName].gridText;
- // let width = context.measureText(text).width + 8;
- // if (row[colName].dataPrefix) width += context.measureText(row[colName].dataPrefix).width + 3;
- // this.columnSizes.putSizeOverride(colIndex, width);
- }
- }
-
- // for (let modelIndex = 0; modelIndex < this.columns.length; modelIndex++) {
- // let width = getHashValue(this.widthHashPrefix + this.columns[modelIndex].uniquePath);
- // if (width) this.columnSizes.putSizeOverride(modelIndex, _.toNumber(width), true);
- // }
-
- columnSizes.buildIndex();
- return columnSizes;
-}
-
-export function countVisibleRealColumns(columnSizes, firstVisibleColumnScrollIndex, gridScrollAreaWidth, columns) {
- const visibleColumnCount = columnSizes.getVisibleScrollCount(firstVisibleColumnScrollIndex, gridScrollAreaWidth);
- // console.log('visibleColumnCount', visibleColumnCount);
- // console.log('gridScrollAreaWidth', gridScrollAreaWidth);
-
- const visibleRealColumnIndexes = [];
- const modelIndexes = {};
- /** @type {(import('dbgate-datalib').DisplayColumn & {widthPx: string; colIndex: number})[]} */
- const realColumns = [];
-
- // frozen columns
- for (let colIndex = 0; colIndex < columnSizes.frozenCount; colIndex++) {
- visibleRealColumnIndexes.push(colIndex);
- }
- // scroll columns
- for (
- let colIndex = firstVisibleColumnScrollIndex;
- colIndex < firstVisibleColumnScrollIndex + visibleColumnCount;
- colIndex++
- ) {
- visibleRealColumnIndexes.push(colIndex + columnSizes.frozenCount);
- }
-
- // real columns
- for (let colIndex of visibleRealColumnIndexes) {
- let modelColumnIndex = columnSizes.realToModel(colIndex);
- modelIndexes[colIndex] = modelColumnIndex;
-
- let col = columns[modelColumnIndex];
- if (!col) continue;
- const widthNumber = columnSizes.getSizeByRealIndex(colIndex);
- realColumns.push({
- ...col,
- colIndex,
- widthNumber,
- widthPx: `${widthNumber}px`,
- });
- }
- return realColumns;
-}
-
-export function filterCellForRow(cell, row: number): CellAddress | null {
- return cell && (cell[0] == row || _.isString(cell[0])) ? cell : null;
-}
-
-export function filterCellsForRow(cells, row: number): CellAddress[] | null {
- const res = (cells || []).filter(x => x[0] == row || _.isString(x[0]));
- return res.length > 0 ? res : null;
-}
-
-export function cellIsSelected(row, col, selectedCells) {
- if (!selectedCells) return false;
- for (const [selectedRow, selectedCol] of selectedCells) {
- if (row == selectedRow && col == selectedCol) return true;
- if (selectedRow == 'header' && col == selectedCol) return true;
- if (row == selectedRow && selectedCol == 'header') return true;
- if (selectedRow == 'header' && selectedCol == 'header') return true;
- }
- return false;
-}
diff --git a/packages/web/src/datagrid/selection.ts b/packages/web/src/datagrid/selection.ts
deleted file mode 100644
index 28ff9384a..000000000
--- a/packages/web/src/datagrid/selection.ts
+++ /dev/null
@@ -1,69 +0,0 @@
-import _ from 'lodash';
-export type CellAddress = [number | 'header' | 'filter' | undefined, number | 'header' | undefined];
-export type RegularCellAddress = [number, number];
-
-export const topLeftCell: CellAddress = [0, 0];
-export const undefinedCell: CellAddress = [undefined, undefined];
-export const nullCell: CellAddress = null;
-export const emptyCellArray: CellAddress[] = [];
-
-export function isRegularCell(cell: CellAddress): cell is RegularCellAddress {
- if (!cell) return false;
- const [row, col] = cell;
- return _.isNumber(row) && _.isNumber(col);
-}
-
-export function getCellRange(a: CellAddress, b: CellAddress): CellAddress[] {
- const [rowA, colA] = a;
- const [rowB, colB] = b;
-
- if (_.isNumber(rowA) && _.isNumber(colA) && _.isNumber(rowB) && _.isNumber(colB)) {
- const rowMin = Math.min(rowA, rowB);
- const rowMax = Math.max(rowA, rowB);
- const colMin = Math.min(colA, colB);
- const colMax = Math.max(colA, colB);
- const res = [];
- for (let row = rowMin; row <= rowMax; row++) {
- for (let col = colMin; col <= colMax; col++) {
- res.push([row, col]);
- }
- }
- return res;
- }
- if (rowA == 'header' && rowB == 'header' && _.isNumber(colA) && _.isNumber(colB)) {
- const colMin = Math.min(colA, colB);
- const colMax = Math.max(colA, colB);
- const res = [];
- for (let col = colMin; col <= colMax; col++) {
- res.push(['header', col]);
- }
- return res;
- }
- if (colA == 'header' && colB == 'header' && _.isNumber(rowA) && _.isNumber(rowB)) {
- const rowMin = Math.min(rowA, rowB);
- const rowMax = Math.max(rowA, rowB);
- const res = [];
- for (let row = rowMin; row <= rowMax; row++) {
- res.push([row, 'header']);
- }
- return res;
- }
- if (colA == 'header' && colB == 'header' && rowA == 'header' && rowB == 'header') {
- return [['header', 'header']];
- }
- return [];
-}
-
-export function convertCellAddress(row, col): CellAddress {
- const rowNumber = parseInt(row);
- const colNumber = parseInt(col);
- return [_.isNaN(rowNumber) ? row : rowNumber, _.isNaN(colNumber) ? col : colNumber];
-}
-
-export function cellFromEvent(event): CellAddress {
- const cell = event.target.closest('td');
- if (!cell) return undefinedCell;
- const col = cell.getAttribute('data-col');
- const row = cell.getAttribute('data-row');
- return convertCellAddress(row, col);
-}
diff --git a/packages/web/src/datagrid/types.ts b/packages/web/src/datagrid/types.ts
deleted file mode 100644
index c6f0791b9..000000000
--- a/packages/web/src/datagrid/types.ts
+++ /dev/null
@@ -1,46 +0,0 @@
-import { GridDisplay, ChangeSet, GridReferenceDefinition } from 'dbgate-datalib';
-import Grider from './Grider';
-
-export interface DataGridProps {
- display: GridDisplay;
- tabVisible?: boolean;
- changeSetState?: { value: ChangeSet };
- dispatchChangeSet?: Function;
- toolbarPortalRef?: any;
- showReferences?: boolean;
- onReferenceClick?: (def: GridReferenceDefinition) => void;
- onReferenceSourceChanged?: Function;
- refReloadToken?: string;
- masterLoadedTime?: number;
- managerSize?: number;
- grider?: Grider;
- conid?: string;
- database?: string;
- jslid?: string;
-
- [field: string]: any;
-}
-
-// export interface DataGridCoreProps extends DataGridProps {
-// rows: any[];
-// loadNextData?: Function;
-// exportGrid?: Function;
-// openQuery?: Function;
-// undo?: Function;
-// redo?: Function;
-
-// errorMessage?: string;
-// isLoadedAll?: boolean;
-// loadedTime?: any;
-// allRowCount?: number;
-// conid?: string;
-// database?: string;
-// insertedRowCount?: number;
-// isLoading?: boolean;
-// }
-
-// export interface LoadingDataGridProps extends DataGridProps {
-// conid?: string;
-// database?: string;
-// jslid?: string;
-// }
diff --git a/packages/web/src/designer/Designer.js b/packages/web/src/designer/Designer.js
deleted file mode 100644
index 076799aac..000000000
--- a/packages/web/src/designer/Designer.js
+++ /dev/null
@@ -1,352 +0,0 @@
-import React from 'react';
-import styled from 'styled-components';
-import DesignerTable from './DesignerTable';
-import uuidv1 from 'uuid/v1';
-import _ from 'lodash';
-import useTheme from '../theme/useTheme';
-import DesignerReference from './DesignerReference';
-import cleanupDesignColumns from './cleanupDesignColumns';
-import { isConnectedByReference } from './designerTools';
-import { getTableInfo } from '../utility/metadataLoaders';
-
-const Wrapper = styled.div`
- flex: 1;
- background-color: ${props => props.theme.designer_background};
- overflow: scroll;
-`;
-
-const Canvas = styled.div`
- width: 3000px;
- height: 3000px;
- position: relative;
-`;
-
-const EmptyInfo = styled.div`
- margin: 50px;
- font-size: 20px;
-`;
-
-function fixPositions(tables) {
- const minLeft = _.min(tables.map(x => x.left));
- const minTop = _.min(tables.map(x => x.top));
- if (minLeft < 0 || minTop < 0) {
- const dLeft = minLeft < 0 ? -minLeft : 0;
- const dTop = minTop < 0 ? -minTop : 0;
- return tables.map(tbl => ({
- ...tbl,
- left: tbl.left + dLeft,
- top: tbl.top + dTop,
- }));
- }
- return tables;
-}
-
-export default function Designer({ value, onChange, conid, database }) {
- const { tables, references } = value || {};
- const theme = useTheme();
-
- const [sourceDragColumn, setSourceDragColumn] = React.useState(null);
- const [targetDragColumn, setTargetDragColumn] = React.useState(null);
- const domTablesRef = React.useRef({});
- const wrapperRef = React.useRef();
- const [changeToken, setChangeToken] = React.useState(0);
-
- const handleDrop = e => {
- var data = e.dataTransfer.getData('app_object_drag_data');
- e.preventDefault();
- if (!data) return;
- const rect = e.target.getBoundingClientRect();
- var json = JSON.parse(data);
- const { objectTypeField } = json;
- if (objectTypeField != 'tables' && objectTypeField != 'views') return;
- json.designerId = uuidv1();
- json.left = e.clientX - rect.left;
- json.top = e.clientY - rect.top;
-
- onChange(current => {
- const foreignKeys = _.compact([
- ...(json.foreignKeys || []).map(fk => {
- const tables = ((current || {}).tables || []).filter(
- tbl => fk.refTableName == tbl.pureName && fk.refSchemaName == tbl.schemaName
- );
- if (tables.length == 1)
- return {
- ...fk,
- sourceId: json.designerId,
- targetId: tables[0].designerId,
- };
- return null;
- }),
- ..._.flatten(
- ((current || {}).tables || []).map(tbl =>
- (tbl.foreignKeys || []).map(fk => {
- if (fk.refTableName == json.pureName && fk.refSchemaName == json.schemaName) {
- return {
- ...fk,
- sourceId: tbl.designerId,
- targetId: json.designerId,
- };
- }
- return null;
- })
- )
- ),
- ]);
-
- return {
- ...current,
- tables: [...((current || {}).tables || []), json],
- references:
- foreignKeys.length == 1
- ? [
- ...((current || {}).references || []),
- {
- designerId: uuidv1(),
- sourceId: foreignKeys[0].sourceId,
- targetId: foreignKeys[0].targetId,
- joinType: 'INNER JOIN',
- columns: foreignKeys[0].columns.map(col => ({
- source: col.columnName,
- target: col.refColumnName,
- })),
- },
- ]
- : (current || {}).references,
- };
- });
- };
-
- const changeTable = React.useCallback(
- table => {
- onChange(current => ({
- ...current,
- tables: fixPositions((current.tables || []).map(x => (x.designerId == table.designerId ? table : x))),
- }));
- },
- [onChange]
- );
-
- const bringToFront = React.useCallback(
- table => {
- onChange(
- current => ({
- ...current,
- tables: [...(current.tables || []).filter(x => x.designerId != table.designerId), table],
- }),
- true
- );
- },
- [onChange]
- );
-
- const removeTable = React.useCallback(
- table => {
- onChange(current => ({
- ...current,
- tables: (current.tables || []).filter(x => x.designerId != table.designerId),
- references: (current.references || []).filter(
- x => x.sourceId != table.designerId && x.targetId != table.designerId
- ),
- columns: (current.columns || []).filter(x => x.designerId != table.designerId),
- }));
- },
- [onChange]
- );
-
- const changeReference = React.useCallback(
- ref => {
- onChange(current => ({
- ...current,
- references: (current.references || []).map(x => (x.designerId == ref.designerId ? ref : x)),
- }));
- },
- [onChange]
- );
-
- const removeReference = React.useCallback(
- ref => {
- onChange(current => ({
- ...current,
- references: (current.references || []).filter(x => x.designerId != ref.designerId),
- }));
- },
- [onChange]
- );
-
- const handleCreateReference = (source, target) => {
- onChange(current => {
- const existingReference = (current.references || []).find(
- x =>
- (x.sourceId == source.designerId && x.targetId == target.designerId) ||
- (x.sourceId == target.designerId && x.targetId == source.designerId)
- );
-
- return {
- ...current,
- references: existingReference
- ? current.references.map(ref =>
- ref == existingReference
- ? {
- ...existingReference,
- columns: [
- ...existingReference.columns,
- existingReference.sourceId == source.designerId
- ? {
- source: source.columnName,
- target: target.columnName,
- }
- : {
- source: target.columnName,
- target: source.columnName,
- },
- ],
- }
- : ref
- )
- : [
- ...(current.references || []),
- {
- designerId: uuidv1(),
- sourceId: source.designerId,
- targetId: target.designerId,
- joinType: isConnectedByReference(current, source, target, null) ? 'CROSS JOIN' : 'INNER JOIN',
- columns: [
- {
- source: source.columnName,
- target: target.columnName,
- },
- ],
- },
- ],
- };
- });
- };
-
- const handleAddReferenceByColumn = async (designerId, foreignKey) => {
- const toTable = await getTableInfo({
- conid,
- database,
- pureName: foreignKey.refTableName,
- schemaName: foreignKey.refSchemaName,
- });
- const newTableDesignerId = uuidv1();
- onChange(current => {
- const fromTable = (current.tables || []).find(x => x.designerId == designerId);
- if (!fromTable) return;
- return {
- ...current,
- tables: [
- ...(current.tables || []),
- {
- ...toTable,
- left: fromTable.left + 300,
- top: fromTable.top + 50,
- designerId: newTableDesignerId,
- },
- ],
- references: [
- ...(current.references || []),
- {
- designerId: uuidv1(),
- sourceId: fromTable.designerId,
- targetId: newTableDesignerId,
- joinType: 'INNER JOIN',
- columns: foreignKey.columns.map(col => ({
- source: col.columnName,
- target: col.refColumnName,
- })),
- },
- ],
- };
- });
- };
-
- const handleSelectColumn = React.useCallback(
- column => {
- onChange(
- current => ({
- ...current,
- columns: (current.columns || []).find(
- x => x.designerId == column.designerId && x.columnName == column.columnName
- )
- ? current.columns
- : [...cleanupDesignColumns(current.columns), _.pick(column, ['designerId', 'columnName'])],
- }),
- true
- );
- },
- [onChange]
- );
-
- const handleChangeColumn = React.useCallback(
- (column, changeFunc) => {
- onChange(current => {
- const currentColumns = (current || {}).columns || [];
- const existing = currentColumns.find(
- x => x.designerId == column.designerId && x.columnName == column.columnName
- );
- if (existing) {
- return {
- ...current,
- columns: currentColumns.map(x => (x == existing ? changeFunc(existing) : x)),
- };
- } else {
- return {
- ...current,
- columns: [
- ...cleanupDesignColumns(currentColumns),
- changeFunc(_.pick(column, ['designerId', 'columnName'])),
- ],
- };
- }
- });
- },
- [onChange]
- );
-
- // React.useEffect(() => {
- // setTimeout(() => setChangeToken((x) => x + 1), 100);
- // }, [value]);
-
- return (
-
- {(tables || []).length == 0 && Drag & drop tables or views from left panel here }
- e.preventDefault()} onDrop={handleDrop} ref={wrapperRef}>
- {(references || []).map(ref => (
-
- ))}
- {(tables || []).map(table => (
- {
- domTablesRef.current[table.designerId] = table;
- }}
- designer={value}
- />
- ))}
-
-
- );
-}
diff --git a/packages/web/src/designer/DesignerComponentCreator.ts b/packages/web/src/designer/DesignerComponentCreator.ts
deleted file mode 100644
index 0f4ad809a..000000000
--- a/packages/web/src/designer/DesignerComponentCreator.ts
+++ /dev/null
@@ -1,91 +0,0 @@
-import _ from 'lodash';
-import { dumpSqlSelect, Select, JoinType, Condition, Relation, mergeConditions, Source } from 'dbgate-sqltree';
-import { EngineDriver } from 'dbgate-types';
-import { DesignerInfo, DesignerTableInfo, DesignerReferenceInfo, DesignerJoinType } from './types';
-import { findPrimaryTable, findConnectingReference, referenceIsJoin, referenceIsExists } from './designerTools';
-
-export class DesignerComponent {
- subComponents: DesignerComponent[] = [];
- parentComponent: DesignerComponent;
- parentReference: DesignerReferenceInfo;
-
- tables: DesignerTableInfo[] = [];
- nonPrimaryReferences: DesignerReferenceInfo[] = [];
-
- get primaryTable() {
- return this.tables[0];
- }
- get nonPrimaryTables() {
- return this.tables.slice(1);
- }
- get nonPrimaryTablesAndReferences() {
- return _.zip(this.nonPrimaryTables, this.nonPrimaryReferences);
- }
- get myAndParentTables() {
- return [...this.parentTables, ...this.tables];
- }
- get parentTables() {
- return this.parentComponent ? this.parentComponent.myAndParentTables : [];
- }
- get thisAndSubComponentsTables() {
- return [...this.tables, ..._.flatten(this.subComponents.map(x => x.thisAndSubComponentsTables))];
- }
-}
-
-export class DesignerComponentCreator {
- toAdd: DesignerTableInfo[];
- components: DesignerComponent[] = [];
-
- constructor(public designer: DesignerInfo) {
- this.toAdd = [...designer.tables];
- while (this.toAdd.length > 0) {
- const component = this.parseComponent(null);
- this.components.push(component);
- }
- }
-
- parseComponent(root) {
- if (root == null) {
- root = findPrimaryTable(this.toAdd);
- }
- if (!root) return null;
- _.remove(this.toAdd, x => x == root);
- const res = new DesignerComponent();
- res.tables.push(root);
-
- for (;;) {
- let found = false;
- for (const test of this.toAdd) {
- const ref = findConnectingReference(this.designer, res.tables, [test], referenceIsJoin);
- if (ref) {
- res.tables.push(test);
- res.nonPrimaryReferences.push(ref);
- _.remove(this.toAdd, x => x == test);
- found = true;
- break;
- }
- }
-
- if (!found) break;
- }
-
- for (;;) {
- let found = false;
- for (const test of this.toAdd) {
- const ref = findConnectingReference(this.designer, res.tables, [test], referenceIsExists);
- if (ref) {
- const subComponent = this.parseComponent(test);
- res.subComponents.push(subComponent);
- subComponent.parentComponent = res;
- subComponent.parentReference = ref;
- found = true;
- break;
- }
- }
-
- if (!found) break;
- }
-
- return res;
- }
-}
diff --git a/packages/web/src/designer/DesignerQueryDumper.ts b/packages/web/src/designer/DesignerQueryDumper.ts
deleted file mode 100644
index d4c5e4af2..000000000
--- a/packages/web/src/designer/DesignerQueryDumper.ts
+++ /dev/null
@@ -1,215 +0,0 @@
-import _ from 'lodash';
-import {
- dumpSqlSelect,
- Select,
- JoinType,
- Condition,
- Relation,
- mergeConditions,
- Source,
- ResultField,
-} from 'dbgate-sqltree';
-import { EngineDriver } from 'dbgate-types';
-import { DesignerInfo, DesignerTableInfo, DesignerReferenceInfo, DesignerJoinType } from './types';
-import { DesignerComponent } from './DesignerComponentCreator';
-import {
- getReferenceConditions,
- referenceIsCrossJoin,
- referenceIsConnecting,
- mergeSelectsFromDesigner,
- findQuerySource,
- findDesignerFilterType,
-} from './designerTools';
-import { parseFilter } from 'dbgate-filterparser';
-
-export class DesignerQueryDumper {
- constructor(public designer: DesignerInfo, public components: DesignerComponent[]) {}
-
- get topLevelTables(): DesignerTableInfo[] {
- return _.flatten(this.components.map(x => x.tables));
- }
-
- dumpComponent(component: DesignerComponent) {
- const select: Select = {
- commandType: 'select',
- from: {
- name: component.primaryTable,
- alias: component.primaryTable.alias,
- relations: [],
- },
- };
-
- for (const [table, ref] of component.nonPrimaryTablesAndReferences) {
- select.from.relations.push({
- name: table,
- alias: table.alias,
- joinType: ref.joinType as JoinType,
- conditions: getReferenceConditions(ref, this.designer),
- });
- }
-
- for (const subComponent of component.subComponents) {
- const subQuery = this.dumpComponent(subComponent);
- subQuery.selectAll = true;
- select.where = mergeConditions(select.where, {
- conditionType: subComponent.parentReference.joinType == 'WHERE NOT EXISTS' ? 'notExists' : 'exists',
- subQuery,
- });
- }
-
- if (component.parentReference) {
- select.where = mergeConditions(select.where, {
- conditionType: 'and',
- conditions: getReferenceConditions(component.parentReference, this.designer),
- });
-
- // cross join conditions in subcomponents
- for (const ref of this.designer.references || []) {
- if (referenceIsCrossJoin(ref) && referenceIsConnecting(ref, component.tables, component.myAndParentTables)) {
- select.where = mergeConditions(select.where, {
- conditionType: 'and',
- conditions: getReferenceConditions(ref, this.designer),
- });
- }
- }
- this.addConditions(select, component.tables);
- }
-
- return select;
- }
-
- addConditions(select: Select, tables: DesignerTableInfo[]) {
- for (const column of this.designer.columns || []) {
- if (!column.filter) continue;
- const table = (this.designer.tables || []).find(x => x.designerId == column.designerId);
- if (!table) continue;
- if (!tables.find(x => x.designerId == table.designerId)) continue;
-
- const condition = parseFilter(column.filter, findDesignerFilterType(column, this.designer));
- if (condition) {
- select.where = mergeConditions(
- select.where,
- _.cloneDeepWith(condition, expr => {
- if (expr.exprType == 'placeholder')
- return {
- exprType: 'column',
- columnName: column.columnName,
- source: findQuerySource(this.designer, column.designerId),
- };
- })
- );
- }
- }
- }
-
- addGroupConditions(select: Select, tables: DesignerTableInfo[], selectIsGrouped: boolean) {
- for (const column of this.designer.columns || []) {
- if (!column.groupFilter) continue;
- const table = (this.designer.tables || []).find(x => x.designerId == column.designerId);
- if (!table) continue;
- if (!tables.find(x => x.designerId == table.designerId)) continue;
-
- const condition = parseFilter(column.groupFilter, findDesignerFilterType(column, this.designer));
- if (condition) {
- select.having = mergeConditions(
- select.having,
- _.cloneDeepWith(condition, expr => {
- if (expr.exprType == 'placeholder') {
- return this.getColumnOutputExpression(column, selectIsGrouped);
- }
- })
- );
- }
- }
- }
-
- getColumnOutputExpression(col, selectIsGrouped): ResultField {
- const source = findQuerySource(this.designer, col.designerId);
- const { columnName } = col;
- let { alias } = col;
- if (selectIsGrouped && !col.isGrouped) {
- // use aggregate
- const aggregate = col.aggregate == null || col.aggregate == '---' ? 'MAX' : col.aggregate;
- if (!alias) alias = `${aggregate}(${columnName})`;
-
- return {
- exprType: 'call',
- func: aggregate == 'COUNT DISTINCT' ? 'COUNT' : aggregate,
- argsPrefix: aggregate == 'COUNT DISTINCT' ? 'DISTINCT' : null,
- alias,
- args: [
- {
- exprType: 'column',
- columnName,
- source,
- },
- ],
- };
- } else {
- return {
- exprType: 'column',
- columnName,
- alias,
- source,
- };
- }
- }
-
- run() {
- let res: Select = null;
- for (const component of this.components) {
- const select = this.dumpComponent(component);
- if (res == null) res = select;
- else res = mergeSelectsFromDesigner(res, select);
- }
-
- // top level cross join conditions
- const topLevelTables = this.topLevelTables;
- for (const ref of this.designer.references || []) {
- if (referenceIsCrossJoin(ref) && referenceIsConnecting(ref, topLevelTables, topLevelTables)) {
- res.where = mergeConditions(res.where, {
- conditionType: 'and',
- conditions: getReferenceConditions(ref, this.designer),
- });
- }
- }
-
- const topLevelColumns = (this.designer.columns || []).filter(col =>
- topLevelTables.find(tbl => tbl.designerId == col.designerId)
- );
- const selectIsGrouped = !!topLevelColumns.find(x => x.isGrouped || (x.aggregate && x.aggregate != '---'));
- const outputColumns = topLevelColumns.filter(x => x.isOutput);
- if (outputColumns.length == 0) {
- res.selectAll = true;
- } else {
- res.columns = outputColumns.map(col => this.getColumnOutputExpression(col, selectIsGrouped));
- }
-
- const groupedColumns = topLevelColumns.filter(x => x.isGrouped);
- if (groupedColumns.length > 0) {
- res.groupBy = groupedColumns.map(col => ({
- exprType: 'column',
- columnName: col.columnName,
- source: findQuerySource(this.designer, col.designerId),
- }));
- }
-
- const orderColumns = _.sortBy(
- topLevelColumns.filter(x => x.sortOrder),
- x => Math.abs(x.sortOrder)
- );
- if (orderColumns.length > 0) {
- res.orderBy = orderColumns.map(col => ({
- exprType: 'column',
- direction: col.sortOrder < 0 ? 'DESC' : 'ASC',
- columnName: col.columnName,
- source: findQuerySource(this.designer, col.designerId),
- }));
- }
-
- this.addConditions(res, topLevelTables);
- this.addGroupConditions(res, topLevelTables, selectIsGrouped);
-
- return res;
- }
-}
diff --git a/packages/web/src/designer/DesignerReference.js b/packages/web/src/designer/DesignerReference.js
deleted file mode 100644
index 60a37bfdf..000000000
--- a/packages/web/src/designer/DesignerReference.js
+++ /dev/null
@@ -1,177 +0,0 @@
-import React from 'react';
-import styled from 'styled-components';
-import DomTableRef from './DomTableRef';
-import _ from 'lodash';
-import useTheme from '../theme/useTheme';
-import { useShowMenu } from '../modals/showMenu';
-import { DropDownMenuDivider, DropDownMenuItem } from '../modals/DropDownMenu';
-import { isConnectedByReference } from './designerTools';
-
-const StyledSvg = styled.svg`
- position: absolute;
- left: 0;
- top: 0;
- right: 0;
- bottom: 0;
- width: 100%;
- height: 100%;
-`;
-
-const ReferenceWrapper = styled.div`
- position: absolute;
- border: 1px solid ${props => props.theme.designer_line};
- background-color: ${props => props.theme.designer_background};
- z-index: 900;
- border-radius: 10px;
- width: 32px;
- height: 32px;
-`;
-
-const ReferenceText = styled.span`
- position: relative;
- float: left;
- top: 50%;
- left: 50%;
- transform: translate(-50%, -50%);
- z-index: 900;
- white-space: nowrap;
- background-color: ${props => props.theme.designer_background};
-`;
-
-function ReferenceContextMenu({ remove, setJoinType, isConnected }) {
- return (
- <>
- Remove
- {!isConnected && (
- <>
-
- setJoinType('INNER JOIN')}>Set INNER JOIN
- setJoinType('LEFT JOIN')}>Set LEFT JOIN
- setJoinType('RIGHT JOIN')}>Set RIGHT JOIN
- setJoinType('FULL OUTER JOIN')}>Set FULL OUTER JOIN
- setJoinType('CROSS JOIN')}>Set CROSS JOIN
- setJoinType('WHERE EXISTS')}>Set WHERE EXISTS
- setJoinType('WHERE NOT EXISTS')}>Set WHERE NOT EXISTS
- >
- )}
- >
- );
-}
-
-export default function DesignerReference({
- domTablesRef,
- reference,
- changeToken,
- onRemoveReference,
- onChangeReference,
- designer,
-}) {
- const { designerId, sourceId, targetId, columns, joinType } = reference;
- const theme = useTheme();
- const showMenu = useShowMenu();
- const domTables = domTablesRef.current;
- /** @type {DomTableRef} */
- const sourceTable = domTables[sourceId];
- /** @type {DomTableRef} */
- const targetTable = domTables[targetId];
- if (!sourceTable || !targetTable) return null;
- const sourceRect = sourceTable.getRect();
- const targetRect = targetTable.getRect();
- if (!sourceRect || !targetRect) return null;
-
- const buswi = 10;
- const extwi = 25;
-
- const possibilities = [];
- possibilities.push({ xsrc: sourceRect.left - buswi, dirsrc: -1, xdst: targetRect.left - buswi, dirdst: -1 });
- possibilities.push({ xsrc: sourceRect.left - buswi, dirsrc: -1, xdst: targetRect.right + buswi, dirdst: 1 });
- possibilities.push({ xsrc: sourceRect.right + buswi, dirsrc: 1, xdst: targetRect.left - buswi, dirdst: -1 });
- possibilities.push({ xsrc: sourceRect.right + buswi, dirsrc: 1, xdst: targetRect.right + buswi, dirdst: 1 });
-
- let minpos = _.minBy(possibilities, p => Math.abs(p.xsrc - p.xdst));
-
- let srcY = _.mean(columns.map(x => sourceTable.getColumnY(x.source)));
- let dstY = _.mean(columns.map(x => targetTable.getColumnY(x.target)));
-
- if (columns.length == 0) {
- srcY = sourceTable.getColumnY('');
- dstY = targetTable.getColumnY('');
- }
-
- const src = { x: minpos.xsrc, y: srcY };
- const dst = { x: minpos.xdst, y: dstY };
-
- const lineStyle = { fill: 'none', stroke: theme.designer_line, strokeWidth: 2 };
-
- const handleContextMenu = event => {
- event.preventDefault();
- showMenu(
- event.pageX,
- event.pageY,
- onRemoveReference({ designerId })}
- isConnected={isConnectedByReference(designer, { designerId: sourceId }, { designerId: targetId }, reference)}
- setJoinType={joinType => {
- onChangeReference({
- ...reference,
- joinType,
- });
- }}
- />
- );
- };
-
- return (
- <>
-
-
- {columns.map((col, colIndex) => {
- let y1 = sourceTable.getColumnY(col.source);
- let y2 = targetTable.getColumnY(col.target);
- return (
-
-
-
-
- );
- })}
-
-
-
- {_.snakeCase(joinType || 'CROSS JOIN')
- .replace('_', '\xa0')
- .replace('_', '\xa0')}
-
-
- >
- );
-}
diff --git a/packages/web/src/designer/DesignerTable.js b/packages/web/src/designer/DesignerTable.js
deleted file mode 100644
index e9b996aa7..000000000
--- a/packages/web/src/designer/DesignerTable.js
+++ /dev/null
@@ -1,413 +0,0 @@
-import React from 'react';
-import styled from 'styled-components';
-import { findForeignKeyForColumn } from 'dbgate-tools';
-import ColumnLabel from '../datagrid/ColumnLabel';
-import { FontIcon } from '../icons';
-import useTheme from '../theme/useTheme';
-import DomTableRef from './DomTableRef';
-import _ from 'lodash';
-import { CheckboxField } from '../utility/inputs';
-import { useShowMenu } from '../modals/showMenu';
-import { DropDownMenuDivider, DropDownMenuItem } from '../modals/DropDownMenu';
-import useShowModal from '../modals/showModal';
-import InputTextModal from '../modals/InputTextModal';
-
-const Wrapper = styled.div`
- position: absolute;
- // background-color: white;
- background-color: ${props => props.theme.designtable_background};
- border: 1px solid ${props => props.theme.border};
-`;
-
-const Header = styled.div`
- font-weight: bold;
- text-align: center;
- padding: 2px;
- background: ${props =>
- // @ts-ignore
- props.objectTypeField == 'views'
- ? props.theme.designtable_background_magenta[2]
- : props.theme.designtable_background_blue[2]};
- border-bottom: 1px solid ${props => props.theme.border};
- cursor: pointer;
- display: flex;
- justify-content: space-between;
-`;
-
-const ColumnsWrapper = styled.div`
- max-height: 400px;
- overflow-y: auto;
- width: calc(100% - 10px);
- padding: 5px;
-`;
-
-const HeaderLabel = styled.div``;
-
-const CloseWrapper = styled.div`
- ${props =>
- `
- background-color: ${props.theme.toolbar_background} ;
-
- &:hover {
- background-color: ${props.theme.toolbar_background2} ;
- }
-
- &:active:hover {
- background-color: ${props.theme.toolbar_background3};
- }
- `}
-`;
-
-// &:hover {
-// background-color: ${(props) => props.theme.designtable_background_gold[1]};
-// }
-
-const ColumnLine = styled.div`
- ${props =>
- // @ts-ignore
- !props.isDragSource &&
- // @ts-ignore
- !props.isDragTarget &&
- `
- &:hover {
- background-color: ${props.theme.designtable_background_gold[1]};
- }
- `}
-
- ${props =>
- // @ts-ignore
- props.isDragSource &&
- `
- background-color: ${props.theme.designtable_background_cyan[2]};
- `}
-
- ${props =>
- // @ts-ignore
- props.isDragTarget &&
- `
- background-color: ${props.theme.designtable_background_cyan[2]};
- `}
-`;
-
-function TableContextMenu({ remove, setTableAlias, removeTableAlias }) {
- return (
- <>
- Remove
-
- Set table alias
- {!!removeTableAlias && Remove table alias }
- >
- );
-}
-
-function ColumnContextMenu({ setSortOrder, addReference }) {
- return (
- <>
- setSortOrder(1)}>Sort ascending
- setSortOrder(-1)}>Sort descending
- setSortOrder(0)}>Unsort
- {!!addReference && Add reference }
- >
- );
-}
-
-function ColumnDesignerIcons({ column, designerId, designer }) {
- const designerColumn = (designer.columns || []).find(
- x => x.designerId == designerId && x.columnName == column.columnName
- );
- if (!designerColumn) return null;
- return (
- <>
- {!!designerColumn.filter && }
- {designerColumn.sortOrder > 0 && }
- {designerColumn.sortOrder < 0 && }
- {!!designerColumn.isGrouped && }
- >
- );
-}
-
-export default function DesignerTable({
- table,
- onChangeTable,
- onBringToFront,
- onRemoveTable,
- onCreateReference,
- onAddReferenceByColumn,
- onSelectColumn,
- onChangeColumn,
- sourceDragColumn,
- setSourceDragColumn,
- targetDragColumn,
- setTargetDragColumn,
- onChangeDomTable,
- wrapperRef,
- setChangeToken,
- designer,
-}) {
- const { pureName, columns, left, top, designerId, alias, objectTypeField } = table;
- const [movingPosition, setMovingPosition] = React.useState(null);
- const movingPositionRef = React.useRef(null);
- const theme = useTheme();
- const domObjectsRef = React.useRef({});
- const showMenu = useShowMenu();
- const showModal = useShowModal();
-
- const moveStartXRef = React.useRef(null);
- const moveStartYRef = React.useRef(null);
-
- const handleMove = React.useCallback(e => {
- let diffX = e.clientX - moveStartXRef.current;
- let diffY = e.clientY - moveStartYRef.current;
- moveStartXRef.current = e.clientX;
- moveStartYRef.current = e.clientY;
-
- movingPositionRef.current = {
- left: (movingPositionRef.current.left || 0) + diffX,
- top: (movingPositionRef.current.top || 0) + diffY,
- };
- setMovingPosition(movingPositionRef.current);
- // setChangeToken((x) => x + 1);
- changeTokenDebounced.current();
- // onChangeTable(
- // {
- // ...props,
- // left: (left || 0) + diffX,
- // top: (top || 0) + diffY,
- // },
- // index
- // );
- }, []);
-
- const changeTokenDebounced = React.useRef(
- // @ts-ignore
- _.debounce(() => setChangeToken(x => x + 1), 100)
- );
-
- const handleMoveEnd = React.useCallback(
- e => {
- if (movingPositionRef.current) {
- onChangeTable({
- ...table,
- left: movingPositionRef.current.left,
- top: movingPositionRef.current.top,
- });
- }
-
- movingPositionRef.current = null;
- setMovingPosition(null);
- changeTokenDebounced.current();
- // setChangeToken((x) => x + 1);
-
- // this.props.model.fixPositions();
-
- // this.props.designer.changedModel(true);
- },
- [onChangeTable, table]
- );
-
- React.useEffect(() => {
- if (movingPosition) {
- document.addEventListener('mousemove', handleMove, true);
- document.addEventListener('mouseup', handleMoveEnd, true);
- return () => {
- document.removeEventListener('mousemove', handleMove, true);
- document.removeEventListener('mouseup', handleMoveEnd, true);
- };
- }
- }, [movingPosition == null, handleMove, handleMoveEnd]);
-
- const headerMouseDown = React.useCallback(
- e => {
- e.preventDefault();
- moveStartXRef.current = e.clientX;
- moveStartYRef.current = e.clientY;
- movingPositionRef.current = { left, top };
- setMovingPosition(movingPositionRef.current);
- // setIsMoving(true);
- },
- [handleMove, handleMoveEnd]
- );
-
- const dispatchDomColumn = (columnName, dom) => {
- domObjectsRef.current[columnName] = dom;
- onChangeDomTable(new DomTableRef(table, domObjectsRef.current, wrapperRef.current));
- changeTokenDebounced.current();
- };
-
- const handleSetTableAlias = () => {
- showModal(modalState => (
- {
- onChangeTable({
- ...table,
- alias: newAlias,
- });
- }}
- />
- ));
- };
-
- const handleHeaderContextMenu = event => {
- event.preventDefault();
- showMenu(
- event.pageX,
- event.pageY,
- onRemoveTable({ designerId })}
- setTableAlias={handleSetTableAlias}
- removeTableAlias={
- alias
- ? () =>
- onChangeTable({
- ...table,
- alias: null,
- })
- : null
- }
- />
- );
- };
-
- const handleColumnContextMenu = column => event => {
- event.preventDefault();
- const foreignKey = findForeignKeyForColumn(table, column);
- showMenu(
- event.pageX,
- event.pageY,
- {
- onChangeColumn(
- {
- ...column,
- designerId,
- },
- col => ({ ...col, sortOrder })
- );
- }}
- addReference={
- foreignKey
- ? () => {
- onAddReferenceByColumn(designerId, foreignKey);
- }
- : null
- }
- />
- );
- };
-
- return (
- onBringToFront(table)}
- ref={dom => dispatchDomColumn('', dom)}
- >
-
- {alias || pureName}
- onRemoveTable(table)} theme={theme}>
-
-
-
-
- {(columns || []).map(column => (
- dispatchDomColumn(column.columnName, dom)}
- // @ts-ignore
- isDragSource={
- sourceDragColumn &&
- sourceDragColumn.designerId == designerId &&
- sourceDragColumn.columnName == column.columnName
- }
- // @ts-ignore
- isDragTarget={
- targetDragColumn &&
- targetDragColumn.designerId == designerId &&
- targetDragColumn.columnName == column.columnName
- }
- onDragStart={e => {
- const dragData = {
- ...column,
- designerId,
- };
- setSourceDragColumn(dragData);
- e.dataTransfer.setData('designer_column_drag_data', JSON.stringify(dragData));
- }}
- onDragEnd={e => {
- setTargetDragColumn(null);
- setSourceDragColumn(null);
- }}
- onDragOver={e => {
- if (sourceDragColumn) {
- e.preventDefault();
- setTargetDragColumn({
- ...column,
- designerId,
- });
- }
- }}
- onDrop={e => {
- var data = e.dataTransfer.getData('designer_column_drag_data');
- e.preventDefault();
- if (!data) return;
- onCreateReference(sourceDragColumn, targetDragColumn);
- setTargetDragColumn(null);
- setSourceDragColumn(null);
- }}
- onMouseDown={e =>
- onSelectColumn({
- ...column,
- designerId,
- })
- }
- >
- x.designerId == designerId && x.columnName == column.columnName && x.isOutput
- )
- }
- onChange={e => {
- if (e.target.checked) {
- onChangeColumn(
- {
- ...column,
- designerId,
- },
- col => ({ ...col, isOutput: true })
- );
- } else {
- onChangeColumn(
- {
- ...column,
- designerId,
- },
- col => ({ ...col, isOutput: false })
- );
- }
- }}
- />
-
-
-
- ))}
-
-
- );
-}
diff --git a/packages/web/src/designer/DomTableRef.ts b/packages/web/src/designer/DomTableRef.ts
deleted file mode 100644
index 53aef90f0..000000000
--- a/packages/web/src/designer/DomTableRef.ts
+++ /dev/null
@@ -1,39 +0,0 @@
-import { DesignerTableInfo } from './types';
-
-export default class DomTableRef {
- domTable: Element;
- domWrapper: Element;
- table: DesignerTableInfo;
- designerId: string;
- domRefs: { [column: string]: Element };
-
- constructor(table: DesignerTableInfo, domRefs, domWrapper: Element) {
- this.domTable = domRefs[''];
- this.domWrapper = domWrapper;
- this.table = table;
- this.designerId = table.designerId;
- this.domRefs = domRefs;
- }
-
- getRect() {
- if (!this.domWrapper) return null;
- if (!this.domTable) return null;
-
- const wrap = this.domWrapper.getBoundingClientRect();
- const rect = this.domTable.getBoundingClientRect();
- return {
- left: rect.left - wrap.left,
- top: rect.top - wrap.top,
- right: rect.right - wrap.left,
- bottom: rect.bottom - wrap.top,
- };
- }
-
- getColumnY(columnName: string) {
- let col = this.domRefs[columnName];
- if (!col) return null;
- const rect = col.getBoundingClientRect();
- const wrap = this.domWrapper.getBoundingClientRect();
- return (rect.top + rect.bottom) / 2 - wrap.top;
- }
-}
diff --git a/packages/web/src/designer/QueryDesignColumns.js b/packages/web/src/designer/QueryDesignColumns.js
deleted file mode 100644
index 7ac113f96..000000000
--- a/packages/web/src/designer/QueryDesignColumns.js
+++ /dev/null
@@ -1,165 +0,0 @@
-import React from 'react';
-import DataFilterControl from '../datagrid/DataFilterControl';
-import { CheckboxField, SelectField, TextField } from '../utility/inputs';
-import TableControl, { TableColumn } from '../utility/TableControl';
-import InlineButton from '../widgets/InlineButton';
-import { findDesignerFilterType } from './designerTools';
-
-function getTableDisplayName(column, tables) {
- const table = (tables || []).find(x => x.designerId == column.designerId);
- if (table) return table.alias || table.pureName;
- return '';
-}
-
-export default function QueryDesignColumns({ value, onChange }) {
- const { columns, tables } = value || {};
-
- const changeColumn = React.useCallback(
- col => {
- onChange(current => ({
- ...current,
- columns: (current.columns || []).map(x =>
- x.designerId == col.designerId && x.columnName == col.columnName ? col : x
- ),
- }));
- },
- [onChange]
- );
-
- const removeColumn = React.useCallback(
- col => {
- onChange(current => ({
- ...current,
- columns: (current.columns || []).filter(x => x.designerId != col.designerId || x.columnName != col.columnName),
- }));
- },
- [onChange]
- );
-
- const hasGroupedColumn = !!(columns || []).find(x => x.isGrouped);
-
- return (
-
-
- getTableDisplayName(row, tables)} />
- (
- {
- if (e.target.checked) changeColumn({ ...row, isOutput: true });
- else changeColumn({ ...row, isOutput: false });
- }}
- />
- )}
- />
- (
- {
- changeColumn({ ...row, alias: e.target.value });
- }}
- />
- )}
- />
-
- (
- {
- if (e.target.checked) changeColumn({ ...row, isGrouped: true });
- else changeColumn({ ...row, isGrouped: false });
- }}
- />
- )}
- />
-
- !row.isGrouped && (
- {
- changeColumn({ ...row, aggregate: e.target.value });
- }}
- >
- ---
- MIN
- MAX
- COUNT
- COUNT DISTINCT
- SUM
- AVG
-
- )
- }
- />
- (
- {
- changeColumn({ ...row, sortOrder: parseInt(e.target.value) });
- }}
- >
- ---
- 1st, ascending
- 1st, descending
- 2nd, ascending
- 2nd, descending
- 3rd, ascending
- 3rd, descending ,
-
- )}
- />
- (
- {
- changeColumn({ ...row, filter });
- }}
- />
- )}
- />
- {hasGroupedColumn && (
- (
- {
- changeColumn({ ...row, groupFilter });
- }}
- />
- )}
- />
- )}
- (
- <>
- removeColumn(row)}>Remove
- >
- )}
- />
-
- );
-}
diff --git a/packages/web/src/designer/QueryDesignToolbar.js b/packages/web/src/designer/QueryDesignToolbar.js
deleted file mode 100644
index c53092e69..000000000
--- a/packages/web/src/designer/QueryDesignToolbar.js
+++ /dev/null
@@ -1,29 +0,0 @@
-import React from 'react';
-import ToolbarButton from '../widgets/ToolbarButton';
-
-export default function QueryDesignToolbar({
- execute,
- isDatabaseDefined,
- busy,
- modelState,
- dispatchModel,
- isConnected,
- kill,
-}) {
- return (
- <>
-
- Execute
-
-
- Kill
-
- dispatchModel({ type: 'undo' })} icon="icon undo">
- Undo
-
- dispatchModel({ type: 'redo' })} icon="icon redo">
- Redo
-
- >
- );
-}
diff --git a/packages/web/src/designer/QueryDesigner.js b/packages/web/src/designer/QueryDesigner.js
deleted file mode 100644
index 031fe40ed..000000000
--- a/packages/web/src/designer/QueryDesigner.js
+++ /dev/null
@@ -1,7 +0,0 @@
-import React from 'react';
-import styled from 'styled-components';
-import Designer from './Designer';
-
-export default function QueryDesigner({ value, conid, database, engine, onChange }) {
- return ;
-}
diff --git a/packages/web/src/designer/cleanupDesignColumns.js b/packages/web/src/designer/cleanupDesignColumns.js
deleted file mode 100644
index 171eefd50..000000000
--- a/packages/web/src/designer/cleanupDesignColumns.js
+++ /dev/null
@@ -1,5 +0,0 @@
-export default function cleanupDesignColumns(columns) {
- return (columns || []).filter(
- x => x.isOutput || x.isGrouped || x.alias || (x.aggregate && x.aggregate != '---') || x.sortOrder || x.filter
- );
-}
diff --git a/packages/web/src/designer/designerTools.ts b/packages/web/src/designer/designerTools.ts
deleted file mode 100644
index 5ed0152d8..000000000
--- a/packages/web/src/designer/designerTools.ts
+++ /dev/null
@@ -1,144 +0,0 @@
-import _ from 'lodash';
-import { dumpSqlSelect, Select, JoinType, Condition, Relation, mergeConditions, Source } from 'dbgate-sqltree';
-import { EngineDriver } from 'dbgate-types';
-import { DesignerInfo, DesignerTableInfo, DesignerReferenceInfo, DesignerJoinType } from './types';
-import { DesignerComponentCreator } from './DesignerComponentCreator';
-import { DesignerQueryDumper } from './DesignerQueryDumper';
-import { getFilterType } from 'dbgate-filterparser';
-
-export function referenceIsConnecting(
- reference: DesignerReferenceInfo,
- tables1: DesignerTableInfo[],
- tables2: DesignerTableInfo[]
-) {
- return (
- (tables1.find(x => x.designerId == reference.sourceId) && tables2.find(x => x.designerId == reference.targetId)) ||
- (tables1.find(x => x.designerId == reference.targetId) && tables2.find(x => x.designerId == reference.sourceId))
- );
-}
-
-export function referenceIsJoin(reference) {
- return ['INNER JOIN', 'LEFT JOIN', 'RIGHT JOIN', 'FULL OUTER JOIN'].includes(reference.joinType);
-}
-export function referenceIsExists(reference) {
- return ['WHERE EXISTS', 'WHERE NOT EXISTS'].includes(reference.joinType);
-}
-export function referenceIsCrossJoin(reference) {
- return !reference.joinType || reference.joinType == 'CROSS JOIN';
-}
-
-export function findConnectingReference(
- designer: DesignerInfo,
- tables1: DesignerTableInfo[],
- tables2: DesignerTableInfo[],
- additionalCondition: (ref: DesignerReferenceInfo) => boolean
-) {
- for (const ref of designer.references || []) {
- if (additionalCondition(ref) && referenceIsConnecting(ref, tables1, tables2)) {
- return ref;
- }
- }
- return null;
-}
-
-export function findQuerySource(designer: DesignerInfo, designerId: string): Source {
- const table = designer.tables.find(x => x.designerId == designerId);
- if (!table) return null;
- return {
- name: table,
- alias: table.alias,
- };
-}
-
-export function mergeSelectsFromDesigner(select1: Select, select2: Select): Select {
- return {
- commandType: 'select',
- from: {
- ...select1.from,
- relations: [
- ...select1.from.relations,
- {
- joinType: 'CROSS JOIN',
- name: select2.from.name,
- alias: select2.from.alias,
- },
- ...select2.from.relations,
- ],
- },
- where: mergeConditions(select1.where, select2.where),
- };
-}
-
-export function findPrimaryTable(tables: DesignerTableInfo[]) {
- return _.minBy(tables, x => x.top);
-}
-
-export function getReferenceConditions(reference: DesignerReferenceInfo, designer: DesignerInfo): Condition[] {
- const sourceTable = designer.tables.find(x => x.designerId == reference.sourceId);
- const targetTable = designer.tables.find(x => x.designerId == reference.targetId);
-
- return reference.columns.map(col => ({
- conditionType: 'binary',
- operator: '=',
- left: {
- exprType: 'column',
- columnName: col.source,
- source: {
- name: sourceTable,
- alias: sourceTable.alias,
- },
- },
- right: {
- exprType: 'column',
- columnName: col.target,
- source: {
- name: targetTable,
- alias: targetTable.alias,
- },
- },
- }));
-}
-
-export function generateDesignedQuery(designer: DesignerInfo, engine: EngineDriver) {
- const { tables, columns, references } = designer;
- const primaryTable = findPrimaryTable(designer.tables);
- if (!primaryTable) return '';
- const componentCreator = new DesignerComponentCreator(designer);
- const designerDumper = new DesignerQueryDumper(designer, componentCreator.components);
- const select = designerDumper.run();
-
- const dmp = engine.createDumper();
- dumpSqlSelect(dmp, select);
- return dmp.s;
-}
-
-export function isConnectedByReference(
- designer: DesignerInfo,
- table1: { designerId: string },
- table2: { designerId: string },
- withoutRef: { designerId: string }
-) {
- if (!designer.references) return false;
- const creator = new DesignerComponentCreator({
- ...designer,
- references: withoutRef
- ? designer.references.filter(x => x.designerId != withoutRef.designerId)
- : designer.references,
- });
- const arrays = creator.components.map(x => x.thisAndSubComponentsTables);
- const array1 = arrays.find(a => a.find(x => x.designerId == table1.designerId));
- const array2 = arrays.find(a => a.find(x => x.designerId == table2.designerId));
- return array1 == array2;
-}
-
-export function findDesignerFilterType({ designerId, columnName }, designer) {
- const table = (designer.tables || []).find(x => x.designerId == designerId);
- if (table) {
- const column = (table.columns || []).find(x => x.columnName == columnName);
- if (column) {
- const { dataType } = column;
- return getFilterType(dataType);
- }
- }
- return 'string';
-}
diff --git a/packages/web/src/designer/types.ts b/packages/web/src/designer/types.ts
deleted file mode 100644
index c746f7ac7..000000000
--- a/packages/web/src/designer/types.ts
+++ /dev/null
@@ -1,44 +0,0 @@
-import { JoinType } from 'dbgate-sqltree';
-import { TableInfo } from 'dbgate-types';
-
-export type DesignerTableInfo = TableInfo & {
- designerId: string;
- alias?: string;
- left: number;
- top: number;
-};
-
-export type DesignerJoinType = JoinType | 'WHERE EXISTS' | 'WHERE NOT EXISTS';
-
-export type DesignerReferenceInfo = {
- designerId: string;
- joinType: DesignerJoinType;
- sourceId: string;
- targetId: string;
- columns: {
- source: string;
- target: string;
- }[];
-};
-
-export type DesignerColumnInfo = {
- designerId: string;
- columnName: string;
- alias?: string;
- isGrouped?: boolean;
- aggregate?: string;
- isOutput?: boolean;
- sortOrder?: number;
- filter?: string;
- groupFilter?: string;
-};
-
-export type DesignerInfo = {
- tables: DesignerTableInfo[];
- columns: DesignerColumnInfo[];
- references: DesignerReferenceInfo[];
-};
-
-// export type DesignerComponent = {
-// tables: DesignerTableInfo[];
-// };
diff --git a/packages/web/src/formview/ChangeSetFormer.ts b/packages/web/src/formview/ChangeSetFormer.ts
deleted file mode 100644
index 11716145c..000000000
--- a/packages/web/src/formview/ChangeSetFormer.ts
+++ /dev/null
@@ -1,93 +0,0 @@
-import {
- ChangeSet,
- changeSetContainsChanges,
- changeSetInsertNewRow,
- createChangeSet,
- deleteChangeSetRows,
- findExistingChangeSetItem,
- getChangeSetInsertedRows,
- TableFormViewDisplay,
- revertChangeSetRowChanges,
- setChangeSetValue,
- ChangeSetRowDefinition,
-} from 'dbgate-datalib';
-import Former from './Former';
-
-export default class ChangeSetFormer extends Former {
- public changeSet: ChangeSet;
- public setChangeSet: Function;
- private batchChangeSet: ChangeSet;
- public rowDefinition: ChangeSetRowDefinition;
- public rowStatus;
-
- constructor(
- public sourceRow: any,
- public changeSetState,
- public dispatchChangeSet,
- public display: TableFormViewDisplay
- ) {
- super();
- this.changeSet = changeSetState && changeSetState.value;
- this.setChangeSet = value => dispatchChangeSet({ type: 'set', value });
- this.batchChangeSet = null;
- this.rowDefinition = display.getChangeSetRow(sourceRow);
- const [matchedField, matchedChangeSetItem] = findExistingChangeSetItem(this.changeSet, this.rowDefinition);
- this.rowData = matchedChangeSetItem ? { ...sourceRow, ...matchedChangeSetItem.fields } : sourceRow;
- let status = 'regular';
- if (matchedChangeSetItem && matchedField == 'updates') status = 'updated';
- if (matchedField == 'deletes') status = 'deleted';
- this.rowStatus = {
- status,
- modifiedFields:
- matchedChangeSetItem && matchedChangeSetItem.fields ? new Set(Object.keys(matchedChangeSetItem.fields)) : null,
- };
- }
-
- applyModification(changeSetReducer) {
- if (this.batchChangeSet) {
- this.batchChangeSet = changeSetReducer(this.batchChangeSet);
- } else {
- this.setChangeSet(changeSetReducer(this.changeSet));
- }
- }
-
- setCellValue(uniqueName: string, value: any) {
- const row = this.sourceRow;
- const definition = this.display.getChangeSetField(row, uniqueName);
- this.applyModification(chs => setChangeSetValue(chs, definition, value));
- }
-
- deleteRow(index: number) {
- this.applyModification(chs => deleteChangeSetRows(chs, this.rowDefinition));
- }
-
- beginUpdate() {
- this.batchChangeSet = this.changeSet;
- }
- endUpdate() {
- this.setChangeSet(this.batchChangeSet);
- this.batchChangeSet = null;
- }
-
- revertRowChanges() {
- this.applyModification(chs => revertChangeSetRowChanges(chs, this.rowDefinition));
- }
- revertAllChanges() {
- this.applyModification(chs => createChangeSet());
- }
- undo() {
- this.dispatchChangeSet({ type: 'undo' });
- }
- redo() {
- this.dispatchChangeSet({ type: 'redo' });
- }
- get canUndo() {
- return this.changeSetState.canUndo;
- }
- get canRedo() {
- return this.changeSetState.canRedo;
- }
- get containsChanges() {
- return changeSetContainsChanges(this.changeSet);
- }
-}
diff --git a/packages/web/src/formview/FormView.js b/packages/web/src/formview/FormView.js
deleted file mode 100644
index 670610a41..000000000
--- a/packages/web/src/formview/FormView.js
+++ /dev/null
@@ -1,583 +0,0 @@
-// @ts-nocheck
-
-import _ from 'lodash';
-import React from 'react';
-import ReactDOM from 'react-dom';
-import ColumnLabel from '../datagrid/ColumnLabel';
-import { findForeignKeyForColumn } from 'dbgate-tools';
-import styled from 'styled-components';
-import useTheme from '../theme/useTheme';
-import useDimensions from '../utility/useDimensions';
-import FormViewToolbar from './FormViewToolbar';
-import { useShowMenu } from '../modals/showMenu';
-import FormViewContextMenu from './FormViewContextMenu';
-import keycodes from '../utility/keycodes';
-import { CellFormattedValue, ShowFormButton } from '../datagrid/DataGridRow';
-import { cellFromEvent } from '../datagrid/selection';
-import InplaceEditor from '../datagrid/InplaceEditor';
-import { copyTextToClipboard } from '../utility/clipboard';
-import { ExpandIcon, FontIcon } from '../icons';
-import openReferenceForm from './openReferenceForm';
-import useOpenNewTab from '../utility/useOpenNewTab';
-import LoadingInfo from '../widgets/LoadingInfo';
-
-const Table = styled.table`
- border-collapse: collapse;
- outline: none;
-`;
-
-const OuterWrapper = styled.div`
- position: absolute;
- left: 0;
- top: 0;
- bottom: 0;
- right: 0;
-`;
-
-const Wrapper = styled.div`
- position: absolute;
- left: 0;
- top: 0;
- bottom: 0;
- right: 0;
- display: flex;
- overflow-x: scroll;
-`;
-
-const TableRow = styled.tr`
- background-color: ${props => props.theme.gridbody_background};
- &:nth-child(6n + 3) {
- background-color: ${props => props.theme.gridbody_background_alt2};
- }
- &:nth-child(6n + 6) {
- background-color: ${props => props.theme.gridbody_background_alt3};
- }
-`;
-
-const TableHeaderCell = styled.td`
- border: 1px solid ${props => props.theme.border};
- text-align: left;
- padding: 2px;
- background-color: ${props => props.theme.gridheader_background};
- overflow: hidden;
- position: relative;
-
- ${props =>
- props.isSelected &&
- `
- background: initial;
- background-color: ${props.theme.gridbody_selection[4]};
- color: ${props.theme.gridbody_invfont1};`}
-`;
-
-const TableBodyCell = styled.td`
- font-weight: normal;
- border: 1px solid ${props => props.theme.border};
- // border-collapse: collapse;
- padding: 2px;
- white-space: nowrap;
- position: relative;
- max-width: 500px;
- overflow: hidden;
- text-overflow: ellipsis;
-
- ${props =>
- props.isSelected &&
- `
- background: initial;
- background-color: ${props.theme.gridbody_selection[4]};
- color: ${props.theme.gridbody_invfont1};`}
-
- ${props =>
- !props.isSelected &&
- props.isModifiedCell &&
- `
- background-color: ${props.theme.gridbody_background_orange[1]};`}
-`;
-
-const FocusField = styled.input`
- // visibility: hidden
- position: absolute;
- left: -1000px;
- top: -1000px;
-`;
-
-const RowCountLabel = styled.div`
- position: absolute;
- background-color: ${props => props.theme.gridbody_background_yellow[1]};
- right: 40px;
- bottom: 20px;
-`;
-
-const HintSpan = styled.span`
- color: gray;
- margin-left: 5px;
- margin-right: 16px;
-`;
-
-const ColumnLabelMargin = styled(ColumnLabel)`
- margin-right: 16px;
-`;
-
-function isDataCell(cell) {
- return cell[1] % 2 == 1;
-}
-
-export default function FormView(props) {
- const {
- toolbarPortalRef,
- tabVisible,
- config,
- setConfig,
- onNavigate,
- former,
- onSave,
- conid,
- database,
- onReload,
- onReconnect,
- allRowCount,
- rowCountBefore,
- onSelectionChanged,
- isLoading,
- } = props;
- /** @type {import('dbgate-datalib').FormViewDisplay} */
- const formDisplay = props.formDisplay;
- const theme = useTheme();
- const [headerRowRef, { height: rowHeight }] = useDimensions();
- const [wrapperRef, { height: wrapperHeight }] = useDimensions();
- const showMenu = useShowMenu();
- const focusFieldRef = React.useRef(null);
- const [currentCell, setCurrentCell] = React.useState([0, 0]);
- const cellRefs = React.useRef({});
- const openNewTab = useOpenNewTab();
-
- const rowCount = Math.floor((wrapperHeight - 20) / rowHeight);
- const columnChunks = _.chunk(formDisplay.columns, rowCount);
-
- const { rowData, rowStatus } = former;
-
- const handleSwitchToTable = () => {
- setConfig(cfg => ({
- ...cfg,
- isFormView: false,
- formViewKey: null,
- }));
- };
-
- const handleFilterThisValue = isDataCell(currentCell)
- ? () => formDisplay.filterCellValue(getCellColumn(currentCell), rowData)
- : null;
-
- const handleContextMenu = event => {
- event.preventDefault();
- showMenu(
- event.pageX,
- event.pageY,
- formDisplay.addFilterColumn(getCellColumn(currentCell))}
- filterThisValue={handleFilterThisValue}
- />
- );
- };
-
- const setCellRef = (row, col, element) => {
- cellRefs.current[`${row},${col}`] = element;
- };
-
- React.useEffect(() => {
- if (tabVisible) {
- if (focusFieldRef.current) focusFieldRef.current.focus();
- }
- }, [tabVisible, focusFieldRef.current]);
-
- React.useEffect(() => {
- if (!onSelectionChanged || !rowData) return;
- const col = getCellColumn(currentCell);
- if (!col) return;
- onSelectionChanged(rowData[col.uniqueName]);
- }, [onSelectionChanged, currentCell, rowData]);
-
- const checkMoveCursorBounds = (row, col) => {
- if (row < 0) row = 0;
- if (col < 0) col = 0;
- if (col >= columnChunks.length * 2) col = columnChunks.length * 2 - 1;
- const chunk = columnChunks[Math.floor(col / 2)];
- if (chunk && row >= chunk.length) row = chunk.length - 1;
- return [row, col];
- };
-
- const handleCursorMove = event => {
- if (event.ctrlKey) {
- switch (event.keyCode) {
- case keycodes.leftArrow:
- return checkMoveCursorBounds(currentCell[0], 0);
- case keycodes.rightArrow:
- return checkMoveCursorBounds(currentCell[0], columnChunks.length * 2 - 1);
- }
- }
- switch (event.keyCode) {
- case keycodes.leftArrow:
- return checkMoveCursorBounds(currentCell[0], currentCell[1] - 1);
- case keycodes.rightArrow:
- return checkMoveCursorBounds(currentCell[0], currentCell[1] + 1);
- case keycodes.upArrow:
- return checkMoveCursorBounds(currentCell[0] - 1, currentCell[1]);
- case keycodes.downArrow:
- return checkMoveCursorBounds(currentCell[0] + 1, currentCell[1]);
- case keycodes.pageUp:
- return checkMoveCursorBounds(0, currentCell[1]);
- case keycodes.pageDown:
- return checkMoveCursorBounds(rowCount - 1, currentCell[1]);
- case keycodes.home:
- return checkMoveCursorBounds(0, 0);
- case keycodes.end:
- return checkMoveCursorBounds(rowCount - 1, columnChunks.length * 2 - 1);
- }
- };
-
- const handleKeyNavigation = event => {
- if (event.ctrlKey) {
- switch (event.keyCode) {
- case keycodes.upArrow:
- return 'previous';
- case keycodes.downArrow:
- return 'next';
- case keycodes.home:
- return 'begin';
- case keycodes.end:
- return 'end';
- }
- }
- };
-
- function handleSave() {
- if (inplaceEditorState.cell) {
- // @ts-ignore
- dispatchInsplaceEditor({ type: 'shouldSave' });
- return;
- }
- if (onSave) onSave();
- }
-
- function getCellColumn(cell) {
- const chunk = columnChunks[Math.floor(cell[1] / 2)];
- if (!chunk) return;
- const column = chunk[cell[0]];
- return column;
- }
-
- function setCellValue(cell, value) {
- const column = getCellColumn(cell);
- if (!column) return;
- former.setCellValue(column.uniqueName, value);
- }
-
- function setNull() {
- if (isDataCell(currentCell)) {
- setCellValue(currentCell, null);
- }
- }
-
- const scrollIntoView = cell => {
- const element = cellRefs.current[`${cell[0]},${cell[1]}`];
- if (element) element.scrollIntoView();
- };
-
- React.useEffect(() => {
- scrollIntoView(currentCell);
- }, [rowData]);
-
- const moveCurrentCell = (row, col) => {
- const moved = checkMoveCursorBounds(row, col);
- setCurrentCell(moved);
- scrollIntoView(moved);
- };
-
- function copyToClipboard() {
- const column = getCellColumn(currentCell);
- if (!column) return;
- const text = currentCell[1] % 2 == 1 ? rowData[column.uniqueName] : column.columnName;
- copyTextToClipboard(text);
- }
-
- const handleKeyDown = event => {
- const navigation = handleKeyNavigation(event);
- if (navigation) {
- event.preventDefault();
- onNavigate(navigation);
- return;
- }
- const moved = handleCursorMove(event);
- if (moved) {
- setCurrentCell(moved);
- scrollIntoView(moved);
- event.preventDefault();
- return;
- }
- if (event.keyCode == keycodes.s && event.ctrlKey) {
- event.preventDefault();
- handleSave();
- // this.saveAndFocus();
- }
-
- if (event.keyCode == keycodes.n0 && event.ctrlKey) {
- event.preventDefault();
- setNull();
- }
-
- if (event.keyCode == keycodes.r && event.ctrlKey) {
- event.preventDefault();
- former.revertRowChanges();
- }
-
- // if (event.keyCode == keycodes.f && event.ctrlKey) {
- // event.preventDefault();
- // filterSelectedValue();
- // }
-
- if (event.keyCode == keycodes.z && event.ctrlKey) {
- event.preventDefault();
- former.undo();
- }
-
- if (event.keyCode == keycodes.y && event.ctrlKey) {
- event.preventDefault();
- former.redo();
- }
-
- if (event.keyCode == keycodes.c && event.ctrlKey) {
- event.preventDefault();
- copyToClipboard();
- }
-
- if (event.keyCode == keycodes.f && event.ctrlKey) {
- event.preventDefault();
- if (handleFilterThisValue) handleFilterThisValue();
- }
-
- if (event.keyCode == keycodes.f5) {
- event.preventDefault();
- onReload();
- }
-
- if (event.keyCode == keycodes.f4) {
- event.preventDefault();
- handleSwitchToTable();
- }
-
- if (
- rowData &&
- !event.ctrlKey &&
- !event.altKey &&
- ((event.keyCode >= keycodes.a && event.keyCode <= keycodes.z) ||
- (event.keyCode >= keycodes.n0 && event.keyCode <= keycodes.n9) ||
- event.keyCode == keycodes.dash)
- ) {
- // @ts-ignore
- dispatchInsplaceEditor({ type: 'show', text: event.nativeEvent.key, cell: currentCell });
- return;
- }
- if (rowData && event.keyCode == keycodes.f2) {
- // @ts-ignore
- dispatchInsplaceEditor({ type: 'show', cell: currentCell, selectAll: true });
- return;
- }
- };
-
- const handleTableMouseDown = event => {
- event.preventDefault();
- if (focusFieldRef.current) focusFieldRef.current.focus();
-
- if (event.target.closest('.buttonLike')) return;
- if (event.target.closest('.resizeHandleControl')) return;
- if (event.target.closest('input')) return;
-
- // event.target.closest('table').focus();
- event.preventDefault();
- if (focusFieldRef.current) focusFieldRef.current.focus();
- const cell = cellFromEvent(event);
-
- if (isDataCell(cell) && !_.isEqual(cell, inplaceEditorState.cell) && _.isEqual(cell, currentCell)) {
- // @ts-ignore
- if (rowData) {
- dispatchInsplaceEditor({ type: 'show', cell, selectAll: true });
- }
- } else if (!_.isEqual(cell, inplaceEditorState.cell)) {
- // @ts-ignore
- dispatchInsplaceEditor({ type: 'close' });
- }
-
- // @ts-ignore
- setCurrentCell(cell);
- };
-
- const getCellWidth = (row, col) => {
- const element = cellRefs.current[`${row},${col}`];
- if (element) return element.getBoundingClientRect().width;
- return 100;
- };
-
- const rowCountInfo = React.useMemo(() => {
- if (rowData == null) return 'No data';
- if (allRowCount == null || rowCountBefore == null) return 'Loading row count...';
- return `Row: ${(rowCountBefore + 1).toLocaleString()} / ${allRowCount.toLocaleString()}`;
- }, [rowCountBefore, allRowCount]);
-
- const [inplaceEditorState, dispatchInsplaceEditor] = React.useReducer((state, action) => {
- switch (action.type) {
- case 'show': {
- const column = getCellColumn(action.cell);
- if (!column) return state;
- if (column.uniquePath.length > 1) return state;
-
- // if (!grider.editable) return {};
- return {
- cell: action.cell,
- text: action.text,
- selectAll: action.selectAll,
- };
- }
- case 'close': {
- const [row, col] = currentCell || [];
- if (focusFieldRef.current) focusFieldRef.current.focus();
- // @ts-ignore
- if (action.mode == 'enter' && row) setTimeout(() => moveCurrentCell(row + 1, col), 0);
- // if (action.mode == 'save') setTimeout(handleSave, 0);
- return {};
- }
- case 'shouldSave': {
- return {
- ...state,
- shouldSave: true,
- };
- }
- }
- return {};
- }, {});
-
- const toolbar =
- toolbarPortalRef &&
- toolbarPortalRef.current &&
- tabVisible &&
- ReactDOM.createPortal(
- ,
- toolbarPortalRef.current
- );
-
- if (isLoading) {
- return (
- <>
-
- {toolbar}
- >
- );
- }
- if (!formDisplay || !formDisplay.isLoadedCorrectly) return toolbar;
-
- return (
-
-
- {columnChunks.map((chunk, chunkIndex) => (
-
- {chunk.map((col, rowIndex) => (
-
- setCellRef(rowIndex, chunkIndex * 2, element)}
- >
- ${col.foreignKey.refTableName}` : null}
- />
-
- {col.foreignKey && (
- {
- e.stopPropagation();
- formDisplay.toggleExpandedColumn(col.uniqueName);
- }}
- >
-
-
- )}
-
- setCellRef(rowIndex, chunkIndex * 2 + 1, element)}
- >
- {inplaceEditorState.cell &&
- rowIndex == inplaceEditorState.cell[0] &&
- chunkIndex * 2 + 1 == inplaceEditorState.cell[1] ? (
- {
- former.setCellValue(col.uniqueName, value);
- }}
- // grider={grider}
- // rowIndex={rowIndex}
- // uniqueName={col.uniqueName}
- />
- ) : (
- <>
- {rowData && (
-
- )}
- {!!col.hintColumnName &&
- rowData &&
- !(rowStatus.modifiedFields && rowStatus.modifiedFields.has(col.uniqueName)) && (
- {rowData[col.hintColumnName]}
- )}
- {col.foreignKey && rowData && rowData[col.uniqueName] && (
- {
- e.stopPropagation();
- openReferenceForm(rowData, col, openNewTab, conid, database);
- }}
- >
-
-
- )}
- >
- )}
-
-
- ))}
-
- ))}
-
-
-
- {toolbar}
-
- {rowCountInfo && {rowCountInfo} }
-
- );
-}
diff --git a/packages/web/src/formview/FormViewContextMenu.js b/packages/web/src/formview/FormViewContextMenu.js
deleted file mode 100644
index 2d55a7508..000000000
--- a/packages/web/src/formview/FormViewContextMenu.js
+++ /dev/null
@@ -1,31 +0,0 @@
-import React from 'react';
-import { DropDownMenuItem, DropDownMenuDivider } from '../modals/DropDownMenu';
-
-export default function FormViewContextMenu({ switchToTable, onNavigate, addToFilter, filterThisValue }) {
- return (
- <>
-
- Table view
-
- {addToFilter && Add to filter }
- {filterThisValue && (
-
- Filter this value
-
- )}
-
- onNavigate('begin')} keyText="Ctrl+Home">
- Navigate to begin
-
- onNavigate('previous')} keyText="Ctrl+Up">
- Navigate to previous
-
- onNavigate('next')} keyText="Ctrl+Down">
- Navigate to next
-
- onNavigate('end')} keyText="Ctrl+End">
- Navigate to end
-
- >
- );
-}
diff --git a/packages/web/src/formview/FormViewFilters.js b/packages/web/src/formview/FormViewFilters.js
deleted file mode 100644
index 2e47b29fa..000000000
--- a/packages/web/src/formview/FormViewFilters.js
+++ /dev/null
@@ -1,116 +0,0 @@
-import React from 'react';
-import _ from 'lodash';
-import { ManagerInnerContainer } from '../datagrid/ManagerStyles';
-import styled from 'styled-components';
-import ColumnLabel from '../datagrid/ColumnLabel';
-import { TextField } from '../utility/inputs';
-import { getFilterType } from 'dbgate-filterparser';
-import DataFilterControl from '../datagrid/DataFilterControl';
-import InlineButton from '../widgets/InlineButton';
-import { FontIcon } from '../icons';
-import keycodes from '../utility/keycodes';
-
-const ColumnWrapper = styled.div`
- margin: 5px;
-`;
-const ColumnNameWrapper = styled.div`
- display: flex;
- justify-content: space-between;
-`;
-
-const TextFieldWrapper = styled.div`
- display: flex;
-`;
-const StyledTextField = styled(TextField)`
- flex: 1;
-`;
-
-function PrimaryKeyFilterEditor({ column, baseTable, formDisplay }) {
- const value = formDisplay.getKeyValue(column.columnName);
- const editorRef = React.useRef(null);
-
- React.useEffect(() => {
- if (editorRef.current) {
- editorRef.current.value = value;
- }
- }, [value, editorRef.current]);
-
- const applyFilter = () => {
- formDisplay.requestKeyValue(column.columnName, editorRef.current.value);
- };
-
- const cancelFilter = () => {
- formDisplay.cancelRequestKey();
- formDisplay.reload();
- };
-
- const handleKeyDown = ev => {
- if (ev.keyCode == keycodes.enter) {
- applyFilter();
- }
- if (ev.keyCode == keycodes.escape) {
- cancelFilter();
- }
- };
-
- return (
-
-
-
-
- x.columnName == column.columnName)} />
-
- {formDisplay.config.formViewKeyRequested && (
-
-
-
- )}
-
-
-
-
-
- );
-}
-
-export default function FormViewFilters(props) {
- const { formDisplay } = props;
- if (!formDisplay || !formDisplay.baseTable || !formDisplay.baseTable.primaryKey) return null;
- const { baseTable } = formDisplay;
- const { formFilterColumns, filters } = formDisplay.config || {};
-
- const allFilterNames = _.union(_.keys(filters || {}), formFilterColumns || []);
-
- return (
-
- {baseTable.primaryKey.columns.map(col => (
-
- ))}
- {allFilterNames.map(uniqueName => {
- const column = formDisplay.columns.find(x => x.uniqueName == uniqueName)
- // const column = baseTable.columns.find(x => x.columnName == columnName);
- if (!column) return null;
- return (
-
-
-
- {
- formDisplay.removeFilter(column.uniqueName);
- }}
- >
-
-
-
- formDisplay.setFilter(column.uniqueName, value)}
- />
-
- );
- })}
-
- );
-}
diff --git a/packages/web/src/formview/FormViewToolbar.js b/packages/web/src/formview/FormViewToolbar.js
deleted file mode 100644
index d418a684a..000000000
--- a/packages/web/src/formview/FormViewToolbar.js
+++ /dev/null
@@ -1,42 +0,0 @@
-import React from 'react';
-import ToolbarButton from '../widgets/ToolbarButton';
-
-export default function FormViewToolbar({ switchToTable, onNavigate, reload, reconnect, former, save }) {
- return (
- <>
-
- Table view
-
- onNavigate('begin')} icon="icon arrow-begin">
- First
-
- onNavigate('previous')} icon="icon arrow-left">
- Previous
-
- onNavigate('next')} icon="icon arrow-right">
- Next
-
- onNavigate('end')} icon="icon arrow-end">
- Last
-
-
- Refresh
-
-
- Reconnect
-
- former.undo()} icon="icon undo">
- Undo
-
- former.redo()} icon="icon redo">
- Redo
-
-
- Save
-
- former.revertAllChanges()} icon="icon close">
- Revert
-
- >
- );
-}
diff --git a/packages/web/src/formview/Former.ts b/packages/web/src/formview/Former.ts
deleted file mode 100644
index cbd1508d2..000000000
--- a/packages/web/src/formview/Former.ts
+++ /dev/null
@@ -1,53 +0,0 @@
-// export interface GriderRowStatus {
-// status: 'regular' | 'updated' | 'deleted' | 'inserted';
-// modifiedFields?: Set;
-// insertedFields?: Set;
-// deletedFields?: Set;
-// }
-
-export default abstract class Former {
- public rowData: any;
-
- // getRowStatus(index): GriderRowStatus {
- // const res: GriderRowStatus = {
- // status: 'regular',
- // };
- // return res;
- // }
- beginUpdate() {}
- endUpdate() {}
- setCellValue(uniqueName: string, value: any) {}
- revertRowChanges() {}
- revertAllChanges() {}
- undo() {}
- redo() {}
- get editable() {
- return false;
- }
- get canInsert() {
- return false;
- }
- get allowSave() {
- return this.containsChanges;
- }
- get canUndo() {
- return false;
- }
- get canRedo() {
- return false;
- }
- get containsChanges() {
- return false;
- }
- get disableLoadNextPage() {
- return false;
- }
- get errors() {
- return null;
- }
- updateRow(changeObject) {
- for (const key of Object.keys(changeObject)) {
- this.setCellValue(key, changeObject[key]);
- }
- }
-}
diff --git a/packages/web/src/formview/SqlFormView.js b/packages/web/src/formview/SqlFormView.js
deleted file mode 100644
index bc1f6ea66..000000000
--- a/packages/web/src/formview/SqlFormView.js
+++ /dev/null
@@ -1,294 +0,0 @@
-import { changeSetToSql, createChangeSet, TableFormViewDisplay } from 'dbgate-datalib';
-import { findEngineDriver } from 'dbgate-tools';
-import React from 'react';
-import { useConnectionInfo, useDatabaseInfo } from '../utility/metadataLoaders';
-import useExtensions from '../utility/useExtensions';
-import FormView from './FormView';
-import axios from '../utility/axios';
-import ChangeSetFormer from './ChangeSetFormer';
-import ConfirmSqlModal from '../modals/ConfirmSqlModal';
-import ErrorMessageModal from '../modals/ErrorMessageModal';
-import { scriptToSql } from 'dbgate-sqltree';
-import useModalState from '../modals/useModalState';
-import useShowModal from '../modals/showModal';
-import stableStringify from 'json-stable-stringify';
-
-async function loadRow(props, sql) {
- const { conid, database } = props;
-
- if (!sql) return null;
-
- const response = await axios.request({
- url: 'database-connections/query-data',
- method: 'post',
- params: {
- conid,
- database,
- },
- data: { sql },
- });
-
- if (response.data.errorMessage) return response.data;
- return response.data.rows[0];
-}
-
-export default function SqlFormView(props) {
- // console.log('SqlFormView', props);
- const {
- formDisplay,
- changeSetState,
- dispatchChangeSet,
- conid,
- database,
- onReferenceSourceChanged,
- refReloadToken,
- } = props;
- // const [rowData, setRowData] = React.useState(null);
- // const [reloadToken, setReloadToken] = React.useState(0);
- // const [rowCountInfo, setRowCountInfo] = React.useState(null);
- // const [isLoading, setIsLoading] = React.useState(false);
- // const loadedFiltersRef = React.useRef('');
-
- const confirmSqlModalState = useModalState();
- const [confirmSql, setConfirmSql] = React.useState('');
- const showModal = useShowModal();
-
- const changeSet = changeSetState && changeSetState.value;
- const changeSetRef = React.useRef(changeSet);
- changeSetRef.current = changeSet;
-
- const [loadProps, setLoadProps] = React.useState({
- isLoadingData: false,
- isLoadedData: false,
- rowData: null,
- isLoadingCount: false,
- isLoadedCount: false,
- loadedTime: new Date().getTime(),
- allRowCount: null,
- rowCountBefore: null,
- errorMessage: null,
- });
- const {
- isLoadingData,
- rowData,
- isLoadedData,
- isLoadingCount,
- isLoadedCount,
- loadedTime,
- allRowCount,
- rowCountBefore,
- errorMessage,
- } = loadProps;
-
- const handleLoadCurrentRow = async () => {
- if (isLoadingData) return;
- let newLoadedRow = false;
- if (formDisplay.config.formViewKeyRequested || formDisplay.config.formViewKey) {
- setLoadProps(oldLoadProps => ({
- ...oldLoadProps,
- isLoadingData: true,
- }));
- const row = await loadRow(props, formDisplay.getCurrentRowQuery());
- setLoadProps(oldLoadProps => ({
- ...oldLoadProps,
- isLoadingData: false,
- isLoadedData: true,
- rowData: row,
- loadedTime: new Date().getTime(),
- }));
- newLoadedRow = row;
- }
- if (formDisplay.config.formViewKeyRequested && newLoadedRow) {
- formDisplay.cancelRequestKey(newLoadedRow);
- }
- if (!newLoadedRow && !formDisplay.config.formViewKeyRequested) {
- await handleNavigate('first');
- }
- };
-
- const handleLoadRowCount = async () => {
- setLoadProps(oldLoadProps => ({
- ...oldLoadProps,
- isLoadingCount: true,
- }));
- const countRow = await loadRow(props, formDisplay.getCountQuery());
- const countBeforeRow = await loadRow(props, formDisplay.getBeforeCountQuery());
-
- setLoadProps(oldLoadProps => ({
- ...oldLoadProps,
- isLoadedCount: true,
- isLoadingCount: false,
- allRowCount: countRow ? parseInt(countRow.count) : null,
- rowCountBefore: countBeforeRow ? parseInt(countBeforeRow.count) : null,
- }));
- };
-
- const handleNavigate = async command => {
- setLoadProps(oldLoadProps => ({
- ...oldLoadProps,
- isLoadingData: true,
- }));
- const row = await loadRow(props, formDisplay.navigateRowQuery(command));
- if (row) {
- formDisplay.navigate(row);
- }
- setLoadProps(oldLoadProps => ({
- ...oldLoadProps,
- isLoadingData: false,
- isLoadedData: true,
- isLoadedCount: false,
- allRowCount: null,
- rowCountBefore: null,
- rowData: row,
- loadedTime: new Date().getTime(),
- }));
- };
-
- React.useEffect(() => {
- if (onReferenceSourceChanged && rowData) onReferenceSourceChanged([rowData], loadedTime);
- }, [onReferenceSourceChanged, rowData, refReloadToken]);
-
- React.useEffect(() => {
- if (!formDisplay.isLoadedCorrectly) return;
- if (!isLoadedData && !isLoadingData) handleLoadCurrentRow();
- if (isLoadedData && !isLoadingCount && !isLoadedCount) handleLoadRowCount();
- });
-
- // React.useEffect(() => {
- // loadedFiltersRef.current = formDisplay ? stableStringify(formDisplay.config) : null;
- // }, [rowData]);
-
- // React.useEffect(() => {
- // if (formDisplay) handleLoadCurrentRow();
- // setRowCountInfo(null);
- // handleLoadRowCount();
- // }, [reloadToken]);
-
- // React.useEffect(() => {
- // if (!formDisplay.isLoadedCorrectly) return;
-
- // if (
- // formDisplay &&
- // (!formDisplay.isLoadedCurrentRow(rowData) ||
- // loadedFiltersRef.current != stableStringify(formDisplay.config.filters))
- // ) {
- // handleLoadCurrentRow();
- // }
- // setRowCountInfo(null);
- // handleLoadRowCount();
- // }, [formDisplay]);
-
- const reload = () => {
- setLoadProps({
- isLoadingData: false,
- isLoadedData: false,
- isLoadingCount: false,
- isLoadedCount: false,
- rowData: null,
- loadedTime: new Date().getTime(),
- allRowCount: null,
- rowCountBefore: null,
- errorMessage: null,
- });
- };
-
- React.useEffect(() => {
- if (props.masterLoadedTime && props.masterLoadedTime > loadedTime) {
- formDisplay.reload();
- }
- if (formDisplay.cache.refreshTime > loadedTime) {
- reload();
- }
- });
-
- const former = React.useMemo(() => new ChangeSetFormer(rowData, changeSetState, dispatchChangeSet, formDisplay), [
- rowData,
- changeSetState,
- dispatchChangeSet,
- formDisplay,
- ]);
-
- function handleSave() {
- const script = changeSetToSql(changeSetRef.current, formDisplay.dbinfo);
- const sql = scriptToSql(formDisplay.driver, script);
- setConfirmSql(sql);
- confirmSqlModalState.open();
- }
-
- async function handleConfirmSql() {
- const resp = await axios.request({
- url: 'database-connections/query-data',
- method: 'post',
- params: {
- conid,
- database,
- },
- data: { sql: confirmSql },
- });
- const { errorMessage } = resp.data || {};
- if (errorMessage) {
- showModal(modalState => (
-
- ));
- } else {
- dispatchChangeSet({ type: 'reset', value: createChangeSet() });
- setConfirmSql(null);
- formDisplay.reload();
- // setReloadToken((x) => x + 1);
- }
- }
-
- // const { config, setConfig, cache, setCache, schemaName, pureName, conid, database } = props;
- // const { formViewKey } = config;
-
- // const [display, setDisplay] = React.useState(null);
-
- // const connection = useConnectionInfo({ conid });
- // const dbinfo = useDatabaseInfo({ conid, database });
- // const extensions = useExtensions();
-
- // console.log('SqlFormView.props', props);
-
- // React.useEffect(() => {
- // const newDisplay = connection
- // ? new TableFormViewDisplay(
- // { schemaName, pureName },
- // findEngineDriver(connection, extensions),
- // config,
- // setConfig,
- // cache,
- // setCache,
- // dbinfo
- // )
- // : null;
- // if (!newDisplay) return;
- // if (display && display.isLoadedCorrectly && !newDisplay.isLoadedCorrectly) return;
- // setDisplay(newDisplay);
- // }, [config, cache, conid, database, schemaName, pureName, dbinfo, extensions]);
-
- return (
- <>
- formDisplay.reload()}
- onReconnect={async () => {
- await axios.post('database-connections/refresh', { conid, database });
- formDisplay.reload();
- }}
- allRowCount={allRowCount}
- rowCountBefore={rowCountBefore}
- />
-
- >
- );
-}
diff --git a/packages/web/src/formview/openReferenceForm.js b/packages/web/src/formview/openReferenceForm.js
deleted file mode 100644
index 00bffeffd..000000000
--- a/packages/web/src/formview/openReferenceForm.js
+++ /dev/null
@@ -1,30 +0,0 @@
-import _ from 'lodash';
-
-export default function openReferenceForm(rowData, column, openNewTab, conid, database) {
- const formViewKey = _.fromPairs(
- column.foreignKey.columns.map(({ refColumnName, columnName }) => [refColumnName, rowData[columnName]])
- );
- openNewTab(
- {
- title: column.foreignKey.refTableName,
- icon: 'img table',
- tabComponent: 'TableDataTab',
- props: {
- schemaName: column.foreignKey.refSchemaName,
- pureName: column.foreignKey.refTableName,
- conid,
- database,
- objectTypeField: 'tables',
- },
- },
- {
- grid: {
- isFormView: true,
- formViewKey,
- },
- },
- {
- forceNewTab: true,
- }
- );
-}
diff --git a/packages/web/src/freetable/FreeTableColumnEditor.js b/packages/web/src/freetable/FreeTableColumnEditor.js
deleted file mode 100644
index 334f2566c..000000000
--- a/packages/web/src/freetable/FreeTableColumnEditor.js
+++ /dev/null
@@ -1,183 +0,0 @@
-import _ from 'lodash';
-import React from 'react';
-import styled from 'styled-components';
-import { ManagerInnerContainer } from '../datagrid/ManagerStyles';
-import { FontIcon } from '../icons';
-import useTheme from '../theme/useTheme';
-import keycodes from '../utility/keycodes';
-
-const Row = styled.div`
- // margin-left: 5px;
- // margin-right: 5px;
- display: flex;
- justify-content: space-between;
- // padding: 5px;
- cursor: pointer;
- &:hover {
- background-color: ${props => props.theme.manager_background_blue[1]};
- }
-`;
-const Name = styled.div`
- white-space: nowrap;
- margin: 5px;
-`;
-const Buttons = styled.div`
- white-space: nowrap;
-`;
-const Icon = styled(FontIcon)`
- // margin-left: 5px;
- position: relative;
- top: 5px;
- &:hover {
- background-color: ${props => props.theme.manager_background3};
- }
- padding: 5px;
-`;
-const EditorInput = styled.input`
- width: calc(100% - 10px);
- background-color: ${props =>
- // @ts-ignore
- props.isError ? props.theme.manager_background_red[1] : props.theme.manager_background};
-`;
-
-function ColumnNameEditor({
- onEnter,
- onBlur = undefined,
- focusOnCreate = false,
- blurOnEnter = false,
- existingNames,
- defaultValue = '',
- ...other
-}) {
- const theme = useTheme();
- const [value, setValue] = React.useState(defaultValue || '');
- const editorRef = React.useRef(null);
- const isError = value && existingNames && existingNames.includes(value);
- const handleKeyDown = event => {
- if (value && event.keyCode == keycodes.enter && !isError) {
- onEnter(value);
- setValue('');
- if (blurOnEnter) editorRef.current.blur();
- }
- if (event.keyCode == keycodes.escape) {
- setValue('');
- editorRef.current.blur();
- }
- };
- const handleBlur = () => {
- if (value && !isError) {
- onEnter(value);
- setValue('');
- }
- if (onBlur) onBlur();
- };
- React.useEffect(() => {
- if (focusOnCreate) editorRef.current.focus();
- }, [focusOnCreate]);
- return (
- setValue(ev.target.value)}
- // @ts-ignore
- isError={isError}
- {...other}
- />
- );
-}
-
-function exchange(array, i1, i2) {
- const i1r = (i1 + array.length) % array.length;
- const i2r = (i2 + array.length) % array.length;
- const res = [...array];
- [res[i1r], res[i2r]] = [res[i2r], res[i1r]];
- return res;
-}
-
-function ColumnManagerRow({ column, onEdit, onRemove, onUp, onDown }) {
- const [isHover, setIsHover] = React.useState(false);
- const theme = useTheme();
- return (
- setIsHover(true)} onMouseLeave={() => setIsHover(false)} theme={theme}>
- {column.columnName}
-
-
-
-
-
-
-
- );
-}
-
-function dispatchChangeColumns(props, func, rowFunc = null) {
- const { modelState, dispatchModel } = props;
- const model = modelState.value;
-
- dispatchModel({
- type: 'set',
- value: {
- rows: rowFunc ? model.rows.map(rowFunc) : model.rows,
- structure: {
- ...model.structure,
- columns: func(model.structure.columns),
- },
- },
- });
-}
-
-export default function FreeTableColumnEditor(props) {
- const { modelState, dispatchModel } = props;
- const [editingColumn, setEditingColumn] = React.useState(null);
- const model = modelState.value;
- return (
- <>
-
- {model.structure.columns.map((column, index) =>
- index == editingColumn ? (
- {
- dispatchChangeColumns(
- props,
- cols => cols.map((col, i) => (index == i ? { columnName } : col)),
- row => _.mapKeys(row, (v, k) => (k == column.columnName ? columnName : k))
- );
- }}
- onBlur={() => setEditingColumn(null)}
- focusOnCreate
- blurOnEnter
- existingNames={model.structure.columns.map(x => x.columnName)}
- />
- ) : (
- setEditingColumn(index)}
- onRemove={() => {
- dispatchChangeColumns(props, cols => cols.filter((c, i) => i != index));
- }}
- onUp={() => {
- dispatchChangeColumns(props, cols => exchange(cols, index, index - 1));
- }}
- onDown={() => {
- dispatchChangeColumns(props, cols => exchange(cols, index, index + 1));
- }}
- />
- )
- )}
- {
- dispatchChangeColumns(props, cols => [...cols, { columnName }]);
- }}
- placeholder="New column"
- existingNames={model.structure.columns.map(x => x.columnName)}
- />
-
- >
- );
-}
diff --git a/packages/web/src/freetable/FreeTableGrid.js b/packages/web/src/freetable/FreeTableGrid.js
deleted file mode 100644
index 33524ae40..000000000
--- a/packages/web/src/freetable/FreeTableGrid.js
+++ /dev/null
@@ -1,92 +0,0 @@
-import { runMacro } from 'dbgate-datalib';
-import React from 'react';
-import _ from 'lodash';
-import styled from 'styled-components';
-
-import { HorizontalSplitter, VerticalSplitter } from '../widgets/Splitter';
-import FreeTableColumnEditor from './FreeTableColumnEditor';
-import FreeTableGridCore from './FreeTableGridCore';
-import MacroDetail from './MacroDetail';
-import MacroManager from './MacroManager';
-import WidgetColumnBar, { WidgetColumnBarItem } from '../widgets/WidgetColumnBar';
-import useTheme from '../theme/useTheme';
-
-const LeftContainer = styled.div`
- background-color: ${props => props.theme.manager_background};
- display: flex;
- flex: 1;
-`;
-
-const DataGridContainer = styled.div`
- position: relative;
- flex-grow: 1;
-`;
-
-function extractMacroValuesForMacro(macroValues, macro) {
- if (!macro) return {};
- return {
- ..._.fromPairs((macro.args || []).filter(x => x.default != null).map(x => [x.name, x.default])),
- ..._.mapKeys(macroValues, (v, k) => k.replace(/^.*#/, '')),
- };
-}
-
-export default function FreeTableGrid(props) {
- const { modelState, dispatchModel } = props;
- const theme = useTheme();
- const [managerSize, setManagerSize] = React.useState(0);
- const [selectedMacro, setSelectedMacro] = React.useState(null);
- const [macroValues, setMacroValues] = React.useState({});
- const [selectedCells, setSelectedCells] = React.useState([]);
- const handleExecuteMacro = () => {
- const newModel = runMacro(
- selectedMacro,
- extractMacroValuesForMacro(macroValues, selectedMacro),
- modelState.value,
- false,
- selectedCells
- );
- dispatchModel({ type: 'set', value: newModel });
- setSelectedMacro(null);
- };
- // console.log('macroValues', macroValues);
- return (
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {!!selectedMacro && (
-
- )}
-
-
-
- );
-}
diff --git a/packages/web/src/freetable/FreeTableGridCore.js b/packages/web/src/freetable/FreeTableGridCore.js
deleted file mode 100644
index 7f518a2bf..000000000
--- a/packages/web/src/freetable/FreeTableGridCore.js
+++ /dev/null
@@ -1,78 +0,0 @@
-import { createGridCache, FreeTableGridDisplay } from 'dbgate-datalib';
-import React from 'react';
-import DataGridCore from '../datagrid/DataGridCore';
-import useShowModal from '../modals/showModal';
-import axios from '../utility/axios';
-import keycodes from '../utility/keycodes';
-import FreeTableGrider from './FreeTableGrider';
-import MacroPreviewGrider from './MacroPreviewGrider';
-import uuidv1 from 'uuid/v1';
-import ImportExportModal from '../modals/ImportExportModal';
-
-export default function FreeTableGridCore(props) {
- const {
- modelState,
- dispatchModel,
- config,
- setConfig,
- macroPreview,
- macroValues,
- onSelectionChanged,
- setSelectedMacro,
- } = props;
- const [cache, setCache] = React.useState(createGridCache());
- const [selectedCells, setSelectedCells] = React.useState([]);
- const showModal = useShowModal();
- const grider = React.useMemo(
- () =>
- macroPreview
- ? new MacroPreviewGrider(modelState.value, macroPreview, macroValues, selectedCells)
- : FreeTableGrider.factory(props),
- [
- ...FreeTableGrider.factoryDeps(props),
- macroPreview,
- macroPreview ? macroValues : null,
- macroPreview ? selectedCells : null,
- ]
- );
- const display = React.useMemo(
- () => new FreeTableGridDisplay(grider.model || modelState.value, config, setConfig, cache, setCache),
- [modelState.value, config, cache, grider]
- );
-
- async function exportGrid() {
- const jslid = uuidv1();
- await axios.post('jsldata/save-free-table', { jslid, data: modelState.value });
- const initialValues = {};
- initialValues.sourceStorageType = 'jsldata';
- initialValues.sourceJslId = jslid;
- initialValues.sourceList = ['editor-data'];
- showModal(modalState => );
- }
-
- const handleSelectionChanged = React.useCallback(
- cells => {
- if (onSelectionChanged) onSelectionChanged(cells);
- setSelectedCells(cells);
- },
- [setSelectedCells]
- );
-
- const handleKeyDown = React.useCallback(event => {
- if (event.keyCode == keycodes.escape) {
- setSelectedMacro(null);
- }
- }, []);
-
- return (
-
- );
-}
diff --git a/packages/web/src/freetable/FreeTableGrider.ts b/packages/web/src/freetable/FreeTableGrider.ts
deleted file mode 100644
index b5b5059bf..000000000
--- a/packages/web/src/freetable/FreeTableGrider.ts
+++ /dev/null
@@ -1,85 +0,0 @@
-import { FreeTableModel } from 'dbgate-datalib';
-import Grider, { GriderRowStatus } from '../datagrid/Grider';
-
-export default class FreeTableGrider extends Grider {
- public model: FreeTableModel;
- private batchModel: FreeTableModel;
-
- constructor(public modelState, public dispatchModel) {
- super();
- this.model = modelState && modelState.value;
- }
- getRowData(index: any) {
- return this.model.rows[index];
- }
- get rowCount() {
- return this.model.rows.length;
- }
- get currentModel(): FreeTableModel {
- return this.batchModel || this.model;
- }
- set currentModel(value) {
- if (this.batchModel) this.batchModel = value;
- else this.dispatchModel({ type: 'set', value });
- }
- setCellValue(index: number, uniqueName: string, value: any) {
- const model = this.currentModel;
- if (model.rows[index])
- this.currentModel = {
- ...model,
- rows: model.rows.map((row, i) => (index == i ? { ...row, [uniqueName]: value } : row)),
- };
- }
- get editable() {
- return true;
- }
- get canInsert() {
- return true;
- }
- get allowSave() {
- return true;
- }
- insertRow(): number {
- const model = this.currentModel;
- this.currentModel = {
- ...model,
- rows: [...model.rows, {}],
- };
- return this.currentModel.rows.length - 1;
- }
- deleteRow(index: number) {
- const model = this.currentModel;
- this.currentModel = {
- ...model,
- rows: model.rows.filter((row, i) => index != i),
- };
- }
- beginUpdate() {
- this.batchModel = this.model;
- }
- endUpdate() {
- if (this.model != this.batchModel) {
- this.dispatchModel({ type: 'set', value: this.batchModel });
- this.batchModel = null;
- }
- }
-
- static factory({ modelState, dispatchModel }): FreeTableGrider {
- return new FreeTableGrider(modelState, dispatchModel);
- }
- static factoryDeps({ modelState, dispatchModel }) {
- return [modelState, dispatchModel];
- }
- undo() {
- this.dispatchModel({ type: 'undo' });
- }
- redo() {
- this.dispatchModel({ type: 'redo' });
- }
- get canUndo() {
- return this.modelState.canUndo;
- }
- get canRedo() {
- return this.modelState.canRedo;
- }
-}
diff --git a/packages/web/src/freetable/MacroDetail.js b/packages/web/src/freetable/MacroDetail.js
deleted file mode 100644
index 078415135..000000000
--- a/packages/web/src/freetable/MacroDetail.js
+++ /dev/null
@@ -1,121 +0,0 @@
-import React from 'react';
-import ToolbarButton from '../widgets/ToolbarButton';
-import styled from 'styled-components';
-import { TabPage, TabControl } from '../widgets/TabControl';
-import dimensions from '../theme/dimensions';
-import GenericEditor from '../sqleditor/GenericEditor';
-import MacroParameters from './MacroParameters';
-import { WidgetTitle } from '../widgets/WidgetStyles';
-import { FormButton } from '../utility/forms';
-import FormStyledButton from '../widgets/FormStyledButton';
-import { FontIcon } from '../icons';
-import useTheme from '../theme/useTheme';
-
-const Container = styled.div`
- display: flex;
- justify-content: space-between;
- align-items: center;
- background: ${props => props.theme.gridheader_background_cyan[0]};
- height: ${dimensions.toolBar.height}px;
- min-height: ${dimensions.toolBar.height}px;
- overflow: hidden;
- border-top: 1px solid ${props => props.theme.border};
- border-bottom: 1px solid ${props => props.theme.border};
-`;
-
-const Header = styled.div`
- font-weight: bold;
- margin-left: 10px;
- display: flex;
-`;
-
-const HeaderText = styled.div`
- margin-left: 10px;
-`;
-
-const MacroDetailContainer = styled.div`
- position: absolute;
- display: flex;
- flex-direction: column;
- top: 0;
- left: 0;
- right: 0;
- bottom: 0;
-`;
-
-const MacroDetailTabWrapper = styled.div`
- display: flex;
- overflow-y: auto;
-`;
-
-const MacroSection = styled.div`
- margin: 5px;
-`;
-
-const TextWrapper = styled.div`
- margin: 5px;
-`;
-
-const Buttons = styled.div`
- display: flex;
-`;
-
-function MacroHeader({ selectedMacro, setSelectedMacro, onExecute }) {
- const theme = useTheme();
- return (
-
-
-
- {selectedMacro.title}
-
-
-
- Execute
-
- setSelectedMacro(null)} patchY={6}>
- Close
-
-
-
- );
-}
-
-export default function MacroDetail({ selectedMacro, setSelectedMacro, onChangeValues, macroValues, onExecute }) {
- return (
-
-
-
-
-
-
- Execute
-
-
-
-
- Parameters
- {selectedMacro.args && selectedMacro.args.length > 0 ? (
-
- ) : (
- This macro has no parameters
- )}
-
-
- Description
- {selectedMacro.description}
-
-
-
-
-
-
-
-
- );
-}
diff --git a/packages/web/src/freetable/MacroManager.js b/packages/web/src/freetable/MacroManager.js
deleted file mode 100644
index cbd288c52..000000000
--- a/packages/web/src/freetable/MacroManager.js
+++ /dev/null
@@ -1,41 +0,0 @@
-import styled from 'styled-components';
-import _ from 'lodash';
-import React from 'react';
-import { ManagerInnerContainer } from '../datagrid/ManagerStyles';
-import SearchInput from '../widgets/SearchInput';
-import { WidgetTitle } from '../widgets/WidgetStyles';
-import macros from './macros';
-import { AppObjectList } from '../appobj/AppObjectList';
-import MacroAppObject from '../appobj/MacroAppObject';
-
-const SearchBoxWrapper = styled.div`
- display: flex;
- margin-bottom: 5px;
-`;
-
-export default function MacroManager({ managerSize, selectedMacro, setSelectedMacro }) {
- const [filter, setFilter] = React.useState('');
-
- return (
- <>
-
-
-
-
- setSelectedMacro(macro)}
- getCommonProps={data => ({
- isBold: selectedMacro && selectedMacro.name == data.name,
- })}
- filter={filter}
- groupFunc={data => data.group}
- />
- {/* {macros.map((macro) => (
-
- ))} */}
-
- >
- );
-}
diff --git a/packages/web/src/freetable/MacroParameters.js b/packages/web/src/freetable/MacroParameters.js
deleted file mode 100644
index 30ad8f885..000000000
--- a/packages/web/src/freetable/MacroParameters.js
+++ /dev/null
@@ -1,17 +0,0 @@
-import React from 'react';
-import _ from 'lodash';
-import FormArgumentList from '../utility/FormArgumentList';
-import { FormProvider } from '../utility/FormProvider';
-
-export default function MacroParameters({ args, onChangeValues, macroValues, namePrefix }) {
- if (!args || args.length == 0) return null;
- const initialValues = {
- ..._.fromPairs(args.filter(x => x.default != null).map(x => [`${namePrefix}${x.name}`, x.default])),
- ...macroValues,
- };
- return (
-
-
-
- );
-}
diff --git a/packages/web/src/freetable/MacroPreviewGrider.ts b/packages/web/src/freetable/MacroPreviewGrider.ts
deleted file mode 100644
index 6503dc09f..000000000
--- a/packages/web/src/freetable/MacroPreviewGrider.ts
+++ /dev/null
@@ -1,40 +0,0 @@
-import { FreeTableModel, MacroDefinition, MacroSelectedCell, runMacro } from 'dbgate-datalib';
-import Grider, { GriderRowStatus } from '../datagrid/Grider';
-import _ from 'lodash';
-
-function convertToSet(row, field) {
- if (!row) return null;
- if (!row[field]) return null;
- if (_.isSet(row[field])) return row[field];
- return new Set(row[field]);
-}
-
-export default class MacroPreviewGrider extends Grider {
- model: FreeTableModel;
- _errors: string[] = [];
- constructor(model: FreeTableModel, macro: MacroDefinition, macroArgs: {}, selectedCells: MacroSelectedCell[]) {
- super();
- this.model = runMacro(macro, macroArgs, model, true, selectedCells, this._errors);
- }
-
- get errors() {
- return this._errors;
- }
-
- getRowStatus(index): GriderRowStatus {
- const row = this.model.rows[index];
- return {
- status: (row && row.__rowStatus) || 'regular',
- modifiedFields: convertToSet(row, '__modifiedFields'),
- insertedFields: convertToSet(row, '__insertedFields'),
- deletedFields: convertToSet(row, '__deletedFields'),
- };
- }
-
- getRowData(index: any) {
- return this.model.rows[index];
- }
- get rowCount() {
- return this.model.rows.length;
- }
-}
diff --git a/packages/web/src/freetable/macros.js b/packages/web/src/freetable/macros.js
deleted file mode 100644
index f614dba4b..000000000
--- a/packages/web/src/freetable/macros.js
+++ /dev/null
@@ -1,273 +0,0 @@
-const macros = [
- {
- title: 'Remove diacritics',
- name: 'removeDiacritics',
- group: 'Text',
- description: 'Removes diacritics from selected cells',
- type: 'transformValue',
- code: `return modules.lodash.deburr(value)`,
- },
- {
- title: 'Search & replace text',
- name: 'stringReplace',
- group: 'Text',
- description: 'Search & replace text or regular expression',
- type: 'transformValue',
- args: [
- {
- type: 'text',
- label: 'Find',
- name: 'find',
- },
- {
- type: 'text',
- label: 'Replace with',
- name: 'replace',
- },
- {
- type: 'checkbox',
- label: 'Case sensitive',
- name: 'caseSensitive',
- },
- {
- type: 'checkbox',
- label: 'Regular expression',
- name: 'isRegex',
- },
- ],
- code: `
-const rtext = args.isRegex ? args.find : modules.lodash.escapeRegExp(args.find);
-const rflags = args.caseSensitive ? 'g' : 'ig';
-return value ? value.toString().replace(new RegExp(rtext, rflags), args.replace || '') : value
- `,
- },
- {
- title: 'Change text case',
- name: 'changeTextCase',
- group: 'Text',
- description: 'Uppercase, lowercase and other case functions',
- type: 'transformValue',
- args: [
- {
- type: 'select',
- options: ['toUpper', 'toLower', 'lowerCase', 'upperCase', 'kebabCase', 'snakeCase', 'camelCase', 'startCase'],
- label: 'Type',
- name: 'type',
- default: 'toUpper',
- },
- ],
- code: `return modules.lodash[args.type](value)`,
- },
- {
- title: 'Row index',
- name: 'rowIndex',
- group: 'Tools',
- description: 'Index of row from 1 (autoincrement)',
- type: 'transformValue',
- code: `return rowIndex + 1`,
- },
- {
- title: 'Generate UUID',
- name: 'uuidv1',
- group: 'Tools',
- description: 'Generate unique identifier',
- type: 'transformValue',
- args: [
- {
- type: 'select',
- options: [
- { value: 'uuidv1', name: 'V1 - from timestamp' },
- { value: 'uuidv4', name: 'V4 - random generated' },
- ],
- label: 'Version',
- name: 'version',
- default: 'uuidv1',
- },
- ],
- code: `return modules[args.version]()`,
- },
- {
- title: 'Current date',
- name: 'currentDate',
- group: 'Tools',
- description: 'Gets current date',
- type: 'transformValue',
- args: [
- {
- type: 'text',
- label: 'Format',
- name: 'format',
- default: 'YYYY-MM-DD HH:mm:ss',
- },
- ],
- code: `return modules.moment().format(args.format)`,
- },
- {
- title: 'Duplicate rows',
- name: 'duplicateRows',
- group: 'Tools',
- description: 'Duplicate selected rows',
- type: 'transformRows',
- code: `
-const selectedRowIndexes = modules.lodash.uniq(selectedCells.map(x => x.row));
-const selectedRows = modules.lodash.groupBy(selectedCells, 'row');
-const maxIndex = modules.lodash.max(selectedRowIndexes);
-return [
- ...rows.slice(0, maxIndex + 1),
- ...selectedRowIndexes.map(index => ({
- ...modules.lodash.pick(rows[index], selectedRows[index].map(x => x.column)),
- __rowStatus: 'inserted',
- })),
- ...rows.slice(maxIndex + 1),
-]
- `,
- },
- {
- title: 'Delete empty rows',
- name: 'deleteEmptyRows',
- group: 'Tools',
- description: 'Delete empty rows - rows with all values null or empty string',
- type: 'transformRows',
- code: `
-return rows.map(row => {
- if (cols.find(col => row[col])) return row;
- return {
- ...row,
- __rowStatus: 'deleted',
- };
-})
-`,
- },
- {
- title: 'Duplicate columns',
- name: 'duplicateColumns',
- group: 'Tools',
- description: 'Duplicate selected columns',
- type: 'transformData',
- code: `
-const selectedColumnNames = modules.lodash.uniq(selectedCells.map(x => x.column));
-const selectedRowIndexes = modules.lodash.uniq(selectedCells.map(x => x.row));
-const addedColumnNames = selectedColumnNames.map(col => (args.prefix || '') + col + (args.postfix || ''));
-const resultRows = rows.map((row, rowIndex) => ({
- ...row,
- ...(selectedRowIndexes.includes(rowIndex) ? modules.lodash.fromPairs(selectedColumnNames.map(col => [(args.prefix || '') + col + (args.postfix || ''), row[col]])) : {}),
- __insertedFields: addedColumnNames,
-}));
-const resultCols = [
- ...cols,
- ...addedColumnNames,
-];
-return {
- rows: resultRows,
- cols: resultCols,
-}
- `,
- args: [
- {
- type: 'text',
- label: 'Prefix',
- name: 'prefix',
- },
- {
- type: 'text',
- label: 'Postfix',
- name: 'postfix',
- default: '_copy',
- },
- ],
- },
- {
- title: 'Extract date fields',
- name: 'extractDateFields',
- group: 'Tools',
- description: 'Extract yaear, month, day and other date/time fields from selection and adds it as new columns',
- type: 'transformData',
- code: `
-const selectedColumnNames = modules.lodash.uniq(selectedCells.map(x => x.column));
-const selectedRowIndexes = modules.lodash.uniq(selectedCells.map(x => x.row));
-const addedColumnNames = modules.lodash.compact([args.year, args.month, args.day, args.hour, args.minute, args.second]);
-const selectedRows = modules.lodash.groupBy(selectedCells, 'row');
-const resultRows = rows.map((row, rowIndex) => {
- if (!selectedRowIndexes.includes(rowIndex)) return {
- ...row,
- __insertedFields: addedColumnNames,
- };
- let mom = null;
- for(const cell of selectedRows[rowIndex]) {
- const m = modules.moment(row[cell.column]);
- if (m.isValid()) {
- mom = m;
- break;
- }
- }
- if (!mom) return {
- ...row,
- __insertedFields: addedColumnNames,
- };
-
- const fields = {
- [args.year]: mom.year(),
- [args.month]: mom.month() + 1,
- [args.day]: mom.day(),
- [args.hour]: mom.hour(),
- [args.minute]: mom.minute(),
- [args.second]: mom.second(),
- };
-
- return {
- ...row,
- ...modules.lodash.pick(fields, addedColumnNames),
- __insertedFields: addedColumnNames,
- }
-});
-const resultCols = [
- ...cols,
- ...addedColumnNames,
-];
-return {
- rows: resultRows,
- cols: resultCols,
-}
- `,
- args: [
- {
- type: 'text',
- label: 'Year name',
- name: 'year',
- default: 'year',
- },
- {
- type: 'text',
- label: 'Month name',
- name: 'month',
- default: 'month',
- },
- {
- type: 'text',
- label: 'Day name',
- name: 'day',
- default: 'day',
- },
- {
- type: 'text',
- label: 'Hour name',
- name: 'hour',
- default: 'hour',
- },
- {
- type: 'text',
- label: 'Minute name',
- name: 'minute',
- default: 'minute',
- },
- {
- type: 'text',
- label: 'Second name',
- name: 'second',
- default: 'second',
- },
- ],
- },
-];
-
-export default macros;
diff --git a/packages/web/src/freetable/useNewFreeTable.js b/packages/web/src/freetable/useNewFreeTable.js
deleted file mode 100644
index 97830a607..000000000
--- a/packages/web/src/freetable/useNewFreeTable.js
+++ /dev/null
@@ -1,14 +0,0 @@
-import _ from 'lodash';
-import useOpenNewTab from '../utility/useOpenNewTab';
-
-export default function useNewFreeTable() {
- const openNewTab = useOpenNewTab();
-
- return ({ title = undefined, ...props } = {}) =>
- openNewTab({
- title: title || 'Data #',
- icon: 'img free-table',
- tabComponent: 'FreeTableTab',
- props,
- });
-}
diff --git a/packages/web/src/icons.js b/packages/web/src/icons.js
deleted file mode 100644
index fac6562c7..000000000
--- a/packages/web/src/icons.js
+++ /dev/null
@@ -1,123 +0,0 @@
-import React from 'react';
-
-const iconNames = {
- 'icon minus-box': 'mdi mdi-minus-box-outline',
- 'icon plus-box': 'mdi mdi-plus-box-outline',
- 'icon invisible-box': 'mdi mdi-minus-box-outline icon-invisible',
- 'icon cloud-upload': 'mdi mdi-cloud-upload',
- 'icon import': 'mdi mdi-application-import',
- 'icon export': 'mdi mdi-application-export',
- 'icon new-connection': 'mdi mdi-database-plus',
- 'icon tables': 'mdi mdi-table-multiple',
- 'icon favorite': 'mdi mdi-star',
- 'icon share': 'mdi mdi-share-variant',
- 'icon add': 'mdi mdi-plus-circle',
- 'icon connection': 'mdi mdi-connection',
-
- 'icon database': 'mdi mdi-database',
- 'icon server': 'mdi mdi-server',
- 'icon table': 'mdi mdi-table',
- 'icon archive': 'mdi mdi-archive',
- 'icon file': 'mdi mdi-file',
- 'icon loading': 'mdi mdi-loading mdi-spin',
- 'icon close': 'mdi mdi-close',
- 'icon filter': 'mdi mdi-filter',
- 'icon filter-off': 'mdi mdi-filter-off',
- 'icon reload': 'mdi mdi-reload',
- 'icon undo': 'mdi mdi-undo',
- 'icon redo': 'mdi mdi-redo',
- 'icon save': 'mdi mdi-content-save',
- 'icon account': 'mdi mdi-account',
- 'icon sql-file': 'mdi mdi-file',
- 'icon web': 'mdi mdi-web',
- 'icon home': 'mdi mdi-home',
- 'icon query-design': 'mdi mdi-vector-polyline-edit',
- 'icon form': 'mdi mdi-form-select',
-
- 'icon edit': 'mdi mdi-pencil',
- 'icon delete': 'mdi mdi-delete',
- 'icon arrow-up': 'mdi mdi-arrow-up',
- 'icon arrow-down': 'mdi mdi-arrow-down',
- 'icon arrow-left': 'mdi mdi-arrow-left',
- 'icon arrow-begin': 'mdi mdi-arrow-collapse-left',
- 'icon arrow-end': 'mdi mdi-arrow-collapse-right',
- 'icon arrow-right': 'mdi mdi-arrow-right',
- 'icon format-code': 'mdi mdi-code-tags-check',
- 'icon show-wizard': 'mdi mdi-comment-edit',
- 'icon disconnected': 'mdi mdi-lan-disconnect',
- 'icon theme': 'mdi mdi-brightness-6',
- 'icon error': 'mdi mdi-close-circle',
- 'icon ok': 'mdi mdi-check-circle',
- 'icon markdown': 'mdi mdi-application',
- 'icon preview': 'mdi mdi-file-find',
- 'icon eye': 'mdi mdi-eye',
-
- 'icon run': 'mdi mdi-play',
- 'icon chevron-down': 'mdi mdi-chevron-down',
- 'icon chevron-left': 'mdi mdi-chevron-left',
- 'icon chevron-right': 'mdi mdi-chevron-right',
- 'icon chevron-up': 'mdi mdi-chevron-up',
- 'icon plugin': 'mdi mdi-toy-brick',
-
- 'img ok': 'mdi mdi-check-circle color-green-8',
- 'img alert': 'mdi mdi-alert-circle color-blue-6',
- 'img error': 'mdi mdi-close-circle color-red-7',
- 'img warn': 'mdi mdi-alert color-gold-7',
- // 'img statusbar-ok': 'mdi mdi-check-circle color-on-statusbar-green',
-
- 'img archive': 'mdi mdi-table color-gold-7',
- 'img archive-folder': 'mdi mdi-database-outline color-green-7',
- 'img autoincrement': 'mdi mdi-numeric-1-box-multiple-outline',
- 'img column': 'mdi mdi-table-column',
- 'img server': 'mdi mdi-server color-blue-7',
- 'img primary-key': 'mdi mdi-key-star color-yellow-7',
- 'img foreign-key': 'mdi mdi-key-link',
- 'img sql-file': 'mdi mdi-file',
- 'img shell': 'mdi mdi-flash color-blue-7',
- 'img chart': 'mdi mdi-chart-bar color-magenta-7',
- 'img markdown': 'mdi mdi-application color-red-7',
- 'img preview': 'mdi mdi-file-find color-red-7',
- 'img favorite': 'mdi mdi-star color-yellow-7',
- 'img query-design': 'mdi mdi-vector-polyline-edit color-red-7',
-
- 'img free-table': 'mdi mdi-table color-green-7',
- 'img macro': 'mdi mdi-hammer-wrench',
-
- 'img database': 'mdi mdi-database color-gold-7',
- 'img table': 'mdi mdi-table color-blue-7',
- 'img view': 'mdi mdi-table color-magenta-7',
- 'img procedure': 'mdi mdi-cog color-blue-7',
- 'img function': 'mdi mdi-function-variant',
-
- 'img sort-asc': 'mdi mdi-sort-alphabetical-ascending color-green',
- 'img sort-desc': 'mdi mdi-sort-alphabetical-descending color-green',
-
- 'img reference': 'mdi mdi-link-box',
- 'img link': 'mdi mdi-link',
- 'img filter': 'mdi mdi-filter',
- 'img group': 'mdi mdi-group',
-};
-
-export function FontIcon({ icon, className = '', ...other }) {
- if (!icon) return null;
- let cls = icon;
- if (icon.startsWith('icon ') || icon.startsWith('img ')) {
- cls = iconNames[icon];
- if (!cls) return null;
- }
- return ;
-}
-
-export function ExpandIcon({ isBlank = false, isExpanded = false, ...other }) {
- if (isBlank) {
- return ;
- }
- return ;
-}
-
-export function ChevronExpandIcon({ isBlank = false, isExpanded = false, ...other }) {
- if (isBlank) {
- return ;
- }
- return ;
-}
diff --git a/packages/web/src/impexp/ImportExportConfigurator.js b/packages/web/src/impexp/ImportExportConfigurator.js
deleted file mode 100644
index 17c843aac..000000000
--- a/packages/web/src/impexp/ImportExportConfigurator.js
+++ /dev/null
@@ -1,580 +0,0 @@
-import React from 'react';
-import _ from 'lodash';
-import FormStyledButton from '../widgets/FormStyledButton';
-import styled from 'styled-components';
-import {
- FormReactSelect,
- FormConnectionSelect,
- FormDatabaseSelect,
- FormTablesSelect,
- FormSchemaSelect,
- FormArchiveFolderSelect,
- FormArchiveFilesSelect,
-} from '../utility/forms';
-import { useArchiveFiles, useConnectionInfo, useDatabaseInfo } from '../utility/metadataLoaders';
-import TableControl, { TableColumn } from '../utility/TableControl';
-import { TextField, SelectField, CheckboxField } from '../utility/inputs';
-import { createPreviewReader, getActionOptions, getTargetName } from './createImpExpScript';
-import getElectron from '../utility/getElectron';
-import ErrorInfo from '../widgets/ErrorInfo';
-import getAsArray from '../utility/getAsArray';
-import LoadingInfo from '../widgets/LoadingInfo';
-import SqlEditor from '../sqleditor/SqlEditor';
-import { useUploadsProvider } from '../utility/UploadsProvider';
-import { FontIcon } from '../icons';
-import useTheme from '../theme/useTheme';
-import { findFileFormat, getFileFormatDirections } from '../utility/fileformats';
-import FormArgumentList from '../utility/FormArgumentList';
-import useExtensions from '../utility/useExtensions';
-import UploadButton from '../utility/UploadButton';
-import useShowModal from '../modals/showModal';
-import ChangeDownloadUrlModal from '../modals/ChangeDownloadUrlModal';
-import { useForm } from '../utility/FormProvider';
-
-const Container = styled.div`
- // max-height: 50vh;
- // overflow-y: scroll;
- flex: 1;
-`;
-
-const Wrapper = styled.div`
- display: flex;
-`;
-
-const SourceListWrapper = styled.div`
- margin: 10px;
-`;
-
-const Column = styled.div`
- margin: 10px;
- flex: 1;
-`;
-
-const Label = styled.div`
- margin: 5px;
- margin-top: 15px;
- color: ${props => props.theme.modal_font2};
-`;
-
-const SourceNameWrapper = styled.div`
- display: flex;
- justify-content: space-between;
-`;
-
-const SourceNameButtons = styled.div`
- display: flex;
-`;
-
-const IconButtonWrapper = styled.div`
- &:hover {
- background-color: ${props => props.theme.modal_background2};
- }
- cursor: pointer;
- color: ${props => props.theme.modal_font_blue[7]};
- margin-left: 5px;
-`;
-
-const SqlWrapper = styled.div`
- position: relative;
- height: 100px;
- width: 20vw;
-`;
-
-const DragWrapper = styled.div`
- padding: 10px;
- background: ${props => props.theme.modal_background2};
-`;
-
-const ArrowWrapper = styled.div`
- font-size: 30px;
- color: ${props => props.theme.modal_font_blue[7]};
- align-self: center;
-`;
-
-const Title = styled.div`
- font-size: 20px;
- text-align: center;
- margin: 10px 0px;
-`;
-
-const ButtonsLine = styled.div`
- display: flex;
-`;
-
-function getFileFilters(extensions, storageType) {
- const res = [];
- const format = findFileFormat(extensions, storageType);
- if (format) res.push({ name: format.name, extensions: [format.extension] });
- res.push({ name: 'All Files', extensions: ['*'] });
- return res;
-}
-
-async function addFileToSourceListDefault({ fileName, shortName, isDownload }, newSources, newValues) {
- const sourceName = shortName;
- newSources.push(sourceName);
- newValues[`sourceFile_${sourceName}`] = {
- fileName,
- isDownload,
- };
-}
-
-async function addFilesToSourceList(extensions, files, values, setValues, preferedStorageType, setPreviewSource) {
- const newSources = [];
- const newValues = {};
- const storage = preferedStorageType || values.sourceStorageType;
- for (const file of getAsArray(files)) {
- const format = findFileFormat(extensions, storage);
- if (format) {
- await (format.addFileToSourceList || addFileToSourceListDefault)(file, newSources, newValues);
- }
- }
- newValues['sourceList'] = [...(values.sourceList || []).filter(x => !newSources.includes(x)), ...newSources];
- if (preferedStorageType && preferedStorageType != values.sourceStorageType) {
- newValues['sourceStorageType'] = preferedStorageType;
- }
- setValues({
- ...values,
- ...newValues,
- });
- if (setPreviewSource && newSources.length == 1) {
- setPreviewSource(newSources[0]);
- }
-}
-
-function ElectronFilesInput() {
- const { values, setValues } = useForm();
- const electron = getElectron();
- const [isLoading, setIsLoading] = React.useState(false);
- const extensions = useExtensions();
-
- const handleClick = async () => {
- const files = electron.remote.dialog.showOpenDialogSync(electron.remote.getCurrentWindow(), {
- properties: ['openFile', 'multiSelections'],
- filters: getFileFilters(extensions, values.sourceStorageType),
- });
- if (files) {
- const path = window.require('path');
- try {
- setIsLoading(true);
- await addFilesToSourceList(
- extensions,
- files.map(full => ({
- fileName: full,
- shortName: path.parse(full).name,
- })),
- values,
- setValues
- );
- } finally {
- setIsLoading(false);
- }
- }
- };
-
- return (
- <>
-
- {isLoading && }
- >
- );
-}
-
-function extractUrlName(url, values) {
- const match = url.match(/\/([^/]+)($|\?)/);
- if (match) {
- const res = match[1];
- if (res.includes('.')) {
- return res.slice(0, res.indexOf('.'));
- }
- return res;
- }
- return `url${values && values.sourceList ? values.sourceList.length + 1 : '1'}`;
-}
-
-function FilesInput({ setPreviewSource = undefined }) {
- const theme = useTheme();
- const electron = getElectron();
- const showModal = useShowModal();
- const { values, setValues } = useForm();
- const extensions = useExtensions();
- const doAddUrl = url => {
- addFilesToSourceList(
- extensions,
- [
- {
- fileName: url,
- shortName: extractUrlName(url, values),
- isDownload: true,
- },
- ],
- values,
- setValues,
- null,
- setPreviewSource
- );
- };
- const handleAddUrl = () =>
- showModal(modalState => );
- return (
- <>
-
- {electron ? : }
-
-
- Drag & drop imported files here
- >
- );
-}
-
-function SourceTargetConfig({
- direction,
- storageTypeField,
- connectionIdField,
- databaseNameField,
- archiveFolderField,
- schemaNameField,
- tablesField = undefined,
- engine = undefined,
- setPreviewSource = undefined,
-}) {
- const extensions = useExtensions();
- const theme = useTheme();
- const { values, setFieldValue } = useForm();
- const types =
- values[storageTypeField] == 'jsldata'
- ? [{ value: 'jsldata', label: 'Query result data', directions: ['source'] }]
- : [
- { value: 'database', label: 'Database', directions: ['source', 'target'] },
- ...extensions.fileFormats.map(format => ({
- value: format.storageType,
- label: `${format.name} files(s)`,
- directions: getFileFormatDirections(format),
- })),
- { value: 'query', label: 'SQL Query', directions: ['source'] },
- { value: 'archive', label: 'Archive', directions: ['source', 'target'] },
- ];
- const storageType = values[storageTypeField];
- const dbinfo = useDatabaseInfo({ conid: values[connectionIdField], database: values[databaseNameField] });
- const archiveFiles = useArchiveFiles({ folder: values[archiveFolderField] });
- const format = findFileFormat(extensions, storageType);
- return (
-
- {direction == 'source' && (
-
- Source configuration
-
- )}
- {direction == 'target' && (
-
- Target configuration
-
- )}
- x.directions.includes(direction))} name={storageTypeField} />
- {(storageType == 'database' || storageType == 'query') && (
- <>
- Server
-
- Database
-
- >
- )}
- {storageType == 'database' && (
- <>
- Schema
-
- {tablesField && (
- <>
- Tables/views
-
-
-
- setFieldValue(
- 'sourceList',
- _.uniq([...(values.sourceList || []), ...(dbinfo && dbinfo.tables.map(x => x.pureName))])
- )
- }
- />
-
- setFieldValue(
- 'sourceList',
- _.uniq([...(values.sourceList || []), ...(dbinfo && dbinfo.views.map(x => x.pureName))])
- )
- }
- />
- setFieldValue('sourceList', [])} />
-
- >
- )}
- >
- )}
- {storageType == 'query' && (
- <>
- Query
-
- setFieldValue('sourceSql', value)}
- engine={engine}
- focusOnCreate
- />
-
- >
- )}
-
- {storageType == 'archive' && (
- <>
- Archive folder
-
- >
- )}
-
- {storageType == 'archive' && direction == 'source' && (
- <>
- Source files
-
-
-
- setFieldValue(
- 'sourceList',
- _.uniq([...(values.sourceList || []), ...(archiveFiles && archiveFiles.map(x => x.name))])
- )
- }
- />
- setFieldValue('sourceList', [])} />
-
- >
- )}
-
- {!!format && direction == 'source' && }
-
- {format && format.args && (
- !arg.direction || arg.direction == direction)}
- namePrefix={`${direction}_${format.storageType}_`}
- />
- )}
-
- );
-}
-
-function SourceName({ name }) {
- const { values, setFieldValue } = useForm();
- const theme = useTheme();
- const showModal = useShowModal();
- const obj = values[`sourceFile_${name}`];
- const handleDelete = () => {
- setFieldValue(
- 'sourceList',
- values.sourceList.filter(x => x != name)
- );
- };
- const doChangeUrl = url => {
- setFieldValue(`sourceFile_${name}`, { fileName: url, isDownload: true });
- };
- const handleChangeUrl = () => {
- showModal(modalState => (
-
- ));
- };
-
- return (
-
- {name}
-
- {obj && !!obj.isDownload && (
-
-
-
- )}
-
-
-
-
-
- );
-}
-
-export default function ImportExportConfigurator({
- uploadedFile = undefined,
- openedFile = undefined,
- onChangePreview = undefined,
-}) {
- const { values, setFieldValue, setValues } = useForm();
- const targetDbinfo = useDatabaseInfo({ conid: values.targetConnectionId, database: values.targetDatabaseName });
- const sourceConnectionInfo = useConnectionInfo({ conid: values.sourceConnectionId });
- const { engine: sourceEngine } = sourceConnectionInfo || {};
- const { sourceList } = values;
- const { setUploadListener } = useUploadsProvider();
- const theme = useTheme();
- const [previewSource, setPreviewSource] = React.useState(null);
- const extensions = useExtensions();
-
- const handleUpload = React.useCallback(
- file => {
- addFilesToSourceList(
- extensions,
- [
- {
- fileName: file.filePath,
- shortName: file.shortName,
- },
- ],
- values,
- setValues,
- !sourceList || sourceList.length == 0 ? file.storageType : null,
- setPreviewSource
- );
- // setFieldValue('sourceList', [...(sourceList || []), file.originalName]);
- },
- [extensions, setFieldValue, sourceList, values]
- );
-
- React.useEffect(() => {
- setUploadListener(() => handleUpload);
- return () => {
- setUploadListener(null);
- };
- }, [handleUpload]);
-
- React.useEffect(() => {
- if (uploadedFile) {
- handleUpload(uploadedFile);
- }
- if (openedFile) {
- addFilesToSourceList(
- extensions,
- [
- {
- fileName: openedFile.filePath,
- shortName: openedFile.shortName,
- },
- ],
- values,
- setValues,
- !sourceList || sourceList.length == 0 ? openedFile.storageType : null,
- setPreviewSource
- );
- }
- }, []);
-
- const supportsPreview =
- !!findFileFormat(extensions, values.sourceStorageType) || values.sourceStorageType == 'archive';
- const previewFileName =
- previewSource && values[`sourceFile_${previewSource}`] && values[`sourceFile_${previewSource}`].fileName;
-
- const handleChangePreviewSource = async () => {
- if (previewSource && supportsPreview) {
- const reader = await createPreviewReader(extensions, values, previewSource);
- if (onChangePreview) onChangePreview(reader);
- } else {
- onChangePreview(null);
- }
- };
-
- React.useEffect(() => {
- handleChangePreviewSource();
- }, [previewSource, supportsPreview, previewFileName]);
-
- const oldValues = React.useRef({});
- React.useEffect(() => {
- const changed = _.pickBy(
- values,
- (v, k) => k.startsWith(`source_${values.sourceStorageType}_`) && oldValues.current[k] != v
- );
- if (!_.isEmpty(changed)) {
- handleChangePreviewSource();
- }
- oldValues.current = values;
- }, [values]);
-
- return (
-
-
-
-
-
-
-
-
-
-
- Map source tables/files
-
-
- } />
- (
- setFieldValue(`actionType_${row}`, e.target.value)}
- />
- )}
- />
- (
- setFieldValue(`targetName_${row}`, e.target.value)}
- />
- )}
- />
-
- supportsPreview ? (
- {
- if (e.target.checked) setPreviewSource(row);
- else setPreviewSource(null);
- }}
- />
- ) : null
- }
- />
-
- {(sourceList || []).length == 0 && }
-
-
- );
-}
diff --git a/packages/web/src/impexp/PreviewDataGrid.js b/packages/web/src/impexp/PreviewDataGrid.js
deleted file mode 100644
index 301348093..000000000
--- a/packages/web/src/impexp/PreviewDataGrid.js
+++ /dev/null
@@ -1,60 +0,0 @@
-import { createGridCache, createGridConfig, FreeTableGridDisplay } from 'dbgate-datalib';
-import React from 'react';
-import DataGridCore from '../datagrid/DataGridCore';
-import RowsArrayGrider from '../datagrid/RowsArrayGrider';
-import axios from '../utility/axios';
-import ErrorInfo from '../widgets/ErrorInfo';
-import LoadingInfo from '../widgets/LoadingInfo';
-
-export default function PreviewDataGrid({ reader, ...other }) {
- const [isLoading, setIsLoading] = React.useState(false);
- const [errorMessage, setErrorMessage] = React.useState(null);
- const [model, setModel] = React.useState(null);
- const [config, setConfig] = React.useState(createGridConfig());
- const [cache, setCache] = React.useState(createGridCache());
- const [grider, setGrider] = React.useState(null);
-
- const handleLoadInitialData = async () => {
- try {
- if (!reader) {
- setModel(null);
- setGrider(null);
- return;
- }
- setErrorMessage(null);
- setIsLoading(true);
- const resp = await axios.post('runners/load-reader', reader);
- // @ts-ignore
- setModel(resp.data);
- setGrider(new RowsArrayGrider(resp.data.rows));
- setIsLoading(false);
- } catch (err) {
- setIsLoading(false);
- const errorMessage = (err && err.response && err.response.data && err.response.data.error) || 'Loading failed';
- setErrorMessage(errorMessage);
- console.error(err.response);
- }
- };
-
- React.useEffect(() => {
- handleLoadInitialData();
- }, [reader]);
-
- const display = React.useMemo(() => new FreeTableGridDisplay(model, config, setConfig, cache, setCache), [
- model,
- config,
- cache,
- grider,
- ]);
-
- if (isLoading) {
- return ;
- }
- if (errorMessage) {
- return ;
- }
-
- if (!grider) return null;
-
- return ;
-}
diff --git a/packages/web/src/impexp/ScriptWriter.js b/packages/web/src/impexp/ScriptWriter.js
deleted file mode 100644
index faf33f909..000000000
--- a/packages/web/src/impexp/ScriptWriter.js
+++ /dev/null
@@ -1,49 +0,0 @@
-import _ from 'lodash';
-import { extractShellApiFunctionName, extractShellApiPlugins } from 'dbgate-tools';
-
-export default class ScriptWriter {
- constructor(varCount = '0') {
- this.s = '';
- this.packageNames = [];
- // this.engines = [];
- this.varCount = parseInt(varCount) || 0;
- }
-
- allocVariable(prefix = 'var') {
- this.varCount += 1;
- return `${prefix}${this.varCount}`;
- }
-
- put(s = '') {
- this.s += s;
- this.s += '\n';
- }
-
- assign(variableName, functionName, props) {
- this.put(`const ${variableName} = await ${extractShellApiFunctionName(functionName)}(${JSON.stringify(props)});`);
- this.packageNames.push(...extractShellApiPlugins(functionName, props));
- }
-
- requirePackage(packageName) {
- this.packageNames.push(packageName);
- }
-
- copyStream(sourceVar, targetVar) {
- this.put(`await dbgateApi.copyStream(${sourceVar}, ${targetVar});`);
- }
-
- comment(s) {
- this.put(`// ${s}`);
- }
-
- getScript(schedule = null) {
- const packageNames = this.packageNames;
- let prefix = _.uniq(packageNames)
- .map(packageName => `// @require ${packageName}\n`)
- .join('');
- if (schedule) prefix += `// @schedule ${schedule}`;
- if (prefix) prefix += '\n';
-
- return prefix + this.s;
- }
-}
diff --git a/packages/web/src/impexp/createImpExpScript.js b/packages/web/src/impexp/createImpExpScript.js
deleted file mode 100644
index b1ff82614..000000000
--- a/packages/web/src/impexp/createImpExpScript.js
+++ /dev/null
@@ -1,240 +0,0 @@
-import _ from 'lodash';
-import ScriptWriter from './ScriptWriter';
-import getAsArray from '../utility/getAsArray';
-import { getConnectionInfo } from '../utility/metadataLoaders';
-import { findEngineDriver, findObjectLike } from 'dbgate-tools';
-import { findFileFormat } from '../utility/fileformats';
-
-export function getTargetName(extensions, source, values) {
- const key = `targetName_${source}`;
- if (values[key]) return values[key];
- const format = findFileFormat(extensions, values.targetStorageType);
- if (format) {
- const res = format.getDefaultOutputName ? format.getDefaultOutputName(source, values) : null;
- if (res) return res;
- return `${source}.${format.extension}`;
- }
- return source;
-}
-
-function extractApiParameters(values, direction, format) {
- const pairs = (format.args || [])
- .filter(arg => arg.apiName)
- .map(arg => [arg.apiName, values[`${direction}_${format.storageType}_${arg.name}`]])
- .filter(x => x[1] != null);
- return _.fromPairs(pairs);
-}
-
-async function getConnection(extensions, storageType, conid, database) {
- if (storageType == 'database' || storageType == 'query') {
- const conn = await getConnectionInfo({ conid });
- const driver = findEngineDriver(conn, extensions);
- return [
- {
- ..._.omit(conn, ['_id', 'displayName']),
- database,
- },
- driver,
- ];
- }
- return [null, null];
-}
-
-function getSourceExpr(extensions, sourceName, values, sourceConnection, sourceDriver) {
- const { sourceStorageType } = values;
- if (sourceStorageType == 'database') {
- const fullName = { schemaName: values.sourceSchemaName, pureName: sourceName };
- return [
- 'tableReader',
- {
- connection: sourceConnection,
- ...fullName,
- },
- ];
- }
- if (sourceStorageType == 'query') {
- return [
- 'queryReader',
- {
- connection: sourceConnection,
- sql: values.sourceSql,
- },
- ];
- }
- if (findFileFormat(extensions, sourceStorageType)) {
- const sourceFile = values[`sourceFile_${sourceName}`];
- const format = findFileFormat(extensions, sourceStorageType);
- if (format && format.readerFunc) {
- return [
- format.readerFunc,
- {
- ..._.omit(sourceFile, ['isDownload']),
- ...extractApiParameters(values, 'source', format),
- },
- ];
- }
- }
- if (sourceStorageType == 'jsldata') {
- return ['jslDataReader', { jslid: values.sourceJslId }];
- }
- if (sourceStorageType == 'archive') {
- return [
- 'archiveReader',
- {
- folderName: values.sourceArchiveFolder,
- fileName: sourceName,
- },
- ];
- }
- throw new Error(`Unknown source storage type: ${sourceStorageType}`);
-}
-
-function getFlagsFroAction(action) {
- switch (action) {
- case 'dropCreateTable':
- return {
- createIfNotExists: true,
- dropIfExists: true,
- };
- case 'truncate':
- return {
- createIfNotExists: true,
- truncate: true,
- };
- }
-
- return {
- createIfNotExists: true,
- };
-}
-
-function getTargetExpr(extensions, sourceName, values, targetConnection, targetDriver) {
- const { targetStorageType } = values;
- const format = findFileFormat(extensions, targetStorageType);
- if (format && format.writerFunc) {
- const outputParams = format.getOutputParams && format.getOutputParams(sourceName, values);
- return [
- format.writerFunc,
- {
- ...(outputParams
- ? outputParams
- : {
- fileName: getTargetName(extensions, sourceName, values),
- }),
- ...extractApiParameters(values, 'target', format),
- },
- ];
- }
- if (targetStorageType == 'database') {
- return [
- 'tableWriter',
- {
- connection: targetConnection,
- schemaName: values.targetSchemaName,
- pureName: getTargetName(extensions, sourceName, values),
- ...getFlagsFroAction(values[`actionType_${sourceName}`]),
- },
- ];
- }
- if (targetStorageType == 'archive') {
- return [
- 'archiveWriter',
- {
- folderName: values.targetArchiveFolder,
- fileName: getTargetName(extensions, sourceName, values),
- },
- ];
- }
-
- throw new Error(`Unknown target storage type: ${targetStorageType}`);
-}
-
-export default async function createImpExpScript(extensions, values, addEditorInfo = true) {
- const script = new ScriptWriter(values.startVariableIndex || 0);
-
- const [sourceConnection, sourceDriver] = await getConnection(
- extensions,
- values.sourceStorageType,
- values.sourceConnectionId,
- values.sourceDatabaseName
- );
- const [targetConnection, targetDriver] = await getConnection(
- extensions,
- values.targetStorageType,
- values.targetConnectionId,
- values.targetDatabaseName
- );
-
- const sourceList = getAsArray(values.sourceList);
- for (const sourceName of sourceList) {
- const sourceVar = script.allocVariable();
- // @ts-ignore
- script.assign(sourceVar, ...getSourceExpr(extensions, sourceName, values, sourceConnection, sourceDriver));
-
- const targetVar = script.allocVariable();
- // @ts-ignore
- script.assign(targetVar, ...getTargetExpr(extensions, sourceName, values, targetConnection, targetDriver));
-
- script.copyStream(sourceVar, targetVar);
- script.put();
- }
- if (addEditorInfo) {
- script.comment('@ImportExportConfigurator');
- script.comment(JSON.stringify(values));
- }
- return script.getScript(values.schedule);
-}
-
-export function getActionOptions(extensions, source, values, targetDbinfo) {
- const res = [];
- const targetName = getTargetName(extensions, source, values);
- if (values.targetStorageType == 'database') {
- let existing = findObjectLike(
- { schemaName: values.targetSchemaName, pureName: targetName },
- targetDbinfo,
- 'tables'
- );
- if (existing) {
- res.push({
- label: 'Append data',
- value: 'appendData',
- });
- res.push({
- label: 'Truncate and import',
- value: 'truncate',
- });
- res.push({
- label: 'Drop and create table',
- value: 'dropCreateTable',
- });
- } else {
- res.push({
- label: 'Create table',
- value: 'createTable',
- });
- }
- } else {
- res.push({
- label: 'Create file',
- value: 'createFile',
- });
- }
- return res;
-}
-
-export async function createPreviewReader(extensions, values, sourceName) {
- const [sourceConnection, sourceDriver] = await getConnection(
- extensions,
- values.sourceStorageType,
- values.sourceConnectionId,
- values.sourceDatabaseName
- );
- const [functionName, props] = getSourceExpr(extensions, sourceName, values, sourceConnection, sourceDriver);
- return {
- functionName,
- props: {
- ...props,
- limitRows: 100,
- },
- };
-}
diff --git a/packages/web/src/index.css b/packages/web/src/index.css
deleted file mode 100644
index 18ce2e20b..000000000
--- a/packages/web/src/index.css
+++ /dev/null
@@ -1,52 +0,0 @@
-body {
- 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;
- */
- -webkit-font-smoothing: antialiased;
- -moz-osx-font-smoothing: grayscale;
-}
-
-code {
- font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', monospace;
-}
-
-.RactModalOverlay {
- position: fixed;
- top: 0;
- left: 0;
- right: 0;
- bottom: 0;
- background-color: #00000080;
-}
-
-.icon-invisible {
- visibility: hidden;
-}
-
-.largeFormMarker input[type='text'] {
- width: 100%;
- padding: 10px 10px;
- font-size: 14px;
- box-sizing: border-box;
- border-radius: 4px;
-}
-
-.largeFormMarker input[type='password'] {
- width: 100%;
- padding: 10px 10px;
- font-size: 14px;
- box-sizing: border-box;
- border-radius: 4px;
-}
-
-.largeFormMarker select {
- width: 100%;
- padding: 10px 10px;
- font-size: 14px;
- box-sizing: border-box;
- border-radius: 4px;
-}
diff --git a/packages/web/src/index.js b/packages/web/src/index.js
deleted file mode 100644
index 6cb89510d..000000000
--- a/packages/web/src/index.js
+++ /dev/null
@@ -1,43 +0,0 @@
-import React from 'react';
-import ReactDOM from 'react-dom';
-import _ from 'lodash';
-import './index.css';
-import '@mdi/font/css/materialdesignicons.css';
-import App from './App';
-import * as serviceWorker from './serviceWorker';
-
-import 'ace-builds/src-noconflict/mode-sql';
-import 'ace-builds/src-noconflict/mode-mysql';
-import 'ace-builds/src-noconflict/mode-pgsql';
-import 'ace-builds/src-noconflict/mode-sqlserver';
-import 'ace-builds/src-noconflict/mode-json';
-import 'ace-builds/src-noconflict/mode-javascript';
-import 'ace-builds/src-noconflict/mode-markdown';
-import 'ace-builds/src-noconflict/theme-github';
-import 'ace-builds/src-noconflict/theme-twilight';
-import 'ace-builds/src-noconflict/ext-searchbox';
-import 'ace-builds/src-noconflict/ext-language_tools';
-import localStorageGarbageCollector from './utility/localStorageGarbageCollector';
-// import 'ace-builds/src-noconflict/snippets/sqlserver';
-// import 'ace-builds/src-noconflict/snippets/pgsql';
-// import 'ace-builds/src-noconflict/snippets/mysql';
-
-localStorageGarbageCollector();
-window['dbgate_tabExports'] = {};
-window['dbgate_getCurrentTabCommands'] = () => {
- const tabid = window['dbgate_activeTabId'];
- return _.mapValues(window['dbgate_tabExports'][tabid] || {}, v => !!v);
-};
-window['dbgate_tabCommand'] = cmd => {
- const tabid = window['dbgate_activeTabId'];
- const commands = window['dbgate_tabExports'][tabid];
- const func = (commands || {})[cmd];
- if (func) func();
-};
-
-ReactDOM.render( , document.getElementById('root'));
-
-// If you want your app to work offline and load faster, you can change
-// unregister() to register() below. Note this comes with some pitfalls.
-// Learn more about service workers: https://bit.ly/CRA-PWA
-serviceWorker.unregister();
diff --git a/packages/web/src/markdown/MarkdownExtendedView.js b/packages/web/src/markdown/MarkdownExtendedView.js
deleted file mode 100644
index 12190d12b..000000000
--- a/packages/web/src/markdown/MarkdownExtendedView.js
+++ /dev/null
@@ -1,34 +0,0 @@
-import React from 'react';
-import Markdown from 'markdown-to-jsx';
-import styled from 'styled-components';
-import OpenChartLink from './OpenChartLink';
-import MarkdownLink from './MarkdownLink';
-import OpenSqlLink from './OpenSqlLink';
-
-const Wrapper = styled.div`
- padding: 10px;
- overflow: auto;
- flex: 1;
-`;
-
-export default function MarkdownExtendedView({ children }) {
- return (
-
-
- {children || ''}
-
-
- );
-}
diff --git a/packages/web/src/markdown/MarkdownLink.js b/packages/web/src/markdown/MarkdownLink.js
deleted file mode 100644
index d201cf64e..000000000
--- a/packages/web/src/markdown/MarkdownLink.js
+++ /dev/null
@@ -1,13 +0,0 @@
-import React from 'react';
-import useTheme from '../theme/useTheme';
-import { StyledThemedLink } from '../widgets/FormStyledButton';
-
-export default function MarkdownLink({ href, title, children }) {
- const theme = useTheme();
-
- return (
-
- {children}
-
- );
-}
diff --git a/packages/web/src/markdown/MarkdownToolbar.js b/packages/web/src/markdown/MarkdownToolbar.js
deleted file mode 100644
index 7c87dab63..000000000
--- a/packages/web/src/markdown/MarkdownToolbar.js
+++ /dev/null
@@ -1,12 +0,0 @@
-import React from 'react';
-import ToolbarButton from '../widgets/ToolbarButton';
-
-export default function MarkdownToolbar({ showPreview }) {
- return (
- <>
-
- Preview
-
- >
- );
-}
diff --git a/packages/web/src/markdown/OpenChartLink.js b/packages/web/src/markdown/OpenChartLink.js
deleted file mode 100644
index 481bb446e..000000000
--- a/packages/web/src/markdown/OpenChartLink.js
+++ /dev/null
@@ -1,35 +0,0 @@
-import React from 'react';
-import { useCurrentDatabase } from '../utility/globalState';
-import axios from '../utility/axios';
-import useTheme from '../theme/useTheme';
-import { StyledThemedLink } from '../widgets/FormStyledButton';
-import useOpenNewTab from '../utility/useOpenNewTab';
-
-export default function OpenChartLink({ file, children }) {
- const openNewTab = useOpenNewTab();
- const currentDb = useCurrentDatabase();
- const theme = useTheme();
-
- const handleClick = async () => {
- const resp = await axios.post('files/load', { folder: 'charts', file, format: 'json' });
- openNewTab(
- {
- title: file,
- icon: 'img chart',
- tabComponent: 'ChartTab',
- props: {
- conid: currentDb && currentDb.connection && currentDb.connection._id,
- database: currentDb && currentDb.name,
- savedFile: file,
- },
- },
- { editor: resp.data }
- );
- };
-
- return (
-
- {children}
-
- );
-}
diff --git a/packages/web/src/markdown/OpenSqlLink.js b/packages/web/src/markdown/OpenSqlLink.js
deleted file mode 100644
index cce857f89..000000000
--- a/packages/web/src/markdown/OpenSqlLink.js
+++ /dev/null
@@ -1,26 +0,0 @@
-import React from 'react';
-import axios from '../utility/axios';
-import useTheme from '../theme/useTheme';
-import { StyledThemedLink } from '../widgets/FormStyledButton';
-import useNewQuery from '../query/useNewQuery';
-
-export default function OpenSqlLink({ file, children }) {
- const newQuery = useNewQuery();
- const theme = useTheme();
-
- const handleClick = async () => {
- const resp = await axios.post('files/load', { folder: 'sql', file, format: 'text' });
- newQuery({
- title: file,
- initialData: resp.data,
- // @ts-ignore
- savedFile: file,
- });
- };
-
- return (
-
- {children}
-
- );
-}
diff --git a/packages/web/src/modals/AboutModal.js b/packages/web/src/modals/AboutModal.js
deleted file mode 100644
index 152e346be..000000000
--- a/packages/web/src/modals/AboutModal.js
+++ /dev/null
@@ -1,93 +0,0 @@
-import React from 'react';
-import ModalBase from './ModalBase';
-import ModalHeader from './ModalHeader';
-import ModalContent from './ModalContent';
-import ModalFooter from './ModalFooter';
-import { useConfig } from '../utility/metadataLoaders';
-import FormStyledButton from '../widgets/FormStyledButton';
-import moment from 'moment';
-import styled from 'styled-components';
-import getElectron from '../utility/getElectron';
-import useTheme from '../theme/useTheme';
-import { StyledThemedLink } from '../widgets/FormStyledButton';
-
-const Container = styled.div`
- display: flex;
-`;
-
-const TextContainer = styled.div``;
-
-const StyledLine = styled.div`
- margin: 5px;
-`;
-
-const StyledValue = styled.span`
- font-weight: bold;
-`;
-
-function Line({ label, children }) {
- return (
-
- {label}: {children}
-
- );
-}
-
-function Link({ label, children, href }) {
- const electron = getElectron();
- const theme = useTheme();
- return (
-
- {label}:{' '}
- {electron ? (
- electron.shell.openExternal(href)}>
- {children}
-
- ) : (
-
- {children}
-
- )}
-
- );
-}
-
-export default function AboutModal({ modalState }) {
- const config = useConfig();
- const { version, buildTime } = config || {};
- return (
-
- About DbGate
-
-
-
-
- {version}
- {moment(buildTime).format('YYYY-MM-DD')}
-
- dbgate.org
-
-
- github
-
-
- docker hub
-
-
- demo.dbgate.org
-
-
- npmjs.com
-
-
-
-
-
- modalState.close()} />
-
-
- );
-}
diff --git a/packages/web/src/modals/ChangeDownloadUrlModal.js b/packages/web/src/modals/ChangeDownloadUrlModal.js
deleted file mode 100644
index ce0b08e70..000000000
--- a/packages/web/src/modals/ChangeDownloadUrlModal.js
+++ /dev/null
@@ -1,42 +0,0 @@
-import React from 'react';
-import ModalBase from './ModalBase';
-import { FormButton, FormSubmit, FormTextField } from '../utility/forms';
-import ModalHeader from './ModalHeader';
-import ModalContent from './ModalContent';
-import ModalFooter from './ModalFooter';
-import FormStyledButton from '../widgets/FormStyledButton';
-import { FormProvider } from '../utility/FormProvider';
-
-export default function ChangeDownloadUrlModal({ modalState, url = '', onConfirm = undefined }) {
- // const textFieldRef = React.useRef(null);
- // React.useEffect(() => {
- // if (textFieldRef.current) textFieldRef.current.focus();
- // }, [textFieldRef.current]);
-
- // const handleSubmit = () => async (values) => {
- // onConfirm(values.url);
- // modalState.close();
- // };
-
- const handleSubmit = React.useCallback(
- async values => {
- onConfirm(values.url);
- modalState.close();
- },
- [modalState, onConfirm]
- );
- return (
-
- Download imported file from web
-
-
-
-
-
-
- modalState.close()} />
-
-
-
- );
-}
diff --git a/packages/web/src/modals/ConfirmModal.js b/packages/web/src/modals/ConfirmModal.js
deleted file mode 100644
index c6e9db5c6..000000000
--- a/packages/web/src/modals/ConfirmModal.js
+++ /dev/null
@@ -1,28 +0,0 @@
-import React from 'react';
-import ModalBase from './ModalBase';
-import FormStyledButton from '../widgets/FormStyledButton';
-import ModalFooter from './ModalFooter';
-import ModalContent from './ModalContent';
-import { FormSubmit } from '../utility/forms';
-import { FormProvider } from '../utility/FormProvider';
-
-export default function ConfirmModal({ message, modalState, onConfirm }) {
- return (
-
-
- {message}
-
-
- {
- modalState.close();
- onConfirm();
- }}
- />
-
-
-
-
- );
-}
diff --git a/packages/web/src/modals/ConfirmSqlModal.js b/packages/web/src/modals/ConfirmSqlModal.js
deleted file mode 100644
index 0b66bb278..000000000
--- a/packages/web/src/modals/ConfirmSqlModal.js
+++ /dev/null
@@ -1,46 +0,0 @@
-import React from 'react';
-import ModalBase from './ModalBase';
-import FormStyledButton from '../widgets/FormStyledButton';
-import SqlEditor from '../sqleditor/SqlEditor';
-import styled from 'styled-components';
-import keycodes from '../utility/keycodes';
-import ModalHeader from './ModalHeader';
-import ModalContent from './ModalContent';
-import ModalFooter from './ModalFooter';
-
-const SqlWrapper = styled.div`
- position: relative;
- height: 30vh;
- width: 40vw;
-`;
-
-export default function ConfirmSqlModal({ modalState, sql, engine, onConfirm }) {
- const handleKeyDown = (data, hash, keyString, keyCode, event) => {
- if (keyCode == keycodes.enter) {
- event.preventDefault();
- modalState.close();
- onConfirm();
- }
- };
- return (
-
- Save changes
-
-
-
-
-
-
-
- {
- modalState.close();
- onConfirm();
- }}
- />
-
-
-
- );
-}
diff --git a/packages/web/src/modals/ConnectionModal.js b/packages/web/src/modals/ConnectionModal.js
deleted file mode 100644
index a1b1bcfc9..000000000
--- a/packages/web/src/modals/ConnectionModal.js
+++ /dev/null
@@ -1,349 +0,0 @@
-import React from 'react';
-import axios from '../utility/axios';
-import ModalBase from './ModalBase';
-import {
- FormButton,
- FormTextField,
- FormSelectField,
- FormSubmit,
- FormPasswordField,
- FormCheckboxField,
- FormElectronFileSelector,
-} from '../utility/forms';
-import ModalHeader from './ModalHeader';
-import ModalFooter from './ModalFooter';
-import ModalContent from './ModalContent';
-import useExtensions from '../utility/useExtensions';
-import LoadingInfo from '../widgets/LoadingInfo';
-import { FontIcon } from '../icons';
-import { FormProvider, useForm } from '../utility/FormProvider';
-import { TabControl, TabPage } from '../widgets/TabControl';
-import { usePlatformInfo } from '../utility/metadataLoaders';
-import getElectron from '../utility/getElectron';
-import { FormFieldTemplateLarge, FormRowLarge } from '../utility/formStyle';
-import styled from 'styled-components';
-import { FlexCol3, FlexCol6, FlexCol9 } from '../utility/flexGrid';
-// import FormikForm from '../utility/FormikForm';
-
-const FlexContainer = styled.div`
- display: flex;
-`;
-
-const TestResultContainer = styled.div`
- margin-left: 10px;
- align-self: center;
- white-space: nowrap;
- overflow: hidden;
- text-overflow: ellipsis;
-`;
-
-const ButtonsContainer = styled.div`
- flex-shrink: 0;
-`;
-
-const AgentInfoWrap = styled.div`
- margin-left: 20px;
- margin-bottom: 20px;
-`;
-
-function DriverFields({ extensions }) {
- const { values, setFieldValue } = useForm();
- const { authType, engine } = values;
- const driver = extensions.drivers.find(x => x.engine == engine);
- // const { authTypes } = driver || {};
- const [authTypes, setAuthTypes] = React.useState(null);
- const currentAuthType = authTypes && authTypes.find(x => x.name == authType);
-
- const loadAuthTypes = async () => {
- const resp = await axios.post('plugins/auth-types', { engine });
- setAuthTypes(resp.data);
- if (resp.data && !currentAuthType) {
- setFieldValue('authType', resp.data[0].name);
- }
- };
-
- React.useEffect(() => {
- setAuthTypes(null);
- loadAuthTypes();
- }, [values.engine]);
-
- if (!driver) return null;
- const disabledFields = (currentAuthType ? currentAuthType.disabledFields : null) || [];
-
- return (
- <>
- {!!authTypes && (
-
- {authTypes.map(auth => (
-
- {auth.title}
-
- ))}
-
- )}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {!disabledFields.includes('password') && (
-
- Save and encrypt
- Save raw (UNSAFE!!)
-
- )}
- >
- );
-}
-
-function SshTunnelFields() {
- const { values, setFieldValue } = useForm();
- const { useSshTunnel, sshMode, sshPort, sshKeyfile } = values;
- const platformInfo = usePlatformInfo();
- const electron = getElectron();
-
- React.useEffect(() => {
- if (useSshTunnel && !sshMode) {
- setFieldValue('sshMode', 'userPassword');
- }
- if (useSshTunnel && !sshPort) {
- setFieldValue('sshPort', '22');
- }
- if (useSshTunnel && sshMode == 'keyFile' && !sshKeyfile) {
- setFieldValue('sshKeyfile', platformInfo.defaultKeyFile);
- }
- }, [useSshTunnel, sshMode]);
-
- return (
- <>
-
-
-
-
-
-
-
-
-
-
-
-
- Username & password
- SSH agent
- {!!electron && Key file }
-
-
- {sshMode != 'userPassword' && }
-
- {sshMode == 'userPassword' && (
-
-
-
-
-
-
-
-
- )}
-
- {sshMode == 'keyFile' && (
-
-
-
-
-
-
-
-
- )}
-
- {useSshTunnel && sshMode == 'agent' && (
-
- {platformInfo.sshAuthSock ? (
-
- SSH Agent found
-
- ) : (
-
- SSH Agent not found
-
- )}
-
- )}
- >
- );
-}
-
-function SslFields() {
- const { values } = useForm();
- const { useSsl } = values;
- const electron = getElectron();
-
- return (
- <>
-
-
-
-
-
- >
- );
-}
-
-export default function ConnectionModal({ modalState, connection = undefined }) {
- const [sqlConnectResult, setSqlConnectResult] = React.useState(null);
- const extensions = useExtensions();
- const [isTesting, setIsTesting] = React.useState(false);
- const testIdRef = React.useRef(0);
-
- const handleTest = async values => {
- setIsTesting(true);
- testIdRef.current += 1;
- const testid = testIdRef.current;
- const resp = await axios.post('connections/test', values);
- if (testIdRef.current != testid) return;
-
- setIsTesting(false);
- setSqlConnectResult(resp.data);
- };
-
- const handleCancel = async () => {
- testIdRef.current += 1; // invalidate current test
- setIsTesting(false);
- };
-
- const handleSubmit = async values => {
- axios.post('connections/save', values);
- modalState.close();
- };
- return (
-
- {connection ? 'Edit connection' : 'Add connection'}
-
-
-
-
-
-
- {extensions.drivers.map(driver => (
-
- {driver.title}
-
- ))}
- {/* Microsoft SQL Server
- MySQL
- Postgre SQL */}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {isTesting ? (
-
- ) : (
-
- )}
-
-
-
-
-
- {!isTesting && sqlConnectResult && sqlConnectResult.msgtype == 'connected' && (
-
- Connected: {sqlConnectResult.version}
-
- )}
- {!isTesting && sqlConnectResult && sqlConnectResult.msgtype == 'error' && (
-
- Connect failed: {sqlConnectResult.error}
-
- )}
- {isTesting && (
-
- Testing connection
-
- )}
-
-
-
-
-
- );
-}
diff --git a/packages/web/src/modals/CreateDatabaseModal.js b/packages/web/src/modals/CreateDatabaseModal.js
deleted file mode 100644
index bb7aed9cf..000000000
--- a/packages/web/src/modals/CreateDatabaseModal.js
+++ /dev/null
@@ -1,30 +0,0 @@
-import React from 'react';
-import axios from '../utility/axios';
-import ModalBase from './ModalBase';
-import { FormButton, FormSubmit, FormTextField } from '../utility/forms';
-import ModalHeader from './ModalHeader';
-import ModalContent from './ModalContent';
-import ModalFooter from './ModalFooter';
-import { FormProvider } from '../utility/FormProvider';
-
-export default function CreateDatabaseModal({ modalState, conid }) {
- const handleSubmit = async values => {
- const { name } = values;
- axios.post('server-connections/create-database', { conid, name });
-
- modalState.close();
- };
- return (
-
- Create database
-
-
-
-
-
-
-
-
-
- );
-}
diff --git a/packages/web/src/modals/DropDownMenu.js b/packages/web/src/modals/DropDownMenu.js
deleted file mode 100644
index 6c71df6ea..000000000
--- a/packages/web/src/modals/DropDownMenu.js
+++ /dev/null
@@ -1,106 +0,0 @@
-import React from 'react';
-import styled from 'styled-components';
-import { sleep } from '../utility/common';
-import useDocumentClick from '../utility/useDocumentClick';
-import { useHideMenu } from './showMenu';
-
-const ContextMenuStyled = styled.ul`
- position: absolute;
- list-style: none;
- background-color: #fff;
- border-radius: 4px;
- border: 1px solid rgba(0, 0, 0, 0.15);
- box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175);
- padding: 5px 0;
- margin: 2px 0 0;
- font-size: 14px;
- text-align: left;
- min-width: 160px;
- z-index: 1050;
- cursor: default;
-`;
-
-const KeyTextSpan = styled.span`
- font-style: italic;
- font-weight: bold;
- text-align: right;
- margin-left: 16px;
-`;
-
-const StyledLink = styled.a`
- padding: 3px 20px;
- line-height: 1.42;
- display: block;
- white-space: nop-wrap;
- color: #262626;
-
- &:hover {
- background-color: #f5f5f5;
- text-decoration: none;
- color: #262626;
- }
-`;
-
-export const DropDownMenuDivider = styled.li`
- margin: 9px 0px 9px 0px;
- border-top: 1px solid #f2f2f2;
- border-bottom: 1px solid #fff;
-`;
-
-export function DropDownMenuItem({ children, keyText = undefined, onClick }) {
- const handleMouseEnter = () => {
- // if (this.context.parentMenu) this.context.parentMenu.closeSubmenu();
- };
-
- return (
-
-
- {children}
- {keyText && {keyText} }
-
-
- );
-}
-
-export function ContextMenu({ left, top, children }) {
- const hideMenu = useHideMenu();
- useDocumentClick(async () => {
- await sleep(0);
- hideMenu();
- });
- const menuRef = React.useRef(null);
- React.useEffect(() => {
- if (menuRef.current) fixPopupPlacement(menuRef.current);
- }, [menuRef.current]);
- return (
-
- {children}
-
- );
-}
-
-function getElementOffset(element) {
- var de = document.documentElement;
- var box = element.getBoundingClientRect();
- var top = box.top + window.pageYOffset - de.clientTop;
- var left = box.left + window.pageXOffset - de.clientLeft;
- return { top: top, left: left };
-}
-
-function fixPopupPlacement(element) {
- const { width, height } = element.getBoundingClientRect();
- let offset = getElementOffset(element);
-
- let newLeft = null;
- let newTop = null;
-
- if (offset.left + width > window.innerWidth) {
- newLeft = offset.left - width;
- }
- if (offset.top + height > window.innerHeight) {
- newTop = offset.top - height;
- }
-
- if (newLeft != null) element.style.left = `${newLeft}px`;
- if (newTop != null) element.style.top = `${newTop}px`;
-}
diff --git a/packages/web/src/modals/ErrorMessageModal.js b/packages/web/src/modals/ErrorMessageModal.js
deleted file mode 100644
index fa60839d7..000000000
--- a/packages/web/src/modals/ErrorMessageModal.js
+++ /dev/null
@@ -1,37 +0,0 @@
-import React from 'react';
-import ModalBase from './ModalBase';
-import FormStyledButton from '../widgets/FormStyledButton';
-import styled from 'styled-components';
-import ModalHeader from './ModalHeader';
-import ModalFooter from './ModalFooter';
-import ModalContent from './ModalContent';
-import { FontIcon } from '../icons';
-
-const Wrapper = styled.div`
-display:flex
-align-items:center
-`;
-
-const IconWrapper = styled.div`
- margin-right: 10px;
- font-size: 20pt;
-`;
-
-export default function ErrorMessageModal({ modalState, title = 'Error', message }) {
- return (
-
- {title}
-
-
-
-
-
- {message}
-
-
-
-
-
-
- );
-}
diff --git a/packages/web/src/modals/FavoriteModal.js b/packages/web/src/modals/FavoriteModal.js
deleted file mode 100644
index 6594e7134..000000000
--- a/packages/web/src/modals/FavoriteModal.js
+++ /dev/null
@@ -1,162 +0,0 @@
-import React from 'react';
-import ModalBase from './ModalBase';
-import {
- FormTextField,
- FormSubmit,
- FormButton,
- FormCheckboxField,
- FormFieldTemplate,
- FormCondition,
- FormSelectField,
-} from '../utility/forms';
-import ModalHeader from './ModalHeader';
-import ModalContent from './ModalContent';
-import ModalFooter from './ModalFooter';
-import { FormProvider, useForm } from '../utility/FormProvider';
-import axios from '../utility/axios';
-import uuidv1 from 'uuid/v1';
-import { FontIcon } from '../icons';
-import useHasPermission from '../utility/useHasPermission';
-import _ from 'lodash';
-import getElectron from '../utility/getElectron';
-import { copyTextToClipboard } from '../utility/clipboard';
-import localforage from 'localforage';
-
-function FontIconPreview() {
- const { values } = useForm();
- return ;
-}
-
-export default function FavoriteModal({ modalState, editingData = undefined, savingTab = undefined }) {
- const hasPermission = useHasPermission();
- const electron = getElectron();
- const savedProperties = ['title', 'icon', 'showInToolbar', 'openOnStartup', 'urlPath'];
- const initialValues = React.useMemo(() => {
- if (savingTab) {
- return {
- title: savingTab.title,
- icon: savingTab.icon,
- urlPath: _.kebabCase(_.deburr(savingTab.title)),
- };
- }
- if (editingData) {
- return _.pick(editingData, savedProperties);
- }
- }, []);
-
- const savedFile = savingTab && savingTab.props && savingTab.props.savedFile;
-
- const canWriteFavorite = hasPermission('files/favorites/write');
-
- const getTabSaveData = async values => {
- const tabdata = {};
- const skipEditor = !!savedFile && values.whatToSave != 'content';
-
- const re = new RegExp(`tabdata_(.*)_${savingTab.tabid}`);
- for (const key of await localforage.keys()) {
- const match = key.match(re);
- if (!match) continue;
- if (skipEditor && match[1] == 'editor') continue;
- tabdata[match[1]] = await localforage.getItem(key);
- }
- for (const key in localStorage) {
- const match = key.match(re);
- if (!match) continue;
- if (skipEditor && match[1] == 'editor') continue;
- tabdata[match[1]] = JSON.parse(localStorage.getItem(key));
- }
- console.log('tabdata', tabdata, skipEditor, savingTab.tabid);
-
- return {
- props:
- values.whatToSave == 'content' && savingTab.props
- ? _.omit(savingTab.props, ['savedFile', 'savedFormat', 'savedFolder'])
- : savingTab.props,
- tabComponent: savingTab.tabComponent,
- tabdata,
- ..._.pick(values, savedProperties),
- };
- };
-
- const saveTab = async values => {
- const data = await getTabSaveData(values);
-
- axios.post('files/save', {
- folder: 'favorites',
- file: uuidv1(),
- format: 'json',
- data,
- });
- };
-
- const saveFile = async values => {
- const oldDataResp = await axios.post('files/load', {
- folder: 'favorites',
- file: editingData.file,
- format: 'json',
- });
-
- axios.post('files/save', {
- folder: 'favorites',
- file: editingData.file,
- format: 'json',
- data: {
- ...oldDataResp.data,
- ...values,
- },
- });
- };
-
- const handleSubmit = async values => {
- modalState.close();
- if (savingTab) {
- saveTab(values);
- }
- if (editingData) {
- saveFile(values);
- }
- };
-
- const handleCopyLink = async values => {
- const tabdata = await getTabSaveData(values);
- copyTextToClipboard(`${document.location.origin}#tabdata=${encodeURIComponent(JSON.stringify(tabdata))}`);
- };
-
- return (
-
- {editingData ? 'Edit favorite' : 'Share / add to favorites'}
-
-
-
-
-
-
-
-
- {!!savingTab && !electron && canWriteFavorite && (
-
- )}
- !values.shareAsLink && canWriteFavorite}>
-
-
-
- {!!savingTab && !!savedFile && (
-
- Link to file
- Content
-
- )}
-
-
- !values.shareAsLink && canWriteFavorite}>
-
-
- values.shareAsLink || !canWriteFavorite}>
-
-
- modalState.close()} />
-
-
-
- );
-}
diff --git a/packages/web/src/modals/FilterMultipleValuesModal.js b/packages/web/src/modals/FilterMultipleValuesModal.js
deleted file mode 100644
index bc41a69c9..000000000
--- a/packages/web/src/modals/FilterMultipleValuesModal.js
+++ /dev/null
@@ -1,68 +0,0 @@
-import React from 'react';
-import ModalBase from './ModalBase';
-import FormStyledButton from '../widgets/FormStyledButton';
-import styled from 'styled-components';
-import ModalHeader from './ModalHeader';
-import ModalFooter from './ModalFooter';
-import ModalContent from './ModalContent';
-
-const Wrapper = styled.div`
- display: flex;
-`;
-
-const OptionsWrapper = styled.div`
- margin-left: 10px;
-`;
-
-function RadioGroupItem({ text, value, defaultChecked = undefined, setMode }) {
- return (
-
- setMode(value)}
- />
- {text}
-
- );
-}
-
-export default function FilterMultipleValuesModal({ modalState, onFilter }) {
- const editorRef = React.useRef(null);
- const [text, setText] = React.useState('');
- const [mode, setMode] = React.useState('is');
- React.useEffect(() => {
- setTimeout(() => {
- if (editorRef.current) editorRef.current.focus();
- }, 1);
- }, []);
-
- const handleOk = () => {
- onFilter(mode, text);
- modalState.close();
- };
-
- return (
-
- Filter multiple values
-
-
-
-
-
-
-
-
-
- );
-}
diff --git a/packages/web/src/modals/ImportExportModal.js b/packages/web/src/modals/ImportExportModal.js
deleted file mode 100644
index b7b2b319a..000000000
--- a/packages/web/src/modals/ImportExportModal.js
+++ /dev/null
@@ -1,249 +0,0 @@
-import React from 'react';
-import moment from 'moment';
-import ModalBase from './ModalBase';
-import FormStyledButton from '../widgets/FormStyledButton';
-import styled from 'styled-components';
-import ModalHeader from './ModalHeader';
-import ModalFooter from './ModalFooter';
-import ModalContent from './ModalContent';
-import ImportExportConfigurator from '../impexp/ImportExportConfigurator';
-import createImpExpScript from '../impexp/createImpExpScript';
-import { useCurrentArchive, useSetCurrentArchive, useSetCurrentWidget, useSetOpenedTabs } from '../utility/globalState';
-import RunnerOutputPane from '../query/RunnerOutputPane';
-import axios from '../utility/axios';
-import WidgetColumnBar, { WidgetColumnBarItem } from '../widgets/WidgetColumnBar';
-import SocketMessagesView from '../query/SocketMessagesView';
-import RunnerOutputFiles from '../query/RunnerOuputFiles';
-import useTheme from '../theme/useTheme';
-import PreviewDataGrid from '../impexp/PreviewDataGrid';
-import useSocket from '../utility/SocketProvider';
-import LoadingInfo from '../widgets/LoadingInfo';
-import { FontIcon } from '../icons';
-import LargeButton, { LargeFormButton } from '../widgets/LargeButton';
-import { getDefaultFileFormat } from '../utility/fileformats';
-import useExtensions from '../utility/useExtensions';
-import { FormProvider, useForm } from '../utility/FormProvider';
-import { FormTextField } from '../utility/forms';
-import useOpenNewTab from '../utility/useOpenNewTab';
-
-const headerHeight = '60px';
-const footerHeight = '100px';
-
-const OutputContainer = styled.div`
- position: relative;
- height: 150px;
-`;
-
-const Wrapper = styled.div`
- display: flex;
- // flex: 1;
-
- position: fixed;
- top: ${headerHeight};
- left: 0;
- right: 0;
- bottom: ${footerHeight};
-`;
-
-const WidgetColumnWrapper = styled.div`
- max-width: 40%;
- // flex-basis: 50%;
- // flow-grow: 0;
- display: flex;
- flex: 1;
- overflow: hidden;
- border-left: 1px solid ${props => props.theme.border};
-`;
-
-const FormWrapper = styled.div`
- position: fixed;
- top: 0;
- left: 0;
- right: 0;
- bottom: 0;
-
- display: flex;
- flex-direction: column;
-`;
-
-const ContentWrapper = styled.div`
- border-top: 1px solid ${props => props.theme.border};
- flex: 1;
- display: flex;
- flex-direction: column;
- overflow-y: auto;
-`;
-
-const Footer = styled.div`
- position: fixed;
- height: ${footerHeight};
- left: 0;
- right: 0;
- bottom: 0px;
- background-color: ${props => props.theme.modalheader_background};
-
- border-top: 1px solid ${props => props.theme.border};
- // padding: 15px;
-`;
-
-const FooterButtons = styled.div`
- margin: 15px;
- display: flex;
-`;
-
-function GenerateSctriptButton({ modalState }) {
- const openNewTab = useOpenNewTab();
- const { values } = useForm();
- const extensions = useExtensions();
-
- const handleGenerateScript = async () => {
- const code = await createImpExpScript(extensions, values);
- openNewTab(
- {
- title: 'Shell #',
- icon: 'img shell',
- tabComponent: 'ShellTab',
- },
- { editor: code }
- );
- modalState.close();
- };
-
- return (
-
- Generate script
-
- );
-}
-
-export default function ImportExportModal({
- modalState,
- initialValues,
- uploadedFile = undefined,
- openedFile = undefined,
- importToArchive = false,
-}) {
- const [executeNumber, setExecuteNumber] = React.useState(0);
- const [runnerId, setRunnerId] = React.useState(null);
- const archive = useCurrentArchive();
- const theme = useTheme();
- const [previewReader, setPreviewReader] = React.useState(0);
- const targetArchiveFolder = importToArchive ? `import-${moment().format('YYYY-MM-DD-hh-mm-ss')}` : archive;
- const socket = useSocket();
- const refreshArchiveFolderRef = React.useRef(null);
- const setArchive = useSetCurrentArchive();
- const setCurrentWidget = useSetCurrentWidget();
- const extensions = useExtensions();
-
- const [busy, setBusy] = React.useState(false);
-
- const handleRunnerDone = React.useCallback(() => {
- setBusy(false);
- if (refreshArchiveFolderRef.current) {
- axios.post('archive/refresh-folders', {});
- axios.post('archive/refresh-files', { folder: refreshArchiveFolderRef.current });
- setArchive(refreshArchiveFolderRef.current);
- setCurrentWidget('archive');
- }
- }, []);
-
- React.useEffect(() => {
- if (runnerId && socket) {
- socket.on(`runner-done-${runnerId}`, handleRunnerDone);
- return () => {
- socket.off(`runner-done-${runnerId}`, handleRunnerDone);
- };
- }
- }, [runnerId, socket]);
-
- const handleExecute = async values => {
- if (busy) return;
-
- setBusy(true);
- const script = await createImpExpScript(extensions, values);
-
- setExecuteNumber(num => num + 1);
-
- let runid = runnerId;
- const resp = await axios.post('runners/start', { script });
- runid = resp.data.runid;
- setRunnerId(runid);
- if (values.targetStorageType == 'archive') {
- refreshArchiveFolderRef.current = values.targetArchiveFolder;
- } else {
- refreshArchiveFolderRef.current = null;
- }
- };
-
- const handleCancel = () => {
- axios.post('runners/cancel', {
- runid: runnerId,
- });
- };
-
- return (
-
-
-
- Import/Export {busy && }
-
-
-
-
-
-
-
-
-
-
-
-
- {previewReader && (
-
-
-
- )}
-
-
-
-
-
-
-
-
-
- {busy ? (
-
- Cancel
-
- ) : (
-
- Run
-
- )}
-
-
- Close
-
-
-
-
-
-
- );
-}
diff --git a/packages/web/src/modals/InputTextModal.js b/packages/web/src/modals/InputTextModal.js
deleted file mode 100644
index 6b649ed7f..000000000
--- a/packages/web/src/modals/InputTextModal.js
+++ /dev/null
@@ -1,29 +0,0 @@
-import React from 'react';
-import ModalBase from './ModalBase';
-import { FormTextField, FormSubmit, FormButton } from '../utility/forms';
-import ModalHeader from './ModalHeader';
-import ModalContent from './ModalContent';
-import ModalFooter from './ModalFooter';
-import { FormProvider } from '../utility/FormProvider';
-
-export default function InputTextModal({ header, label, value, modalState, onConfirm }) {
- const handleSubmit = async values => {
- const { value } = values;
- modalState.close();
- onConfirm(value);
- };
- return (
-
- {header}
-
-
-
-
-
- modalState.close()} />
-
-
-
-
- );
-}
diff --git a/packages/web/src/modals/InsertJoinModal.js b/packages/web/src/modals/InsertJoinModal.js
deleted file mode 100644
index 3e342741d..000000000
--- a/packages/web/src/modals/InsertJoinModal.js
+++ /dev/null
@@ -1,191 +0,0 @@
-import React from 'react';
-import ModalBase from './ModalBase';
-import FormStyledButton from '../widgets/FormStyledButton';
-import SqlEditor from '../sqleditor/SqlEditor';
-import styled from 'styled-components';
-import keycodes from '../utility/keycodes';
-import ModalHeader from './ModalHeader';
-import ModalContent from './ModalContent';
-import ModalFooter from './ModalFooter';
-import analyseQuerySources from '../sqleditor/analyseQuerySources';
-import TableControl, { TableColumn } from '../utility/TableControl';
-import { TextField } from '../utility/inputs';
-
-const FlexLine = styled.div`
- display: flex;
- margin-bottom: 15px;
-`;
-
-const FlexColumn = styled.div`
- margin: 5px;
-`;
-
-const Label = styled.div`
- margin: 5px;
-`;
-
-const SqlWrapper = styled.div`
- position: relative;
- height: 80px;
- width: 40vw;
-`;
-
-const JOIN_TYPES = ['INNER JOIN', 'LEFT JOIN', 'RIGHT JOIN'];
-
-export default function InsertJoinModal({ sql, modalState, engine, dbinfo, onInsert }) {
- const sources = React.useMemo(
- () => analyseQuerySources(sql, [...dbinfo.tables.map(x => x.pureName), ...dbinfo.views.map(x => x.pureName)]),
- [sql, dbinfo]
- );
-
- const [sourceIndex, setSourceIndex] = React.useState(0);
- const [targetIndex, setTargetIndex] = React.useState(0);
- const [joinIndex, setJoinIndex] = React.useState(0);
- const [alias, setAlias] = React.useState('');
- const sourceRef = React.useRef(null);
- const targetRef = React.useRef(null);
- const aliasRef = React.useRef(null);
- const joinRef = React.useRef(null);
-
- const targets = React.useMemo(() => {
- const source = sources[sourceIndex];
- if (!source) return [];
- /** @type {import('dbgate-types').TableInfo} */
- const table = dbinfo.tables.find(x => x.pureName == sources[sourceIndex].name);
- if (!table) return [];
- return [
- ...table.foreignKeys.map(fk => ({
- baseColumns: fk.columns.map(x => x.columnName).join(', '),
- refTable: fk.refTableName,
- refColumns: fk.columns.map(x => x.refColumnName).join(', '),
- constraintName: fk.constraintName,
- columnMap: fk.columns,
- })),
- ...table.dependencies.map(fk => ({
- baseColumns: fk.columns.map(x => x.refColumnName).join(', '),
- refTable: fk.pureName,
- refColumns: fk.columns.map(x => x.columnName).join(', '),
- constraintName: fk.constraintName,
- columnMap: fk.columns.map(x => ({
- columnName: x.refColumnName,
- refColumnName: x.columnName,
- })),
- })),
- ];
- }, [sourceIndex, sources]);
-
- const sqlPreview = React.useMemo(() => {
- const source = sources[sourceIndex];
- const target = targets[targetIndex];
- if (source && target) {
- return `${JOIN_TYPES[joinIndex]} ${target.refTable}${alias ? ` ${alias}` : ''} ON ${target.columnMap
- .map(col => `${source.name}.${col.columnName} = ${alias || target.refTable}.${col.refColumnName}`)
- .join(' AND ')}`;
- }
- return '';
- }, [joinIndex, sources, targets, sourceIndex, targetIndex, alias]);
-
- const sourceKeyDown = React.useCallback(event => {
- if (event.keyCode == keycodes.enter || event.keyCode == keycodes.rightArrow) {
- targetRef.current.focus();
- }
- }, []);
- const targetKeyDown = React.useCallback(event => {
- if (event.keyCode == keycodes.leftArrow) {
- sourceRef.current.focus();
- }
- if (event.keyCode == keycodes.enter || event.keyCode == keycodes.rightArrow) {
- joinRef.current.focus();
- }
- }, []);
- const joinKeyDown = React.useCallback(event => {
- if (event.keyCode == keycodes.leftArrow) {
- targetRef.current.focus();
- }
- if (event.keyCode == keycodes.enter) {
- aliasRef.current.focus();
- }
- }, []);
- const aliasKeyDown = React.useCallback(
- event => {
- if (event.keyCode == keycodes.enter) {
- event.preventDefault();
- modalState.close();
- onInsert(sqlPreview);
- }
- },
- [onInsert, sqlPreview]
- );
-
- return (
-
- Insert join
-
-
-
- Existing table
-
-
-
-
-
-
- New table
-
-
-
-
- {/* */}
-
-
-
- Join
- ({ name }))}
- selectedIndex={joinIndex}
- setSelectedIndex={setJoinIndex}
- tableRef={joinRef}
- onKeyDown={joinKeyDown}
- >
-
-
- Alias
- setAlias(e.target.value)}
- editorRef={aliasRef}
- onKeyDown={aliasKeyDown}
- />
-
-
-
-
-
-
-
-
- {
- modalState.close();
- onInsert(sqlPreview);
- }}
- />
-
-
-
- );
-}
diff --git a/packages/web/src/modals/ModalBase.js b/packages/web/src/modals/ModalBase.js
deleted file mode 100644
index b410751cd..000000000
--- a/packages/web/src/modals/ModalBase.js
+++ /dev/null
@@ -1,87 +0,0 @@
-import React from 'react';
-import Modal from 'react-modal';
-import styled from 'styled-components';
-import useTheme from '../theme/useTheme';
-import ErrorBoundary from '../utility/ErrorBoundary';
-
-// const StyledModal = styled(Modal)`
-// position: absolute;
-// top: 40px;
-// left: 40px;
-// right: 40px;
-// bottom: 40px;
-// border: 1px solid #ccc;
-// background: #fff;
-// overflow: auto;
-// webkitoverflowscrolling: touch;
-// borderradius: 4px;
-// outline: none;
-// padding: 20px;
-// `;
-
-const StyledModal = styled(Modal)`
- border: 1px solid ${props => props.theme.border};
- background: ${props => props.theme.modal_background};
- overflow: auto;
- webkitoverflowscrolling: touch;
- outline: none;
-
- ${props =>
- props.fullScreen &&
- `
- position: fixed;
- top: 0;
- left: 0;
- right: 0;
- bottom: 0;
- // width: 100%;
- // height: 100%;
- `}
-
- ${props =>
- !props.fullScreen &&
- `
- border-radius: 10px;
- width: 50%;
- max-width: 900px;
- margin: auto;
- margin-top: 15vh;
- `}
-
- // z-index:1200;
-
- ${props =>
- props.isFlex &&
- `
- display: flex;
- `}
-`;
-
-const ModalContent = styled.div`
- padding: 20px;
-`;
-
-export default function ModalBase({ modalState, children, isFlex = false, fullScreen = false }) {
- const theme = useTheme();
- return (
-
- {children}
-
- );
-}
diff --git a/packages/web/src/modals/ModalContent.js b/packages/web/src/modals/ModalContent.js
deleted file mode 100644
index 7411b429d..000000000
--- a/packages/web/src/modals/ModalContent.js
+++ /dev/null
@@ -1,27 +0,0 @@
-import React from 'react';
-import styled from 'styled-components';
-import useTheme from '../theme/useTheme';
-
-const Wrapper = styled.div`
- border-bottom: 1px solid ${props => props.theme.border};
- border-top: 1px solid ${props => props.theme.border};
- ${props =>
- // @ts-ignore
- !props.noPadding &&
- `
- padding: 15px;
- `}
-`;
-
-export default function ModalContent({ children, noPadding = false }) {
- const theme = useTheme();
- return (
-
- {children}
-
- );
-}
diff --git a/packages/web/src/modals/ModalFooter.js b/packages/web/src/modals/ModalFooter.js
deleted file mode 100644
index d5d81f89d..000000000
--- a/packages/web/src/modals/ModalFooter.js
+++ /dev/null
@@ -1,14 +0,0 @@
-import React from 'react';
-import styled from 'styled-components';
-import useTheme from '../theme/useTheme';
-
-const Wrapper = styled.div`
- border-bottom: 1px solid ${props => props.theme.border};
- padding: 15px;
- background-color: ${props => props.theme.modalheader_background};
-`;
-
-export default function ModalFooter({ children }) {
- const theme = useTheme();
- return {children} ;
-}
diff --git a/packages/web/src/modals/ModalHeader.js b/packages/web/src/modals/ModalHeader.js
deleted file mode 100644
index 19b3a6b22..000000000
--- a/packages/web/src/modals/ModalHeader.js
+++ /dev/null
@@ -1,33 +0,0 @@
-import React from 'react';
-import styled from 'styled-components';
-import { FontIcon } from '../icons';
-import useTheme from '../theme/useTheme';
-
-const Wrapper = styled.div`
- font-size: 15pt;
- padding: 15px;
- display: flex;
- justify-content: space-between;
- background-color: ${props => props.theme.modalheader_background};
-`;
-
-const CloseWrapper = styled.div`
- font-size: 12pt;
- &:hover {
- background-color: ${props => props.theme.modalheader_background2};
- }
- padding: 5px 10px;
- border-radius: 10px;
-`;
-
-export default function ModalHeader({ children, modalState }) {
- const theme = useTheme();
- return (
-
- {children}
-
-
-
-
- );
-}
diff --git a/packages/web/src/modals/SaveArchiveModal.js b/packages/web/src/modals/SaveArchiveModal.js
deleted file mode 100644
index dd67ba158..000000000
--- a/packages/web/src/modals/SaveArchiveModal.js
+++ /dev/null
@@ -1,40 +0,0 @@
-import React from 'react';
-import ModalBase from './ModalBase';
-import { FormTextField, FormSubmit, FormArchiveFolderSelect, FormFieldTemplate } from '../utility/forms';
-import styled from 'styled-components';
-import ModalHeader from './ModalHeader';
-import ModalContent from './ModalContent';
-import ModalFooter from './ModalFooter';
-import { FormProvider } from '../utility/FormProvider';
-
-const SelectWrapper = styled.div`
- width: 150px;
- position: relative;
- flex: 1;
-`;
-
-export default function SaveArchiveModal({ file = 'new-table', folder = 'default', modalState, onSave }) {
- const handleSubmit = async values => {
- const { file, folder } = values;
- modalState.close();
- if (onSave) onSave(folder, file);
- };
- return (
-
- Save to archive
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- );
-}
diff --git a/packages/web/src/modals/SaveFileModal.js b/packages/web/src/modals/SaveFileModal.js
deleted file mode 100644
index db587740d..000000000
--- a/packages/web/src/modals/SaveFileModal.js
+++ /dev/null
@@ -1,86 +0,0 @@
-import React from 'react';
-import axios from '../utility/axios';
-import ModalBase from './ModalBase';
-import { FormTextField, FormSubmit } from '../utility/forms';
-import ModalHeader from './ModalHeader';
-import ModalContent from './ModalContent';
-import ModalFooter from './ModalFooter';
-import { FormProvider } from '../utility/FormProvider';
-import FormStyledButton from '../widgets/FormStyledButton';
-import getElectron from '../utility/getElectron';
-
-export default function SaveFileModal({
- data,
- folder,
- format,
- modalState,
- name,
- fileExtension,
- filePath,
- onSave = undefined,
-}) {
- const electron = getElectron();
-
- const handleSubmit = async values => {
- const { name } = values;
- await axios.post('files/save', { folder, file: name, data, format });
- modalState.close();
- if (onSave) {
- onSave(name, {
- savedFile: name,
- savedFolder: folder,
- savedFilePath: null,
- });
- }
- };
-
- const handleSaveToDisk = async filePath => {
- const path = window.require('path');
- const parsed = path.parse(filePath);
- // if (!parsed.ext) filePath += `.${fileExtension}`;
-
- await axios.post('files/save-as', { filePath, data, format });
- modalState.close();
-
- if (onSave) {
- onSave(parsed.name, {
- savedFile: null,
- savedFolder: null,
- savedFilePath: filePath,
- });
- }
- };
-
- return (
-
- Save file
-
-
-
-
-
-
- {electron && (
- {
- const file = electron.remote.dialog.showSaveDialogSync(electron.remote.getCurrentWindow(), {
- filters: [
- { name: `${fileExtension.toUpperCase()} files`, extensions: [fileExtension] },
- { name: `All files`, extensions: ['*'] },
- ],
- defaultPath: filePath || `${name}.${fileExtension}`,
- properties: ['showOverwriteConfirmation'],
- });
- if (file) {
- handleSaveToDisk(file);
- }
- }}
- />
- )}
-
-
-
- );
-}
diff --git a/packages/web/src/modals/SaveTabModal.js b/packages/web/src/modals/SaveTabModal.js
deleted file mode 100644
index c60b4a955..000000000
--- a/packages/web/src/modals/SaveTabModal.js
+++ /dev/null
@@ -1,117 +0,0 @@
-import React from 'react';
-import axios from '../utility/axios';
-import { changeTab } from '../utility/common';
-import getElectron from '../utility/getElectron';
-import { useOpenedTabs, useSetOpenedTabs } from '../utility/globalState';
-import keycodes from '../utility/keycodes';
-import SaveFileToolbarButton from '../utility/SaveFileToolbarButton';
-import ToolbarPortal from '../utility/ToolbarPortal';
-import useHasPermission from '../utility/useHasPermission';
-import SaveFileModal from './SaveFileModal';
-import useModalState from './useModalState';
-
-export default function SaveTabModal({
- data,
- folder,
- format,
- tabid,
- tabVisible,
- fileExtension,
- toolbarPortalRef = undefined,
-}) {
- const setOpenedTabs = useSetOpenedTabs();
- const openedTabs = useOpenedTabs();
- const saveFileModalState = useModalState();
- const hasPermission = useHasPermission();
- const canSave = hasPermission(`files/${folder}/write`);
-
- const { savedFile, savedFilePath } = openedTabs.find(x => x.tabid == tabid).props || {};
- const onSave = (title, newProps) => {
- changeTab(tabid, setOpenedTabs, tab => ({
- ...tab,
- title,
- props: {
- ...tab.props,
- savedFormat: format,
- ...newProps,
- },
- }));
- };
-
- const handleSave = async () => {
- if (savedFile) {
- await axios.post('files/save', { folder, file: savedFile, data, format });
- }
- if (savedFilePath) {
- await axios.post('files/save-as', { filePath: savedFilePath, data, format });
- }
- };
- const handleSaveRef = React.useRef(handleSave);
- handleSaveRef.current = handleSave;
-
- const handleKeyboard = React.useCallback(
- e => {
- if (e.keyCode == keycodes.s && e.ctrlKey) {
- e.preventDefault();
- if (e.shiftKey) {
- saveFileModalState.open();
- } else {
- if (savedFile || savedFilePath) handleSaveRef.current();
- else saveFileModalState.open();
- }
- }
- },
- [saveFileModalState]
- );
-
- React.useEffect(() => {
- if (tabVisible && canSave) {
- document.addEventListener('keydown', handleKeyboard);
- return () => {
- document.removeEventListener('keydown', handleKeyboard);
- };
- }
- }, [tabVisible, handleKeyboard, canSave]);
-
- React.useEffect(() => {
- const electron = getElectron();
- if (electron) {
- const { ipcRenderer } = electron;
- window['dbgate_tabExports'][tabid] = {
- save: handleSaveRef.current,
- saveAs: saveFileModalState.open,
- };
- ipcRenderer.send('update-menu');
-
- return () => {
- delete window['dbgate_tabExports'][tabid];
- ipcRenderer.send('update-menu');
- };
- }
- }, []);
-
- return (
- <>
-
-
- {canSave && (
-
-
-
- )}
- >
- );
-}
diff --git a/packages/web/src/modals/SetFilterModal.js b/packages/web/src/modals/SetFilterModal.js
deleted file mode 100644
index c9877b942..000000000
--- a/packages/web/src/modals/SetFilterModal.js
+++ /dev/null
@@ -1,132 +0,0 @@
-import React from 'react';
-import ModalBase from './ModalBase';
-import FormStyledButton from '../widgets/FormStyledButton';
-import styled from 'styled-components';
-import { FormSubmit, FormSelectFieldRaw, FormRadioGroupItem, FormTextFieldRaw } from '../utility/forms';
-import ModalHeader from './ModalHeader';
-import ModalFooter from './ModalFooter';
-import ModalContent from './ModalContent';
-import { TextField } from '../utility/inputs';
-import { FormProvider } from '../utility/FormProvider';
-import { FormRow } from '../utility/formStyle';
-
-const Wrapper = styled.div`
- display: flex;
-`;
-
-const OptionsWrapper = styled.div`
- margin-left: 10px;
-`;
-
-function RadioGroupItem({ text, value, defaultChecked = undefined, setMode }) {
- return (
-
- setMode(value)}
- />
- {text}
-
- );
-}
-
-function Select({ filterType, name }) {
- return (
-
- {filterType == 'number' && (
- <>
- eqals
- does not equal
- is smaller
- is greater
- is smaller or equal
- is greater or equal
- >
- )}
- {filterType == 'string' && (
- <>
- contains
- does not contain
- begins with
- does not begin with
- ends with
- does not end with
- equals
- does not equal
- is smaller
- is greater
- is smaller or equal
- is greater or equal
- >
- )}
- {filterType == 'datetime' && (
- <>
- eqals
- does not equal
- is before
- is after
- is before or equal
- is after or equal
- >
- )}
-
- );
-}
-
-export default function SetFilterModal({ modalState, onFilter, filterType, condition1 }) {
- const editorRef = React.useRef(null);
- // const [condition1, setValue1] = React.useState(condition);
- // const [value2, setValue2] = React.useState('equals');
- // const [mode, setMode] = React.useState('and');
- React.useEffect(() => {
- setTimeout(() => {
- if (editorRef.current) editorRef.current.focus();
- }, 1);
- }, []);
-
- const createTerm = (condition, value) => {
- if (!value) return null;
- if (filterType == 'string') return `${condition}"${value}"`;
- return `${condition}${value}`;
- };
-
- const handleOk = values => {
- const { value1, condition1, value2, condition2, joinOperator } = values;
- const term1 = createTerm(condition1, value1);
- const term2 = createTerm(condition2, value2);
- if (term1 && term2) onFilter(`${term1}${joinOperator}${term2}`);
- else if (term1) onFilter(term1);
- else if (term2) onFilter(term2);
- modalState.close();
- };
-
- return (
-
-
- Set filter
-
- Show rows where
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- );
-}
diff --git a/packages/web/src/modals/showMenu.js b/packages/web/src/modals/showMenu.js
deleted file mode 100644
index 6ac91097a..000000000
--- a/packages/web/src/modals/showMenu.js
+++ /dev/null
@@ -1,40 +0,0 @@
-import React from 'react';
-import { ContextMenu } from './DropDownMenu';
-import uuidv1 from 'uuid/v1';
-
-const Context = React.createContext(null);
-
-export function MenuLayerProvider({ children }) {
- const [menu, setMenu] = React.useState(null);
- return {children} ;
-}
-
-export function MenuLayer() {
- const [menu] = React.useContext(Context);
- return (
-
- {menu != null && (
-
- {menu.menu}
-
- )}
-
- );
-}
-
-export function useHideMenu() {
- const [, setMenu] = React.useContext(Context);
- return () => setMenu(null);
-}
-
-export function useShowMenu() {
- const [, setMenu] = React.useContext(Context);
- const showMenu = (left, top, menu) => {
- const menuid = uuidv1();
- setMenu({ menuid, left, top, menu });
- };
- return showMenu;
- // const container = document.createElement('div');
- // document.body.appendChild(container);
- // ReactDOM.render( , container);
-}
diff --git a/packages/web/src/modals/showModal.js b/packages/web/src/modals/showModal.js
deleted file mode 100644
index a822d27de..000000000
--- a/packages/web/src/modals/showModal.js
+++ /dev/null
@@ -1,40 +0,0 @@
-import React from 'react';
-import ReactDOM from 'react-dom';
-import useModalState from './useModalState';
-
-function ShowModalComponent({ renderModal, onClose }) {
- const modalState = useModalState(true);
- if (!modalState.isOpen) {
- onClose();
- }
- return renderModal(modalState);
-}
-
-const Context = React.createContext(null);
-
-export function ModalLayerProvider({ children }) {
- const [modals, setModals] = React.useState([]);
- return {children} ;
-}
-
-export function ModalLayer() {
- const [modals, setModals] = React.useContext(Context);
- return (
-
- {modals.map((modal, index) => (
- setModals(x => x.filter(y => y != modal))} />
- ))}
-
- );
-}
-
-export default function useShowModal() {
- const [modals, setModals] = React.useContext(Context);
- const showModal = renderModal => {
- setModals([...modals, renderModal]);
- };
- return showModal;
- // const container = document.createElement('div');
- // document.body.appendChild(container);
- // ReactDOM.render( , container);
-}
diff --git a/packages/web/src/modals/useModalState.js b/packages/web/src/modals/useModalState.js
deleted file mode 100644
index 07815fe31..000000000
--- a/packages/web/src/modals/useModalState.js
+++ /dev/null
@@ -1,8 +0,0 @@
-import React from 'react';
-
-export default function useModalState(isOpenDefault = false) {
- const [isOpen, setOpen] = React.useState(isOpenDefault);
- const close = () => setOpen(false);
- const open = () => setOpen(true);
- return { isOpen, open, close };
-}
diff --git a/packages/web/src/plugins/PluginsList.js b/packages/web/src/plugins/PluginsList.js
deleted file mode 100644
index 57a52f213..000000000
--- a/packages/web/src/plugins/PluginsList.js
+++ /dev/null
@@ -1,87 +0,0 @@
-import React from 'react';
-import styled from 'styled-components';
-import useTheme from '../theme/useTheme';
-import { useSetOpenedTabs } from '../utility/globalState';
-import { extractPluginIcon, extractPluginAuthor } from '../plugins/manifestExtractors';
-import useOpenNewTab from '../utility/useOpenNewTab';
-
-const Wrapper = styled.div`
- margin: 1px 3px 10px 5px;
- display: flex;
- align-items: center;
- &:hover {
- background-color: ${props => props.theme.left_background_blue[1]};
- }
-`;
-
-const Texts = styled.div`
- margin-left: 10px;
-`;
-
-const Name = styled.div`
- font-weight: bold;
-`;
-
-const Line = styled.div`
- display: flex;
-`;
-
-const Icon = styled.img`
- width: 50px;
- height: 50px;
-`;
-
-const Description = styled.div`
- font-style: italic;
-`;
-
-const Author = styled.div`
- font-weight: bold;
-`;
-
-const Version = styled.div`
- margin-left: 5px;
-`;
-
-function openPlugin(openNewTab, packageManifest) {
- openNewTab({
- title: packageManifest.name,
- icon: 'icon plugin',
- tabComponent: 'PluginTab',
- props: {
- packageName: packageManifest.name,
- },
- });
-}
-
-function PluginsListItem({ packageManifest }) {
- const openNewTab = useOpenNewTab();
- const theme = useTheme();
- return (
- openPlugin(openNewTab, packageManifest)} theme={theme}>
-
-
-
- {packageManifest.name}
- {packageManifest.version}
-
-
- {packageManifest.description}
-
-
- {extractPluginAuthor(packageManifest)}
-
-
-
- );
-}
-
-export default function PluginsList({ plugins }) {
- return (
- <>
- {plugins.map(packageManifest => (
-
- ))}
- >
- );
-}
diff --git a/packages/web/src/plugins/PluginsProvider.js b/packages/web/src/plugins/PluginsProvider.js
deleted file mode 100644
index 15a51c5c5..000000000
--- a/packages/web/src/plugins/PluginsProvider.js
+++ /dev/null
@@ -1,62 +0,0 @@
-import React from 'react';
-import _ from 'lodash';
-import axios from '../utility/axios';
-import { useInstalledPlugins } from '../utility/metadataLoaders';
-
-const PluginsContext = React.createContext(null);
-
-const dbgateEnv = {
- axios,
-};
-
-export default function PluginsProvider({ children }) {
- const installedPlugins = useInstalledPlugins();
- const [plugins, setPlugins] = React.useState({});
- const handleLoadPlugins = async () => {
- const newPlugins = {};
- for (const installed of installedPlugins) {
- if (!_.keys(plugins).includes(installed.name)) {
- console.log('Loading module', installed.name);
- const resp = await axios.request({
- method: 'get',
- url: 'plugins/script',
- params: {
- packageName: installed.name,
- },
- });
- const module = eval(`${resp.data}; plugin`);
- console.log('Loaded plugin', module);
- const moduleContent = module.__esModule ? module.default : module;
- if (moduleContent.initialize) moduleContent.initialize(dbgateEnv);
- newPlugins[installed.name] = moduleContent;
- }
- }
- setPlugins(x =>
- _.pick(
- { ...x, ...newPlugins },
- installedPlugins.map(y => y.name)
- )
- );
- };
- React.useEffect(() => {
- handleLoadPlugins();
- }, [installedPlugins]);
- return {children} ;
-}
-
-export function usePlugins() {
- const installed = useInstalledPlugins();
- const loaded = React.useContext(PluginsContext);
-
- return React.useMemo(
- () =>
- installed
- .map(manifest => ({
- packageName: manifest.name,
- manifest,
- content: loaded[manifest.name],
- }))
- .filter(x => x.content),
- [installed, loaded]
- );
-}
diff --git a/packages/web/src/plugins/manifestExtractors.js b/packages/web/src/plugins/manifestExtractors.js
deleted file mode 100644
index 32f62ef65..000000000
--- a/packages/web/src/plugins/manifestExtractors.js
+++ /dev/null
@@ -1,21 +0,0 @@
-import _ from 'lodash';
-
-export function extractPluginIcon(packageManifest) {
- const { links } = packageManifest || {};
- const { repository } = links || {};
- const homepage = (links && links.homepage) || packageManifest.homepage;
- const tested = repository || homepage || packageManifest.homepage;
-
- if (tested) {
- const match = tested.match(/https:\/\/github.com\/([^/]*)\/([^/]*)/);
- if (match) {
- return `https://raw.githubusercontent.com/${match[1]}/${match[2]}/master/icon.svg`;
- }
- }
- // eslint-disable-next-line no-undef
- return `${process.env.PUBLIC_URL}/unknown.svg`;
-}
-
-export function extractPluginAuthor(packageManifest) {
- return _.isPlainObject(packageManifest.author) ? packageManifest.author.name : packageManifest.author;
-}
diff --git a/packages/web/src/query/MessagesView.js b/packages/web/src/query/MessagesView.js
deleted file mode 100644
index 2fd763b52..000000000
--- a/packages/web/src/query/MessagesView.js
+++ /dev/null
@@ -1,107 +0,0 @@
-import React from 'react';
-import styled from 'styled-components';
-import moment from 'moment';
-import useTheme from '../theme/useTheme';
-
-const MainContainer = styled.div`
- flex: 1;
- display: flex;
- overflow-y: scroll;
- background-color: ${props => props.theme.gridbody_background};
-`;
-
-const StyledTable = styled.table`
- flex: 1;
- border-spacing: 0;
- border-collapse: collapse;
-`;
-
-const StyledHeader = styled.td`
- text-align: left;
- border-bottom: 2px solid ${props => props.theme.border};
- background-color: ${props => props.theme.gridheader_background};
- padding: 5px;
-`;
-
-const StyledCell = styled.td`
- border-top: 1px solid ${props => props.theme.border};
- padding: 5px;
-`;
-
-const StyledRow = styled.tr`
- color: ${props =>
- // @ts-ignore
- props.severity == 'error' ? props.theme.gridbody_font_red[5] : props.theme.gridbody_font1};
-
- ${props =>
- // @ts-ignore
- props.line != null &&
- `
- &:hover {
- background-color: ${props.theme.gridbody_background2};
- }
- `}
-`;
-
-function formatDuration(duration) {
- if (duration == 0) return '0';
- if (duration < 1000) {
- return `${Math.round(duration)} ms`;
- }
- if (duration < 10000) {
- return `${Math.round(duration / 100) / 10} s`;
- }
- return `${Math.round(duration / 1000)} s`;
-}
-
-function MessagesView({ items, onMessageClick, showProcedure = false, showLine = false }) {
- const handleClick = row => {
- if (onMessageClick) onMessageClick(row);
- };
- const theme = useTheme();
-
- const mainDiv = React.useRef(null);
-
- React.useEffect(() => {
- const element = mainDiv.current;
- if (element) {
- element.scrollTop = element.scrollHeight;
- }
- }, [items]);
-
- const time0 = items[0] && new Date(items[0].time).getTime();
-
- return (
-
-
-
- Number
- Message
- Time
- Delta
- Duration
- {showProcedure && Procedure }
- {showLine && Line }
-
- {items.map((row, index) => (
- // @ts-ignore
- handleClick(row)} theme={theme}>
- {index + 1}
- {row.message}
- {moment(row.time).format('HH:mm:ss')}
- {formatDuration(new Date(row.time).getTime() - time0)}
-
- {index > 0
- ? formatDuration(new Date(row.time).getTime() - new Date(items[index - 1].time).getTime())
- : 'n/a'}
-
- {showProcedure && {row.procedure} }
- {showLine && {row.line} }
-
- ))}
-
-
- );
-}
-
-export default React.memo(MessagesView);
diff --git a/packages/web/src/query/QueryToolbar.js b/packages/web/src/query/QueryToolbar.js
deleted file mode 100644
index 7c51409be..000000000
--- a/packages/web/src/query/QueryToolbar.js
+++ /dev/null
@@ -1,28 +0,0 @@
-import React from 'react';
-import useHasPermission from '../utility/useHasPermission';
-import ToolbarButton from '../widgets/ToolbarButton';
-
-export default function QueryToolbar({ execute, isDatabaseDefined, busy, format, isConnected, kill }) {
- const hasPermission = useHasPermission();
- return (
- <>
-
- Execute
-
- {/*
- Cancel
- */}
-
- Kill
-
- {/* {hasPermission('files/sql/write') && (
-
- Save
-
- )} */}
-
- Format
-
- >
- );
-}
diff --git a/packages/web/src/query/RunnerOuputFiles.js b/packages/web/src/query/RunnerOuputFiles.js
deleted file mode 100644
index 036bd0589..000000000
--- a/packages/web/src/query/RunnerOuputFiles.js
+++ /dev/null
@@ -1,92 +0,0 @@
-import React from 'react';
-import useSocket from '../utility/SocketProvider';
-import axios from '../utility/axios';
-import styled from 'styled-components';
-import TableControl, { TableColumn } from '../utility/TableControl';
-import formatFileSize from '../utility/formatFileSize';
-import resolveApi from '../utility/resolveApi';
-import getElectron from '../utility/getElectron';
-import ErrorInfo from '../widgets/ErrorInfo';
-
-export default function RunnerOutputFiles({ runnerId, executeNumber }) {
- const socket = useSocket();
- const [files, setFiles] = React.useState([]);
-
- const handleRunnerDone = React.useCallback(async () => {
- const resp = await axios.get(`runners/files?runid=${runnerId}`);
- setFiles(resp.data);
- }, [runnerId]);
-
- React.useEffect(() => {
- if (runnerId && socket) {
- socket.on(`runner-done-${runnerId}`, handleRunnerDone);
- return () => {
- socket.off(`runner-done-${runnerId}`, handleRunnerDone);
- };
- }
- }, [runnerId, socket]);
-
- React.useEffect(() => {
- setFiles([]);
- }, [executeNumber]);
-
- const electron = getElectron();
-
- if (!files || files.length == 0) {
- return ;
- }
-
- return (
-
-
- formatFileSize(row.size)} />
- {!electron && (
- (
-
- download
-
- )}
- />
- )}
- {electron && (
- (
- {
- const file = electron.remote.dialog.showSaveDialogSync(electron.remote.getCurrentWindow(), {});
- if (file) {
- const fs = window.require('fs');
- fs.copyFile(row.path, file, () => {});
- }
- }}
- >
- save
-
- )}
- />
- )}
- {electron && (
- (
- {
- electron.remote.shell.showItemInFolder(row.path);
- }}
- >
- show
-
- )}
- />
- )}
-
- );
-}
diff --git a/packages/web/src/query/RunnerOutputPane.js b/packages/web/src/query/RunnerOutputPane.js
deleted file mode 100644
index 01e49bf9f..000000000
--- a/packages/web/src/query/RunnerOutputPane.js
+++ /dev/null
@@ -1,27 +0,0 @@
-import React from 'react';
-import { HorizontalSplitter } from '../widgets/Splitter';
-import SocketMessagesView from './SocketMessagesView';
-import { WidgetTitle } from '../widgets/WidgetStyles';
-import RunnerOutputFiles from './RunnerOuputFiles';
-import styled from 'styled-components';
-
-const Container = styled.div`
- flex: 1;
- display: flex;
- flex-direction: column;
-`;
-
-export default function RunnerOutputPane({ runnerId, executeNumber }) {
- return (
-
-
- Messages
-
-
-
- Output files
-
-
-
- );
-}
diff --git a/packages/web/src/query/ShellToolbar.js b/packages/web/src/query/ShellToolbar.js
deleted file mode 100644
index a9c747f40..000000000
--- a/packages/web/src/query/ShellToolbar.js
+++ /dev/null
@@ -1,18 +0,0 @@
-import React from 'react';
-import ToolbarButton from '../widgets/ToolbarButton';
-
-export default function ShellToolbar({ execute, cancel, busy, edit, editAvailable }) {
- return (
- <>
-
- Execute
-
-
- Cancel
-
-
- Show wizard
-
- >
- );
-}
diff --git a/packages/web/src/query/SocketMessagesView.js b/packages/web/src/query/SocketMessagesView.js
deleted file mode 100644
index a3b467559..000000000
--- a/packages/web/src/query/SocketMessagesView.js
+++ /dev/null
@@ -1,57 +0,0 @@
-import _ from 'lodash';
-import React from 'react';
-import MessagesView from './MessagesView';
-import useSocket from '../utility/SocketProvider';
-import ErrorInfo from '../widgets/ErrorInfo';
-
-export default function SocketMessagesView({
- eventName,
- onMessageClick = undefined,
- executeNumber,
- showProcedure = false,
- showLine = false,
-}) {
- const [displayedMessages, setDisplayedMessages] = React.useState([]);
- const cachedMessagesRef = React.useRef([]);
- const socket = useSocket();
-
- const displayCachedMessages = React.useMemo(
- () =>
- _.throttle(() => {
- setDisplayedMessages([...cachedMessagesRef.current]);
- }, 500),
- []
- );
-
- const handleInfo = React.useCallback(info => {
- cachedMessagesRef.current.push(info);
- displayCachedMessages();
- }, []);
-
- React.useEffect(() => {
- setDisplayedMessages([]);
- cachedMessagesRef.current = [];
- }, [executeNumber]);
-
- React.useEffect(() => {
- if (eventName && socket) {
- socket.on(eventName, handleInfo);
- return () => {
- socket.off(eventName, handleInfo);
- };
- }
- }, [eventName, socket]);
-
- if (!displayedMessages || displayedMessages.length == 0) {
- return ;
- }
-
- return (
-
- );
-}
diff --git a/packages/web/src/query/useNewQuery.js b/packages/web/src/query/useNewQuery.js
deleted file mode 100644
index ee796771e..000000000
--- a/packages/web/src/query/useNewQuery.js
+++ /dev/null
@@ -1,55 +0,0 @@
-import _ from 'lodash';
-import { useSetOpenedTabs, useCurrentDatabase } from '../utility/globalState';
-import useOpenNewTab from '../utility/useOpenNewTab';
-
-export default function useNewQuery() {
- const openNewTab = useOpenNewTab();
- const currentDatabase = useCurrentDatabase();
-
- const connection = _.get(currentDatabase, 'connection') || {};
- const database = _.get(currentDatabase, 'name');
-
- const tooltip = `${connection.displayName || connection.server}\n${database}`;
-
- return ({ title = undefined, initialData = undefined, ...props } = {}) =>
- openNewTab(
- {
- title: title || 'Query #',
- icon: 'img sql-file',
- tooltip,
- tabComponent: 'QueryTab',
- props: {
- ...props,
- conid: connection._id,
- database,
- },
- },
- { editor: initialData }
- );
-}
-
-export function useNewQueryDesign() {
- const openNewTab = useOpenNewTab();
- const currentDatabase = useCurrentDatabase();
-
- const connection = _.get(currentDatabase, 'connection') || {};
- const database = _.get(currentDatabase, 'name');
-
- const tooltip = `${connection.displayName || connection.server}\n${database}`;
-
- return ({ title = undefined, initialData = undefined, ...props } = {}) =>
- openNewTab(
- {
- title: title || 'Query #',
- icon: 'img query-design',
- tooltip,
- tabComponent: 'QueryDesignTab',
- props: {
- ...props,
- conid: connection._id,
- database,
- },
- },
- { editor: initialData }
- );
-}
diff --git a/packages/web/src/react-app-env.d.ts b/packages/web/src/react-app-env.d.ts
deleted file mode 100644
index 6431bc5fc..000000000
--- a/packages/web/src/react-app-env.d.ts
+++ /dev/null
@@ -1 +0,0 @@
-///
diff --git a/packages/web/src/serviceWorker.js b/packages/web/src/serviceWorker.js
deleted file mode 100644
index 4ef7870d5..000000000
--- a/packages/web/src/serviceWorker.js
+++ /dev/null
@@ -1,130 +0,0 @@
-// This optional code is used to register a service worker.
-// register() is not called by default.
-
-// This lets the app load faster on subsequent visits in production, and gives
-// it offline capabilities. However, it also means that developers (and users)
-// will only see deployed updates on subsequent visits to a page, after all the
-// existing tabs open on the page have been closed, since previously cached
-// resources are updated in the background.
-
-// To learn more about the benefits of this model and instructions on how to
-// opt-in, read https://bit.ly/CRA-PWA
-
-const isLocalhost = Boolean(
- window.location.hostname === 'localhost' ||
- // [::1] is the IPv6 localhost address.
- window.location.hostname === '[::1]' ||
- // 127.0.0.0/8 are considered localhost for IPv4.
- window.location.hostname.match(/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/)
-);
-
-export function register(config) {
- if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
- // The URL constructor is available in all browsers that support SW.
- const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href);
- if (publicUrl.origin !== window.location.origin) {
- // Our service worker won't work if PUBLIC_URL is on a different origin
- // from what our page is served on. This might happen if a CDN is used to
- // serve assets; see https://github.com/facebook/create-react-app/issues/2374
- return;
- }
-
- window.addEventListener('load', () => {
- const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;
-
- if (isLocalhost) {
- // This is running on localhost. Let's check if a service worker still exists or not.
- checkValidServiceWorker(swUrl, config);
-
- // Add some additional logging to localhost, pointing developers to the
- // service worker/PWA documentation.
- navigator.serviceWorker.ready.then(() => {
- console.log(
- 'This web app is being served cache-first by a service ' +
- 'worker. To learn more, visit https://bit.ly/CRA-PWA'
- );
- });
- } else {
- // Is not localhost. Just register service worker
- registerValidSW(swUrl, config);
- }
- });
- }
-}
-
-function registerValidSW(swUrl, config) {
- navigator.serviceWorker
- .register(swUrl)
- .then(registration => {
- registration.onupdatefound = () => {
- const installingWorker = registration.installing;
- if (installingWorker == null) {
- return;
- }
- installingWorker.onstatechange = () => {
- if (installingWorker.state === 'installed') {
- if (navigator.serviceWorker.controller) {
- // At this point, the updated precached content has been fetched,
- // but the previous service worker will still serve the older
- // content until all client tabs are closed.
- console.log(
- 'New content is available and will be used when all ' +
- 'tabs for this page are closed. See https://bit.ly/CRA-PWA.'
- );
-
- // Execute callback
- if (config && config.onUpdate) {
- config.onUpdate(registration);
- }
- } else {
- // At this point, everything has been precached.
- // It's the perfect time to display a
- // "Content is cached for offline use." message.
- console.log('Content is cached for offline use.');
-
- // Execute callback
- if (config && config.onSuccess) {
- config.onSuccess(registration);
- }
- }
- }
- };
- };
- })
- .catch(error => {
- console.error('Error during service worker registration:', error);
- });
-}
-
-function checkValidServiceWorker(swUrl, config) {
- // Check if the service worker can be found. If it can't reload the page.
- fetch(swUrl, {
- headers: { 'Service-Worker': 'script' },
- })
- .then(response => {
- // Ensure service worker exists, and that we really are getting a JS file.
- const contentType = response.headers.get('content-type');
- if (response.status === 404 || (contentType != null && contentType.indexOf('javascript') === -1)) {
- // No service worker found. Probably a different app. Reload the page.
- navigator.serviceWorker.ready.then(registration => {
- registration.unregister().then(() => {
- window.location.reload();
- });
- });
- } else {
- // Service worker found. Proceed as normal.
- registerValidSW(swUrl, config);
- }
- })
- .catch(() => {
- console.log('No internet connection found. App is running in offline mode.');
- });
-}
-
-export function unregister() {
- if ('serviceWorker' in navigator) {
- navigator.serviceWorker.ready.then(registration => {
- registration.unregister();
- });
- }
-}
diff --git a/packages/web/src/setupTests.js b/packages/web/src/setupTests.js
deleted file mode 100644
index 74b1a275a..000000000
--- a/packages/web/src/setupTests.js
+++ /dev/null
@@ -1,5 +0,0 @@
-// jest-dom adds custom jest matchers for asserting on DOM nodes.
-// allows you to do things like:
-// expect(element).toHaveTextContent(/react/i)
-// learn more: https://github.com/testing-library/jest-dom
-import '@testing-library/jest-dom/extend-expect';
diff --git a/packages/web/src/sqleditor/GenericEditor.js b/packages/web/src/sqleditor/GenericEditor.js
deleted file mode 100644
index d2e18dcea..000000000
--- a/packages/web/src/sqleditor/GenericEditor.js
+++ /dev/null
@@ -1,72 +0,0 @@
-import React from 'react';
-import styled from 'styled-components';
-import AceEditor from 'react-ace';
-import useDimensions from '../utility/useDimensions';
-import useTheme from '../theme/useTheme';
-
-const Wrapper = styled.div`
- position: absolute;
- left: 0;
- top: 0;
- right: 0;
- bottom: 0;
-`;
-
-export default function GenericEditor({
- mode,
- value = undefined,
- readOnly = false,
- onChange = undefined,
- tabVisible = false,
- onKeyDown = undefined,
- editorRef = undefined,
- focusOnCreate = false,
-}) {
- const [containerRef, { height, width }] = useDimensions();
- const ownEditorRef = React.useRef(null);
- const theme = useTheme();
-
- const currentEditorRef = editorRef || ownEditorRef;
-
- React.useEffect(() => {
- if ((tabVisible || focusOnCreate) && currentEditorRef.current && currentEditorRef.current.editor)
- currentEditorRef.current.editor.focus();
- }, [tabVisible, focusOnCreate]);
-
- const handleKeyDown = React.useCallback(
- async (data, hash, keyString, keyCode, event) => {
- if (onKeyDown) onKeyDown(data, hash, keyString, keyCode, event);
- },
- [onKeyDown]
- );
-
- React.useEffect(() => {
- if ((onKeyDown || !readOnly) && currentEditorRef.current) {
- currentEditorRef.current.editor.keyBinding.addKeyboardHandler(handleKeyDown);
- }
- return () => {
- currentEditorRef.current.editor.keyBinding.removeKeyboardHandler(handleKeyDown);
- };
- }, [handleKeyDown]);
-
- return (
-
-
-
- );
-}
diff --git a/packages/web/src/sqleditor/JslDataGrid.js b/packages/web/src/sqleditor/JslDataGrid.js
deleted file mode 100644
index 7b49cd64b..000000000
--- a/packages/web/src/sqleditor/JslDataGrid.js
+++ /dev/null
@@ -1,24 +0,0 @@
-import React from 'react';
-import DataGrid from '../datagrid/DataGrid';
-import { JslGridDisplay, createGridConfig, createGridCache } from 'dbgate-datalib';
-import useFetch from '../utility/useFetch';
-import JslDataGridCore from '../datagrid/JslDataGridCore';
-
-export default function JslDataGrid({ jslid }) {
- const info = useFetch({
- params: { jslid },
- url: 'jsldata/get-info',
- defaultValue: {},
- });
- const columns = (info && info.columns) || [];
- const [config, setConfig] = React.useState(createGridConfig());
- const [cache, setCache] = React.useState(createGridCache());
- const display = React.useMemo(() => new JslGridDisplay(jslid, columns, config, setConfig, cache, setCache), [
- jslid,
- columns,
- config,
- cache,
- ]);
-
- return ;
-}
diff --git a/packages/web/src/sqleditor/ResultTabs.js b/packages/web/src/sqleditor/ResultTabs.js
deleted file mode 100644
index 2b12f30c1..000000000
--- a/packages/web/src/sqleditor/ResultTabs.js
+++ /dev/null
@@ -1,39 +0,0 @@
-import React from 'react';
-import _ from 'lodash';
-import { TabPage, TabControl } from '../widgets/TabControl';
-import useSocket from '../utility/SocketProvider';
-import JslDataGrid from './JslDataGrid';
-
-export default function ResultTabs({ children, sessionId, executeNumber }) {
- const socket = useSocket();
- const [resultInfos, setResultInfos] = React.useState([]);
-
- const handleResultSet = React.useCallback(props => {
- const { jslid, resultIndex } = props;
- setResultInfos(array => [...array, { jslid, resultIndex }]);
- }, []);
-
- React.useEffect(() => {
- setResultInfos([]);
- }, [executeNumber]);
-
- React.useEffect(() => {
- if (sessionId && socket) {
- socket.on(`session-recordset-${sessionId}`, handleResultSet);
- return () => {
- socket.off(`session-recordset-${sessionId}`, handleResultSet);
- };
- }
- }, [sessionId, socket]);
-
- return (
- 0 ? 'Result 1' : null}>
- {children}
- {_.sortBy(resultInfos, 'resultIndex').map(info => (
-
-
-
- ))}
-
- );
-}
diff --git a/packages/web/src/sqleditor/SqlEditor.js b/packages/web/src/sqleditor/SqlEditor.js
deleted file mode 100644
index 61d08465e..000000000
--- a/packages/web/src/sqleditor/SqlEditor.js
+++ /dev/null
@@ -1,172 +0,0 @@
-import React from 'react';
-import styled from 'styled-components';
-import AceEditor from 'react-ace';
-import useDimensions from '../utility/useDimensions';
-import analyseQuerySources from './analyseQuerySources';
-import keycodes from '../utility/keycodes';
-import useCodeCompletion from './useCodeCompletion';
-import useShowModal from '../modals/showModal';
-import InsertJoinModal from '../modals/InsertJoinModal';
-import { getDatabaseInfo } from '../utility/metadataLoaders';
-import useTheme from '../theme/useTheme';
-import { useShowMenu } from '../modals/showMenu';
-import SqlEditorContextMenu from './SqlEditorContextMenu';
-import sqlFormatter from 'sql-formatter';
-
-const Wrapper = styled.div`
- position: absolute;
- left: 0;
- top: 0;
- right: 0;
- bottom: 0;
-`;
-
-const engineToMode = {
- mssql: 'sqlserver',
- mysql: 'mysql',
- postgre: 'pgsql',
-};
-
-// const COMMON_KEYWORDS = [
-// 'select',
-// 'where',
-// 'update',
-// 'delete',
-// 'group',
-// 'order',
-// 'from',
-// 'by',
-// 'create',
-// 'table',
-// 'drop',
-// 'alter',
-// 'view',
-// 'execute',
-// 'procedure',
-// ];
-
-export default function SqlEditor({
- value = undefined,
- engine = undefined,
- readOnly = false,
- onChange = undefined,
- tabVisible = false,
- onKeyDown = undefined,
- editorRef = undefined,
- focusOnCreate = false,
- conid = undefined,
- database = undefined,
- onExecute = undefined,
-}) {
- const [containerRef, { height, width }] = useDimensions();
- const ownEditorRef = React.useRef(null);
- const theme = useTheme();
- const showMenu = useShowMenu();
-
- const currentEditorRef = editorRef || ownEditorRef;
- const showModal = useShowModal();
-
- useCodeCompletion({
- conid,
- database,
- tabVisible,
- currentEditorRef,
- });
-
- React.useEffect(() => {
- if ((tabVisible || focusOnCreate) && currentEditorRef.current && currentEditorRef.current.editor)
- currentEditorRef.current.editor.focus();
- }, [tabVisible, focusOnCreate]);
-
- const handleInsertJoin = async () => {
- const dbinfo = await getDatabaseInfo({ conid, database });
- showModal(modalState => (
- {
- const editor = currentEditorRef.current.editor;
- editor.session.insert(editor.getCursorPosition(), text);
- }}
- />
- ));
- };
-
- const handleKeyDown = React.useCallback(
- (data, hash, keyString, keyCode, event) => {
- if (keyCode == keycodes.j && event.ctrlKey && !readOnly && tabVisible) {
- event.preventDefault();
- handleInsertJoin();
- }
-
- if (onKeyDown) onKeyDown(data, hash, keyString, keyCode, event);
- },
- [onKeyDown]
- );
-
- React.useEffect(() => {
- if ((onKeyDown || !readOnly) && currentEditorRef.current) {
- currentEditorRef.current.editor.keyBinding.addKeyboardHandler(handleKeyDown);
-
- return () => {
- currentEditorRef.current.editor.keyBinding.removeKeyboardHandler(handleKeyDown);
- };
- }
- }, [handleKeyDown]);
-
- const handleFormatCode = () => {
- currentEditorRef.current.editor.setValue(sqlFormatter.format(editorRef.current.editor.getValue()));
- currentEditorRef.current.editor.clearSelection();
- };
-
- const menuRefs = React.useRef(null);
- menuRefs.current = {
- execute: onExecute,
- insertJoin: !readOnly ? handleInsertJoin : null,
- toggleComment: !readOnly ? () => currentEditorRef.current.editor.execCommand('togglecomment') : null,
- formatCode: !readOnly ? handleFormatCode : null,
- };
- const handleContextMenu = React.useCallback(event => {
- event.preventDefault();
- showMenu(event.pageX, event.pageY, );
- }, []);
-
- React.useEffect(() => {
- if (currentEditorRef.current) {
- currentEditorRef.current.editor.container.addEventListener('contextmenu', handleContextMenu);
-
- return () => {
- currentEditorRef.current.editor.container.removeEventListener('contextmenu', handleContextMenu);
- };
- }
- }, [handleContextMenu]);
-
- return (
-
-
-
- );
-}
diff --git a/packages/web/src/sqleditor/SqlEditorContextMenu.js b/packages/web/src/sqleditor/SqlEditorContextMenu.js
deleted file mode 100644
index d2bd11413..000000000
--- a/packages/web/src/sqleditor/SqlEditorContextMenu.js
+++ /dev/null
@@ -1,29 +0,0 @@
-import React from 'react';
-import { DropDownMenuItem, DropDownMenuDivider } from '../modals/DropDownMenu';
-
-export default function SqlEditorContextMenu({ execute, insertJoin, toggleComment, formatCode }) {
- return (
- <>
- {!!execute && (
-
- Execute query
-
- )}
- {!!insertJoin && (
-
- Insert SQL Join
-
- )}
- {!!toggleComment && (
-
- Toggle comment
-
- )}
- {!!formatCode && (
-
- Format code
-
- )}
- >
- );
-}
diff --git a/packages/web/src/sqleditor/analyseQuerySources.js b/packages/web/src/sqleditor/analyseQuerySources.js
deleted file mode 100644
index d9e255540..000000000
--- a/packages/web/src/sqleditor/analyseQuerySources.js
+++ /dev/null
@@ -1,38 +0,0 @@
-export default function analyseQuerySources(sql, sourceNames) {
- const upperSourceNames = sourceNames.map(x => x.toUpperCase());
- const tokens = sql.split(/\s+/);
- const res = [];
- for (let i = 0; i < tokens.length; i += 1) {
- const lastWordMatch = tokens[i].match(/([^.]+)$/);
- if (lastWordMatch) {
- const word = lastWordMatch[1];
- const wordUpper = word.toUpperCase();
- if (upperSourceNames.includes(wordUpper)) {
- const preWord = tokens[i - 1];
- if (preWord && /^((join)|(from)|(update)|(delete)|(insert))$/i.test(preWord)) {
- let postWord = tokens[i + 1];
- if (postWord && /^as$/i.test(postWord)) {
- postWord = tokens[i + 2];
- }
- if (!postWord) {
- res.push({
- name: word,
- });
- } else if (
- /^((where)|(inner)|(left)|(right)|(on)|(join))$/i.test(postWord) ||
- !/^[a-zA-Z][a-zA-Z0-9]*$/i.test(postWord)
- ) {
- res.push({
- name: word,
- });
- } else
- res.push({
- name: word,
- alias: postWord,
- });
- }
- }
- }
- }
- return res;
-}
diff --git a/packages/web/src/sqleditor/useCodeCompletion.js b/packages/web/src/sqleditor/useCodeCompletion.js
deleted file mode 100644
index 749e01d22..000000000
--- a/packages/web/src/sqleditor/useCodeCompletion.js
+++ /dev/null
@@ -1,127 +0,0 @@
-import React from 'react';
-import { addCompleter, setCompleters } from 'ace-builds/src-noconflict/ext-language_tools';
-import { getDatabaseInfo } from '../utility/metadataLoaders';
-import analyseQuerySources from './analyseQuerySources';
-
-const COMMON_KEYWORDS = [
- 'select',
- 'where',
- 'update',
- 'delete',
- 'group',
- 'order',
- 'from',
- 'by',
- 'create',
- 'table',
- 'drop',
- 'alter',
- 'view',
- 'execute',
- 'procedure',
- 'distinct',
- 'go',
-];
-
-export default function useCodeCompletion({ conid, database, tabVisible, currentEditorRef }) {
- React.useEffect(() => {
- if (!tabVisible) return;
-
- setCompleters([]);
- addCompleter({
- getCompletions: async function (editor, session, pos, prefix, callback) {
- const cursor = session.selection.cursor;
- const line = session.getLine(cursor.row).slice(0, cursor.column);
- const dbinfo = await getDatabaseInfo({ conid, database });
-
- let list = COMMON_KEYWORDS.map(word => ({
- name: word,
- value: word,
- caption: word,
- meta: 'keyword',
- score: 800,
- }));
-
- if (dbinfo) {
- const colMatch = line.match(/([a-zA-Z0-9_]+)\.([a-zA-Z0-9_]*)?$/);
- if (colMatch) {
- const table = colMatch[1];
- const sources = analyseQuerySources(editor.getValue(), [
- ...dbinfo.tables.map(x => x.pureName),
- ...dbinfo.views.map(x => x.pureName),
- ]);
- const source = sources.find(x => (x.alias || x.name) == table);
- console.log('sources', sources);
- console.log('table', table, source);
- if (source) {
- const table = dbinfo.tables.find(x => x.pureName == source.name);
- if (table) {
- list = [
- ...table.columns.map(x => ({
- name: x.columnName,
- value: x.columnName,
- caption: x.columnName,
- meta: 'column',
- score: 1000,
- })),
- ];
- }
- }
- } else {
- list = [
- ...list,
- ...dbinfo.tables.map(x => ({
- name: x.pureName,
- value: x.pureName,
- caption: x.pureName,
- meta: 'table',
- score: 1000,
- })),
- ...dbinfo.views.map(x => ({
- name: x.pureName,
- value: x.pureName,
- caption: x.pureName,
- meta: 'view',
- score: 1000,
- })),
- ];
- }
- }
-
- // if (/(join)|(from)|(update)|(delete)|(insert)\s*([a-zA-Z0-9_]*)?$/i.test(line)) {
- // if (dbinfo) {
- // }
- // }
-
- callback(null, list);
- },
- });
-
- const doLiveAutocomplete = function (e) {
- const editor = e.editor;
- var hasCompleter = editor.completer && editor.completer.activated;
- const session = editor.session;
- const cursor = session.selection.cursor;
- const line = session.getLine(cursor.row).slice(0, cursor.column);
-
- // We don't want to autocomplete with no prefix
- if (e.command.name === 'backspace') {
- // do not hide after backspace
- } else if (e.command.name === 'insertstring') {
- if ((!hasCompleter && /^[a-zA-Z]/.test(e.args)) || e.args == '.') {
- editor.execCommand('startAutocomplete');
- }
-
- if (e.args == ' ' && /((from)|(join))\s*$/i.test(line)) {
- editor.execCommand('startAutocomplete');
- }
- }
- };
-
- currentEditorRef.current.editor.commands.on('afterExec', doLiveAutocomplete);
-
- return () => {
- currentEditorRef.current.editor.commands.removeListener('afterExec', doLiveAutocomplete);
- };
- }, [tabVisible, conid, database, currentEditorRef.current]);
-}
diff --git a/packages/web/src/tabs/ArchiveFileTab.js b/packages/web/src/tabs/ArchiveFileTab.js
deleted file mode 100644
index ebde08373..000000000
--- a/packages/web/src/tabs/ArchiveFileTab.js
+++ /dev/null
@@ -1,8 +0,0 @@
-import React from 'react';
-import JslDataGrid from '../sqleditor/JslDataGrid';
-
-export default function ArchiveFileTab({ archiveFolder, archiveFile, tabVisible, toolbarPortalRef, tabid }) {
- return ;
-}
-
-ArchiveFileTab.matchingProps = ['archiveFile', 'archiveFolder'];
diff --git a/packages/web/src/tabs/ChartTab.js b/packages/web/src/tabs/ChartTab.js
deleted file mode 100644
index 934ce1279..000000000
--- a/packages/web/src/tabs/ChartTab.js
+++ /dev/null
@@ -1,74 +0,0 @@
-import React from 'react';
-import _ from 'lodash';
-import { createFreeTableModel } from 'dbgate-datalib';
-import useUndoReducer from '../utility/useUndoReducer';
-import ReactDOM from 'react-dom';
-import { useUpdateDatabaseForTab } from '../utility/globalState';
-import LoadingInfo from '../widgets/LoadingInfo';
-import ErrorInfo from '../widgets/ErrorInfo';
-import useEditorData from '../utility/useEditorData';
-import SaveTabModal from '../modals/SaveTabModal';
-import ChartEditor from '../charts/ChartEditor';
-import ChartToolbar from '../charts/ChartToolbar';
-import ToolbarPortal from '../utility/ToolbarPortal';
-
-export default function ChartTab({ tabVisible, toolbarPortalRef, conid, database, tabid }) {
- const [modelState, dispatchModel] = useUndoReducer(createFreeTableModel());
- const { initialData, setEditorData, errorMessage, isLoading } = useEditorData({
- tabid,
- });
- useUpdateDatabaseForTab(tabVisible, conid, database);
-
- React.useEffect(() => {
- // @ts-ignore
- if (initialData) dispatchModel({ type: 'reset', value: initialData });
- }, [initialData]);
-
- React.useEffect(() => {
- setEditorData(modelState.value);
- }, [modelState]);
-
- const setConfig = React.useCallback(
- config =>
- // @ts-ignore
- dispatchModel({
- type: 'compute',
- compute: v => ({ ...v, config: _.isFunction(config) ? config(v.config) : config }),
- }),
- [dispatchModel]
- );
-
- if (isLoading) {
- return ;
- }
- if (errorMessage) {
- return ;
- }
-
- return (
- <>
-
-
-
-
-
- >
- );
-}
-
-ChartTab.allowAddToFavorites = props => true;
diff --git a/packages/web/src/tabs/FavoriteEditorTab.js b/packages/web/src/tabs/FavoriteEditorTab.js
deleted file mode 100644
index 1dc2bae18..000000000
--- a/packages/web/src/tabs/FavoriteEditorTab.js
+++ /dev/null
@@ -1,100 +0,0 @@
-import React from 'react';
-import ReactDOM from 'react-dom';
-import _ from 'lodash';
-import keycodes from '../utility/keycodes';
-import GenericEditor from '../sqleditor/GenericEditor';
-import useEditorData from '../utility/useEditorData';
-import LoadingInfo from '../widgets/LoadingInfo';
-import { useOpenedTabs, useSetOpenedTabs } from '../utility/globalState';
-import useOpenNewTab from '../utility/useOpenNewTab';
-import axios from '../utility/axios';
-import useHasPermission from '../utility/useHasPermission';
-import ToolbarButton from '../widgets/ToolbarButton';
-import useShowModal from '../modals/showModal';
-import ErrorMessageModal from '../modals/ErrorMessageModal';
-import { useOpenFavorite } from '../appobj/FavoriteFileAppObject';
-
-function FavoriteEditorToolbar({ save, showPreview }) {
- const hasPermission = useHasPermission();
-
- return (
- <>
- {hasPermission('files/favorites/write') && save && (
-
- Save
-
- )}
-
- Preview
-
- >
- );
-}
-
-export default function FavoriteEditorTab({ tabid, tabVisible, savedFile, toolbarPortalRef, ...other }) {
- const { editorData, setEditorData, isLoading, saveToStorage } = useEditorData({ tabid });
- const openNewTab = useOpenNewTab();
- const showModal = useShowModal();
- const openFavorite = useOpenFavorite();
-
- const showPreview = () => {
- try {
- const data = JSON.parse(editorData);
- openFavorite(data);
- } catch (err) {
- showModal(modalState => (
-
- ));
- }
- };
-
- const handleKeyDown = (data, hash, keyString, keyCode, event) => {
- if (keyCode == keycodes.f5) {
- event.preventDefault();
- showPreview();
- }
- };
-
- const handleSave = () => {
- try {
- const data = JSON.parse(editorData);
- axios.post('files/save', {
- file: savedFile,
- folder: 'favorites',
- format: 'json',
- data,
- });
- } catch (err) {
- showModal(modalState => (
-
- ));
- }
- };
-
- if (isLoading) {
- return (
-
-
-
- );
- }
-
- return (
- <>
-
- {toolbarPortalRef &&
- toolbarPortalRef.current &&
- tabVisible &&
- ReactDOM.createPortal(
- ,
- toolbarPortalRef.current
- )}
- >
- );
-}
diff --git a/packages/web/src/tabs/FreeTableTab.js b/packages/web/src/tabs/FreeTableTab.js
deleted file mode 100644
index 7495c885b..000000000
--- a/packages/web/src/tabs/FreeTableTab.js
+++ /dev/null
@@ -1,67 +0,0 @@
-import React from 'react';
-import { createFreeTableModel } from 'dbgate-datalib';
-import useUndoReducer from '../utility/useUndoReducer';
-import { useSetOpenedTabs } from '../utility/globalState';
-import useGridConfig from '../utility/useGridConfig';
-import FreeTableGrid from '../freetable/FreeTableGrid';
-import SaveArchiveModal from '../modals/SaveArchiveModal';
-import useModalState from '../modals/useModalState';
-import axios from '../utility/axios';
-import LoadingInfo from '../widgets/LoadingInfo';
-import { changeTab } from '../utility/common';
-import ErrorInfo from '../widgets/ErrorInfo';
-import useEditorData from '../utility/useEditorData';
-
-export default function FreeDataTab({ archiveFolder, archiveFile, tabVisible, toolbarPortalRef, tabid, initialArgs }) {
- const [config, setConfig] = useGridConfig(tabid);
- const [modelState, dispatchModel] = useUndoReducer(createFreeTableModel());
- const saveArchiveModalState = useModalState();
- const setOpenedTabs = useSetOpenedTabs();
- const { initialData, setEditorData, errorMessage, isLoading } = useEditorData({
- tabid,
- loadFromArgs:
- initialArgs && initialArgs.functionName
- ? () => axios.post('runners/load-reader', initialArgs).then(x => x.data)
- : null,
- });
-
- React.useEffect(() => {
- // @ts-ignore
- if (initialData) dispatchModel({ type: 'reset', value: initialData });
- }, [initialData]);
-
- React.useEffect(() => {
- setEditorData(modelState.value);
- }, [modelState]);
-
- const handleSave = async (folder, file) => {
- await axios.post('archive/save-free-table', { folder, file, data: modelState.value });
- changeTab(tabid, setOpenedTabs, tab => ({
- ...tab,
- title: file,
- props: { archiveFile: file, archiveFolder: folder },
- }));
- };
-
- if (isLoading) {
- return ;
- }
- if (errorMessage) {
- return ;
- }
-
- return (
- <>
- saveArchiveModalState.open()}
- />
-
- >
- );
-}
diff --git a/packages/web/src/tabs/InfoPageTab.js b/packages/web/src/tabs/InfoPageTab.js
deleted file mode 100644
index daa581a49..000000000
--- a/packages/web/src/tabs/InfoPageTab.js
+++ /dev/null
@@ -1,12 +0,0 @@
-import React from 'react';
-import styled from 'styled-components';
-import resolveApi from '../utility/resolveApi';
-
-const Frame = styled.iframe`
- flex: 1;
- border: 0px solid gray;
-`;
-
-export default function InfoPageTab({ page }) {
- return ;
-}
diff --git a/packages/web/src/tabs/MarkdownEditorTab.js b/packages/web/src/tabs/MarkdownEditorTab.js
deleted file mode 100644
index 63241a8e7..000000000
--- a/packages/web/src/tabs/MarkdownEditorTab.js
+++ /dev/null
@@ -1,78 +0,0 @@
-import React from 'react';
-import ReactDOM from 'react-dom';
-import _ from 'lodash';
-import keycodes from '../utility/keycodes';
-import GenericEditor from '../sqleditor/GenericEditor';
-import MarkdownToolbar from '../markdown/MarkdownToolbar';
-import useEditorData from '../utility/useEditorData';
-import SaveTabModal from '../modals/SaveTabModal';
-import useModalState from '../modals/useModalState';
-import LoadingInfo from '../widgets/LoadingInfo';
-import { useOpenedTabs, useSetOpenedTabs } from '../utility/globalState';
-import useOpenNewTab from '../utility/useOpenNewTab';
-import { setSelectedTabFunc } from '../utility/common';
-import ToolbarPortal from '../utility/ToolbarPortal';
-
-export default function MarkdownEditorTab({ tabid, tabVisible, toolbarPortalRef, ...other }) {
- const { editorData, setEditorData, isLoading, saveToStorage } = useEditorData({ tabid });
- const openedTabs = useOpenedTabs();
- const setOpenedTabs = useSetOpenedTabs();
- const openNewTab = useOpenNewTab();
-
- const handleKeyDown = (data, hash, keyString, keyCode, event) => {
- if (keyCode == keycodes.f5) {
- event.preventDefault();
- showPreview();
- }
- };
-
- const showPreview = async () => {
- await saveToStorage();
- const existing = (openedTabs || []).find(x => x.props && x.props.sourceTabId == tabid && x.closedTime == null);
- if (existing) {
- setOpenedTabs(tabs => setSelectedTabFunc(tabs, existing.tabid));
- } else {
- const thisTab = (openedTabs || []).find(x => x.tabid == tabid);
- openNewTab({
- title: thisTab.title,
- icon: 'img preview',
- tabComponent: 'MarkdownPreviewTab',
- props: {
- sourceTabId: tabid,
- },
- });
- }
- };
-
- if (isLoading) {
- return (
-
-
-
- );
- }
-
- return (
- <>
-
-
-
-
-
- >
- );
-}
diff --git a/packages/web/src/tabs/MarkdownPreviewTab.js b/packages/web/src/tabs/MarkdownPreviewTab.js
deleted file mode 100644
index 559177a46..000000000
--- a/packages/web/src/tabs/MarkdownPreviewTab.js
+++ /dev/null
@@ -1,23 +0,0 @@
-import React from 'react';
-import LoadingInfo from '../widgets/LoadingInfo';
-import MarkdownExtendedView from '../markdown/MarkdownExtendedView';
-import useEditorData from '../utility/useEditorData';
-
-export default function MarkdownPreviewTab({ sourceTabId, tabVisible }) {
- const [reloadToken, setReloadToken] = React.useState(0);
- const { editorData, isLoading } = useEditorData({ tabid: sourceTabId, reloadToken });
-
- React.useEffect(() => {
- if (tabVisible) setReloadToken(x => x + 1);
- }, [tabVisible]);
-
- if (isLoading) {
- return (
-
-
-
- );
- }
-
- return {editorData || ''} ;
-}
diff --git a/packages/web/src/tabs/MarkdownViewTab.js b/packages/web/src/tabs/MarkdownViewTab.js
deleted file mode 100644
index 3e27fcaa9..000000000
--- a/packages/web/src/tabs/MarkdownViewTab.js
+++ /dev/null
@@ -1,36 +0,0 @@
-import React from 'react';
-import axios from '../utility/axios';
-import LoadingInfo from '../widgets/LoadingInfo';
-import MarkdownExtendedView from '../markdown/MarkdownExtendedView';
-
-export default function MarkdownViewTab({ savedFile }) {
- const [isLoading, setIsLoading] = React.useState(false);
- const [text, setText] = React.useState(null);
-
- const handleLoad = async () => {
- setIsLoading(true);
- const resp = await axios.post('files/load', {
- folder: 'markdown',
- file: savedFile,
- format: 'text',
- });
- setText(resp.data);
- setIsLoading(false);
- };
-
- React.useEffect(() => {
- handleLoad();
- }, []);
-
- if (isLoading) {
- return (
-
-
-
- );
- }
-
- return {text || ''} ;
-}
-
-MarkdownViewTab.allowAddToFavorites = props => true;
diff --git a/packages/web/src/tabs/PluginTab.js b/packages/web/src/tabs/PluginTab.js
deleted file mode 100644
index f8939627b..000000000
--- a/packages/web/src/tabs/PluginTab.js
+++ /dev/null
@@ -1,138 +0,0 @@
-import React from 'react';
-import styled from 'styled-components';
-import _ from 'lodash';
-import Markdown from 'markdown-to-jsx';
-import useTheme from '../theme/useTheme';
-import useFetch from '../utility/useFetch';
-import LoadingInfo from '../widgets/LoadingInfo';
-import compareVersions from 'compare-versions';
-import { extractPluginIcon, extractPluginAuthor } from '../plugins/manifestExtractors';
-import FormStyledButton from '../widgets/FormStyledButton';
-import axios from '../utility/axios';
-import { useInstalledPlugins } from '../utility/metadataLoaders';
-import useHasPermission from '../utility/useHasPermission';
-
-const WhitePage = styled.div`
- position: absolute;
- left: 0;
- top: 0;
- right: 0;
- bottom: 0;
- background-color: ${props => props.theme.main_background};
- overflow: auto;
- padding: 10px;
-`;
-
-const Icon = styled.img`
- width: 80px;
- height: 80px;
-`;
-
-const Header = styled.div`
- display: flex;
- border-bottom: 1px solid ${props => props.theme.border};
- margin-bottom: 20px;
- padding-bottom: 20px;
-`;
-
-const HeaderBody = styled.div`
- margin-left: 10px;
-`;
-
-const Title = styled.div`
- font-size: 20pt;
-`;
-
-const HeaderLine = styled.div`
- margin-top: 5px;
-`;
-
-const Author = styled.span`
- font-weight: bold;
-`;
-
-const Version = styled.span``;
-
-function Delimiter() {
- return | ;
-}
-
-function PluginTabCore({ packageName }) {
- const hasPermission = useHasPermission();
- const theme = useTheme();
- const installed = useInstalledPlugins();
- const info = useFetch({
- params: { packageName },
- url: 'plugins/info',
- defaultValue: null,
- });
- let { readme, manifest } = info || {};
- const handleInstall = async () => {
- axios.post('plugins/install', { packageName });
- };
- const handleUninstall = async () => {
- axios.post('plugins/uninstall', { packageName });
- };
- const handleUpgrade = async () => {
- axios.post('plugins/upgrade', { packageName });
- };
-
- if (info == null) {
- return ;
- }
-
- const installedFound = installed.find(x => x.name == packageName);
- const onlineFound = manifest;
-
- if (manifest == null) {
- if (installedFound) {
- manifest = installedFound;
- readme = installedFound.readme;
- }
- if (manifest == null) {
- return null;
- }
- }
-
- return (
- <>
-
-
-
- {packageName}
-
- {extractPluginAuthor(manifest)}
-
- {installedFound ? installedFound.version : manifest.version}
-
-
- {hasPermission('plugins/install') && !installedFound && (
-
- )}
- {hasPermission('plugins/install') && !!installedFound && (
-
- )}
- {hasPermission('plugins/install') &&
- installedFound &&
- onlineFound &&
- compareVersions(onlineFound.version, installedFound.version) > 0 && (
-
- )}
-
-
-
- {readme}
- >
- );
-}
-
-export default function PluginTab({ packageName }) {
- const theme = useTheme();
- return (
-
-
-
- );
-}
-
-PluginTab.matchingProps = ['packageName'];
diff --git a/packages/web/src/tabs/QueryDesignTab.js b/packages/web/src/tabs/QueryDesignTab.js
deleted file mode 100644
index c9b9648a8..000000000
--- a/packages/web/src/tabs/QueryDesignTab.js
+++ /dev/null
@@ -1,229 +0,0 @@
-import React from 'react';
-import _ from 'lodash';
-import ReactDOM from 'react-dom';
-import axios from '../utility/axios';
-
-import { useConnectionInfo } from '../utility/metadataLoaders';
-import SqlEditor from '../sqleditor/SqlEditor';
-import { useUpdateDatabaseForTab, useSetOpenedTabs } from '../utility/globalState';
-import QueryDesignToolbar from '../designer/QueryDesignToolbar';
-import SocketMessagesView from '../query/SocketMessagesView';
-import { TabPage } from '../widgets/TabControl';
-import ResultTabs from '../sqleditor/ResultTabs';
-import { VerticalSplitter } from '../widgets/Splitter';
-import keycodes from '../utility/keycodes';
-import { changeTab } from '../utility/common';
-import useSocket from '../utility/SocketProvider';
-import SaveTabModal from '../modals/SaveTabModal';
-import sqlFormatter from 'sql-formatter';
-import useEditorData from '../utility/useEditorData';
-import LoadingInfo from '../widgets/LoadingInfo';
-import useExtensions from '../utility/useExtensions';
-import QueryDesigner from '../designer/QueryDesigner';
-import QueryDesignColumns from '../designer/QueryDesignColumns';
-import { findEngineDriver } from 'dbgate-tools';
-import { generateDesignedQuery } from '../designer/designerTools';
-import useUndoReducer from '../utility/useUndoReducer';
-import { StatusBarItem } from '../widgets/StatusBar';
-import useTimerLabel from '../utility/useTimerLabel';
-import ToolbarPortal from '../utility/ToolbarPortal';
-
-export default function QueryDesignTab({
- tabid,
- conid,
- database,
- tabVisible,
- toolbarPortalRef,
- statusbarPortalRef,
- ...other
-}) {
- const [sessionId, setSessionId] = React.useState(null);
- const [visibleResultTabs, setVisibleResultTabs] = React.useState(false);
- const [executeNumber, setExecuteNumber] = React.useState(0);
- const setOpenedTabs = useSetOpenedTabs();
- const socket = useSocket();
- const [busy, setBusy] = React.useState(false);
- const extensions = useExtensions();
- const connection = useConnectionInfo({ conid });
- const engine = findEngineDriver(connection, extensions);
- const [sqlPreview, setSqlPreview] = React.useState('');
- const { initialData, setEditorData, isLoading } = useEditorData({
- tabid,
- });
- const [modelState, dispatchModel] = useUndoReducer(
- {
- tables: [],
- references: [],
- columns: [],
- },
- { mergeNearActions: true }
- );
- const timerLabel = useTimerLabel();
-
- React.useEffect(() => {
- // @ts-ignore
- if (initialData) dispatchModel({ type: 'reset', value: initialData });
- }, [initialData]);
-
- React.useEffect(() => {
- setEditorData(modelState.value);
- }, [modelState]);
-
- const handleSessionDone = React.useCallback(() => {
- setBusy(false);
- timerLabel.stop();
- }, []);
-
- const generatePreview = (value, engine) => {
- if (!engine || !value) return;
- const sql = generateDesignedQuery(value, engine);
- setSqlPreview(sqlFormatter.format(sql));
- };
-
- React.useEffect(() => {
- generatePreview(modelState.value, engine);
- }, [modelState.value, engine]);
-
- const handleChange = React.useCallback(
- (value, skipUndoChain) =>
- // @ts-ignore
- dispatchModel({
- type: 'compute',
- useMerge: skipUndoChain,
- compute: v => (_.isFunction(value) ? value(v) : value),
- }),
- [dispatchModel]
- );
-
- React.useEffect(() => {
- if (sessionId && socket) {
- socket.on(`session-done-${sessionId}`, handleSessionDone);
- return () => {
- socket.off(`session-done-${sessionId}`, handleSessionDone);
- };
- }
- }, [sessionId, socket]);
-
- React.useEffect(() => {
- changeTab(tabid, setOpenedTabs, tab => ({ ...tab, busy }));
- }, [busy]);
-
- useUpdateDatabaseForTab(tabVisible, conid, database);
-
- const handleExecute = React.useCallback(async () => {
- if (busy) return;
- setExecuteNumber(num => num + 1);
- setVisibleResultTabs(true);
-
- let sesid = sessionId;
- if (!sesid) {
- const resp = await axios.post('sessions/create', {
- conid,
- database,
- });
- sesid = resp.data.sesid;
- setSessionId(sesid);
- }
- setBusy(true);
- timerLabel.start();
- await axios.post('sessions/execute-query', {
- sesid,
- sql: sqlPreview,
- });
- }, [busy, conid, sessionId, database, sqlPreview]);
-
- const handleKill = async () => {
- await axios.post('sessions/kill', {
- sesid: sessionId,
- });
- setSessionId(null);
- setBusy(false);
- timerLabel.stop();
- };
-
- const handleKeyDown = React.useCallback(
- e => {
- if (e.keyCode == keycodes.f5) {
- e.preventDefault();
- handleExecute();
- }
- },
- [handleExecute]
- );
-
- React.useEffect(() => {
- if (tabVisible) {
- document.addEventListener('keydown', handleKeyDown, false);
- return () => {
- document.removeEventListener('keydown', handleKeyDown);
- };
- }
- }, [tabVisible, handleKeyDown]);
-
- if (isLoading) {
- return (
-
-
-
- );
- }
-
- return (
- <>
-
-
-
-
-
-
-
-
-
- {visibleResultTabs && (
-
-
-
- )}
-
-
-
-
-
- {statusbarPortalRef &&
- statusbarPortalRef.current &&
- tabVisible &&
- ReactDOM.createPortal({timerLabel.text} , statusbarPortalRef.current)}
-
- >
- );
-}
-
-QueryDesignTab.allowAddToFavorites = props => true;
diff --git a/packages/web/src/tabs/QueryTab.js b/packages/web/src/tabs/QueryTab.js
deleted file mode 100644
index bbdd26e23..000000000
--- a/packages/web/src/tabs/QueryTab.js
+++ /dev/null
@@ -1,253 +0,0 @@
-import React from 'react';
-import _ from 'lodash';
-import ReactDOM from 'react-dom';
-import axios from '../utility/axios';
-
-import { useConnectionInfo } from '../utility/metadataLoaders';
-import SqlEditor from '../sqleditor/SqlEditor';
-import { useUpdateDatabaseForTab, useSetOpenedTabs } from '../utility/globalState';
-import QueryToolbar from '../query/QueryToolbar';
-import SocketMessagesView from '../query/SocketMessagesView';
-import { TabPage } from '../widgets/TabControl';
-import ResultTabs from '../sqleditor/ResultTabs';
-import { VerticalSplitter } from '../widgets/Splitter';
-import keycodes from '../utility/keycodes';
-import { changeTab } from '../utility/common';
-import useSocket from '../utility/SocketProvider';
-import SaveTabModal from '../modals/SaveTabModal';
-import useModalState from '../modals/useModalState';
-import sqlFormatter from 'sql-formatter';
-import useEditorData from '../utility/useEditorData';
-import applySqlTemplate from '../utility/applySqlTemplate';
-import LoadingInfo from '../widgets/LoadingInfo';
-import useExtensions from '../utility/useExtensions';
-import useTimerLabel from '../utility/useTimerLabel';
-import { StatusBarItem } from '../widgets/StatusBar';
-import ToolbarPortal from '../utility/ToolbarPortal';
-import { useShowMenu } from '../modals/showMenu';
-
-function createSqlPreview(sql) {
- if (!sql) return undefined;
- let data = sql.substring(0, 500);
- data = data.replace(/\[[^\]]+\]\./g, '');
- data = data.replace(/\[a-zA-Z0-9_]+\./g, '');
- data = data.replace(/\/\*.*\*\//g, '');
- data = data.replace(/[\[\]]/g, '');
- data = data.replace(/--[^\n]*\n/g, '');
-
- for (let step = 1; step <= 5; step++) {
- data = data.replace(/\([^\(^\)]+\)/g, '');
- }
- data = data.replace(/\s+/g, ' ');
- data = data.trim();
- data = data.replace(/^(.{50}[^\s]*).*/, '$1');
- return data;
-}
-
-export default function QueryTab({
- tabid,
- conid,
- database,
- initialArgs,
- tabVisible,
- toolbarPortalRef,
- statusbarPortalRef,
- ...other
-}) {
- const [sessionId, setSessionId] = React.useState(null);
- const [visibleResultTabs, setVisibleResultTabs] = React.useState(false);
- const [executeNumber, setExecuteNumber] = React.useState(0);
- const setOpenedTabs = useSetOpenedTabs();
- const socket = useSocket();
- const [busy, setBusy] = React.useState(false);
- const extensions = useExtensions();
- const timerLabel = useTimerLabel();
- const { editorData, setEditorData, isLoading } = useEditorData({
- tabid,
- loadFromArgs:
- initialArgs && initialArgs.sqlTemplate
- ? () => applySqlTemplate(initialArgs.sqlTemplate, extensions, { conid, database, ...other })
- : null,
- });
-
- const editorRef = React.useRef(null);
-
- const handleSessionDone = React.useCallback(() => {
- setBusy(false);
- timerLabel.stop();
- }, []);
-
- React.useEffect(() => {
- if (sessionId && socket) {
- socket.on(`session-done-${sessionId}`, handleSessionDone);
- return () => {
- socket.off(`session-done-${sessionId}`, handleSessionDone);
- };
- }
- }, [sessionId, socket]);
-
- React.useEffect(() => {
- changeTab(tabid, setOpenedTabs, tab => ({ ...tab, busy }));
- }, [busy]);
-
- useUpdateDatabaseForTab(tabVisible, conid, database);
- const connection = useConnectionInfo({ conid });
-
- const updateContentPreviewDebounced = React.useRef(
- _.debounce(
- // @ts-ignore
- sql =>
- changeTab(tabid, setOpenedTabs, tab => ({
- ...tab,
- contentPreview: createSqlPreview(sql),
- })),
- 500
- )
- );
-
- React.useEffect(() => {
- // @ts-ignore
- updateContentPreviewDebounced.current(editorData);
- }, [editorData]);
-
- const handleExecute = async () => {
- if (busy) return;
- setExecuteNumber(num => num + 1);
- setVisibleResultTabs(true);
- const selectedText = editorRef.current.editor.getSelectedText();
-
- let sesid = sessionId;
- if (!sesid) {
- const resp = await axios.post('sessions/create', {
- conid,
- database,
- });
- sesid = resp.data.sesid;
- setSessionId(sesid);
- }
- setBusy(true);
- timerLabel.start();
- await axios.post('sessions/execute-query', {
- sesid,
- sql: selectedText || editorData,
- });
- };
- // const handleExecuteRef = React.useRef(handleExecute);
- // handleExecuteRef.current = handleExecute;
-
- // const handleCancel = () => {
- // axios.post('sessions/cancel', {
- // sesid: sessionId,
- // });
- // };
-
- const handleKill = async () => {
- await axios.post('sessions/kill', {
- sesid: sessionId,
- });
- setSessionId(null);
- setBusy(false);
- timerLabel.stop();
- };
-
- const handleKeyDown = (data, hash, keyString, keyCode, event) => {
- if (keyCode == keycodes.f5 || (keyCode == keycodes.enter && event.ctrlKey)) {
- event.preventDefault();
- handleExecute();
- }
- };
-
- const handleMesageClick = message => {
- // console.log('EDITOR', editorRef.current.editor);
- if (editorRef.current && editorRef.current.editor) {
- editorRef.current.editor.gotoLine(message.line);
- }
- };
-
- const handleFormatCode = () => {
- editorRef.current.editor.setValue(sqlFormatter.format(editorRef.current.editor.getValue()));
- editorRef.current.editor.clearSelection();
- };
-
- if (isLoading) {
- return (
-
-
-
- );
- }
-
- return (
- <>
-
-
- {visibleResultTabs && (
-
-
-
-
-
- )}
-
- {/* {toolbarPortalRef &&
- toolbarPortalRef.current &&
- tabVisible &&
- ReactDOM.createPortal(
- ,
- toolbarPortalRef.current
- )} */}
- {statusbarPortalRef &&
- statusbarPortalRef.current &&
- tabVisible &&
- ReactDOM.createPortal({timerLabel.text} , statusbarPortalRef.current)}
-
-
-
-
- >
- );
-}
-
-QueryTab.allowAddToFavorites = props => true;
diff --git a/packages/web/src/tabs/ShellTab.js b/packages/web/src/tabs/ShellTab.js
deleted file mode 100644
index 3f9174b6d..000000000
--- a/packages/web/src/tabs/ShellTab.js
+++ /dev/null
@@ -1,148 +0,0 @@
-import React from 'react';
-import ReactDOM from 'react-dom';
-import _ from 'lodash';
-import axios from '../utility/axios';
-import { useSetOpenedTabs } from '../utility/globalState';
-import { VerticalSplitter } from '../widgets/Splitter';
-import keycodes from '../utility/keycodes';
-import { changeTab } from '../utility/common';
-import useSocket from '../utility/SocketProvider';
-import GenericEditor from '../sqleditor/GenericEditor';
-import ShellToolbar from '../query/ShellToolbar';
-import RunnerOutputPane from '../query/RunnerOutputPane';
-import useShowModal from '../modals/showModal';
-import ImportExportModal from '../modals/ImportExportModal';
-import useEditorData from '../utility/useEditorData';
-import SaveTabModal from '../modals/SaveTabModal';
-import LoadingInfo from '../widgets/LoadingInfo';
-import useTimerLabel from '../utility/useTimerLabel';
-import { StatusBarItem } from '../widgets/StatusBar';
-import ToolbarPortal from '../utility/ToolbarPortal';
-
-const configRegex = /\s*\/\/\s*@ImportExportConfigurator\s*\n\s*\/\/\s*(\{[^\n]+\})\n/;
-const requireRegex = /\s*(\/\/\s*@require\s+[^\n]+)\n/g;
-const initRegex = /([^\n]+\/\/\s*@init)/g;
-
-export default function ShellTab({ tabid, tabVisible, toolbarPortalRef, statusbarPortalRef, ...other }) {
- const [busy, setBusy] = React.useState(false);
- const showModal = useShowModal();
- const { editorData, setEditorData, isLoading } = useEditorData({ tabid });
- const timerLabel = useTimerLabel();
-
- const setOpenedTabs = useSetOpenedTabs();
-
- const [executeNumber, setExecuteNumber] = React.useState(0);
- const [runnerId, setRunnerId] = React.useState(null);
-
- const socket = useSocket();
-
- React.useEffect(() => {
- changeTab(tabid, setOpenedTabs, tab => ({ ...tab, busy }));
- }, [busy]);
-
- const editorRef = React.useRef(null);
-
- const handleRunnerDone = React.useCallback(() => {
- setBusy(false);
- timerLabel.stop();
- }, []);
-
- React.useEffect(() => {
- if (runnerId && socket) {
- socket.on(`runner-done-${runnerId}`, handleRunnerDone);
- return () => {
- socket.off(`runner-done-${runnerId}`, handleRunnerDone);
- };
- }
- }, [runnerId, socket]);
-
- const handleExecute = async () => {
- if (busy) return;
- setExecuteNumber(num => num + 1);
- const selectedText = editorRef.current.editor.getSelectedText();
-
- let runid = runnerId;
- const resp = await axios.post('runners/start', {
- script: selectedText
- ? [...(editorData || '').matchAll(requireRegex)].map(x => `${x[1]}\n`).join('') +
- [...(editorData || '').matchAll(initRegex)].map(x => `${x[1]}\n`).join('') +
- selectedText
- : editorData,
- });
- runid = resp.data.runid;
- setRunnerId(runid);
- setBusy(true);
- timerLabel.start();
- };
-
- const handleCancel = () => {
- axios.post('runners/cancel', {
- runid: runnerId,
- });
- timerLabel.stop();
- };
-
- const handleKeyDown = (data, hash, keyString, keyCode, event) => {
- if (keyCode == keycodes.f5) {
- event.preventDefault();
- handleExecute();
- }
- };
-
- const handleEdit = () => {
- const jsonTextMatch = (editorData || '').match(configRegex);
- if (jsonTextMatch) {
- showModal(modalState => (
-
- ));
- }
- };
-
- if (isLoading) {
- return (
-
-
-
- );
- }
-
- return (
- <>
-
-
-
-
-
-
-
- {statusbarPortalRef &&
- statusbarPortalRef.current &&
- tabVisible &&
- ReactDOM.createPortal({timerLabel.text} , statusbarPortalRef.current)}
-
- >
- );
-}
-
-ShellTab.allowAddToFavorites = props => true;
diff --git a/packages/web/src/tabs/TableDataTab.js b/packages/web/src/tabs/TableDataTab.js
deleted file mode 100644
index 647af48e8..000000000
--- a/packages/web/src/tabs/TableDataTab.js
+++ /dev/null
@@ -1,31 +0,0 @@
-import React from 'react';
-import { createGridCache, createChangeSet, createGridConfig } 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';
-
-export default function TableDataTab({ conid, database, schemaName, pureName, tabVisible, toolbarPortalRef, tabid }) {
- const [changeSetState, dispatchChangeSet] = useUndoReducer(createChangeSet());
- useUpdateDatabaseForTab(tabVisible, conid, database);
- const [config, setConfig] = useGridConfig(tabid);
-
- return (
-
- );
-}
-
-TableDataTab.matchingProps = ['conid', 'database', 'schemaName', 'pureName'];
-TableDataTab.allowAddToFavorites = props => true;
diff --git a/packages/web/src/tabs/TableStructureTab.js b/packages/web/src/tabs/TableStructureTab.js
deleted file mode 100644
index b5946d037..000000000
--- a/packages/web/src/tabs/TableStructureTab.js
+++ /dev/null
@@ -1,141 +0,0 @@
-import React from 'react';
-import styled from 'styled-components';
-import _ from 'lodash';
-import ObjectListControl from '../utility/ObjectListControl';
-import { TableColumn } from '../utility/TableControl';
-import { useTableInfo, useDbCore } from '../utility/metadataLoaders';
-import useTheme from '../theme/useTheme';
-import ColumnLabel from '../datagrid/ColumnLabel';
-import { FontIcon } from '../icons';
-
-const WhitePage = styled.div`
- position: absolute;
- left: 0;
- top: 0;
- right: 0;
- bottom: 0;
- background-color: ${props => props.theme.main_background};
- overflow: auto;
-`;
-
-const IconTextSpan = styled.span`
- white-space: nowrap;
-`;
-
-function getConstraintIcon(data) {
- if (data.constraintType == 'primaryKey') return 'img primary-key';
- if (data.constraintType == 'foreignKey') return 'img foreign-key';
- return null;
-}
-
-function ConstraintLabel({ data }) {
- const icon = getConstraintIcon(data);
- return (
-
- {data.constraintName}
-
- );
-}
-
-export default function TableStructureTab({ conid, database, schemaName, pureName, objectTypeField = 'tables' }) {
- const theme = useTheme();
- const tableInfo = useDbCore({ conid, database, schemaName, pureName, objectTypeField });
- if (!tableInfo) return null;
- const { columns, primaryKey, foreignKeys, dependencies } = tableInfo;
- return (
-
- ({ ...x, ordinal: index + 1 }))}
- NameComponent={({ data }) => }
- // makeAppObj={columnAppObject}
- title="Columns"
- >
- (row.notNull ? 'YES' : 'NO')}
- />
-
-
- (row.isSparse ? 'YES' : 'NO')}
- />
-
- (row.isPersisted ? 'YES' : 'NO')}
- />
- {/* {_.includes(dbCaps.columnListOptionalColumns, 'referencedTableNamesFormatted') && (
-
- )}
- (
-
- this.deleteColumn(row)}
- >
- Delete
- {' '}
- |{' '}
- this.editColumn(row)}
- >
- Edit
-
-
- )}
- /> */}
-
-
-
- row.columns.map(x => x.columnName).join(', ')}
- />
-
-
-
- row.columns.map(x => x.columnName).join(', ')}
- />
- row.refTableName} />
- row.columns.map(x => x.refColumnName).join(', ')}
- />
-
-
-
-
-
- row.columns.map(x => x.columnName).join(', ')}
- />
- row.pureName} />
- row.columns.map(x => x.refColumnName).join(', ')}
- />
-
-
-
-
- );
-}
diff --git a/packages/web/src/tabs/ViewDataTab.js b/packages/web/src/tabs/ViewDataTab.js
deleted file mode 100644
index dff851026..000000000
--- a/packages/web/src/tabs/ViewDataTab.js
+++ /dev/null
@@ -1,59 +0,0 @@
-import React from 'react';
-import DataGrid from '../datagrid/DataGrid';
-import { ViewGridDisplay, createGridCache, createChangeSet } from 'dbgate-datalib';
-import { useConnectionInfo, useViewInfo } from '../utility/metadataLoaders';
-import useUndoReducer from '../utility/useUndoReducer';
-import usePropsCompare from '../utility/usePropsCompare';
-import { useUpdateDatabaseForTab } from '../utility/globalState';
-import useGridConfig from '../utility/useGridConfig';
-import SqlDataGridCore from '../datagrid/SqlDataGridCore';
-import useExtensions from '../utility/useExtensions';
-import { findEngineDriver } from 'dbgate-tools';
-
-export default function ViewDataTab({ conid, database, schemaName, pureName, tabVisible, toolbarPortalRef, tabid }) {
- const viewInfo = useViewInfo({ conid, database, schemaName, pureName });
- const [config, setConfig] = useGridConfig(tabid);
- const [cache, setCache] = React.useState(createGridCache());
- const [changeSetState, dispatchChangeSet] = useUndoReducer(createChangeSet());
- const extensions = useExtensions();
-
- useUpdateDatabaseForTab(tabVisible, conid, database);
- const connection = useConnectionInfo({ conid });
-
- // usePropsCompare({ tableInfo, connection, config, cache });
-
- const display = React.useMemo(
- () =>
- viewInfo && connection
- ? new ViewGridDisplay(
- viewInfo,
- findEngineDriver(connection, extensions),
- //@ts-ignore
- config,
- setConfig,
- cache,
- setCache
- )
- : null,
- [viewInfo, connection, config, cache]
- );
-
- if (!display) return null;
-
- return (
-
- );
-}
-
-ViewDataTab.matchingProps = ['conid', 'database', 'schemaName', 'pureName'];
-ViewDataTab.allowAddToFavorites = props => true;
diff --git a/packages/web/src/tabs/index.js b/packages/web/src/tabs/index.js
deleted file mode 100644
index a561058b1..000000000
--- a/packages/web/src/tabs/index.js
+++ /dev/null
@@ -1,33 +0,0 @@
-import TableDataTab from './TableDataTab';
-import ViewDataTab from './ViewDataTab';
-import TableStructureTab from './TableStructureTab';
-import QueryTab from './QueryTab';
-import ShellTab from './ShellTab';
-import InfoPageTab from './InfoPageTab';
-import ArchiveFileTab from './ArchiveFileTab';
-import FreeTableTab from './FreeTableTab';
-import PluginTab from './PluginTab';
-import ChartTab from './ChartTab';
-import MarkdownEditorTab from './MarkdownEditorTab';
-import MarkdownViewTab from './MarkdownViewTab';
-import MarkdownPreviewTab from './MarkdownPreviewTab';
-import FavoriteEditorTab from './FavoriteEditorTab';
-import QueryDesignTab from './QueryDesignTab';
-
-export default {
- TableDataTab,
- ViewDataTab,
- TableStructureTab,
- QueryTab,
- InfoPageTab,
- ShellTab,
- ArchiveFileTab,
- FreeTableTab,
- PluginTab,
- ChartTab,
- MarkdownEditorTab,
- MarkdownViewTab,
- MarkdownPreviewTab,
- FavoriteEditorTab,
- QueryDesignTab,
-};
diff --git a/packages/web/src/theme/_theme.bak.js b/packages/web/src/theme/_theme.bak.js
deleted file mode 100644
index 58c3c6b24..000000000
--- a/packages/web/src/theme/_theme.bak.js
+++ /dev/null
@@ -1,33 +0,0 @@
-// export default {
-// widgetMenu: {
-// iconSize: 60,
-// background: '#222',
-// iconFontSize: '23pt',
-// iconFontColor: '#eee',
-// backgroundHover: '#555',
-// backgroundSelected: '#4CAF50',
-// },
-// leftPanel: {
-// // width: 300,
-// background: '#ccc',
-// },
-// tabsPanel: {
-// height: 53,
-// background: '#ddd',
-// hoverFont: '#338',
-// },
-// statusBar: {
-// height: 20,
-// background: '#00c',
-// },
-// toolBar: {
-// height: 30,
-// background: '#eee',
-// },
-// mainArea: {
-// background: '#eee',
-// },
-// splitter: {
-// thickness: 3,
-// },
-// };
diff --git a/packages/web/src/theme/colorUtil.js b/packages/web/src/theme/colorUtil.js
deleted file mode 100644
index cfddd70b8..000000000
--- a/packages/web/src/theme/colorUtil.js
+++ /dev/null
@@ -1,163 +0,0 @@
-// https://css-tricks.com/using-javascript-to-adjust-saturation-and-brightness-of-rgb-colors/
-
-export function hexToRgb(rgb) {
- if (!rgb) throw new Error(`Ivalid RGB color: ${rgb}`);
- if (rgb.match(/^#[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]$/)) {
- rgb = `#${rgb[1]}${rgb[1]}${rgb[2]}${rgb[2]}${rgb[3]}${rgb[3]}`;
- }
- if (!rgb.match(/^#[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]$/)) {
- throw new Error(`Ivalid RGB color: ${rgb}`);
- }
- return [rgb.substring(1, 3), rgb.substring(3, 5), rgb.substring(5, 7)].map(x => parseInt(x, 16));
-}
-
-function componentToHex(c) {
- let num = Math.round(c);
- if (num < 0) num = 0;
- if (num > 255) num = 255;
- var hex = num.toString(16);
- return hex.length == 1 ? '0' + hex : hex;
-}
-
-export function rgbToHex(r, g, b) {
- return '#' + componentToHex(r) + componentToHex(g) + componentToHex(b);
-}
-
-export function getLightnessOfRGB(rgb) {
- // First convert to an array of integers by removing the whitespace, taking the 3rd char to the 2nd last then splitting by ','
- const rgbIntArray = hexToRgb(rgb);
-
- // Get the highest and lowest out of red green and blue
- const highest = Math.max(...rgbIntArray);
- const lowest = Math.min(...rgbIntArray);
-
- // Return the average divided by 255
- return (highest + lowest) / 2 / 255;
-}
-
-export function getColorType(rgb) {
- return getLightnessOfRGB(rgb) > 0.5 ? 'light' : 'dark';
-}
-
-export function saturateByTenth(rgb) {
- const rgbIntArray = hexToRgb(rgb);
- const grayVal = getLightnessOfRGB(rgb) * 255;
- const [lowest, middle, highest] = getLowestMiddleHighest(rgbIntArray);
-
- if (lowest.val === highest.val) {
- return rgb;
- }
-
- const saturationRange = Math.round(Math.min(255 - grayVal, grayVal));
- const maxChange = Math.min(255 - highest.val, lowest.val);
- const changeAmount = Math.min(saturationRange / 10, maxChange);
- const middleValueRatio = (grayVal - middle.val) / (grayVal - highest.val);
-
- const returnArray = [];
- returnArray[highest.index] = Math.round(highest.val + changeAmount);
- returnArray[lowest.index] = Math.round(lowest.val - changeAmount);
- returnArray[middle.index] = Math.round(grayVal + (returnArray[highest.index] - grayVal) * middleValueRatio);
- return `rgb(${[returnArray].join()})`;
-}
-
-function getLowestMiddleHighest(rgbIntArray) {
- let highest = { val: -1, index: -1 };
- let lowest = { val: Infinity, index: -1 };
-
- rgbIntArray.map((val, index) => {
- if (val > highest.val) {
- highest = { val: val, index: index };
- }
- if (val < lowest.val) {
- lowest = { val: val, index: index };
- }
- });
-
- if (lowest.index === highest.index) {
- lowest.index = highest.index + 1;
- }
-
- let middle = { index: 3 - highest.index - lowest.index };
- middle.val = rgbIntArray[middle.index];
- return [lowest, middle, highest];
-}
-
-export function lightenByTenth(rgb, ratio = 0.1) {
- const rgbIntArray = hexToRgb(rgb);
- // Grab the values in order of magnitude
- // This uses the getLowestMiddleHighest function from the saturate section
- const [lowest, middle, highest] = getLowestMiddleHighest(rgbIntArray);
-
- if (lowest.val === 255) {
- return rgb;
- }
-
- const returnArray = [];
-
- // First work out increase on lower value
- returnArray[lowest.index] = Math.round(lowest.val + Math.min(255 - lowest.val, 255 * ratio));
-
- // Then apply to the middle and higher values
- const increaseFraction = (returnArray[lowest.index] - lowest.val) / (255 - lowest.val);
- returnArray[middle.index] = middle.val + (255 - middle.val) * increaseFraction;
- returnArray[highest.index] = highest.val + (255 - highest.val) * increaseFraction;
-
- // Convert the array back into an rgb string
- return rgbToHex(...returnArray);
-}
-
-export function darkenByTenth(rgb, ratio = 0.1) {
- // Our rgb to int array function again
- const rgbIntArray = hexToRgb(rgb);
- //grab the values in order of magnitude
- //this uses the function from the saturate function
- const [lowest, middle, highest] = getLowestMiddleHighest(rgbIntArray);
-
- if (highest.val === 0) {
- return rgb;
- }
-
- const returnArray = [];
-
- returnArray[highest.index] = highest.val - Math.min(highest.val, 255 * ratio);
- const decreaseFraction = (highest.val - returnArray[highest.index]) / highest.val;
- returnArray[middle.index] = middle.val - middle.val * decreaseFraction;
- returnArray[lowest.index] = lowest.val - lowest.val * decreaseFraction;
-
- // Convert the array back into an rgb string
- return rgbToHex(...returnArray);
-}
-
-export function desaturateByTenth(rgb) {
- const rgbIntArray = hexToRgb(rgb);
- //grab the values in order of magnitude
- //this uses the getLowestMiddleHighest function from the saturate section
- const [lowest, middle, highest] = getLowestMiddleHighest(rgbIntArray);
- const grayVal = getLightnessOfRGB(rgb) * 255;
-
- if (lowest.val === highest.val) {
- return rgb;
- }
-
- const saturationRange = Math.round(Math.min(255 - grayVal, grayVal));
- const maxChange = grayVal - lowest.val;
- const changeAmount = Math.min(saturationRange / 10, maxChange);
-
- const middleValueRatio = (grayVal - middle.val) / (grayVal - highest.val);
-
- const returnArray = [];
- returnArray[highest.index] = Math.round(highest.val - changeAmount);
- returnArray[lowest.index] = Math.round(lowest.val + changeAmount);
- returnArray[middle.index] = Math.round(grayVal + (returnArray[highest.index] - grayVal) * middleValueRatio);
- return rgbToHex(...returnArray);
-}
-
-export function accentColor(rgb, index, ratio = 0.1) {
- const rgbIntArray = hexToRgb(rgb);
- const returnArray = rgbIntArray.map((v, i) => {
- if (i == index) return v + 255 * ratio;
- return v - 128 * ratio;
- });
-
- return rgbToHex(...returnArray);
-}
diff --git a/packages/web/src/theme/dark.js b/packages/web/src/theme/dark.js
deleted file mode 100644
index a39ba49e5..000000000
--- a/packages/web/src/theme/dark.js
+++ /dev/null
@@ -1,38 +0,0 @@
-import fillTheme from './fillTheme';
-
-const theme = {
- main_type: 'dark',
- main_background: '#444',
-
- fontWhite1: '#ddd',
-
- selectionAntName: 'blue',
- aceEditorTheme: 'twilight',
- jsonViewerTheme: 'monokai',
-
- border: '#555',
- border_background: '#555',
-
- toolbar_background: '#333',
- content_background: '#333',
- left_background: '#333',
- widget_background: '#222',
- title_background: '#555',
- manager_background: '#222',
- tabs_background: '#111',
- gridheader_background: '#333',
- gridbody_background: '#1a1a1a',
- scrollbar_background: '#444',
- input_background: '#222',
- modal_background: '#222',
- modalheader_background: '#555',
- button_background: '#004488',
- statusbar_background: '#00c',
- inlinebtn_background: '#222',
-
- designer_background: '#333',
- designtable_background: '#000',
- designer_line: '#bbb',
-};
-
-export default fillTheme(theme);
diff --git a/packages/web/src/theme/dimensions.js b/packages/web/src/theme/dimensions.js
deleted file mode 100644
index 6835bf256..000000000
--- a/packages/web/src/theme/dimensions.js
+++ /dev/null
@@ -1,18 +0,0 @@
-export default {
- widgetMenu: {
- iconSize: 60,
- iconFontSize: '23pt',
- },
- tabsPanel: {
- height: 53,
- },
- statusBar: {
- height: 20,
- },
- toolBar: {
- height: 30,
- },
- splitter: {
- thickness: 3,
- },
-};
diff --git a/packages/web/src/theme/fillTheme.js b/packages/web/src/theme/fillTheme.js
deleted file mode 100644
index 728597148..000000000
--- a/packages/web/src/theme/fillTheme.js
+++ /dev/null
@@ -1,95 +0,0 @@
-import _ from 'lodash';
-import { accentColor, darkenByTenth, getColorType, lightenByTenth } from './colorUtil';
-import { generate, presetPalettes, presetDarkPalettes, presetPrimaryColors } from '@ant-design/colors';
-
-function fillOne(theme, name, type, add, background, fontName, invFontName, changeLightFunc, fontPalettes) {
- add[`${name}_font1`] = add[`${fontName}1`];
- add[`${name}_font2`] = add[`${fontName}2`];
- add[`${name}_font3`] = add[`${fontName}3`];
- add[`${name}_font4`] = add[`${fontName}4`];
-
- add[`${name}_invfont1`] = add[`${invFontName}1`];
- add[`${name}_invfont2`] = add[`${invFontName}2`];
- add[`${name}_invfont3`] = add[`${invFontName}3`];
- add[`${name}_invfont4`] = add[`${invFontName}4`];
- // add[`${name}_fontDisabled`] = add.fontBlack3;
-
- if (background) {
- add[`${name}_background1`] = background;
- add[`${name}_background2`] = changeLightFunc(add[`${name}_background1`]);
- add[`${name}_background3`] = changeLightFunc(add[`${name}_background2`]);
- add[`${name}_background4`] = changeLightFunc(add[`${name}_background3`]);
- }
-
- for (const colorName in presetPrimaryColors) {
- add[`${name}_font_${colorName}`] = fontPalettes[colorName];
- if (background) {
- add[`${name}_background_${colorName}`] = generate(presetPrimaryColors[colorName], {
- theme: type,
- backgroundColor: background,
- });
-
- add[`${name}_selection`] = generate(
- theme.selectionAntName ? presetPrimaryColors[theme.selectionAntName] : theme.selectionBaseColor,
- {
- theme: type,
- backgroundColor: background,
- }
- );
- }
- }
-
- add[`${name}_font_hover`] = add[`${name}_font_geekblue`][8];
- add[`${name}_font_link`] = add[`${name}_font_geekblue`][7];
-
- if (background) {
- add[`${name}_background_alt2`] = changeLightFunc(add[`${name}_background1`], type == 'light' ? 0.05 : 0.1);
- add[`${name}_background_alt3`] = add[`${name}_background_geekblue`][type == 'light' ? 0 : 1];
- }
-}
-
-function fillThemeCore(theme) {
- const add = { ...theme };
- add.fontWhite1 = add.fontWhite1 || '#FFFFFF';
- add.fontWhite2 = add.fontWhite2 || darkenByTenth(add.fontWhite1, 0.3);
- add.fontWhite3 = add.fontWhite3 || darkenByTenth(add.fontWhite2, 0.2);
- add.fontWhite4 = add.fontWhite4 || darkenByTenth(add.fontWhite3, 0.2);
-
- add.fontBlack1 = add.fontBlack1 || '#000000';
- add.fontBlack2 = add.fontBlack2 || lightenByTenth(add.fontBlack1, 0.3);
- add.fontBlack3 = add.fontBlack3 || lightenByTenth(add.fontBlack2, 0.2);
- add.fontBlack4 = add.fontBlack4 || lightenByTenth(add.fontBlack3, 0.2);
-
- for (const key of _.keys(theme)) {
- const matchType = key.match(/^(.*)_type$/);
- const matchBg = key.match(/^(.*)_background$/);
- if (!matchType && !matchBg) continue;
- const name = matchType ? matchType[1] : matchBg[1];
- if (matchBg && theme[`${name}_type`]) continue;
-
- const type = matchType ? theme[key] : getColorType(theme[key]);
- if (type != 'light' && type != 'dark') continue;
-
- const background = theme[`${name}_background`];
- if (type == 'light') {
- fillOne(theme, name, type, add, background, 'fontBlack', 'fontWhite', darkenByTenth, presetPalettes);
- }
- if (type == 'dark') {
- fillOne(theme, name, type, add, background, 'fontWhite', 'fontBlack', lightenByTenth, presetDarkPalettes);
- }
- }
-
- if (add.main_type == 'dark') add.main_palettes = presetDarkPalettes;
- else add.main_palettes = presetPalettes;
-
- return {
- ...add,
- ...theme,
- };
-}
-
-export default function fillTheme(theme) {
- theme = fillThemeCore(theme);
- console.log('THEME', theme);
- return theme;
-}
diff --git a/packages/web/src/theme/light.js b/packages/web/src/theme/light.js
deleted file mode 100644
index 6324946ff..000000000
--- a/packages/web/src/theme/light.js
+++ /dev/null
@@ -1,37 +0,0 @@
-import fillTheme from './fillTheme';
-
-const theme = {
- main_type: 'light',
- main_background: '#fff',
-
- selectionAntName: 'blue',
- aceEditorTheme: 'github',
- jsonViewerTheme: 'rjv-default',
-
- border: '#ccc',
- border_background: '#ccc',
-
- toolbar_background: '#eee',
- content_background: '#eee',
- left_background: '#ccc',
- widget_background: '#222',
- title_background: '#888',
- manager_background: '#fff',
- tabs_background: '#eee',
- gridheader_background: '#eee',
- gridheader_type: 'light',
- gridbody_background: '#fff',
- scrollbar_background: '#ddd',
- input_background: '#fff',
- modal_background: '#fff',
- modalheader_background: '#eff',
- button_background: '#337ab7',
- statusbar_background: '#00c',
- inlinebtn_background: '#ededed',
-
- designer_background: '#eee',
- designtable_background: '#fff',
- designer_line: '#666',
-};
-
-export default fillTheme(theme);
diff --git a/packages/web/src/theme/useTheme.js b/packages/web/src/theme/useTheme.js
deleted file mode 100644
index 518eb0991..000000000
--- a/packages/web/src/theme/useTheme.js
+++ /dev/null
@@ -1,10 +0,0 @@
-import { useCurrentTheme } from '../utility/globalState';
-import light from './light';
-import dark from './dark';
-
-const themes = { light, dark };
-
-export default function useTheme() {
- const currentTheme = useCurrentTheme();
- return themes[currentTheme] || light;
-}
diff --git a/packages/web/src/themes/ThemeHelmet.js b/packages/web/src/themes/ThemeHelmet.js
deleted file mode 100644
index 4ebe05b99..000000000
--- a/packages/web/src/themes/ThemeHelmet.js
+++ /dev/null
@@ -1,72 +0,0 @@
-import React from 'react';
-import { Helmet } from 'react-helmet';
-import useTheme from '../theme/useTheme';
-import _ from 'lodash';
-
-export default function ThemeHelmet() {
- const theme = useTheme();
- return (
-
-
-
- );
-}
diff --git a/packages/web/src/utility/ConnectionsPinger.js b/packages/web/src/utility/ConnectionsPinger.js
deleted file mode 100644
index 67784ca45..000000000
--- a/packages/web/src/utility/ConnectionsPinger.js
+++ /dev/null
@@ -1,35 +0,0 @@
-import React from 'react';
-import _ from 'lodash';
-import { useOpenedConnections, useCurrentDatabase } from './globalState';
-import axios from './axios';
-
-export default function ConnectionsPinger({ children }) {
- const openedConnections = useOpenedConnections();
- const currentDatabase = useCurrentDatabase();
-
- const doServerPing = () => {
- axios.post('server-connections/ping', { connections: openedConnections });
- };
-
- const doDatabasePing = () => {
- const database = _.get(currentDatabase, 'name');
- const conid = _.get(currentDatabase, 'connection._id');
- if (conid && database) {
- axios.post('database-connections/ping', { conid, database });
- }
- };
-
- React.useEffect(() => {
- doServerPing();
- const handle = window.setInterval(doServerPing, 30 * 1000);
- return () => window.clearInterval(handle);
- }, [openedConnections]);
-
- React.useEffect(() => {
- doDatabasePing();
- const handle = window.setInterval(doDatabasePing, 30 * 1000);
- return () => window.clearInterval(handle);
- }, [currentDatabase]);
-
- return children;
-}
diff --git a/packages/web/src/utility/ErrorBoundary.js b/packages/web/src/utility/ErrorBoundary.js
deleted file mode 100644
index da309d36a..000000000
--- a/packages/web/src/utility/ErrorBoundary.js
+++ /dev/null
@@ -1,95 +0,0 @@
-import React from 'react';
-import _ from 'lodash';
-import ErrorInfo from '../widgets/ErrorInfo';
-import styled from 'styled-components';
-import localforage from 'localforage';
-import FormStyledButton from '../widgets/FormStyledButton';
-
-const Stack = styled.pre`
- margin-left: 20px;
-`;
-
-const WideButton = styled(FormStyledButton)`
- width: 150px;
-`;
-
-const Info = styled.div`
- margin: 20px;
-`;
-
-export function ErrorScreen({ error }) {
- let message;
- try {
- message = 'Error: ' + (error.message || error).toString();
- } catch (e) {
- message = 'DbGate internal error detected';
- }
-
- const handleReload = () => {
- window.location.reload();
- };
-
- const handleClearReload = async () => {
- localStorage.clear();
- try {
- await localforage.clear();
- } catch (err) {
- console.error('Error clearing app data', err);
- }
- window.location.reload();
- };
-
- return (
-
-
-
-
-
- If reloading doesn't help, you can try to clear all browser data (opened tabs, history of opened windows)
- and reload app. Your connections and saved files are not touched by this clear operation.
- If you see this error in the tab, closing the tab should solve the problem.
-
- {_.isString(error.stack) ? error.stack : null}
-
- );
-}
-
-export default class ErrorBoundary extends React.Component {
- constructor(props) {
- super(props);
- this.state = { hasError: false };
- }
-
- static getDerivedStateFromError(error) {
- // Update state so the next render will show the fallback UI.
- return {
- hasError: true,
- error,
- };
- }
- componentDidCatch(error, errorInfo) {
- // You can also log the error to an error reporting service
- // logErrorToMyService(error, errorInfo);
- console.error(error);
- // console.log('errorInfo', errorInfo);
- // console.log('error', error);
- }
- render() {
- if (this.state.hasError) {
- return ;
- }
- return this.props.children;
- }
-}
-
-export function ErrorBoundaryTest({ children }) {
- let error;
- try {
- const x = 1;
- // @ts-ignore
- x.log();
- } catch (err) {
- error = err;
- }
- return ;
-}
diff --git a/packages/web/src/utility/FormArgumentList.js b/packages/web/src/utility/FormArgumentList.js
deleted file mode 100644
index edbbe555f..000000000
--- a/packages/web/src/utility/FormArgumentList.js
+++ /dev/null
@@ -1,42 +0,0 @@
-import React from 'react';
-import _ from 'lodash';
-import styled from 'styled-components';
-import { FormTextField, FormSelectField, FormCheckboxField } from './forms';
-import { useForm } from './FormProvider';
-
-const FormArgumentsWrapper = styled.div``;
-
-function FormArgument({ arg, namePrefix }) {
- const name = `${namePrefix}${arg.name}`;
- if (arg.type == 'text') {
- return ;
- }
- if (arg.type == 'checkbox') {
- return ;
- }
- if (arg.type == 'select') {
- return (
-
- {arg.options.map(opt =>
- _.isString(opt) ? {opt} : {opt.name}
- )}
-
- );
- }
- return null;
-}
-
-export default function FormArgumentList({ args, onChangeValues = undefined, namePrefix }) {
- const { values } = useForm();
- React.useEffect(() => {
- if (onChangeValues) onChangeValues(values);
- }, [values]);
- return (
-
- {' '}
- {args.map(arg => (
-
- ))}
-
- );
-}
diff --git a/packages/web/src/utility/FormProvider.js b/packages/web/src/utility/FormProvider.js
deleted file mode 100644
index f51583294..000000000
--- a/packages/web/src/utility/FormProvider.js
+++ /dev/null
@@ -1,65 +0,0 @@
-import React from 'react';
-import { FormFieldTemplateDefault } from './formStyle';
-import keycodes from './keycodes';
-
-const FormContext = React.createContext(null);
-const FormFieldTemplateContext = React.createContext(null);
-
-export function FormProvider({ children, initialValues = {}, template = FormFieldTemplateDefault }) {
- const [values, setValues] = React.useState(initialValues);
- return (
-
- {children}
-
- );
-}
-
-export function FormProviderCore({ children, values, setValues, template = FormFieldTemplateDefault }) {
- const [submitAction, setSubmitAction] = React.useState(null);
- const handleEnter = React.useCallback(
- e => {
- if (e.keyCode == keycodes.enter && submitAction && submitAction.action) {
- e.preventDefault();
- submitAction.action(values);
- }
- },
- [submitAction, values]
- );
- React.useEffect(() => {
- document.addEventListener('keyup', handleEnter);
- return () => {
- document.removeEventListener('keyup', handleEnter);
- };
- }, [handleEnter]);
- const setFieldValue = React.useCallback(
- (field, value) =>
- setValues(v => ({
- ...v,
- [field]: value,
- })),
- [setValues]
- );
- const provider = {
- values,
- setValues,
- setFieldValue,
- setSubmitAction,
- };
- return (
-
- {children}
-
- );
-}
-
-export function useForm() {
- return React.useContext(FormContext);
-}
-
-export function FormFieldTemplateProvider({ children, template = FormFieldTemplateDefault }) {
- return {children} ;
-}
-
-export function useFormFieldTemplate() {
- return React.useContext(FormFieldTemplateContext);
-}
diff --git a/packages/web/src/utility/ObjectListControl.js b/packages/web/src/utility/ObjectListControl.js
deleted file mode 100644
index e807d8f18..000000000
--- a/packages/web/src/utility/ObjectListControl.js
+++ /dev/null
@@ -1,45 +0,0 @@
-import React from 'react';
-import styled from 'styled-components';
-import TableControl, { TableColumn } from './TableControl';
-// import { AppObjectControl } from '../appobj/AppObjects';
-import useTheme from '../theme/useTheme';
-
-const ObjectListWrapper = styled.div`
- margin-bottom: 20px;
-`;
-
-const ObjectListHeader = styled.div`
- background-color: ${props => props.theme.gridheader_background};
- 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, NameComponent, children }) {
- const theme = useTheme();
- if (collection.length == 0 && !showIfEmpty) return null;
-
- return (
-
-
- {title}
-
-
-
- } />
- {children}
-
-
-
- );
-}
diff --git a/packages/web/src/utility/SaveFileToolbarButton.js b/packages/web/src/utility/SaveFileToolbarButton.js
deleted file mode 100644
index d4af2f855..000000000
--- a/packages/web/src/utility/SaveFileToolbarButton.js
+++ /dev/null
@@ -1,26 +0,0 @@
-import React from 'react';
-import { DropDownMenuItem } from '../modals/DropDownMenu';
-import ToolbarButton, { ToolbarDropDownButton } from '../widgets/ToolbarButton';
-
-export default function SaveFileToolbarButton({ tabid, save, saveAs }) {
- if (!saveAs) return null;
-
- if (save) {
- return (
-
-
- Save
-
-
- Save As
-
-
- );
- }
-
- return (
-
- Save As
-
- );
-}
diff --git a/packages/web/src/utility/SocketProvider.js b/packages/web/src/utility/SocketProvider.js
deleted file mode 100644
index 9ec8a472b..000000000
--- a/packages/web/src/utility/SocketProvider.js
+++ /dev/null
@@ -1,21 +0,0 @@
-import io from 'socket.io-client';
-import React from 'react';
-import resolveApi from './resolveApi';
-import { cacheClean } from './cache';
-
-const SocketContext = React.createContext(null);
-
-export function SocketProvider({ children }) {
- const [socket, setSocket] = React.useState();
- React.useEffect(() => {
- // const newSocket = io('http://localhost:3000', { transports: ['websocket'] });
- const newSocket = io(resolveApi());
- setSocket(newSocket);
- newSocket.on('clean-cache', reloadTrigger => cacheClean(reloadTrigger));
- }, []);
- return {children} ;
-}
-
-export default function useSocket() {
- return React.useContext(SocketContext);
-}
diff --git a/packages/web/src/utility/TableControl.js b/packages/web/src/utility/TableControl.js
deleted file mode 100644
index a2aae15d9..000000000
--- a/packages/web/src/utility/TableControl.js
+++ /dev/null
@@ -1,123 +0,0 @@
-import React from 'react';
-import _ from 'lodash';
-import styled from 'styled-components';
-import keycodes from './keycodes';
-import useTheme from '../theme/useTheme';
-
-const Table = styled.table`
- border-collapse: collapse;
- width: 100%;
- user-select: ${props =>
- // @ts-ignore
- props.focusable ? 'none' : ''};
- // outline: none;
-`;
-const TableHead = styled.thead``;
-const TableBody = styled.tbody``;
-const TableHeaderRow = styled.tr``;
-const TableBodyRow = styled.tr`
- background-color: ${props =>
- // @ts-ignore
- props.isSelected ? props.theme.gridbody_background_blue[1] : props.theme.gridbody_background};
-`;
-const TableHeaderCell = styled.td`
- border: 1px solid ${props => props.theme.gridheader_background};
- background-color: ${props => props.theme.gridheader_background};
- padding: 5px;
-`;
-const TableBodyCell = styled.td`
- border: 1px solid ${props => props.theme.gridbody_background2};
- padding: 5px;
-`;
-
-export function TableColumn({ fieldName, header, sortable = false, 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,
- focusOnCreate = false,
- onKeyDown = undefined,
- tabIndex = -1,
- setSelectedIndex = undefined,
- selectedIndex = undefined,
- tableRef = undefined,
-}) {
- const columns = (children instanceof Array ? _.flatten(children) : [children])
- .filter(child => child && child.props && child.props.fieldName)
- .map(child => child.props);
-
- const myTableRef = React.useRef(null);
- const currentTableRef = tableRef || myTableRef;
- const theme = useTheme();
-
- React.useEffect(() => {
- if (focusOnCreate) {
- currentTableRef.current.focus();
- }
- }, []);
-
- const handleKeyDown = React.useCallback(
- event => {
- if (event.keyCode == keycodes.downArrow) {
- setSelectedIndex(i => Math.min(i + 1, rows.length - 1));
- }
- if (event.keyCode == keycodes.upArrow) {
- setSelectedIndex(i => Math.max(0, i - 1));
- }
- if (onKeyDown) onKeyDown(event);
- },
- [setSelectedIndex, rows]
- );
-
- return (
-
-
-
- {columns.map(x => (
-
- {x.header}
-
- ))}
-
-
-
- {rows.map((row, index) => (
- {
- setSelectedIndex(index);
- currentTableRef.current.focus();
- }
- : undefined
- }
- >
- {columns.map(col => (
-
- {format(row, col)}
-
- ))}
-
- ))}
-
-
- );
-}
diff --git a/packages/web/src/utility/ToolbarPortal.js b/packages/web/src/utility/ToolbarPortal.js
deleted file mode 100644
index ba184681f..000000000
--- a/packages/web/src/utility/ToolbarPortal.js
+++ /dev/null
@@ -1,13 +0,0 @@
-import React from 'react';
-import ReactDOM from 'react-dom';
-
-export default function ToolbarPortal({ toolbarPortalRef, tabVisible, children }) {
- return (
- (toolbarPortalRef &&
- toolbarPortalRef.current &&
- tabVisible &&
- children &&
- ReactDOM.createPortal(children, toolbarPortalRef.current)) ||
- null
- );
-}
diff --git a/packages/web/src/utility/UploadButton.js b/packages/web/src/utility/UploadButton.js
deleted file mode 100644
index 3c54d5900..000000000
--- a/packages/web/src/utility/UploadButton.js
+++ /dev/null
@@ -1,26 +0,0 @@
-import React from 'react';
-import useTheme from '../theme/useTheme';
-import { FormStyledLabel } from '../widgets/FormStyledButton';
-import styled from 'styled-components';
-import { useUploadFiles } from './UploadsProvider';
-
-const Wrapper = styled.div`
- margin: 10px;
-`;
-
-export default function UploadButton() {
- const theme = useTheme();
- const uploadFiles = useUploadFiles();
- const handleChange = e => {
- const files = [...e.target.files];
- uploadFiles(files);
- };
- return (
-
-
- Upload file
-
-
-
- );
-}
diff --git a/packages/web/src/utility/UploadsProvider.js b/packages/web/src/utility/UploadsProvider.js
deleted file mode 100644
index 726a54dbd..000000000
--- a/packages/web/src/utility/UploadsProvider.js
+++ /dev/null
@@ -1,109 +0,0 @@
-import React from 'react';
-import { useDropzone } from 'react-dropzone';
-import ImportExportModal from '../modals/ImportExportModal';
-import useShowModal from '../modals/showModal';
-import { findFileFormat } from './fileformats';
-import getElectron from './getElectron';
-import resolveApi from './resolveApi';
-import useExtensions from './useExtensions';
-import { useOpenElectronFileCore, canOpenByElectron } from './useOpenElectronFile';
-
-const UploadsContext = React.createContext(null);
-
-export default function UploadsProvider({ children }) {
- const [uploadListener, setUploadListener] = React.useState(null);
- return {children} ;
-}
-
-export function useUploadsProvider() {
- return React.useContext(UploadsContext);
-}
-
-export function useUploadFiles() {
- const { uploadListener } = useUploadsProvider();
- const showModal = useShowModal();
- const extensions = useExtensions();
- const electron = getElectron();
- const openElectronFileCore = useOpenElectronFileCore();
-
- const handleUploadFiles = React.useCallback(
- files => {
- files.forEach(async file => {
- if (parseInt(file.size, 10) >= 4 * 1024 * 1024) {
- // to big file
- return;
- }
-
- console.log('FILE', file);
-
- if (electron && canOpenByElectron(file.path, extensions)) {
- openElectronFileCore(file.path);
- return;
- }
-
- const formData = new FormData();
- formData.append('data', file);
-
- const fetchOptions = {
- method: 'POST',
- body: formData,
- };
-
- const apiBase = resolveApi();
- const resp = await fetch(`${apiBase}/uploads/upload`, fetchOptions);
- const fileData = await resp.json();
-
- fileData.shortName = file.name;
-
- for (const format of extensions.fileFormats) {
- if (file.name.endsWith('.' + format.extension)) {
- fileData.shortName = file.name.slice(0, -format.extension.length - 1);
- fileData.storageType = format.storageType;
- }
- }
-
- if (uploadListener) {
- uploadListener(fileData);
- } else {
- if (findFileFormat(extensions, fileData.storageType)) {
- showModal(modalState => (
-
- ));
- }
- }
-
- // const reader = new FileReader();
-
- // reader.onabort = () => console.log('file reading was aborted');
- // reader.onerror = () => console.log('file reading has failed');
- // reader.onload = () => {
- // // Do whatever you want with the file contents
- // const binaryStr = reader.result;
- // console.log(binaryStr);
- // };
- // reader.readAsArrayBuffer(file);
- });
- },
- [uploadListener, extensions]
- );
-
- return handleUploadFiles;
-}
-
-export function useUploadsZone() {
- const onDrop = useUploadFiles();
- const { getRootProps, getInputProps, isDragActive } = useDropzone({ onDrop });
-
- return { getRootProps, getInputProps, isDragActive };
-}
diff --git a/packages/web/src/utility/applySqlTemplate.js b/packages/web/src/utility/applySqlTemplate.js
deleted file mode 100644
index bd0a59cb4..000000000
--- a/packages/web/src/utility/applySqlTemplate.js
+++ /dev/null
@@ -1,32 +0,0 @@
-import { getDbCore, getConnectionInfo, getSqlObjectInfo } from '../utility/metadataLoaders';
-import sqlFormatter from 'sql-formatter';
-import { driverBase, findEngineDriver } from 'dbgate-tools';
-
-export default async function applySqlTemplate(sqlTemplate, extensions, props) {
- if (sqlTemplate == 'CREATE TABLE') {
- const tableInfo = await getDbCore(props, props.objectTypeField || 'tables');
- const connection = await getConnectionInfo(props);
- const driver = findEngineDriver(connection, extensions) || driverBase;
- const dmp = driver.createDumper();
- if (tableInfo) dmp.createTable(tableInfo);
- return dmp.s;
- }
- if (sqlTemplate == 'CREATE OBJECT') {
- const objectInfo = await getSqlObjectInfo(props);
- if (objectInfo) {
- if (objectInfo.requiresFormat && objectInfo.createSql) return sqlFormatter.format(objectInfo.createSql);
- else return objectInfo.createSql;
- }
- }
- if (sqlTemplate == 'EXECUTE PROCEDURE') {
- const procedureInfo = await getSqlObjectInfo(props);
- const connection = await getConnectionInfo(props);
-
- const driver = findEngineDriver(connection, extensions) || driverBase;
- const dmp = driver.createDumper();
- if (procedureInfo) dmp.put('^execute %f', procedureInfo);
- return dmp.s;
- }
-
- return null;
-}
diff --git a/packages/web/src/utility/axios.js b/packages/web/src/utility/axios.js
deleted file mode 100644
index 9a587ccb9..000000000
--- a/packages/web/src/utility/axios.js
+++ /dev/null
@@ -1,14 +0,0 @@
-import axios from 'axios';
-import resolveApi from './resolveApi';
-
-const axiosInstance = axios.create({
- baseURL: resolveApi(),
-});
-
-axiosInstance.defaults.headers = {
- 'Cache-Control': 'no-cache',
- Pragma: 'no-cache',
- Expires: '0',
-};
-
-export default axiosInstance;
diff --git a/packages/web/src/utility/cache.js b/packages/web/src/utility/cache.js
deleted file mode 100644
index 8dd251bf0..000000000
--- a/packages/web/src/utility/cache.js
+++ /dev/null
@@ -1,40 +0,0 @@
-import getAsArray from './getAsArray';
-
-let cachedByKey = {};
-let cachedPromisesByKey = {};
-const cachedKeysByReloadTrigger = {};
-
-export function cacheGet(key) {
- return cachedByKey[key];
-}
-
-export function cacheSet(key, value, reloadTrigger) {
- cachedByKey[key] = value;
- for (const item of getAsArray(reloadTrigger)) {
- if (!(item in cachedKeysByReloadTrigger)) {
- cachedKeysByReloadTrigger[item] = [];
- }
- cachedKeysByReloadTrigger[item].push(key);
- }
- delete cachedPromisesByKey[key];
-}
-
-export function cacheClean(reloadTrigger) {
- for (const item of getAsArray(reloadTrigger)) {
- const keys = cachedKeysByReloadTrigger[item];
- if (keys) {
- for (const key of keys) {
- delete cachedByKey[key];
- delete cachedPromisesByKey[key];
- }
- }
- delete cachedKeysByReloadTrigger[item];
- }
-}
-
-export function getCachedPromise(key, func) {
- if (key in cachedPromisesByKey) return cachedPromisesByKey[key];
- const promise = func();
- cachedPromisesByKey[key] = promise;
- return promise;
-}
diff --git a/packages/web/src/utility/clipboard.js b/packages/web/src/utility/clipboard.js
deleted file mode 100644
index dabbe22d1..000000000
--- a/packages/web/src/utility/clipboard.js
+++ /dev/null
@@ -1,56 +0,0 @@
-export function copyTextToClipboard(text) {
- const textArea = document.createElement('textarea');
-
- //
- // *** This styling is an extra step which is likely not required. ***
- //
- // Why is it here? To ensure:
- // 1. the element is able to have focus and selection.
- // 2. if element was to flash render it has minimal visual impact.
- // 3. less flakyness with selection and copying which **might** occur if
- // the textarea element is not visible.
- //
- // The likelihood is the element won't even render, not even a flash,
- // so some of these are just precautions. However in IE the element
- // is visible whilst the popup box asking the user for permission for
- // the web page to copy to the clipboard.
- //
-
- // Place in top-left corner of screen regardless of scroll position.
- textArea.style.position = 'fixed';
- textArea.style.top = '0';
- textArea.style.left = '0';
-
- // Ensure it has a small width and height. Setting to 1px / 1em
- // doesn't work as this gives a negative w/h on some browsers.
- textArea.style.width = '2em';
- textArea.style.height = '2em';
-
- // We don't need padding, reducing the size if it does flash render.
- textArea.style.padding = '0';
-
- // Clean up any borders.
- textArea.style.border = 'none';
- textArea.style.outline = 'none';
- textArea.style.boxShadow = 'none';
-
- // Avoid flash of white box if rendered for any reason.
- textArea.style.background = 'transparent';
-
- textArea.value = text;
-
- document.body.appendChild(textArea);
-
- textArea.select();
-
- try {
- let successful = document.execCommand('copy');
- if (!successful) {
- console.log('Failed copy to clipboard');
- }
- } catch (err) {
- console.log('Failed copy to clipboard: ' + err);
- }
-
- document.body.removeChild(textArea);
-}
diff --git a/packages/web/src/utility/common.js b/packages/web/src/utility/common.js
deleted file mode 100644
index 26afb3ba3..000000000
--- a/packages/web/src/utility/common.js
+++ /dev/null
@@ -1,24 +0,0 @@
-export class LoadingToken {
- constructor() {
- this.isCanceled = false;
- }
-
- cancel() {
- this.isCanceled = true;
- }
-}
-
-export function sleep(milliseconds) {
- return new Promise(resolve => window.setTimeout(() => resolve(null), milliseconds));
-}
-
-export function changeTab(tabid, setOpenedTabs, changeFunc) {
- setOpenedTabs(files => files.map(tab => (tab.tabid == tabid ? changeFunc(tab) : tab)));
-}
-
-export function setSelectedTabFunc(files, tabid) {
- return [
- ...(files || []).filter(x => x.tabid != tabid).map(x => ({ ...x, selected: false })),
- ...(files || []).filter(x => x.tabid == tabid).map(x => ({ ...x, selected: true })),
- ];
-}
diff --git a/packages/web/src/utility/fileformats.js b/packages/web/src/utility/fileformats.js
deleted file mode 100644
index 4d5e7760d..000000000
--- a/packages/web/src/utility/fileformats.js
+++ /dev/null
@@ -1,33 +0,0 @@
-const jsonlFormat = {
- storageType: 'jsonl',
- extension: 'jsonl',
- name: 'JSON lines',
- readerFunc: 'jsonLinesReader',
- writerFunc: 'jsonLinesWriter',
-};
-
-/** @returns {import('dbgate-types').FileFormatDefinition[]} */
-export function buildFileFormats(plugins) {
- const res = [jsonlFormat];
- for (const { content } of plugins) {
- const { fileFormats } = content;
- if (fileFormats) res.push(...fileFormats);
- }
- return res;
-}
-
-export function findFileFormat(extensions, storageType) {
- return extensions.fileFormats.find(x => x.storageType == storageType);
-}
-
-export function getFileFormatDirections(format) {
- if (!format) return [];
- const res = [];
- if (format.readerFunc) res.push('source');
- if (format.writerFunc) res.push('target');
- return res;
-}
-
-export function getDefaultFileFormat(extensions) {
- return extensions.fileFormats.find(x => x.storageType == 'csv') || jsonlFormat;
-}
diff --git a/packages/web/src/utility/flexGrid.js b/packages/web/src/utility/flexGrid.js
deleted file mode 100644
index 0603932f5..000000000
--- a/packages/web/src/utility/flexGrid.js
+++ /dev/null
@@ -1,73 +0,0 @@
-// @ts-nocheck
-import styled from 'styled-components';
-
-export const FlexCol3 = styled.div`
- flex-basis: 25%;
- max-width: 25%;
- ${props =>
- !!props.marginRight &&
- `
- margin-right: ${props.marginRight}px;
- `}
- ${props =>
- !!props.marginLeft &&
- `
- margin-left: ${props.marginLeft}px;
- `}
-`;
-export const FlexCol4 = styled.div`
- flex-basis: 33.3333%;
- max-width: 33.3333%;
- ${props =>
- !!props.marginRight &&
- `
- margin-right: ${props.marginRight}px;
- `}
- ${props =>
- !!props.marginLeft &&
- `
- margin-left: ${props.marginLeft}px;
- `}
-`;
-export const FlexCol6 = styled.div`
- flex-basis: 50%;
- max-width: 50%;
- ${props =>
- !!props.marginRight &&
- `
- margin-right: ${props.marginRight}px;
- `}
- ${props =>
- !!props.marginLeft &&
- `
- margin-left: ${props.marginLeft}px;
- `}
-`;
-export const FlexCol8 = styled.div`
- flex-basis: 66.6667%;
- max-width: 66.6667%;
- ${props =>
- !!props.marginRight &&
- `
- margin-right: ${props.marginRight}px;
- `}
- ${props =>
- !!props.marginLeft &&
- `
- margin-left: ${props.marginLeft}px;
- `}
-`;
-export const FlexCol9 = styled.div`
- flex-basis: 75%;
- max-width: 75%;
- ${props =>
- !!props.marginRight &&
- `
- margin-right: ${props.marginRight}px;
- `}
- ${props =>
- !!props.marginLeft &&
- `
- margin-left: ${props.marginLeft}px;
- `}
-`;
diff --git a/packages/web/src/utility/formStyle.js b/packages/web/src/utility/formStyle.js
deleted file mode 100644
index f4be22a13..000000000
--- a/packages/web/src/utility/formStyle.js
+++ /dev/null
@@ -1,122 +0,0 @@
-import styled from 'styled-components';
-import React from 'react';
-import useTheme from '../theme/useTheme';
-
-export const FormRow = styled.div`
- display: flex;
- margin: 10px;
-`;
-
-export const FormLabel = styled.div`
- width: 10vw;
- font-weight: bold;
-`;
-
-export const FormValue = styled.div``;
-
-export function FormFieldTemplateDefault({ label, children, labelProps, type }) {
- return (
-
- {label}
- {children}
-
- );
-}
-
-export const FormRowTiny = styled.div`
- margin: 5px;
-`;
-
-export const FormLabelTiny = styled.div`
- color: ${props => props.theme.manager_font3};
-`;
-
-export const FormValueTiny = styled.div`
- margin-left: 15px;
- margin-top: 3px;
-`;
-
-const FormLabelSpan = styled.span`
- ${props =>
- // @ts-ignore
- props.disabled &&
- `
- color: ${props.theme.manager_font3};
-`}
-`;
-
-export function FormFieldTemplateTiny({ label, children, labelProps, type }) {
- const theme = useTheme();
- if (type == 'checkbox') {
- return (
-
- {children}{' '}
-
- {label}
-
-
- );
- }
- return (
-
-
-
- {label}
-
-
- {children}
-
- );
-}
-
-const FormRowLargeTemplate = styled.div`
- ${props =>
- // @ts-ignore
- !props.noMargin &&
- `
- margin: 20px;
- `}
-`;
-
-export const FormRowLarge = styled.div`
- margin: 20px;
- display: flex;
-`;
-
-export const FormLabelLarge = styled.div`
- margin-bottom: 3px;
- color: ${props => props.theme.manager_font3};
-`;
-
-export const FormValueLarge = styled.div``;
-
-export function FormFieldTemplateLarge({ label, labelProps, children, type, noMargin = false }) {
- const theme = useTheme();
- if (type == 'checkbox') {
- return (
-
- {children}{' '}
-
- {label}
-
-
- );
- }
- return (
-
-
-
- {label}
-
-
- {children}
-
- );
-}
diff --git a/packages/web/src/utility/formatFileSize.js b/packages/web/src/utility/formatFileSize.js
deleted file mode 100644
index 059569559..000000000
--- a/packages/web/src/utility/formatFileSize.js
+++ /dev/null
@@ -1,6 +0,0 @@
-export default function formatFileSize(size) {
- if (size > 1000000000) return `${Math.round(size / 10000000000) * 10} GB`;
- if (size > 1000000) return `${Math.round(size / 10000000) * 10} MB`;
- if (size > 1000) return `${Math.round(size / 10000) * 10} KB`;
- return `${size} bytes`;
-}
diff --git a/packages/web/src/utility/forms.js b/packages/web/src/utility/forms.js
deleted file mode 100644
index 73dd75bff..000000000
--- a/packages/web/src/utility/forms.js
+++ /dev/null
@@ -1,370 +0,0 @@
-import React from 'react';
-import Select from 'react-select';
-import Creatable from 'react-select/creatable';
-import { TextField, SelectField, CheckboxField } from './inputs';
-import FormStyledButton from '../widgets/FormStyledButton';
-import {
- useConnectionList,
- useDatabaseList,
- useDatabaseInfo,
- useArchiveFolders,
- useArchiveFiles,
-} from './metadataLoaders';
-import getAsArray from './getAsArray';
-import axios from './axios';
-import useTheme from '../theme/useTheme';
-import { useForm, useFormFieldTemplate } from './FormProvider';
-import { FontIcon } from '../icons';
-import getElectron from './getElectron';
-import InlineButton from '../widgets/InlineButton';
-import styled from 'styled-components';
-
-const FlexContainer = styled.div`
- display: flex;
-`;
-
-export function FormFieldTemplate({ label, children, type }) {
- const FieldTemplate = useFormFieldTemplate();
- return (
-
- {children}
-
- );
-}
-
-export function FormCondition({ condition, children }) {
- const { values } = useForm();
- if (condition(values)) return children;
- return null;
-}
-
-export function FormTextFieldRaw({ name, focused = false, ...other }) {
- const { values, setFieldValue } = useForm();
- const handleChange = event => {
- setFieldValue(name, event.target.value);
- };
- const textFieldRef = React.useRef(null);
- React.useEffect(() => {
- if (textFieldRef.current && focused) textFieldRef.current.focus();
- }, [textFieldRef.current, focused]);
-
- return ;
-}
-
-export function FormPasswordFieldRaw({ name, focused = false, ...other }) {
- const { values, setFieldValue } = useForm();
- const [showPassword, setShowPassword] = React.useState(false);
- const handleChange = event => {
- setFieldValue(name, event.target.value);
- };
- const textFieldRef = React.useRef(null);
- React.useEffect(() => {
- if (textFieldRef.current && focused) textFieldRef.current.focus();
- }, [textFieldRef.current, focused]);
- const value = values[name];
- const isCrypted = value && value.startsWith('crypt:');
-
- return (
-
-
- {!isCrypted && (
- setShowPassword(x => !x)} disabled={other.disabled}>
-
-
- )}
-
- );
-}
-
-export function FormTextField({ name, label, focused = false, templateProps = undefined, ...other }) {
- const FieldTemplate = useFormFieldTemplate();
- return (
-
-
-
- );
-}
-
-export function FormPasswordField({ name, label, focused = false, templateProps = undefined, ...other }) {
- const FieldTemplate = useFormFieldTemplate();
- return (
-
-
-
- );
-}
-
-export function FormCheckboxFieldRaw({ name = undefined, defaultValue = undefined, ...other }) {
- const { values, setFieldValue } = useForm();
- const handleChange = event => {
- setFieldValue(name, event.target.checked);
- };
- let isChecked = values[name];
- if (isChecked == null) isChecked = defaultValue;
- return ;
- // return ;
-}
-
-export function FormCheckboxField({ label, templateProps = undefined, ...other }) {
- const { values, setFieldValue } = useForm();
- const FieldTemplate = useFormFieldTemplate();
- return (
- setFieldValue(other.name, !values[other.name]) }
- }
- {...templateProps}
- >
-
-
- );
-}
-
-export function FormSelectFieldRaw({ children, name, ...other }) {
- const { values, setFieldValue } = useForm();
- const handleChange = event => {
- setFieldValue(name, event.target.value);
- };
- return (
-
- {children}
-
- );
-}
-
-export function FormSelectField({ label, name, children = null, templateProps = undefined, ...other }) {
- const FieldTemplate = useFormFieldTemplate();
- return (
-
-
- {children}
-
-
- );
-}
-
-export function FormSubmit({ onClick, value, ...other }) {
- const { values, setSubmitAction } = useForm();
- React.useEffect(() => {
- setSubmitAction({ action: onClick });
- }, [onClick]);
- return onClick(values)} {...other} />;
-}
-
-export function FormButton({ onClick, value, ...other }) {
- const { values } = useForm();
- return onClick(values)} {...other} />;
-}
-
-export function FormRadioGroupItem({ name, text, value }) {
- const { setFieldValue, values } = useForm();
- return (
-
- setFieldValue(name, value)}
- />
- {text}
-
- );
-}
-
-export function FormReactSelect({ options, name, isMulti = false, Component = Select, ...other }) {
- const { setFieldValue, values } = useForm();
- const theme = useTheme();
-
- return (
- ({
- ...t,
- colors: {
- ...t.colors,
- neutral0: theme.input_background,
- neutral10: theme.input_background2,
- neutral20: theme.input_background3,
- neutral30: theme.input_background4,
- neutral40: theme.input_font3,
- neutral50: theme.input_font3,
- neutral60: theme.input_font2,
- neutral70: theme.input_font2,
- neutral80: theme.input_font2,
- neutral90: theme.input_font1,
- primary: theme.input_background_blue[5],
- primary75: theme.input_background_blue[3],
- primary50: theme.input_background_blue[2],
- primary25: theme.input_background_blue[0],
- danger: theme.input_background_red[5],
- dangerLight: theme.input_background_red[1],
- },
- })}
- options={options}
- value={
- isMulti
- ? options.filter(x => values[name] && values[name].includes(x.value))
- : options.find(x => x.value == values[name])
- }
- onChange={item => setFieldValue(name, isMulti ? getAsArray(item).map(x => x.value) : item ? item.value : null)}
- menuPortalTarget={document.body}
- isMulti={isMulti}
- closeMenuOnSelect={!isMulti}
- {...other}
- />
- );
-}
-
-export function FormConnectionSelect({ name }) {
- const connections = useConnectionList();
- const connectionOptions = React.useMemo(
- () =>
- (connections || []).map(conn => ({
- value: conn._id,
- label: conn.displayName || conn.server,
- })),
- [connections]
- );
-
- if (connectionOptions.length == 0) return Not available
;
- return ;
-}
-
-export function FormDatabaseSelect({ conidName, name }) {
- const { values } = useForm();
- const databases = useDatabaseList({ conid: values[conidName] });
- const databaseOptions = React.useMemo(
- () =>
- (databases || []).map(db => ({
- value: db.name,
- label: db.name,
- })),
- [databases]
- );
-
- if (databaseOptions.length == 0) return Not available
;
- return ;
-}
-
-export function FormSchemaSelect({ conidName, databaseName, name }) {
- const { values } = useForm();
- const dbinfo = useDatabaseInfo({ conid: values[conidName], database: values[databaseName] });
- const schemaOptions = React.useMemo(
- () =>
- ((dbinfo && dbinfo.schemas) || []).map(schema => ({
- value: schema.schemaName,
- label: schema.schemaName,
- })),
- [dbinfo]
- );
-
- if (schemaOptions.length == 0) return Not available
;
- return ;
-}
-
-export function FormTablesSelect({ conidName, databaseName, schemaName, name }) {
- const { values } = useForm();
- const dbinfo = useDatabaseInfo({ conid: values[conidName], database: values[databaseName] });
- const tablesOptions = React.useMemo(
- () =>
- [...((dbinfo && dbinfo.tables) || []), ...((dbinfo && dbinfo.views) || [])]
- .filter(x => !values[schemaName] || x.schemaName == values[schemaName])
- .map(x => ({
- value: x.pureName,
- label: x.pureName,
- })),
- [dbinfo, values[schemaName]]
- );
-
- if (tablesOptions.length == 0) return Not available
;
- return ;
-}
-
-export function FormArchiveFilesSelect({ folderName, name }) {
- // const { values } = useFormikContext();
- const files = useArchiveFiles({ folder: folderName });
- const filesOptions = React.useMemo(
- () =>
- (files || []).map(x => ({
- value: x.name,
- label: x.name,
- })),
- [files]
- );
-
- if (filesOptions.length == 0) return Not available
;
- return ;
-}
-
-export function FormArchiveFolderSelect({ name, additionalFolders = [], ...other }) {
- const { setFieldValue } = useForm();
- const folders = useArchiveFolders();
- const folderOptions = React.useMemo(
- () => [
- ...(folders || []).map(folder => ({
- value: folder.name,
- label: folder.name,
- })),
- ...additionalFolders
- .filter(x => !(folders || []).find(y => y.name == x))
- .map(folder => ({
- value: folder,
- label: folder,
- })),
- ],
- [folders]
- );
-
- const handleCreateOption = folder => {
- axios.post('archive/create-folder', { folder });
- setFieldValue(name, folder);
- };
-
- return (
-
- );
-}
-
-export function FormElectronFileSelectorRaw({ name, ...other }) {
- const { values, setFieldValue } = useForm();
- const handleBrowse = () => {
- const electron = getElectron();
- if (!electron) return;
- const filePaths = electron.remote.dialog.showOpenDialogSync(electron.remote.getCurrentWindow(), {
- defaultPath: values[name],
- properties: ['showHiddenFiles'],
- });
- const filePath = filePaths && filePaths[0];
- if (filePath) setFieldValue(name, filePath);
- };
- return (
-
-
- Browse
-
- );
-}
-
-export function FormElectronFileSelector({ label, name, templateProps = undefined, ...other }) {
- const FieldTemplate = useFormFieldTemplate();
- return (
-
-
-
- );
-}
diff --git a/packages/web/src/utility/fullDisplayName.js b/packages/web/src/utility/fullDisplayName.js
deleted file mode 100644
index 49574a291..000000000
--- a/packages/web/src/utility/fullDisplayName.js
+++ /dev/null
@@ -1,4 +0,0 @@
-export default function fullDisplayName({ schemaName, pureName }) {
- if (schemaName) return `${schemaName}.${pureName}`;
- return pureName;
-}
diff --git a/packages/web/src/utility/getAsArray.js b/packages/web/src/utility/getAsArray.js
deleted file mode 100644
index 623baebc0..000000000
--- a/packages/web/src/utility/getAsArray.js
+++ /dev/null
@@ -1,7 +0,0 @@
-import _ from 'lodash';
-
-export default function getAsArray(obj) {
- if (_.isArray(obj)) return obj;
- if (obj != null) return [obj];
- return [];
-}
diff --git a/packages/web/src/utility/getElectron.js b/packages/web/src/utility/getElectron.js
deleted file mode 100644
index 0599f25ec..000000000
--- a/packages/web/src/utility/getElectron.js
+++ /dev/null
@@ -1,7 +0,0 @@
-export default function getElectron() {
- if (window.require) {
- const electron = window.require('electron');
- return electron;
- }
- return null;
-}
diff --git a/packages/web/src/utility/globalState.js b/packages/web/src/utility/globalState.js
deleted file mode 100644
index 004743b37..000000000
--- a/packages/web/src/utility/globalState.js
+++ /dev/null
@@ -1,154 +0,0 @@
-import _ from 'lodash';
-import React from 'react';
-import useStorage from './useStorage';
-import { useConnectionInfo, useConfig, getConnectionInfo } from './metadataLoaders';
-import usePrevious from './usePrevious';
-import useNewQuery from '../query/useNewQuery';
-import useShowModal from '../modals/showModal';
-import useExtensions from './useExtensions';
-
-function createGlobalState(defaultValue) {
- const Context = React.createContext(null);
-
- function Provider({ children }) {
- const [currentvalue, setCurrentValue] = React.useState(defaultValue);
- return {children} ;
- }
-
- function useValue() {
- return React.useContext(Context)[0];
- }
-
- function useSetValue() {
- return React.useContext(Context)[1];
- }
-
- return [Provider, useValue, useSetValue];
-}
-
-function createStorageState(storageKey, defaultValue) {
- const Context = React.createContext(null);
-
- function Provider({ children }) {
- const [currentvalue, setCurrentValue] = useStorage(storageKey, localStorage, defaultValue);
- return {children} ;
- }
-
- function useValue() {
- return React.useContext(Context)[0];
- }
-
- function useSetValue() {
- return React.useContext(Context)[1];
- }
-
- return [Provider, useValue, useSetValue];
-}
-
-const [CurrentWidgetProvider, useCurrentWidget, useSetCurrentWidget] = createGlobalState('database');
-export { CurrentWidgetProvider, useCurrentWidget, useSetCurrentWidget };
-
-const [CurrentDatabaseProvider, useCurrentDatabaseCore, useSetCurrentDatabaseCore] = createGlobalState(null);
-
-function useSetCurrentDatabase() {
- const setDb = useSetCurrentDatabaseCore();
- const db = useCurrentDatabaseCore();
- return value => {
- if (_.get(db, 'name') !== _.get(value, 'name') || _.get(db, 'connection._id') != _.get(value, 'connection._id')) {
- setDb(value);
- }
- };
-}
-
-function useCurrentDatabase() {
- const config = useConfig();
- const db = useCurrentDatabaseCore();
-
- const [connection, setConnection] = React.useState(null);
- const loadSingleConnection = async () => {
- if (config && config.singleDatabase) {
- const conn = await getConnectionInfo({ conid: config.singleDatabase.conid });
- setConnection(conn);
- }
- };
- React.useEffect(() => {
- loadSingleConnection();
- }, [config]);
-
- if (config && config.singleDatabase) {
- if (connection) {
- return {
- connection,
- name: config.singleDatabase.database,
- };
- }
- return null;
- }
- return db;
-}
-
-export { CurrentDatabaseProvider, useCurrentDatabase, useSetCurrentDatabase };
-
-const [OpenedTabsProvider, useOpenedTabs, useSetOpenedTabs] = createStorageState('openedTabs', []);
-export { OpenedTabsProvider, useOpenedTabs, useSetOpenedTabs };
-
-export function useUpdateDatabaseForTab(tabVisible, conid, database) {
- const connection = useConnectionInfo({ conid });
- const setDb = useSetCurrentDatabase();
- const currentDb = useCurrentDatabase();
- const previousTabVisible = usePrevious(!!(tabVisible && connection));
-
- if (!conid || !database) return;
-
- if (!previousTabVisible && tabVisible && connection) {
- if (currentDb && currentDb.connection && currentDb.connection._id == conid && currentDb.name == database) {
- return;
- }
- setDb({
- name: database,
- connection,
- });
- }
-}
-
-// export function useAppObjectParams() {
-// const setOpenedTabs = useSetOpenedTabs();
-// const currentDatabase = useCurrentDatabase();
-// const newQuery = useNewQuery();
-// const openedTabs = useOpenedTabs();
-// const openedConnections = useOpenedConnections();
-// const setOpenedConnections = useSetOpenedConnections();
-// const currentArchive = useCurrentArchive();
-// const showModal = useShowModal();
-// const config = useConfig();
-// const extensions = useExtensions();
-
-// return {
-// setOpenedTabs,
-// currentDatabase,
-// currentArchive,
-// newQuery,
-// openedTabs,
-// openedConnections,
-// setOpenedConnections,
-// config,
-// showModal,
-// extensions,
-// };
-// }
-
-const [OpenedConnectionsProvider, useOpenedConnections, useSetOpenedConnections] = createGlobalState([]);
-
-export { OpenedConnectionsProvider, useOpenedConnections, useSetOpenedConnections };
-
-const [LeftPanelWidthProvider, useLeftPanelWidth, useSetLeftPanelWidth] = createGlobalState(300);
-
-export { LeftPanelWidthProvider, useLeftPanelWidth, useSetLeftPanelWidth };
-
-const [CurrentArchiveProvider, useCurrentArchive, useSetCurrentArchive] = createGlobalState('default');
-
-export { CurrentArchiveProvider, useCurrentArchive, useSetCurrentArchive };
-
-const [CurrentThemeProvider, useCurrentTheme, useSetCurrentTheme] = createStorageState('selectedTheme', 'light');
-
-export { CurrentThemeProvider, useCurrentTheme, useSetCurrentTheme };
diff --git a/packages/web/src/utility/inputs.js b/packages/web/src/utility/inputs.js
deleted file mode 100644
index 63c0498c8..000000000
--- a/packages/web/src/utility/inputs.js
+++ /dev/null
@@ -1,22 +0,0 @@
-import React from 'react';
-
-export function TextField({ editorRef = undefined, ...other }) {
- return ;
-}
-
-export function SelectField({ children = null, options = [], ...other }) {
- return (
-
- {children}
- {options.map(x => (
-
- {x.label}
-
- ))}
-
- );
-}
-
-export function CheckboxField({ editorRef = undefined, ...other }) {
- return ;
-}
diff --git a/packages/web/src/utility/keycodes.js b/packages/web/src/utility/keycodes.js
deleted file mode 100644
index 4c02d1af1..000000000
--- a/packages/web/src/utility/keycodes.js
+++ /dev/null
@@ -1,99 +0,0 @@
-export default {
- backspace: 8,
- tab: 9,
- enter: 13,
- shift: 16,
- ctrl: 17,
- alt: 18,
- pauseBreak: 19,
- capsLock: 20,
- escape: 27,
- pageUp: 33,
- pageDown: 34,
- end: 35,
- home: 36,
- leftArrow: 37,
- upArrow: 38,
- rightArrow: 39,
- downArrow: 40,
- insert: 45,
- delete: 46,
- n0: 48,
- n1: 49,
- n2: 50,
- n3: 51,
- n4: 52,
- n5: 53,
- n6: 54,
- n7: 55,
- n8: 56,
- n9: 57,
- a: 65,
- b: 66,
- c: 67,
- d: 68,
- e: 69,
- f: 70,
- g: 71,
- h: 72,
- i: 73,
- j: 74,
- k: 75,
- l: 76,
- m: 77,
- n: 78,
- o: 79,
- p: 80,
- q: 81,
- r: 82,
- s: 83,
- t: 84,
- u: 85,
- v: 86,
- w: 87,
- x: 88,
- y: 89,
- z: 90,
- leftWindowKey: 91,
- rightWindowKey: 92,
- selectKey: 93,
- numPad0: 96,
- numPad1: 97,
- numPad2: 98,
- numPad3: 99,
- numPad4: 100,
- numPad5: 101,
- numPad6: 102,
- numPad7: 103,
- numPad8: 104,
- numPad9: 105,
- multiply: 106,
- add: 107,
- subtract: 109,
- decimalPoint: 110,
- divide: 111,
- f1: 112,
- f2: 113,
- f3: 114,
- f4: 115,
- f5: 116,
- f6: 117,
- f7: 118,
- f8: 119,
- f9: 120,
- f10: 121,
- f12: 123,
- numLock: 144,
- scrollLock: 145,
- semiColon: 186,
- equalSign: 187,
- comma: 188,
- dash: 189,
- period: 190,
- forwardSlash: 191,
- graveAccent: 192,
- openBracket: 219,
- backSlash: 220,
- closeBracket: 221,
- singleQuote: 222,
-};
diff --git a/packages/web/src/utility/layout.js b/packages/web/src/utility/layout.js
deleted file mode 100644
index 8858f1942..000000000
--- a/packages/web/src/utility/layout.js
+++ /dev/null
@@ -1,7 +0,0 @@
-import styled from 'styled-components';
-
-export const Grid = styled.div``;
-
-export const Row = styled.div``;
-
-export const Col = styled.div``;
diff --git a/packages/web/src/utility/localStorageGarbageCollector.js b/packages/web/src/utility/localStorageGarbageCollector.js
deleted file mode 100644
index d5d581703..000000000
--- a/packages/web/src/utility/localStorageGarbageCollector.js
+++ /dev/null
@@ -1,35 +0,0 @@
-import moment from 'moment';
-import localforage from 'localforage';
-
-export default async function localStorageGarbageCollector() {
- const openedTabsJson = localStorage.getItem('openedTabs');
- let openedTabs = openedTabsJson ? JSON.parse(openedTabsJson) : [];
-
- const closeLimit = moment().add(-7, 'day').valueOf();
-
- openedTabs = openedTabs.filter(x => !x.closedTime || x.closedTime > closeLimit);
- localStorage.setItem('openedTabs', JSON.stringify(openedTabs));
-
- const toRemove = [];
- for (const key in localStorage) {
- if (!key.startsWith('tabdata_')) continue;
- if (openedTabs.find(x => key.endsWith('_' + x.tabid))) continue;
- toRemove.push(key);
- }
-
- for (const key of toRemove) {
- localStorage.removeItem(key);
- }
-
- const keysForage = await localforage.keys();
- const toRemoveForage = [];
- for (const key in keysForage) {
- if (!key.startsWith('tabdata_')) continue;
- if (openedTabs.find(x => key.endsWith('_' + x.tabid))) continue;
- toRemoveForage.push(key);
- }
-
- for (const key of toRemoveForage) {
- await localforage.removeItem(key);
- }
-}
diff --git a/packages/web/src/utility/metadataLoaders.js b/packages/web/src/utility/metadataLoaders.js
deleted file mode 100644
index 946adfa0d..000000000
--- a/packages/web/src/utility/metadataLoaders.js
+++ /dev/null
@@ -1,309 +0,0 @@
-import useFetch from './useFetch';
-import axios from './axios';
-import _ from 'lodash';
-import { cacheGet, cacheSet, getCachedPromise } from './cache';
-import stableStringify from 'json-stable-stringify';
-
-const databaseInfoLoader = ({ conid, database }) => ({
- url: 'database-connections/structure',
- params: { conid, database },
- reloadTrigger: `database-structure-changed-${conid}-${database}`,
- transform: db => {
- const allForeignKeys = _.flatten(db.tables.map(x => x.foreignKeys));
- return {
- ...db,
- tables: db.tables.map(table => ({
- ...table,
- dependencies: allForeignKeys.filter(
- x => x.refSchemaName == table.schemaName && x.refTableName == table.pureName
- ),
- })),
- };
- },
-});
-
-// const tableInfoLoader = ({ conid, database, schemaName, pureName }) => ({
-// url: 'metadata/table-info',
-// params: { conid, database, schemaName, pureName },
-// reloadTrigger: `database-structure-changed-${conid}-${database}`,
-// });
-
-// const sqlObjectInfoLoader = ({ objectTypeField, conid, database, schemaName, pureName }) => ({
-// url: 'metadata/sql-object-info',
-// params: { objectTypeField, conid, database, schemaName, pureName },
-// reloadTrigger: `database-structure-changed-${conid}-${database}`,
-// });
-
-const connectionInfoLoader = ({ conid }) => ({
- url: 'connections/get',
- params: { conid },
- reloadTrigger: 'connection-list-changed',
-});
-
-const configLoader = () => ({
- url: 'config/get',
- params: {},
- reloadTrigger: 'config-changed',
-});
-
-const platformInfoLoader = () => ({
- url: 'config/platform-info',
- params: {},
- reloadTrigger: 'platform-info-changed',
-});
-
-const favoritesLoader = () => ({
- url: 'files/favorites',
- params: {},
- reloadTrigger: 'files-changed-favorites',
-});
-
-// const sqlObjectListLoader = ({ conid, database }) => ({
-// url: 'metadata/list-objects',
-// params: { conid, database },
-// reloadTrigger: `database-structure-changed-${conid}-${database}`,
-// });
-
-const databaseStatusLoader = ({ conid, database }) => ({
- url: 'database-connections/status',
- params: { conid, database },
- reloadTrigger: `database-status-changed-${conid}-${database}`,
-});
-
-const databaseListLoader = ({ conid }) => ({
- url: 'server-connections/list-databases',
- params: { conid },
- reloadTrigger: `database-list-changed-${conid}`,
-});
-
-const archiveFoldersLoader = () => ({
- url: 'archive/folders',
- params: {},
- reloadTrigger: `archive-folders-changed`,
-});
-
-const archiveFilesLoader = ({ folder }) => ({
- url: 'archive/files',
- params: { folder },
- reloadTrigger: `archive-files-changed-${folder}`,
-});
-
-const serverStatusLoader = () => ({
- url: 'server-connections/server-status',
- params: {},
- reloadTrigger: `server-status-changed`,
-});
-
-const connectionListLoader = () => ({
- url: 'connections/list',
- params: {},
- reloadTrigger: `connection-list-changed`,
-});
-
-const installedPluginsLoader = () => ({
- url: 'plugins/installed',
- params: {},
- reloadTrigger: `installed-plugins-changed`,
-});
-
-const filesLoader = ({ folder }) => ({
- url: 'files/list',
- params: { folder },
- reloadTrigger: `files-changed-${folder}`,
-});
-const allFilesLoader = () => ({
- url: 'files/list-all',
- params: {},
- reloadTrigger: `all-files-changed`,
-});
-
-async function getCore(loader, args) {
- const { url, params, reloadTrigger, transform } = loader(args);
- const key = stableStringify({ url, ...params });
-
- async function doLoad() {
- const resp = await axios.request({
- method: 'get',
- url,
- params,
- });
- return (transform || (x => x))(resp.data);
- }
-
- const fromCache = cacheGet(key);
- if (fromCache) return fromCache;
- const res = await getCachedPromise(key, doLoad);
-
- cacheSet(key, res, reloadTrigger);
- return res;
-}
-
-function useCore(loader, args) {
- const { url, params, reloadTrigger, transform } = loader(args);
- const cacheKey = stableStringify({ url, ...params });
-
- const res = useFetch({
- url,
- params,
- reloadTrigger,
- cacheKey,
- transform,
- });
-
- return res;
-}
-
-/** @returns {Promise} */
-export function getDatabaseInfo(args) {
- return getCore(databaseInfoLoader, args);
-}
-
-/** @returns {import('dbgate-types').DatabaseInfo} */
-export function useDatabaseInfo(args) {
- return useCore(databaseInfoLoader, args);
-}
-
-export async function getDbCore(args, objectTypeField = undefined) {
- const db = await getDatabaseInfo(args);
- if (!db) return null;
- return db[objectTypeField || args.objectTypeField].find(
- x => x.pureName == args.pureName && x.schemaName == args.schemaName
- );
-}
-
-export function useDbCore(args, objectTypeField = undefined) {
- const db = useDatabaseInfo(args);
- if (!db) return null;
- return db[objectTypeField || args.objectTypeField].find(
- x => x.pureName == args.pureName && x.schemaName == args.schemaName
- );
-}
-
-/** @returns {Promise} */
-export function getTableInfo(args) {
- return getDbCore(args, 'tables');
-}
-
-/** @returns {import('dbgate-types').TableInfo} */
-export function useTableInfo(args) {
- return useDbCore(args, 'tables');
-}
-
-/** @returns {Promise} */
-export function getViewInfo(args) {
- return getDbCore(args, 'views');
-}
-
-/** @returns {import('dbgate-types').ViewInfo} */
-export function useViewInfo(args) {
- return useDbCore(args, 'views');
-}
-
-export function getSqlObjectInfo(args) {
- return getDbCore(args);
-}
-
-export function useSqlObjectInfo(args) {
- return useDbCore(args);
-}
-
-/** @returns {Promise} */
-export function getConnectionInfo(args) {
- return getCore(connectionInfoLoader, args);
-}
-
-/** @returns {import('dbgate-types').StoredConnection} */
-export function useConnectionInfo(args) {
- return useCore(connectionInfoLoader, args);
-}
-
-// export function getSqlObjectList(args) {
-// return getCore(sqlObjectListLoader, args);
-// }
-// export function useSqlObjectList(args) {
-// return useCore(sqlObjectListLoader, args);
-// }
-
-export function getDatabaseStatus(args) {
- return getCore(databaseStatusLoader, args);
-}
-export function useDatabaseStatus(args) {
- return useCore(databaseStatusLoader, args);
-}
-
-export function getDatabaseList(args) {
- return getCore(databaseListLoader, args);
-}
-export function useDatabaseList(args) {
- return useCore(databaseListLoader, args);
-}
-
-export function getServerStatus() {
- return getCore(serverStatusLoader, {});
-}
-export function useServerStatus() {
- return useCore(serverStatusLoader, {});
-}
-
-export function getConnectionList() {
- return getCore(connectionListLoader, {});
-}
-export function useConnectionList() {
- return useCore(connectionListLoader, {});
-}
-
-export function getConfig() {
- return getCore(configLoader, {}) || {};
-}
-export function useConfig() {
- return useCore(configLoader, {}) || {};
-}
-
-export function getPlatformInfo() {
- return getCore(platformInfoLoader, {}) || {};
-}
-export function usePlatformInfo() {
- return useCore(platformInfoLoader, {}) || {};
-}
-
-export function getArchiveFiles(args) {
- return getCore(archiveFilesLoader, args);
-}
-export function useArchiveFiles(args) {
- return useCore(archiveFilesLoader, args);
-}
-
-export function getArchiveFolders(args) {
- return getCore(archiveFoldersLoader, args);
-}
-export function useArchiveFolders(args) {
- return useCore(archiveFoldersLoader, args);
-}
-
-export function getInstalledPlugins(args) {
- return getCore(installedPluginsLoader, args) || [];
-}
-export function useInstalledPlugins(args) {
- return useCore(installedPluginsLoader, args) || [];
-}
-
-export function getFiles(args) {
- return getCore(filesLoader, args);
-}
-export function useFiles(args) {
- return useCore(filesLoader, args);
-}
-
-export function getAllFiles(args) {
- return getCore(allFilesLoader, args);
-}
-export function useAllFiles(args) {
- return useCore(allFilesLoader, args);
-}
-
-export function getFavorites(args) {
- return getCore(favoritesLoader, args);
-}
-export function useFavorites(args) {
- return useCore(favoritesLoader, args);
-}
diff --git a/packages/web/src/utility/resolveApi.js b/packages/web/src/utility/resolveApi.js
deleted file mode 100644
index 672c9469a..000000000
--- a/packages/web/src/utility/resolveApi.js
+++ /dev/null
@@ -1,21 +0,0 @@
-export default function resolveApi() {
- if (window.require) {
- const electron = window.require('electron');
-
- if (electron) {
- const port = electron.remote.getGlobal('port');
- if (port) {
- return `http://localhost:${port}`;
- }
- }
- }
-
- // eslint-disable-next-line
- const apiUrl = process.env.REACT_APP_API_URL;
- if (apiUrl) {
- if (apiUrl == 'ORIGIN') return window.location.origin;
- return apiUrl;
- }
-
- return 'http://localhost:3000';
-}
diff --git a/packages/web/src/utility/useDimensions.js b/packages/web/src/utility/useDimensions.js
deleted file mode 100644
index 62f83e2e9..000000000
--- a/packages/web/src/utility/useDimensions.js
+++ /dev/null
@@ -1,107 +0,0 @@
-// import { useState, useCallback, useLayoutEffect } from 'react';
-
-// function getDimensionObject(node) {
-// const rect = node.getBoundingClientRect();
-
-// return {
-// width: rect.width,
-// height: rect.height,
-// top: 'x' in rect ? rect.x : rect.top,
-// left: 'y' in rect ? rect.y : rect.left,
-// x: 'x' in rect ? rect.x : rect.left,
-// y: 'y' in rect ? rect.y : rect.top,
-// right: rect.right,
-// bottom: rect.bottom,
-// };
-// }
-
-// function useDimensions({ liveMeasure = true } = {}) {
-// const [dimensions, setDimensions] = useState({});
-// const [node, setNode] = useState(null);
-
-// const ref = useCallback(node => {
-// setNode(node);
-// }, []);
-
-// useLayoutEffect(() => {
-// if (node) {
-// const measure = () => window.requestAnimationFrame(() => setDimensions(getDimensionObject(node)));
-// measure();
-
-// if (liveMeasure) {
-// window.addEventListener('resize', measure);
-// window.addEventListener('scroll', measure);
-
-// return () => {
-// window.removeEventListener('resize', measure);
-// window.removeEventListener('scroll', measure);
-// };
-// }
-// }
-// }, [node]);
-
-// return [ref, dimensions, node];
-// }
-
-// export default useDimensions;
-
-import { useLayoutEffect, useState, useCallback } from 'react';
-import ResizeObserver from 'resize-observer-polyfill';
-
-// Export hook
-export default function useDimensions(dependencies = []) {
- const [node, setNode] = useState(null);
- const ref = useCallback(newNode => {
- setNode(newNode);
- }, []);
-
- // Keep track of measurements
- const [dimensions, setDimensions] = useState({
- x: 0,
- y: 0,
- left: 0,
- top: 0,
- right: 0,
- bottom: 0,
- width: 0,
- height: 0,
- });
-
- // Define measure function
- const measure = useCallback(innerNode => {
- const rect = innerNode.getBoundingClientRect();
- setDimensions({
- x: rect.left,
- y: rect.top,
- left: rect.left,
- top: rect.top,
- right: rect.right,
- bottom: rect.bottom,
- width: rect.width,
- height: rect.height,
- });
- }, []);
-
- useLayoutEffect(() => {
- if (!node) {
- return;
- }
-
- // Set initial measurements
- measure(node);
-
- // Observe resizing of element
- const resizeObserver = new ResizeObserver(() => {
- measure(node);
- });
-
- resizeObserver.observe(node);
-
- // Cleanup
- return () => {
- resizeObserver.disconnect();
- };
- }, [node, measure, ...dependencies]);
-
- return [ref, dimensions, node];
-}
diff --git a/packages/web/src/utility/useDocumentClick.js b/packages/web/src/utility/useDocumentClick.js
deleted file mode 100644
index 55dc84f4e..000000000
--- a/packages/web/src/utility/useDocumentClick.js
+++ /dev/null
@@ -1,20 +0,0 @@
-import React from 'react';
-
-export default function useDocumentClick(callback) {
- const mouseUpListener = React.useCallback(e => {
- callback();
- document.removeEventListener('mouseup', mouseUpListener, true);
- }, []);
- const mouseDownListener = React.useCallback(e => {
- document.addEventListener('mouseup', mouseUpListener, true);
- document.removeEventListener('mousedown', mouseDownListener, true);
- }, []);
-
- React.useEffect(() => {
- document.addEventListener('mousedown', mouseDownListener, true);
- return () => {
- document.removeEventListener('mouseup', mouseUpListener, true);
- document.removeEventListener('mousedown', mouseDownListener, true);
- };
- }, []);
-}
diff --git a/packages/web/src/utility/useEditorData.js b/packages/web/src/utility/useEditorData.js
deleted file mode 100644
index c6b80b9ef..000000000
--- a/packages/web/src/utility/useEditorData.js
+++ /dev/null
@@ -1,126 +0,0 @@
-import React from 'react';
-import _ from 'lodash';
-import localforage from 'localforage';
-import { changeTab } from './common';
-import { useSetOpenedTabs } from './globalState';
-
-function getParsedLocalStorage(key) {
- const value = localStorage.getItem(key);
- if (value != null) {
- try {
- const res = JSON.parse(value);
- return res;
- } catch (e) {
- // console.log('FAILED LOAD FROM STORAGE', e);
- // console.log('VALUE', value);
- localStorage.removeItem(key);
- }
- }
- return null;
-}
-
-export default function useEditorData({ tabid, reloadToken = 0, loadFromArgs = null }) {
- const localStorageKey = `tabdata_editor_${tabid}`;
- const setOpenedTabs = useSetOpenedTabs();
- const changeCounterRef = React.useRef(0);
- const savedCounterRef = React.useRef(0);
- const [errorMessage, setErrorMessage] = React.useState(null);
-
- const [value, setValue] = React.useState(null);
- const [isLoading, setIsLoading] = React.useState(true);
- const initialDataRef = React.useRef(null);
-
- const valueRef = React.useRef(null);
-
- const initialLoad = async () => {
- if (loadFromArgs) {
- try {
- const init = await loadFromArgs();
- changeTab(tabid, setOpenedTabs, tab => ({
- ...tab,
- props: _.omit(tab.props, ['initialArgs']),
- }));
- setValue(init);
- valueRef.current = init;
- initialDataRef.current = init;
- // mark as not saved
- changeCounterRef.current += 1;
- } catch (err) {
- const message = (err && err.response && err.response.data && err.response.data.error) || 'Loading failed';
- setErrorMessage(message);
- console.error(err.response);
- }
- } else {
- const initFallback = getParsedLocalStorage(localStorageKey);
- if (initFallback != null) {
- setValue(initFallback);
- valueRef.current = initFallback;
- // move to local forage
- await localforage.setItem(localStorageKey, initFallback);
- localStorage.removeItem(localStorageKey);
- initialDataRef.current = initFallback;
- } else {
- const init = await localforage.getItem(localStorageKey);
- if (init) {
- setValue(init);
- valueRef.current = init;
- initialDataRef.current = init;
- }
- }
- }
- setIsLoading(false);
- };
-
- React.useEffect(() => {
- initialLoad();
- }, [reloadToken]);
-
- const saveToStorage = React.useCallback(async () => {
- if (valueRef.current == null) return;
- try {
- await localforage.setItem(localStorageKey, valueRef.current);
- localStorage.removeItem(localStorageKey);
- savedCounterRef.current = changeCounterRef.current;
- } catch (err) {
- console.error(err);
- }
- }, [localStorageKey, valueRef]);
-
- const saveToStorageSync = React.useCallback(() => {
- if (valueRef.current == null) return;
- if (savedCounterRef.current == changeCounterRef.current) return; // all saved
- // on window unload must be synchronous actions, save to local storage instead
- localStorage.setItem(localStorageKey, JSON.stringify(valueRef.current));
- }, [localStorageKey, valueRef]);
-
- const saveToStorageDebounced = React.useMemo(() => _.debounce(saveToStorage, 5000), [saveToStorage]);
-
- const handleChange = newValue => {
- if (_.isFunction(newValue)) {
- valueRef.current = newValue(valueRef.current);
- } else {
- if (newValue != null) valueRef.current = newValue;
- }
- setValue(valueRef.current);
- changeCounterRef.current += 1;
- saveToStorageDebounced();
- };
-
- React.useEffect(() => {
- window.addEventListener('beforeunload', saveToStorageSync);
- return () => {
- saveToStorage();
- window.removeEventListener('beforeunload', saveToStorageSync);
- };
- }, []);
-
- return {
- editorData: value,
- setEditorData: handleChange,
- isLoading,
- initialData: initialDataRef.current,
- errorMessage,
- saveToStorage,
- saveToStorageSync,
- };
-}
diff --git a/packages/web/src/utility/useExtensions.js b/packages/web/src/utility/useExtensions.js
deleted file mode 100644
index b428f8241..000000000
--- a/packages/web/src/utility/useExtensions.js
+++ /dev/null
@@ -1,35 +0,0 @@
-import React from 'react';
-import { usePlugins } from '../plugins/PluginsProvider';
-import { buildFileFormats } from './fileformats';
-
-const ExtensionsContext = React.createContext(buildExtensions([]));
-
-export function ExtensionsProvider({ children }) {
- const plugins = usePlugins();
- const extensions = React.useMemo(() => buildExtensions(plugins), [plugins]);
- return {children} ;
-}
-
-function buildDrivers(plugins) {
- const res = [];
- for (const { content } of plugins) {
- if (content.driver) res.push(content.driver);
- if (content.drivers) res.push(...content.drivers);
- }
- return res;
-}
-
-export function buildExtensions(plugins) {
- /** @type {import('dbgate-types').ExtensionsDirectory} */
- const extensions = {
- plugins,
- fileFormats: buildFileFormats(plugins),
- drivers: buildDrivers(plugins),
- };
- return extensions;
-}
-
-/** @returns {import('dbgate-types').ExtensionsDirectory} */
-export default function useExtensions() {
- return React.useContext(ExtensionsContext);
-}
diff --git a/packages/web/src/utility/useFetch.js b/packages/web/src/utility/useFetch.js
deleted file mode 100644
index ee93439f9..000000000
--- a/packages/web/src/utility/useFetch.js
+++ /dev/null
@@ -1,88 +0,0 @@
-import React from 'react';
-import _ from 'lodash';
-import axios from './axios';
-import useSocket from './SocketProvider';
-import stableStringify from 'json-stable-stringify';
-import { getCachedPromise, cacheGet, cacheSet, cacheClean } from './cache';
-import getAsArray from './getAsArray';
-
-export default function useFetch({
- url,
- data = undefined,
- params = undefined,
- defaultValue = undefined,
- reloadTrigger = undefined,
- cacheKey = undefined,
- transform = x => x,
- ...config
-}) {
- const [value, setValue] = React.useState([defaultValue, []]);
- const [loadCounter, setLoadCounter] = React.useState(0);
- const socket = useSocket();
-
- const handleReload = React.useCallback(() => {
- setLoadCounter(counter => counter + 1);
- }, []);
-
- const indicators = [url, stableStringify(data), stableStringify(params), loadCounter];
-
- async function loadValue(loadedIndicators) {
- async function doLoad() {
- const resp = await axios.request({
- method: 'get',
- params,
- url,
- data,
- ...config,
- });
- return transform(resp.data);
- }
-
- if (cacheKey) {
- const fromCache = cacheGet(cacheKey);
- if (fromCache) {
- setValue([fromCache, loadedIndicators]);
- } else {
- try {
- const res = await getCachedPromise(cacheKey, doLoad);
- cacheSet(cacheKey, res, reloadTrigger);
- setValue([res, loadedIndicators]);
- } catch (err) {
- console.error('Error when using cached promise', err);
- cacheClean(cacheKey);
- const res = await doLoad();
- cacheSet(cacheKey, res, reloadTrigger);
- setValue([res, loadedIndicators]);
- }
- }
- } else {
- const res = await doLoad();
- setValue([res, loadedIndicators]);
- }
- }
-
- React.useEffect(() => {
- loadValue(indicators);
- }, [...indicators]);
-
- React.useEffect(() => {
- if (reloadTrigger && !socket) {
- console.error('Socket not available, reloadTrigger not planned');
- }
- if (reloadTrigger && socket) {
- for (const item of getAsArray(reloadTrigger)) {
- socket.on(item, handleReload);
- }
- return () => {
- for (const item of getAsArray(reloadTrigger)) {
- socket.off(item, handleReload);
- }
- };
- }
- }, [socket, reloadTrigger]);
-
- const [returnValue, loadedIndicators] = value;
- if (_.isEqual(indicators, loadedIndicators)) return returnValue;
-
- return defaultValue;
-}
diff --git a/packages/web/src/utility/useGridConfig.js b/packages/web/src/utility/useGridConfig.js
deleted file mode 100644
index ea2c766c1..000000000
--- a/packages/web/src/utility/useGridConfig.js
+++ /dev/null
@@ -1,23 +0,0 @@
-import { createGridConfig } from 'dbgate-datalib';
-import React from 'react';
-
-const loadGridConfigFunc = tabid => () => {
- const existing = localStorage.getItem(`tabdata_grid_${tabid}`);
- if (existing) {
- return {
- ...createGridConfig(),
- ...JSON.parse(existing),
- };
- }
- return createGridConfig();
-};
-
-export default function useGridConfig(tabid) {
- const [config, setConfig] = React.useState(loadGridConfigFunc(tabid));
-
- React.useEffect(() => {
- localStorage.setItem(`tabdata_grid_${tabid}`, JSON.stringify(config));
- }, [config]);
-
- return [config, setConfig];
-}
diff --git a/packages/web/src/utility/useHasPermission.js b/packages/web/src/utility/useHasPermission.js
deleted file mode 100644
index 75dd8682f..000000000
--- a/packages/web/src/utility/useHasPermission.js
+++ /dev/null
@@ -1,10 +0,0 @@
-import React from 'react';
-import { useConfig } from './metadataLoaders';
-import { compilePermissions, testPermission } from 'dbgate-tools';
-
-export default function useHasPermission() {
- const config = useConfig();
- const compiled = React.useMemo(() => compilePermissions(config.permissions), [config]);
- const hasPermission = tested => testPermission(tested, compiled);
- return hasPermission;
-}
diff --git a/packages/web/src/utility/useOpenElectronFile.js b/packages/web/src/utility/useOpenElectronFile.js
deleted file mode 100644
index 5240cca00..000000000
--- a/packages/web/src/utility/useOpenElectronFile.js
+++ /dev/null
@@ -1,88 +0,0 @@
-import _ from 'lodash';
-import React from 'react';
-import ImportExportModal from '../modals/ImportExportModal';
-import useShowModal from '../modals/showModal';
-import useNewQuery from '../query/useNewQuery';
-import getElectron from './getElectron';
-import useExtensions from './useExtensions';
-
-export function canOpenByElectron(file, extensions) {
- if (!file) return false;
- const nameLower = file.toLowerCase();
- if (nameLower.endsWith('.sql')) return true;
- for (const format of extensions.fileFormats) {
- if (nameLower.endsWith(`.${format.extension}`)) return true;
- }
- return false;
-}
-
-export function useOpenElectronFileCore() {
- const newQuery = useNewQuery();
- const extensions = useExtensions();
- const showModal = useShowModal();
-
- return filePath => {
- const nameLower = filePath.toLowerCase();
- const path = window.require('path');
- const fs = window.require('fs');
- const parsed = path.parse(filePath);
-
- if (nameLower.endsWith('.sql')) {
- const data = fs.readFileSync(filePath, { encoding: 'utf-8' });
-
- newQuery({
- title: parsed.name,
- initialData: data,
- // @ts-ignore
- savedFilePath: filePath,
- savedFormat: 'text',
- });
- }
- for (const format of extensions.fileFormats) {
- if (nameLower.endsWith(`.${format.extension}`)) {
- showModal(modalState => (
-
- ));
- }
- }
- };
-}
-
-function getFileFormatFilters(extensions) {
- return extensions.fileFormats.filter(x => x.readerFunc).map(x => ({ name: x.name, extensions: [x.extension] }));
-}
-
-function getFileFormatExtensions(extensions) {
- return extensions.fileFormats.filter(x => x.readerFunc).map(x => x.extension);
-}
-
-export default function useOpenElectronFile() {
- const electron = getElectron();
- const openElectronFileCore = useOpenElectronFileCore();
- const extensions = useExtensions();
-
- return () => {
- const filePaths = electron.remote.dialog.showOpenDialogSync(electron.remote.getCurrentWindow(), {
- filters: [
- { name: `All supported files`, extensions: ['sql', ...getFileFormatExtensions(extensions)] },
- { name: `SQL files`, extensions: ['sql'] },
- ...getFileFormatFilters(extensions),
- ],
- });
- const filePath = filePaths && filePaths[0];
- if (canOpenByElectron(filePath, extensions)) {
- openElectronFileCore(filePath);
- }
- };
-}
diff --git a/packages/web/src/utility/useOpenNewTab.js b/packages/web/src/utility/useOpenNewTab.js
deleted file mode 100644
index 2c20dc0d7..000000000
--- a/packages/web/src/utility/useOpenNewTab.js
+++ /dev/null
@@ -1,90 +0,0 @@
-import uuidv1 from 'uuid/v1';
-import React from 'react';
-import localforage from 'localforage';
-import stableStringify from 'json-stable-stringify';
-import _ from 'lodash';
-import { useOpenedTabs, useSetOpenedTabs } from './globalState';
-import tabs from '../tabs';
-import { setSelectedTabFunc } from './common';
-
-function findFreeNumber(numbers) {
- if (numbers.length == 0) return 1;
- return _.max(numbers) + 1;
- // let res = 1;
- // while (numbers.includes(res)) res += 1;
- // return res;
-}
-
-export default function useOpenNewTab() {
- const setOpenedTabs = useSetOpenedTabs();
- const openedTabs = useOpenedTabs();
-
- const openNewTab = React.useCallback(
- async (newTab, initialData = undefined, options) => {
- let existing = null;
-
- const { savedFile, savedFolder, savedFilePath } = newTab.props || {};
- if (savedFile || savedFilePath) {
- existing = openedTabs.find(
- x =>
- x.props &&
- x.tabComponent == newTab.tabComponent &&
- x.closedTime == null &&
- x.props.savedFile == savedFile &&
- x.props.savedFolder == savedFolder &&
- x.props.savedFilePath == savedFilePath
- );
- }
-
- const { forceNewTab } = options || {};
-
- const component = tabs[newTab.tabComponent];
- if (!existing && !forceNewTab && component && component.matchingProps) {
- const testString = stableStringify(_.pick(newTab.props || {}, component.matchingProps));
- existing = openedTabs.find(
- x =>
- x.props &&
- x.tabComponent == newTab.tabComponent &&
- x.closedTime == null &&
- stableStringify(_.pick(x.props || {}, component.matchingProps)) == testString
- );
- }
-
- if (existing) {
- setOpenedTabs(tabs => setSelectedTabFunc(tabs, existing.tabid));
- return;
- }
-
- // new tab will be created
- if (newTab.title.endsWith('#')) {
- const numbers = openedTabs
- .filter(x => x.closedTime == null && x.title && x.title.startsWith(newTab.title))
- .map(x => parseInt(x.title.substring(newTab.title.length)));
-
- newTab.title = `${newTab.title}${findFreeNumber(numbers)}`;
- }
-
- const tabid = uuidv1();
- if (initialData) {
- for (const key of _.keys(initialData)) {
- if (key == 'editor') {
- await localforage.setItem(`tabdata_${key}_${tabid}`, initialData[key]);
- } else {
- localStorage.setItem(`tabdata_${key}_${tabid}`, JSON.stringify(initialData[key]));
- }
- }
- }
- setOpenedTabs(files => [
- ...(files || []).map(x => ({ ...x, selected: false })),
- {
- tabid,
- selected: true,
- ...newTab,
- },
- ]);
- },
- [setOpenedTabs, openedTabs]
- );
-
- return openNewTab;
-}
diff --git a/packages/web/src/utility/usePrevious.js b/packages/web/src/utility/usePrevious.js
deleted file mode 100644
index 52ac35ca1..000000000
--- a/packages/web/src/utility/usePrevious.js
+++ /dev/null
@@ -1,17 +0,0 @@
-// copied from https://usehooks.com/usePrevious/
-
-import React from 'react';
-
-export default function usePrevious(value) {
- const ref = React.useRef();
-
- // Store current value in ref
-
- React.useEffect(() => {
- ref.current = value;
- }, [value]); // Only re-run if value changes
-
- // Return previous value (happens before update in useEffect above)
-
- return ref.current;
-}
diff --git a/packages/web/src/utility/usePropsCompare.js b/packages/web/src/utility/usePropsCompare.js
deleted file mode 100644
index 60ebd39d2..000000000
--- a/packages/web/src/utility/usePropsCompare.js
+++ /dev/null
@@ -1,12 +0,0 @@
-import _ from 'lodash';
-import usePrevious from './usePrevious';
-
-export default function usePropsCompare(props) {
- const prevProps = usePrevious(props);
- if (!prevProps) return;
- for (const key of _.union(_.keys(props), _.keys(prevProps))) {
- if (props[key] !== prevProps[key]) {
- console.log(`Different prop value found: prop=${key}, old, new`, prevProps[key], prevProps[key]);
- }
- }
-}
diff --git a/packages/web/src/utility/useStorage.js b/packages/web/src/utility/useStorage.js
deleted file mode 100644
index 175820faf..000000000
--- a/packages/web/src/utility/useStorage.js
+++ /dev/null
@@ -1,41 +0,0 @@
-import React from 'react';
-
-export default function useStorage(key, storageObject, initialValue) {
- // State to store our value
- // Pass initial state function to useState so logic is only executed once
- const [storedValue, setStoredValue] = React.useState(() => {
- try {
- // Get from local storage by key
- const item = storageObject.getItem(key);
- // Parse stored json or if none return initialValue
- return item ? JSON.parse(item) : initialValue;
- } catch (error) {
- // If error also return initialValue
- console.error(error);
- return initialValue;
- }
- });
-
- // use storedValue to ref, so that setValue with function argument works without changeing setValue itself
- const storedValueRef = React.useRef(storedValue);
- storedValueRef.current = storedValue;
-
- // Return a wrapped version of useState's setter function that ...
- // ... persists the new value to localStorage.
- const setValue = React.useCallback(value => {
- try {
- // Allow value to be a function so we have same API as useState
- const valueToStore = value instanceof Function ? value(storedValueRef.current) : value;
- // Save state
- setStoredValue(valueToStore);
- // Save to local storage
- storageObject.setItem(key, JSON.stringify(valueToStore));
- } catch (error) {
- // A more advanced implementation would handle the error case
- console.error(error);
- console.log('Error saving storage value', key, value);
- }
- }, []);
-
- return [storedValue, setValue];
-}
diff --git a/packages/web/src/utility/useTimerLabel.js b/packages/web/src/utility/useTimerLabel.js
deleted file mode 100644
index f8c976e93..000000000
--- a/packages/web/src/utility/useTimerLabel.js
+++ /dev/null
@@ -1,37 +0,0 @@
-import React from 'react';
-import _ from 'lodash';
-
-function formatSeconds(duration) {
- if (duration == null) return '';
- const hours = _.padStart(Math.floor(duration / 3600).toString(), 2, '0');
- const minutes = _.padStart((Math.floor(duration / 60) % 60).toString(), 2, '0');
- const seconds = _.padStart((duration % 60).toString(), 2, '0');
- return `${hours}:${minutes}:${seconds}`;
-}
-
-export default function useTimerLabel() {
- const [duration, setDuration] = React.useState(null);
- const [busy, setBusy] = React.useState(false);
- React.useEffect(() => {
- if (busy) {
- setDuration(0);
- const handle = setInterval(() => setDuration(x => x + 1), 1000);
- return () => window.clearInterval(handle);
- }
- }, [busy]);
-
- const start = React.useCallback(() => {
- setBusy(true);
- }, []);
-
- const stop = React.useCallback(() => {
- setBusy(false);
- }, []);
-
- return {
- start,
- stop,
- text: formatSeconds(duration),
- duration,
- };
-}
diff --git a/packages/web/src/utility/useUndoReducer.js b/packages/web/src/utility/useUndoReducer.js
deleted file mode 100644
index 11f2d9f71..000000000
--- a/packages/web/src/utility/useUndoReducer.js
+++ /dev/null
@@ -1,69 +0,0 @@
-import _ from 'lodash';
-import React from 'react';
-
-const reducer = options => (state, action) => {
- const { mergeNearActions } = options || {};
-
- const useMerge =
- action.useMerge || (mergeNearActions && state.lastActionTm && new Date().getTime() - state.lastActionTm < 100);
-
- switch (action.type) {
- case 'set':
- return {
- history: [...state.history.slice(0, useMerge ? state.current : state.current + 1), action.value],
- current: useMerge ? state.current : state.current + 1,
- value: action.value,
- canUndo: true,
- canRedo: false,
- lastActionTm: new Date().getTime(),
- };
- case 'compute': {
- const newValue = action.compute(state.history[state.current]);
- return {
- history: [...state.history.slice(0, useMerge ? state.current : state.current + 1), newValue],
- current: useMerge ? state.current : state.current + 1,
- value: newValue,
- canUndo: true,
- canRedo: false,
- lastActionTm: new Date().getTime(),
- };
- }
- case 'undo':
- if (state.current > 0)
- return {
- history: state.history,
- current: state.current - 1,
- value: state.history[state.current - 1],
- canUndo: state.current > 1,
- canRedo: true,
- lastActionTm: null,
- };
- return state;
- case 'redo':
- if (state.current < state.history.length - 1)
- return {
- history: state.history,
- current: state.current + 1,
- value: state.history[state.current + 1],
- canUndo: true,
- canRedo: state.current < state.history.length - 2,
- lastActionTm: null,
- };
- return state;
- case 'reset':
- return {
- history: [action.value],
- current: 0,
- value: action.value,
- lastActionTm: null,
- };
- }
-};
-
-export default function useUndoReducer(initialValue, options) {
- return React.useReducer(reducer(options), {
- history: [initialValue],
- current: 0,
- value: initialValue,
- });
-}
diff --git a/packages/web/src/widgets/ArchiveWidget.js b/packages/web/src/widgets/ArchiveWidget.js
deleted file mode 100644
index c0ee87725..000000000
--- a/packages/web/src/widgets/ArchiveWidget.js
+++ /dev/null
@@ -1,82 +0,0 @@
-import React from 'react';
-import _ from 'lodash';
-
-import { AppObjectList } from '../appobj/AppObjectList';
-import { useCurrentArchive, useSetCurrentArchive } from '../utility/globalState';
-import { SearchBoxWrapper, WidgetsInnerContainer } from './WidgetStyles';
-import WidgetColumnBar, { WidgetColumnBarItem } from './WidgetColumnBar';
-import { useArchiveFiles, useArchiveFolders } from '../utility/metadataLoaders';
-import ArchiveFolderAppObject from '../appobj/ArchiveFolderAppObject';
-import ArchiveFileAppObject from '../appobj/ArchiveFileAppObject';
-import SearchInput from './SearchInput';
-import InlineButton from './InlineButton';
-import axios from '../utility/axios';
-
-function ArchiveFolderList() {
- const folders = useArchiveFolders();
- const [filter, setFilter] = React.useState('');
-
- const setArchive = useSetCurrentArchive();
-
- const handleRefreshFolders = () => {
- axios.post('archive/refresh-folders', {});
- };
-
- return (
- <>
-
-
- Refresh
-
-
- setArchive(archive.name)}
- filter={filter}
- />
-
- >
- );
-}
-
-function ArchiveFilesList() {
- const folder = useCurrentArchive();
- const files = useArchiveFiles({ folder });
- const [filter, setFilter] = React.useState('');
- const handleRefreshFiles = () => {
- axios.post('archive/refresh-files', { folder });
- };
-
- return (
- <>
-
-
- Refresh
-
-
- ({
- fileName: file.name,
- folderName: folder,
- }))}
- filter={filter}
- AppObjectComponent={ArchiveFileAppObject}
- />
-
- >
- );
-}
-
-export default function ArchiveWidget() {
- return (
-
-
-
-
-
-
-
-
- );
-}
diff --git a/packages/web/src/widgets/DatabaseWidget.js b/packages/web/src/widgets/DatabaseWidget.js
deleted file mode 100644
index 568a3a031..000000000
--- a/packages/web/src/widgets/DatabaseWidget.js
+++ /dev/null
@@ -1,196 +0,0 @@
-import React from 'react';
-import _ from 'lodash';
-
-import { AppObjectList } from '../appobj/AppObjectList';
-import ConnectionAppObject from '../appobj/ConnectionAppObject';
-import DatabaseAppObject from '../appobj/DatabaseAppObject';
-import { useSetCurrentDatabase, useCurrentDatabase, useOpenedConnections } from '../utility/globalState';
-import InlineButton from './InlineButton';
-import DatabaseObjectAppObject from '../appobj/DatabaseObjectAppObject';
-import {
- // useSqlObjectList,
- useDatabaseList,
- useConnectionList,
- useServerStatus,
- useDatabaseStatus,
- useDatabaseInfo,
- useConfig,
-} from '../utility/metadataLoaders';
-import { SearchBoxWrapper, WidgetsInnerContainer } from './WidgetStyles';
-import axios from '../utility/axios';
-import LoadingInfo from './LoadingInfo';
-import SearchInput from './SearchInput';
-import ErrorInfo from './ErrorInfo';
-import WidgetColumnBar, { WidgetColumnBarItem } from './WidgetColumnBar';
-import ToolbarButton from './ToolbarButton';
-import useShowModal from '../modals/showModal';
-import ConnectionModal from '../modals/ConnectionModal';
-import SubColumnParamList from '../appobj/SubColumnParamList';
-import { ChevronExpandIcon } from '../icons';
-
-function SubDatabaseList({ data }) {
- const setDb = useSetCurrentDatabase();
- const handleDatabaseClick = database => {
- setDb({
- ...database,
- connection: data,
- });
- };
- const { _id } = data;
- const databases = useDatabaseList({ conid: _id });
- return (
- ({ ...db, connection: data }))}
- AppObjectComponent={DatabaseAppObject}
- // makeAppObj={databaseAppObject({ boldCurrentDatabase: true })}
- onObjectClick={handleDatabaseClick}
- />
- );
-}
-
-function ConnectionList() {
- const connections = useConnectionList();
- const serverStatus = useServerStatus();
- const openedConnections = useOpenedConnections();
- const connectionsWithStatus =
- connections && serverStatus ? connections.map(conn => ({ ...conn, status: serverStatus[conn._id] })) : connections;
- const showModal = useShowModal();
-
- const handleRefreshConnections = () => {
- for (const conid of openedConnections) {
- axios.post('server-connections/refresh', { conid });
- }
- };
-
- const showNewConnection = () => {
- showModal(modalState => );
- };
-
- const [filter, setFilter] = React.useState('');
- return (
- <>
-
-
- Refresh
-
-
-
-
- (displayName || server || '').toUpperCase()
- )}
- AppObjectComponent={ConnectionAppObject}
- // makeAppObj={connectionAppObject({ boldCurrentDatabase: true })}
- SubItems={SubDatabaseList}
- filter={filter}
- isExpandable={data => openedConnections.includes(data._id)}
- expandOnClick
- />
- {connections && connections.length == 0 && (
-
- Add new connection
-
- )}
-
- >
- );
-}
-
-function SqlObjectList({ conid, database }) {
- const objects = useDatabaseInfo({ conid, database });
- const status = useDatabaseStatus({ conid, database });
-
- const handleRefreshDatabase = () => {
- axios.post('database-connections/refresh', { conid, database });
- };
-
- const [filter, setFilter] = React.useState('');
- const objectList = _.flatten(
- ['tables', 'views', 'procedures', 'functions'].map(objectTypeField =>
- _.sortBy(
- ((objects || {})[objectTypeField] || []).map(obj => ({ ...obj, objectTypeField })),
- ['schemaName', 'pureName']
- )
- )
- );
-
- const inputRef = React.useRef(null);
-
- if (status && status.name == 'error') {
- return (
-
-
- Refresh
-
- );
- }
-
- if (objectList.length == 0 && status && status.name != 'pending' && objects) {
- return (
-
-
- Refresh
-
- );
- }
-
- return (
- <>
-
-
- Refresh
-
-
- {(status && status.name == 'pending') || !objects ? (
-
- ) : (
- ({ ...x, conid, database }))}
- AppObjectComponent={DatabaseObjectAppObject}
- groupFunc={data => _.startCase(data.objectTypeField)}
- filter={filter}
- SubItems={SubColumnParamList}
- isExpandable={data => data.objectTypeField == 'tables' || data.objectTypeField == 'views'}
- ExpandIconComponent={ChevronExpandIcon}
- />
- )}
-
- >
- );
-}
-
-function SqlObjectListWrapper() {
- const db = useCurrentDatabase();
-
- if (!db) {
- return (
-
-
-
- );
- }
- const { name, connection } = db;
-
- return ;
- // return tables of {db && db.name}
- // return tables of {JSON.stringify(db)}
-}
-
-export default function DatabaseWidget() {
- const config = useConfig();
- return (
-
- {!config.singleDatabase && (
-
-
-
- )}
-
-
-
-
- );
-}
diff --git a/packages/web/src/widgets/DropDownButton.js b/packages/web/src/widgets/DropDownButton.js
deleted file mode 100644
index c1d725fea..000000000
--- a/packages/web/src/widgets/DropDownButton.js
+++ /dev/null
@@ -1,20 +0,0 @@
-import React from 'react';
-import { FontIcon } from '../icons';
-import { useShowMenu } from '../modals/showMenu';
-import InlineButton from './InlineButton';
-
-export default function DropDownButton({ children }) {
- const buttonRef = React.useRef(null);
- const showMenu = useShowMenu();
-
- const handleShowMenu = () => {
- const rect = buttonRef.current.getBoundingClientRect();
- showMenu(rect.left, rect.bottom, children);
- };
-
- return (
-
-
-
- );
-}
diff --git a/packages/web/src/widgets/ErrorInfo.js b/packages/web/src/widgets/ErrorInfo.js
deleted file mode 100644
index 736bad3cc..000000000
--- a/packages/web/src/widgets/ErrorInfo.js
+++ /dev/null
@@ -1,39 +0,0 @@
-import React from 'react';
-
-import styled from 'styled-components';
-import { FontIcon } from '../icons';
-
-const Container = styled.div`
- display: flex;
- align-items: center;
- margin-right: 10px;
-`;
-
-const Icon = styled.div`
- font-size: 20pt;
- margin: 10px;
-`;
-
-const ContainerSmall = styled.div`
- display: flex;
- margin-right: 10px;
-`;
-
-export default function ErrorInfo({ message, icon = 'img error', isSmall = false }) {
- if (isSmall) {
- return (
-
-
- {message}
-
- );
- }
- return (
-
-
-
-
- {message}
-
- );
-}
diff --git a/packages/web/src/widgets/FavoritesWidget.js b/packages/web/src/widgets/FavoritesWidget.js
deleted file mode 100644
index ce0f3191f..000000000
--- a/packages/web/src/widgets/FavoritesWidget.js
+++ /dev/null
@@ -1,57 +0,0 @@
-import React from 'react';
-import _ from 'lodash';
-
-import { AppObjectList } from '../appobj/AppObjectList';
-import { useOpenedTabs } from '../utility/globalState';
-import ClosedTabAppObject from '../appobj/ClosedTabAppObject';
-import { WidgetsInnerContainer } from './WidgetStyles';
-import WidgetColumnBar, { WidgetColumnBarItem } from './WidgetColumnBar';
-import { useFavorites } from '../utility/metadataLoaders';
-import useHasPermission from '../utility/useHasPermission';
-import { FavoriteFileAppObject } from '../appobj/FavoriteFileAppObject';
-
-function ClosedTabsList() {
- const tabs = useOpenedTabs();
-
- return (
- <>
-
- x.closedTime),
- x => -x.closedTime
- )}
- AppObjectComponent={ClosedTabAppObject}
- />
-
- >
- );
-}
-
-function FavoritesList() {
- const favorites = useFavorites();
-
- return (
- <>
-
-
-
- >
- );
-}
-
-export default function FavoritesWidget() {
- const hasPermission = useHasPermission();
- return (
-
- {hasPermission('files/favorites/read') && (
-
-
-
- )}
-
-
-
-
- );
-}
diff --git a/packages/web/src/widgets/FilesWidget.js b/packages/web/src/widgets/FilesWidget.js
deleted file mode 100644
index 8c90c53b8..000000000
--- a/packages/web/src/widgets/FilesWidget.js
+++ /dev/null
@@ -1,46 +0,0 @@
-import React from 'react';
-import _ from 'lodash';
-
-import { AppObjectList } from '../appobj/AppObjectList';
-import { WidgetsInnerContainer } from './WidgetStyles';
-import { SavedFileAppObject } from '../appobj/SavedFileAppObject';
-import WidgetColumnBar, { WidgetColumnBarItem } from './WidgetColumnBar';
-import { useFiles } from '../utility/metadataLoaders';
-
-function SavedFilesList() {
- const sqlFiles = useFiles({ folder: 'sql' });
- const shellFiles = useFiles({ folder: 'shell' });
- const markdownFiles = useFiles({ folder: 'markdown' });
- const chartFiles = useFiles({ folder: 'charts' });
- const queryFiles = useFiles({ folder: 'query' });
-
- const files = [
- ...(sqlFiles || []),
- ...(shellFiles || []),
- ...(markdownFiles || []),
- ...(chartFiles || []),
- ...(queryFiles || []),
- ];
-
- return (
- <>
-
- _.startCase(data.folder)}
- />
-
- >
- );
-}
-
-export default function FilesWidget() {
- return (
-
-
-
-
-
- );
-}
diff --git a/packages/web/src/widgets/FormStyledButton.js b/packages/web/src/widgets/FormStyledButton.js
deleted file mode 100644
index 3185b451d..000000000
--- a/packages/web/src/widgets/FormStyledButton.js
+++ /dev/null
@@ -1,77 +0,0 @@
-// @ts-nocheck
-import React from 'react';
-import styled from 'styled-components';
-import dimensions from '../theme/dimensions';
-import useTheme from '../theme/useTheme';
-
-// const StyledInputBase=styled.input``;
-// const StyledLabelBase=styled.label``;
-
-const makeStyle = base => styled(base)`
- // height: ${dimensions.toolBar.height - 5}px;
- border: 1px solid ${props => props.theme.button_background2};
- padding: 5px;
- margin: 2px;
- width: 100px;
- background-color: ${props => props.theme.button_background};
- color: ${props => props.theme.button_font1};
- border-radius: 2px;
-
- ${props =>
- !props.disabled &&
- `
- &:hover {
- background-color: ${props.theme.button_background2};
- }
-
- &:active:hover {
- background-color: ${props.theme.button_background3};
- }
- `}
-
- ${props =>
- props.disabled &&
- `
- background-color: ${props.theme.button_background3};
- color: ${props.theme.button_font3} ;
- `}
-`;
-
-const ButtonInput = makeStyle(styled.input``);
-const FormStyledLabelBase = makeStyle(styled.label``);
-export const FormStyledLabel = styled(FormStyledLabelBase)``;
-
-export default function FormStyledButton({
- onClick = undefined,
- type = 'button',
- value,
- disabled = undefined,
- ...other
-}) {
- const theme = useTheme();
- return (
- {
- if (!disabled && onClick) onClick();
- }
- : undefined
- }
- disabled={disabled}
- value={value}
- {...other}
- />
- );
-}
-
-export const StyledThemedLink = styled.a`
- text-decoration: none;
- cursor: pointer;
- color: ${props => props.theme.main_background_blue[7]};
- &:hover {
- text-decoration: underline;
- }
-`;
diff --git a/packages/web/src/widgets/InlineButton.js b/packages/web/src/widgets/InlineButton.js
deleted file mode 100644
index 0ca76d2bb..000000000
--- a/packages/web/src/widgets/InlineButton.js
+++ /dev/null
@@ -1,74 +0,0 @@
-// @ts-nocheck
-import React from 'react';
-import styled from 'styled-components';
-import useTheme from '../theme/useTheme';
-
-const ButtonDiv = styled.div`
- background: linear-gradient(
- to bottom,
- ${props => props.theme.inlinebtn_background} 5%,
- ${props => props.theme.inlinebtn_background3} 100%
- );
- background-color: ${props => props.theme.inlinebtn_background};
- border: 1px solid ${props => props.theme.inlinebtn_background3};
- display: inline-block;
- cursor: pointer;
- vertical-align: middle;
- color: ${props => (props.disabled ? props.theme.inlinebtn_font3 : props.theme.inlinebtn_font1)};
- font-size: 12px;
- padding: 3px;
- margin: 0;
- text-decoration: none;
- ${props =>
- !props.disabled &&
- `
- &:hover {
- border: 1px solid ${props.theme.inlinebtn_font2};
- }
- &:active:hover {
- background: linear-gradient(
- to bottom,
- ${props.theme.inlinebtn_background3} 5%,
- ${props.theme.inlinebtn_background} 100%
- );
- background-color: ${props.theme.inlinebtn_background3};
- }
- `}
- display: flex;
-
- ${props =>
- props.square &&
- `
- width: 18px;
- `}
-`;
-
-const InnerDiv = styled.div`
- margin: auto;
- flex: 1;
- text-align: center;
-`;
-
-export default function InlineButton({
- children,
- onClick = undefined,
- buttonRef = undefined,
- disabled = undefined,
- square = false,
-}) {
- const theme = useTheme();
- return (
- {
- if (!disabled && onClick) onClick();
- }}
- disabled={disabled}
- square={square}
- theme={theme}
- >
- {children}
-
- );
-}
diff --git a/packages/web/src/widgets/LargeButton.js b/packages/web/src/widgets/LargeButton.js
deleted file mode 100644
index 104c6a669..000000000
--- a/packages/web/src/widgets/LargeButton.js
+++ /dev/null
@@ -1,70 +0,0 @@
-// @ts-nocheck
-import React from 'react';
-import styled from 'styled-components';
-import { FontIcon } from '../icons';
-import dimensions from '../theme/dimensions';
-import useTheme from '../theme/useTheme';
-import { useForm } from '../utility/FormProvider';
-
-const ButtonDiv = styled.div`
- padding: 5px 15px;
- color: ${props => props.theme.main_font1};
- border: 1px solid ${props => props.theme.border};
- width: 120px;
- height: 60px;
- background-color: ${props => props.theme.toolbar_background};
-
- ${props =>
- !props.disabled &&
- `
- &:hover {
- background-color: ${props.theme.toolbar_background2} ;
- }
-
- &:active:hover {
- background-color: ${props.theme.toolbar_background3};
- }
- `}
-
- ${props =>
- props.disabled &&
- `
- color: ${props.theme.main_font3};
- `}
-`;
-
-const IconDiv = styled.div`
- font-size: 30px;
- text-align: center;
-`;
-
-const ButtonDivInner = styled.div`
- text-align: center;
-`;
-
-export default function LargeButton({ children, onClick, icon = undefined, disabled = undefined }) {
- const theme = useTheme();
- return (
- {
- if (!disabled && onClick) onClick();
- }}
- disabled={disabled}
- >
-
-
-
- {children}
-
- );
-}
-
-export function LargeFormButton({ children, onClick, icon = undefined, disabled = undefined }) {
- const { values } = useForm();
- return (
- onClick(values)}>
- {children}
-
- );
-}
diff --git a/packages/web/src/widgets/LoadingInfo.js b/packages/web/src/widgets/LoadingInfo.js
deleted file mode 100644
index 65b2a13bf..000000000
--- a/packages/web/src/widgets/LoadingInfo.js
+++ /dev/null
@@ -1,53 +0,0 @@
-import React from 'react';
-
-import styled from 'styled-components';
-import { FontIcon } from '../icons';
-import useTheme from '../theme/useTheme';
-
-const Container = styled.div`
- display: flex;
- align-items: center;
- margin-right: 10px;
-`;
-
-const Spinner = styled.div`
- font-size: 20pt;
- margin: 10px;
-`;
-
-const LoadingInfoWrapper = styled.div`
- position: absolute;
- left: 0;
- top: 0;
- right: 0;
- bottom: 0;
- display: flex;
- align-items: center;
- justify-content: space-around;
-`;
-const LoadingInfoBox = styled.div`
- background-color: ${props => props.theme.main_background2};
- padding: 10px;
- border: 1px solid gray;
-`;
-
-export default function LoadingInfo({ message, wrapper = false }) {
- const theme = useTheme();
- const core = (
-
-
-
-
- {message}
-
- );
- if (wrapper) {
- return (
-
- {core}
-
- );
- } else {
- return core;
- }
-}
diff --git a/packages/web/src/widgets/PluginsWidget.js b/packages/web/src/widgets/PluginsWidget.js
deleted file mode 100644
index ea4c0f6c5..000000000
--- a/packages/web/src/widgets/PluginsWidget.js
+++ /dev/null
@@ -1,65 +0,0 @@
-import React from 'react';
-import _ from 'lodash';
-import { SearchBoxWrapper, WidgetsInnerContainer } from './WidgetStyles';
-import WidgetColumnBar, { WidgetColumnBarItem } from './WidgetColumnBar';
-import { useInstalledPlugins } from '../utility/metadataLoaders';
-import SearchInput from './SearchInput';
-import useFetch from '../utility/useFetch';
-import PluginsList from '../plugins/PluginsList';
-
-function InstalledPluginsList() {
- const plugins = useInstalledPlugins();
-
- return (
-
-
-
- );
-}
-
-function AvailablePluginsList() {
- const [filter, setFilter] = React.useState('');
- const [search, setSearch] = React.useState('');
-
- const plugins = useFetch({
- url: 'plugins/search',
- params: {
- filter: search,
- },
- defaultValue: [],
- });
-
- const setDebouncedFilter = React.useRef(
- // @ts-ignore
- _.debounce(value => setSearch(value), 500)
- );
-
- React.useEffect(() => {
- // @ts-ignore
- setDebouncedFilter.current(filter);
- }, [filter]);
-
- return (
- <>
-
-
-
-
-
-
- >
- );
-}
-
-export default function PluginsWidget() {
- return (
-
-
-
-
-
-
-
-
- );
-}
diff --git a/packages/web/src/widgets/SearchInput.js b/packages/web/src/widgets/SearchInput.js
deleted file mode 100644
index 14dccf70e..000000000
--- a/packages/web/src/widgets/SearchInput.js
+++ /dev/null
@@ -1,28 +0,0 @@
-import React from 'react';
-import styled from 'styled-components';
-import keycodes from '../utility/keycodes';
-
-const StyledInput = styled.input`
- flex: 1;
- min-width: 10px;
- width: 10px;
-`;
-
-export default function SearchInput({ placeholder, filter, setFilter, inputRef = undefined }) {
- const handleKeyDown = ev => {
- if (ev.keyCode == keycodes.escape) {
- setFilter('');
- }
- };
- return (
- setFilter(e.target.value)}
- onFocus={e => e.target.select()}
- onKeyDown={handleKeyDown}
- />
- );
-}
diff --git a/packages/web/src/widgets/Splitter.js b/packages/web/src/widgets/Splitter.js
deleted file mode 100644
index 750951c8c..000000000
--- a/packages/web/src/widgets/Splitter.js
+++ /dev/null
@@ -1,169 +0,0 @@
-import _ from 'lodash';
-import React from 'react';
-import styled from 'styled-components';
-import useDimensions from '../utility/useDimensions';
-import dimensions from '../theme/dimensions';
-import useTheme from '../theme/useTheme';
-
-const SplitterMainBase = styled.div`
- flex: 1;
- display: flex;
- position: absolute;
- left: 0;
- right: 0;
- top: 0;
- bottom: 0;
-`;
-
-// @ts-ignore
-const VerticalMainContainer = styled(SplitterMainBase)`
- flex: 1;
- display: flex;
- flex-direction: column;
-`;
-
-const HorizontalMainContainer = styled(SplitterMainBase)`
- flex: 1;
- display: flex;
-`;
-
-export const VerticalSplitHandle = styled.div`
- background-color: ${props => props.theme.border};
- height: ${dimensions.splitter.thickness}px;
- cursor: row-resize;
- &:hover {
- background-color: ${props => props.theme.border_background2};
- }
-`;
-
-export const HorizontalSplitHandle = styled.div`
- background-color: ${props => props.theme.border};
- width: ${dimensions.splitter.thickness}px;
- cursor: col-resize;
- &:hover {
- background-color: ${props => props.theme.border_background2};
- }
-`;
-
-const ChildContainer1 = styled.div`
- // flex: 0 0 50%;
- // flex-basis: 100px;
- // flex-grow: 1;
- display: flex;
- position: relative;
- overflow: hidden;
-`;
-
-const ChildContainer2 = styled.div`
- flex: 1;
- // flex: 0 0 50%;
- // flex-basis: 100px;
- // flex-grow: 1;
- display: flex;
- position: relative;
- overflow: hidden;
-`;
-
-export function useSplitterDrag(axes, onResize) {
- const [resizeStart, setResizeStart] = React.useState(null);
-
- React.useEffect(() => {
- if (resizeStart != null) {
- const handleResizeMove = e => {
- e.preventDefault();
- let diff = e[axes] - resizeStart;
- setResizeStart(e[axes]);
- onResize(diff);
- };
- const handleResizeEnd = e => {
- e.preventDefault();
- setResizeStart(null);
- };
-
- document.addEventListener('mousemove', handleResizeMove, true);
- document.addEventListener('mouseup', handleResizeEnd, true);
-
- return () => {
- document.removeEventListener('mousemove', handleResizeMove, true);
- document.removeEventListener('mouseup', handleResizeEnd, true);
- };
- }
- }, [resizeStart]);
-
- const handleResizeDown = e => {
- setResizeStart(e[axes]);
- };
-
- return handleResizeDown;
-}
-
-function SplitterCore({
- children,
- eventField,
- dimensionField,
- styleField,
- Handle,
- Main,
- initialValue = undefined,
- size = undefined,
- setSize = undefined,
-}) {
- const theme = useTheme();
- const childrenArray = _.isArray(children) ? children : [children];
- if (childrenArray.length !== 1 && childrenArray.length != 2) {
- throw new Error('Splitter must have 1 or 2 children');
- }
- const [refNode, dimensions] = useDimensions();
- const [mySize, setMySize] = React.useState(0);
- const size1 = size === undefined ? mySize : size;
- const setSize1 = setSize === undefined ? setMySize : setSize;
-
- React.useEffect(() => {
- if (_.isString(initialValue) && initialValue.endsWith('px')) setSize1(parseInt(initialValue.slice(0, -2)));
- else if (_.isString(initialValue) && initialValue.endsWith('%'))
- setSize1((dimensions[dimensionField] * parseFloat(initialValue.slice(0, -1))) / 100);
- else setSize1(dimensions[dimensionField] / 2);
- }, [dimensions]);
-
- const handleResizeDown = useSplitterDrag(eventField, diff => setSize1(v => v + diff));
-
- const isSplitter = !!childrenArray[1];
-
- return (
-
- {childrenArray[0]}
- {isSplitter && }
- {isSplitter && {childrenArray[1]} }
-
- );
-}
-
-export function VerticalSplitter({ children, ...other }) {
- return (
-
- {children}
-
- );
-}
-
-export function HorizontalSplitter({ children, ...other }) {
- return (
-
- {children}
-
- );
-}
diff --git a/packages/web/src/widgets/StatusBar.js b/packages/web/src/widgets/StatusBar.js
deleted file mode 100644
index 621c320e9..000000000
--- a/packages/web/src/widgets/StatusBar.js
+++ /dev/null
@@ -1,97 +0,0 @@
-import React from 'react';
-import styled from 'styled-components';
-import { FontIcon } from '../icons';
-import useTheme from '../theme/useTheme';
-
-import { useCurrentDatabase } from '../utility/globalState';
-import { useDatabaseStatus } from '../utility/metadataLoaders';
-
-const Container = styled.div`
- display: flex;
- color: ${props => props.theme.statusbar_font1};
- align-items: stretch;
- justify-content: space-between;
-`;
-
-export const StatusBarItem = styled.div`
- padding: 2px 10px;
-`;
-
-const ErrorWrapper = styled.span`
- color: ${props =>
- // @ts-ignore
- props.theme.statusbar_font_red[5]};
-`;
-
-const InfoWrapper = styled.span`
- color: ${props =>
- // @ts-ignore
- props.theme.statusbar_font_green[5]};
-`;
-
-const StatusbarContainer = styled.div`
- display: flex;
-`;
-
-export default function StatusBar({ statusbarPortalRef }) {
- const { name, connection } = useCurrentDatabase() || {};
- const status = useDatabaseStatus(connection ? { conid: connection._id, database: name } : {});
- const { displayName, server, user, engine } = connection || {};
- const theme = useTheme();
- return (
-
-
- {name && (
-
- {name}
-
- )}
- {(displayName || server) && (
-
- {displayName || server}
-
- )}
-
- {user && (
-
- {user}
-
- )}
-
- {connection && status && (
-
- {status.name == 'pending' && (
- <>
- Loading
- >
- )}
- {status.name == 'ok' && (
- <>
-
-
- {' '}
- Connected
- >
- )}
- {status.name == 'error' && (
- <>
-
-
- {' '}
- Error
- >
- )}
-
- )}
- {!connection && (
-
- <>
- Not connected
- >
-
- )}
-
-
-
- );
-}
diff --git a/packages/web/src/widgets/TabControl.js b/packages/web/src/widgets/TabControl.js
deleted file mode 100644
index 8b933ab1f..000000000
--- a/packages/web/src/widgets/TabControl.js
+++ /dev/null
@@ -1,130 +0,0 @@
-import React from 'react';
-import _ from 'lodash';
-import styled from 'styled-components';
-import useTheme from '../theme/useTheme';
-import dimensions from '../theme/dimensions';
-
-const TabItem = styled.div`
- border-right: 1px solid ${props => props.theme.border};
- padding-left: 15px;
- padding-right: 15px;
- display: flex;
- align-items: center;
- cursor: pointer;
- &:hover {
- color: ${props => props.theme.tabs_font_hover};
- }
- background-color: ${props =>
- // @ts-ignore
- props.selected ? props.theme.tabs_background1 : 'inherit'};
-`;
-
-const TabNameWrapper = styled.span`
- margin-left: 5px;
-`;
-
-// visibility: ${(props) =>
-// // @ts-ignore
-// props.tabVisible ? 'visible' : 'none'};
-
-const TabContainer = styled.div`
- ${props =>
- // @ts-ignore
- !props.isInline &&
- `
- position: absolute;
- display: flex;
- left: 0;
- right: 0
- top: 0;
- bottom: 0;
- `}
-
- ${props =>
- // @ts-ignore
- !props.tabVisible && (props.isInline ? `display:none` : `visibility: hidden;`)}
-`;
-
-const TabsContainer = styled.div`
- display: flex;
- height: ${dimensions.tabsPanel.height}px;
- right: 0;
- background-color: ${props => props.theme.tabs_background2};
-`;
-
-const TabContentContainer = styled.div`
- flex: 1;
- position: relative;
-`;
-
-const MainContainer = styled.div`
- display: flex;
- flex: 1;
- flex-direction: column;
-`;
-
-export function TabPage({ key, label, children }) {
- return children;
-}
-
-export function TabControl({ children, activePageIndex = undefined, activePageLabel = undefined, isInline = false }) {
- const [value, setValue] = React.useState(0);
-
- // const [mountedTabs, setMountedTabs] = React.useState({});
-
- const childrenArray = (_.isArray(children) ? _.flatten(children) : [children]).filter(x => x);
-
- React.useEffect(() => {
- if (activePageIndex != null) setValue(activePageIndex);
- }, [activePageIndex]);
-
- React.useEffect(() => {
- if (activePageLabel != null) {
- const pageIndex = _.findIndex(childrenArray, x => x.props.label == activePageLabel);
- if (pageIndex >= 0) setValue(pageIndex);
- }
- }, [activePageLabel]);
-
- React.useEffect(() => {
- if (childrenArray.length > 0 && (value < 0 || value >= childrenArray.length)) {
- setValue(0);
- }
- });
-
- const theme = useTheme();
-
- // // cleanup closed tabs
- // if (_.difference(_.keys(mountedTabs), _.map(childrenArray, 'props.key')).length > 0) {
- // setMountedTabs(_.pickBy(mountedTabs, (v, k) => childrenArray.find((x) => x.props.key == k)));
- // }
-
- return (
-
-
- {childrenArray
- .filter(x => x.props)
- .map((tab, index) => (
- // @ts-ignore
- setValue(index)} selected={value == index} theme={theme}>
- {tab.props.label}
-
- ))}
-
-
- {childrenArray.map((tab, index) => {
- const tabVisible = index == value;
- return (
-
- {childrenArray[index] && childrenArray[index].props.children}
-
- );
- })}
-
-
- );
-}
diff --git a/packages/web/src/widgets/Toolbar.js b/packages/web/src/widgets/Toolbar.js
deleted file mode 100644
index 3873c1edc..000000000
--- a/packages/web/src/widgets/Toolbar.js
+++ /dev/null
@@ -1,183 +0,0 @@
-import React from 'react';
-import useModalState from '../modals/useModalState';
-import ConnectionModal from '../modals/ConnectionModal';
-import { DropDownMenuItem } from '../modals/DropDownMenu';
-import styled from 'styled-components';
-import ToolbarButton, { ToolbarButtonExternalImage, ToolbarDropDownButton } from './ToolbarButton';
-import useNewQuery, { useNewQueryDesign } from '../query/useNewQuery';
-import { useConfig, useFavorites } from '../utility/metadataLoaders';
-import {
- useSetOpenedTabs,
- useOpenedTabs,
- useCurrentTheme,
- useSetCurrentTheme,
- useCurrentDatabase,
-} from '../utility/globalState';
-import useNewFreeTable from '../freetable/useNewFreeTable';
-import ImportExportModal from '../modals/ImportExportModal';
-import useShowModal from '../modals/showModal';
-import useExtensions from '../utility/useExtensions';
-import { getDefaultFileFormat } from '../utility/fileformats';
-import getElectron from '../utility/getElectron';
-import AboutModal from '../modals/AboutModal';
-import useOpenNewTab from '../utility/useOpenNewTab';
-import tabs from '../tabs';
-import FavoriteModal from '../modals/FavoriteModal';
-import { useOpenFavorite } from '../appobj/FavoriteFileAppObject';
-import ErrorMessageModal from '../modals/ErrorMessageModal';
-import useOpenElectronFile from '../utility/useOpenElectronFile';
-
-const ToolbarContainer = styled.div`
- display: flex;
- user-select: none;
-`;
-
-export default function ToolBar({ toolbarPortalRef }) {
- const newQuery = useNewQuery();
- const newQueryDesign = useNewQueryDesign();
- const newFreeTable = useNewFreeTable();
- const config = useConfig();
- const currentDatabase = useCurrentDatabase();
- // const toolbar = config.toolbar || [];
- const setOpenedTabs = useSetOpenedTabs();
- const openedTabs = useOpenedTabs();
- const openNewTab = useOpenNewTab();
- const showModal = useShowModal();
- const currentTheme = useCurrentTheme();
- const setCurrentTheme = useSetCurrentTheme();
- const extensions = useExtensions();
- const electron = getElectron();
- const favorites = useFavorites();
- const openFavorite = useOpenFavorite();
- const openElectronFile = useOpenElectronFile();
-
- const currentTab = openedTabs.find(x => x.selected);
-
- React.useEffect(() => {
- if (config.runAsPortal == false) {
- window['dbgate_createNewConnection'] = showNewConnection;
- }
- window['dbgate_newQuery'] = newQuery;
- window['dbgate_closeAll'] = () => setOpenedTabs([]);
- window['dbgate_showAbout'] = showAbout;
- window['dbgate_openFile'] = openElectronFile;
- });
-
- const showAbout = () => {
- showModal(modalState => );
- };
-
- const showImport = () => {
- showModal(modalState => (
-
- ));
- };
-
- const showNewConnection = () => {
- showModal(modalState => );
- };
-
- const switchTheme = () => {
- if (currentTheme == 'light') setCurrentTheme('dark');
- else setCurrentTheme('light');
- };
-
- const newMarkdown = () => {
- openNewTab({
- title: 'Page #',
- tabComponent: 'MarkdownEditorTab',
- icon: 'img markdown',
- });
- };
-
- const addToFavorite = () => {
- showModal(modalState => );
- };
-
- const newShell = () => {
- openNewTab({
- title: 'Shell #',
- icon: 'img shell',
- tabComponent: 'ShellTab',
- });
- };
-
- React.useEffect(() => {
- const { hash } = document.location;
- const openFavoriteName = hash && hash.startsWith('#favorite=') ? hash.substring('#favorite='.length) : null;
- const openTabdata = hash && hash.startsWith('#tabdata=') ? hash.substring('#tabdata='.length) : null;
- if (openFavoriteName) {
- const open = (favorites || []).find(x => x.urlPath == openFavoriteName);
- if (open) {
- openFavorite(open);
- window.history.replaceState(null, null, ' ');
- }
- } else if (openTabdata) {
- try {
- const json = JSON.parse(decodeURIComponent(openTabdata));
- openFavorite(json);
- window.history.replaceState(null, null, ' ');
- } catch (err) {
- showModal(modalState => );
- }
- } else if (!openedTabs.find(x => x.closedTime == null)) {
- for (const fav of (favorites || []).filter(x => x.openOnStartup)) {
- openFavorite(fav);
- }
- }
- }, [favorites]);
-
- return (
-
- {!electron && (
-
- )}
- {(favorites || [])
- .filter(x => x.showInToolbar)
- .map(x => (
- openFavorite(x)} icon={x.icon || 'icon favorite'}>
- {x.title}
-
- ))}
-
- {config.runAsPortal == false && Connection }
- newQuery()}>SQL query
- {!!currentDatabase && newQueryDesign()}>Query designer }
- newFreeTable()}>Free table editor
- newMarkdown()}>Markdown page
- newShell()}>JavaScript shell script
-
-
-
- Import data
-
- {!!currentTab &&
- tabs[currentTab.tabComponent] &&
- tabs[currentTab.tabComponent].allowAddToFavorites &&
- tabs[currentTab.tabComponent].allowAddToFavorites(currentTab.props) && (
-
- Share
-
- )}
-
- {currentTheme == 'dark' ? 'Light mode' : 'Dark mode'}
-
-
-
-
- );
-}
diff --git a/packages/web/src/widgets/ToolbarButton.js b/packages/web/src/widgets/ToolbarButton.js
deleted file mode 100644
index 7f84b9051..000000000
--- a/packages/web/src/widgets/ToolbarButton.js
+++ /dev/null
@@ -1,117 +0,0 @@
-// @ts-nocheck
-import React from 'react';
-import styled from 'styled-components';
-import { FontIcon } from '../icons';
-import { useShowMenu } from '../modals/showMenu';
-import dimensions from '../theme/dimensions';
-import useTheme from '../theme/useTheme';
-
-const ButtonDiv = styled.div`
- padding: 5px 15px;
- // margin: 2px;
- color: ${props => props.theme.main_font1};
- border: 0;
- border-right: 1px solid ${props => props.theme.border};
- height: ${dimensions.toolBar.height}px;
-
- ${props =>
- !props.disabled &&
- `
- &:hover {
- background-color: ${props.theme.toolbar_background2} ;
- }
-
- &:active:hover {
- background-color: ${props.theme.toolbar_background3};
- }
- `}
-
- ${props =>
- props.disabled &&
- `
- color: ${props.theme.main_font3};
- `}
-`;
-
-const StyledIconSpan = styled.span`
- margin-right: 5px;
- // font-size: 18px;
- color: ${props => (props.disabled ? props.theme.main_font3 : props.theme.main_font_link)};
-`;
-
-const ButtonDivInner = styled.div`
- position: relative;
- top: ${props => props.patchY}px;
- white-space: nowrap;
-`;
-
-const ButtonExternalImage = styled.img`
- width: 20px;
- height: 20px;
-`;
-
-export default function ToolbarButton({ children, onClick, icon = undefined, disabled = undefined, patchY = 2 }) {
- const theme = useTheme();
- return (
- {
- if (!disabled && onClick) onClick();
- }}
- disabled={disabled}
- >
-
- {icon && (
-
-
-
- )}
- {children}
-
-
- );
-}
-
-export function ToolbarButtonExternalImage({ image, onClick, disabled = undefined }) {
- const theme = useTheme();
- return (
- {
- if (!disabled && onClick) onClick();
- }}
- disabled={disabled}
- >
-
-
- );
-}
-
-export function ToolbarDropDownButton({ children, icon = undefined, text, disabled = undefined, patchY = 2 }) {
- const theme = useTheme();
- const showMenu = useShowMenu();
- const buttonRef = React.useRef(null);
-
- return (
- {
- if (disabled) return;
-
- const rect = buttonRef.current.getBoundingClientRect();
- showMenu(rect.left, rect.bottom, children);
- }}
- disabled={disabled}
- >
-
- {icon && (
-
-
-
- )}
- {text}
-
-
-
- );
-}
diff --git a/packages/web/src/widgets/WidgetColumnBar.js b/packages/web/src/widgets/WidgetColumnBar.js
deleted file mode 100644
index 87af36bf8..000000000
--- a/packages/web/src/widgets/WidgetColumnBar.js
+++ /dev/null
@@ -1,79 +0,0 @@
-import React from 'react';
-import _ from 'lodash';
-import {
- SearchBoxWrapper,
- WidgetsInnerContainer,
- WidgetsMainContainer,
- WidgetsOuterContainer,
- WidgetTitle,
-} from './WidgetStyles';
-import { VerticalSplitHandle, useSplitterDrag } from './Splitter';
-import useDimensions from '../utility/useDimensions';
-import useTheme from '../theme/useTheme';
-
-export function WidgetColumnBarItem({ title, children, name, height = undefined, collapsed = false }) {
- return <>>;
-}
-
-function WidgetContainer({ widget, visible, splitterVisible, parentHeight, initialSize = undefined }) {
- const [size, setSize] = React.useState(null);
- const theme = useTheme();
-
- const handleResizeDown = useSplitterDrag('clientY', diff => setSize(v => v + diff));
-
- React.useEffect(() => {
- if (_.isString(initialSize) && initialSize.endsWith('px')) setSize(parseInt(initialSize.slice(0, -2)));
- else if (_.isString(initialSize) && initialSize.endsWith('%'))
- setSize((parentHeight * parseFloat(initialSize.slice(0, -1))) / 100);
- else setSize(parentHeight / 3);
- }, [parentHeight]);
-
- if (!visible) return null;
-
- return (
- <>
-
- {widget.props.children}
-
- {splitterVisible && }
- >
- );
-}
-
-export default function WidgetColumnBar({ children, onChangeCollapsedWidgets = undefined }) {
- const childArray = _.isArray(children) ? children : [children];
- const [refNode, dimensions] = useDimensions();
- const [collapsedWidgets, setCollapsedWidgets] = React.useState(() =>
- childArray.filter(x => x && x.props.collapsed).map(x => x.props.name)
- );
- const toggleCollapsed = name => {
- // skip collapse last uncollapsed item
- if (!childArray.find(x => x.props && x.props.name != name && !collapsedWidgets.includes(x.props.name))) return;
-
- if (collapsedWidgets.includes(name)) setCollapsedWidgets(collapsedWidgets.filter(x => x != name));
- else setCollapsedWidgets([...collapsedWidgets, name]);
- };
- React.useEffect(() => {
- if (onChangeCollapsedWidgets) onChangeCollapsedWidgets(collapsedWidgets);
- }, [onChangeCollapsedWidgets, collapsedWidgets]);
-
- return (
-
- {childArray.map((widget, index) => {
- if (!widget) return null;
- return (
-
- toggleCollapsed(widget.props.name)}>{widget.props.title}
- x && !collapsedWidgets.includes(x.props.name))}
- />
-
- );
- })}
-
- );
-}
diff --git a/packages/web/src/widgets/WidgetContainer.js b/packages/web/src/widgets/WidgetContainer.js
deleted file mode 100644
index 51ea1f4b0..000000000
--- a/packages/web/src/widgets/WidgetContainer.js
+++ /dev/null
@@ -1,21 +0,0 @@
-import React from 'react';
-import { useCurrentWidget } from '../utility/globalState';
-import ArchiveWidget from './ArchiveWidget';
-import DatabaseWidget from './DatabaseWidget';
-import FavoritesWidget from './FavoritesWidget';
-import FilesWidget from './FilesWidget';
-import PluginsWidget from './PluginsWidget';
-
-function WidgetContainerCore() {
- const currentWidget = useCurrentWidget();
- if (currentWidget === 'database') return ;
- if (currentWidget === 'file') return ;
- if (currentWidget === 'archive') return ;
- if (currentWidget === 'plugins') return ;
- if (currentWidget === 'favorites') return ;
- return null;
-}
-
-const WidgetContainer = React.memo(WidgetContainerCore);
-
-export default WidgetContainer;
diff --git a/packages/web/src/widgets/WidgetIconPanel.js b/packages/web/src/widgets/WidgetIconPanel.js
deleted file mode 100644
index e6817f565..000000000
--- a/packages/web/src/widgets/WidgetIconPanel.js
+++ /dev/null
@@ -1,93 +0,0 @@
-import React from 'react';
-import dimensions from '../theme/dimensions';
-import styled from 'styled-components';
-import { useCurrentWidget, useSetCurrentWidget } from '../utility/globalState';
-import { FontIcon } from '../icons';
-import useTheme from '../theme/useTheme';
-
-const IconWrapper = styled.div`
- color: ${props => props.theme.widget_font2};
- font-size: ${dimensions.widgetMenu.iconFontSize};
- height: ${dimensions.widgetMenu.iconSize}px;
- display: flex;
- align-items: center;
- justify-content: center;
-
- ${props =>
- // @ts-ignore
- props.isSelected &&
- `
- background-color: ${props.theme.widget_background3};
- // position: relative;
- // border-left: 3px solid ${props.theme.widget_font1};
- // left: -3px;
- color: ${props.theme.widget_font1};
- `}
-
- &:hover {
- color: ${props => props.theme.widget_font1};
- }
-`;
-
-export default function WidgetIconPanel() {
- const theme = useTheme();
- const widgets = [
- {
- icon: 'icon database',
- name: 'database',
- title: 'Database connections',
- },
- // {
- // icon: 'fa-table',
- // name: 'table',
- // },
- {
- icon: 'icon file',
- name: 'file',
- title: 'Closed tabs & Saved SQL files',
- },
- {
- icon: 'icon archive',
- name: 'archive',
- title: 'Archive (saved tabular data)',
- },
- {
- icon: 'icon plugin',
- name: 'plugins',
- title: 'Extensions & Plugins',
- },
- {
- icon: 'icon favorite',
- name: 'favorites',
- title: 'Favorites',
- },
- // {
- // icon: 'fa-cog',
- // name: 'settings',
- // },
- // {
- // icon: 'fa-check',
- // name: 'settings',
- // },
- ];
-
- const currentWidget = useCurrentWidget();
- const setCurrentWidget = useSetCurrentWidget();
-
- return (
- <>
- {widgets.map(({ icon, name, title }) => (
- setCurrentWidget(name === currentWidget ? null : name)}
- title={title}
- theme={theme}
- >
-
-
- ))}
- >
- );
-}
diff --git a/packages/web/src/widgets/WidgetStyles.js b/packages/web/src/widgets/WidgetStyles.js
deleted file mode 100644
index e09f72804..000000000
--- a/packages/web/src/widgets/WidgetStyles.js
+++ /dev/null
@@ -1,87 +0,0 @@
-// @ts-nocheck
-import React from 'react';
-import styled from 'styled-components';
-import useTheme from '../theme/useTheme';
-// import theme from '../theme';
-import { useLeftPanelWidth } from '../utility/globalState';
-
-export const SearchBoxWrapper = styled.div`
- display: flex;
- margin-bottom: 5px;
-`;
-
-export const WidgetsMainContainer = styled.div`
- position: relative;
- display: flex;
- // flex-flow: column wrap;
- flex: 1;
- flex-direction: column;
- user-select: none;
-`;
-
-const StyledWidgetsOuterContainer = styled.div`
- overflow: hidden;
- // width: ${props => props.leftPanelWidth}px;
- position: relative;
- flex-direction: column;
- display: flex;
-`;
-
-export function WidgetsOuterContainer({ children, style = undefined, refNode = undefined }) {
- // const leftPanelWidth = useLeftPanelWidth();
- return (
-
- {children}
-
- );
-}
-
-export const StyledWidgetsInnerContainer = styled.div`
- flex: 1 1;
- overflow-x: auto;
- overflow-y: auto;
- width: ${props => props.leftPanelWidth}px;
-`;
-
-export function WidgetsInnerContainer({ children }) {
- const leftPanelWidth = useLeftPanelWidth();
- return {children} ;
-}
-
-// export const Input = styled.input`
-// flex: 1;
-// min-width: 90px;
-// `;
-
-const StyledWidgetTitle = styled.div`
- padding: 5px;
- font-weight: bold;
- text-transform: uppercase;
- background-color: ${props => props.theme.title_background};
- &:hover {
- background-color: ${props => props.theme.title_background2};
- }
- border: 1px solid ${props => props.theme.border};
-`;
-
-export function WidgetTitle({ children, inputRef = undefined, onClick = undefined }) {
- const theme = useTheme();
- return (
- {
- if (inputRef && inputRef.current) inputRef.current.focus();
- if (onClick) onClick();
- }}
- >
- {children}
-
- );
-}
diff --git a/packages/web/tsconfig.json b/packages/web/tsconfig.json
deleted file mode 100644
index 1dccaa152..000000000
--- a/packages/web/tsconfig.json
+++ /dev/null
@@ -1,28 +0,0 @@
-{
- "compilerOptions": {
- "module": "esnext",
- "allowJs": true,
- "checkJs": true,
- "noEmit": true,
- "jsx": "react",
- "allowSyntheticDefaultImports": true,
- "esModuleInterop": true,
- "skipLibCheck": true,
- "moduleResolution": "Node",
- "noImplicitAny": false,
- "strictNullChecks": false,
- "target": "es5",
- "lib": [
- "dom",
- "dom.iterable",
- "esnext"
- ],
- "strict": true,
- "forceConsistentCasingInFileNames": true,
- "resolveJsonModule": true,
- "isolatedModules": true,
- },
- "include": [
- "src"
- ]
-}