Skip to content

Commit

Permalink
A4A: Implement the 'Remove member' action. (#94102)
Browse files Browse the repository at this point in the history
* Move handle member action to a hook.

* Add handler for 'Remove member' action.

* Fix success message.

* Temporarily disable password reset.

* Address PR comments.
  • Loading branch information
jkguidaven authored Sep 3, 2024
1 parent b5b89c2 commit 8b21a6e
Show file tree
Hide file tree
Showing 4 changed files with 122 additions and 31 deletions.
41 changes: 41 additions & 0 deletions client/a8c-for-agencies/data/team/use-remove-member.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { useMutation, UseMutationOptions, UseMutationResult } from '@tanstack/react-query';
import wpcom from 'calypso/lib/wp';
import { useSelector } from 'calypso/state';
import { getActiveAgencyId } from 'calypso/state/a8c-for-agencies/agency/selectors';

interface APIError {
status: number;
code: string | null;
message: string;
}

export interface Params {
id: number;
}

interface APIResponse {
success: boolean;
}

function removeMemberMutation( params: Params, agencyId?: number ): Promise< APIResponse > {
if ( ! agencyId ) {
throw new Error( 'Agency ID is required to remove a team member' );
}

return wpcom.req.post( {
apiNamespace: 'wpcom/v2',
path: `/agency/${ agencyId }/users/${ params.id }`,
method: 'DELETE',
} );
}

export default function useRemoveMemberMutation< TContext = unknown >(
options?: UseMutationOptions< APIResponse, APIError, Params, TContext >
): UseMutationResult< APIResponse, APIError, Params, TContext > {
const agencyId = useSelector( getActiveAgencyId );

return useMutation< APIResponse, APIError, Params, TContext >( {
...options,
mutationFn: ( args ) => removeMemberMutation( args, agencyId ),
} );
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import { useTranslate } from 'i18n-calypso';
import { useCallback } from 'react';
import useCancelMemberInviteMutation from 'calypso/a8c-for-agencies/data/team/use-cancel-member-invite';
import useRemoveMemberMutation from 'calypso/a8c-for-agencies/data/team/use-remove-member';
import { useDispatch } from 'calypso/state';
import { errorNotice, successNotice } from 'calypso/state/notices/actions';
import { TeamMember } from '../types';

type Props = {
onRefetchList?: () => void;
};

export default function useHandleMemberAction( { onRefetchList }: Props ) {
const translate = useTranslate();
const dispatch = useDispatch();

const { mutate: cancelMemberInvite } = useCancelMemberInviteMutation();

const { mutate: removeMember } = useRemoveMemberMutation();

return useCallback(
( action: string, item: TeamMember ) => {
if ( action === 'cancel-user-invite' ) {
cancelMemberInvite(
{ id: item.id },
{
onSuccess: () => {
dispatch(
successNotice( translate( 'The invitation has been successfully cancelled.' ), {
id: 'cancel-user-invite-success',
duration: 5000,
} )
);
onRefetchList?.();
},

onError: ( error ) => {
dispatch(
errorNotice( error.message, {
id: 'cancel-user-invite-error',
duration: 5000,
} )
);
},
}
);
}

if ( action === 'delete-user' ) {
removeMember(
{ id: item.id },
{
onSuccess: () => {
dispatch(
successNotice( translate( 'The member has been successfully removed.' ), {
id: 'remove-user-success',
duration: 5000,
} )
);
onRefetchList?.();
},

onError: ( error ) => {
dispatch(
errorNotice( error.message, {
id: 'remove-user-error',
duration: 5000,
} )
);
},
}
);
}
},
[ cancelMemberInvite, dispatch, onRefetchList, removeMember, translate ]
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ export const ActionColumn = ( {
{
name: 'password-reset',
label: translate( 'Send password reset' ),
isEnabled: true,
isEnabled: false, // FIXME: Implement this action
},
{
name: 'delete-user',
Expand Down
33 changes: 3 additions & 30 deletions client/a8c-for-agencies/sections/team/primary/team-list/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import page from '@automattic/calypso-router';
import { useDesktopBreakpoint } from '@automattic/viewport-react';
import { Button } from '@wordpress/components';
import { useTranslate } from 'i18n-calypso';
import { ReactNode, useCallback, useMemo, useState } from 'react';
import { ReactNode, useMemo, useState } from 'react';
import { initialDataViewsState } from 'calypso/a8c-for-agencies/components/items-dashboard/constants';
import ItemsDataViews from 'calypso/a8c-for-agencies/components/items-dashboard/items-dataviews';
import { DataViewsState } from 'calypso/a8c-for-agencies/components/items-dashboard/items-dataviews/interfaces';
Expand All @@ -14,13 +14,12 @@ import LayoutHeader, {
} from 'calypso/a8c-for-agencies/components/layout/header';
import LayoutTop from 'calypso/a8c-for-agencies/components/layout/top';
import { A4A_TEAM_INVITE_LINK } from 'calypso/a8c-for-agencies/components/sidebar-menu/lib/constants';
import useCancelMemberInviteMutation from 'calypso/a8c-for-agencies/data/team/use-cancel-member-invite';
import { useDispatch, useSelector } from 'calypso/state';
import { hasAgencyCapability } from 'calypso/state/a8c-for-agencies/agency/selectors';
import { A4AStore } from 'calypso/state/a8c-for-agencies/types';
import { recordTracksEvent } from 'calypso/state/analytics/actions';
import { getCurrentUser } from 'calypso/state/current-user/selectors';
import { errorNotice, successNotice } from 'calypso/state/notices/actions';
import useHandleMemberAction from '../../hooks/use-handle-member-action';
import { useMemberList } from '../../hooks/use-member-list';
import { TeamMember } from '../../types';
import GetStarted from '../get-started';
Expand All @@ -38,40 +37,14 @@ export default function TeamList() {

const { members, hasMembers, isPending, refetch } = useMemberList();

const { mutate: cancelMemberInvite } = useCancelMemberInviteMutation();

const title = translate( 'Manage team members' );

const onInviteClick = () => {
dispatch( recordTracksEvent( 'calypso_a4a_team_invite_team_member_click' ) );
page( A4A_TEAM_INVITE_LINK );
};

const handleAction = useCallback(
( action: string, item: TeamMember ) => {
if ( action === 'cancel-user-invite' ) {
cancelMemberInvite(
{ id: item.id },
{
onSuccess: () => {
dispatch(
successNotice( 'The invitation has been successfully cancelled.', {
id: 'cancel-user-invite-success',
duration: 5000,
} )
);
refetch();
},

onError: ( error ) => {
dispatch( errorNotice( error.message ) );
},
}
);
}
},
[ cancelMemberInvite, dispatch, refetch ]
);
const handleAction = useHandleMemberAction( { onRefetchList: refetch } );

const canRemove = useSelector( ( state: A4AStore ) =>
hasAgencyCapability( state, 'a4a_remove_users' )
Expand Down

0 comments on commit 8b21a6e

Please sign in to comment.