diff --git a/components/messages.js b/components/messages.js index 3f888e90..46586916 100644 --- a/components/messages.js +++ b/components/messages.js @@ -7,6 +7,7 @@ export const labels = defineMessages({ cancel: { id: 'label.cancel', defaultMessage: 'Cancel' }, continue: { id: 'label.continue', defaultMessage: 'Continue' }, delete: { id: 'label.delete', defaultMessage: 'Delete' }, + leave: { id: 'label.leave', defaultMessage: 'Leave' }, users: { id: 'label.users', defaultMessage: 'Users' }, createUser: { id: 'label.create-user', defaultMessage: 'Create user' }, username: { id: 'label.username', defaultMessage: 'Username' }, @@ -67,6 +68,7 @@ export const labels = defineMessages({ dateRange: { id: 'label.date-range', defaultMessage: 'Date range' }, viewDetails: { id: 'label.view-details', defaultMessage: 'View details' }, deleteTeam: { id: 'label.delete-team', defaultMessage: 'Delete team' }, + leaveTeam: { id: 'label.leave-team', defaultMessage: 'Leave team' }, refresh: { id: 'label.refresh', defaultMessage: 'Refresh' }, pages: { id: 'label.pages', defaultMessage: 'Pages' }, referrers: { id: 'label.referrers', defaultMessage: 'Referrers' }, @@ -123,6 +125,10 @@ export const messages = defineMessages({ id: 'message.delete-user-warning', defaultMessage: 'Are you sure you want to delete the user {username}?', }, + leaveTeamWarning: { + id: 'message.leave-team-warning', + defaultMessage: 'Are you sure you want to leave the team {name}?', + }, deleteTeamWarning: { id: 'message.delete-team-warning', defaultMessage: 'Are you sure you want to delete the team {name}?', diff --git a/components/pages/settings/teams/TeamLeaveForm.js b/components/pages/settings/teams/TeamLeaveForm.js new file mode 100644 index 00000000..8b75ddb9 --- /dev/null +++ b/components/pages/settings/teams/TeamLeaveForm.js @@ -0,0 +1,32 @@ +import { Button, Form, FormButtons, SubmitButton } from 'react-basics'; +import useApi from 'hooks/useApi'; +import useMessages from 'hooks/useMessages'; + +export default function TeamLeaveForm({ teamUserId, teamName, onSave, onClose }) { + const { formatMessage, labels, messages, FormattedMessage } = useMessages(); + const { del, useMutation } = useApi(); + const { mutate, error, isLoading } = useMutation(data => del(`/teamUsers/${teamUserId}`, data)); + + const handleSubmit = async data => { + mutate(data, { + onSuccess: async () => { + onSave(); + onClose(); + }, + }); + }; + + return ( +
+ ); +} diff --git a/components/pages/settings/teams/TeamMembers.js b/components/pages/settings/teams/TeamMembers.js index 2e9b87f7..ab435c4d 100644 --- a/components/pages/settings/teams/TeamMembers.js +++ b/components/pages/settings/teams/TeamMembers.js @@ -6,7 +6,7 @@ import useMessages from 'hooks/useMessages'; export default function TeamMembers({ teamId, readOnly }) { const { toast, showToast } = useToast(); const { get, useQuery } = useApi(); - const { formatMessage, labels } = useMessages(); + const { formatMessage, messages } = useMessages(); const { data, isLoading, refetch } = useQuery(['teams:users', teamId], () => get(`/teams/${teamId}/users`), ); @@ -17,7 +17,7 @@ export default function TeamMembers({ teamId, readOnly }) { const handleSave = async () => { await refetch(); - showToast({ message: formatMessage(labels.saved), variant: 'success' }); + showToast({ message: formatMessage(messages.saved), variant: 'success' }); }; return ( diff --git a/components/pages/settings/teams/TeamMembersTable.js b/components/pages/settings/teams/TeamMembersTable.js index 8498a19d..0d405fec 100644 --- a/components/pages/settings/teams/TeamMembersTable.js +++ b/components/pages/settings/teams/TeamMembersTable.js @@ -5,7 +5,7 @@ import { TableRow, TableCell, TableColumn, - Button, + LoadingButton, Icon, Icons, Flexbox, @@ -15,12 +15,14 @@ import { ROLES } from 'lib/constants'; import useUser from 'hooks/useUser'; import useApi from 'hooks/useApi'; import useMessages from 'hooks/useMessages'; +import { useState } from 'react'; export default function TeamMembersTable({ data = [], onSave, readOnly }) { const { formatMessage, labels } = useMessages(); const { user } = useUser(); const { del, useMutation } = useApi(); - const { mutate } = useMutation(data => del(`/teamUsers/${data.teamUserId}`)); + const { mutate, isLoading } = useMutation(data => del(`/teamUsers/${data.teamUserId}`)); + const [loadingIds, setLoadingIds] = useState([]); const columns = [ { name: 'username', label: formatMessage(labels.username), style: { flex: 2 } }, @@ -29,12 +31,18 @@ export default function TeamMembersTable({ data = [], onSave, readOnly }) { ]; const handleRemoveTeamMember = teamUserId => { + setLoadingIds(prev => [...prev, teamUserId]); + mutate( { teamUserId }, { - onSuccess: async () => { + onSuccess: () => { + setLoadingIds(loadingIds.filter(a => a !== teamUserId)); onSave(); }, + onError: () => { + setLoadingIds(loadingIds.filter(a => a !== teamUserId)); + }, }, ); }; @@ -59,15 +67,16 @@ export default function TeamMembersTable({ data = [], onSave, readOnly }) { ), action: !readOnly && (