statusbar - show query execution duration

This commit is contained in:
Jan Prochazka 2021-01-28 12:49:00 +01:00
parent 8396e726ec
commit 51ba9d3b5a
5 changed files with 128 additions and 53 deletions

View File

@ -100,6 +100,7 @@ export default function Screen() {
? 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();
@ -131,10 +132,10 @@ export default function Screen() {
<TabsPanel></TabsPanel>
</TabsPanelContainer>
<BodyDiv contentLeft={contentLeft} theme={theme}>
<TabContent toolbarPortalRef={toolbarPortalRef} />
<TabContent toolbarPortalRef={toolbarPortalRef} statusbarPortalRef={statusbarPortalRef} />
</BodyDiv>
<StausBarContainer theme={theme}>
<StatusBar />
<StatusBar statusbarPortalRef={statusbarPortalRef} />
</StausBarContainer>
<ModalLayer />
<MenuLayer />

View File

@ -18,12 +18,18 @@ const TabContainerStyled = styled.div`
`;
function TabContainer({ TabComponent, ...props }) {
const { tabVisible, tabid, toolbarPortalRef } = props;
const { tabVisible, tabid, toolbarPortalRef, statusbarPortalRef } = props;
return (
// @ts-ignore
<TabContainerStyled tabVisible={tabVisible}>
<ErrorBoundary>
<TabComponent {...props} tabid={tabid} tabVisible={tabVisible} toolbarPortalRef={toolbarPortalRef} />
<TabComponent
{...props}
tabid={tabid}
tabVisible={tabVisible}
toolbarPortalRef={toolbarPortalRef}
statusbarPortalRef={statusbarPortalRef}
/>
</ErrorBoundary>
</TabContainerStyled>
);
@ -42,7 +48,7 @@ function createTabComponent(selectedTab) {
return null;
}
export default function TabContent({ toolbarPortalRef }) {
export default function TabContent({ toolbarPortalRef, statusbarPortalRef }) {
const files = useOpenedTabs();
const [mountedTabs, setMountedTabs] = React.useState({});
@ -84,6 +90,7 @@ export default function TabContent({ toolbarPortalRef }) {
tabid={tabid}
tabVisible={tabVisible}
toolbarPortalRef={toolbarPortalRef}
statusbarPortalRef={statusbarPortalRef}
TabComponent={TabComponent}
/>
);

View File

@ -21,8 +21,19 @@ 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';
export default function QueryTab({ tabid, conid, database, initialArgs, tabVisible, toolbarPortalRef, ...other }) {
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);
@ -31,6 +42,7 @@ export default function QueryTab({ tabid, conid, database, initialArgs, tabVisib
const [busy, setBusy] = React.useState(false);
const saveFileModalState = useModalState();
const extensions = useExtensions();
const timerLabel = useTimerLabel();
const { editorData, setEditorData, isLoading } = useEditorData({
tabid,
loadFromArgs:
@ -43,6 +55,7 @@ export default function QueryTab({ tabid, conid, database, initialArgs, tabVisib
const handleSessionDone = React.useCallback(() => {
setBusy(false);
timerLabel.stop();
}, []);
React.useEffect(() => {
@ -77,6 +90,7 @@ export default function QueryTab({ tabid, conid, database, initialArgs, tabVisib
setSessionId(sesid);
}
setBusy(true);
timerLabel.start();
await axios.post('sessions/execute-query', {
sesid,
sql: selectedText || editorData,
@ -95,6 +109,7 @@ export default function QueryTab({ tabid, conid, database, initialArgs, tabVisib
});
setSessionId(null);
setBusy(false);
timerLabel.stop();
};
const handleKeyDown = (data, hash, keyString, keyCode, event) => {
@ -167,6 +182,10 @@ export default function QueryTab({ tabid, conid, database, initialArgs, tabVisib
/>,
toolbarPortalRef.current
)}
{statusbarPortalRef &&
statusbarPortalRef.current &&
tabVisible &&
ReactDOM.createPortal(<StatusBarItem>{timerLabel.text}</StatusBarItem>, statusbarPortalRef.current)}
<SaveTabModal
modalState={saveFileModalState}
tabVisible={tabVisible}

View File

@ -0,0 +1,37 @@
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,
};
}

View File

@ -10,9 +10,10 @@ const Container = styled.div`
display: flex;
color: ${props => props.theme.statusbar_font1};
align-items: stretch;
justify-content: space-between;
`;
const Item = styled.div`
export const StatusBarItem = styled.div`
padding: 2px 10px;
// margin: auto;
// flex-grow: 0;
@ -30,62 +31,72 @@ const InfoWrapper = styled.span`
props.theme.statusbar_font_green[5]};
`;
export default function StatusBar() {
const StatusbarContainer = styled.div`
display: flex;
// align-items: flex-end;
// display: flex;
// user-select: none;
`;
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 (
<Container theme={theme}>
{name && (
<Item>
<FontIcon icon="icon database" /> {name}
</Item>
)}
{(displayName || server) && (
<Item>
<FontIcon icon="icon server" /> {displayName || server}
</Item>
)}
<StatusbarContainer>
{name && (
<StatusBarItem>
<FontIcon icon="icon database" /> {name}
</StatusBarItem>
)}
{(displayName || server) && (
<StatusBarItem>
<FontIcon icon="icon server" /> {displayName || server}
</StatusBarItem>
)}
{user && (
<Item>
<FontIcon icon="icon account" /> {user}
</Item>
)}
{user && (
<StatusBarItem>
<FontIcon icon="icon account" /> {user}
</StatusBarItem>
)}
{connection && status && (
<Item>
{status.name == 'pending' && (
{connection && status && (
<StatusBarItem>
{status.name == 'pending' && (
<>
<FontIcon icon="icon loading" /> Loading
</>
)}
{status.name == 'ok' && (
<>
<InfoWrapper theme={theme}>
<FontIcon icon="icon ok" />
</InfoWrapper>{' '}
Connected
</>
)}
{status.name == 'error' && (
<>
<ErrorWrapper theme={theme}>
<FontIcon icon="icon error" />
</ErrorWrapper>{' '}
Error
</>
)}
</StatusBarItem>
)}
{!connection && (
<StatusBarItem>
<>
<FontIcon icon="icon loading" /> Loading
<FontIcon icon="icon disconnected" /> Not connected
</>
)}
{status.name == 'ok' && (
<>
<InfoWrapper theme={theme}>
<FontIcon icon="icon ok" />
</InfoWrapper>{' '}
Connected
</>
)}
{status.name == 'error' && (
<>
<ErrorWrapper theme={theme}>
<FontIcon icon="icon error" />
</ErrorWrapper>{' '}
Error
</>
)}
</Item>
)}
{!connection && (
<Item>
<>
<FontIcon icon="icon disconnected" /> Not connected
</>
</Item>
)}
</StatusBarItem>
)}
</StatusbarContainer>
<StatusbarContainer ref={statusbarPortalRef}></StatusbarContainer>
</Container>
);
}