diff --git a/eslint-suppressions.json b/eslint-suppressions.json index 17967697f4e..3a0c20851cd 100644 --- a/eslint-suppressions.json +++ b/eslint-suppressions.json @@ -3275,11 +3275,6 @@ "count": 2 } }, - "public/app/features/provisioning/Wizard/SynchronizeStep.tsx": { - "react/no-unescaped-entities": { - "count": 1 - } - }, "public/app/features/query/components/QueryEditorRow.tsx": { "@grafana/no-aria-label-selectors": { "count": 1 diff --git a/public/app/features/provisioning/Wizard/ProvisioningWizard.tsx b/public/app/features/provisioning/Wizard/ProvisioningWizard.tsx index 2c125fbdbe8..717400785fc 100644 --- a/public/app/features/provisioning/Wizard/ProvisioningWizard.tsx +++ b/public/app/features/provisioning/Wizard/ProvisioningWizard.tsx @@ -358,7 +358,13 @@ export function ProvisioningWizard({ type }: { type: RepoType }) {
{activeStep === 'connection' && } {activeStep === 'bootstrap' && } - {activeStep === 'synchronize' && } + {activeStep === 'synchronize' && ( + + )} {activeStep === 'finish' && }
diff --git a/public/app/features/provisioning/Wizard/SynchronizeStep.tsx b/public/app/features/provisioning/Wizard/SynchronizeStep.tsx index d05d1a96c4e..09ab5ff7a24 100644 --- a/public/app/features/provisioning/Wizard/SynchronizeStep.tsx +++ b/public/app/features/provisioning/Wizard/SynchronizeStep.tsx @@ -1,11 +1,13 @@ +import { skipToken } from '@reduxjs/toolkit/query'; import { useState } from 'react'; import { useFormContext } from 'react-hook-form'; import { Trans, t } from '@grafana/i18n'; -import { Button, Text, Stack, Alert, TextLink, Field, Checkbox } from '@grafana/ui'; -import { Job } from 'app/api/clients/provisioning/v0alpha1'; +import { Alert, Button, Checkbox, Field, Spinner, Stack, Text, TextLink } from '@grafana/ui'; +import { Job, useGetRepositoryStatusQuery } from 'app/api/clients/provisioning/v0alpha1'; import { JobStatus } from '../Job/JobStatus'; +import { ProvisioningAlert } from '../Shared/ProvisioningAlert'; import { useStepStatus } from './StepStatusContext'; import { useCreateSyncJob } from './hooks/useCreateSyncJob'; @@ -14,9 +16,11 @@ import { WizardFormData } from './types'; export interface SynchronizeStepProps { isLegacyStorage?: boolean; + onCancel?: (repoName: string) => void; + isCancelling?: boolean; } -export function SynchronizeStep({ isLegacyStorage }: SynchronizeStepProps) { +export function SynchronizeStep({ isLegacyStorage, onCancel, isCancelling }: SynchronizeStepProps) { const { getValues, register, watch } = useFormContext(); const { setStepStatusInfo } = useStepStatus(); const [repoName = '', repoType] = watch(['repositoryName', 'repository.type']); @@ -29,6 +33,14 @@ export function SynchronizeStep({ isLegacyStorage }: SynchronizeStepProps) { setStepStatusInfo, }); const [job, setJob] = useState(); + const repositoryStatusQuery = useGetRepositoryStatusQuery(repoName ? { name: repoName } : skipToken); + + const { + healthy: isRepositoryHealthy, + message: repositoryHealthMessages, + checked, + } = repositoryStatusQuery?.data?.status?.health || {}; + const isButtonDisabled = checked !== undefined && isRepositoryHealthy === false; const startSynchronization = async () => { const [history] = getValues(['migrate.history']); @@ -38,53 +50,69 @@ export function SynchronizeStep({ isLegacyStorage }: SynchronizeStepProps) { } }; + if (repositoryStatusQuery.isFetching) { + return ; + } if (job) { return ; } return ( - + Sync resources with external storage. After this one-time step, all future updates will be automatically saved to the repository and provisioned back into the instance. - -
    -
  • - - Resources won't be able to be created, edited, or deleted during this process. In the last step, they will - disappear. - -
  • -
  • - - Once provisioning is complete, resources will reappear and be managed through external storage. - -
  • -
  • - - The duration of this process depends on the number of resources involved. - -
  • -
  • - - Enterprise instance administrators can display an announcement banner to users. See{' '} - - this guide - {' '} - for step-by-step instructions. - -
  • -
-
+ {repositoryHealthMessages && !isRepositoryHealthy && ( + + )} + {isRepositoryHealthy && ( + +
    +
  • + + Resources won't be able to be created, edited, or deleted during this process. In the last step, + they will disappear. + +
  • +
  • + + Once provisioning is complete, resources will reappear and be managed through external storage. + +
  • +
  • + + The duration of this process depends on the number of resources involved. + +
  • +
  • + + Enterprise instance administrators can display an announcement banner to users. See{' '} + + this guide + {' '} + for step-by-step instructions. + +
  • +
+
+ )} {supportsHistory && ( <> @@ -105,9 +133,21 @@ export function SynchronizeStep({ isLegacyStorage }: SynchronizeStepProps) { )} - + + {isRepositoryHealthy === false ? ( + + ) : ( + + )} +
); } diff --git a/public/locales/en-US/grafana.json b/public/locales/en-US/grafana.json index edd1aea6fd8..4a2217515fd 100644 --- a/public/locales/en-US/grafana.json +++ b/public/locales/en-US/grafana.json @@ -11655,6 +11655,7 @@ "tooltip-unhealthy-repository": "Unable to pull an unhealthy repository" }, "synchronize-step": { + "repository-unhealthy": "The repository cannot be synchronized. Cancel provisioning and try again once the issue has been resolved. See details below.", "synchronization-description": "Include commits for each historical value", "synchronization-options": "Synchronization options" }, @@ -11678,6 +11679,8 @@ "alert-point-3": "The duration of this process depends on the number of resources involved.", "alert-point-4": "Enterprise instance administrators can display an announcement banner to users. See <2>this guide for step-by-step instructions.", "alert-title": "Important: No data or configuration will be lost, but dashboards will be temporarily unavailable for a few minutes.", + "button-cancel": "Cancel", + "button-cancelling": "Cancelling...", "button-next": "Finish", "button-start": "Begin synchronization", "discard-modal": {