Skip to content

Commit

Permalink
Admin can revoke user invites from Manage Users page
Browse files Browse the repository at this point in the history
  • Loading branch information
alihadimazeh committed Jun 18, 2024
1 parent c4fcac0 commit a2f5cc6
Show file tree
Hide file tree
Showing 6 changed files with 52 additions and 5 deletions.
3 changes: 2 additions & 1 deletion app/assets/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,8 @@
"invited": {
"time_sent": "Time Sent",
"valid": "Valid"
}
},
"revoke_invite": "Revoke Invite"
},
"server_rooms": {
"server_rooms": "Server Rooms",
Expand Down
9 changes: 9 additions & 0 deletions app/controllers/api/v1/admin/invitations_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,15 @@ def create
logger.error "Failed to send invitations to #{params[:invitations][:emails]} - #{e}"
render_error status: :bad_request
end

def destroy
invitation = Invitation.find(params[:id])
invitation.destroy
render_data status: :ok
rescue StandardError => e
logger.error "Failed to revoke invite, error: #{e.message}"
render_error status: :bad_request
end
end
end
end
Expand Down
19 changes: 17 additions & 2 deletions app/javascript/components/admin/manage_users/InvitedUsersTable.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,10 @@

import React, { useState } from 'react';
import PropTypes from 'prop-types';
import { Table } from 'react-bootstrap';
import { Table, Dropdown } from 'react-bootstrap';
import { useTranslation } from 'react-i18next';
import { CheckIcon, XMarkIcon } from '@heroicons/react/24/solid';
import { CheckIcon, XMarkIcon, XCircleIcon } from '@heroicons/react/24/solid';
import { EllipsisVerticalIcon } from '@heroicons/react/24/outline';
import SortBy from '../../shared_components/search/SortBy';
import useInvitations from '../../../hooks/queries/admin/manage_users/useInvitations';
import Pagination from '../../shared_components/Pagination';
Expand All @@ -27,12 +28,15 @@ import EmptyUsersList from './EmptyUsersList';
import { localizeDateTimeString } from '../../../helpers/DateTimeHelper';
import { useAuth } from '../../../contexts/auth/AuthProvider';
import ManageUsersInvitedRowPlaceHolder from './ManageUsersInvitedRowPlaceHolder';
// import Modal from '../../shared_components/modals/Modal';
import useRevokeUserInvite from '../../../hooks/mutations/admin/manage_users/useRevokeUserInvite';

export default function InvitedUsersTable({ searchInput }) {
const { t } = useTranslation();
const [page, setPage] = useState();
const { isLoading, data: invitations } = useInvitations(searchInput, page);
const currentUser = useAuth();
const revokeUserInvite = useRevokeUserInvite();

if (!searchInput && invitations?.data?.length === 0) {
return <EmptyUsersList text={t('admin.manage_users.empty_invited_users')} subtext={t('admin.manage_users.empty_invited_users_subtext')} />;
Expand Down Expand Up @@ -73,6 +77,17 @@ export default function InvitedUsersTable({ searchInput }) {
<td className="text-dark border-0">
{ invitation.valid ? <CheckIcon className="text-success hi-s" /> : <XMarkIcon className="text-danger hi-s" />}
</td>
<td className="text-dark border-0">
<Dropdown className="float-end cursor-pointer">
<Dropdown.Toggle className="hi-s" as={EllipsisVerticalIcon} />
<Dropdown.Menu>
<Dropdown.Item onClick={() => revokeUserInvite.mutate(invitation.id)}>
<XCircleIcon className="hi-s me-2" />
{t('admin.manage_users.revoke_invite')}
</Dropdown.Item>
</Dropdown.Menu>
</Dropdown>
</td>
</tr>
))
)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { useMutation, useQueryClient } from 'react-query';
import { toast } from 'react-toastify';
import { useTranslation } from 'react-i18next';
import axios from '../../../../helpers/Axios';

export default function useRevokeUserInvite() {
const { t } = useTranslation();
const queryClient = useQueryClient();

return useMutation(
(id) => axios.delete(`/admin/invitations/${id}.json`),
{
onSuccess: () => {
queryClient.invalidateQueries(['getInvitations']);
toast.success(t('toast.success.invitations.invitation_revoked'));
},
onError: () => {
toast.error(t('toast.error.problem_completing_action'));
},
},
);
}
2 changes: 1 addition & 1 deletion app/serializers/invitation_serializer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
# frozen_string_literal: true

class InvitationSerializer < ApplicationSerializer
attributes :email, :updated_at, :valid
attributes :id, :email, :updated_at, :valid

def valid
object.updated_at.in(Invitation::INVITATION_VALIDITY_PERIOD)
Expand Down
2 changes: 1 addition & 1 deletion config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@
end
resources :rooms_configurations, only: :update, param: :name
resources :roles
resources :invitations, only: %i[index create]
resources :invitations, only: %i[index create destroy]
resources :role_permissions, only: [:index] do
collection do
post '/', to: 'role_permissions#update'
Expand Down

0 comments on commit a2f5cc6

Please sign in to comment.