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:
Leo Giovanetti
2023-07-20 11:23:15 +05:30
committed by GitHub
co-authored by Omar López
parent d2104dac5a
commit 8ba4b4d50e
5 changed files with 38 additions and 24 deletions
+12 -7
View File
@@ -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 (
+10 -6
View File
@@ -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"
+5 -4
View File
@@ -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",
});