diff --git a/apps/web/src/api/buster_rest/slack/index.ts b/apps/web/src/api/buster_rest/slack/index.ts index e69de29bb..156c51906 100644 --- a/apps/web/src/api/buster_rest/slack/index.ts +++ b/apps/web/src/api/buster_rest/slack/index.ts @@ -0,0 +1,2 @@ +export * from './request'; +export * from './queryRequests'; diff --git a/apps/web/src/api/buster_rest/slack/queryRequests.ts b/apps/web/src/api/buster_rest/slack/queryRequests.ts index e69de29bb..9403d0673 100644 --- a/apps/web/src/api/buster_rest/slack/queryRequests.ts +++ b/apps/web/src/api/buster_rest/slack/queryRequests.ts @@ -0,0 +1,98 @@ +import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; +import { queryKeys } from '@/api/query_keys'; +import { useBusterNotifications } from '@/context/BusterNotifications'; +import { useMemoizedFn } from '@/hooks'; +import type { + InitiateOAuthRequest, + UpdateIntegrationRequest +} from '@buster/server-shared/slack'; +import { + initiateSlackOAuth, + getSlackIntegration, + removeSlackIntegration, + updateSlackIntegration, + getSlackChannels +} from './request'; + +// GET /api/v2/slack/integration +export const useGetSlackIntegration = (enabled = true) => { + return useQuery({ + ...queryKeys.slackGetIntegration, + queryFn: getSlackIntegration, + enabled + }); +}; + +// GET /api/v2/slack/channels +export const useGetSlackChannels = (enabled = true) => { + return useQuery({ + ...queryKeys.slackGetChannels, + queryFn: getSlackChannels, + enabled + }); +}; + +// POST /api/v2/slack/auth/init +export const useInitiateSlackOAuth = () => { + return useMutation({ + mutationFn: initiateSlackOAuth + }); +}; + +// PUT /api/v2/slack/integration +export const useUpdateSlackIntegration = () => { + const queryClient = useQueryClient(); + + return useMutation({ + mutationFn: updateSlackIntegration, + onSuccess: () => { + // Invalidate the integration query to refetch the updated data + queryClient.invalidateQueries({ + queryKey: queryKeys.slackGetIntegration.queryKey, + refetchType: 'all' + }); + } + }); +}; + +// DELETE /api/v2/slack/integration +export const useRemoveSlackIntegration = () => { + const queryClient = useQueryClient(); + const { openConfirmModal } = useBusterNotifications(); + + const mutationFn = useMemoizedFn( + async ({ ignoreConfirm = false }: { ignoreConfirm?: boolean } = {}) => { + const method = async () => { + return await removeSlackIntegration(); + }; + + if (ignoreConfirm) { + return method(); + } + + return openConfirmModal({ + title: 'Remove Slack Integration', + content: 'Are you sure you want to remove the Slack integration? This will disconnect your workspace from Slack.', + primaryButtonProps: { + text: 'Remove' + }, + onOk: method + }); + } + ); + + return useMutation({ + mutationFn, + onSuccess: () => { + // Invalidate both integration and channels queries + queryClient.invalidateQueries({ + queryKey: queryKeys.slackGetIntegration.queryKey, + refetchType: 'all' + }); + queryClient.invalidateQueries({ + queryKey: queryKeys.slackGetChannels.queryKey, + refetchType: 'all' + }); + } + }); +}; diff --git a/apps/web/src/api/buster_rest/slack/request.ts b/apps/web/src/api/buster_rest/slack/request.ts index 526ed6f37..5accad851 100644 --- a/apps/web/src/api/buster_rest/slack/request.ts +++ b/apps/web/src/api/buster_rest/slack/request.ts @@ -1 +1,35 @@ import { mainApiV2 } from '../instances'; +import type { + InitiateOAuthRequest, + UpdateIntegrationRequest, + InitiateOAuthResponse, + GetIntegrationResponse, + RemoveIntegrationResponse, + UpdateIntegrationResponse, + GetChannelsResponse +} from '@buster/server-shared/slack'; + +// POST /api/v2/slack/auth/init +export const initiateSlackOAuth = async (data: InitiateOAuthRequest) => { + return mainApiV2.post('/slack/auth/init', data).then((res) => res.data); +}; + +// GET /api/v2/slack/integration +export const getSlackIntegration = async () => { + return mainApiV2.get('/slack/integration').then((res) => res.data); +}; + +// DELETE /api/v2/slack/integration +export const removeSlackIntegration = async () => { + return mainApiV2.delete('/slack/integration').then((res) => res.data); +}; + +// PUT /api/v2/slack/integration +export const updateSlackIntegration = async (data: UpdateIntegrationRequest) => { + return mainApiV2.put('/slack/integration', data).then((res) => res.data); +}; + +// GET /api/v2/slack/channels +export const getSlackChannels = async () => { + return mainApiV2.get('/slack/channels').then((res) => res.data); +}; diff --git a/apps/web/src/api/query_keys/index.ts b/apps/web/src/api/query_keys/index.ts index ceab64d1d..0a304bd60 100644 --- a/apps/web/src/api/query_keys/index.ts +++ b/apps/web/src/api/query_keys/index.ts @@ -11,6 +11,7 @@ import { searchQueryKeys } from './search'; import { termsQueryKeys } from './terms'; import { userQueryKeys } from './users'; import { securityQueryKeys } from './security'; +import { slackQueryKeys } from './slack'; export const queryKeys = { ...datasetQueryKeys, @@ -25,5 +26,6 @@ export const queryKeys = { ...datasetGroupQueryKeys, ...permissionGroupQueryKeys, ...currencyQueryKeys, - ...securityQueryKeys + ...securityQueryKeys, + ...slackQueryKeys }; diff --git a/apps/web/src/api/query_keys/slack.ts b/apps/web/src/api/query_keys/slack.ts new file mode 100644 index 000000000..091acec57 --- /dev/null +++ b/apps/web/src/api/query_keys/slack.ts @@ -0,0 +1,18 @@ +import type { + GetIntegrationResponse, + GetChannelsResponse +} from '@buster/server-shared/slack'; +import { queryOptions } from '@tanstack/react-query'; + +export const slackGetIntegration = queryOptions({ + queryKey: ['slack', 'integration'] +}); + +export const slackGetChannels = queryOptions({ + queryKey: ['slack', 'channels'] +}); + +export const slackQueryKeys = { + slackGetIntegration, + slackGetChannels +}; \ No newline at end of file