Skip to content

Commit

Permalink
Merge pull request #1094 from open-sauced/beta
Browse files Browse the repository at this point in the history
v1.41.0-beta.2 -> production
  • Loading branch information
brandonroberts committed Apr 13, 2023
2 parents 3b7c860 + e0633f1 commit 1b2e9c1
Show file tree
Hide file tree
Showing 15 changed files with 272 additions and 55 deletions.
14 changes: 14 additions & 0 deletions CHANGELOG.md
Expand Up @@ -5,6 +5,20 @@

> All notable changes to this project will be documented in this file
## [1.41.0-beta.2](https://github.com/open-sauced/insights/compare/v1.41.0-beta.1...v1.41.0-beta.2) (2023-04-13)


### 馃悰 Bug Fixes

* not indexed repo causing runtime error ([#1093](https://github.com/open-sauced/insights/issues/1093)) ([b721771](https://github.com/open-sauced/insights/commit/b721771f508ebed46464150459abe277ef4f09e5))

## [1.41.0-beta.1](https://github.com/open-sauced/insights/compare/v1.40.0...v1.41.0-beta.1) (2023-04-13)


### 馃崟 Features

* implement highlight reaction features ([#1085](https://github.com/open-sauced/insights/issues/1085)) ([3295b00](https://github.com/open-sauced/insights/commit/3295b00efef4ae0e565f8c9829ffb196f3baccc6))

## [1.40.0](https://github.com/open-sauced/insights/compare/v1.39.0...v1.40.0) (2023-04-07)


Expand Down
Expand Up @@ -15,15 +15,14 @@ import { FiEdit, FiLinkedin, FiTwitter } from "react-icons/fi";
import { BsLink45Deg } from "react-icons/bs";
import { FaUserPlus } from "react-icons/fa";
import { GrFlag } from "react-icons/gr";
import { useSWRConfig } from "swr";
import Emoji from "react-emoji-render";

import useSupabaseAuth from "lib/hooks/useSupabaseAuth";
import GhOpenGraphImg from "../GhOpenGraphImg/gh-open-graph-img";
import {
Dialog,
DialogContent,
DialogHeader,
DialogTrigger,
DialogTitle,
DialogDescription,
DialogCloseButton
Expand All @@ -45,6 +44,10 @@ import {
import { deleteHighlight } from "lib/hooks/deleteHighlight";
import { useToast } from "lib/hooks/useToast";
import useFollowUser from "lib/hooks/useFollowUser";
import useFetchAllEmojis from "lib/hooks/useFetchAllEmojis";
import useHighlightReactions from "lib/hooks/useHighlightReactions";
import useUserHighlightReactions from "lib/hooks/useUserHighlightReactions";
import { truncateString } from "lib/utils/truncate-string";

interface ContributorHighlightCardProps {
title?: string;
Expand All @@ -53,6 +56,7 @@ interface ContributorHighlightCardProps {
user: string;
id: string;
refreshCallBack?: () => void;
emojis: DbEmojis[];
}

const ContributorHighlightCard = ({
Expand All @@ -61,7 +65,8 @@ const ContributorHighlightCard = ({
prLink,
user,
id,
refreshCallBack
refreshCallBack,
emojis
}: ContributorHighlightCardProps) => {
const { toast } = useToast();
const twitterTweet = `${title || "Open Source Highlight"} - OpenSauced from ${user}`;
Expand All @@ -79,6 +84,9 @@ const ContributorHighlightCard = ({

const { follow, unFollow, isError } = useFollowUser(user);

const { data: reactions, mutate } = useHighlightReactions(id);
const { data: userReaction, deleteReaction, addReaction } = useUserHighlightReactions(id);

useEffect(() => {
if (!openEdit) {
setTimeout(() => {
Expand All @@ -87,6 +95,25 @@ const ContributorHighlightCard = ({
}
}, [openEdit]);

const isUserReaction = (id: string) => {
const matches = userReaction.find((reaction) => reaction.emoji_id === id);
return !matches ? false : true;
};

const getEmojiNameById = (id: string) => {
return emojis && emojis.length > 0 ? emojis.filter((emoji) => emoji.id === id)[0].name : "";
};

const handleUpdateReaction = async (id: string) => {
if (isUserReaction(id)) {
// making sure the delete is triggered before the data is refetched
await deleteReaction(id);
mutate();
} else {
await addReaction(id);
mutate();
}
};
const handleCopyToClipboard = async (content: string) => {
const url = new URL(content).toString();
try {
Expand Down Expand Up @@ -164,29 +191,17 @@ const ContributorHighlightCard = ({
}, [highlight]);

return (
<article className="inline-flex flex-col max-w-xs md:max-w-[40rem] flex-1 gap-3 lg:gap-6">
<article className="flex flex-col md:max-w-[40rem] flex-1 gap-3 lg:gap-6">
<div>
<div className="flex items-center justify-between">
{title && (
<Title className="!text-sm lg:!text-xl !text-light-slate-12" level={4}>
{title}
</Title>
)}
<div className="flex items-center justify-between w-full">
<div className="flex items-center justify-between gap-1 pr-2">
{title && (
<Title className="!text-sm break-words lg:!text-xl !text-light-slate-12" level={4}>
{title}
</Title>
)}
</div>
<div className="flex items-center gap-3 ml-auto lg:gap-3">
<DropdownMenu>
<DropdownMenuTrigger className="py-2 px-2 hidden rounded-full data-[state=open]:bg-light-slate-7">
<HiOutlineEmojiHappy size={20} />
</DropdownMenuTrigger>
<DropdownMenuContent className="flex flex-row gap-2 rounded-3xl" side="left">
<DropdownMenuItem className="rounded-full">馃憤</DropdownMenuItem>
<DropdownMenuItem className="rounded-full">馃憥</DropdownMenuItem>
<DropdownMenuItem className="rounded-full">馃崟</DropdownMenuItem>
<DropdownMenuItem className="rounded-full">馃槃</DropdownMenuItem>
<DropdownMenuItem className="rounded-full">鉂わ笍</DropdownMenuItem>
<DropdownMenuItem className="rounded-full">馃殌</DropdownMenuItem>
<DropdownMenuItem className="rounded-full">馃憖</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
<DropdownMenu>
<DropdownMenuTrigger className=" py-2 px-2 rounded-full data-[state=open]:bg-light-slate-7">
<TfiMoreAlt size={24} />
Expand Down Expand Up @@ -291,6 +306,47 @@ const ContributorHighlightCard = ({
{/* Generated OG card section */}
<GhOpenGraphImg githubLink={prLink} />

<div className="flex flex-wrap items-center gap-1">
<DropdownMenu>
<DropdownMenuTrigger className="p-1 rounded-full data-[state=open]:bg-light-slate-7">
<HiOutlineEmojiHappy className="w-5 h-5" />
</DropdownMenuTrigger>

<DropdownMenuContent className="flex flex-row gap-1 rounded-3xl" side="right">
{emojis &&
emojis.length > 0 &&
emojis.map(({ id, name }) => (
<DropdownMenuItem
onClick={async () => (sessionToken ? handleUpdateReaction(id) : await signIn({ provider: "github" }))}
key={id}
className="rounded-full !px-2 !cursor-pointer"
>
<Emoji text={`:${name}:`} />
</DropdownMenuItem>
))}
</DropdownMenuContent>
</DropdownMenu>
{reactions &&
emojis &&
reactions.length > 0 &&
reactions.map(({ emoji_id, reaction_count }) => (
<div
className={`px-1 py-0 md:py-0.5 hover:bg-light-slate-6 transition md:px-1.5 shrink-0 border flex items-center justify-center rounded-full cursor-pointer ${
isUserReaction(emoji_id) && "bg-light-slate-6"
}`}
onClick={async () =>
sessionToken ? handleUpdateReaction(emoji_id) : await signIn({ provider: "github" })
}
key={emoji_id}
>
<Emoji
className="text-xs md:text-sm text-light-slate-10"
text={`:${getEmojiNameById(emoji_id)}: ${reaction_count}`}
/>
</div>
))}
</div>

<Dialog open={openEdit} onOpenChange={setOpenEdit}>
<DialogContent>
<DialogHeader>
Expand Down
2 changes: 1 addition & 1 deletion components/molecules/RepoRow/repo-row.tsx
Expand Up @@ -98,7 +98,7 @@ const RepoRow = ({ repo, topic, userPage, selected, handleOnSelectRepo }: RepoPr
const spamPrsPercentage = getPrsSpam(totalPrs, spamPrsCount || 0);
const prVelocityInDays = getRelativeDays(prVelocityCount || 0);
const contributorData = getPullRequestsContributors(repositoryPullRequests);

const days = getPullRequestsToDays(repositoryPullRequests);
const last30days = [
{
Expand Down
Expand Up @@ -73,7 +73,7 @@ const ContributorProfilePage = ({
};
});

const { sessionToken, user: loggedInUser, signIn } = useSupabaseAuth();
const { user: loggedInUser, signIn } = useSupabaseAuth();

const { chart } = useTopicContributorCommits(githubName, "*", repositories);
const prsMergedPercentage = getPercent(prTotal, prMerged || 0);
Expand Down
@@ -1,3 +1,4 @@
import Link from "next/link";
import { useEffect, useRef, useState } from "react";
import { useRouter } from "next/router";

Expand All @@ -15,7 +16,8 @@ import { useFetchUserHighlights } from "lib/hooks/useFetchUserHighlights";
import Button from "components/atoms/Button/button";
import useSupabaseAuth from "lib/hooks/useSupabaseAuth";
import uppercaseFirst from "lib/utils/uppercase-first";
import Link from "next/link";
import useFetchAllEmojis from "lib/hooks/useFetchAllEmojis";

import PaginationResults from "components/molecules/PaginationResults/pagination-result";
import Pagination from "components/molecules/Pagination/pagination";

Expand Down Expand Up @@ -48,6 +50,8 @@ const ContributorProfileTab = ({
const { user } = useSupabaseAuth();

const { data: highlights, isError, isLoading, mutate, meta, setPage } = useFetchUserHighlights(login || "");
const { data: emojis } = useFetchAllEmojis();

const [inputVisible, setInputVisible] = useState(false);
const pathnameRef = useRef<string | null>();

Expand All @@ -72,7 +76,7 @@ const ContributorProfileTab = ({

return (
<Tabs defaultValue={uppercaseFirst(currentPathname as string)} className="">
<TabsList className="w-full border-b justify-start">
<TabsList className="justify-start w-full border-b">
<TabsTrigger
className="data-[state=active]:border-sauced-orange data-[state=active]:border-b-2 text-2xl"
value="Highlights"
Expand Down Expand Up @@ -105,7 +109,7 @@ const ContributorProfileTab = ({
<HighlightInputForm refreshCallback={mutate} />
</div>
)}
<div className="mt-8 flex flex-col gap-8">
<div className="flex flex-col gap-8 mt-8">
{/* <HightlightEmptyState /> */}

{isError && <>An error occured</>}
Expand All @@ -117,11 +121,12 @@ const ContributorProfileTab = ({
<div>
{/* eslint-disable-next-line camelcase */}
{highlights.map(({ id, title, highlight, url, created_at }) => (
<div className="flex gap-2 flex-col lg:flex-row lg:gap-7" key={id}>
<div className="flex flex-col gap-2 lg:flex-row lg:gap-7" key={id}>
<Link href={`/feed/${id}`}>
<p className="text-light-slate-10 text-sm">{getFormattedDate(created_at)}</p>
<p className="text-sm text-light-slate-10">{getFormattedDate(created_at)}</p>
</Link>
<ContributorHighlightCard
emojis={emojis}
id={id}
user={login || ""}
title={title}
Expand Down Expand Up @@ -152,7 +157,7 @@ const ContributorProfileTab = ({
)}
</div>
) : (
<div className="flex justify-center rounded-xl border border-dashed border-light-slate-8 px-6 lg:px-32 py-20 items-center">
<div className="flex items-center justify-center px-6 py-20 border border-dashed rounded-xl border-light-slate-8 lg:px-32">
<div className="text-center">
{user?.user_metadata.user_name === login ? (
<>
Expand Down Expand Up @@ -183,46 +188,46 @@ const ContributorProfileTab = ({

<TabsContent value="Contributions">
<div className="mt-4">
<div className="bg-white mt-4 rounded-2xl border p-4 md:p-6">
<div className=" flex flex-col lg:flex-row gap-2 md:gap-12 lg:gap-16 justify-between">
<div className="p-4 mt-4 bg-white border rounded-2xl md:p-6">
<div className="flex flex-col justify-between gap-2 lg:flex-row md:gap-12 lg:gap-16">
<div>
<span className="text-xs text-light-slate-11">PRs opened</span>
{openPrs ? (
<div className="flex lg:justify-center md:pr-8 mt-1">
<div className="flex mt-1 lg:justify-center md:pr-8">
<Text className="!text-lg md:!text-xl lg:!text-2xl !text-black !leading-none">{openPrs} PRs</Text>
</div>
) : (
<div className="flex justify-center items-end mt-1"> - </div>
<div className="flex items-end justify-center mt-1"> - </div>
)}
</div>
<div>
<span className="text-xs text-light-slate-11">Avg PRs velocity</span>
{prVelocity ? (
<div className="flex gap-2 lg:justify-center items-center">
<div className="flex items-center gap-2 lg:justify-center">
<Text className="!text-lg md:!text-xl lg:!text-2xl !text-black !leading-none">
{getRelativeDays(prVelocity)}
</Text>

<Pill color="purple" text={`${prsMergedPercentage}%`} />
</div>
) : (
<div className="flex justify-center items-end mt-1"> - </div>
<div className="flex items-end justify-center mt-1"> - </div>
)}
</div>
<div>
<span className="text-xs text-light-slate-11">Contributed Repos</span>
{recentContributionCount ? (
<div className="flex lg:justify-center mt-1">
<div className="flex mt-1 lg:justify-center">
<Text className="!text-lg md:!text-xl lg:!text-2xl !text-black !leading-none">
{`${recentContributionCount} Repo${recentContributionCount > 1 ? "s" : ""}`}
</Text>
</div>
) : (
<div className="flex justify-center items-end mt-1"> - </div>
<div className="flex items-end justify-center mt-1"> - </div>
)}
</div>
</div>
<div className="mt-10 h-32">
<div className="h-32 mt-10">
<CardLineChart lineChartOption={chart} className="!h-32" />
</div>
<div>
Expand All @@ -232,7 +237,7 @@ const ContributorProfileTab = ({
<div className="mt-6">
<PullRequestTable limit={15} contributor={githubName} topic={"*"} repositories={undefined} />
</div>
<div className="mt-8 text-light-slate-9 text-sm">
<div className="mt-8 text-sm text-light-slate-9">
<p>The data for these contributions is from publicly available open source projects on GitHub.</p>
</div>
</div>
Expand Down
9 changes: 3 additions & 6 deletions components/organisms/RepositoriesTable/repositories-table.tsx
Expand Up @@ -75,11 +75,10 @@ const RepositoriesTable = ({
}: RepositoriesTableProps): JSX.Element => {
const isLoadedWithRepos = !loading && !error && Array.isArray(listOfRepositories) && listOfRepositories.length > 0;
const isFilteredRepoNotIndexed =
Array.isArray(repo) && !loading && !error && Array.isArray(listOfRepositories) && listOfRepositories.length === 0;
const [repoOwner, repoName] = repo && Array.isArray(repo) ? repo : [];
Array.isArray(repo) && !loading && !error && Array.isArray(listOfRepositories) && listOfRepositories.length === 0;

return (
<section className="flex flex-col">
<section className="flex flex-col">
{loading && <SkeletonWrapper height={50} count={10} radius={4} classNames="px-6 mt-2" />}
{error && <>An error has occured...</>}

Expand All @@ -96,9 +95,7 @@ const RepositoriesTable = ({
// eslint-disable-next-line
repo={{
id: "",
full_name: repoName as string,
// eslint-disable-next-line camelcase
owner_avatar: getAvatarByUsername(repoOwner as string)
full_name: repo.join("/") as string
}}
userPage={user}
handleOnSelectRepo={handleOnSelectRepo}
Expand Down
22 changes: 22 additions & 0 deletions lib/hooks/useFetchAllEmojis.ts
@@ -0,0 +1,22 @@
import publicApiFetcher from "lib/utils/public-api-fetcher";
import useSWR, { Fetcher } from "swr";

interface PaginatedEmojiResponse {
data: DbEmojis[];
meta: Meta;
}
const useFetchAllEmojis = () => {
const { data, error, mutate } = useSWR<PaginatedEmojiResponse, Error>(
"emojis",
publicApiFetcher as Fetcher<PaginatedEmojiResponse, Error>
);

return {
data: data?.data ?? [],
isError: !!error,
isLoading: !error && !data,
mutate
};
};

export default useFetchAllEmojis;
2 changes: 1 addition & 1 deletion lib/hooks/useFilterPrefetch.ts
Expand Up @@ -45,4 +45,4 @@ const useFilterPrefetch = () => {
return { filterValues };
};

export default useFilterPrefetch;
export default useFilterPrefetch;
1 change: 0 additions & 1 deletion lib/hooks/useFollowUser.ts
@@ -1,5 +1,4 @@
import publicApiFetcher from "lib/utils/public-api-fetcher";
import { useEffect, useState } from "react";
import useSWR, { Fetcher } from "swr";
import useSupabaseAuth from "./useSupabaseAuth";

Expand Down

0 comments on commit 1b2e9c1

Please sign in to comment.