feat: Pending members selection (#10168)
* Pending members selection * Discard changes to .vscode/launch.json * revert yarn.lock --------- Co-authored-by: Omar López <zomars@me.com>
This commit is contained in:
co-authored by
Omar López
parent
d2104dac5a
commit
8ba4b4d50e
@@ -19,16 +19,17 @@ interface IUserToValue {
|
||||
email: string;
|
||||
}
|
||||
|
||||
const mapUserToValue = ({ id, name, username, email }: IUserToValue) => ({
|
||||
const mapUserToValue = ({ id, name, username, email }: IUserToValue, pendingString: string) => ({
|
||||
value: `${id || ""}`,
|
||||
label: `${name || ""}`,
|
||||
label: `${name || email || ""}${!username ? ` (${pendingString})` : ""}`,
|
||||
avatar: `${WEBAPP_URL}/${username}/avatar.png`,
|
||||
email,
|
||||
});
|
||||
|
||||
export const mapMemberToChildrenOption = (
|
||||
member: EventTypeSetupProps["teamMembers"][number],
|
||||
slug: string
|
||||
slug: string,
|
||||
pendingString: string
|
||||
) => {
|
||||
return {
|
||||
slug,
|
||||
@@ -43,7 +44,7 @@ export const mapMemberToChildrenOption = (
|
||||
eventTypeSlugs: member.eventTypes ?? [],
|
||||
},
|
||||
value: `${member.id ?? ""}`,
|
||||
label: member.name ?? "",
|
||||
label: `${member.name || member.email || ""}${!member.username ? ` (${pendingString})` : ""}`,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -291,9 +292,13 @@ export const EventTeamTab = ({
|
||||
// description: t("round_robin_description"),
|
||||
},
|
||||
];
|
||||
const teamMembersOptions = teamMembers.map(mapUserToValue);
|
||||
const childrenEventTypeOptions = teamMembers.map((member) => {
|
||||
return mapMemberToChildrenOption(member, eventType.slug);
|
||||
const pendingMembers = (member: (typeof teamMembers)[number]) =>
|
||||
!!eventType.team?.parentId || !!member.username;
|
||||
const teamMembersOptions = teamMembers
|
||||
.filter(pendingMembers)
|
||||
.map((member) => mapUserToValue(member, t("pending")));
|
||||
const childrenEventTypeOptions = teamMembers.filter(pendingMembers).map((member) => {
|
||||
return mapMemberToChildrenOption(member, eventType.slug, t("pending"));
|
||||
});
|
||||
const isManagedEventType = eventType.schedulingType === SchedulingType.MANAGED;
|
||||
return (
|
||||
|
||||
@@ -130,7 +130,9 @@ function TeamPage({ team, isUnpublished, markdownStrippedBio, isValidOrgDomain }
|
||||
<div className="ms-3 inline-block truncate">
|
||||
<span className="text-default text-sm font-bold">{ch.name}</span>
|
||||
<span className="text-subtle block text-xs">
|
||||
{t("number_member", { count: ch.members.length })}
|
||||
{t("number_member", {
|
||||
count: ch.members.filter((mem) => mem.user.username !== null).length,
|
||||
})}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -138,11 +140,13 @@ function TeamPage({ team, isUnpublished, markdownStrippedBio, isValidOrgDomain }
|
||||
className="mr-6"
|
||||
size="sm"
|
||||
truncateAfter={4}
|
||||
items={ch.members.map(({ user: member }) => ({
|
||||
alt: member.name || "",
|
||||
image: `/${member.username}/avatar.png`,
|
||||
title: member.name || "",
|
||||
}))}
|
||||
items={ch.members
|
||||
.filter((mem) => mem.user.username !== null)
|
||||
.map(({ user: member }) => ({
|
||||
alt: member.name || "",
|
||||
image: `/${member.username}/avatar.png`,
|
||||
title: member.name || "",
|
||||
}))}
|
||||
/>
|
||||
</Link>
|
||||
</li>
|
||||
|
||||
@@ -62,12 +62,12 @@ export const ChildrenEventTypeSelect = ({
|
||||
size="mdLg"
|
||||
className="overflow-visible"
|
||||
imageSrc={`${CAL_URL}/${children.owner.username}/avatar.png`}
|
||||
alt={children.owner.name || ""}
|
||||
alt={children.owner.name || children.owner.email || ""}
|
||||
/>
|
||||
<div className="flex w-full flex-row justify-between">
|
||||
<div className="flex flex-col">
|
||||
<span className="text text-sm font-semibold leading-none">
|
||||
{children.owner.name}
|
||||
{children.owner.name || children.owner.email}
|
||||
<div className="flex flex-row gap-1">
|
||||
{children.owner.membership === MembershipRole.OWNER ? (
|
||||
<Badge variant="gray">{t("owner")}</Badge>
|
||||
@@ -77,9 +77,11 @@ export const ChildrenEventTypeSelect = ({
|
||||
{children.hidden && <Badge variant="gray">{t("hidden")}</Badge>}
|
||||
</div>
|
||||
</span>
|
||||
<small className="text-subtle font-normal leading-normal">
|
||||
{`/${children.owner.username}/${children.slug}`}
|
||||
</small>
|
||||
{children.owner.username && (
|
||||
<small className="text-subtle font-normal leading-normal">
|
||||
{`/${children.owner.username}/${children.slug}`}
|
||||
</small>
|
||||
)}
|
||||
</div>
|
||||
<div className="flex flex-row items-center gap-2">
|
||||
<Tooltip content={t("show_eventtype_on_profile")}>
|
||||
@@ -97,7 +99,7 @@ export const ChildrenEventTypeSelect = ({
|
||||
</div>
|
||||
</Tooltip>
|
||||
<ButtonGroup combined>
|
||||
{children.created && (
|
||||
{children.created && children.owner.username && (
|
||||
<Tooltip content={t("preview")}>
|
||||
<Button
|
||||
color="secondary"
|
||||
|
||||
@@ -117,9 +117,6 @@ export default async function getEventTypeById({
|
||||
slug: true,
|
||||
parentId: true,
|
||||
members: {
|
||||
where: {
|
||||
accepted: true,
|
||||
},
|
||||
select: {
|
||||
role: true,
|
||||
user: {
|
||||
@@ -356,7 +353,11 @@ export default async function getEventTypeById({
|
||||
...member.user,
|
||||
avatar: `${CAL_URL}/${member.user.username}/avatar.png`,
|
||||
};
|
||||
return { ...user, eventTypes: user.eventTypes.map((evTy) => evTy.slug), membership: member.role };
|
||||
return {
|
||||
...user,
|
||||
eventTypes: user.eventTypes.map((evTy) => evTy.slug),
|
||||
membership: member.role,
|
||||
};
|
||||
})
|
||||
: [];
|
||||
|
||||
|
||||
@@ -67,6 +67,7 @@ export const updateHandler = async ({ ctx, input }: UpdateOptions) => {
|
||||
select: {
|
||||
name: true,
|
||||
id: true,
|
||||
parentId: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -187,7 +188,8 @@ export const updateHandler = async ({ ctx, input }: UpdateOptions) => {
|
||||
const teamMemberIds = memberships.map((membership) => membership.userId);
|
||||
// guard against missing IDs, this may mean a member has just been removed
|
||||
// or this request was forged.
|
||||
if (!hosts.every((host) => teamMemberIds.includes(host.userId))) {
|
||||
// we let this pass through on organization sub-teams
|
||||
if (!hosts.every((host) => teamMemberIds.includes(host.userId)) && !eventType.team?.parentId) {
|
||||
throw new TRPCError({
|
||||
code: "FORBIDDEN",
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user