fix: wrong invite message (#4470)

Co-authored-by: Piyush Gupta <piyushguptaa2z123@gmail.com>
This commit is contained in:
Dhruwang Jariwala
2024-12-18 19:54:16 +05:30
committed by GitHub
parent 4676b4cd25
commit 1c58ac3704
15 changed files with 167 additions and 75 deletions
@@ -26,11 +26,12 @@ export const EditMemberships = async ({
return (
<div>
<div className="rounded-lg border border-slate-200">
<div className="grid-cols-20 grid h-12 content-center rounded-t-lg bg-slate-100 px-4 text-left text-sm font-semibold text-slate-900">
<div className="col-span-5">{t("common.full_name")}</div>
<div className="col-span-5">{t("common.email")}</div>
{canDoRoleManagement && <div className="col-span-5">{t("common.role")}</div>}
<div className="col-span-5"></div>
<div className="grid h-12 grid-cols-5 content-center rounded-t-lg bg-slate-100 px-4 text-left text-sm font-semibold text-slate-900">
<div className="col-span-1">{t("common.full_name")}</div>
<div className="col-span-1 text-center">{t("common.email")}</div>
{canDoRoleManagement && <div className="col-span-1 text-center">{t("common.role")}</div>}
<div className="col-span-1 text-center">{t("common.status")}</div>
<div className="col-span-1"></div>
</div>
{role && (
@@ -2,7 +2,10 @@ import { isInviteExpired } from "@/app/lib/utils";
import { EditMembershipRole } from "@/modules/ee/role-management/components/edit-membership-role";
import { MemberActions } from "@/modules/organization/settings/teams/components/edit-memberships/member-actions";
import { Badge } from "@/modules/ui/components/badge";
import { TooltipRenderer } from "@/modules/ui/components/tooltip";
import { useTranslations } from "next-intl";
import { getAccessFlags } from "@formbricks/lib/membership/utils";
import { getFormattedDateTimeString } from "@formbricks/lib/utils/datetime";
import { TInvite } from "@formbricks/types/invites";
import { TMember, TOrganizationRole } from "@formbricks/types/memberships";
import { TOrganization } from "@formbricks/types/organizations";
@@ -22,7 +25,7 @@ const isInvitee = (member: TMember | TInvite): member is TInvite => {
return (member as TInvite).expiresAt !== undefined;
};
export const MembersInfo = async ({
export const MembersInfo = ({
organization,
invites,
currentUserRole,
@@ -32,6 +35,24 @@ export const MembersInfo = async ({
isFormbricksCloud,
}: MembersInfoProps) => {
const allMembers = [...members, ...invites];
const t = useTranslations();
const getMembershipBadge = (member: TMember | TInvite) => {
if (isInvitee(member)) {
return isInviteExpired(member) ? (
<Badge type="gray" text="Expired" size="tiny" data-testid="expired-badge" />
) : (
<TooltipRenderer
tooltipContent={`${t("environments.settings.general.invited_on", {
date: getFormattedDateTimeString(member.createdAt),
})}`}>
<Badge type="warning" text="Pending" size="tiny" />
</TooltipRenderer>
);
}
return <Badge type="success" text="Active" size="tiny" />;
};
const { isOwner, isManager } = getAccessFlags(currentUserRole);
const isOwnerOrManager = isOwner || isManager;
@@ -63,19 +84,19 @@ export const MembersInfo = async ({
};
return (
<div className="grid-cols-20" id="membersInfoWrapper">
<div className="grid-cols-5" id="membersInfoWrapper">
{allMembers.map((member) => (
<div
className="singleMemberInfo grid-cols-20 grid h-auto w-full content-center rounded-lg px-4 py-3 text-left text-sm text-slate-900"
className="singleMemberInfo grid h-auto w-full grid-cols-5 content-center rounded-lg px-4 py-3 text-left text-sm text-slate-900"
key={member.email}>
<div className="ph-no-capture col-span-5 flex flex-col justify-center break-all">
<div className="ph-no-capture col-span-1 flex flex-col justify-center break-all">
<p>{member.name}</p>
</div>
<div className="ph-no-capture col-span-5 flex flex-col justify-center break-all">
<div className="ph-no-capture col-span-1 flex flex-col justify-center break-all text-center">
{member.email}
</div>
<div className="ph-no-capture col-span-5 flex flex-col items-start justify-center break-all">
<div className="ph-no-capture col-span-1 flex flex-col items-center justify-center break-all">
{canDoRoleManagement && allMembers?.length > 0 && (
<EditMembershipRole
currentUserRole={currentUserRole}
@@ -90,15 +111,8 @@ export const MembersInfo = async ({
/>
)}
</div>
<div className="col-span-5 flex items-center justify-end gap-x-4 pr-4">
{isInvitee(member) &&
(isInviteExpired(member) ? (
<Badge className="mr-2" type="gray" size="tiny" text="Expired" />
) : (
<Badge className="mr-2" type="warning" size="tiny" text="Pending" />
))}
<div className="col-span-1 flex items-center justify-center">{getMembershipBadge(member)}</div>
<div className="col-span-1 flex items-center justify-end gap-x-4 pr-4">
<MemberActions
organization={organization}
member={!isInvitee(member) ? member : undefined}
@@ -1,5 +1,6 @@
"use client";
import { getFormattedErrorMessage } from "@/lib/utils/helper";
import { TOrganizationTeam } from "@/modules/ee/teams/team-list/types/team";
import { inviteUserAction, leaveOrganizationAction } from "@/modules/organization/settings/teams/actions";
import { InviteMemberModal } from "@/modules/organization/settings/teams/components/invite-member/invite-member-modal";
@@ -59,16 +60,55 @@ export const OrganizationActions = ({
}
};
const handleInviteMembers = async (data: TInvitee[]) => {
try {
await Promise.all(
const handleAddMembers = async (data: TInvitee[]) => {
if (data.length === 1) {
// Individual invite
const inviteUserActionResult = await inviteUserAction({
organizationId: organization.id,
email: data[0].email.toLowerCase(),
name: data[0].name,
role: data[0].role,
teamIds: data[0].teamIds,
});
if (inviteUserActionResult?.data) {
toast.success(t("environments.settings.general.member_invited_successfully"));
} else {
const errorMessage = getFormattedErrorMessage(inviteUserActionResult);
toast.error(errorMessage);
}
} else {
const invitePromises = await Promise.all(
data.map(async ({ name, email, role, teamIds }) => {
await inviteUserAction({ organizationId: organization.id, email, name, role, teamIds });
const inviteUserActionResult = await inviteUserAction({
organizationId: organization.id,
email: email.toLowerCase(),
name,
role,
teamIds: teamIds,
});
return {
email,
success: Boolean(inviteUserActionResult?.data),
};
})
);
toast.success(t("environments.settings.general.member_invited_successfully"));
} catch (err) {
toast.error(`${t("common.error")}: ${err.message}`);
let failedInvites: string[] = [];
let successInvites: string[] = [];
invitePromises.forEach((invite) => {
if (!invite.success) {
failedInvites.push(invite.email);
} else {
successInvites.push(invite.email);
}
});
if (failedInvites.length > 0) {
toast.error(`${failedInvites.length} ${t("environments.settings.general.invites_failed")}`);
}
if (successInvites.length > 0) {
toast.success(
`${successInvites.length} ${t("environments.settings.general.member_invited_successfully")}`
);
}
}
};
@@ -96,7 +136,7 @@ export const OrganizationActions = ({
<InviteMemberModal
open={isInviteMemberModalOpen}
setOpen={setInviteMemberModalOpen}
onSubmit={handleInviteMembers}
onSubmit={handleAddMembers}
canDoRoleManagement={canDoRoleManagement}
isFormbricksCloud={isFormbricksCloud}
environmentId={environmentId}