Use useAsync for JobStep steps

This commit is contained in:
Roberto Jimenez Sanchez
2025-03-12 11:03:39 +01:00
parent ccf60f10d3
commit 242a275cc9
4 changed files with 44 additions and 81 deletions
+3 -3
View File
@@ -5900,14 +5900,14 @@ exports[`better eslint`] = {
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "21"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "22"]
],
"public/app/features/provisioning/Wizard/JobStep.tsx:5381": [
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "0"]
],
"public/app/features/provisioning/Wizard/MigrateStep.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "0"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "1"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "2"]
],
"public/app/features/provisioning/Wizard/PullStep.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "0"]
],
"public/app/features/provisioning/Wizard/Stepper.tsx:5381": [
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "0"]
],
@@ -39,7 +39,7 @@ export function JobStatus({ name, onStatusChange, onRunningChange, onErrorChange
}
}, [job, onStatusChange, onErrorChange, onRunningChange]);
if (jobQuery.isLoading || !job) {
if (!name || jobQuery.isLoading || !job) {
return (
<Stack direction="row" alignItems="center" justifyContent="center" gap={2}>
<Spinner size={24} />
@@ -1,11 +1,10 @@
import { skipToken } from '@reduxjs/toolkit/query';
import { ReactNode, useEffect, useRef, useState } from 'react';
import { ReactNode, useState } from 'react';
import { useFormContext } from 'react-hook-form';
import { useAsync } from 'react-use';
import { Box, Spinner, Stack, Text } from '@grafana/ui';
import { Stack, Text } from '@grafana/ui';
import { JobStatus } from '../JobStatus';
import { useListJobQuery } from '../api';
import { StepStatus, useStepStatus } from '../hooks/useStepStatus';
import { WizardFormData } from './types';
@@ -20,92 +19,59 @@ interface JobStepProps {
export type { JobStepProps };
export function JobStep({ onStepUpdate, description, startJob, children }: JobStepProps) {
const hasInitialized = useRef(false);
const { watch } = useFormContext<WizardFormData>();
const repositoryName = watch('repositoryName');
const stepStatus = useStepStatus({ onStepUpdate });
const [jobName, setJobName] = useState<string>();
// Query the job status if we have a job name
const jobQuery = useListJobQuery(jobName ? { watch: true, fieldSelector: `metadata.name=${jobName}` } : skipToken);
useEffect(() => {
if (!repositoryName || hasInitialized.current) {
useAsync(async () => {
if (!repositoryName) {
return;
}
hasInitialized.current = true;
let isMounted = true;
try {
stepStatus.setRunning();
const response = await startJob(repositoryName);
const executeJob = async () => {
try {
if (!isMounted) {
return;
}
stepStatus.setRunning();
const response = await startJob(repositoryName);
if (!response?.metadata?.name) {
stepStatus.setError('Invalid response from operation');
return;
}
setJobName(response.metadata.name);
} catch (error) {
if (!isMounted) {
return;
}
stepStatus.setError(error instanceof Error ? error.message : 'Failed to start operation');
if (!response?.metadata?.name) {
stepStatus.setError('Invalid response from operation');
throw new Error('Invalid response from operation');
}
};
executeJob();
return () => {
isMounted = false;
};
setJobName(response.metadata.name);
} catch (error) {
stepStatus.setError(error instanceof Error ? error.message : 'Failed to start operation');
throw error; // Re-throw to mark the async operation as failed
}
}, [repositoryName, startJob, stepStatus]);
const job = jobQuery.data?.items?.[0];
const showSpinner = !job;
return (
<Stack direction="column" gap={2}>
{description && <Text color="secondary">{description}</Text>}
{children}
<Box>
{showSpinner && (
<Stack direction="row" alignItems="center" gap={2}>
<Spinner size={24} />
<Text element="h4" weight="bold">
Starting...
</Text>
</Stack>
)}
{job && (
<JobStatus
name={jobName!}
onStatusChange={(success) => {
if (success) {
stepStatus.setSuccess();
} else {
stepStatus.setError('Job failed');
}
}}
onRunningChange={(isRunning) => {
if (isRunning) {
stepStatus.setRunning();
}
}}
onErrorChange={(error) => {
if (error) {
stepStatus.setError(error);
}
}}
/>
)}
</Box>
{jobName && (
<JobStatus
name={jobName}
onStatusChange={(success) => {
if (success) {
stepStatus.setSuccess();
} else {
stepStatus.setError('Job failed');
}
}}
onRunningChange={(isRunning) => {
if (isRunning) {
stepStatus.setRunning();
}
}}
onErrorChange={(error) => {
if (error) {
stepStatus.setError(error);
}
}}
/>
)}
</Stack>
);
}
@@ -1,5 +1,3 @@
import { ReactNode } from 'react';
import { useCreateRepositorySyncMutation } from '../api';
import { StepStatus } from '../hooks/useStepStatus';
@@ -7,10 +5,9 @@ import { JobStep } from './JobStep';
interface PullStepProps {
onStepUpdate: (status: StepStatus, error?: string) => void;
description?: ReactNode;
}
export function PullStep({ onStepUpdate, description }: PullStepProps) {
export function PullStep({ onStepUpdate }: PullStepProps) {
const [syncRepo] = useCreateRepositorySyncMutation();
const startSync = async (repositoryName: string) => {
@@ -24,7 +21,7 @@ export function PullStep({ onStepUpdate, description }: PullStepProps) {
return (
<JobStep
onStepUpdate={onStepUpdate}
description={description || 'Pulling repository content...'}
description="Pulling all content from your repository to this Grafana instance. This ensures your dashboards and other resources are synchronized with the repository."
startJob={startSync}
/>
);