From 4c287221a2c5c475b6611d2823cb4788a98787b5 Mon Sep 17 00:00:00 2001 From: Divyansh Singh Date: Tue, 11 Jul 2023 04:59:18 +0530 Subject: [PATCH] feat: react/unreact on highlights (#200) * feat: react/unreact on highlights * fix: lint fixes * fix: manifest default key error * rebase --------- Co-authored-by: Anush008 --- src/popup/components/HighlightSlide.tsx | 142 ++++++++++++++++++++---- src/popup/pages/home.tsx | 1 - src/popup/pages/settings.tsx | 3 - src/utils/fetchOpenSaucedApiData.ts | 19 ++++ tailwind.config.js | 1 + vite.config.ts | 2 +- 6 files changed, 141 insertions(+), 27 deletions(-) diff --git a/src/popup/components/HighlightSlide.tsx b/src/popup/components/HighlightSlide.tsx index fb13ef2..a08b87d 100644 --- a/src/popup/components/HighlightSlide.tsx +++ b/src/popup/components/HighlightSlide.tsx @@ -1,5 +1,6 @@ import { useEffect, useState } from "react"; -import { getHighlightReactions } from "../../utils/fetchOpenSaucedApiData"; +import { getHighlightReactions, getUserHighlightReactions, reactOnHighlight, removeReactionOnHighlight } from "../../utils/fetchOpenSaucedApiData"; +import { getAuthToken } from "../../utils/checkAuthentication"; interface HighlightSlideProps { highlight: { @@ -12,26 +13,39 @@ interface HighlightSlideProps { emojis: Record[]; } +interface HighlightReaction { + url: string; + reaction_count: string; + reactedByUser: boolean; + emojiId: string; +} + export const HighlightSlide = ({ highlight, emojis }: HighlightSlideProps) => { - const [highlightReactions, setHighlightReactions] = useState[]>([]); + const [highlightReactions, setHighlightReactions] = useState([]); + const [reactingDivOpen, setReactingDivOpen] = useState(false); - useEffect(() => { - async function fetchHighlightReactions () { - const highlightReactionData = await getHighlightReactions(highlight.id); + async function fetchHighlightReactions () { + const highlightReactionData = await getHighlightReactions(highlight.id); + const userHighlightReactionData = await getUserHighlightReactions( await getAuthToken(), highlight.id); + + const highlightReactionsWithEmojiUrls = emojis.filter(emoji => highlightReactionData.some(highlightReaction => highlightReaction.emoji_id === emoji.id)).map(emoji => { + const highlightReaction = highlightReactionData.find(highlightReaction => highlightReaction.emoji_id === emoji.id)!; - const highlightReactionsWithEmojiUrls = emojis.filter(emoji => highlightReactionData.some(highlightReaction => highlightReaction.emoji_id === emoji.id)).map(emoji => { - const highlightReaction = highlightReactionData.find(highlightReaction => highlightReaction.emoji_id === emoji.id)!; + const reactedByUser = userHighlightReactionData.some(userHighlightReaction => userHighlightReaction.emoji_id === emoji.id); - return { - url: emoji.url, - reaction_count: highlightReaction.reaction_count, - highlight_url: highlight.url, - }; - }); + return { + url: emoji.url, + reaction_count: highlightReaction.reaction_count, + reactedByUser, + emojiId: emoji.id, + } as HighlightReaction; + }); - setHighlightReactions(highlightReactionsWithEmojiUrls); - } + setHighlightReactions(highlightReactionsWithEmojiUrls); + } + + useEffect(() => { void fetchHighlightReactions(); }, []); @@ -41,6 +55,17 @@ export const HighlightSlide = ({ highlight, emojis }: HighlightSlideProps) => { .join("/"); const openGraphUrl = `https://opengraph.githubassets.com/1/${openGraphSearchParameter}`; + const addReactionToHighlight = async (highlightId: string, emojiId: string) => { + await reactOnHighlight(await getAuthToken(), highlightId, emojiId); + setReactingDivOpen(false); + await fetchHighlightReactions(); + }; + + const removeReactionFromHighlight = async (highlightId: string, emojiId: string) => { + await removeReactionOnHighlight(await getAuthToken(), highlightId, emojiId); + await fetchHighlightReactions(); + }; + return (
{/* fixed height, content ellipsis */} @@ -92,17 +117,94 @@ export const HighlightSlide = ({ highlight, emojis }: HighlightSlideProps) => { />
+
+ +
+ + + + { - highlightReactions.length > 0 + highlightReactions.length > 0 && !reactingDivOpen ? ( highlightReactions.map(highlightReaction => (
{ + await removeReactionFromHighlight(highlight.id, highlightReaction.emojiId); + } + : async () => { + await addReactionToHighlight(highlight.id, highlightReaction.emojiId); + } + } + onKeyDown={ + highlightReaction.reactedByUser + ? async () => { + await removeReactionFromHighlight(highlight.id, highlightReaction.emojiId); + } + : async () => { + await addReactionToHighlight(highlight.id, highlightReaction.emojiId); + } + } > Emoji @@ -111,11 +213,7 @@ export const HighlightSlide = ({ highlight, emojis }: HighlightSlideProps) => {
))) - : ( - - No reactions yet. - - ) + : null }
diff --git a/src/popup/pages/home.tsx b/src/popup/pages/home.tsx index 1d344ce..f31c103 100644 --- a/src/popup/pages/home.tsx +++ b/src/popup/pages/home.tsx @@ -160,7 +160,6 @@ const Home = () => { return; } - console.log(inputFields); inputFields[0].value = data.name; inputFields[1].value = data.description; } diff --git a/src/popup/pages/settings.tsx b/src/popup/pages/settings.tsx index 75ea2b8..8d6606d 100644 --- a/src/popup/pages/settings.tsx +++ b/src/popup/pages/settings.tsx @@ -1,6 +1,3 @@ -import { FaChevronLeft } from "react-icons/fa"; -import OpenSaucedLogo from "../../assets/opensauced-logo.svg"; -import { goBack } from "react-chrome-extension-router"; import Toggle from "../components/ToggleSwitch"; import AIPRDescription from "./aiprdescription"; import { useEffect, useState } from "react"; diff --git a/src/utils/fetchOpenSaucedApiData.ts b/src/utils/fetchOpenSaucedApiData.ts index 03bf642..f71afc1 100644 --- a/src/utils/fetchOpenSaucedApiData.ts +++ b/src/utils/fetchOpenSaucedApiData.ts @@ -217,8 +217,27 @@ export const getHighlightReactions = async (highlightId: string):Promise[]> => { + const response = await fetch(`${OPEN_SAUCED_USER_HIGHLIGHTS_ENDPOINT}/${highlightId}/reactions`, { + headers: { Authorization: `Bearer ${userToken}` }, + method: "GET", + }); + + return response.json(); +}; + export const getEmojis = async ():Promise => { const response = await fetch(`${OPEN_SAUCED_EMOJIS_ENDPOINT}`, { method: "GET" }); return response.json(); }; + +export const reactOnHighlight = async (userToken: string, highlightId: string, emojiId: string) => fetch(`${OPEN_SAUCED_USER_HIGHLIGHTS_ENDPOINT}/${highlightId}/reactions/${emojiId}`, { + headers: { Authorization: `Bearer ${userToken}` }, + method: "POST", +}); + +export const removeReactionOnHighlight = async (userToken: string, highlightId: string, emojiId: string) => fetch(`${OPEN_SAUCED_USER_HIGHLIGHTS_ENDPOINT}/${highlightId}/reactions/${emojiId}`, { + headers: { Authorization: `Bearer ${userToken}` }, + method: "DELETE", +}); diff --git a/tailwind.config.js b/tailwind.config.js index b177619..7e13676 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -7,6 +7,7 @@ module.exports = { extend: { colors: { orange: "hsla(19, 100%, 50%, 1)", + lightOrange: "hsla(19, 100%, 50%, 0.5)" }, boxShadow: { button: "0 0 0.2rem 0.2rem rgb(245, 131, 106, 0.2)", diff --git a/vite.config.ts b/vite.config.ts index 32e2f53..7a8fd4a 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -1,7 +1,7 @@ import { defineConfig } from "vite"; import react from "@vitejs/plugin-react"; import { crx } from "@crxjs/vite-plugin"; -import * as manifest from "./manifest.json"; +import manifest from "./manifest.json" assert { type: "json" }; // https://vitejs.dev/config/ export default defineConfig({