mirror of
https://github.com/portainer/portainer.git
synced 2025-08-03 04:45:21 +02:00
feat(edge): EE-4621 support high latency for tunnel (#8302)
This commit is contained in:
parent
07df4b1591
commit
60275dd31c
8 changed files with 111 additions and 23 deletions
|
@ -1,4 +1,4 @@
|
|||
import { ReactNode } from 'react';
|
||||
import { ReactNode, useEffect, useState, useRef } from 'react';
|
||||
|
||||
import { Button } from '@@/buttons';
|
||||
|
||||
|
@ -26,6 +26,37 @@ export function Dialog<T>({
|
|||
}: Props<T>) {
|
||||
const ariaLabel = requireString(title) || requireString(message) || 'Dialog';
|
||||
|
||||
const [count, setCount] = useState<number>(0);
|
||||
const countRef = useRef(count);
|
||||
countRef.current = count;
|
||||
|
||||
useEffect(() => {
|
||||
let retFn;
|
||||
|
||||
// only countdown the first button with non-zero timeout
|
||||
for (let i = 0; i < buttons.length; i++) {
|
||||
const button = buttons[i];
|
||||
if (button.timeout) {
|
||||
setCount(button.timeout as number);
|
||||
|
||||
const intervalID = setInterval(() => {
|
||||
const count = countRef.current;
|
||||
|
||||
setCount(count - 1);
|
||||
if (count === 1) {
|
||||
onSubmit(button.value);
|
||||
}
|
||||
}, 1000);
|
||||
|
||||
retFn = () => clearInterval(intervalID);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return retFn;
|
||||
}, [buttons, onSubmit]);
|
||||
|
||||
return (
|
||||
<Modal onDismiss={() => onSubmit()} aria-label={ariaLabel}>
|
||||
{title && <Modal.Header title={title} modalType={modalType} />}
|
||||
|
@ -39,7 +70,7 @@ export function Dialog<T>({
|
|||
key={index}
|
||||
size="medium"
|
||||
>
|
||||
{button.label}
|
||||
{button.label} {button.timeout && count ? `(${count})` : null}
|
||||
</Button>
|
||||
))}
|
||||
</Modal.Footer>
|
||||
|
|
|
@ -7,6 +7,7 @@ export interface ButtonOptions<TValue = undefined> {
|
|||
className?: string;
|
||||
color?: ComponentProps<typeof Button>['color'];
|
||||
value?: TValue;
|
||||
timeout?: number;
|
||||
}
|
||||
|
||||
export interface ButtonsOptions<T> {
|
||||
|
|
|
@ -6,9 +6,10 @@ import { ButtonOptions } from './types';
|
|||
|
||||
export function buildConfirmButton(
|
||||
label = 'Confirm',
|
||||
color: ComponentProps<typeof Button>['color'] = 'primary'
|
||||
color: ComponentProps<typeof Button>['color'] = 'primary',
|
||||
timeout = 0
|
||||
): ButtonOptions<true> {
|
||||
return { label, color, value: true };
|
||||
return { label, color, value: true, timeout };
|
||||
}
|
||||
|
||||
export function buildCancelButton(label = 'Cancel'): ButtonOptions<false> {
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
height: 100%;
|
||||
text-align: center;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { useRouter } from '@uirouter/react';
|
||||
import { useState } from 'react';
|
||||
import { useCurrentStateAndParams, useRouter } from '@uirouter/react';
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
import { Environment } from '@/react/portainer/environments/types';
|
||||
import { snapshotEndpoints } from '@/react/portainer/environments/environment.service';
|
||||
|
@ -9,6 +9,7 @@ import * as notifications from '@/portainer/services/notifications';
|
|||
import { confirm } from '@@/modals/confirm';
|
||||
import { PageHeader } from '@@/PageHeader';
|
||||
import { ModalType } from '@@/modals';
|
||||
import { buildConfirmButton } from '@@/modals/utils';
|
||||
|
||||
import { EnvironmentList } from './EnvironmentList';
|
||||
import { EdgeLoadingSpinner } from './EdgeLoadingSpinner';
|
||||
|
@ -17,10 +18,37 @@ import { LicenseNodePanel } from './LicenseNodePanel';
|
|||
import { BackupFailedPanel } from './BackupFailedPanel';
|
||||
|
||||
export function HomeView() {
|
||||
const [connectingToEdgeEndpoint, setConnectingToEdgeEndpoint] =
|
||||
useState(false);
|
||||
const { params } = useCurrentStateAndParams();
|
||||
const [connectingToEdgeEndpoint, setConnectingToEdgeEndpoint] = useState(
|
||||
!!params.redirect
|
||||
);
|
||||
|
||||
const router = useRouter();
|
||||
|
||||
useEffect(() => {
|
||||
async function redirect() {
|
||||
const options = {
|
||||
title: `Failed connecting to ${params.environmentName}`,
|
||||
message: `There was an issue connecting to edge agent via tunnel. Click 'Retry' below to retry now, or wait 10 seconds to automatically retry.`,
|
||||
confirmButton: buildConfirmButton('Retry', 'primary', 10),
|
||||
modalType: ModalType.Destructive,
|
||||
};
|
||||
|
||||
if (await confirm(options)) {
|
||||
setConnectingToEdgeEndpoint(true);
|
||||
router.stateService.go(params.route, {
|
||||
endpointId: params.environmentId,
|
||||
});
|
||||
} else {
|
||||
router.stateService.go('portainer.home', {}, { inherit: false });
|
||||
}
|
||||
}
|
||||
|
||||
if (params.redirect) {
|
||||
redirect();
|
||||
}
|
||||
}, [params, setConnectingToEdgeEndpoint, router]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<PageHeader
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue