BulkActionError: Add Git Sync Error Display for Bulk Delete and Bulk Move (#111195)
* BulkDeleteProvisionedResource & BulkMoveProvisionedResource: display error * use ProvisioningAlert component * MoveProvisionedDashboardForm use ProvisioningAlert * DeleteProvisionedDashboardForm use ProvisioningAlert
This commit is contained in:
+21
-9
@@ -1,4 +1,4 @@
|
||||
import { useState } from 'react';
|
||||
import { useCallback, useState } from 'react';
|
||||
import { FormProvider, useForm } from 'react-hook-form';
|
||||
|
||||
import { AppEvents } from '@grafana/data';
|
||||
@@ -12,7 +12,10 @@ import { JobStatus } from 'app/features/provisioning/Job/JobStatus';
|
||||
import { useGetResourceRepositoryView } from 'app/features/provisioning/hooks/useGetResourceRepositoryView';
|
||||
import { GENERAL_FOLDER_UID } from 'app/features/search/constants';
|
||||
|
||||
import { ProvisioningAlert } from '../../Shared/ProvisioningAlert';
|
||||
import { StepStatusInfo } from '../../Wizard/types';
|
||||
import { useSelectionRepoValidation } from '../../hooks/useSelectionRepoValidation';
|
||||
import { StatusInfo } from '../../types';
|
||||
import { RepoInvalidStateBanner } from '../Shared/RepoInvalidStateBanner';
|
||||
import { ResourceEditFormSharedFields } from '../Shared/ResourceEditFormSharedFields';
|
||||
import { getDefaultWorkflow, getWorkflowOptions } from '../defaults';
|
||||
@@ -30,6 +33,7 @@ interface FormProps extends BulkActionProvisionResourceProps {
|
||||
function FormContent({ initialValues, selectedItems, repository, workflowOptions, onDismiss }: FormProps) {
|
||||
// States
|
||||
const [job, setJob] = useState<Job>();
|
||||
const [jobError, setJobError] = useState<string | StatusInfo>();
|
||||
const [hasSubmitted, setHasSubmitted] = useState(false);
|
||||
|
||||
// Hooks
|
||||
@@ -72,21 +76,29 @@ function FormContent({ initialValues, selectedItems, repository, workflowOptions
|
||||
const disableBtn =
|
||||
isCreatingJob || job?.status?.state === 'working' || job?.status?.state === 'pending' || hasSubmitted;
|
||||
|
||||
const onStatusChange = useCallback((statusInfo: StepStatusInfo) => {
|
||||
if (statusInfo.status === 'error' && statusInfo.error) {
|
||||
setJobError(statusInfo.error);
|
||||
}
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<FormProvider {...methods}>
|
||||
<form onSubmit={handleSubmit(handleSubmitForm)}>
|
||||
<Stack direction="column" gap={2}>
|
||||
<Box paddingBottom={2}>
|
||||
<Trans i18nKey="browse-dashboards.bulk-delete-resources-form.delete-warning">
|
||||
This will delete selected folders and their descendants. In total, this will affect:
|
||||
</Trans>
|
||||
<DescendantCount selectedItems={{ ...selectedItems, panel: {}, $all: false }} />
|
||||
</Box>
|
||||
|
||||
{hasSubmitted && job ? (
|
||||
<JobStatus watch={job} jobType="delete" />
|
||||
<>
|
||||
<ProvisioningAlert error={jobError} />
|
||||
<JobStatus watch={job} jobType="delete" onStatusChange={onStatusChange} />
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<Box paddingBottom={2}>
|
||||
<Trans i18nKey="browse-dashboards.bulk-delete-resources-form.delete-warning">
|
||||
This will delete selected folders and their descendants. In total, this will affect:
|
||||
</Trans>
|
||||
<DescendantCount selectedItems={{ ...selectedItems, panel: {}, $all: false }} />
|
||||
</Box>
|
||||
<ResourceEditFormSharedFields
|
||||
resourceType="folder"
|
||||
isNew={false}
|
||||
|
||||
+22
-8
@@ -1,5 +1,5 @@
|
||||
import { skipToken } from '@reduxjs/toolkit/query';
|
||||
import { useState } from 'react';
|
||||
import { useState, useCallback } from 'react';
|
||||
import { FormProvider, useForm } from 'react-hook-form';
|
||||
|
||||
import { AppEvents } from '@grafana/data';
|
||||
@@ -16,7 +16,10 @@ import { getDefaultWorkflow, getWorkflowOptions } from 'app/features/provisionin
|
||||
import { useGetResourceRepositoryView } from 'app/features/provisioning/hooks/useGetResourceRepositoryView';
|
||||
import { GENERAL_FOLDER_UID } from 'app/features/search/constants';
|
||||
|
||||
import { ProvisioningAlert } from '../../Shared/ProvisioningAlert';
|
||||
import { StepStatusInfo } from '../../Wizard/types';
|
||||
import { useSelectionRepoValidation } from '../../hooks/useSelectionRepoValidation';
|
||||
import { StatusInfo } from '../../types';
|
||||
import { MoveActionAvailableTargetWarning } from '../Shared/MoveActionAvailableTargetWarning';
|
||||
import { ProvisioningAwareFolderPicker } from '../Shared/ProvisioningAwareFolderPicker';
|
||||
import { RepoInvalidStateBanner } from '../Shared/RepoInvalidStateBanner';
|
||||
@@ -36,6 +39,7 @@ interface FormProps extends BulkActionProvisionResourceProps {
|
||||
function FormContent({ initialValues, selectedItems, repository, workflowOptions, onDismiss }: FormProps) {
|
||||
// States
|
||||
const [job, setJob] = useState<Job>();
|
||||
const [jobError, setJobError] = useState<string | StatusInfo>();
|
||||
const [targetFolderUID, setTargetFolderUID] = useState<string | undefined>(undefined);
|
||||
const [hasSubmitted, setHasSubmitted] = useState(false);
|
||||
|
||||
@@ -109,20 +113,30 @@ function FormContent({ initialValues, selectedItems, repository, workflowOptions
|
||||
}
|
||||
};
|
||||
|
||||
const onStatusChange = useCallback((statusInfo: StepStatusInfo) => {
|
||||
if (statusInfo.status === 'error' && statusInfo.error) {
|
||||
setJobError(statusInfo.error);
|
||||
}
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<FormProvider {...methods}>
|
||||
<form onSubmit={handleSubmit(handleSubmitForm)}>
|
||||
<Stack direction="column" gap={2}>
|
||||
<MoveActionAvailableTargetWarning />
|
||||
<Box paddingBottom={2}>
|
||||
<Trans i18nKey="browse-dashboards.bulk-move-resources-form.move-total">In total, this will affect:</Trans>
|
||||
<DescendantCount selectedItems={{ ...selectedItems, panel: {}, $all: false }} />
|
||||
</Box>
|
||||
|
||||
{hasSubmitted && job ? (
|
||||
<JobStatus watch={job} jobType="move" />
|
||||
<>
|
||||
<ProvisioningAlert error={jobError} />
|
||||
<JobStatus watch={job} jobType="move" onStatusChange={onStatusChange} />
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<MoveActionAvailableTargetWarning />
|
||||
<Box paddingBottom={2}>
|
||||
<Trans i18nKey="browse-dashboards.bulk-move-resources-form.move-total">
|
||||
In total, this will affect:
|
||||
</Trans>
|
||||
<DescendantCount selectedItems={{ ...selectedItems, panel: {}, $all: false }} />
|
||||
</Box>
|
||||
{/* Target folder selection */}
|
||||
<Field
|
||||
noMargin
|
||||
|
||||
+32
-16
@@ -1,4 +1,4 @@
|
||||
import { useState } from 'react';
|
||||
import { useCallback, useState } from 'react';
|
||||
import { FormProvider, useForm } from 'react-hook-form';
|
||||
import { useNavigate } from 'react-router-dom-v5-compat';
|
||||
|
||||
@@ -12,7 +12,9 @@ import { JobStatus } from 'app/features/provisioning/Job/JobStatus';
|
||||
import { StepStatusInfo } from 'app/features/provisioning/Wizard/types';
|
||||
import { PROVISIONING_URL } from 'app/features/provisioning/constants';
|
||||
|
||||
import { ProvisioningAlert } from '../../Shared/ProvisioningAlert';
|
||||
import { useProvisionedRequestHandler } from '../../hooks/useProvisionedRequestHandler';
|
||||
import { StatusInfo } from '../../types';
|
||||
import { ProvisionedDashboardFormData } from '../../types/form';
|
||||
import { buildResourceBranchRedirectUrl } from '../../utils/redirect';
|
||||
import { useBulkActionJob } from '../BulkActions/useBulkActionJob';
|
||||
@@ -44,16 +46,20 @@ export function DeleteProvisionedDashboardForm({
|
||||
repository,
|
||||
onDismiss,
|
||||
}: Props) {
|
||||
const methods = useForm<ProvisionedDashboardFormData>({ defaultValues });
|
||||
const { editPanel: panelEditor } = dashboard.useState();
|
||||
const { handleSubmit, watch } = methods;
|
||||
const navigate = useNavigate();
|
||||
|
||||
const [ref, workflow] = watch(['ref', 'workflow']);
|
||||
const { createBulkJob, isLoading } = useBulkActionJob();
|
||||
const [deleteRepoFile, request] = useDeleteRepositoryFilesWithPathMutation();
|
||||
// State
|
||||
const [job, setJob] = useState<Job>();
|
||||
const [hasSubmitted, setHasSubmitted] = useState(false);
|
||||
const [jobError, setJobError] = useState<string | StatusInfo>();
|
||||
|
||||
// Hooks
|
||||
const navigate = useNavigate();
|
||||
const { editPanel: panelEditor } = dashboard.useState();
|
||||
const { createBulkJob, isLoading } = useBulkActionJob();
|
||||
const [deleteRepoFile, request] = useDeleteRepositoryFilesWithPathMutation();
|
||||
// Form
|
||||
const methods = useForm<ProvisionedDashboardFormData>({ defaultValues });
|
||||
const { handleSubmit, watch } = methods;
|
||||
const [ref, workflow] = watch(['ref', 'workflow']);
|
||||
|
||||
// Helper function to show error messages
|
||||
const showError = (error?: unknown) => {
|
||||
@@ -136,12 +142,19 @@ export function DeleteProvisionedDashboardForm({
|
||||
navigate(url);
|
||||
};
|
||||
|
||||
const handleJobStatusChange = (statusInfo: StepStatusInfo) => {
|
||||
if (statusInfo.status === 'success') {
|
||||
panelEditor?.onDiscard();
|
||||
navigate('/dashboards');
|
||||
}
|
||||
};
|
||||
const handleJobStatusChange = useCallback(
|
||||
(statusInfo: StepStatusInfo) => {
|
||||
if (statusInfo.status === 'success') {
|
||||
panelEditor?.onDiscard();
|
||||
navigate('/dashboards');
|
||||
}
|
||||
|
||||
if (statusInfo.status === 'error' && statusInfo.error) {
|
||||
setJobError(statusInfo.error);
|
||||
}
|
||||
},
|
||||
[panelEditor, navigate]
|
||||
);
|
||||
|
||||
useProvisionedRequestHandler({
|
||||
request,
|
||||
@@ -165,7 +178,10 @@ export function DeleteProvisionedDashboardForm({
|
||||
onClose={onDismiss}
|
||||
>
|
||||
{hasSubmitted && job ? (
|
||||
<JobStatus watch={job} jobType="delete" onStatusChange={handleJobStatusChange} />
|
||||
<>
|
||||
<ProvisioningAlert error={jobError} />
|
||||
<JobStatus watch={job} jobType="move" onStatusChange={handleJobStatusChange} />
|
||||
</>
|
||||
) : (
|
||||
<FormProvider {...methods}>
|
||||
<form onSubmit={handleSubmit(handleSubmitForm)}>
|
||||
|
||||
+22
-9
@@ -1,5 +1,5 @@
|
||||
import { skipToken } from '@reduxjs/toolkit/query';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useCallback, useEffect, useState } from 'react';
|
||||
import { FormProvider, useForm } from 'react-hook-form';
|
||||
import { useNavigate } from 'react-router-dom-v5-compat';
|
||||
|
||||
@@ -19,7 +19,9 @@ import { DashboardScene } from 'app/features/dashboard-scene/scene/DashboardScen
|
||||
import { JobStatus } from 'app/features/provisioning/Job/JobStatus';
|
||||
import { StepStatusInfo } from 'app/features/provisioning/Wizard/types';
|
||||
|
||||
import { ProvisioningAlert } from '../../Shared/ProvisioningAlert';
|
||||
import { ProvisionedOperationInfo, useProvisionedRequestHandler } from '../../hooks/useProvisionedRequestHandler';
|
||||
import { StatusInfo } from '../../types';
|
||||
import { ProvisionedDashboardFormData } from '../../types/form';
|
||||
import { buildResourceBranchRedirectUrl } from '../../utils/redirect';
|
||||
import { useBulkActionJob } from '../BulkActions/useBulkActionJob';
|
||||
@@ -73,6 +75,7 @@ export function MoveProvisionedDashboardForm({
|
||||
const [targetPath, setTargetPath] = useState<string>('');
|
||||
const [job, setJob] = useState<Job>();
|
||||
const [hasSubmitted, setHasSubmitted] = useState(false);
|
||||
const [jobError, setJobError] = useState<string | StatusInfo>();
|
||||
|
||||
const navigate = useNavigate();
|
||||
|
||||
@@ -197,13 +200,20 @@ export function MoveProvisionedDashboardForm({
|
||||
navigate(url);
|
||||
};
|
||||
|
||||
const handleJobStatusChange = (statusInfo: StepStatusInfo) => {
|
||||
if (statusInfo.status === 'success') {
|
||||
dashboard.setState({ isDirty: false });
|
||||
panelEditor?.onDiscard();
|
||||
navigate('/dashboards');
|
||||
}
|
||||
};
|
||||
const handleJobStatusChange = useCallback(
|
||||
(statusInfo: StepStatusInfo) => {
|
||||
if (statusInfo.status === 'success') {
|
||||
dashboard.setState({ isDirty: false });
|
||||
panelEditor?.onDiscard();
|
||||
navigate('/dashboards');
|
||||
}
|
||||
|
||||
if (statusInfo.status === 'error' && statusInfo.error) {
|
||||
setJobError(statusInfo.error);
|
||||
}
|
||||
},
|
||||
[dashboard, panelEditor, navigate]
|
||||
);
|
||||
|
||||
useProvisionedRequestHandler({
|
||||
request: moveRequest,
|
||||
@@ -229,7 +239,10 @@ export function MoveProvisionedDashboardForm({
|
||||
onClose={onDismiss}
|
||||
>
|
||||
{hasSubmitted && job ? (
|
||||
<JobStatus watch={job} jobType="move" onStatusChange={handleJobStatusChange} />
|
||||
<>
|
||||
<ProvisioningAlert error={jobError} />
|
||||
<JobStatus watch={job} jobType="move" onStatusChange={handleJobStatusChange} />
|
||||
</>
|
||||
) : (
|
||||
<FormProvider {...methods}>
|
||||
<form onSubmit={handleSubmit(handleSubmitForm)}>
|
||||
|
||||
Reference in New Issue
Block a user