Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: scatter plot tooltip issue and remove cloudinary rounded image solution #1266

Merged
merged 4 commits into from
Jun 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 21 additions & 26 deletions components/atoms/Avatar/avatar-hover-card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,37 +5,32 @@ import Link from "next/link";
import HoverCardWrapper from "components/molecules/HoverCardWrapper/hover-card-wrapper";

import { getAvatarByUsername } from "lib/utils/github";
import roundedImage from "lib/utils/roundedImages";
bdougie marked this conversation as resolved.
Show resolved Hide resolved
import Image from "next/image";

declare interface AvatarProps {
contributor: string;
repositories: number[];
}

const AvatarHoverCard = ({ contributor, repositories }: AvatarProps): JSX.Element => {
const avatar = roundedImage(getAvatarByUsername(contributor), process.env.NEXT_PUBLIC_CLOUD_NAME);

return (
<HoverCard.Root>
<Link href={`/user/${contributor}`} as={`/user/${contributor}`}>
<HoverCard.Trigger asChild>
<img
alt={contributor}
className="w-full h-full"
height={500}
src={avatar}
width={500}
/>
</HoverCard.Trigger>
</Link>
<HoverCard.Portal>
<HoverCard.Content sideOffset={5}>
<HoverCardWrapper username={contributor} repositories={repositories} />
</HoverCard.Content>
</HoverCard.Portal>
</HoverCard.Root>

);
};
const AvatarHoverCard = ({ contributor, repositories }: AvatarProps): JSX.Element => (
<HoverCard.Root>
<Link href={`/user/${contributor}`} as={`/user/${contributor}`}>
<HoverCard.Trigger asChild>
<Image
alt={contributor}
className="border rounded-full"
height={500}
src={getAvatarByUsername(contributor, 40)}
width={500}
/>
</HoverCard.Trigger>
</Link>
<HoverCard.Portal>
<HoverCard.Content sideOffset={5}>
<HoverCardWrapper username={contributor} repositories={repositories} />
</HoverCard.Content>
</HoverCard.Portal>
</HoverCard.Root>
);

export default AvatarHoverCard;
15 changes: 11 additions & 4 deletions components/molecules/CardProfile/card-profile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,26 @@ interface CardProfileProps {
githubName: string;
totalPRs: number;
dateOfFirstPR: string;
isRoundedAvatar?: boolean;
}

const CardProfile = ({ githubAvatar, githubName, totalPRs, dateOfFirstPR }: CardProfileProps): JSX.Element => {
const CardProfile = ({
githubAvatar,
githubName,
totalPRs,
dateOfFirstPR,
isRoundedAvatar,
}: CardProfileProps): JSX.Element => {
return (
<Link href={`/user/${githubName}`} as={`/user/${githubName}`}>
<div className="flex items-center gap-2">
<Avatar size={40} avatarURL={githubAvatar ? githubAvatar : undefined} />
<Avatar isCircle={isRoundedAvatar} size={40} avatarURL={githubAvatar ? githubAvatar : undefined} />
<div>
<div>
<Text className="!text-base !text-black ">{githubName}</Text>
</div>
<div className="flex gap-2 text-xs">
<div className="flex text-xs items-center gap-1 text-light-slate-11">
<div className="flex gap-2 text-xs">
<div className="flex items-center gap-1 text-xs text-light-slate-11">
{totalPRs !== undefined && (
<>
<Tooltip content="PRs merged">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ const ContributorHoverCard = ({
githubAvatar={githubAvatar}
githubName={githubName}
totalPRs={totalPR}
isRoundedAvatar={true}
/>
</div>
<div className="">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ import { useRouter } from "next/router";

import ContributorHoverCard, { ContributorsProfileType } from "../ContributorHoverCard/contributor-hover-card";

import roundedImage from "lib/utils/roundedImages";
import { useFetchUser } from "lib/hooks/useFetchUser";
import { useContributorPullRequestsChart } from "lib/hooks/useContributorPullRequestsChart";
import { getAvatarByUsername } from "lib/utils/github";

interface HoverCardWrapperProps {
username: string;
Expand All @@ -18,7 +18,7 @@ const HoverCardWrapper = ({ username, repositories }: HoverCardWrapperProps) =>
const { repoList } = useContributorPullRequestsChart(username, "*", repositories);

const profile: ContributorsProfileType = {
githubAvatar: roundedImage(`https://www.github.com/${username}.png?size=60`, process.env.NEXT_PUBLIC_CLOUD_NAME),
githubAvatar: getAvatarByUsername(username, 40),
githubName: username,
totalPR: repoList.length,
};
Expand Down
78 changes: 28 additions & 50 deletions components/molecules/NivoScatterChart/nivo-scatter-chart.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
import { useRouter } from "next/router";
import { MouseEvent, useCallback, useState } from "react";

import { ResponsiveScatterPlot } from "@nivo/scatterplot";
import { ResponsiveScatterPlot, ScatterPlotNodeProps } from "@nivo/scatterplot";
import { animated } from "@react-spring/web";

import humanizeNumber from "lib/utils/humanizeNumber";

import ToggleOption from "components/atoms/ToggleOption/toggle-option";
import Title from "components/atoms/Typography/title";
import HoverCardWrapper from "../HoverCardWrapper/hover-card-wrapper";
import ToggleGroup from "components/atoms/ToggleGroup/toggle-group";
import { PrStatusFilter } from "components/organisms/Dashboard/dashboard";
import AvatarHoverCard from "components/atoms/Avatar/avatar-hover-card";

export interface ScatterChartDataItems {
x: string | number;
Expand Down Expand Up @@ -49,13 +49,29 @@ const NivoScatterPlot = ({
isMobile,
repositories,
metadata,
handleSetPrFilter
handleSetPrFilter,
}: ScatterPlotProps) => {
const [showMembers, setShowMembers] = useState<boolean>(false);
const [isLogarithmic, setIsLogarithmic] = useState<boolean>(false);

let functionTimeout: any;

// Brought this in here to have access to repositories
const CustomNode = (props: ScatterPlotNodeProps<ScatterChartDataItems>) => {
return (
<animated.foreignObject
className="cursor-pointer"
width={35}
height={35}
r={props.style.size.to((size: number) => size / 2) as unknown as number}
y={props.style.y.to((yVal: number) => yVal - 35 / 1) as unknown as number}
x={props.style.x.to((xVal: number) => xVal - 35 / 2) as unknown as number}
>
<AvatarHoverCard contributor={props.node.data.contributor} repositories={repositories!} />
</animated.foreignObject>
);
};

const handleTogglePrFilter = (val: string) => {
switch (val) {
case "0":
Expand Down Expand Up @@ -102,7 +118,7 @@ const NivoScatterPlot = ({

return (
<>
<div className="flex flex-col md:flex-row justify-between px-7 pt-3 items-center">
<div className="flex flex-col items-center justify-between pt-3 md:flex-row px-7">
<Title level={4} className="!text-sm !text-light-slate-12">
{title}
</Title>
Expand All @@ -127,7 +143,7 @@ const NivoScatterPlot = ({
</>
</ToggleGroup>
{/* replaced display flex to hidden on show/bots container */}
<div className="flex mt-3 md:mt-0 flex-col md:flex-row gap-2">
<div className="flex flex-col gap-2 mt-3 md:mt-0 md:flex-row">
<div>
<ToggleOption handleToggle={handleShowBots} checked={showBots} optionText="Show Bots"></ToggleOption>
</div>
Expand All @@ -142,17 +158,15 @@ const NivoScatterPlot = ({
</div>
<div className="h-[400px]">
<ResponsiveScatterPlot
tooltip={({ node }) => (
<>{isMobile ? "" : <HoverCardWrapper repositories={repositories} username={node.data.contributor} />}</>
)}
// leaving this here for now so we don't see the default tooltip from nivo
nodeSize={isMobile ? 25 : 35}
data={isMobile ? filteredData : data}
margin={{ top: 30, right: isMobile ? 30 : 60, bottom: 70, left: isMobile ? 75 : 90 }}
xScale={{ type: "linear", min: 0, max: isMobile ? 7 : 32, reverse: true }}
yScale={{
type: isLogarithmic ? "symlog" : "linear",
min: 0,
max: Math.max(Math.round(maxFilesModified * 3), 10)
max: Math.max(Math.round(maxFilesModified * 3), 10),
}}
blendMode="normal"
useMesh={false}
Expand All @@ -163,17 +177,17 @@ const NivoScatterPlot = ({
tickPadding: 5,
tickRotation: 0,
tickValues: isMobile ? 4 : 7,
format: (value) => (value === 0 ? "Today" : value > 32 ? "30+ days ago" : `${value} days ago`)
format: (value) => (value === 0 ? "Today" : value > 32 ? "30+ days ago" : `${value} days ago`),
}}
theme={{
axis: {},
grid: {
line: {
strokeDasharray: "4 4",
strokeWidth: 1,
strokeOpacity: 0.7
}
}
strokeOpacity: 0.7,
},
},
}}
isInteractive={true}
axisLeft={{
Expand All @@ -186,48 +200,12 @@ const NivoScatterPlot = ({
legendOffset: -60,
format: (value: number) => {
return parseInt(`${value}`) >= 1000 ? humanizeNumber(value, "abbreviation") : `${value}`;
}
},
}}
/>
</div>
</>
);
};

const CustomNode = (props: any) => {
const router = useRouter();
const handleMouseEnter = useCallback(
(event: React.MouseEvent) => props.onMouseEnter?.(props.node, event),
[props.node.data.contributor, props.onMouseEnter]
);
const handleMouseMove = useCallback(
(event: MouseEvent) => props.onMouseMove?.(props.node, event),
[props.node.data.contributor, props.onMouseMove]
);
const handleMouseLeave = useCallback(
(event: React.MouseEvent) => props.onMouseLeave?.(props.node, event),
[props.node, props.onMouseLeave]
);
const handleClick = useCallback(
(event: React.MouseEvent) => router.push(`/user/${props.node.data.contributor}`),
[props.node, props.onClick]
);

return (
<animated.image
className="cursor-pointer"
width={35}
height={35}
r={props.style.size.to((size: number) => size / 2)}
y={props.style.y.to((yVal: number) => yVal - 35 / 1)}
x={props.style.x.to((xVal: number) => xVal - 35 / 2)}
href={props.node.data.image}
onMouseEnter={props.isInteractive ? handleMouseEnter : undefined}
onMouseMove={props.isInteractive ? handleMouseMove : undefined}
onMouseLeave={props.isInteractive ? handleMouseLeave : undefined}
onClick={props.isInteractive ? handleClick : undefined}
/>
);
};

export default NivoScatterPlot;
8 changes: 4 additions & 4 deletions components/organisms/Dashboard/dashboard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ import humanizeNumber from "lib/utils/humanizeNumber";
import { useMediaQuery } from "lib/hooks/useMediaQuery";
import { getInsights, useInsights } from "lib/hooks/api/useInsights";
import { calcDaysFromToday } from "lib/utils/date-utils";
import roundedImage from "lib/utils/roundedImages";
import usePullRequests from "lib/hooks/api/usePullRequests";
import useContributors from "lib/hooks/api/useContributors";
import { getAvatarByUsername } from "lib/utils/github";

type ContributorPrMap = { [contributor: string]: DbRepoPR };
export type PrStatusFilter = "open" | "closed" | "all";
Expand Down Expand Up @@ -73,7 +73,7 @@ const Dashboard = ({ repositories }: DashboardProps): JSX.Element => {
x: calcDaysFromToday(new Date(updated_at)),
y: linesCount,
contributor: author_login,
image: roundedImage(`https://www.github.com/${author_image}.png?size=60`, process.env.NEXT_PUBLIC_CLOUD_NAME),
image: getAvatarByUsername(author_image, 40),
};
return data;
});
Expand All @@ -92,7 +92,7 @@ const Dashboard = ({ repositories }: DashboardProps): JSX.Element => {

return (
<div className="flex flex-col w-full gap-4">
<section className="flex flex-wrap gap-4 items-center lg:flex-row lg:flex-nowrap max-w-full">
<section className="flex flex-wrap items-center max-w-full gap-4 lg:flex-row lg:flex-nowrap">
<HighlightCard
label="Contributors"
icon="contributors"
Expand Down Expand Up @@ -134,7 +134,7 @@ const Dashboard = ({ repositories }: DashboardProps): JSX.Element => {
isLoading={isLoading}
/>
</section>
<section className="flex flex-col lg:flex-row max-w-full gap-4 mb-6">
<section className="flex flex-col max-w-full gap-4 mb-6 lg:flex-row">
<div className="flex flex-col w-full">
<Card className="w-full">
<NivoScatterPlot
Expand Down
10 changes: 0 additions & 10 deletions lib/utils/roundedImages.ts

This file was deleted.