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 <peeroke@gmail.com> Co-authored-by: Alex van Andel <me@alexvanandel.com>
This commit is contained in:
co-authored by
Peer Richelsen
Alex van Andel
parent
0dddc2224a
commit
698d8ae4bd
@@ -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<typeof UserAvatar> & {
|
||||
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 (
|
||||
<UserAvatar
|
||||
data-testid="organization-avatar"
|
||||
size={size}
|
||||
user={user}
|
||||
previewSrc={previewSrc}
|
||||
indicator={
|
||||
organization ? (
|
||||
<div
|
||||
className={classNames("absolute bottom-0 right-0 z-10", size === "lg" ? "h-6 w-6" : "h-10 w-10")}>
|
||||
<img
|
||||
src={getOrgAvatarUrl(organization)}
|
||||
alt={user.username || ""}
|
||||
className="flex h-full items-center justify-center rounded-full"
|
||||
/>
|
||||
</div>
|
||||
) : null
|
||||
}
|
||||
{...rest}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default OrganizationMemberAvatar;
|
||||
@@ -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];
|
||||
}
|
||||
|
||||
@@ -205,6 +205,7 @@ const OrgProfileForm = ({ defaultValues }: { defaultValues: FormValues }) => {
|
||||
return (
|
||||
<>
|
||||
<Avatar
|
||||
data-testid="profile-upload-avatar"
|
||||
alt={defaultValues.name || ""}
|
||||
imageSrc={getPlaceholderAvatar(value, defaultValues.name as string)}
|
||||
size="lg"
|
||||
|
||||
@@ -13,9 +13,16 @@ import { useTelemetry, telemetryEventTypes } from "@calcom/lib/telemetry";
|
||||
import { MembershipRole } from "@calcom/prisma/enums";
|
||||
import type { RouterOutputs } from "@calcom/trpc/react";
|
||||
import { trpc } from "@calcom/trpc/react";
|
||||
import { Badge, Button, showToast, SkeletonButton, SkeletonContainer, SkeletonText } from "@calcom/ui";
|
||||
import {
|
||||
Badge,
|
||||
Button,
|
||||
showToast,
|
||||
SkeletonButton,
|
||||
SkeletonContainer,
|
||||
SkeletonText,
|
||||
UserAvatar,
|
||||
} from "@calcom/ui";
|
||||
import { ArrowRight, Plus, Trash2 } from "@calcom/ui/components/icon";
|
||||
import { UserAvatar } from "@calcom/web/components/ui/avatar/UserAvatar";
|
||||
|
||||
type TeamMember = RouterOutputs["viewer"]["teams"]["get"]["members"][number];
|
||||
|
||||
|
||||
@@ -26,8 +26,8 @@ import {
|
||||
showToast,
|
||||
Tooltip,
|
||||
} from "@calcom/ui";
|
||||
import { UserAvatar } from "@calcom/ui";
|
||||
import { ExternalLink, MoreHorizontal, Edit2, Lock, UserX } from "@calcom/ui/components/icon";
|
||||
import { UserAvatar } from "@calcom/web/components/ui/avatar/UserAvatar";
|
||||
|
||||
import MemberChangeRoleModal from "./MemberChangeRoleModal";
|
||||
import TeamAvailabilityModal from "./TeamAvailabilityModal";
|
||||
|
||||
@@ -9,7 +9,7 @@ import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||
import type { MembershipRole } from "@calcom/prisma/enums";
|
||||
import { trpc } from "@calcom/trpc";
|
||||
import { Button, ButtonGroup, DataTable } from "@calcom/ui";
|
||||
import { UserAvatar } from "@calcom/web/components/ui/avatar/UserAvatar";
|
||||
import { UserAvatar } from "@calcom/ui";
|
||||
|
||||
import { UpgradeTip } from "../../tips/UpgradeTip";
|
||||
import { TBContext, createTimezoneBuddyStore } from "../store";
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
/* eslint-disable playwright/missing-playwright-await */
|
||||
import { render } from "@testing-library/react";
|
||||
|
||||
import { AVATAR_FALLBACK } from "@calcom/lib/constants";
|
||||
|
||||
import { UserAvatar } from "./UserAvatar";
|
||||
|
||||
const mockUser = {
|
||||
name: "John Doe",
|
||||
username: "pro",
|
||||
organizationId: null,
|
||||
};
|
||||
|
||||
describe("tests for UserAvatar component", () => {
|
||||
test("Should render the UsersAvatar Correctly", () => {
|
||||
const { getByTestId } = render(<UserAvatar user={mockUser} data-testid="user-avatar-test" />);
|
||||
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(
|
||||
<UserAvatar
|
||||
user={mockUser}
|
||||
organization={{ id: -1, requestedSlug: "steve", slug: "steve", logoUrl: AVATAR_FALLBACK }}
|
||||
data-testid="user-avatar-test"
|
||||
/>
|
||||
);
|
||||
|
||||
const avatar = getByTestId("user-avatar-test");
|
||||
const organizationLogo = getByTestId("organization-logo");
|
||||
|
||||
expect(avatar).toBeInTheDocument();
|
||||
expect(organizationLogo).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
@@ -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<React.ComponentProps<typeof Avatar>, "alt" | "imageSrc"> & {
|
||||
user: Pick<User, "organizationId" | "name" | "username">;
|
||||
/**
|
||||
* 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<UserAvatarProps, "size" | "user"> & { organization: Organization }) {
|
||||
const organizationUrl = organization.logoUrl ?? getOrgAvatarUrl(organization);
|
||||
return (
|
||||
<div className={classNames("absolute bottom-0 right-0 z-10", size === "lg" ? "h-6 w-6" : "h-10 w-10")}>
|
||||
<img
|
||||
data-testId="organization-logo"
|
||||
src={organizationUrl}
|
||||
alt={user.username || ""}
|
||||
className="flex h-full items-center justify-center rounded-full"
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 ? (
|
||||
<OrganizationIndicator size={props.size} organization={props.organization} user={props.user} />
|
||||
) : (
|
||||
props.indicator
|
||||
);
|
||||
|
||||
return <Avatar {...rest} alt={user.name || "Nameless User"} imageSrc={previewSrc} indicator={indicator} />;
|
||||
}
|
||||
@@ -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";
|
||||
|
||||
@@ -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";
|
||||
|
||||
Reference in New Issue
Block a user