Skip to content

Commit 4a341b9

Browse files
added option to send invitation by email
1 parent c8c288e commit 4a341b9

File tree

3 files changed

+68
-3
lines changed

3 files changed

+68
-3
lines changed

client/packages/lowcoder/src/api/inviteApi.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ export type InviteInfo = {
2020
class InviteApi extends Api {
2121
static getInviteURL = "/invitation";
2222
static acceptInviteURL = (invitationId: string) => `/invitation/${invitationId}/invite`;
23+
static sendInvitationURL = `${this.getInviteURL}/email/invite`;
2324

2425
// generate invitation
2526
static getInvite(request: GetInviteRequest): AxiosPromise<GenericApiResponse<InviteInfo>> {
@@ -36,6 +37,11 @@ class InviteApi extends Api {
3637
// the same api as getInviteInfo, method is by post
3738
return Api.get(InviteApi.acceptInviteURL(request.invitationId));
3839
}
40+
41+
// send invitations
42+
static sendInvitations(request: {emails: string[], orgId: string}): AxiosPromise<GenericApiResponse<any>> {
43+
return Api.post(InviteApi.sendInvitationURL, request);
44+
}
3945
}
4046

4147
export default InviteApi;

client/packages/lowcoder/src/i18n/locales/en.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2484,6 +2484,12 @@ export const en = {
24842484
"inviteUserLabel": "Invitation Link:",
24852485
"inviteCopyLink": "Copy Link",
24862486
"inviteText": "{userName} Invites You to Join the Workspace \"{organization}\", Click on the Link to Join: {inviteLink}",
2487+
"inviteByEmailHelp": "You can enter one or more email addresses to send invitation links",
2488+
"inviteByEmailLabel": "Enter emails:",
2489+
"inviteByEmailButton": "Send Invitations",
2490+
"inviteByEmailSuccess": "Invitations sent successfully!",
2491+
"inviteByEmailError": "Something went wrong while sending invitations. Please try again.",
2492+
"noValidEmails": "No valid emails found",
24872493
"groupName": "Group Name",
24882494
"createTime": "Create Time",
24892495
"manageBtn": "Manage",

client/packages/lowcoder/src/pages/common/inviteDialog.tsx

Lines changed: 56 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ import { HelpText } from "components/HelpText";
1212
import copyToClipboard from "copy-to-clipboard";
1313
import { trans } from "i18n";
1414
import { messageInstance } from "lowcoder-design/src/components/GlobalInstances";
15+
import Divider from "antd/es/divider";
16+
import Flex from "antd/es/flex";
17+
import Select from "antd/es/select";
1518

1619
const InviteButton = styled(TacoButton)`
1720
width: 76px;
@@ -23,14 +26,36 @@ const StyledLoading = styled(WhiteLoading)`
2326
height: 170px;
2427
`;
2528

26-
function InviteContent(props: { inviteInfo: InviteInfo }) {
27-
const { inviteInfo } = props;
29+
function InviteContent(props: { inviteInfo: InviteInfo, onClose?: () => void }) {
30+
const { inviteInfo, onClose } = props;
2831
const inviteLink = genInviteLink(inviteInfo?.inviteCode);
2932
const inviteText = trans("memberSettings.inviteText", {
3033
userName: inviteInfo.createUserName,
3134
organization: inviteInfo.invitedOrganizationName,
3235
inviteLink,
3336
});
37+
const [emails, setEmails] = useState<string[]>([]);
38+
39+
const isValidEmail = (email: string) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
40+
41+
const sendInvitations = async () => {
42+
const filteredEmails = emails.filter(isValidEmail);
43+
if (!filteredEmails.length) {
44+
return messageInstance.error(trans("memberSettings.noValidEmails"));
45+
}
46+
try {
47+
const resp = await InviteApi.sendInvitations({emails: filteredEmails, orgId: inviteInfo.invitedOrganizationId})
48+
if (validateResponse(resp) && resp.data.success) {
49+
messageInstance.success(trans('membersSettings.inviteByEmailSuccess'));
50+
onClose?.();
51+
return;
52+
}
53+
throw new Error(trans('membersSettings.inviteByEmailError'));
54+
} catch(e: any) {
55+
messageInstance.error(e.message);
56+
}
57+
}
58+
3459
return (
3560
<>
3661
<HelpText style={{ marginBottom: 16 }}>{trans("memberSettings.inviteUserHelp")}</HelpText>
@@ -48,6 +73,34 @@ function InviteContent(props: { inviteInfo: InviteInfo }) {
4873
{trans("memberSettings.inviteCopyLink")}
4974
</InviteButton>
5075
</div>
76+
<Divider style={{marginTop: '60px'}}/>
77+
<HelpText style={{ marginBottom: 16 }}>{trans("memberSettings.inviteByEmailHelp")}</HelpText>
78+
<CommonTextLabel>{trans("memberSettings.inviteByEmailLabel")}</CommonTextLabel>
79+
<Select
80+
mode="tags"
81+
allowClear
82+
open={false}
83+
style={{ width: '100%', marginTop: '8px', marginBottom: '8px' }}
84+
placeholder="Enter emails"
85+
defaultValue={[]}
86+
onChange={(value) => {
87+
setEmails(value);
88+
}}
89+
options={[]}
90+
showSearch={false}
91+
suffixIcon={''}
92+
/>
93+
<Flex justify="end">
94+
<TacoButton
95+
buttonType="primary"
96+
onClick={() => {
97+
sendInvitations();
98+
}}
99+
disabled={!Boolean(emails?.length)}
100+
>
101+
{trans("memberSettings.inviteByEmailButton")}
102+
</TacoButton>
103+
</Flex>
51104
</>
52105
);
53106
}
@@ -101,7 +154,7 @@ function InviteDialog(props: {
101154
showCancelButton={false}
102155
width="440px"
103156
>
104-
{!inviteInfo ? <StyledLoading size={20} /> : <InviteContent inviteInfo={inviteInfo} />}
157+
{!inviteInfo ? <StyledLoading size={20} /> : <InviteContent inviteInfo={inviteInfo} onClose={() => setInviteDialogVisible(false)} />}
105158
</CustomModal>
106159
</>
107160
);

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy