+ {itemNumber > 0 && (
+
+ {itemNumber} Results
+
+ )}
-
+
>
);
}
diff --git a/packages/manager/apps/pci-databases-analytics/src/configuration/polling.constants.ts b/packages/manager/apps/pci-databases-analytics/src/configuration/polling.constants.ts
index 768940abbe15..b571b69c7cf3 100644
--- a/packages/manager/apps/pci-databases-analytics/src/configuration/polling.constants.ts
+++ b/packages/manager/apps/pci-databases-analytics/src/configuration/polling.constants.ts
@@ -14,3 +14,5 @@ export const POLLING = {
};
export const USER_INACTIVITY_TIMEOUT = 5 * 60_000; // inactivity after 5 minutes
+
+export const TERMINATE_CONFIRMATION = 'TERMINATE';
diff --git a/packages/manager/apps/pci-databases-analytics/src/hooks/api/catalog/useGetCatalog.hook.tsx b/packages/manager/apps/pci-databases-analytics/src/hooks/api/catalog/useGetCatalog.hook.tsx
index 1904b04c3ad5..efe4b1eabfbf 100644
--- a/packages/manager/apps/pci-databases-analytics/src/hooks/api/catalog/useGetCatalog.hook.tsx
+++ b/packages/manager/apps/pci-databases-analytics/src/hooks/api/catalog/useGetCatalog.hook.tsx
@@ -13,6 +13,7 @@ export function useGetCatalog(
const queryKey = ['order/catalog/public/cloud', subsidiary, product];
return useQueryImmediateRefetch({
queryKey,
+ enabled: !!user?.ovhSubsidiary,
queryFn: () => catalogApi.getCatalog(subsidiary, product),
...options,
}) as UseQueryResult
;
diff --git a/packages/manager/apps/pci-databases-analytics/src/hooks/api/catalog/useGetCatalog.spec.tsx b/packages/manager/apps/pci-databases-analytics/src/hooks/api/catalog/useGetCatalog.spec.tsx
index a5f21aaba297..56091e30566a 100644
--- a/packages/manager/apps/pci-databases-analytics/src/hooks/api/catalog/useGetCatalog.spec.tsx
+++ b/packages/manager/apps/pci-databases-analytics/src/hooks/api/catalog/useGetCatalog.spec.tsx
@@ -13,15 +13,9 @@ vi.mock('@/data/api/catalog/catalog.api', () => ({
},
}));
-vi.mock('@ovh-ux/manager-react-shell-client', () => {
+vi.mock('@/hooks/useUser', () => {
return {
- useShell: vi.fn(() => ({
- environment: {
- getEnvironment: vi.fn(() => ({
- getUser: vi.fn(() => mockedUser),
- })),
- },
- })),
+ useUser: vi.fn(() => mockedUser),
};
});
diff --git a/packages/manager/apps/pci-databases-analytics/src/hooks/api/database/service/useDeleteService.hook.tsx b/packages/manager/apps/pci-databases-analytics/src/hooks/api/database/service/useDeleteService.hook.tsx
index d06e595e39a2..9f6afb1ba91b 100644
--- a/packages/manager/apps/pci-databases-analytics/src/hooks/api/database/service/useDeleteService.hook.tsx
+++ b/packages/manager/apps/pci-databases-analytics/src/hooks/api/database/service/useDeleteService.hook.tsx
@@ -1,19 +1,32 @@
-import { useMutation } from '@tanstack/react-query';
+import { useMutation, useQueryClient } from '@tanstack/react-query';
+import { useParams } from 'react-router-dom';
+import * as database from '@/types/cloud/project/database';
import { deleteService } from '@/data/api/database/service.api';
import { CdbError, ServiceData } from '@/data/api/database';
interface UseDeleteService {
onError: (cause: CdbError) => void;
- onSuccess: () => void;
+ onDeleteSuccess: () => void;
}
-export function useDeleteService({ onError, onSuccess }: UseDeleteService) {
+export function useDeleteService({
+ onError,
+ onDeleteSuccess,
+}: UseDeleteService) {
+ const queryClient = useQueryClient();
+ const { projectId } = useParams();
const mutation = useMutation({
mutationFn: (serviceInfo: ServiceData) => {
return deleteService(serviceInfo);
},
onError,
- onSuccess,
+ onSuccess: () => {
+ onDeleteSuccess();
+ // Invalidate service list query to get the latest data
+ queryClient.invalidateQueries({
+ queryKey: [projectId, 'database/service'],
+ });
+ },
});
return {
diff --git a/packages/manager/apps/pci-databases-analytics/src/hooks/api/database/service/useDeleteService.spec.tsx b/packages/manager/apps/pci-databases-analytics/src/hooks/api/database/service/useDeleteService.spec.tsx
index 2764f233f815..665f5ac3f315 100644
--- a/packages/manager/apps/pci-databases-analytics/src/hooks/api/database/service/useDeleteService.spec.tsx
+++ b/packages/manager/apps/pci-databases-analytics/src/hooks/api/database/service/useDeleteService.spec.tsx
@@ -1,93 +1,26 @@
import { renderHook, waitFor } from '@testing-library/react';
import { vi } from 'vitest';
import { useDeleteService } from './useDeleteService.hook';
-import { useEditService } from './useEditService.hook';
-import { useAddService } from './useAddService.hook';
import * as databaseAPI from '@/data/api/database/service.api';
import * as database from '@/types/cloud/project/database';
import { QueryClientWrapper } from '@/__tests__/helpers/wrappers/QueryClientWrapper';
-import {
- mockedService,
- mockedServiceCreation,
- mockedServiceCreationWithEngine,
-} from '@/__tests__/helpers/mocks/services';
vi.mock('@/data/api/database/service.api', () => ({
- getServices: vi.fn(),
- getService: vi.fn(),
- addService: vi.fn(),
- editService: vi.fn(),
deleteService: vi.fn(),
}));
-describe('useAddService', () => {
- it('should call useAddService on mutation with data', async () => {
- const onSuccess = vi.fn();
- const onError = vi.fn();
-
- vi.mocked(databaseAPI.addService).mockResolvedValue(mockedService);
- const { result } = renderHook(() => useAddService({ onError, onSuccess }), {
- wrapper: QueryClientWrapper,
- });
-
- result.current.addService(mockedServiceCreationWithEngine);
-
- await waitFor(() => {
- expect(databaseAPI.addService).toHaveBeenCalledWith({
- projectId: undefined,
- engine: database.EngineEnum.mongodb,
- serviceInfo: mockedServiceCreation,
- });
- expect(onSuccess).toHaveBeenCalledWith(mockedService);
- });
- });
-});
-
-describe('useEditService', () => {
- it('should call useEditService on mutation with data', async () => {
- const projectId = 'projectId';
- const engine = database.EngineEnum.mysql;
- const serviceId = 'serviceId';
- const onSuccess = vi.fn();
- const onError = vi.fn();
-
- vi.mocked(databaseAPI.editService).mockResolvedValue(mockedService);
- const { result } = renderHook(
- () => useEditService({ onError, onSuccess }),
- { wrapper: QueryClientWrapper },
- );
-
- const editServiceProps: databaseAPI.EditService = {
- projectId,
- engine,
- serviceId,
- data: mockedService,
- };
- result.current.editService(editServiceProps);
-
- await waitFor(() => {
- expect(databaseAPI.editService).toHaveBeenCalledWith(editServiceProps);
- expect(onSuccess).toHaveBeenCalledWith(
- mockedService,
- editServiceProps,
- undefined,
- );
- });
- });
-});
-
describe('useDeleteService', () => {
it('should call useDeleteService on mutation with data', async () => {
const projectId = 'projectId';
const engine = database.EngineEnum.mysql;
const serviceId = 'serviceId';
- const onSuccess = vi.fn();
+ const onDeleteSuccess = vi.fn();
const onError = vi.fn();
vi.mocked(databaseAPI.deleteService).mockResolvedValue(undefined);
const { result } = renderHook(
- () => useDeleteService({ onError, onSuccess }),
+ () => useDeleteService({ onError, onDeleteSuccess }),
{ wrapper: QueryClientWrapper },
);
@@ -102,11 +35,7 @@ describe('useDeleteService', () => {
expect(databaseAPI.deleteService).toHaveBeenCalledWith(
deleteServiceProps,
);
- expect(onSuccess).toHaveBeenCalledWith(
- undefined,
- deleteServiceProps,
- undefined,
- );
+ expect(onDeleteSuccess).toHaveBeenCalledWith();
});
});
});
diff --git a/packages/manager/apps/pci-databases-analytics/src/hooks/api/database/service/useEditService.hook.tsx b/packages/manager/apps/pci-databases-analytics/src/hooks/api/database/service/useEditService.hook.tsx
index b7d7d9bd8b5b..c63d1c485152 100644
--- a/packages/manager/apps/pci-databases-analytics/src/hooks/api/database/service/useEditService.hook.tsx
+++ b/packages/manager/apps/pci-databases-analytics/src/hooks/api/database/service/useEditService.hook.tsx
@@ -1,17 +1,26 @@
-import { useMutation } from '@tanstack/react-query';
+import { useMutation, useQueryClient } from '@tanstack/react-query';
+import { useParams } from 'react-router-dom';
import * as database from '@/types/cloud/project/database';
import { EditService, editService } from '@/data/api/database/service.api';
import { CdbError } from '@/data/api/database';
interface UseEditService {
onError: (cause: CdbError) => void;
- onSuccess: (service: database.Service) => void;
+ onEditSuccess: (service: database.Service) => void;
}
-export function useEditService({ onError, onSuccess }: UseEditService) {
+export function useEditService({ onError, onEditSuccess }: UseEditService) {
+ const queryClient = useQueryClient();
+ const { projectId } = useParams();
const mutation = useMutation({
mutationFn: (serviceUpdate: EditService) => editService(serviceUpdate),
onError,
- onSuccess,
+ onSuccess: (data: database.Service) => {
+ onEditSuccess(data);
+ // Invalidate service list query to get the latest data
+ queryClient.invalidateQueries({
+ queryKey: [projectId, 'database/service'],
+ });
+ },
});
return {
diff --git a/packages/manager/apps/pci-databases-analytics/src/hooks/api/database/service/useEditService.spec.tsx b/packages/manager/apps/pci-databases-analytics/src/hooks/api/database/service/useEditService.spec.tsx
index ad465d60a0f0..fd46cebadb70 100644
--- a/packages/manager/apps/pci-databases-analytics/src/hooks/api/database/service/useEditService.spec.tsx
+++ b/packages/manager/apps/pci-databases-analytics/src/hooks/api/database/service/useEditService.spec.tsx
@@ -19,12 +19,12 @@ describe('useEditService', () => {
const projectId = 'projectId';
const engine = database.EngineEnum.mysql;
const serviceId = 'serviceId';
- const onSuccess = vi.fn();
+ const onEditSuccess = vi.fn();
const onError = vi.fn();
vi.mocked(databaseAPI.editService).mockResolvedValue(mockedService);
const { result } = renderHook(
- () => useEditService({ onError, onSuccess }),
+ () => useEditService({ onError, onEditSuccess }),
{ wrapper: QueryClientWrapper },
);
@@ -38,11 +38,7 @@ describe('useEditService', () => {
await waitFor(() => {
expect(databaseAPI.editService).toHaveBeenCalledWith(editServiceProps);
- expect(onSuccess).toHaveBeenCalledWith(
- mockedService,
- editServiceProps,
- undefined,
- );
+ expect(onEditSuccess).toHaveBeenCalledWith(mockedService);
});
});
});
diff --git a/packages/manager/apps/pci-databases-analytics/src/pages/services/Services.spec.tsx b/packages/manager/apps/pci-databases-analytics/src/pages/services/Services.spec.tsx
index db1fb6225460..5483f208748d 100644
--- a/packages/manager/apps/pci-databases-analytics/src/pages/services/Services.spec.tsx
+++ b/packages/manager/apps/pci-databases-analytics/src/pages/services/Services.spec.tsx
@@ -13,6 +13,7 @@ import * as serviceApi from '@/data/api/database/service.api';
import { RouterWithQueryClientWrapper } from '@/__tests__/helpers/wrappers/RouterWithQueryClientWrapper';
import { mockedUser } from '@/__tests__/helpers/mocks/user';
import { mockedService } from '@/__tests__/helpers/mocks/services';
+import { TERMINATE_CONFIRMATION } from '@/configuration/polling.constants';
describe('Services List page', () => {
beforeEach(() => {
@@ -183,8 +184,19 @@ describe('Open modals', () => {
await openButtonInMenu('service-action-delete-button');
await waitFor(() => {
expect(screen.getByTestId('delete-service-modal')).toBeInTheDocument();
+ expect(
+ screen.getByTestId('delete-service-confirmation-input'),
+ ).toBeInTheDocument();
});
act(() => {
+ fireEvent.change(
+ screen.getByTestId('delete-service-confirmation-input'),
+ {
+ target: {
+ value: TERMINATE_CONFIRMATION,
+ },
+ },
+ );
fireEvent.click(screen.getByTestId('delete-service-submit-button'));
});
await waitFor(() => {
diff --git a/packages/manager/apps/pci-databases-analytics/src/pages/services/[serviceId]/_components/DeleteService.component.tsx b/packages/manager/apps/pci-databases-analytics/src/pages/services/[serviceId]/_components/DeleteService.component.tsx
index 5c84ed85ba11..7b3dee627cf7 100644
--- a/packages/manager/apps/pci-databases-analytics/src/pages/services/[serviceId]/_components/DeleteService.component.tsx
+++ b/packages/manager/apps/pci-databases-analytics/src/pages/services/[serviceId]/_components/DeleteService.component.tsx
@@ -1,6 +1,6 @@
import { useParams } from 'react-router-dom';
import { useTranslation } from 'react-i18next';
-import { useMemo } from 'react';
+import { useMemo, useState } from 'react';
import { AlertTriangle } from 'lucide-react';
import { Button } from '@/components/ui/button';
import {
@@ -12,6 +12,7 @@ import {
DialogTitle,
} from '@/components/ui/dialog';
import { useToast } from '@/components/ui/use-toast';
+import { Input } from '@/components/ui/input';
import { ModalController } from '@/hooks/useModale';
@@ -23,6 +24,7 @@ import { useTrackAction, useTrackPage } from '@/hooks/useTracking';
import { TRACKING } from '@/configuration/tracking.constants';
import { useGetIntegrations } from '@/hooks/api/database/integration/useGetIntegrations.hook';
import { getCdbApiErrorMessage } from '@/lib/apiHelper';
+import { TERMINATE_CONFIRMATION } from '@/configuration/polling.constants';
interface DeleteServiceModalProps {
service: database.Service;
@@ -44,6 +46,7 @@ const DeleteService = ({
const track = useTrackAction();
const { t } = useTranslation('pci-databases-analytics/services/service');
const toast = useToast();
+ const [confirmationInput, setConfirmationInput] = useState('');
const integrationsQuery = useGetIntegrations(
projectId,
service.engine,
@@ -90,7 +93,7 @@ const DeleteService = ({
onError(err);
}
},
- onSuccess: () => {
+ onDeleteSuccess: () => {
track(
TRACKING.deleteService.success(service.engine, service.nodes[0].region),
);
@@ -152,6 +155,16 @@ const DeleteService = ({
name: service.description,
})}
+
+
{t('deleteServiceConfirmation')}
+
{
+ setConfirmationInput(event.target.value);
+ }}
+ />
+