diff --git a/CHANGELOG.md b/CHANGELOG.md index 76a86ed45a..037989e0c7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,40 @@ > All notable changes to this project will be documented in this file +## [1.56.0](https://github.com/open-sauced/insights/compare/v1.55.0...v1.56.0) (2023-07-17) + + +### πŸ› Bug Fixes + +* add hidden form for Netlify forms submission ([#1351](https://github.com/open-sauced/insights/issues/1351)) ([8075012](https://github.com/open-sauced/insights/commit/80750124072a742443a89716f9b2e956f7bdcb25)) +* ensure font color of selected interests pill changed is white ([#1342](https://github.com/open-sauced/insights/issues/1342)) ([b778f11](https://github.com/open-sauced/insights/commit/b778f11484d02b4d159fe3cd22f43de4a5c28196)) +* improve loading performance of individual highlight ([#1349](https://github.com/open-sauced/insights/issues/1349)) ([9e193fe](https://github.com/open-sauced/insights/commit/9e193feae32739894051ec9d3236826cb00a1c88)) +* prevent concurrent user profile update requests ([#1372](https://github.com/open-sauced/insights/issues/1372)) ([b23b9df](https://github.com/open-sauced/insights/commit/b23b9df076596b7d5163ef9f8d7bc7f28ecde92a)) + + +### 🎨 Styles + +* text inputs colors were not consistent in the user settings page ([#1360](https://github.com/open-sauced/insights/issues/1360)) ([edae9c4](https://github.com/open-sauced/insights/commit/edae9c4a26bbc21921422356c623f2a8c0ca0939)) + + +### πŸ• Features + +* add force login component to design system ([#1330](https://github.com/open-sauced/insights/issues/1330)) ([9d68ffc](https://github.com/open-sauced/insights/commit/9d68ffcef1bbd2f17f05492d1b4e9d4ce4263de4)) +* add top contributors panel to feeds page ([#1347](https://github.com/open-sauced/insights/issues/1347)) ([5b58dd5](https://github.com/open-sauced/insights/commit/5b58dd532ff495fa921053ee1bb48eef2544d678)) +* added new topics to the list ([#1357](https://github.com/open-sauced/insights/issues/1357)) ([33f03bb](https://github.com/open-sauced/insights/commit/33f03bb53b82e8bb18e49c7e5ccba80c77ab982d)) +* change position of visibility action component ([#1331](https://github.com/open-sauced/insights/issues/1331)) ([f3f615c](https://github.com/open-sauced/insights/commit/f3f615caf3b8a69943d6b1443ac0b35075501b4b)) +* changed the last commit date icon with a calender ([#1350](https://github.com/open-sauced/insights/issues/1350)) ([2ae9d53](https://github.com/open-sauced/insights/commit/2ae9d5330e9231d108a9a20b458aed5398c7d24c)) +* implement featured highlights list ([#1337](https://github.com/open-sauced/insights/issues/1337)) ([ed32594](https://github.com/open-sauced/insights/commit/ed32594c64dc616e57e7b9fbea299ba4584bdb68)) +* implement newsletter submission functionality ([#1332](https://github.com/open-sauced/insights/issues/1332)) ([d996ac7](https://github.com/open-sauced/insights/commit/d996ac714fa2cf6394416fcb542c278634edc394)) +* upgrade to Next 13.4, Supabase helper libs to 0.7.x ([#1301](https://github.com/open-sauced/insights/issues/1301)) ([26876c2](https://github.com/open-sauced/insights/commit/26876c260546815102ac5584c0579e12b1323361)) + +## [1.56.0-beta.12](https://github.com/open-sauced/insights/compare/v1.56.0-beta.11...v1.56.0-beta.12) (2023-07-17) + + +### πŸ• Features + +* add top contributors panel to feeds page ([#1347](https://github.com/open-sauced/insights/issues/1347)) ([5b58dd5](https://github.com/open-sauced/insights/commit/5b58dd532ff495fa921053ee1bb48eef2544d678)) + ## [1.56.0-beta.11](https://github.com/open-sauced/insights/compare/v1.56.0-beta.10...v1.56.0-beta.11) (2023-07-17) diff --git a/components/atoms/TopContributorCard/top-contributor-card.tsx b/components/atoms/TopContributorCard/top-contributor-card.tsx new file mode 100644 index 0000000000..d6fded5a88 --- /dev/null +++ b/components/atoms/TopContributorCard/top-contributor-card.tsx @@ -0,0 +1,79 @@ +import React, { useEffect, useState } from "react"; + +import Link from "next/link"; +import { useRouter } from "next/router"; +import { getAvatarByUsername } from "lib/utils/github"; +import useFollowUser from "lib/hooks/useFollowUser"; +import useSupabaseAuth from "lib/hooks/useSupabaseAuth"; + +import Avatar from "../Avatar/avatar"; +import Button from "../Button/button"; + +export interface TopContributorCardProps { + login: string; +} + +const TopContributorCard = ({ login }: TopContributorCardProps) => { + const router = useRouter(); + const currentPath = router.asPath; + + const { isError: notFollowing, follow, unFollow } = useFollowUser(login); + const [host, setHost] = useState(""); + const { sessionToken, signIn } = useSupabaseAuth(); + + const handleFollowContributor = async () => { + try { + if (notFollowing) { + await follow(); + return; + } + await unFollow(); + } catch (error) { + console.log(error); + } + }; + + useEffect(() => { + if (typeof window !== "undefined") { + setHost(window.location.origin as string); + } + }, []); + + return ( +
+ +
+ +

{login}

+
+ + {sessionToken && !notFollowing ? ( + + ) : ( + + )} +
+ ); +}; + +export default TopContributorCard; diff --git a/components/atoms/TopUserCard/top-user-card.tsx b/components/atoms/TopUserCard/top-user-card.tsx deleted file mode 100644 index 548a6a602f..0000000000 --- a/components/atoms/TopUserCard/top-user-card.tsx +++ /dev/null @@ -1,36 +0,0 @@ -import React from "react"; -import { getAvatarByUsername } from "lib/utils/github"; -import Avatar from "../Avatar/avatar"; -import Button from "../Button/button"; - -export interface TopUserCardProps { - clasName?: string; - following: boolean; - username: string; -} -/** - * - * additional props to handle follow button click will be added in future versions - */ - -const TopUserCard = ({ username, following }: TopUserCardProps) => { - return ( -
-
- -

{username}

-
- {following ? ( - - ) : ( - - )} -
- ); -}; - -export default TopUserCard; diff --git a/components/molecules/TopContributorsPanel/top-contributors-panel.tsx b/components/molecules/TopContributorsPanel/top-contributors-panel.tsx new file mode 100644 index 0000000000..bc3e8df227 --- /dev/null +++ b/components/molecules/TopContributorsPanel/top-contributors-panel.tsx @@ -0,0 +1,32 @@ +import React from "react"; +import TopContributorCard from "components/atoms/TopContributorCard/top-contributor-card"; +import { useFetchTopContributors } from "lib/hooks/useFetchTopContributors"; +import SkeletonWrapper from "components/atoms/SkeletonLoader/skeleton-wrapper"; + +interface TopContributorsPanelProps { + loggedInUserLogin: string; +} +const TopContributorsPanel = ({ loggedInUserLogin }: TopContributorsPanelProps) => { + const { data, isLoading } = useFetchTopContributors(); + + const topContributorsWithoutLoggedInUser = data ? data.filter((user) => user.login !== loggedInUserLogin) : []; + const top3Contributors = topContributorsWithoutLoggedInUser.slice(0, 3).map((user) => user.login); + + return ( +
+

Top Contributors

+ + {isLoading && + Array.from({ length: 3 }).map((_, i) => ( +
+ +
+ ))} + {top3Contributors.map((login, i) => ( + + ))} +
+ ); +}; + +export default TopContributorsPanel; diff --git a/components/molecules/TopUsersPanel/top-user-panel.tsx b/components/molecules/TopUsersPanel/top-user-panel.tsx deleted file mode 100644 index 77d647b813..0000000000 --- a/components/molecules/TopUsersPanel/top-user-panel.tsx +++ /dev/null @@ -1,18 +0,0 @@ -import React from "react"; -import TopUserCard, { TopUserCardProps } from "components/atoms/TopUserCard/top-user-card"; - -interface TopUsersPanelProps { - users: TopUserCardProps[]; -} -const TopUsersPanel = ({ users }: TopUsersPanelProps) => { - return ( -
-

Top Users

- {users.map((user, i) => ( - - ))} -
- ); -}; - -export default TopUsersPanel; diff --git a/lib/hooks/useFetchTopContributors.ts b/lib/hooks/useFetchTopContributors.ts new file mode 100644 index 0000000000..454d4a2150 --- /dev/null +++ b/lib/hooks/useFetchTopContributors.ts @@ -0,0 +1,20 @@ +import useSWR, { Fetcher } from "swr"; +import publicApiFetcher from "lib/utils/public-api-fetcher"; + +type TopContributorsResponse = { login: string }[]; + +const useFetchTopContributors = () => { + const { data, error, mutate } = useSWR( + "users/top", + publicApiFetcher as Fetcher + ); + + return { + data: data ?? [], + isLoading: !error && !data, + isError: !!error, + mutate, + }; +}; + +export { useFetchTopContributors }; diff --git a/lib/hooks/useFollowUser.ts b/lib/hooks/useFollowUser.ts index d5395a951e..af2696dbec 100644 --- a/lib/hooks/useFollowUser.ts +++ b/lib/hooks/useFollowUser.ts @@ -1,4 +1,4 @@ -import useSWR, { Fetcher } from "swr"; +import useSWR, { Fetcher, useSWRConfig } from "swr"; import publicApiFetcher from "lib/utils/public-api-fetcher"; import useSupabaseAuth from "./useSupabaseAuth"; @@ -6,7 +6,8 @@ interface FollowUserResponse { data: DbFollowUser; } const useFollowUser = (username: string) => { - const { sessionToken } = useSupabaseAuth(); + const { sessionToken, user } = useSupabaseAuth(); + const { mutate: mutateGlobal } = useSWRConfig(); // adding this to mutate the global user data to update the users card status on follow/unfollow const { data, error, mutate } = useSWR( username ? `users/${username}/follow` : null, @@ -23,6 +24,7 @@ const useFollowUser = (username: string) => { if (req && req.ok) { mutate(); + mutateGlobal(`user/${user?.user_metadata?.username}`); } }; @@ -36,6 +38,7 @@ const useFollowUser = (username: string) => { if (req && req.ok) { mutate(); + mutateGlobal(`user/${user?.user_metadata?.username}`); } }; diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index 72cca5edbc..d7d928fcf1 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -1,12 +1,12 @@ { "name": "@open-sauced/insights", - "version": "1.56.0-beta.11", + "version": "1.56.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@open-sauced/insights", - "version": "1.56.0-beta.11", + "version": "1.56.0", "hasInstallScript": true, "license": "Apache 2.0", "dependencies": { diff --git a/package.json b/package.json index 2409fe0eac..a5cd054ff5 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "@open-sauced/insights", "description": "πŸ•The dashboard for open source discovery.", "keywords": [], - "version": "1.56.0-beta.11", + "version": "1.56.0", "author": "Brian Douglas ", "private": true, "license": "Apache 2.0", diff --git a/pages/feed/index.tsx b/pages/feed/index.tsx index 8b1e0dc2fe..85fe04d9ee 100644 --- a/pages/feed/index.tsx +++ b/pages/feed/index.tsx @@ -4,6 +4,7 @@ import Link from "next/link"; import formatDistanceToNowStrict from "date-fns/formatDistanceToNowStrict"; import clsx from "clsx"; +import TopContributorsPanel from "components/molecules/TopContributorsPanel/top-contributors-panel"; import useSupabaseAuth from "lib/hooks/useSupabaseAuth"; import { useFetchAllHighlights } from "lib/hooks/useFetchAllHighlights"; import { useFetchHighlightRepos } from "lib/hooks/useFetchHiglightRepos"; @@ -68,6 +69,7 @@ const Feeds: WithPageLayout = (props: HighlightSSRProps) => { const { data, mutate, setPage, isLoading, meta } = useFetchAllHighlights(selectedRepo); const { data: emojis } = useFetchAllEmojis(); + const { data: loggedInUser, isLoading: loggedInUserLoading } = useFetchUser(user?.user_metadata.user_name as string); const { followers_count, following_count, highlights_count } = loggedInUser || {}; @@ -121,7 +123,7 @@ const Feeds: WithPageLayout = (props: HighlightSSRProps) => { twitterCard="summary_large_image" />
-
+
{user && (
= (props: HighlightSSRProps) => { />
)} +
{singleHighlight && ( = (args) => ; +const TopContributorCardTemplate: StoryFn = (args) => ; -export const Following = TopUserCardTemplate.bind({}); -export const NotFollowing = TopUserCardTemplate.bind({}); +export const Following = TopContributorCardTemplate.bind({}); +export const NotFollowing = TopContributorCardTemplate.bind({}); Following.args = { - username: "diivi", - following: true, + login: "diivi", }; NotFollowing.args = { - username: "ogdev-01", - following: false, + login: "ogdev-01", }; diff --git a/stories/molecules/top-contributors-panel.stories.tsx b/stories/molecules/top-contributors-panel.stories.tsx new file mode 100644 index 0000000000..3f3445414c --- /dev/null +++ b/stories/molecules/top-contributors-panel.stories.tsx @@ -0,0 +1,16 @@ +import { Meta, StoryFn } from "@storybook/react"; +import TopContributorsPanel from "components/molecules/TopContributorsPanel/top-contributors-panel"; + +const storyConfig = { + title: "Design System/Molecules/TopContributorsPanel", +} as Meta; + +export default storyConfig; + +const TopContributorsPanelTemplate: StoryFn = (args) => ; + +export const Default = TopContributorsPanelTemplate.bind({}); + +Default.args = { + loggedInUserLogin: "ogdev-01", +}; diff --git a/stories/molecules/top-users-panel.stories.tsx b/stories/molecules/top-users-panel.stories.tsx deleted file mode 100644 index 29e7280c84..0000000000 --- a/stories/molecules/top-users-panel.stories.tsx +++ /dev/null @@ -1,23 +0,0 @@ -import { ComponentMeta, ComponentStory } from "@storybook/react"; -import TopUsersPanel from "components/molecules/TopUsersPanel/top-user-panel"; - -const storyConfig = { - title: "Design System/Molecules/TopUsersPanel", -} as ComponentMeta; - -export default storyConfig; - -const sampleUsers = [ - { username: "bdougie", following: true }, - { username: "diivi", following: false }, - { username: "ogdev-01", following: false }, - { username: "brandonroberts", following: true }, -]; - -const TopUsersPanelTemplate: ComponentStory = (args) => ; - -export const Default = TopUsersPanelTemplate.bind({}); - -Default.args = { - users: sampleUsers, -};