SynchronizeStep: fix when user can click next when repo is not ready (#111789)

* SynchronizeStep: fix when user can click next when repo is not ready
This commit is contained in:
Yunwen Zheng 2025-10-01 10:31:41 -04:00 committed by GitHub
parent ed7163a26f
commit 3541926e5c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 62 additions and 18 deletions

View File

@ -1,5 +1,5 @@
import { skipToken } from '@reduxjs/toolkit/query';
import { memo, useState } from 'react';
import { memo, useEffect, useState } from 'react';
import { useFormContext } from 'react-hook-form';
import { Trans, t } from '@grafana/i18n';
@ -37,7 +37,15 @@ export const SynchronizeStep = memo(function SynchronizeStep({
setStepStatusInfo,
});
const [job, setJob] = useState<Job>();
const repositoryStatusQuery = useGetRepositoryStatusQuery(repoName ? { name: repoName } : skipToken);
const [shouldEnablePolling, setShouldEnablePolling] = useState(true);
const POLLING_INTERVAL_MS = 5000;
const repositoryStatusQuery = useGetRepositoryStatusQuery(repoName ? { name: repoName } : skipToken, {
// Disable polling by setting interval to 0 when we should stop
pollingInterval: shouldEnablePolling ? POLLING_INTERVAL_MS : 0,
skipPollingIfUnfocused: true,
});
const {
healthy: isRepositoryHealthy,
@ -45,9 +53,21 @@ export const SynchronizeStep = memo(function SynchronizeStep({
checked,
} = repositoryStatusQuery?.data?.status?.health || {};
// healthStatusNotReady: If the repository is not yet ready (e.g., initial setup), synchronization cannot be started.
// User can potentially fail at this step if they click too fast and repo is not ready.
const healthStatusNotReady =
isRepositoryHealthy === false && repositoryStatusQuery?.data?.status?.observedGeneration === 0;
// Stop polling when repository becomes healthy
useEffect(() => {
if (!healthStatusNotReady) {
setShouldEnablePolling(false);
}
}, [healthStatusNotReady]);
const hasError = repositoryStatusQuery.isError;
const isLoading = repositoryStatusQuery.isLoading || repositoryStatusQuery.isFetching;
const isButtonDisabled = hasError || (checked !== undefined && isRepositoryHealthy === false);
const isButtonDisabled = hasError || (checked !== undefined && isRepositoryHealthy === false) || healthStatusNotReady;
const startSynchronization = async () => {
const [history] = getValues(['migrate.history']);
@ -151,21 +171,43 @@ export const SynchronizeStep = memo(function SynchronizeStep({
</>
)}
<Field noMargin>
{hasError || (checked !== undefined && isRepositoryHealthy === false) ? (
<Button variant="destructive" onClick={() => onCancel?.(repoName)} disabled={isCancelling}>
{isCancelling ? (
<Trans i18nKey="provisioning.wizard.button-cancelling">Cancelling...</Trans>
) : (
<Trans i18nKey="provisioning.wizard.button-cancel">Cancel</Trans>
)}
</Button>
) : (
<Button variant="primary" onClick={startSynchronization} disabled={isButtonDisabled}>
<Trans i18nKey="provisioning.wizard.button-start">Begin synchronization</Trans>
</Button>
)}
</Field>
{healthStatusNotReady ? (
<>
<Stack>
<Trans i18nKey="provisioning.wizard.check-status-message">
Repository connecting, synchronize will be ready soon.
</Trans>
</Stack>
<Stack>
<Stack>
<Button
onClick={() => {
repositoryStatusQuery.refetch();
}}
disabled={isLoading}
>
<Trans i18nKey="provisioning.wizard.check-status-button">Check repository status</Trans>
</Button>
</Stack>
</Stack>
</>
) : (
<Field noMargin>
{hasError || (checked !== undefined && isRepositoryHealthy === false) ? (
<Button variant="destructive" onClick={() => onCancel?.(repoName)} disabled={isCancelling}>
{isCancelling ? (
<Trans i18nKey="provisioning.wizard.button-cancelling">Cancelling...</Trans>
) : (
<Trans i18nKey="provisioning.wizard.button-cancel">Cancel</Trans>
)}
</Button>
) : (
<Button variant="primary" onClick={startSynchronization} disabled={isButtonDisabled}>
<Trans i18nKey="provisioning.wizard.button-start">Begin synchronization</Trans>
</Button>
)}
</Field>
)}
</Stack>
);
});

View File

@ -11692,6 +11692,8 @@
"button-cancelling": "Cancelling...",
"button-next": "Finish",
"button-start": "Begin synchronization",
"check-status-button": "Check repository status",
"check-status-message": "Repository connecting, synchronize will be ready soon.",
"discard-modal": {
"body": "This will delete the repository configuration and you will lose all progress. Are you sure you want to discard your changes?",
"confirm": "Yes, discard",