mirror of
https://github.com/DeNNiiInc/dbgate.git
synced 2026-04-20 03:06:00 +00:00
remove web
This commit is contained in:
@@ -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 (
|
||||
<MainContainer ref={mainDiv} theme={theme}>
|
||||
<StyledTable theme={theme}>
|
||||
<tr>
|
||||
<StyledHeader theme={theme}>Number</StyledHeader>
|
||||
<StyledHeader theme={theme}>Message</StyledHeader>
|
||||
<StyledHeader theme={theme}>Time</StyledHeader>
|
||||
<StyledHeader theme={theme}>Delta</StyledHeader>
|
||||
<StyledHeader theme={theme}>Duration</StyledHeader>
|
||||
{showProcedure && <StyledHeader theme={theme}>Procedure</StyledHeader>}
|
||||
{showLine && <StyledHeader theme={theme}>Line</StyledHeader>}
|
||||
</tr>
|
||||
{items.map((row, index) => (
|
||||
// @ts-ignore
|
||||
<StyledRow key={index} severity={row.severity} line={row.line} onClick={() => handleClick(row)} theme={theme}>
|
||||
<StyledCell theme={theme}>{index + 1}</StyledCell>
|
||||
<StyledCell theme={theme}>{row.message}</StyledCell>
|
||||
<StyledCell theme={theme}>{moment(row.time).format('HH:mm:ss')}</StyledCell>
|
||||
<StyledCell theme={theme}>{formatDuration(new Date(row.time).getTime() - time0)}</StyledCell>
|
||||
<StyledCell theme={theme}>
|
||||
{index > 0
|
||||
? formatDuration(new Date(row.time).getTime() - new Date(items[index - 1].time).getTime())
|
||||
: 'n/a'}
|
||||
</StyledCell>
|
||||
{showProcedure && <StyledCell theme={theme}>{row.procedure}</StyledCell>}
|
||||
{showLine && <StyledCell theme={theme}>{row.line}</StyledCell>}
|
||||
</StyledRow>
|
||||
))}
|
||||
</StyledTable>
|
||||
</MainContainer>
|
||||
);
|
||||
}
|
||||
|
||||
export default React.memo(MessagesView);
|
||||
@@ -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 (
|
||||
<>
|
||||
<ToolbarButton disabled={!isDatabaseDefined || busy} onClick={execute} icon="icon run">
|
||||
Execute
|
||||
</ToolbarButton>
|
||||
{/* <ToolbarButton disabled={!busy} onClick={cancel} icon="icon close">
|
||||
Cancel
|
||||
</ToolbarButton> */}
|
||||
<ToolbarButton disabled={!isConnected} onClick={kill} icon="icon close">
|
||||
Kill
|
||||
</ToolbarButton>
|
||||
{/* {hasPermission('files/sql/write') && (
|
||||
<ToolbarButton onClick={save} icon="icon save">
|
||||
Save
|
||||
</ToolbarButton>
|
||||
)} */}
|
||||
<ToolbarButton onClick={format} icon="icon format-code">
|
||||
Format
|
||||
</ToolbarButton>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -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 <ErrorInfo message="No output files" icon="img alert" />;
|
||||
}
|
||||
|
||||
return (
|
||||
<TableControl rows={files}>
|
||||
<TableColumn fieldName="name" header="Name" />
|
||||
<TableColumn fieldName="size" header="Size" formatter={row => formatFileSize(row.size)} />
|
||||
{!electron && (
|
||||
<TableColumn
|
||||
fieldName="download"
|
||||
header="Download"
|
||||
formatter={row => (
|
||||
<a href={`${resolveApi()}/runners/data/${runnerId}/${row.name}`} target="_blank" rel="noopener noreferrer">
|
||||
download
|
||||
</a>
|
||||
)}
|
||||
/>
|
||||
)}
|
||||
{electron && (
|
||||
<TableColumn
|
||||
fieldName="copy"
|
||||
header="Copy"
|
||||
formatter={row => (
|
||||
<a
|
||||
href="#"
|
||||
onClick={() => {
|
||||
const file = electron.remote.dialog.showSaveDialogSync(electron.remote.getCurrentWindow(), {});
|
||||
if (file) {
|
||||
const fs = window.require('fs');
|
||||
fs.copyFile(row.path, file, () => {});
|
||||
}
|
||||
}}
|
||||
>
|
||||
save
|
||||
</a>
|
||||
)}
|
||||
/>
|
||||
)}
|
||||
{electron && (
|
||||
<TableColumn
|
||||
fieldName="show"
|
||||
header="Show"
|
||||
formatter={row => (
|
||||
<a
|
||||
href="#"
|
||||
onClick={() => {
|
||||
electron.remote.shell.showItemInFolder(row.path);
|
||||
}}
|
||||
>
|
||||
show
|
||||
</a>
|
||||
)}
|
||||
/>
|
||||
)}
|
||||
</TableControl>
|
||||
);
|
||||
}
|
||||
@@ -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 (
|
||||
<HorizontalSplitter>
|
||||
<Container>
|
||||
<WidgetTitle>Messages</WidgetTitle>
|
||||
<SocketMessagesView eventName={runnerId ? `runner-info-${runnerId}` : null} executeNumber={executeNumber} />
|
||||
</Container>
|
||||
<Container>
|
||||
<WidgetTitle>Output files</WidgetTitle>
|
||||
<RunnerOutputFiles runnerId={runnerId} executeNumber={executeNumber} />
|
||||
</Container>
|
||||
</HorizontalSplitter>
|
||||
);
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
import React from 'react';
|
||||
import ToolbarButton from '../widgets/ToolbarButton';
|
||||
|
||||
export default function ShellToolbar({ execute, cancel, busy, edit, editAvailable }) {
|
||||
return (
|
||||
<>
|
||||
<ToolbarButton disabled={busy} onClick={execute} icon="icon run">
|
||||
Execute
|
||||
</ToolbarButton>
|
||||
<ToolbarButton disabled={!busy} onClick={cancel} icon="icon close">
|
||||
Cancel
|
||||
</ToolbarButton>
|
||||
<ToolbarButton disabled={!editAvailable} onClick={edit} icon="icon show-wizard">
|
||||
Show wizard
|
||||
</ToolbarButton>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -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 <ErrorInfo message="No messages" icon="img alert" />;
|
||||
}
|
||||
|
||||
return (
|
||||
<MessagesView
|
||||
items={displayedMessages}
|
||||
onMessageClick={onMessageClick}
|
||||
showProcedure={showProcedure}
|
||||
showLine={showLine}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@@ -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 }
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user