GitStart 846da08cbd
refactor: antdv5 notfications (#2161)
Co-authored-by: gitstart <gitstart@users.noreply.github.com>
Co-authored-by: Nitesh Singh <nitesh.singh@gitstart.dev>
Co-authored-by: gitstart-app[bot] <57568882+gitstart-app[bot]@users.noreply.github.com>
Co-authored-by: Rubens Rafael <70234898+RubensRafael@users.noreply.github.com>
Co-authored-by: RubensRafael <rubensrafael2@live.com>
Co-authored-by: niteshsingh1357 <niteshsingh1357@gmail.com>
Co-authored-by: gitstart_bot <gitstart_bot@users.noreply.github.com>
Co-authored-by: Palash Gupta <palashgdev@gmail.com>
2023-02-02 11:38:32 +05:30

292 lines
6.7 KiB
TypeScript

import { PlusOutlined } from '@ant-design/icons';
import { Button, Modal, notification, Space, Table, Typography } from 'antd';
import { ColumnsType } from 'antd/lib/table';
import deleteInvite from 'api/user/deleteInvite';
import getPendingInvites from 'api/user/getPendingInvites';
import sendInvite from 'api/user/sendInvite';
import { INVITE_MEMBERS_HASH } from 'constants/app';
import ROUTES from 'constants/routes';
import React, { useCallback, useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { useQuery } from 'react-query';
import { useLocation } from 'react-router-dom';
import { useCopyToClipboard } from 'react-use';
import { PayloadProps } from 'types/api/user/getPendingInvites';
import { ROLES } from 'types/roles';
import InviteTeamMembers from '../InviteTeamMembers';
import { TitleWrapper } from './styles';
function PendingInvitesContainer(): JSX.Element {
const [
isInviteTeamMemberModalOpen,
setIsInviteTeamMemberModalOpen,
] = useState<boolean>(false);
const [isInvitingMembers, setIsInvitingMembers] = useState<boolean>(false);
const { t } = useTranslation(['organizationsettings', 'common']);
const [state, setText] = useCopyToClipboard();
const [notifications, NotificationElement] = notification.useNotification();
useEffect(() => {
if (state.error) {
notifications.error({
message: state.error.message,
});
}
if (state.value) {
notifications.success({
message: t('success', {
ns: 'common',
}),
});
}
}, [state.error, state.value, t, notifications]);
const getPendingInvitesResponse = useQuery({
queryFn: () => getPendingInvites(),
queryKey: 'getPendingInvites',
});
const toggleModal = (value: boolean): void => {
setIsInviteTeamMemberModalOpen(value);
};
const [allMembers, setAllMembers] = useState<InviteTeamMembersProps[]>([
{
email: '',
name: '',
role: 'VIEWER',
},
]);
const [dataSource, setDataSource] = useState<DataProps[]>([]);
const { hash } = useLocation();
const getParsedInviteData = useCallback(
(payload: PayloadProps = []) =>
payload?.map((data) => ({
key: data.createdAt,
name: data.name,
email: data.email,
accessLevel: data.role,
inviteLink: `${window.location.origin}${ROUTES.SIGN_UP}?token=${data.token}`,
})),
[],
);
useEffect(() => {
if (hash === INVITE_MEMBERS_HASH) {
toggleModal(true);
}
}, [hash]);
useEffect(() => {
if (
getPendingInvitesResponse.status === 'success' &&
getPendingInvitesResponse?.data?.payload
) {
const data = getParsedInviteData(
getPendingInvitesResponse?.data?.payload || [],
);
setDataSource(data);
}
}, [
getParsedInviteData,
getPendingInvitesResponse?.data?.payload,
getPendingInvitesResponse.status,
]);
const onRevokeHandler = async (email: string): Promise<void> => {
try {
const response = await deleteInvite({
email,
});
if (response.statusCode === 200) {
// remove from the client data
const index = dataSource.findIndex((e) => e.email === email);
if (index !== -1) {
setDataSource([
...dataSource.slice(0, index),
...dataSource.slice(index + 1, dataSource.length),
]);
}
notifications.success({
message: t('success', {
ns: 'common',
}),
});
} else {
notifications.error({
message:
response.error ||
t('something_went_wrong', {
ns: 'common',
}),
});
}
} catch (error) {
notifications.error({
message: t('something_went_wrong', {
ns: 'common',
}),
});
}
};
const columns: ColumnsType<DataProps> = [
{
title: 'Name',
dataIndex: 'name',
key: 'name',
},
{
title: 'Emails',
dataIndex: 'email',
key: 'email',
},
{
title: 'Access Level',
dataIndex: 'accessLevel',
key: 'accessLevel',
},
{
title: 'Invite Link',
dataIndex: 'inviteLink',
key: 'Invite Link',
ellipsis: true,
},
{
title: 'Action',
dataIndex: 'action',
key: 'Action',
render: (_, record): JSX.Element => (
<Space direction="horizontal">
<Typography.Link
onClick={(): Promise<void> => onRevokeHandler(record.email)}
>
Revoke
</Typography.Link>
<Typography.Link
onClick={(): void => {
setText(record.inviteLink);
}}
>
Copy Invite Link
</Typography.Link>
</Space>
),
},
];
const onInviteClickHandler = async (): Promise<void> => {
try {
setIsInvitingMembers(true);
allMembers.forEach(
async (members): Promise<void> => {
const { error, statusCode } = await sendInvite({
email: members.email,
name: members.name,
role: members.role,
});
if (statusCode !== 200) {
notifications.error({
message:
error ||
t('something_went_wrong', {
ns: 'common',
}),
});
}
},
);
setTimeout(async () => {
const { data, status } = await getPendingInvitesResponse.refetch();
if (status === 'success' && data.payload) {
setDataSource(getParsedInviteData(data?.payload || []));
}
setIsInvitingMembers(false);
toggleModal(false);
}, 2000);
} catch (error) {
notifications.error({
message: t('something_went_wrong', {
ns: 'common',
}),
});
}
};
return (
<div>
{NotificationElement}
<Modal
title={t('invite_team_members')}
open={isInviteTeamMemberModalOpen}
onCancel={(): void => toggleModal(false)}
centered
destroyOnClose
footer={[
<Button key="back" onClick={(): void => toggleModal(false)} type="default">
{t('cancel', {
ns: 'common',
})}
</Button>,
<Button
key={t('invite_team_members').toString()}
onClick={onInviteClickHandler}
type="primary"
disabled={isInvitingMembers}
loading={isInvitingMembers}
>
{t('invite_team_members')}
</Button>,
]}
>
<InviteTeamMembers allMembers={allMembers} setAllMembers={setAllMembers} />
</Modal>
<Space direction="vertical" size="middle">
<TitleWrapper>
<Typography.Title level={3}>{t('pending_invites')}</Typography.Title>
<Button
icon={<PlusOutlined />}
type="primary"
onClick={(): void => {
toggleModal(true);
}}
>
{t('invite_members')}
</Button>
</TitleWrapper>
<Table
tableLayout="fixed"
dataSource={dataSource}
columns={columns}
pagination={false}
loading={getPendingInvitesResponse.status === 'loading'}
/>
</Space>
</div>
);
}
export interface InviteTeamMembersProps {
email: string;
name: string;
role: ROLES;
}
interface DataProps {
key: number;
name: string;
email: string;
accessLevel: ROLES;
inviteLink: string;
}
export default PendingInvitesContainer;