mirror of
https://github.com/Azure/cosmos-explorer.git
synced 2025-03-13 05:15:30 +00:00
190 lines
7.4 KiB
TypeScript
190 lines
7.4 KiB
TypeScript
import {
|
|
FocusTrapCallout,
|
|
FocusZone,
|
|
FocusZoneTabbableElements,
|
|
FontWeights,
|
|
Icon,
|
|
mergeStyleSets,
|
|
ProgressIndicator,
|
|
Stack,
|
|
Text,
|
|
TooltipHost,
|
|
} from "@fluentui/react";
|
|
import { useId } from "@fluentui/react-hooks";
|
|
import { ActionButton, DefaultButton } from "@fluentui/react/lib/Button";
|
|
import * as React from "react";
|
|
import "../../../../less/hostedexplorer.less";
|
|
import { ConnectionStatusType, ContainerStatusType, Notebook, PoolIdType } from "../../../Common/Constants";
|
|
import Explorer from "../../Explorer";
|
|
import { useNotebook } from "../../Notebook/useNotebook";
|
|
import "../CommandBar/ConnectionStatusComponent.less";
|
|
interface Props {
|
|
container: Explorer;
|
|
poolId: PoolIdType;
|
|
}
|
|
export const ConnectionStatus: React.FC<Props> = ({ container, poolId }: Props): JSX.Element => {
|
|
const connectionInfo = useNotebook((state) => state.connectionInfo);
|
|
const [second, setSecond] = React.useState("00");
|
|
const [minute, setMinute] = React.useState("00");
|
|
const [isActive, setIsActive] = React.useState(false);
|
|
const [counter, setCounter] = React.useState(0);
|
|
const [statusColor, setStatusColor] = React.useState("");
|
|
const [toolTipContent, setToolTipContent] = React.useState("Connect to temporary workspace.");
|
|
const [isBarDismissed, setIsBarDismissed] = React.useState<boolean>(false);
|
|
const buttonId = useId("callout-button");
|
|
const containerInfo = useNotebook((state) => state.containerStatus);
|
|
|
|
const styles = mergeStyleSets({
|
|
callout: {
|
|
width: 320,
|
|
padding: "20px 24px",
|
|
},
|
|
title: {
|
|
marginBottom: 12,
|
|
fontWeight: FontWeights.semilight,
|
|
},
|
|
buttons: {
|
|
display: "flex",
|
|
justifyContent: "flex-end",
|
|
marginTop: 20,
|
|
},
|
|
});
|
|
|
|
React.useEffect(() => {
|
|
let intervalId: NodeJS.Timeout;
|
|
|
|
if (isActive) {
|
|
intervalId = setInterval(() => {
|
|
const secondCounter = counter % 60;
|
|
const minuteCounter = Math.floor(counter / 60);
|
|
const computedSecond: string = String(secondCounter).length === 1 ? `0${secondCounter}` : `${secondCounter}`;
|
|
const computedMinute: string = String(minuteCounter).length === 1 ? `0${minuteCounter}` : `${minuteCounter}`;
|
|
|
|
setSecond(computedSecond);
|
|
setMinute(computedMinute);
|
|
|
|
setCounter((counter) => counter + 1);
|
|
}, 1000);
|
|
}
|
|
return () => clearInterval(intervalId);
|
|
}, [isActive, counter]);
|
|
|
|
React.useEffect(() => {
|
|
if (connectionInfo?.status === ConnectionStatusType.Reconnect) {
|
|
setToolTipContent("Click here to Reconnect to temporary workspace.");
|
|
} else if (connectionInfo?.status === ConnectionStatusType.Failed) {
|
|
setStatusColor("status failed is-animating");
|
|
setToolTipContent("Click here to Reconnect to temporary workspace.");
|
|
}
|
|
}, [connectionInfo.status]);
|
|
|
|
const stopTimer = () => {
|
|
setIsActive(false);
|
|
setCounter(0);
|
|
setSecond("00");
|
|
setMinute("00");
|
|
};
|
|
|
|
const memoryUsageInfo = useNotebook((state) => state.memoryUsageInfo);
|
|
const totalGB = memoryUsageInfo ? memoryUsageInfo.totalKB / Notebook.memoryGuageToGB : 0;
|
|
const usedGB = totalGB > 0 ? totalGB - memoryUsageInfo.freeKB / Notebook.memoryGuageToGB : 0;
|
|
|
|
if (
|
|
connectionInfo &&
|
|
(connectionInfo.status === ConnectionStatusType.Connect || connectionInfo.status === ConnectionStatusType.Reconnect)
|
|
) {
|
|
return (
|
|
<ActionButton className="commandReactBtn" onClick={() => container.allocateContainer(poolId)}>
|
|
<TooltipHost content={toolTipContent}>
|
|
<Stack className="connectionStatusContainer" horizontal>
|
|
<Icon iconName="ConnectVirtualMachine" className="connectIcon" />
|
|
<span>{connectionInfo.status}</span>
|
|
</Stack>
|
|
</TooltipHost>
|
|
</ActionButton>
|
|
);
|
|
}
|
|
|
|
if (connectionInfo && connectionInfo.status === ConnectionStatusType.Connecting && isActive === false) {
|
|
stopTimer();
|
|
setIsActive(true);
|
|
setStatusColor("status connecting is-animating");
|
|
setToolTipContent("Connecting to temporary workspace.");
|
|
} else if (connectionInfo && connectionInfo.status === ConnectionStatusType.Connected && isActive === true) {
|
|
stopTimer();
|
|
setStatusColor("status connected is-animating");
|
|
setToolTipContent("Connected to temporary workspace.");
|
|
} else if (connectionInfo && connectionInfo.status === ConnectionStatusType.Failed && isActive === true) {
|
|
stopTimer();
|
|
setStatusColor("status failed is-animating");
|
|
setToolTipContent("Click here to Reconnect to temporary workspace.");
|
|
}
|
|
return (
|
|
<>
|
|
<TooltipHost
|
|
content={
|
|
containerInfo?.status === ContainerStatusType.Active
|
|
? `Connected to temporary workspace. This temporary workspace will get disconnected in ${Math.round(
|
|
containerInfo.durationLeftInMinutes
|
|
)} minutes.`
|
|
: toolTipContent
|
|
}
|
|
>
|
|
<ActionButton
|
|
id={buttonId}
|
|
className={connectionInfo.status === ConnectionStatusType.Failed ? "commandReactBtn" : "connectedReactBtn"}
|
|
onClick={(e: React.MouseEvent<HTMLSpanElement>) =>
|
|
connectionInfo.status === ConnectionStatusType.Failed
|
|
? container.allocateContainer(poolId)
|
|
: e.preventDefault()
|
|
}
|
|
>
|
|
<Stack className="connectionStatusContainer" horizontal>
|
|
<i className={statusColor}></i>
|
|
<span className={connectionInfo.status === ConnectionStatusType.Failed ? "connectionStatusFailed" : ""}>
|
|
{connectionInfo.status}
|
|
</span>
|
|
{connectionInfo.status === ConnectionStatusType.Connecting && isActive && (
|
|
<ProgressIndicator description={minute + ":" + second} />
|
|
)}
|
|
{connectionInfo.status === ConnectionStatusType.Connected && !isActive && (
|
|
<ProgressIndicator
|
|
className={totalGB !== 0 && usedGB / totalGB > 0.8 ? "lowMemory" : ""}
|
|
description={usedGB.toFixed(1) + " of " + totalGB.toFixed(1) + " GB"}
|
|
percentComplete={totalGB !== 0 ? usedGB / totalGB : 0}
|
|
/>
|
|
)}
|
|
</Stack>
|
|
{!isBarDismissed &&
|
|
containerInfo.status &&
|
|
containerInfo.status === ContainerStatusType.Active &&
|
|
Math.round(containerInfo.durationLeftInMinutes) <= Notebook.remainingTimeForAlert ? (
|
|
<FocusTrapCallout
|
|
role="alertdialog"
|
|
className={styles.callout}
|
|
gapSpace={0}
|
|
target={`#${buttonId}`}
|
|
onDismiss={() => setIsBarDismissed(true)}
|
|
setInitialFocus
|
|
>
|
|
<Text block variant="xLarge" className={styles.title}>
|
|
Remaining Time
|
|
</Text>
|
|
<Text block variant="small">
|
|
This temporary workspace will get disconnected in {Math.round(containerInfo.durationLeftInMinutes)}{" "}
|
|
minutes. To save your work permanently, save your notebooks to a GitHub repository or download the
|
|
notebooks to your local machine before the session ends.
|
|
</Text>
|
|
<FocusZone handleTabKey={FocusZoneTabbableElements.all} isCircularNavigation>
|
|
<Stack className={styles.buttons} gap={8} horizontal>
|
|
<DefaultButton onClick={() => setIsBarDismissed(true)}>Dimiss</DefaultButton>
|
|
</Stack>
|
|
</FocusZone>
|
|
</FocusTrapCallout>
|
|
) : undefined}
|
|
</ActionButton>
|
|
</TooltipHost>
|
|
</>
|
|
);
|
|
};
|