mirror of
https://git.mirrors.martin98.com/https://github.com/SigNoz/signoz
synced 2025-08-14 21:35:59 +08:00
feat: moved invite members form to antd form (#2745)
* feat: moved invite members form to antd form Signed-off-by: GermaVinsmoke <vaibhav1180@gmail.com> * chore: center align add more btn Signed-off-by: GermaVinsmoke <vaibhav1180@gmail.com> * chore: name optional, space proper alignment Signed-off-by: GermaVinsmoke <vaibhav1180@gmail.com> * chore: used lib fn for require message Signed-off-by: GermaVinsmoke <vaibhav1180@gmail.com> --------- Signed-off-by: GermaVinsmoke <vaibhav1180@gmail.com> Co-authored-by: Palash Gupta <palashgdev@gmail.com>
This commit is contained in:
parent
fda0441686
commit
234a69de8c
@ -1,54 +1,24 @@
|
||||
import { PlusOutlined } from '@ant-design/icons';
|
||||
import { Button, Form, Input, Select, Space, Typography } from 'antd';
|
||||
import { Dispatch, SetStateAction, useCallback, useEffect } from 'react';
|
||||
import {
|
||||
Button,
|
||||
Form,
|
||||
FormInstance,
|
||||
Input,
|
||||
Select,
|
||||
Space,
|
||||
Typography,
|
||||
} from 'antd';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { requireErrorMessage } from 'utils/form/requireErrorMessage';
|
||||
|
||||
import { InviteTeamMembersProps } from '../PendingInvitesContainer/index';
|
||||
import { SelectDrawer, TitleWrapper } from './styles';
|
||||
import { InviteMemberFormValues } from '../PendingInvitesContainer/index';
|
||||
import { SelectDrawer, SpaceContainer, TitleWrapper } from './styles';
|
||||
|
||||
const { Option } = Select;
|
||||
|
||||
function InviteTeamMembers({ allMembers, setAllMembers }: Props): JSX.Element {
|
||||
function InviteTeamMembers({ form, onFinish }: Props): JSX.Element {
|
||||
const { t } = useTranslation('organizationsettings');
|
||||
|
||||
useEffect(
|
||||
() => (): void => {
|
||||
setAllMembers([
|
||||
{
|
||||
email: '',
|
||||
name: '',
|
||||
role: 'VIEWER',
|
||||
},
|
||||
]);
|
||||
},
|
||||
[setAllMembers],
|
||||
);
|
||||
|
||||
const onAddHandler = (): void => {
|
||||
setAllMembers((state) => [
|
||||
...state,
|
||||
{
|
||||
email: '',
|
||||
name: '',
|
||||
role: 'VIEWER',
|
||||
},
|
||||
]);
|
||||
};
|
||||
|
||||
const onChangeHandler = useCallback(
|
||||
(value: string, index: number, type: string): void => {
|
||||
setAllMembers((prev) => [
|
||||
...prev.slice(0, index),
|
||||
{
|
||||
...prev[index],
|
||||
[type]: value,
|
||||
},
|
||||
...prev.slice(index, prev.length - 1),
|
||||
]);
|
||||
},
|
||||
[setAllMembers],
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
<TitleWrapper>
|
||||
@ -56,52 +26,50 @@ function InviteTeamMembers({ allMembers, setAllMembers }: Props): JSX.Element {
|
||||
<Typography>{t('name_optional')}</Typography>
|
||||
<Typography>{t('role')}</Typography>
|
||||
</TitleWrapper>
|
||||
<Form>
|
||||
<Space direction="vertical" align="center" size="middle">
|
||||
{allMembers.map((e, index) => (
|
||||
<Space key={Number(index)} direction="horizontal">
|
||||
<Input
|
||||
placeholder={t('email_placeholder')}
|
||||
value={e.email}
|
||||
onChange={(event): void => {
|
||||
onChangeHandler(event.target.value, index, 'email');
|
||||
}}
|
||||
required
|
||||
/>
|
||||
<Input
|
||||
placeholder={t('name_placeholder')}
|
||||
value={e.name}
|
||||
onChange={(event): void => {
|
||||
onChangeHandler(event.target.value, index, 'name');
|
||||
}}
|
||||
required
|
||||
/>
|
||||
<SelectDrawer
|
||||
value={e.role}
|
||||
onSelect={(value: unknown): void => {
|
||||
if (typeof value === 'string') {
|
||||
onChangeHandler(value, index, 'role');
|
||||
}
|
||||
}}
|
||||
>
|
||||
<Option value="ADMIN">ADMIN</Option>
|
||||
<Option value="VIEWER">VIEWER</Option>
|
||||
<Option value="EDITOR">EDITOR</Option>
|
||||
</SelectDrawer>
|
||||
</Space>
|
||||
))}
|
||||
<Button onClick={onAddHandler} icon={<PlusOutlined />} type="default">
|
||||
{t('add_another_team_member')}
|
||||
</Button>
|
||||
</Space>
|
||||
<Form
|
||||
form={form}
|
||||
onFinish={onFinish}
|
||||
initialValues={{ members: [{ email: '', name: '', role: 'VIEWER' }] }}
|
||||
>
|
||||
<Form.List name="members">
|
||||
{(fields, { add }): JSX.Element => (
|
||||
<SpaceContainer direction="vertical" align="center" size="middle">
|
||||
{fields.map(({ key, name }) => (
|
||||
<Space key={key} direction="horizontal" align="start">
|
||||
<Form.Item
|
||||
name={[name, 'email']}
|
||||
rules={[{ required: true, message: requireErrorMessage('Email') }]}
|
||||
>
|
||||
<Input placeholder={t('email_placeholder')} />
|
||||
</Form.Item>
|
||||
<Form.Item name={[name, 'name']}>
|
||||
<Input placeholder={t('name_placeholder')} />
|
||||
</Form.Item>
|
||||
<Form.Item name={[name, 'role']} initialValue="VIEWER">
|
||||
<SelectDrawer>
|
||||
<Option value="ADMIN">ADMIN</Option>
|
||||
<Option value="VIEWER">VIEWER</Option>
|
||||
<Option value="EDITOR">EDITOR</Option>
|
||||
</SelectDrawer>
|
||||
</Form.Item>
|
||||
</Space>
|
||||
))}
|
||||
<Form.Item>
|
||||
<Button onClick={add} icon={<PlusOutlined />} type="default">
|
||||
{t('add_another_team_member')}
|
||||
</Button>
|
||||
</Form.Item>
|
||||
</SpaceContainer>
|
||||
)}
|
||||
</Form.List>
|
||||
</Form>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
interface Props {
|
||||
allMembers: InviteTeamMembersProps[];
|
||||
setAllMembers: Dispatch<SetStateAction<InviteTeamMembersProps[]>>;
|
||||
form: FormInstance<InviteMemberFormValues>;
|
||||
onFinish: (values: InviteMemberFormValues) => Promise<void>;
|
||||
}
|
||||
|
||||
export default InviteTeamMembers;
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Select } from 'antd';
|
||||
import { Select, Space } from 'antd';
|
||||
import styled from 'styled-components';
|
||||
|
||||
export const SelectDrawer = styled(Select)`
|
||||
@ -13,3 +13,9 @@ export const TitleWrapper = styled.div`
|
||||
min-width: 11rem;
|
||||
}
|
||||
`;
|
||||
|
||||
export const SpaceContainer = styled(Space)`
|
||||
& .ant-form-item {
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
`;
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { PlusOutlined } from '@ant-design/icons';
|
||||
import { Button, Modal, Space, Typography } from 'antd';
|
||||
import { Button, Form, Modal, Space, Typography } from 'antd';
|
||||
import { ColumnsType } from 'antd/lib/table';
|
||||
import deleteInvite from 'api/user/deleteInvite';
|
||||
import getPendingInvites from 'api/user/getPendingInvites';
|
||||
@ -27,6 +27,7 @@ function PendingInvitesContainer(): JSX.Element {
|
||||
isInviteTeamMemberModalOpen,
|
||||
setIsInviteTeamMemberModalOpen,
|
||||
] = useState<boolean>(false);
|
||||
const [form] = Form.useForm<InviteMemberFormValues>();
|
||||
const [isInvitingMembers, setIsInvitingMembers] = useState<boolean>(false);
|
||||
const { t } = useTranslation(['organizationsettings', 'common']);
|
||||
const [state, setText] = useCopyToClipboard();
|
||||
@ -58,14 +59,6 @@ function PendingInvitesContainer(): JSX.Element {
|
||||
setIsInviteTeamMemberModalOpen(value);
|
||||
};
|
||||
|
||||
const [allMembers, setAllMembers] = useState<InviteTeamMembersProps[]>([
|
||||
{
|
||||
email: '',
|
||||
name: '',
|
||||
role: 'VIEWER',
|
||||
},
|
||||
]);
|
||||
|
||||
const [dataSource, setDataSource] = useState<DataProps[]>([]);
|
||||
|
||||
const { hash } = useLocation();
|
||||
@ -192,45 +185,48 @@ function PendingInvitesContainer(): JSX.Element {
|
||||
},
|
||||
];
|
||||
|
||||
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',
|
||||
}),
|
||||
const onInviteClickHandler = useCallback(
|
||||
async (values: InviteMemberFormValues): Promise<void> => {
|
||||
try {
|
||||
setIsInvitingMembers(true);
|
||||
values.members.forEach(
|
||||
async (member): Promise<void> => {
|
||||
const { error, statusCode } = await sendInvite({
|
||||
email: member.email,
|
||||
name: member.name,
|
||||
role: member.role,
|
||||
});
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
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',
|
||||
}),
|
||||
});
|
||||
}
|
||||
};
|
||||
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',
|
||||
}),
|
||||
});
|
||||
}
|
||||
},
|
||||
[getParsedInviteData, getPendingInvitesResponse, notifications, t],
|
||||
);
|
||||
|
||||
return (
|
||||
<div>
|
||||
@ -248,7 +244,7 @@ function PendingInvitesContainer(): JSX.Element {
|
||||
</Button>,
|
||||
<Button
|
||||
key={t('invite_team_members').toString()}
|
||||
onClick={onInviteClickHandler}
|
||||
onClick={form.submit}
|
||||
type="primary"
|
||||
disabled={isInvitingMembers}
|
||||
loading={isInvitingMembers}
|
||||
@ -257,7 +253,7 @@ function PendingInvitesContainer(): JSX.Element {
|
||||
</Button>,
|
||||
]}
|
||||
>
|
||||
<InviteTeamMembers allMembers={allMembers} setAllMembers={setAllMembers} />
|
||||
<InviteTeamMembers form={form} onFinish={onInviteClickHandler} />
|
||||
</Modal>
|
||||
|
||||
<Space direction="vertical" size="middle">
|
||||
@ -298,4 +294,15 @@ interface DataProps {
|
||||
accessLevel: ROLES;
|
||||
inviteLink: string;
|
||||
}
|
||||
|
||||
type Role = 'ADMIN' | 'VIEWER' | 'EDITOR';
|
||||
|
||||
export interface InviteMemberFormValues {
|
||||
members: {
|
||||
email: string;
|
||||
name: string;
|
||||
role: Role;
|
||||
}[];
|
||||
}
|
||||
|
||||
export default PendingInvitesContainer;
|
||||
|
Loading…
x
Reference in New Issue
Block a user