diff --git a/frontend/src/component/integrations/IntegrationList/ConfiguredIntegrations/ConfiguredIntegrations.tsx b/frontend/src/component/integrations/IntegrationList/ConfiguredIntegrations/ConfiguredIntegrations.tsx index 523802857c..4c2f9466fc 100644 --- a/frontend/src/component/integrations/IntegrationList/ConfiguredIntegrations/ConfiguredIntegrations.tsx +++ b/frontend/src/component/integrations/IntegrationList/ConfiguredIntegrations/ConfiguredIntegrations.tsx @@ -27,23 +27,25 @@ export const ConfiguredIntegrations: VFC = ({ isLoading={loading} > - {addons?.map( - ({ - id, - enabled, - provider, - description, - // events, - // projects, - }) => { + {addons + ?.sort(({ id: a }, { id: b }) => a - b) + .map(addon => { + const { + id, + enabled, + provider, + description, + // events, + // projects, + } = addon; const providerConfig = providers.find( item => item.name === provider ); return ( = ({ link={`/integrations/edit/${id}`} /> ); - } - )} + })} ); diff --git a/frontend/src/component/integrations/IntegrationList/IntegrationCard/IntegrationCard.tsx b/frontend/src/component/integrations/IntegrationList/IntegrationCard/IntegrationCard.tsx index cde1781f78..a424c807a3 100644 --- a/frontend/src/component/integrations/IntegrationList/IntegrationCard/IntegrationCard.tsx +++ b/frontend/src/component/integrations/IntegrationList/IntegrationCard/IntegrationCard.tsx @@ -6,6 +6,7 @@ import { ConditionallyRender } from 'component/common/ConditionallyRender/Condit import ChevronRightIcon from '@mui/icons-material/ChevronRight'; import { Badge } from 'component/common/Badge/Badge'; import { IntegrationCardMenu } from './IntegrationCardMenu/IntegrationCardMenu'; +import type { AddonSchema } from 'openapi'; interface IIntegrationCardProps { id?: string | number; @@ -16,6 +17,7 @@ interface IIntegrationCardProps { isEnabled?: boolean; configureActionText?: string; link: string; + addon?: AddonSchema; } const StyledLink = styled(Link)(({ theme }) => ({ @@ -55,15 +57,15 @@ const StyledAction = styled(Typography)(({ theme }) => ({ })); export const IntegrationCard: VFC = ({ - id, icon, title, description, isEnabled, configureActionText = 'Configure', link, + addon, }) => { - const isConfigured = id !== undefined; + const isConfigured = addon !== undefined; return ( @@ -85,7 +87,7 @@ export const IntegrationCard: VFC = ({ /> } + show={} /> diff --git a/frontend/src/component/integrations/IntegrationList/IntegrationCard/IntegrationCardMenu/IntegrationCardMenu.tsx b/frontend/src/component/integrations/IntegrationList/IntegrationCard/IntegrationCardMenu/IntegrationCardMenu.tsx index f3090843f8..3e8e634bf8 100644 --- a/frontend/src/component/integrations/IntegrationList/IntegrationCard/IntegrationCardMenu/IntegrationCardMenu.tsx +++ b/frontend/src/component/integrations/IntegrationList/IntegrationCard/IntegrationCardMenu/IntegrationCardMenu.tsx @@ -1,4 +1,4 @@ -import { useState, VFC } from 'react'; +import { useCallback, useState, VFC } from 'react'; import { IconButton, ListItemIcon, @@ -16,9 +16,14 @@ import { UPDATE_ADDON, } from 'component/providers/AccessProvider/permissions'; import { useHasRootAccess } from 'hooks/useHasAccess'; +import useAddonsApi from 'hooks/api/actions/useAddonsApi/useAddonsApi'; +import type { AddonSchema } from 'openapi'; +import useAddons from 'hooks/api/getters/useAddons/useAddons'; +import useToast from 'hooks/useToast'; +import { formatUnknownError } from 'utils/formatUnknownError'; interface IIntegrationCardMenuProps { - id: string; + addon: AddonSchema; } const StyledMenu = styled('div')(({ theme }) => ({ @@ -30,9 +35,14 @@ const StyledMenu = styled('div')(({ theme }) => ({ alignItems: 'center', })); -export const IntegrationCardMenu: VFC = ({ id }) => { +export const IntegrationCardMenu: VFC = ({ + addon, +}) => { const [open, setOpen] = useState(false); const [anchorEl, setAnchorEl] = useState(null); + const { updateAddon, removeAddon } = useAddonsApi(); + const { refetchAddons } = useAddons(); + const { setToastData, setToastApiError } = useToast(); const handleMenuClick = (event: React.SyntheticEvent) => { event.preventDefault(); @@ -47,6 +57,36 @@ export const IntegrationCardMenu: VFC = ({ id }) => { const updateAccess = useHasRootAccess(UPDATE_ADDON); const deleteAccess = useHasRootAccess(DELETE_ADDON); + const toggleIntegration = useCallback(async () => { + try { + await updateAddon({ ...addon, enabled: !addon.enabled }); + refetchAddons(); + setToastData({ + type: 'success', + title: 'Success', + text: !addon.enabled + ? 'Integration is now enabled' + : 'Integration is now disabled', + }); + } catch (error: unknown) { + setToastApiError(formatUnknownError(error)); + } + }, [setToastApiError, refetchAddons, setToastData, updateAddon]); + + const deleteIntegration = useCallback(async () => { + try { + await removeAddon(addon.id); + refetchAddons(); + setToastData({ + type: 'success', + title: 'Success', + text: 'Integration has been deleted', + }); + } catch (error: unknown) { + setToastApiError(formatUnknownError(error)); + } + }, [setToastApiError, refetchAddons, setToastData, removeAddon]); + return ( @@ -73,54 +113,37 @@ export const IntegrationCardMenu: VFC = ({ id }) => { vertical: 'top', horizontal: 'right', }} - // style={{ top: 0, left: -100 }} onClick={event => { event.preventDefault(); }} onClose={handleMenuClick} > { - // e.preventDefault(); - // navigate( - // getProjectEditPath( - // id, - // Boolean( - // uiConfig.flags - // .newProjectLayout - // ) - // ) - // ); - // }} + onClick={e => { + e.preventDefault(); + toggleIntegration(); + }} disabled={!updateAccess} > - Disable + + {addon.enabled ? 'Disable' : 'Enable'} + {' '} setRemoveDialogOpen(true)} + onClick={e => { + e.preventDefault(); + deleteIntegration(); + }} > Delete - {/* { - e.preventDefault(); - setShowDelDialog(true); - }} - disabled={!canDeleteProject} - > - - {id === DEFAULT_PROJECT_ID && - !canDeleteProject - ? "You can't delete the default project" - : 'Delete project'} - */} );