232 lines
6.5 KiB
TypeScript
232 lines
6.5 KiB
TypeScript
import React, { useState, useCallback } from "react";
|
|
import classnames from "classnames";
|
|
|
|
import { COLORS } from "styles/var/colors";
|
|
import { DEFAULT_GRAVATAR_LINK } from "utilities/constants";
|
|
|
|
interface IFleetAvatarProps {
|
|
className?: string;
|
|
}
|
|
|
|
/**
|
|
* a simple component that can be used to display a the Fleet logo as an avatar
|
|
*/
|
|
const FleetAvatar = ({ className }: IFleetAvatarProps) => {
|
|
return (
|
|
<svg
|
|
data-testid="fleet-avatar"
|
|
className={className}
|
|
width="32"
|
|
height="32"
|
|
viewBox="0 0 32 32"
|
|
fill="none"
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
>
|
|
<circle cx="16" cy="16" r="15.5" fill="white" stroke="#C5C7D1" />
|
|
<path
|
|
d="M10 12C11.1046 12 12 11.1046 12 10C12 8.89543 11.1046 8 10 8C8.89543 8 8 8.89543 8 10C8 11.1046 8.89543 12 10 12Z"
|
|
fill="white"
|
|
/>
|
|
<path
|
|
d="M16 12C17.1046 12 18 11.1046 18 10C18 8.89543 17.1046 8 16 8C14.8954 8 14 8.89543 14 10C14 11.1046 14.8954 12 16 12Z"
|
|
fill="white"
|
|
/>
|
|
<path
|
|
d="M22 12C23.1046 12 24 11.1046 24 10C24 8.89543 23.1046 8 22 8C20.8954 8 20 8.89543 20 10C20 11.1046 20.8954 12 22 12Z"
|
|
fill="white"
|
|
/>
|
|
<path
|
|
d="M10 18C11.1046 18 12 17.1046 12 16C12 14.8954 11.1046 14 10 14C8.89543 14 8 14.8954 8 16C8 17.1046 8.89543 18 10 18Z"
|
|
fill="white"
|
|
/>
|
|
<path
|
|
d="M16 18C17.1046 18 18 17.1046 18 16C18 14.8954 17.1046 14 16 14C14.8954 14 14 14.8954 14 16C14 17.1046 14.8954 18 16 18Z"
|
|
fill="white"
|
|
/>
|
|
<path
|
|
d="M10 24C11.1046 24 12 23.1046 12 22C12 20.8954 11.1046 20 10 20C8.89543 20 8 20.8954 8 22C8 23.1046 8.89543 24 10 24Z"
|
|
fill="white"
|
|
/>
|
|
<path
|
|
d="M10.75 12.5C11.7165 12.5 12.5 11.7165 12.5 10.75C12.5 9.7835 11.7165 9 10.75 9C9.7835 9 9 9.7835 9 10.75C9 11.7165 9.7835 12.5 10.75 12.5Z"
|
|
fill="#63C740"
|
|
/>
|
|
<path
|
|
d="M16 12.5C16.9665 12.5 17.75 11.7165 17.75 10.75C17.75 9.7835 16.9665 9 16 9C15.0335 9 14.25 9.7835 14.25 10.75C14.25 11.7165 15.0335 12.5 16 12.5Z"
|
|
fill="#5CABDF"
|
|
/>
|
|
<path
|
|
d="M21.25 12.5C22.2165 12.5 23 11.7165 23 10.75C23 9.7835 22.2165 9 21.25 9C20.2835 9 19.5 9.7835 19.5 10.75C19.5 11.7165 20.2835 12.5 21.25 12.5Z"
|
|
fill="#D66C7B"
|
|
/>
|
|
<path
|
|
d="M10.75 17.75C11.7165 17.75 12.5 16.9665 12.5 16C12.5 15.0335 11.7165 14.25 10.75 14.25C9.7835 14.25 9 15.0335 9 16C9 16.9665 9.7835 17.75 10.75 17.75Z"
|
|
fill="#C98DEF"
|
|
/>
|
|
<path
|
|
d="M16 17.75C16.9665 17.75 17.75 16.9665 17.75 16C17.75 15.0335 16.9665 14.25 16 14.25C15.0335 14.25 14.25 15.0335 14.25 16C14.25 16.9665 15.0335 17.75 16 17.75Z"
|
|
fill="#FAA669"
|
|
/>
|
|
<path
|
|
d="M10.75 23C11.7165 23 12.5 22.2165 12.5 21.25C12.5 20.2835 11.7165 19.5 10.75 19.5C9.7835 19.5 9 20.2835 9 21.25C9 22.2165 9.7835 23 10.75 23Z"
|
|
fill="#3AEFC3"
|
|
/>
|
|
</svg>
|
|
);
|
|
};
|
|
|
|
interface IAPIOnlyAvatar {
|
|
className?: string;
|
|
}
|
|
|
|
const APIOnlyAvatar = ({ className }: IAPIOnlyAvatar) => {
|
|
return (
|
|
<svg
|
|
data-testid="apionly-avatar"
|
|
className={className}
|
|
width="32"
|
|
height="32"
|
|
viewBox="0 0 32 32"
|
|
fill="none"
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
>
|
|
<circle
|
|
cx="16"
|
|
cy="16"
|
|
r="15"
|
|
fill="white"
|
|
stroke={COLORS["ui-fleet-black-50"]}
|
|
strokeWidth="2"
|
|
/>
|
|
<path
|
|
d="M11.5 12.75L8 16L11.5 19.25"
|
|
stroke={COLORS["ui-fleet-black-50"]}
|
|
strokeWidth="2"
|
|
strokeLinecap="round"
|
|
strokeLinejoin="round"
|
|
/>
|
|
<path
|
|
d="M18 11L14.5 21"
|
|
stroke={COLORS["ui-fleet-black-50"]}
|
|
strokeWidth="2"
|
|
strokeLinecap="round"
|
|
strokeLinejoin="round"
|
|
/>
|
|
<path
|
|
d="M21 19.25L24.5 16L21 12.75"
|
|
stroke={COLORS["ui-fleet-black-50"]}
|
|
strokeWidth="2"
|
|
strokeLinecap="round"
|
|
strokeLinejoin="round"
|
|
/>
|
|
</svg>
|
|
);
|
|
};
|
|
|
|
interface IDefaultAvatar {
|
|
className?: string;
|
|
}
|
|
|
|
const DefaultAvatar = ({ className }: IAPIOnlyAvatar) => {
|
|
return (
|
|
<svg
|
|
data-testid="default-avatar"
|
|
className={className}
|
|
width="32"
|
|
height="32"
|
|
viewBox="0 0 32 32"
|
|
fill="none"
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
>
|
|
<circle
|
|
cx="16"
|
|
cy="16"
|
|
r="15.25"
|
|
stroke={COLORS["ui-fleet-black-50"]}
|
|
strokeWidth="1.5"
|
|
/>
|
|
<circle
|
|
cx="16"
|
|
cy="13"
|
|
r="5.25"
|
|
stroke={COLORS["ui-fleet-black-50"]}
|
|
strokeWidth="1.5"
|
|
/>
|
|
<path
|
|
stroke={COLORS["ui-fleet-black-50"]}
|
|
strokeWidth="1.5"
|
|
d="M16 18.75c5.084 0 9.21 4.102 9.248 9.178-.01.017-.024.044-.052.08a2.945 2.945 0 0 1-.462.463c-.448.374-1.127.812-1.99 1.23-1.725.833-4.114 1.549-6.744 1.549s-5.019-.716-6.744-1.55c-.863-.417-1.542-.855-1.99-1.23a2.945 2.945 0 0 1-.462-.461c-.028-.037-.043-.064-.053-.081A9.25 9.25 0 0 1 16 18.75Z"
|
|
/>
|
|
</svg>
|
|
);
|
|
};
|
|
|
|
interface IAvatarUserInterface {
|
|
gravatar_url?: string;
|
|
gravatar_url_dark?: string;
|
|
}
|
|
|
|
interface IAvatarProps {
|
|
className?: string;
|
|
size?: string;
|
|
user: IAvatarUserInterface;
|
|
hasWhiteBackground?: boolean;
|
|
/**
|
|
* Set this to `true` to use the fleet avatar instead of the users gravatar.
|
|
*/
|
|
useFleetAvatar?: boolean;
|
|
// Set this to true to show the API Only avatar
|
|
useApiOnlyAvatar?: boolean;
|
|
}
|
|
|
|
const baseClass = "avatar";
|
|
|
|
const Avatar = ({
|
|
className,
|
|
size,
|
|
user,
|
|
hasWhiteBackground,
|
|
useApiOnlyAvatar = false,
|
|
useFleetAvatar = false,
|
|
}: IAvatarProps) => {
|
|
const [isLoading, setIsLoading] = useState(true);
|
|
const [isError, setIsError] = useState(false);
|
|
|
|
const onLoad = useCallback(() => {
|
|
setIsLoading(false);
|
|
}, []);
|
|
const onError = useCallback(() => {
|
|
setIsError(true);
|
|
}, []);
|
|
|
|
const avatarClasses = classnames(baseClass, className, {
|
|
[`${baseClass}--${size?.toLowerCase()}`]: !!size,
|
|
"has-white-background": !!hasWhiteBackground,
|
|
});
|
|
const { gravatar_url } = user;
|
|
|
|
let avatar;
|
|
|
|
if (useFleetAvatar) {
|
|
avatar = <FleetAvatar className={avatarClasses} />;
|
|
} else if (useApiOnlyAvatar) {
|
|
avatar = <APIOnlyAvatar className={avatarClasses} />;
|
|
} else if (gravatar_url) {
|
|
avatar = (
|
|
<img
|
|
alt="User avatar"
|
|
className={`${avatarClasses} ${isLoading || isError ? "default" : ""}`}
|
|
src={gravatar_url}
|
|
onError={onError}
|
|
onLoad={onLoad}
|
|
/>
|
|
);
|
|
} else {
|
|
avatar = <DefaultAvatar className={avatarClasses} />;
|
|
}
|
|
|
|
return <div className="avatar-wrapper">{avatar}</div>;
|
|
};
|
|
|
|
export default Avatar;
|