Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@ import type {
} from 'sentry/types/integrations';
import type {Team} from 'sentry/types/organization';
import {getApiUrl} from 'sentry/utils/api/getApiUrl';
import {useApiQuery} from 'sentry/utils/queryClient';
import {useApi} from 'sentry/utils/useApi';
import {fetchMutation, useApiQuery, useMutation} from 'sentry/utils/queryClient';
import {useLocation} from 'sentry/utils/useLocation';
import {useOrganization} from 'sentry/utils/useOrganization';

Expand All @@ -26,7 +25,6 @@ export function IntegrationExternalTeamMappings(props: Props) {
const {integration} = props;
const organization = useOrganization();
const location = useLocation();
const api = useApi({persistInFlight: true});
const ORGANIZATION_TEAMS_ENDPOINT = getApiUrl(
'/organizations/$organizationIdOrSlug/teams/',
{
Expand Down Expand Up @@ -59,32 +57,32 @@ export function IntegrationExternalTeamMappings(props: Props) {
return Promise.all([refetchTeams(), refetchInitialResults()]);
};

if (isTeamsPending || isInitialResultsPending) {
return <LoadingIndicator />;
}
if (isTeamsError || isInitialResultsError) {
return <LoadingError onRetry={() => fetchData()} />;
}

const handleDelete = async (mapping: ExternalActorMapping) => {
try {
const deleteMutation = useMutation({
mutationFn: (mapping: ExternalActorMapping) => {
const team = teams.find(item => item.id === mapping.teamId);
if (!team) {
throw new Error('Cannot find correct team slug.');
}
const endpoint = `/teams/${organization.slug}/${team.slug}/external-teams/${mapping.id}/`;

await api.requestPromise(endpoint, {
return fetchMutation({
url: `/teams/${organization.slug}/${team.slug}/external-teams/${mapping.id}/`,
method: 'DELETE',
});
// remove config and update state
},
onSuccess: () => {
addSuccessMessage(t('Deletion successful'));
fetchData();
} catch {
// no 4xx errors should happen on delete
},
onError: () => {
addErrorMessage(t('An error occurred'));
}
};
},
});

if (isTeamsPending || isInitialResultsPending) {
return <LoadingIndicator />;
}
if (isTeamsError || isInitialResultsError) {
return <LoadingError onRetry={() => fetchData()} />;
}

const handleSubmitSuccess = () => {
fetchData();
Expand Down Expand Up @@ -146,7 +144,7 @@ export function IntegrationExternalTeamMappings(props: Props) {
getBaseFormEndpoint={mapping => getBaseFormEndpoint(mapping)}
defaultOptions={defaultTeamOptions()}
onCreate={onCreate}
onDelete={handleDelete}
onDelete={deleteMutation.mutate}
onSubmitSuccess={async () => {
await fetchData();
}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,7 @@ import type {
} from 'sentry/types/integrations';
import type {Member} from 'sentry/types/organization';
import {getApiUrl} from 'sentry/utils/api/getApiUrl';
import {useApiQuery} from 'sentry/utils/queryClient';
import {useApi} from 'sentry/utils/useApi';
import {fetchMutation, useApiQuery, useMutation} from 'sentry/utils/queryClient';
import {useOrganization} from 'sentry/utils/useOrganization';

import {IntegrationExternalMappingForm} from './integrationExternalMappingForm';
Expand All @@ -27,7 +26,6 @@ type Props = {
export function IntegrationExternalUserMappings(props: Props) {
const {integration} = props;
const organization = useOrganization();
const api = useApi({persistInFlight: true});

const DATA_ENDPOINT = getApiUrl('/organizations/$organizationIdOrSlug/members/', {
path: {organizationIdOrSlug: organization.slug},
Expand Down Expand Up @@ -62,30 +60,28 @@ export function IntegrationExternalUserMappings(props: Props) {
return Promise.all([refetchMembers(), refetchInitialResults()]);
};

const deleteMutation = useMutation({
mutationFn: (mapping: ExternalActorMapping) =>
fetchMutation({
url: `/organizations/${organization.slug}/external-users/${mapping.id}/`,
method: 'DELETE',
}),
onSuccess: () => {
addSuccessMessage(t('Deletion successful'));
fetchData();
},
onError: () => {
addErrorMessage(t('An error occurred'));
},
});

if (isMembersPending || isInitialResultsPending) {
return <LoadingIndicator />;
}
if (isMembersError || isInitialResultsError) {
return <LoadingError onRetry={() => fetchData()} />;
}

const handleDelete = async (mapping: ExternalActorMapping) => {
try {
await api.requestPromise(
`/organizations/${organization.slug}/external-users/${mapping.id}/`,
{
method: 'DELETE',
}
);
// remove config and update state
addSuccessMessage(t('Deletion successful'));
fetchData();
} catch {
// no 4xx errors should happen on delete
addErrorMessage(t('An error occurred'));
}
};

const handleSubmitSuccess = () => {
// Don't bother updating state. The info is in array of objects for each object in another array of objects.
// Easier and less error-prone to re-fetch the data and re-calculate state.
Expand Down Expand Up @@ -139,7 +135,7 @@ export function IntegrationExternalUserMappings(props: Props) {
getBaseFormEndpoint={() => BASE_FORM_ENDPOINT}
defaultOptions={defaultUserOptions}
onCreate={openMembersModal}
onDelete={handleDelete}
onDelete={deleteMutation.mutate}
onSubmitSuccess={async () => {
await fetchData();
}}
Expand Down
Loading