query - basic print workflow - messages on client

This commit is contained in:
Jan Prochazka
2020-04-05 20:48:04 +02:00
parent 3df4e9b7dc
commit 72375ec635
13 changed files with 315 additions and 24 deletions

View File

@@ -0,0 +1,24 @@
import React from 'react';
export default function MessagesView({ items }) {
return (
<table>
<tr>
<th>Number</th>
<th>Message</th>
<th>Time</th>
<th>Procedure</th>
<th>Line</th>
</tr>
{items.map((row, index) => (
<tr key={index}>
<td>{index + 1}</td>
<td>{row.message}</td>
<td>{row.time}</td>
<td>{row.procedure}</td>
<td>{row.line}</td>
</tr>
))}
</table>
);
}

View File

@@ -1,8 +1,10 @@
import React from 'react'
import ToolbarButton from '../widgets/ToolbarButton'
import React from 'react';
import ToolbarButton from '../widgets/ToolbarButton';
export default function QueryToolbar() {
return <>
<ToolbarButton onClick={()=>{}}>Execute</ToolbarButton>
export default function QueryToolbar({ execute,isDatabaseDefined }) {
return (
<>
<ToolbarButton disabled={!isDatabaseDefined} onClick={execute}>Execute</ToolbarButton>
</>
}
);
}

View File

@@ -0,0 +1,21 @@
import React from 'react';
import MessagesView from './MessagesView';
import useSocket from '../utility/SocketProvider';
export default function SessionMessagesView({ sessionId }) {
const [messages, setMessages] = React.useState([]);
const socket = useSocket();
const handleInfo = React.useCallback((info) => setMessages((items) => [...items, info]), []);
React.useEffect(() => {
if (sessionId && socket) {
socket.on(`session-info-${sessionId}`, handleInfo);
return () => {
socket.off(`session-info-${sessionId}`, handleInfo);
};
}
}, [sessionId, socket]);
return <MessagesView items={messages} />;
}

View File

@@ -1,17 +1,30 @@
import React from 'react';
import ReactDOM from 'react-dom';
import _ from 'lodash';
import axios from '../utility/axios';
import engines from '@dbgate/engines';
import useTableInfo from '../utility/useTableInfo';
import useConnectionInfo from '../utility/useConnectionInfo';
import SqlEditor from '../sqleditor/SqlEditor';
import { useUpdateDatabaseForTab } from '../utility/globalState';
import QueryToolbar from '../query/QueryToolbar';
import styled from 'styled-components';
import SessionMessagesView from '../query/SessionMessagesView';
const MainContainer = styled.div``;
const EditorContainer = styled.div`
height: 600px;
position: relative;
`;
const MessagesContainer = styled.div``;
export default function QueryTab({ tabid, conid, database, tabVisible, toolbarPortalRef }) {
const localStorageKey = `sql_${tabid}`;
const [queryText, setQueryText] = React.useState(() => localStorage.getItem(localStorageKey) || '');
const queryTextRef = React.useRef(queryText);
const [sessionId, setSessionId] = React.useState(null);
const saveToStorage = React.useCallback(() => localStorage.setItem(localStorageKey, queryTextRef.current), [
localStorageKey,
@@ -22,26 +35,57 @@ export default function QueryTab({ tabid, conid, database, tabVisible, toolbarPo
React.useEffect(() => {
window.addEventListener('beforeunload', saveToStorage);
return () => {
saveToStorage();
window.removeEventListener('beforeunload', saveToStorage);
};
}, []);
useUpdateDatabaseForTab(tabVisible, conid, database);
const connection = useConnectionInfo(conid);
const handleChange = text => {
const handleChange = (text) => {
if (text != null) queryTextRef.current = text;
setQueryText(text);
saveToStorageDebounced();
};
return (
<>
<SqlEditor value={queryText} onChange={handleChange} tabVisible={tabVisible} />
const handleExecute = async () => {
let sesid = sessionId;
if (!sesid) {
const resp = await axios.post('sessions/create', {
conid,
database,
});
sesid = resp.data.sesid;
setSessionId(sesid);
}
const resp2 = await axios.post('sessions/execute-query', {
sesid,
sql: queryText,
});
};
{toolbarPortalRef &&
toolbarPortalRef.current &&
tabVisible &&
ReactDOM.createPortal(<QueryToolbar />, toolbarPortalRef.current)}
</>
return (
<MainContainer>
<EditorContainer>
<SqlEditor
value={queryText}
onChange={handleChange}
tabVisible={tabVisible}
engine={connection && connection.engine}
/>
{toolbarPortalRef &&
toolbarPortalRef.current &&
tabVisible &&
ReactDOM.createPortal(
<QueryToolbar isDatabaseDefined={conid && database} execute={handleExecute} />,
toolbarPortalRef.current
)}
</EditorContainer>
<MessagesContainer>
<SessionMessagesView sessionId={sessionId} />
</MessagesContainer>
</MainContainer>
);
}

View File

@@ -16,9 +16,9 @@ export default function useFetch({
const [loadCounter, setLoadCounter] = React.useState(0);
const socket = useSocket();
const handleReload = () => {
setLoadCounter(loadCounter + 1);
};
const handleReload = React.useCallback(() => {
setLoadCounter((counter) => counter + 1);
}, []);
const indicators = [url, stableStringify(data), stableStringify(params), loadCounter];
@@ -32,15 +32,29 @@ export default function useFetch({
});
setValue([resp.data, loadedIndicators]);
}
// React.useEffect(() => {
// loadValue(indicators);
// if (reloadTrigger && socket) {
// socket.on(reloadTrigger, handleReload);
// return () => {
// socket.off(reloadTrigger, handleReload);
// };
// }
// }, [...indicators, socket]);
React.useEffect(() => {
loadValue(indicators);
}, [...indicators]);
React.useEffect(() => {
if (reloadTrigger && socket) {
socket.on(reloadTrigger, handleReload);
return () => {
socket.off(reloadTrigger, handleReload);
};
}
}, [...indicators, socket]);
}, [socket, reloadTrigger]);
const [returnValue, loadedIndicators] = value;
if (_.isEqual(indicators, loadedIndicators)) return returnValue;