From 71de2e0a35cf54cd3d7de8e506ef88b8a4482bee Mon Sep 17 00:00:00 2001 From: Sooraj Date: Fri, 2 Sep 2022 15:48:30 +0530 Subject: [PATCH] console: add hooks required for operations CRUD PR-URL: https://github.com/hasura/graphql-engine-mono/pull/5670 Co-authored-by: Varun Choudhary <68095256+Varun-Choudhary@users.noreply.github.com> GitOrigin-RevId: f9bf532689fd7fe8df6ca7abbd9d12c2a4c1320c --- .../features/QueryCollections/hooks/index.ts | 5 ++ .../index.ts | 1 + .../mocks/handlers.mock.ts | 39 +++++++++++ ...AddOperationsToQueryCollection.stories.tsx | 54 +++++++++++++++ .../useAddOperationsToQueryCollection.test.ts | 33 ++++++++++ .../useAddOperationsToQueryCollection.ts | 49 ++++++++++++++ .../index.ts | 1 + .../mocks/handlers.mock.ts | 14 ++++ ...EditOperationInQueryCollection.stories.tsx | 52 +++++++++++++++ .../useEditOperationInQueryCollection.test.ts | 37 +++++++++++ .../useEditOperationInQueryCollection.ts | 60 +++++++++++++++++ .../index.ts | 1 + .../mocks/handlers.mock.ts | 16 +++++ ...oveOperationsToQueryCollection.stories.tsx | 54 +++++++++++++++ ...useMoveOperationsToQueryCollection.test.ts | 37 +++++++++++ .../useMoveOperationsToQueryCollection.ts | 66 +++++++++++++++++++ .../index.ts | 1 + .../mocks/handlers.mock.ts | 39 +++++++++++ ...eOperationsFromQueryCollection.stories.tsx | 54 +++++++++++++++ ...emoveOperationsFromQueryCollection.test.ts | 33 ++++++++++ .../useRemoveOperationsFromQueryCollection.ts | 48 ++++++++++++++ 21 files changed, 694 insertions(+) create mode 100644 console/src/features/QueryCollections/hooks/index.ts create mode 100644 console/src/features/QueryCollections/hooks/useAddOperationsToQueryCollection/index.ts create mode 100644 console/src/features/QueryCollections/hooks/useAddOperationsToQueryCollection/mocks/handlers.mock.ts create mode 100644 console/src/features/QueryCollections/hooks/useAddOperationsToQueryCollection/useAddOperationsToQueryCollection.stories.tsx create mode 100644 console/src/features/QueryCollections/hooks/useAddOperationsToQueryCollection/useAddOperationsToQueryCollection.test.ts create mode 100644 console/src/features/QueryCollections/hooks/useAddOperationsToQueryCollection/useAddOperationsToQueryCollection.ts create mode 100644 console/src/features/QueryCollections/hooks/useEditOperationInQueryCollection/index.ts create mode 100644 console/src/features/QueryCollections/hooks/useEditOperationInQueryCollection/mocks/handlers.mock.ts create mode 100644 console/src/features/QueryCollections/hooks/useEditOperationInQueryCollection/useEditOperationInQueryCollection.stories.tsx create mode 100644 console/src/features/QueryCollections/hooks/useEditOperationInQueryCollection/useEditOperationInQueryCollection.test.ts create mode 100644 console/src/features/QueryCollections/hooks/useEditOperationInQueryCollection/useEditOperationInQueryCollection.ts create mode 100644 console/src/features/QueryCollections/hooks/useMoveOperationsToQueryCollection/index.ts create mode 100644 console/src/features/QueryCollections/hooks/useMoveOperationsToQueryCollection/mocks/handlers.mock.ts create mode 100644 console/src/features/QueryCollections/hooks/useMoveOperationsToQueryCollection/useMoveOperationsToQueryCollection.stories.tsx create mode 100644 console/src/features/QueryCollections/hooks/useMoveOperationsToQueryCollection/useMoveOperationsToQueryCollection.test.ts create mode 100644 console/src/features/QueryCollections/hooks/useMoveOperationsToQueryCollection/useMoveOperationsToQueryCollection.ts create mode 100644 console/src/features/QueryCollections/hooks/useRemoveOperationsFromQueryCollection/index.ts create mode 100644 console/src/features/QueryCollections/hooks/useRemoveOperationsFromQueryCollection/mocks/handlers.mock.ts create mode 100644 console/src/features/QueryCollections/hooks/useRemoveOperationsFromQueryCollection/useRemoveOperationsFromQueryCollection.stories.tsx create mode 100644 console/src/features/QueryCollections/hooks/useRemoveOperationsFromQueryCollection/useRemoveOperationsFromQueryCollection.test.ts create mode 100644 console/src/features/QueryCollections/hooks/useRemoveOperationsFromQueryCollection/useRemoveOperationsFromQueryCollection.ts diff --git a/console/src/features/QueryCollections/hooks/index.ts b/console/src/features/QueryCollections/hooks/index.ts new file mode 100644 index 00000000000..98a35cfbd3a --- /dev/null +++ b/console/src/features/QueryCollections/hooks/index.ts @@ -0,0 +1,5 @@ +export { useAddOperationsToQueryCollection } from './useAddOperationsToQueryCollection'; +export { useEditOperationInQueryCollection } from './useEditOperationInQueryCollection'; +export { useMoveOperationsToQueryCollection } from './useMoveOperationsToQueryCollection'; +export { useOperationsFromQueryCollection } from './useOperationsFromQueryCollection'; +export { useRemoveOperationsFromQueryCollection } from './useRemoveOperationsFromQueryCollection'; diff --git a/console/src/features/QueryCollections/hooks/useAddOperationsToQueryCollection/index.ts b/console/src/features/QueryCollections/hooks/useAddOperationsToQueryCollection/index.ts new file mode 100644 index 00000000000..d65bc71742b --- /dev/null +++ b/console/src/features/QueryCollections/hooks/useAddOperationsToQueryCollection/index.ts @@ -0,0 +1 @@ +export * from './useAddOperationsToQueryCollection'; diff --git a/console/src/features/QueryCollections/hooks/useAddOperationsToQueryCollection/mocks/handlers.mock.ts b/console/src/features/QueryCollections/hooks/useAddOperationsToQueryCollection/mocks/handlers.mock.ts new file mode 100644 index 00000000000..48943d843d9 --- /dev/null +++ b/console/src/features/QueryCollections/hooks/useAddOperationsToQueryCollection/mocks/handlers.mock.ts @@ -0,0 +1,39 @@ +import { rest } from 'msw'; +import { TMigration } from '../../../../MetadataAPI/hooks/useMetadataMigration'; + +const baseUrl = 'http://localhost:8080'; + +export const handlers = (delay = 0, url = baseUrl) => [ + // todo export metadata mock based on the input + + rest.post(`${url}/v1/metadata`, (req, res, ctx) => { + const body = req.body as TMigration['query']; + + if (body.type === 'add_query_to_collection') { + if ( + body.args.query_name === 'MyQuery33' && + body.args.query === 'query MyQuery { user { email name}}' + ) + return res( + ctx.delay(delay), + ctx.json({ + message: 'success', + }) + ); + return res( + ctx.delay(delay), + ctx.status(500), + ctx.json({ + message: 'error', + }) + ); + } + + return res( + ctx.delay(delay), + ctx.json({ + message: 'success', + }) + ); + }), +]; diff --git a/console/src/features/QueryCollections/hooks/useAddOperationsToQueryCollection/useAddOperationsToQueryCollection.stories.tsx b/console/src/features/QueryCollections/hooks/useAddOperationsToQueryCollection/useAddOperationsToQueryCollection.stories.tsx new file mode 100644 index 00000000000..5e9e3ade2a5 --- /dev/null +++ b/console/src/features/QueryCollections/hooks/useAddOperationsToQueryCollection/useAddOperationsToQueryCollection.stories.tsx @@ -0,0 +1,54 @@ +import React from 'react'; +import { ReactQueryDecorator } from '@/storybook/decorators/react-query'; +import { ReduxDecorator } from '@/storybook/decorators/redux-decorator'; +import ReactJson from 'react-json-view'; +import { Button } from '@/new-components/Button'; +import { Meta, Story } from '@storybook/react'; + +import { handlers } from './mocks/handlers.mock'; +import { useAddOperationsToQueryCollection } from '.'; + +const UseAddOperationsToQueryCollection: React.FC = () => { + const { addOperationToQueryCollection, isSuccess, isLoading, error } = + useAddOperationsToQueryCollection(); + + return ( +
+ + +
+ ); +}; + +export const Primary: Story = () => { + return ; +}; + +export default { + title: 'hooks/Query Collections/useAddOperationsToQueryCollection', + decorators: [ + ReduxDecorator({ tables: { currentDataSource: 'default' } }), + ReactQueryDecorator(), + ], + parameters: { + msw: handlers(1000), + }, +} as Meta; diff --git a/console/src/features/QueryCollections/hooks/useAddOperationsToQueryCollection/useAddOperationsToQueryCollection.test.ts b/console/src/features/QueryCollections/hooks/useAddOperationsToQueryCollection/useAddOperationsToQueryCollection.test.ts new file mode 100644 index 00000000000..7493ba9f051 --- /dev/null +++ b/console/src/features/QueryCollections/hooks/useAddOperationsToQueryCollection/useAddOperationsToQueryCollection.test.ts @@ -0,0 +1,33 @@ +import { setupServer } from 'msw/node'; +import { renderHook } from '@testing-library/react-hooks'; +import { handlers } from './mocks/handlers.mock'; +import { useAddOperationsToQueryCollection } from '.'; +import { wrapper } from '../../../../hooks/__tests__/common/decorator'; + +const server = setupServer(); + +beforeAll(() => server.listen()); +afterAll(() => server.close()); + +describe('useAddOperationsToQueryCollection', () => { + beforeEach(() => { + server.use(...handlers(1, '')); + }); + + test('When useAddOperationsToQueryCollection is used with a valid QueryCollection Then it should call the API with correct payload', async () => { + const { waitForValueToChange, result }: any = renderHook( + () => useAddOperationsToQueryCollection(), + { wrapper } + ); + + await result.current.addOperationToQueryCollection('testCollection', [ + { + name: 'MyQuery33', + query: 'query MyQuery { user { email name}}', + }, + ]); + + await waitForValueToChange(() => result.current.isSuccess); + expect(result.current.isSuccess).toBe(true); + }); +}); diff --git a/console/src/features/QueryCollections/hooks/useAddOperationsToQueryCollection/useAddOperationsToQueryCollection.ts b/console/src/features/QueryCollections/hooks/useAddOperationsToQueryCollection/useAddOperationsToQueryCollection.ts new file mode 100644 index 00000000000..0afae7610a9 --- /dev/null +++ b/console/src/features/QueryCollections/hooks/useAddOperationsToQueryCollection/useAddOperationsToQueryCollection.ts @@ -0,0 +1,49 @@ +import { useCallback } from 'react'; + +import { useMetadata, useMetadataMigration } from '@/features/MetadataAPI'; +import { QueryCollection } from '@/metadata/types'; + +export const useAddOperationsToQueryCollection = () => { + const { mutate, ...rest } = useMetadataMigration(); + + const { data: metadata } = useMetadata(); + + const addOperationToQueryCollection = useCallback( + ( + queryCollection: string, + queries: QueryCollection[], + options?: Parameters[1] + ) => { + if (!queryCollection || !queries) + throw Error( + `useAddOperationsToQueryCollection: Invalid input - ${ + queryCollection && 'queryCollection' + } ${queries && 'queries'}` + ); + return mutate( + { + query: { + type: 'bulk', + ...(metadata?.resource_version && { + resource_version: metadata.resource_version, + }), + args: queries.map(query => ({ + type: 'add_query_to_collection', + args: { + collection_name: queryCollection, + query_name: query.name, + query: query.query, + }, + })), + }, + }, + { + ...options, + } + ); + }, + [metadata, mutate] + ); + + return { addOperationToQueryCollection, ...rest }; +}; diff --git a/console/src/features/QueryCollections/hooks/useEditOperationInQueryCollection/index.ts b/console/src/features/QueryCollections/hooks/useEditOperationInQueryCollection/index.ts new file mode 100644 index 00000000000..fbab0960298 --- /dev/null +++ b/console/src/features/QueryCollections/hooks/useEditOperationInQueryCollection/index.ts @@ -0,0 +1 @@ +export * from './useEditOperationInQueryCollection'; diff --git a/console/src/features/QueryCollections/hooks/useEditOperationInQueryCollection/mocks/handlers.mock.ts b/console/src/features/QueryCollections/hooks/useEditOperationInQueryCollection/mocks/handlers.mock.ts new file mode 100644 index 00000000000..f8ff547f388 --- /dev/null +++ b/console/src/features/QueryCollections/hooks/useEditOperationInQueryCollection/mocks/handlers.mock.ts @@ -0,0 +1,14 @@ +import { rest } from 'msw'; + +const baseUrl = 'http://localhost:8080'; + +export const handlers = (delay = 0, url = baseUrl) => [ + rest.post(`${url}/v1/metadata`, (req, res, ctx) => { + return res( + ctx.delay(delay), + ctx.json({ + message: 'success', + }) + ); + }), +]; diff --git a/console/src/features/QueryCollections/hooks/useEditOperationInQueryCollection/useEditOperationInQueryCollection.stories.tsx b/console/src/features/QueryCollections/hooks/useEditOperationInQueryCollection/useEditOperationInQueryCollection.stories.tsx new file mode 100644 index 00000000000..fdee8270034 --- /dev/null +++ b/console/src/features/QueryCollections/hooks/useEditOperationInQueryCollection/useEditOperationInQueryCollection.stories.tsx @@ -0,0 +1,52 @@ +import React from 'react'; +import { ReactQueryDecorator } from '@/storybook/decorators/react-query'; +import { ReduxDecorator } from '@/storybook/decorators/redux-decorator'; +import ReactJson from 'react-json-view'; +import { Button } from '@/new-components/Button'; +import { Meta, Story } from '@storybook/react'; + +import { handlers } from './mocks/handlers.mock'; +import { useEditOperationInQueryCollection } from '.'; + +const UseEditOperationInQueryCollection: React.FC = () => { + const { editOperationInQueryCollection, isSuccess, isLoading, error } = + useEditOperationInQueryCollection(); + + return ( +
+ + +
+ ); +}; + +export const Primary: Story = () => { + return ; +}; + +export default { + title: 'hooks/Query Collections/useEditOperationInQueryCollection', + decorators: [ + ReduxDecorator({ tables: { currentDataSource: 'default' } }), + ReactQueryDecorator(), + ], + parameters: { + msw: handlers(1000), + }, +} as Meta; diff --git a/console/src/features/QueryCollections/hooks/useEditOperationInQueryCollection/useEditOperationInQueryCollection.test.ts b/console/src/features/QueryCollections/hooks/useEditOperationInQueryCollection/useEditOperationInQueryCollection.test.ts new file mode 100644 index 00000000000..d4ab230f6e1 --- /dev/null +++ b/console/src/features/QueryCollections/hooks/useEditOperationInQueryCollection/useEditOperationInQueryCollection.test.ts @@ -0,0 +1,37 @@ +import { setupServer } from 'msw/node'; +import { renderHook } from '@testing-library/react-hooks'; +import { handlers } from './mocks/handlers.mock'; +import { useEditOperationInQueryCollection } from '.'; +import { wrapper } from '../../../../hooks/__tests__/common/decorator'; + +const server = setupServer(); + +beforeAll(() => server.listen()); +afterAll(() => server.close()); + +describe('useEditOperationInQueryCollection', () => { + beforeEach(() => { + server.use(...handlers(100, '')); + }); + + test('When useEditOperationInQueryCollection is used with a valid input Then it should call the API with correct payload', async () => { + const { waitForValueToChange, result }: any = renderHook( + () => useEditOperationInQueryCollection(), + { wrapper } + ); + + await result.current.editOperationInQueryCollection( + 'testCollection', + 'MyQuery', + [ + { + name: 'NewMyQuery', + query: 'query NewMyQuery { user { email name}}', + }, + ] + ); + + await waitForValueToChange(() => result.current.isSuccess); + expect(result.current.isSuccess).toBe(true); + }); +}); diff --git a/console/src/features/QueryCollections/hooks/useEditOperationInQueryCollection/useEditOperationInQueryCollection.ts b/console/src/features/QueryCollections/hooks/useEditOperationInQueryCollection/useEditOperationInQueryCollection.ts new file mode 100644 index 00000000000..223aa20c02b --- /dev/null +++ b/console/src/features/QueryCollections/hooks/useEditOperationInQueryCollection/useEditOperationInQueryCollection.ts @@ -0,0 +1,60 @@ +import { useCallback } from 'react'; + +import { useMetadata, useMetadataMigration } from '@/features/MetadataAPI'; +import { QueryCollection } from '@/metadata/types'; + +export const useEditOperationInQueryCollection = () => { + const { mutate, ...rest } = useMetadataMigration(); + + const { data: metadata } = useMetadata(); + + const editOperationInQueryCollection = useCallback( + ( + queryCollection: string, + oldOperationName: string, + query: QueryCollection, + options?: Parameters[1] + ) => { + if (!queryCollection || !query || !oldOperationName) + throw Error( + `useEditOperationInQueryCollection: Invalid input - ${ + !queryCollection && 'queryCollection' + } ${!query && ', query'} ${!oldOperationName && ', oldOperationName'}` + ); + + return mutate( + { + query: { + type: 'bulk', + ...(metadata?.resource_version && { + resource_version: metadata.resource_version, + }), + args: [ + { + type: 'drop_query_from_collection', + args: { + collection_name: queryCollection, + query_name: oldOperationName, + }, + }, + { + type: 'add_query_to_collection', + args: { + collection_name: queryCollection, + query_name: query.name, + query: query.query, + }, + }, + ], + }, + }, + { + ...options, + } + ); + }, + [metadata, mutate] + ); + + return { editOperationInQueryCollection, ...rest }; +}; diff --git a/console/src/features/QueryCollections/hooks/useMoveOperationsToQueryCollection/index.ts b/console/src/features/QueryCollections/hooks/useMoveOperationsToQueryCollection/index.ts new file mode 100644 index 00000000000..e9385ad7b02 --- /dev/null +++ b/console/src/features/QueryCollections/hooks/useMoveOperationsToQueryCollection/index.ts @@ -0,0 +1 @@ +export * from './useMoveOperationsToQueryCollection'; diff --git a/console/src/features/QueryCollections/hooks/useMoveOperationsToQueryCollection/mocks/handlers.mock.ts b/console/src/features/QueryCollections/hooks/useMoveOperationsToQueryCollection/mocks/handlers.mock.ts new file mode 100644 index 00000000000..ae5b0b73595 --- /dev/null +++ b/console/src/features/QueryCollections/hooks/useMoveOperationsToQueryCollection/mocks/handlers.mock.ts @@ -0,0 +1,16 @@ +import { rest } from 'msw'; + +const baseUrl = 'http://localhost:8080'; + +export const handlers = (delay = 0, url = baseUrl) => [ + // todo export metadata mock based on the input + + rest.post(`${url}/v1/metadata`, (req, res, ctx) => { + return res( + ctx.delay(delay), + ctx.json({ + message: 'success', + }) + ); + }), +]; diff --git a/console/src/features/QueryCollections/hooks/useMoveOperationsToQueryCollection/useMoveOperationsToQueryCollection.stories.tsx b/console/src/features/QueryCollections/hooks/useMoveOperationsToQueryCollection/useMoveOperationsToQueryCollection.stories.tsx new file mode 100644 index 00000000000..837cb4e66ef --- /dev/null +++ b/console/src/features/QueryCollections/hooks/useMoveOperationsToQueryCollection/useMoveOperationsToQueryCollection.stories.tsx @@ -0,0 +1,54 @@ +import React from 'react'; +import { ReactQueryDecorator } from '@/storybook/decorators/react-query'; +import { ReduxDecorator } from '@/storybook/decorators/redux-decorator'; +import ReactJson from 'react-json-view'; +import { Button } from '@/new-components/Button'; +import { Meta, Story } from '@storybook/react'; + +import { handlers } from './mocks/handlers.mock'; +import { useMoveOperationsToQueryCollection } from '.'; + +const UseMoveOperationsToQueryCollection: React.FC = () => { + const { moveOperationToQueryCollection, isSuccess, isLoading, error } = + useMoveOperationsToQueryCollection(); + + return ( +
+ + +
+ ); +}; + +export const Primary: Story = () => { + return ; +}; + +export default { + title: 'hooks/Query Collections/useMoveOperationsToQueryCollection', + decorators: [ + ReduxDecorator({ tables: { currentDataSource: 'default' } }), + ReactQueryDecorator(), + ], + parameters: { + msw: handlers(1000), + }, +} as Meta; diff --git a/console/src/features/QueryCollections/hooks/useMoveOperationsToQueryCollection/useMoveOperationsToQueryCollection.test.ts b/console/src/features/QueryCollections/hooks/useMoveOperationsToQueryCollection/useMoveOperationsToQueryCollection.test.ts new file mode 100644 index 00000000000..59375299c42 --- /dev/null +++ b/console/src/features/QueryCollections/hooks/useMoveOperationsToQueryCollection/useMoveOperationsToQueryCollection.test.ts @@ -0,0 +1,37 @@ +import { setupServer } from 'msw/node'; +import { renderHook } from '@testing-library/react-hooks'; +import { handlers } from './mocks/handlers.mock'; +import { useMoveOperationsToQueryCollection } from '.'; +import { wrapper } from '../../../../hooks/__tests__/common/decorator'; + +const server = setupServer(); + +beforeAll(() => server.listen()); +afterAll(() => server.close()); + +describe('useMoveOperationsToQueryCollection', () => { + beforeEach(() => { + server.use(...handlers(100, '')); + }); + + test('When useMoveOperationsToQueryCollection is used with a valid input Then it should call the API with correct payload', async () => { + const { waitForValueToChange, result }: any = renderHook( + () => useMoveOperationsToQueryCollection(), + { wrapper } + ); + + await result.current.moveOperationToQueryCollection( + 'fromCollection', + 'targetCollection', + [ + { + name: 'NewMyQuery', + query: 'query NewMyQuery { user { email name}}', + }, + ] + ); + + await waitForValueToChange(() => result.current.isSuccess); + expect(result.current.isSuccess).toBe(true); + }); +}); diff --git a/console/src/features/QueryCollections/hooks/useMoveOperationsToQueryCollection/useMoveOperationsToQueryCollection.ts b/console/src/features/QueryCollections/hooks/useMoveOperationsToQueryCollection/useMoveOperationsToQueryCollection.ts new file mode 100644 index 00000000000..74e5a81d7c0 --- /dev/null +++ b/console/src/features/QueryCollections/hooks/useMoveOperationsToQueryCollection/useMoveOperationsToQueryCollection.ts @@ -0,0 +1,66 @@ +import { useCallback } from 'react'; + +import { useMetadata, useMetadataMigration } from '@/features/MetadataAPI'; +import { QueryCollection } from '@/metadata/types'; + +export const useMoveOperationsToQueryCollection = () => { + const { mutate, ...rest } = useMetadataMigration(); + + const { data: metadata } = useMetadata(); + + const moveOperationToQueryCollection = useCallback( + ( + fromCollection: string, + toCollection: string, + // considering the move action can be done on multiple queries, this hook can handle multiple queries + queries: QueryCollection[], + options?: Parameters[1] + ) => { + if (!fromCollection || !queries || !toCollection) + throw Error( + `useMoveOperationsToQueryCollection: Invalid input - ${ + !fromCollection && 'fromCollection' + } ${!queries && ', queries'} ${!toCollection && ', toCollection'}` + ); + + // considering there is no direct API to edit an operation, we use bulk transaction to drop and add an operation. + // ie. drop_query_from_collection and then recreate with add_query_to_collection in a single transaction + + return mutate( + { + query: { + type: 'bulk', + ...(metadata?.resource_version && { + resource_version: metadata.resource_version, + }), + args: queries + .map(query => [ + { + type: 'drop_query_from_collection', + args: { + collection_name: fromCollection, + query_name: query.name, + }, + }, + { + type: 'add_query_to_collection', + args: { + collection_name: toCollection, + query_name: query.name, + query: query.query, + }, + }, + ]) + .flat(), + }, + }, + { + ...options, + } + ); + }, + [metadata, mutate] + ); + + return { moveOperationToQueryCollection, ...rest }; +}; diff --git a/console/src/features/QueryCollections/hooks/useRemoveOperationsFromQueryCollection/index.ts b/console/src/features/QueryCollections/hooks/useRemoveOperationsFromQueryCollection/index.ts new file mode 100644 index 00000000000..5349c8b0437 --- /dev/null +++ b/console/src/features/QueryCollections/hooks/useRemoveOperationsFromQueryCollection/index.ts @@ -0,0 +1 @@ +export * from './useRemoveOperationsFromQueryCollection'; diff --git a/console/src/features/QueryCollections/hooks/useRemoveOperationsFromQueryCollection/mocks/handlers.mock.ts b/console/src/features/QueryCollections/hooks/useRemoveOperationsFromQueryCollection/mocks/handlers.mock.ts new file mode 100644 index 00000000000..723ce8da1a0 --- /dev/null +++ b/console/src/features/QueryCollections/hooks/useRemoveOperationsFromQueryCollection/mocks/handlers.mock.ts @@ -0,0 +1,39 @@ +import { rest } from 'msw'; +import { TMigration } from '../../../../MetadataAPI/hooks/useMetadataMigration'; + +const baseUrl = 'http://localhost:8080'; + +export const handlers = (delay = 0, url = baseUrl) => [ + // todo export metadata mock based on the input + + rest.post(`${url}/v1/metadata`, (req, res, ctx) => { + const body = req.body as TMigration['query']; + + if (body?.args && body?.args?.[0]?.type === 'add_query_to_collection') { + if ( + body?.args?.[0]?.query_name === 'MyQuery33' && + body?.args?.[0]?.collection_name === 'testCollection' + ) + return res( + ctx.delay(delay), + ctx.json({ + message: 'success', + }) + ); + return res( + ctx.delay(delay), + ctx.status(500), + ctx.json({ + message: 'error', + }) + ); + } + + return res( + ctx.delay(delay), + ctx.json({ + message: 'success', + }) + ); + }), +]; diff --git a/console/src/features/QueryCollections/hooks/useRemoveOperationsFromQueryCollection/useRemoveOperationsFromQueryCollection.stories.tsx b/console/src/features/QueryCollections/hooks/useRemoveOperationsFromQueryCollection/useRemoveOperationsFromQueryCollection.stories.tsx new file mode 100644 index 00000000000..873b629bea8 --- /dev/null +++ b/console/src/features/QueryCollections/hooks/useRemoveOperationsFromQueryCollection/useRemoveOperationsFromQueryCollection.stories.tsx @@ -0,0 +1,54 @@ +import React from 'react'; +import { ReactQueryDecorator } from '@/storybook/decorators/react-query'; +import { ReduxDecorator } from '@/storybook/decorators/redux-decorator'; +import ReactJson from 'react-json-view'; +import { Button } from '@/new-components/Button'; +import { Meta, Story } from '@storybook/react'; + +import { handlers } from './mocks/handlers.mock'; +import { useRemoveOperationsFromQueryCollection } from '.'; + +const UseRemoveOperationsFromQueryCollection: React.FC = () => { + const { removeOperationsFromQueryCollection, isSuccess, isLoading, error } = + useRemoveOperationsFromQueryCollection(); + + return ( +
+ + +
+ ); +}; + +export const Primary: Story = () => { + return ; +}; + +export default { + title: 'hooks/Query Collections/useRemoveOperationsFromQueryCollection', + decorators: [ + ReduxDecorator({ tables: { currentDataSource: 'default' } }), + ReactQueryDecorator(), + ], + parameters: { + msw: handlers(1000), + }, +} as Meta; diff --git a/console/src/features/QueryCollections/hooks/useRemoveOperationsFromQueryCollection/useRemoveOperationsFromQueryCollection.test.ts b/console/src/features/QueryCollections/hooks/useRemoveOperationsFromQueryCollection/useRemoveOperationsFromQueryCollection.test.ts new file mode 100644 index 00000000000..67c2806f46a --- /dev/null +++ b/console/src/features/QueryCollections/hooks/useRemoveOperationsFromQueryCollection/useRemoveOperationsFromQueryCollection.test.ts @@ -0,0 +1,33 @@ +import { setupServer } from 'msw/node'; +import { renderHook } from '@testing-library/react-hooks'; +import { handlers } from './mocks/handlers.mock'; +import { useRemoveOperationsFromQueryCollection } from '.'; +import { wrapper } from '../../../../hooks/__tests__/common/decorator'; + +const server = setupServer(); + +beforeAll(() => server.listen()); +afterAll(() => server.close()); + +describe('useRemoveOperationsFromQueryCollection', () => { + beforeEach(() => { + server.use(...handlers(1, '')); + }); + + test('When useRemoveOperationsFromQueryCollection is used with a valid QueryCollection Then it should call the API with correct payload', async () => { + const { waitForValueToChange, result }: any = renderHook( + () => useRemoveOperationsFromQueryCollection(), + { wrapper } + ); + + await result.current.removeOperationsFromQueryCollection('testCollection', [ + { + name: 'MyQuery33', + query: 'query MyQuery { user { email name}}', + }, + ]); + + await waitForValueToChange(() => result.current.isSuccess); + expect(result.current.isSuccess).toBe(true); + }); +}); diff --git a/console/src/features/QueryCollections/hooks/useRemoveOperationsFromQueryCollection/useRemoveOperationsFromQueryCollection.ts b/console/src/features/QueryCollections/hooks/useRemoveOperationsFromQueryCollection/useRemoveOperationsFromQueryCollection.ts new file mode 100644 index 00000000000..7869dd15e21 --- /dev/null +++ b/console/src/features/QueryCollections/hooks/useRemoveOperationsFromQueryCollection/useRemoveOperationsFromQueryCollection.ts @@ -0,0 +1,48 @@ +import { useCallback } from 'react'; + +import { useMetadata, useMetadataMigration } from '@/features/MetadataAPI'; +import { QueryCollection } from '@/metadata/types'; + +export const useRemoveOperationsFromQueryCollection = () => { + const { mutate, ...rest } = useMetadataMigration(); + + const { data: metadata } = useMetadata(); + + const removeOperationsFromQueryCollection = useCallback( + ( + queryCollection: string, + queries: QueryCollection[], + options?: Parameters[1] + ) => { + if (!queryCollection || !queries) + throw Error( + `useRemoveOperationsFromQueryCollection: Invalid input - ${ + queryCollection && 'queryCollection' + } ${queries && 'queries'}` + ); + return mutate( + { + query: { + type: 'bulk', + ...(metadata?.resource_version && { + resource_version: metadata.resource_version, + }), + args: queries.map(query => ({ + type: 'drop_query_from_collection', + args: { + collection_name: queryCollection, + query_name: query.name, + }, + })), + }, + }, + { + ...options, + } + ); + }, + [metadata, mutate] + ); + + return { removeOperationsFromQueryCollection, ...rest }; +};