mirror of
https://git.mirrors.martin98.com/https://github.com/SigNoz/signoz
synced 2025-08-15 16:16:00 +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 { PlusOutlined } from '@ant-design/icons';
|
||||||
import { Button, Form, Input, Select, Space, Typography } from 'antd';
|
import {
|
||||||
import { Dispatch, SetStateAction, useCallback, useEffect } from 'react';
|
Button,
|
||||||
|
Form,
|
||||||
|
FormInstance,
|
||||||
|
Input,
|
||||||
|
Select,
|
||||||
|
Space,
|
||||||
|
Typography,
|
||||||
|
} from 'antd';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import { requireErrorMessage } from 'utils/form/requireErrorMessage';
|
||||||
|
|
||||||
import { InviteTeamMembersProps } from '../PendingInvitesContainer/index';
|
import { InviteMemberFormValues } from '../PendingInvitesContainer/index';
|
||||||
import { SelectDrawer, TitleWrapper } from './styles';
|
import { SelectDrawer, SpaceContainer, TitleWrapper } from './styles';
|
||||||
|
|
||||||
const { Option } = Select;
|
const { Option } = Select;
|
||||||
|
|
||||||
function InviteTeamMembers({ allMembers, setAllMembers }: Props): JSX.Element {
|
function InviteTeamMembers({ form, onFinish }: Props): JSX.Element {
|
||||||
const { t } = useTranslation('organizationsettings');
|
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 (
|
return (
|
||||||
<>
|
<>
|
||||||
<TitleWrapper>
|
<TitleWrapper>
|
||||||
@ -56,52 +26,50 @@ function InviteTeamMembers({ allMembers, setAllMembers }: Props): JSX.Element {
|
|||||||
<Typography>{t('name_optional')}</Typography>
|
<Typography>{t('name_optional')}</Typography>
|
||||||
<Typography>{t('role')}</Typography>
|
<Typography>{t('role')}</Typography>
|
||||||
</TitleWrapper>
|
</TitleWrapper>
|
||||||
<Form>
|
<Form
|
||||||
<Space direction="vertical" align="center" size="middle">
|
form={form}
|
||||||
{allMembers.map((e, index) => (
|
onFinish={onFinish}
|
||||||
<Space key={Number(index)} direction="horizontal">
|
initialValues={{ members: [{ email: '', name: '', role: 'VIEWER' }] }}
|
||||||
<Input
|
>
|
||||||
placeholder={t('email_placeholder')}
|
<Form.List name="members">
|
||||||
value={e.email}
|
{(fields, { add }): JSX.Element => (
|
||||||
onChange={(event): void => {
|
<SpaceContainer direction="vertical" align="center" size="middle">
|
||||||
onChangeHandler(event.target.value, index, 'email');
|
{fields.map(({ key, name }) => (
|
||||||
}}
|
<Space key={key} direction="horizontal" align="start">
|
||||||
required
|
<Form.Item
|
||||||
/>
|
name={[name, 'email']}
|
||||||
<Input
|
rules={[{ required: true, message: requireErrorMessage('Email') }]}
|
||||||
placeholder={t('name_placeholder')}
|
>
|
||||||
value={e.name}
|
<Input placeholder={t('email_placeholder')} />
|
||||||
onChange={(event): void => {
|
</Form.Item>
|
||||||
onChangeHandler(event.target.value, index, 'name');
|
<Form.Item name={[name, 'name']}>
|
||||||
}}
|
<Input placeholder={t('name_placeholder')} />
|
||||||
required
|
</Form.Item>
|
||||||
/>
|
<Form.Item name={[name, 'role']} initialValue="VIEWER">
|
||||||
<SelectDrawer
|
<SelectDrawer>
|
||||||
value={e.role}
|
<Option value="ADMIN">ADMIN</Option>
|
||||||
onSelect={(value: unknown): void => {
|
<Option value="VIEWER">VIEWER</Option>
|
||||||
if (typeof value === 'string') {
|
<Option value="EDITOR">EDITOR</Option>
|
||||||
onChangeHandler(value, index, 'role');
|
</SelectDrawer>
|
||||||
}
|
</Form.Item>
|
||||||
}}
|
</Space>
|
||||||
>
|
))}
|
||||||
<Option value="ADMIN">ADMIN</Option>
|
<Form.Item>
|
||||||
<Option value="VIEWER">VIEWER</Option>
|
<Button onClick={add} icon={<PlusOutlined />} type="default">
|
||||||
<Option value="EDITOR">EDITOR</Option>
|
{t('add_another_team_member')}
|
||||||
</SelectDrawer>
|
</Button>
|
||||||
</Space>
|
</Form.Item>
|
||||||
))}
|
</SpaceContainer>
|
||||||
<Button onClick={onAddHandler} icon={<PlusOutlined />} type="default">
|
)}
|
||||||
{t('add_another_team_member')}
|
</Form.List>
|
||||||
</Button>
|
|
||||||
</Space>
|
|
||||||
</Form>
|
</Form>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
allMembers: InviteTeamMembersProps[];
|
form: FormInstance<InviteMemberFormValues>;
|
||||||
setAllMembers: Dispatch<SetStateAction<InviteTeamMembersProps[]>>;
|
onFinish: (values: InviteMemberFormValues) => Promise<void>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default InviteTeamMembers;
|
export default InviteTeamMembers;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { Select } from 'antd';
|
import { Select, Space } from 'antd';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
|
|
||||||
export const SelectDrawer = styled(Select)`
|
export const SelectDrawer = styled(Select)`
|
||||||
@ -13,3 +13,9 @@ export const TitleWrapper = styled.div`
|
|||||||
min-width: 11rem;
|
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 { 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 { ColumnsType } from 'antd/lib/table';
|
||||||
import deleteInvite from 'api/user/deleteInvite';
|
import deleteInvite from 'api/user/deleteInvite';
|
||||||
import getPendingInvites from 'api/user/getPendingInvites';
|
import getPendingInvites from 'api/user/getPendingInvites';
|
||||||
@ -27,6 +27,7 @@ function PendingInvitesContainer(): JSX.Element {
|
|||||||
isInviteTeamMemberModalOpen,
|
isInviteTeamMemberModalOpen,
|
||||||
setIsInviteTeamMemberModalOpen,
|
setIsInviteTeamMemberModalOpen,
|
||||||
] = useState<boolean>(false);
|
] = useState<boolean>(false);
|
||||||
|
const [form] = Form.useForm<InviteMemberFormValues>();
|
||||||
const [isInvitingMembers, setIsInvitingMembers] = useState<boolean>(false);
|
const [isInvitingMembers, setIsInvitingMembers] = useState<boolean>(false);
|
||||||
const { t } = useTranslation(['organizationsettings', 'common']);
|
const { t } = useTranslation(['organizationsettings', 'common']);
|
||||||
const [state, setText] = useCopyToClipboard();
|
const [state, setText] = useCopyToClipboard();
|
||||||
@ -58,14 +59,6 @@ function PendingInvitesContainer(): JSX.Element {
|
|||||||
setIsInviteTeamMemberModalOpen(value);
|
setIsInviteTeamMemberModalOpen(value);
|
||||||
};
|
};
|
||||||
|
|
||||||
const [allMembers, setAllMembers] = useState<InviteTeamMembersProps[]>([
|
|
||||||
{
|
|
||||||
email: '',
|
|
||||||
name: '',
|
|
||||||
role: 'VIEWER',
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
|
|
||||||
const [dataSource, setDataSource] = useState<DataProps[]>([]);
|
const [dataSource, setDataSource] = useState<DataProps[]>([]);
|
||||||
|
|
||||||
const { hash } = useLocation();
|
const { hash } = useLocation();
|
||||||
@ -192,45 +185,48 @@ function PendingInvitesContainer(): JSX.Element {
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const onInviteClickHandler = async (): Promise<void> => {
|
const onInviteClickHandler = useCallback(
|
||||||
try {
|
async (values: InviteMemberFormValues): Promise<void> => {
|
||||||
setIsInvitingMembers(true);
|
try {
|
||||||
allMembers.forEach(
|
setIsInvitingMembers(true);
|
||||||
async (members): Promise<void> => {
|
values.members.forEach(
|
||||||
const { error, statusCode } = await sendInvite({
|
async (member): Promise<void> => {
|
||||||
email: members.email,
|
const { error, statusCode } = await sendInvite({
|
||||||
name: members.name,
|
email: member.email,
|
||||||
role: members.role,
|
name: member.name,
|
||||||
});
|
role: member.role,
|
||||||
|
|
||||||
if (statusCode !== 200) {
|
|
||||||
notifications.error({
|
|
||||||
message:
|
|
||||||
error ||
|
|
||||||
t('something_went_wrong', {
|
|
||||||
ns: 'common',
|
|
||||||
}),
|
|
||||||
});
|
});
|
||||||
}
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
setTimeout(async () => {
|
if (statusCode !== 200) {
|
||||||
const { data, status } = await getPendingInvitesResponse.refetch();
|
notifications.error({
|
||||||
if (status === 'success' && data.payload) {
|
message:
|
||||||
setDataSource(getParsedInviteData(data?.payload || []));
|
error ||
|
||||||
}
|
t('something_went_wrong', {
|
||||||
setIsInvitingMembers(false);
|
ns: 'common',
|
||||||
toggleModal(false);
|
}),
|
||||||
}, 2000);
|
});
|
||||||
} catch (error) {
|
}
|
||||||
notifications.error({
|
},
|
||||||
message: 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 (
|
return (
|
||||||
<div>
|
<div>
|
||||||
@ -248,7 +244,7 @@ function PendingInvitesContainer(): JSX.Element {
|
|||||||
</Button>,
|
</Button>,
|
||||||
<Button
|
<Button
|
||||||
key={t('invite_team_members').toString()}
|
key={t('invite_team_members').toString()}
|
||||||
onClick={onInviteClickHandler}
|
onClick={form.submit}
|
||||||
type="primary"
|
type="primary"
|
||||||
disabled={isInvitingMembers}
|
disabled={isInvitingMembers}
|
||||||
loading={isInvitingMembers}
|
loading={isInvitingMembers}
|
||||||
@ -257,7 +253,7 @@ function PendingInvitesContainer(): JSX.Element {
|
|||||||
</Button>,
|
</Button>,
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
<InviteTeamMembers allMembers={allMembers} setAllMembers={setAllMembers} />
|
<InviteTeamMembers form={form} onFinish={onInviteClickHandler} />
|
||||||
</Modal>
|
</Modal>
|
||||||
|
|
||||||
<Space direction="vertical" size="middle">
|
<Space direction="vertical" size="middle">
|
||||||
@ -298,4 +294,15 @@ interface DataProps {
|
|||||||
accessLevel: ROLES;
|
accessLevel: ROLES;
|
||||||
inviteLink: string;
|
inviteLink: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Role = 'ADMIN' | 'VIEWER' | 'EDITOR';
|
||||||
|
|
||||||
|
export interface InviteMemberFormValues {
|
||||||
|
members: {
|
||||||
|
email: string;
|
||||||
|
name: string;
|
||||||
|
role: Role;
|
||||||
|
}[];
|
||||||
|
}
|
||||||
|
|
||||||
export default PendingInvitesContainer;
|
export default PendingInvitesContainer;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user