mirror of
https://github.com/DeNNiiInc/dbgate.git
synced 2026-04-22 11:06:02 +00:00
statusbar - show current database
This commit is contained in:
@@ -9,6 +9,7 @@ import WidgetIconPanel from './widgets/WidgetIconPanel';
|
|||||||
import { useCurrentWidget } from './utility/globalState';
|
import { useCurrentWidget } from './utility/globalState';
|
||||||
import WidgetContainer from './widgets/WidgetContainer';
|
import WidgetContainer from './widgets/WidgetContainer';
|
||||||
import ToolBar from './widgets/Toolbar';
|
import ToolBar from './widgets/Toolbar';
|
||||||
|
import StatusBar from './widgets/StatusBar';
|
||||||
|
|
||||||
const BodyDiv = styled.div`
|
const BodyDiv = styled.div`
|
||||||
position: fixed;
|
position: fixed;
|
||||||
@@ -57,7 +58,7 @@ const TabsPanelContainer = styled.div`
|
|||||||
background-color: ${theme.tabsPanel.background};
|
background-color: ${theme.tabsPanel.background};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const StausBar = styled.div`
|
const StausBarContainer = styled.div`
|
||||||
position: fixed;
|
position: fixed;
|
||||||
height: ${theme.statusBar.height}px;
|
height: ${theme.statusBar.height}px;
|
||||||
left: 0;
|
left: 0;
|
||||||
@@ -89,7 +90,9 @@ export default function Screen() {
|
|||||||
<BodyDiv leftPanelWidth={leftPanelWidth}>
|
<BodyDiv leftPanelWidth={leftPanelWidth}>
|
||||||
<TabContent toolbarPortalRef={toolbarPortalRef} />
|
<TabContent toolbarPortalRef={toolbarPortalRef} />
|
||||||
</BodyDiv>
|
</BodyDiv>
|
||||||
<StausBar></StausBar>
|
<StausBarContainer>
|
||||||
|
<StatusBar />
|
||||||
|
</StausBarContainer>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,25 +1,11 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { MicrosoftIcon, SqliteIcon, PostgreSqlIcon, MySqlIcon, ServerIcon } from '../icons';
|
import { getEngineIcon } from '../icons';
|
||||||
import { DropDownMenuItem } from '../modals/DropDownMenu';
|
import { DropDownMenuItem } from '../modals/DropDownMenu';
|
||||||
import showModal from '../modals/showModal';
|
import showModal from '../modals/showModal';
|
||||||
import ConnectionModal from '../modals/ConnectionModal';
|
import ConnectionModal from '../modals/ConnectionModal';
|
||||||
import axios from '../utility/axios';
|
import axios from '../utility/axios';
|
||||||
import { filterName } from '@dbgate/datalib';
|
import { filterName } from '@dbgate/datalib';
|
||||||
|
|
||||||
function getIcon(engine) {
|
|
||||||
switch (engine) {
|
|
||||||
case 'mssql':
|
|
||||||
return MicrosoftIcon;
|
|
||||||
case 'sqlite':
|
|
||||||
return SqliteIcon;
|
|
||||||
case 'postgres':
|
|
||||||
return PostgreSqlIcon;
|
|
||||||
case 'mysql':
|
|
||||||
return MySqlIcon;
|
|
||||||
}
|
|
||||||
return ServerIcon;
|
|
||||||
}
|
|
||||||
|
|
||||||
function Menu({ data, makeAppObj }) {
|
function Menu({ data, makeAppObj }) {
|
||||||
const handleEdit = () => {
|
const handleEdit = () => {
|
||||||
showModal(modalState => <ConnectionModal modalState={modalState} connection={data} />);
|
showModal(modalState => <ConnectionModal modalState={modalState} connection={data} />);
|
||||||
@@ -38,7 +24,7 @@ function Menu({ data, makeAppObj }) {
|
|||||||
export default function connectionAppObject({ _id, server, displayName, engine }) {
|
export default function connectionAppObject({ _id, server, displayName, engine }) {
|
||||||
const title = displayName || server;
|
const title = displayName || server;
|
||||||
const key = _id;
|
const key = _id;
|
||||||
const Icon = getIcon(engine);
|
const Icon = getEngineIcon(engine);
|
||||||
const matcher = filter => filterName(filter, displayName, server);
|
const matcher = filter => filterName(filter, displayName, server);
|
||||||
|
|
||||||
return { title, key, Icon, Menu, matcher };
|
return { title, key, Icon, Menu, matcher };
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { DropDownMenuItem } from '../modals/DropDownMenu';
|
import { DropDownMenuItem, DropDownMenuDivider } from '../modals/DropDownMenu';
|
||||||
|
|
||||||
export default function DataGridContextMenu({ copy, revertRowChanges, deleteSelectedRows, insertNewRow, reload }) {
|
export default function DataGridContextMenu({ copy, revertRowChanges, deleteSelectedRows, insertNewRow, reload }) {
|
||||||
return (
|
return (
|
||||||
@@ -7,6 +7,7 @@ export default function DataGridContextMenu({ copy, revertRowChanges, deleteSele
|
|||||||
<DropDownMenuItem onClick={reload} keyText="F5">
|
<DropDownMenuItem onClick={reload} keyText="F5">
|
||||||
Reload
|
Reload
|
||||||
</DropDownMenuItem>
|
</DropDownMenuItem>
|
||||||
|
<DropDownMenuDivider />
|
||||||
<DropDownMenuItem onClick={copy} keyText="Ctrl+C">
|
<DropDownMenuItem onClick={copy} keyText="Ctrl+C">
|
||||||
Copy
|
Copy
|
||||||
</DropDownMenuItem>
|
</DropDownMenuItem>
|
||||||
|
|||||||
@@ -102,3 +102,17 @@ export const HourGlassIcon = props => <FontIcon icon="fas fa-hourglass" {...prop
|
|||||||
export const InfoBlueCircleIcon = props => <FontIcon icon="fas fa-info-circle blue" {...props} />;
|
export const InfoBlueCircleIcon = props => <FontIcon icon="fas fa-info-circle blue" {...props} />;
|
||||||
|
|
||||||
export const SpinnerIcon = props => <FontIcon icon="fas fa-spinner spin" {...props} />;
|
export const SpinnerIcon = props => <FontIcon icon="fas fa-spinner spin" {...props} />;
|
||||||
|
|
||||||
|
export function getEngineIcon(engine) {
|
||||||
|
switch (engine) {
|
||||||
|
case 'mssql':
|
||||||
|
return MicrosoftIcon;
|
||||||
|
case 'sqlite':
|
||||||
|
return SqliteIcon;
|
||||||
|
case 'postgres':
|
||||||
|
return PostgreSqlIcon;
|
||||||
|
case 'mysql':
|
||||||
|
return MySqlIcon;
|
||||||
|
}
|
||||||
|
return ServerIcon;
|
||||||
|
}
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ export default function ConfirmSqlModal({ modalState, sql, engine, onConfirm })
|
|||||||
<ModalBase modalState={modalState}>
|
<ModalBase modalState={modalState}>
|
||||||
<h2>Save changes</h2>
|
<h2>Save changes</h2>
|
||||||
<SqlWrapper>
|
<SqlWrapper>
|
||||||
<SqlEditor value={sql} engine={engine} />
|
<SqlEditor value={sql} engine={engine} readOnly />
|
||||||
</SqlWrapper>
|
</SqlWrapper>
|
||||||
|
|
||||||
<FormRow>
|
<FormRow>
|
||||||
|
|||||||
19
packages/web/src/query/useNewQuery.js
Normal file
19
packages/web/src/query/useNewQuery.js
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
import { useSetOpenedTabs } from '../utility/globalState';
|
||||||
|
import { openNewTab } from '../utility/common';
|
||||||
|
|
||||||
|
export default function useNewQuery() {
|
||||||
|
const setOpenedTabs = useSetOpenedTabs();
|
||||||
|
|
||||||
|
return () =>
|
||||||
|
openNewTab(setOpenedTabs, {
|
||||||
|
title: 'Query',
|
||||||
|
icon: 'sql.svg',
|
||||||
|
tabComponent: 'QueryTab',
|
||||||
|
// props: {
|
||||||
|
// schemaName,
|
||||||
|
// pureName,
|
||||||
|
// conid,
|
||||||
|
// database,
|
||||||
|
// },
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -22,19 +22,31 @@ const engineToMode = {
|
|||||||
postgre: 'pgsql',
|
postgre: 'pgsql',
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function SqlEditor({ value, engine }) {
|
export default function SqlEditor({
|
||||||
|
value = undefined,
|
||||||
|
engine = undefined,
|
||||||
|
readOnly = false,
|
||||||
|
onChange = undefined,
|
||||||
|
tabVisible = false,
|
||||||
|
}) {
|
||||||
const [containerRef, { height, width }] = useDimensions();
|
const [containerRef, { height, width }] = useDimensions();
|
||||||
|
const editorRef = React.useRef(null);
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
console.log('editorRef.current', editorRef.current);
|
||||||
|
if (tabVisible) editorRef.current.editor.focus();
|
||||||
|
}, [tabVisible]);
|
||||||
return (
|
return (
|
||||||
<Wrapper ref={containerRef}>
|
<Wrapper ref={containerRef}>
|
||||||
<AceEditor
|
<AceEditor
|
||||||
|
ref={editorRef}
|
||||||
mode={engineToMode[engine] || 'sql'}
|
mode={engineToMode[engine] || 'sql'}
|
||||||
theme="github"
|
theme="github"
|
||||||
// onChange={onChange}
|
onChange={onChange}
|
||||||
name="UNIQUE_ID_OF_DIV"
|
name="UNIQUE_ID_OF_DIV"
|
||||||
editorProps={{ $blockScrolling: true }}
|
editorProps={{ $blockScrolling: true }}
|
||||||
value={value}
|
value={value}
|
||||||
readOnly
|
readOnly={readOnly}
|
||||||
fontSize="11pt"
|
fontSize="11pt"
|
||||||
width={`${width}px`}
|
width={`${width}px`}
|
||||||
height={`${height}px`}
|
height={`${height}px`}
|
||||||
|
|||||||
23
packages/web/src/tabs/QueryTab.js
Normal file
23
packages/web/src/tabs/QueryTab.js
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import engines from '@dbgate/engines';
|
||||||
|
import useTableInfo from '../utility/useTableInfo';
|
||||||
|
import useConnectionInfo from '../utility/useConnectionInfo';
|
||||||
|
import SqlEditor from '../sqleditor/SqlEditor';
|
||||||
|
|
||||||
|
export default function QueryTab({ conid, database, schemaName, pureName, tabVisible }) {
|
||||||
|
const [queryText, setQueryText] = React.useState('');
|
||||||
|
// const tableInfo = useTableInfo({ conid, database, schemaName, pureName });
|
||||||
|
// const connnection = useConnectionInfo(conid);
|
||||||
|
// if (!connnection || !tableInfo) return null;
|
||||||
|
// // console.log(tableInfo);
|
||||||
|
|
||||||
|
// const driver = engines(connnection.engine);
|
||||||
|
// const dmp = driver.createDumper();
|
||||||
|
// if (tableInfo) dmp.createTable(tableInfo);
|
||||||
|
|
||||||
|
const handleChange = text => {
|
||||||
|
setQueryText(text);
|
||||||
|
};
|
||||||
|
|
||||||
|
return <SqlEditor value={queryText} onChange={handleChange} tabVisible={tabVisible} />;
|
||||||
|
}
|
||||||
@@ -14,5 +14,5 @@ export default function TableCreateScriptTab({ conid, database, schemaName, pure
|
|||||||
const dmp = driver.createDumper();
|
const dmp = driver.createDumper();
|
||||||
if (tableInfo) dmp.createTable(tableInfo);
|
if (tableInfo) dmp.createTable(tableInfo);
|
||||||
|
|
||||||
return <SqlEditor engine={connnection && connnection.engine} value={dmp.s} />;
|
return <SqlEditor engine={connnection && connnection.engine} value={dmp.s} readOnly />;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import engines from '@dbgate/engines';
|
|||||||
import getTableInfo from '../utility/getTableInfo';
|
import getTableInfo from '../utility/getTableInfo';
|
||||||
import useUndoReducer from '../utility/useUndoReducer';
|
import useUndoReducer from '../utility/useUndoReducer';
|
||||||
import usePropsCompare from '../utility/usePropsCompare';
|
import usePropsCompare from '../utility/usePropsCompare';
|
||||||
|
import { useUpdateDatabaseForTab } from '../utility/globalState';
|
||||||
|
|
||||||
export default function TableDataTab({ conid, database, schemaName, pureName, tabVisible, toolbarPortalRef }) {
|
export default function TableDataTab({ conid, database, schemaName, pureName, tabVisible, toolbarPortalRef }) {
|
||||||
const tableInfo = useTableInfo({ conid, database, schemaName, pureName });
|
const tableInfo = useTableInfo({ conid, database, schemaName, pureName });
|
||||||
@@ -17,8 +18,7 @@ export default function TableDataTab({ conid, database, schemaName, pureName, ta
|
|||||||
const [cache, setCache] = React.useState(createGridCache());
|
const [cache, setCache] = React.useState(createGridCache());
|
||||||
const [changeSetState, dispatchChangeSet] = useUndoReducer(createChangeSet());
|
const [changeSetState, dispatchChangeSet] = useUndoReducer(createChangeSet());
|
||||||
|
|
||||||
// console.log('changeSet', changeSet);
|
useUpdateDatabaseForTab(tabVisible, conid, database);
|
||||||
|
|
||||||
const connection = useConnectionInfo(conid);
|
const connection = useConnectionInfo(conid);
|
||||||
|
|
||||||
// usePropsCompare({ tableInfo, connection, config, cache });
|
// usePropsCompare({ tableInfo, connection, config, cache });
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
import TableDataTab from './TableDataTab';
|
import TableDataTab from './TableDataTab';
|
||||||
import TableStructureTab from './TableStructureTab';
|
import TableStructureTab from './TableStructureTab';
|
||||||
import TableCreateScriptTab from './TableCreateScriptTab'
|
import TableCreateScriptTab from './TableCreateScriptTab';
|
||||||
|
import QueryTab from './QueryTab';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
TableDataTab,
|
TableDataTab,
|
||||||
TableStructureTab,
|
TableStructureTab,
|
||||||
TableCreateScriptTab,
|
TableCreateScriptTab,
|
||||||
|
QueryTab,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
|
import _ from 'lodash';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import useStorage from './useStorage';
|
import useStorage from './useStorage';
|
||||||
|
import useConnectionInfo from './useConnectionInfo';
|
||||||
|
|
||||||
function createGlobalState(defaultValue) {
|
function createGlobalState(defaultValue) {
|
||||||
const Context = React.createContext(null);
|
const Context = React.createContext(null);
|
||||||
@@ -42,8 +44,30 @@ function createStorageState(storageKey, defaultValue) {
|
|||||||
const [CurrentWidgetProvider, useCurrentWidget, useSetCurrentWidget] = createGlobalState('database');
|
const [CurrentWidgetProvider, useCurrentWidget, useSetCurrentWidget] = createGlobalState('database');
|
||||||
export { CurrentWidgetProvider, useCurrentWidget, useSetCurrentWidget };
|
export { CurrentWidgetProvider, useCurrentWidget, useSetCurrentWidget };
|
||||||
|
|
||||||
const [CurrentDatabaseProvider, useCurrentDatabase, useSetCurrentDatabase] = createGlobalState(null);
|
const [CurrentDatabaseProvider, useCurrentDatabase, useSetCurrentDatabaseCore] = createGlobalState(null);
|
||||||
|
|
||||||
|
function useSetCurrentDatabase() {
|
||||||
|
const setDb = useSetCurrentDatabaseCore();
|
||||||
|
const db = useCurrentDatabase();
|
||||||
|
return value => {
|
||||||
|
if (_.get(db, 'name') !== _.get(value, 'name') || _.get(db, 'connection._id') != _.get(value, 'connection._id')) {
|
||||||
|
setDb(value);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export { CurrentDatabaseProvider, useCurrentDatabase, useSetCurrentDatabase };
|
export { CurrentDatabaseProvider, useCurrentDatabase, useSetCurrentDatabase };
|
||||||
|
|
||||||
const [OpenedTabsProvider, useOpenedTabs, useSetOpenedTabs] = createStorageState('openedTabs', []);
|
const [OpenedTabsProvider, useOpenedTabs, useSetOpenedTabs] = createStorageState('openedTabs', []);
|
||||||
export { OpenedTabsProvider, useOpenedTabs, useSetOpenedTabs };
|
export { OpenedTabsProvider, useOpenedTabs, useSetOpenedTabs };
|
||||||
|
|
||||||
|
export function useUpdateDatabaseForTab(tabVisible, conid, database) {
|
||||||
|
const connection = useConnectionInfo(conid);
|
||||||
|
const setDb = useSetCurrentDatabase();
|
||||||
|
if (tabVisible && connection) {
|
||||||
|
setDb({
|
||||||
|
name: database,
|
||||||
|
connection,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
43
packages/web/src/widgets/StatusBar.js
Normal file
43
packages/web/src/widgets/StatusBar.js
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import styled from 'styled-components';
|
||||||
|
|
||||||
|
import { getEngineIcon } from '../icons';
|
||||||
|
import { useCurrentDatabase } from '../utility/globalState';
|
||||||
|
|
||||||
|
const Container = styled.div`
|
||||||
|
display: flex;
|
||||||
|
color: white;
|
||||||
|
align-items: stretch;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const Item = styled.div`
|
||||||
|
padding: 2px 10px;
|
||||||
|
// margin: auto;
|
||||||
|
// flex-grow: 0;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export default function StatusBar() {
|
||||||
|
const { name, connection } = useCurrentDatabase() || {};
|
||||||
|
const { displayName, server, user, engine } = connection || {};
|
||||||
|
const EngineIcon = getEngineIcon(engine);
|
||||||
|
return (
|
||||||
|
<Container>
|
||||||
|
{name && (
|
||||||
|
<Item>
|
||||||
|
<i className="fas fa-database" /> {name}
|
||||||
|
</Item>
|
||||||
|
)}
|
||||||
|
{(displayName || server) && (
|
||||||
|
<Item>
|
||||||
|
<EngineIcon size={12} /> {displayName || server}
|
||||||
|
</Item>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{user && (
|
||||||
|
<Item>
|
||||||
|
<i className="fas fa-user" /> {user}
|
||||||
|
</Item>
|
||||||
|
)}
|
||||||
|
</Container>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -3,6 +3,7 @@ import useModalState from '../modals/useModalState';
|
|||||||
import ConnectionModal from '../modals/ConnectionModal';
|
import ConnectionModal from '../modals/ConnectionModal';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
import ToolbarButton from './ToolbarButton';
|
import ToolbarButton from './ToolbarButton';
|
||||||
|
import useNewQuery from '../query/useNewQuery';
|
||||||
|
|
||||||
const ToolbarContainer = styled.div`
|
const ToolbarContainer = styled.div`
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -11,11 +12,13 @@ const ToolbarContainer = styled.div`
|
|||||||
|
|
||||||
export default function ToolBar({ toolbarPortalRef }) {
|
export default function ToolBar({ toolbarPortalRef }) {
|
||||||
const modalState = useModalState();
|
const modalState = useModalState();
|
||||||
|
const newQuery = useNewQuery();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ToolbarContainer>
|
<ToolbarContainer>
|
||||||
<ConnectionModal modalState={modalState} />
|
<ConnectionModal modalState={modalState} />
|
||||||
<ToolbarButton onClick={modalState.open}>Add connection</ToolbarButton>
|
<ToolbarButton onClick={modalState.open}>Add connection</ToolbarButton>
|
||||||
|
<ToolbarButton onClick={newQuery}>Query</ToolbarButton>
|
||||||
<ToolbarContainer ref={toolbarPortalRef}></ToolbarContainer>
|
<ToolbarContainer ref={toolbarPortalRef}></ToolbarContainer>
|
||||||
</ToolbarContainer>
|
</ToolbarContainer>
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user