mirror of
https://github.com/wavetermdev/waveterm.git
synced 2025-01-02 18:39:05 +01:00
connection status overlay (#337)
This commit is contained in:
parent
11e4f6074d
commit
a00dc5682e
@ -287,39 +287,95 @@
|
||||
|
||||
.connstatus-overlay {
|
||||
position: absolute;
|
||||
top: var(--header-height);
|
||||
left: 2px;
|
||||
right: 2px;
|
||||
background-color: rgba(0, 0, 0, 0.3);
|
||||
top: calc(var(--header-height) + 6px);
|
||||
left: 6px;
|
||||
right: 6px;
|
||||
z-index: var(--zindex-block-mask-inner);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
background: rgba(230, 186, 30, 0.2);
|
||||
backdrop-filter: blur(50px);
|
||||
border-radius: 6px;
|
||||
box-shadow: 0px 13px 16px 0px rgba(0, 0, 0, 0.4);
|
||||
|
||||
.connstatus-mainelem {
|
||||
.connstatus-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 20px;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
padding: 10px 8px 10px 12px;
|
||||
width: 100%;
|
||||
background-color: rgba(60, 60, 60, 0.65);
|
||||
backdrop-filter: blur(3px);
|
||||
font: var(--base-font);
|
||||
color: var(--secondary-text-color);
|
||||
gap: 12px;
|
||||
|
||||
.connstatus-error {
|
||||
color: var(--error-color);
|
||||
.connstatus-status-icon-wrapper {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
flex-grow: 1;
|
||||
min-width: 0;
|
||||
|
||||
&.has-error {
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
> i {
|
||||
color: #e6ba1e;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.connstatus-status {
|
||||
.ellipsis();
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
gap: 4px;
|
||||
flex-grow: 1;
|
||||
width: 100%;
|
||||
|
||||
.connstatus-status-text {
|
||||
.ellipsis();
|
||||
max-width: 100%;
|
||||
font-size: 11px;
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
line-height: 16px;
|
||||
letter-spacing: 0.11px;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.connstatus-error {
|
||||
.ellipsis();
|
||||
width: 94%;
|
||||
font-size: 11px;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: 15px;
|
||||
letter-spacing: 0.11px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.connstatus-actions {
|
||||
margin-top: 10px;
|
||||
display: flex;
|
||||
gap: 5px;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
align-items: flex-start;
|
||||
justify-content: center;
|
||||
gap: 6px;
|
||||
|
||||
button {
|
||||
i {
|
||||
font-size: 11px;
|
||||
opacity: 0.7;
|
||||
}
|
||||
}
|
||||
|
||||
.button:last-child {
|
||||
margin-top: 1.5px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
// Copyright 2024, Command Line Inc.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import { BlockComponentModel } from "@/app/block/blocktypes";
|
||||
import {
|
||||
blockViewToIcon,
|
||||
blockViewToName,
|
||||
@ -12,6 +13,7 @@ import {
|
||||
Input,
|
||||
} from "@/app/block/blockutil";
|
||||
import { Button } from "@/app/element/button";
|
||||
import { useWidth } from "@/app/hook/useWidth";
|
||||
import { TypeAheadModal } from "@/app/modals/typeaheadmodal";
|
||||
import { ContextMenuModel } from "@/app/store/contextmenu";
|
||||
import {
|
||||
@ -264,52 +266,76 @@ function renderHeaderElements(headerTextUnion: HeaderElem[], preview: boolean):
|
||||
|
||||
const ConnStatusOverlay = React.memo(
|
||||
({
|
||||
blockModel,
|
||||
nodeModel,
|
||||
viewModel,
|
||||
changeConnModalAtom,
|
||||
}: {
|
||||
blockModel: BlockComponentModel;
|
||||
nodeModel: NodeModel;
|
||||
viewModel: ViewModel;
|
||||
changeConnModalAtom: jotai.PrimitiveAtom<boolean>;
|
||||
}) => {
|
||||
const [blockData] = WOS.useWaveObjectValue<Block>(WOS.makeORef("block", nodeModel.blockId));
|
||||
const [connModalOpen, setConnModalOpen] = jotai.useAtom(changeConnModalAtom);
|
||||
const [connModalOpen] = jotai.useAtom(changeConnModalAtom);
|
||||
const connName = blockData.meta?.connection;
|
||||
const connStatus = jotai.useAtomValue(getConnStatusAtom(connName));
|
||||
const isLayoutMode = jotai.useAtomValue(atoms.controlShiftDelayAtom);
|
||||
const width = useWidth(blockModel?.blockRef);
|
||||
const [showError, setShowError] = React.useState(false);
|
||||
|
||||
React.useEffect(() => {
|
||||
if (width) {
|
||||
const hasError = !util.isBlank(connStatus.error);
|
||||
const showError = hasError && width >= 250 && connStatus.status != "connecting";
|
||||
setShowError(showError);
|
||||
}
|
||||
}, [width, connStatus, setShowError]);
|
||||
|
||||
const handleTryReconnect = React.useCallback(() => {
|
||||
const prtn = WshServer.ConnConnectCommand(connName, { timeout: 60000 });
|
||||
prtn.catch((e) => console.log("error reconnecting", connName, e));
|
||||
}, [connName]);
|
||||
const handleSwitchConnection = React.useCallback(() => {
|
||||
setConnModalOpen(true);
|
||||
}, [setConnModalOpen]);
|
||||
if (isLayoutMode || connStatus.status == "connected" || connModalOpen) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let statusText = `Disconnected from "${connName}"`;
|
||||
let showReconnect = true;
|
||||
if (connStatus.status == "connecting") {
|
||||
statusText = `Connecting to "${connName}"...`;
|
||||
showReconnect = false;
|
||||
}
|
||||
let reconDisplay = null;
|
||||
let reconClassName = "outlined";
|
||||
if (width && width < 350) {
|
||||
reconDisplay = <i className="fa-sharp fa-solid fa-rotate-right"></i>;
|
||||
reconClassName = clsx(reconClassName, "font-size-12 vertical-padding-5 horizontal-padding-6");
|
||||
} else {
|
||||
reconDisplay = "Reconnect";
|
||||
reconClassName = clsx(reconClassName, "font-size-11 vertical-padding-3 horizontal-padding-7");
|
||||
}
|
||||
const showIcon = connStatus.status != "connecting";
|
||||
|
||||
if (isLayoutMode || connStatus.status == "connected" || connModalOpen) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="connstatus-overlay">
|
||||
<div className="connstatus-mainelem">
|
||||
<div style={{ marginBottom: 5 }}>{statusText}</div>
|
||||
{!util.isBlank(connStatus.error) ? (
|
||||
<div className="connstatus-error">error: {connStatus.error}</div>
|
||||
) : null}
|
||||
<div className="connstatus-content">
|
||||
<div className={clsx("connstatus-status-icon-wrapper", { "has-error": showError })}>
|
||||
{showIcon && <i className="fa-solid fa-triangle-exclamation"></i>}
|
||||
<div className="connstatus-status">
|
||||
<div className="connstatus-status-text">{statusText}</div>
|
||||
{showError ? <div className="connstatus-error">error: {connStatus.error}</div> : null}
|
||||
</div>
|
||||
</div>
|
||||
{showReconnect ? (
|
||||
<div className="connstatus-actions">
|
||||
<Button className="secondary" onClick={handleTryReconnect}>
|
||||
<i className="fa-sharp fa-solid fa-arrow-right-arrow-left" style={{ marginRight: 5 }} />
|
||||
Reconnect Now
|
||||
</Button>
|
||||
<Button className="secondary" onClick={handleSwitchConnection}>
|
||||
<i className="fa-sharp fa-solid fa-arrow-right-arrow-left" style={{ marginRight: 5 }} />
|
||||
Switch Connection
|
||||
<Button className={reconClassName} onClick={handleTryReconnect}>
|
||||
{reconDisplay}
|
||||
</Button>
|
||||
{/* <Button className="secondary ghost vertical-padding-5 horizontal-padding-6">
|
||||
<i className="fa-sharp fa-regular fa-xmark-large"></i>
|
||||
</Button> */}
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
@ -417,7 +443,12 @@ const BlockFrame_Default_Component = (props: BlockFrameProps) => {
|
||||
ref={blockModel?.blockRef}
|
||||
>
|
||||
<BlockMask nodeModel={nodeModel} />
|
||||
<ConnStatusOverlay nodeModel={nodeModel} viewModel={viewModel} changeConnModalAtom={changeConnModalAtom} />
|
||||
<ConnStatusOverlay
|
||||
blockModel={blockModel}
|
||||
nodeModel={nodeModel}
|
||||
viewModel={viewModel}
|
||||
changeConnModalAtom={changeConnModalAtom}
|
||||
/>
|
||||
<div className="block-frame-default-inner" style={innerStyle}>
|
||||
<BlockFrame_Header {...props} connBtnRef={connBtnRef} changeConnModalAtom={changeConnModalAtom} />
|
||||
{preview ? previewElem : children}
|
||||
|
@ -17,7 +17,10 @@
|
||||
cursor: pointer;
|
||||
outline: inherit;
|
||||
display: flex;
|
||||
padding: 8px 20px;
|
||||
padding-top: 8px;
|
||||
padding-bottom: 8px;
|
||||
padding-left: 20px;
|
||||
padding-right: 20px;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
border-radius: 6px;
|
||||
@ -79,6 +82,11 @@
|
||||
color: var(--error-color);
|
||||
}
|
||||
|
||||
&.outlined {
|
||||
background: none;
|
||||
border: 1px solid rgba(255, 255, 255, 0.5);
|
||||
}
|
||||
|
||||
&.disabled {
|
||||
opacity: 0.5;
|
||||
}
|
||||
@ -96,6 +104,86 @@
|
||||
padding-bottom: 2px;
|
||||
}
|
||||
|
||||
.vertical-padding-3 {
|
||||
padding-top: 3px;
|
||||
padding-bottom: 3px;
|
||||
}
|
||||
|
||||
.vertical-padding-4 {
|
||||
padding-top: 4px;
|
||||
padding-bottom: 4px;
|
||||
}
|
||||
|
||||
.vertical-padding-5 {
|
||||
padding-top: 5px;
|
||||
padding-bottom: 5px;
|
||||
}
|
||||
|
||||
.vertical-padding-6 {
|
||||
padding-top: 6px;
|
||||
padding-bottom: 6px;
|
||||
}
|
||||
|
||||
.vertical-padding-7 {
|
||||
padding-top: 7px;
|
||||
padding-bottom: 7px;
|
||||
}
|
||||
|
||||
.vertical-padding-8 {
|
||||
padding-top: 8px;
|
||||
padding-bottom: 8px;
|
||||
}
|
||||
|
||||
.vertical-padding-9 {
|
||||
padding-top: 9px;
|
||||
padding-bottom: 9px;
|
||||
}
|
||||
|
||||
.vertical-padding-10 {
|
||||
padding-top: 10px;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
|
||||
.horizontal-padding-2 {
|
||||
padding-left: 2px;
|
||||
padding-right: 2px;
|
||||
}
|
||||
|
||||
.horizontal-padding-3 {
|
||||
padding-left: 3px;
|
||||
padding-right: 3px;
|
||||
}
|
||||
|
||||
.horizontal-padding-4 {
|
||||
padding-left: 4px;
|
||||
padding-right: 4px;
|
||||
}
|
||||
|
||||
.horizontal-padding-5 {
|
||||
padding-left: 5px;
|
||||
padding-right: 5px;
|
||||
}
|
||||
|
||||
.horizontal-padding-6 {
|
||||
padding-left: 6px;
|
||||
padding-right: 6px;
|
||||
}
|
||||
|
||||
.horizontal-padding-7 {
|
||||
padding-left: 7px;
|
||||
padding-right: 7px;
|
||||
}
|
||||
|
||||
.horizontal-padding-8 {
|
||||
padding-left: 8px;
|
||||
padding-right: 8px;
|
||||
}
|
||||
|
||||
.horizontal-padding-9 {
|
||||
padding-left: 9px;
|
||||
padding-right: 9px;
|
||||
}
|
||||
|
||||
.horizontal-padding-10 {
|
||||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
|
Loading…
Reference in New Issue
Block a user