From 698d8ae4bdbc27a87d2e3fff4a4f190eddc1925f Mon Sep 17 00:00:00 2001 From: sean-brydon <55134778+sean-brydon@users.noreply.github.com> Date: Fri, 5 Jan 2024 20:36:44 +1000 Subject: [PATCH] chore: front-end-avatars (#12716) * Update UserAvatar and remove org avatar * Update Imports * Fix imports to use calcom/ui * type: fix imports * fix: use testId on profile * test: use image src instead of innerHTML * fix: Allow alt on useravatar * test: add testId to org profile --------- Co-authored-by: Peer Richelsen Co-authored-by: Alex van Andel --- .../steps-views/UserProfile.tsx | 6 +-- apps/web/components/team/screens/Team.tsx | 3 +- apps/web/components/ui/avatar/UserAvatar.tsx | 19 ------- apps/web/pages/[user].tsx | 4 +- .../web/pages/settings/my-account/profile.tsx | 5 +- .../playwright/settings/upload-avatar.e2e.ts | 5 +- .../components/OrganizationMemberAvatar.tsx | 47 ---------------- .../pages/components/MemberListItem.tsx | 3 +- .../organizations/pages/settings/profile.tsx | 1 + .../ee/teams/components/AddNewTeamMembers.tsx | 11 +++- .../ee/teams/components/MemberListItem.tsx | 2 +- .../components/AvailabilitySliderTable.tsx | 2 +- .../ui/components/avatar/UserAvatar.test.tsx | 37 +++++++++++++ packages/ui/components/avatar/UserAvatar.tsx | 54 +++++++++++++++++++ packages/ui/components/avatar/index.ts | 1 + packages/ui/index.tsx | 2 +- 16 files changed, 118 insertions(+), 84 deletions(-) delete mode 100644 apps/web/components/ui/avatar/UserAvatar.tsx delete mode 100644 packages/features/ee/organizations/components/OrganizationMemberAvatar.tsx create mode 100644 packages/ui/components/avatar/UserAvatar.test.tsx create mode 100644 packages/ui/components/avatar/UserAvatar.tsx diff --git a/apps/web/components/getting-started/steps-views/UserProfile.tsx b/apps/web/components/getting-started/steps-views/UserProfile.tsx index 79141c1361..54ff76fc1f 100644 --- a/apps/web/components/getting-started/steps-views/UserProfile.tsx +++ b/apps/web/components/getting-started/steps-views/UserProfile.tsx @@ -3,7 +3,6 @@ import type { FormEvent } from "react"; import { useRef, useState } from "react"; import { useForm } from "react-hook-form"; -import OrganizationMemberAvatar from "@calcom/features/ee/organizations/components/OrganizationMemberAvatar"; import { useLocale } from "@calcom/lib/hooks/useLocale"; import { md } from "@calcom/lib/markdownIt"; import { telemetryEventTypes, useTelemetry } from "@calcom/lib/telemetry"; @@ -11,6 +10,7 @@ import turndown from "@calcom/lib/turndownService"; import { trpc } from "@calcom/trpc/react"; import type { Ensure } from "@calcom/types/utils"; import { Button, Editor, ImageUploader, Label, showToast } from "@calcom/ui"; +import { UserAvatar } from "@calcom/ui"; import { ArrowRight } from "@calcom/ui/components/icon"; type FormData = { @@ -108,9 +108,7 @@ const UserProfile = () => { return (
- {user && ( - - )} + {user && } , "inviteToken">; type MembersType = TeamType["members"]; diff --git a/apps/web/components/ui/avatar/UserAvatar.tsx b/apps/web/components/ui/avatar/UserAvatar.tsx deleted file mode 100644 index a542fc3d9f..0000000000 --- a/apps/web/components/ui/avatar/UserAvatar.tsx +++ /dev/null @@ -1,19 +0,0 @@ -import { getUserAvatarUrl } from "@calcom/lib/getAvatarUrl"; -import type { User } from "@calcom/prisma/client"; -import { Avatar } from "@calcom/ui"; - -type UserAvatarProps = Omit, "alt" | "imageSrc"> & { - user: Pick; - /** - * Useful when allowing the user to upload their own avatar and showing the avatar before it's uploaded - */ - previewSrc?: string | null; -}; - -/** - * It is aware of the user's organization to correctly show the avatar from the correct URL - */ -export function UserAvatar(props: UserAvatarProps) { - const { user, previewSrc = getUserAvatarUrl(user), ...rest } = props; - return ; -} diff --git a/apps/web/pages/[user].tsx b/apps/web/pages/[user].tsx index d51280a379..349c8be4b6 100644 --- a/apps/web/pages/[user].tsx +++ b/apps/web/pages/[user].tsx @@ -11,7 +11,6 @@ import { useEmbedStyles, useIsEmbed, } from "@calcom/embed-core/embed-iframe"; -import OrganizationMemberAvatar from "@calcom/features/ee/organizations/components/OrganizationMemberAvatar"; import { getSlugOrRequestedSlug } from "@calcom/features/ee/organizations/lib/orgDomains"; import { orgDomainConfig } from "@calcom/features/ee/organizations/lib/orgDomains"; import { EventTypeDescriptionLazy as EventTypeDescription } from "@calcom/features/eventtypes/components"; @@ -28,6 +27,7 @@ import { RedirectType, type EventType, type User } from "@calcom/prisma/client"; import { baseEventTypeSelect } from "@calcom/prisma/selects"; import { EventTypeMetaDataSchema, teamMetadataSchema } from "@calcom/prisma/zod-utils"; import { HeadSeo, UnpublishedEntity } from "@calcom/ui"; +import { UserAvatar } from "@calcom/ui"; import { Verified, ArrowRight } from "@calcom/ui/components/icon"; import type { EmbedProps } from "@lib/withEmbedSsr"; @@ -101,7 +101,7 @@ export function UserPage(props: InferGetServerSidePropsType
- - { // todo: remove this; ideally the organization-avatar is updated the moment // 'Settings updated succesfully' is saved. await page.waitForLoadState("networkidle"); + const avatar = page.getByTestId("profile-upload-avatar").locator("img"); - await expect(await page.getByTestId("organization-avatar").innerHTML()).toContain(response.objectKey); + const src = await avatar.getAttribute("src"); + + await expect(src).toContain(response.objectKey); const urlResponse = await page.request.get(`/api/avatar/${response.objectKey}.png`, { maxRedirects: 0, diff --git a/packages/features/ee/organizations/components/OrganizationMemberAvatar.tsx b/packages/features/ee/organizations/components/OrganizationMemberAvatar.tsx deleted file mode 100644 index 7c898776c7..0000000000 --- a/packages/features/ee/organizations/components/OrganizationMemberAvatar.tsx +++ /dev/null @@ -1,47 +0,0 @@ -import classNames from "@calcom/lib/classNames"; -import { getOrgAvatarUrl } from "@calcom/lib/getAvatarUrl"; -// import { Avatar } from "@calcom/ui"; -import { UserAvatar } from "@calcom/web/components/ui/avatar/UserAvatar"; - -type OrganizationMemberAvatarProps = React.ComponentProps & { - organization: { - id: number; - slug: string | null; - requestedSlug: string | null; - } | null; -}; - -/** - * Shows the user's avatar along with a small organization's avatar - */ -const OrganizationMemberAvatar = ({ - size, - user, - organization, - previewSrc, - ...rest -}: OrganizationMemberAvatarProps) => { - return ( - - {user.username -
- ) : null - } - {...rest} - /> - ); -}; - -export default OrganizationMemberAvatar; diff --git a/packages/features/ee/organizations/pages/components/MemberListItem.tsx b/packages/features/ee/organizations/pages/components/MemberListItem.tsx index 34e7190c3b..d36baaac9f 100644 --- a/packages/features/ee/organizations/pages/components/MemberListItem.tsx +++ b/packages/features/ee/organizations/pages/components/MemberListItem.tsx @@ -12,11 +12,10 @@ import { DropdownMenuItem, DropdownMenuTrigger, Tooltip, + UserAvatar, } from "@calcom/ui"; import { ExternalLink, MoreHorizontal } from "@calcom/ui/components/icon"; -import { UserAvatar } from "@components/ui/avatar/UserAvatar"; - interface Props { member: RouterOutputs["viewer"]["organizations"]["listOtherTeamMembers"]["rows"][number]; } diff --git a/packages/features/ee/organizations/pages/settings/profile.tsx b/packages/features/ee/organizations/pages/settings/profile.tsx index 1e690870e7..b2bb7063dd 100644 --- a/packages/features/ee/organizations/pages/settings/profile.tsx +++ b/packages/features/ee/organizations/pages/settings/profile.tsx @@ -205,6 +205,7 @@ const OrgProfileForm = ({ defaultValues }: { defaultValues: FormValues }) => { return ( <> { + test("Should render the UsersAvatar Correctly", () => { + const { getByTestId } = render(); + const avatar = getByTestId("user-avatar-test"); + + expect(avatar).toBeInTheDocument(); + }); + + test("It should render the organization logo if a organization is passed in", () => { + const { getByTestId } = render( + + ); + + const avatar = getByTestId("user-avatar-test"); + const organizationLogo = getByTestId("organization-logo"); + + expect(avatar).toBeInTheDocument(); + expect(organizationLogo).toBeInTheDocument(); + }); +}); diff --git a/packages/ui/components/avatar/UserAvatar.tsx b/packages/ui/components/avatar/UserAvatar.tsx new file mode 100644 index 0000000000..cc38e76020 --- /dev/null +++ b/packages/ui/components/avatar/UserAvatar.tsx @@ -0,0 +1,54 @@ +import { classNames } from "@calcom/lib"; +import { getOrgAvatarUrl, getUserAvatarUrl } from "@calcom/lib/getAvatarUrl"; +import type { User } from "@calcom/prisma/client"; +import { Avatar } from "@calcom/ui"; + +type Organization = { + id: number; + slug: string | null; + requestedSlug: string | null; + logoUrl?: string; +}; + +type UserAvatarProps = Omit, "alt" | "imageSrc"> & { + user: Pick; + /** + * Useful when allowing the user to upload their own avatar and showing the avatar before it's uploaded + */ + previewSrc?: string | null; + organization?: Organization | null; + alt?: string | null; +}; + +function OrganizationIndicator({ + size, + organization, + user, +}: Pick & { organization: Organization }) { + const organizationUrl = organization.logoUrl ?? getOrgAvatarUrl(organization); + return ( +
+ {user.username +
+ ); +} + +/** + * It is aware of the user's organization to correctly show the avatar from the correct URL + */ +export function UserAvatar(props: UserAvatarProps) { + const { user, previewSrc = getUserAvatarUrl(user), ...rest } = props; + + const indicator = props.organization ? ( + + ) : ( + props.indicator + ); + + return ; +} diff --git a/packages/ui/components/avatar/index.ts b/packages/ui/components/avatar/index.ts index d3908f8bc5..a24a507aae 100644 --- a/packages/ui/components/avatar/index.ts +++ b/packages/ui/components/avatar/index.ts @@ -1,4 +1,5 @@ export { Avatar } from "./Avatar"; +export { UserAvatar } from "./UserAvatar"; export type { AvatarProps } from "./Avatar"; export { AvatarGroup } from "./AvatarGroup"; export type { AvatarGroupProps } from "./AvatarGroup"; diff --git a/packages/ui/index.tsx b/packages/ui/index.tsx index c7f60603cd..7db5db6658 100644 --- a/packages/ui/index.tsx +++ b/packages/ui/index.tsx @@ -1,4 +1,4 @@ -export { Avatar, AvatarGroup } from "./components/avatar"; +export { Avatar, AvatarGroup, UserAvatar } from "./components/avatar"; export type { AvatarProps, AvatarGroupProps } from "./components/avatar"; export { ArrowButton } from "./components/arrow-button"; export type { ArrowButtonProps } from "./components/arrow-button";