From fb48a3b35561389ed880eed6ac5aad8de6ffa3e9 Mon Sep 17 00:00:00 2001 From: Mehdi Sakout Date: Fri, 21 Oct 2022 17:24:46 +0100 Subject: [PATCH 01/96] migrate manifest to v3 --- public/manifest.json | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/public/manifest.json b/public/manifest.json index f584349c..b83f0713 100644 --- a/public/manifest.json +++ b/public/manifest.json @@ -1,17 +1,15 @@ { "name": "Hackertab.dev - developer news", "description": "All developer news in one tab", - "version": "1.14.1", - "manifest_version": 2, + "version": "1.14.2", + "manifest_version": 3, "chrome_url_overrides": { "newtab": "index.html" }, "background": { - "scripts": [ - "background.js" - ] + "service_worker": "background.js" }, - "permissions": [ + "host_permissions": [ "https://*.hackertab.dev/*" ], "icons": { @@ -19,11 +17,5 @@ "32": "/logos/logo32.png", "48": "/logos/logo48.png", "128": "/logos/logo128.png" - }, - "content_security_policy": "script-src 'self' object-src 'self'", - "applications": { - "gecko": { - "id": "{f8793186-e9da-4332-aa1e-dc3d9f7bb04c}" - } } } From 9232a90a0f887b6076ac8d2be2b3934994d06134 Mon Sep 17 00:00:00 2001 From: Mehdi Sakout Date: Fri, 21 Oct 2022 17:52:02 +0100 Subject: [PATCH 02/96] fix web build command --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index db989a0f..cbf55f8c 100644 --- a/package.json +++ b/package.json @@ -36,7 +36,7 @@ "proxy": "https://api.hackertab.dev/", "scripts": { "start": "craco start", - "web-build": "REACT_APP_WEB_BUILD=1 CI= react-scripts --max_old_space_size=3072 build", + "web-build": "craco --max_old_space_size=4096 build", "build": "./script/build.sh", "stores-build": "./script/stores_build.sh", "eject": "react-scripts eject" From 5ca65f8d6effd8e69a4e7f23011d8d16b31199cc Mon Sep 17 00:00:00 2001 From: Mehdi Sakout Date: Fri, 21 Oct 2022 17:52:18 +0100 Subject: [PATCH 03/96] fix uppercase issue --- yarn.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yarn.lock b/yarn.lock index d2911c9a..08d5d99e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3962,7 +3962,7 @@ console-browserify@^1.1.0: constants-browserify@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/Constants-browserify/-/Constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75" + resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75" integrity sha512-xFxOwqIzR/e1k1gLiWEophSCMqXcwVHIH7akf7b/vxcUeGunlj3hvZaaqxwHsTgn+IndtkQJgSztIDWeumWJDQ== content-disposition@0.5.4: From 513522be55539d38c282942d360cbf7871e5d72b Mon Sep 17 00:00:00 2001 From: Mehdi Sakout Date: Fri, 21 Oct 2022 17:52:52 +0100 Subject: [PATCH 04/96] add missing manifest attributes on the fly --- script/stores_build.sh | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/script/stores_build.sh b/script/stores_build.sh index caee7d36..39a70bd8 100755 --- a/script/stores_build.sh +++ b/script/stores_build.sh @@ -27,6 +27,12 @@ firefox_build() { export INLINE_RUNTIME_CHUNK=false export GENERATE_SOURCEMAP=false + echo 'add missing geeko id' + yarn global add json + json -I -f public/manifest.json -e 'this.applications={}' + json -I -f public/manifest.json -e 'this.applications.gecko={}' + json -I -f public/manifest.json -e 'this.applications.gecko.id="{f8793186-e9da-4332-aa1e-dc3d9f7bb04c}"' + yarn build mkdir -p dist @@ -35,7 +41,10 @@ firefox_build() { cd dist/ && zip -r ../firefox_extension.zip * -x "*.DS_Store" && cd .. echo 'zipping the source code for Firefox' - zip -r source_code.zip 'public/' 'script/' 'src' 'LICENSE' 'package.json' 'yarn.lock' 'README.md' 'craco.config.js' '.env' -x "*.DS_Store" + zip -r source_code.zip 'public/' 'script/' 'src' 'LICENSE' 'package.json' 'yarn.lock' 'README.md' 'craco.config.js' '.env' 'tsconfig.json' -x "*.DS_Store" + + echo "revert manifest changes" + git restore public/manifest.json } chrome_build firefox_build \ No newline at end of file From c4e9c4e42f0e601ff12bbf20ed894753265fdeb4 Mon Sep 17 00:00:00 2001 From: medyo Date: Sun, 23 Oct 2022 15:19:55 +0100 Subject: [PATCH 05/96] migrate the ads component to typescript --- src/components/CarbonAd.js | 80 ------------------- src/features/carbonAds/api/getAd.ts | 31 +++++++ .../carbonAds}/components/CarbonAd.css | 0 .../carbonAds/components/CarbonAd.tsx | 53 ++++++++++++ src/features/carbonAds/index.ts | 1 + src/features/carbonAds/types/index.ts | 9 +++ src/lib/axios.ts | 6 ++ src/lib/react-query.ts | 28 +++++++ src/utils/UrlUtils.ts | 7 ++ 9 files changed, 135 insertions(+), 80 deletions(-) delete mode 100644 src/components/CarbonAd.js create mode 100644 src/features/carbonAds/api/getAd.ts rename src/{ => features/carbonAds}/components/CarbonAd.css (100%) create mode 100644 src/features/carbonAds/components/CarbonAd.tsx create mode 100644 src/features/carbonAds/index.ts create mode 100644 src/features/carbonAds/types/index.ts create mode 100644 src/lib/axios.ts create mode 100644 src/lib/react-query.ts create mode 100644 src/utils/UrlUtils.ts diff --git a/src/components/CarbonAd.js b/src/components/CarbonAd.js deleted file mode 100644 index 76b6d61c..00000000 --- a/src/components/CarbonAd.js +++ /dev/null @@ -1,80 +0,0 @@ -import axios from 'axios' -import React, { useEffect, useState, useRef } from 'react' -import './CarbonAd.css' -import { getBaseApi } from '../utils/DataUtils' - -export default function CarbonAd() { - const [ad, setAd] = useState() - const cancelTokenSource = useRef() - - useEffect(() => { - cancelTokenSource.current = axios.CancelToken.source() - - const setup = async () => { - const userAgent = new URLSearchParams(navigator.userAgent).toString() - try { - const request = await axios.get(`${getBaseApi('')}/monetization/?useragent=${userAgent}`, { - cancelToken: cancelTokenSource.current.token, - }) - if (request.data) { - setAd(request.data.ads[0]) - } - } catch (_) {} - } - setup() - return () => { - cancelTokenSource.current.cancel() - } - }, []) - - const prependHTTP = (url) => { - url = decodeURIComponent(url) - if (!/^(?:f|ht)tps?\:\/\//.test(url)) { - url = 'https:' + url - } - return url - } - - return ( -
- {ad && ( - - )} -
- ) -} diff --git a/src/features/carbonAds/api/getAd.ts b/src/features/carbonAds/api/getAd.ts new file mode 100644 index 00000000..8d64d9d1 --- /dev/null +++ b/src/features/carbonAds/api/getAd.ts @@ -0,0 +1,31 @@ +import { useQuery } from '@tanstack/react-query'; +import { ExtractFnReturnType, QueryConfig } from 'src/lib/react-query'; +import { Ad } from "../types"; +import { axios } from 'src/lib/axios'; + +const getAd = async (): Promise => { + const userAgent = new URLSearchParams(navigator.userAgent).toString() + + return axios.get('/monetization/', { + params: { + useragent: userAgent + } + }).then(response => { + if (response.data?.ads?.length) { + return response.data.ads[0]; + } + }); +} + +type QueryFnType = typeof getAd; + +type UseGetAdOptions = { + config?: QueryConfig; +}; +export const useGetAd = ({ config }: UseGetAdOptions = {}) => { + return useQuery>({ + ...config, + queryKey: ['ad'], + queryFn: () => getAd(), + }); +} \ No newline at end of file diff --git a/src/components/CarbonAd.css b/src/features/carbonAds/components/CarbonAd.css similarity index 100% rename from src/components/CarbonAd.css rename to src/features/carbonAds/components/CarbonAd.css diff --git a/src/features/carbonAds/components/CarbonAd.tsx b/src/features/carbonAds/components/CarbonAd.tsx new file mode 100644 index 00000000..c2908855 --- /dev/null +++ b/src/features/carbonAds/components/CarbonAd.tsx @@ -0,0 +1,53 @@ +import './CarbonAd.css' +import { addHttpsProtocol } from 'src/utils/UrlUtils' +import { useGetAd } from '../api/getAd' +export default function CarbonAd() { + const { data: ad } = useGetAd() + + if (!ad) { + return null + } + + return ( +
+ {ad && ( + + )} +
+ ) +} diff --git a/src/features/carbonAds/index.ts b/src/features/carbonAds/index.ts new file mode 100644 index 00000000..5f97d5e7 --- /dev/null +++ b/src/features/carbonAds/index.ts @@ -0,0 +1 @@ +export * from "./components/CarbonAd"; \ No newline at end of file diff --git a/src/features/carbonAds/types/index.ts b/src/features/carbonAds/types/index.ts new file mode 100644 index 00000000..503d0dc8 --- /dev/null +++ b/src/features/carbonAds/types/index.ts @@ -0,0 +1,9 @@ +export type Ad = { + statlink: string, + company: string, + companyTagline: string, + smallImage: string, + backgroundColor: string, + description: string, + ad_via_link: string +} \ No newline at end of file diff --git a/src/lib/axios.ts b/src/lib/axios.ts new file mode 100644 index 00000000..af44a586 --- /dev/null +++ b/src/lib/axios.ts @@ -0,0 +1,6 @@ +import Axios from 'axios'; +import { getBaseApi } from 'src/utils/DataUtils' + +export const axios = Axios.create({ + baseURL: getBaseApi(null) +}); \ No newline at end of file diff --git a/src/lib/react-query.ts b/src/lib/react-query.ts new file mode 100644 index 00000000..89cd5c8a --- /dev/null +++ b/src/lib/react-query.ts @@ -0,0 +1,28 @@ +import { AxiosError } from 'axios'; +import { QueryClient, UseQueryOptions, UseMutationOptions, DefaultOptions } from '@tanstack/react-query'; +import { PromiseValue } from 'type-fest'; + +const queryConfig: DefaultOptions = { + queries: { + useErrorBoundary: true, + refetchOnWindowFocus: false, + retry: false, + }, +}; + +export const queryClient = new QueryClient({ defaultOptions: queryConfig }); + +export type ExtractFnReturnType any> = PromiseValue< + ReturnType +>; + +export type QueryConfig any> = Omit< + UseQueryOptions>, + 'queryKey' | 'queryFn' +>; + +export type MutationConfig any> = UseMutationOptions< + ExtractFnReturnType, + AxiosError, + Parameters[0] +>; diff --git a/src/utils/UrlUtils.ts b/src/utils/UrlUtils.ts new file mode 100644 index 00000000..6df0a2a6 --- /dev/null +++ b/src/utils/UrlUtils.ts @@ -0,0 +1,7 @@ +export const addHttpsProtocol = (url: string): string => { + url = decodeURIComponent(url) + if (!/^(?:f|ht)tps?:\/\//.test(url)) { + url = 'https:' + url + } + return url +} \ No newline at end of file From a98bf18824ce1b3a5dface32d78001c98fe43502 Mon Sep 17 00:00:00 2001 From: medyo Date: Sun, 23 Oct 2022 15:20:53 +0100 Subject: [PATCH 06/96] use single quote --- src/bookmark/BookmarksSidebar.js | 2 +- src/cards/ProductHuntCard.js | 10 +++++----- src/cards/RedditCard.js | 8 ++++---- src/components/CardComponent.js | 20 ++++++++++---------- src/components/CardItemWithActions.js | 6 +++--- src/components/Changelog.js | 2 +- src/components/Footer.js | 2 +- src/components/Header.js | 12 ++++++------ src/components/ListComponent.js | 2 +- 9 files changed, 32 insertions(+), 32 deletions(-) diff --git a/src/bookmark/BookmarksSidebar.js b/src/bookmark/BookmarksSidebar.js index d11baf73..d7d9891a 100644 --- a/src/bookmark/BookmarksSidebar.js +++ b/src/bookmark/BookmarksSidebar.js @@ -7,7 +7,7 @@ import { SiGithub, SiReddit, SiProducthunt, SiYcombinator } from 'react-icons/si import { ProSidebar, Menu, MenuItem, SubMenu, SidebarHeader, SidebarContent } from 'react-pro-sidebar'; import 'react-pro-sidebar/dist/css/styles.css'; import PreferencesContext from '../preferences/PreferencesContext'; -import CardLink from "../components/CardLink"; +import CardLink from '../components/CardLink' import { trackLinkUnBookmark, Attributes } from 'src/lib/analytics' const BookmarkItem = ({ item, appendRef = true }) => { diff --git a/src/cards/ProductHuntCard.js b/src/cards/ProductHuntCard.js index 6a36d0fe..466ccb64 100644 --- a/src/cards/ProductHuntCard.js +++ b/src/cards/ProductHuntCard.js @@ -1,11 +1,11 @@ import React, { useEffect, useState, useContext } from 'react' -import CardComponent from "../components/CardComponent"; -import ListComponent from "../components/ListComponent"; -import { BiCommentDetail } from "react-icons/bi" -import { VscTriangleUp } from 'react-icons/vsc'; +import CardComponent from '../components/CardComponent' +import ListComponent from '../components/ListComponent' +import { BiCommentDetail } from 'react-icons/bi' +import { VscTriangleUp } from 'react-icons/vsc' import PreferencesContext from '../preferences/PreferencesContext' -import CardLink from "../components/CardLink" +import CardLink from '../components/CardLink' import CardItemWithActions from '../components/CardItemWithActions' import producthuntApi from '../services/producthunt' import ProductHuntPlaceholder from '../components/ProductHuntPlaceholder' diff --git a/src/cards/RedditCard.js b/src/cards/RedditCard.js index 9f7c90c3..eb04efa1 100644 --- a/src/cards/RedditCard.js +++ b/src/cards/RedditCard.js @@ -1,11 +1,11 @@ import React, { useContext, useState, useEffect } from 'react' import { FaReddit } from 'react-icons/fa'; import redditApi from '../services/reddit' -import CardComponent from "../components/CardComponent" -import ListComponent from "../components/ListComponent" -import { format } from 'timeago.js'; +import CardComponent from '../components/CardComponent' +import ListComponent from '../components/ListComponent' +import { format } from 'timeago.js' import PreferencesContext from '../preferences/PreferencesContext' -import CardLink from "../components/CardLink" +import CardLink from '../components/CardLink' import { BiCommentDetail } from 'react-icons/bi'; import { MdAccessTime } from "react-icons/md" import { VscTriangleUp } from 'react-icons/vsc'; diff --git a/src/components/CardComponent.js b/src/components/CardComponent.js index 79d23355..bc8ef328 100644 --- a/src/components/CardComponent.js +++ b/src/components/CardComponent.js @@ -1,18 +1,18 @@ -import React, { useContext } from 'react'; -import { BsBoxArrowInUpRight } from 'react-icons/bs'; +import React, { useContext } from 'react' +import { BsBoxArrowInUpRight } from 'react-icons/bs' import { APP } from '../Constants' import PreferencesContext from '../preferences/PreferencesContext' function CardComponent({ icon, title, children, fullBlock, link }) { - const { openLinksNewTab } = useContext(PreferencesContext); + const { openLinksNewTab } = useContext(PreferencesContext) - const handleHeaderLinkClick = (e) => { - e.preventDefault(); - let url = `${link}?${APP.ref}`; - window.open(url, openLinksNewTab ? '_blank' : '_self'); - }; + const handleHeaderLinkClick = (e) => { + e.preventDefault() + let url = `${link}?${APP.ref}` + window.open(url, openLinksNewTab ? '_blank' : '_self') + } - return ( + return (
{icon} {title}{' '} @@ -27,4 +27,4 @@ function CardComponent({ icon, title, children, fullBlock, link }) { ) } -export default CardComponent; +export default CardComponent diff --git a/src/components/CardItemWithActions.js b/src/components/CardItemWithActions.js index 3bb9d712..91b34875 100644 --- a/src/components/CardItemWithActions.js +++ b/src/components/CardItemWithActions.js @@ -1,7 +1,7 @@ import React, { useState, useContext, useEffect } from 'react' import PreferencesContext from '../preferences/PreferencesContext' -import { BiBookmarkPlus } from "react-icons/bi"; -import { BiBookmarkMinus } from "react-icons/bi"; +import { BiBookmarkPlus } from 'react-icons/bi' +import { BiBookmarkMinus } from 'react-icons/bi' import { trackLinkBookmark, trackLinkUnBookmark, Attributes } from 'src/lib/analytics' export default function CardItemWithActions({ cardItem, item, index, source }) { @@ -24,7 +24,7 @@ export default function CardItemWithActions({ cardItem, item, index, source }) { [Attributes.TITLE]: item.title, [Attributes.LINK]: item.url, [Attributes.SOURCE]: source, - } + } if (isBookmarked) { trackLinkUnBookmark(analyticsAttrs) } else { diff --git a/src/components/Changelog.js b/src/components/Changelog.js index 4ff3949f..f9bc4e00 100644 --- a/src/components/Changelog.js +++ b/src/components/Changelog.js @@ -31,7 +31,7 @@ function Changelog({}) { useEffect(() => { try { - setLocalAppVersion(chrome.runtime.getManifest().version) + //setLocalAppVersion(chrome.runtime.getManifest().version) } catch (e) { setLocalAppVersion('') } diff --git a/src/components/Footer.js b/src/components/Footer.js index a72ed87c..c247a655 100644 --- a/src/components/Footer.js +++ b/src/components/Footer.js @@ -51,4 +51,4 @@ function Footer({ feedbackWidget }) { ) } -export default Footer; +export default Footer diff --git a/src/components/Header.js b/src/components/Header.js index 399454c7..ca45647e 100644 --- a/src/components/Header.js +++ b/src/components/Header.js @@ -1,9 +1,9 @@ import React, { useEffect, useRef, useState } from 'react' -import { BsFillGearFill } from "react-icons/bs" -import { CgTab } from 'react-icons/cg'; -import { BsFillBookmarksFill } from "react-icons/bs" -import { ReactComponent as HackertabLogo } from '../logo.svg'; -import UserTags from "./UserTags"; +import { BsFillGearFill } from 'react-icons/bs' +import { CgTab } from 'react-icons/cg' +import { BsFillBookmarksFill } from 'react-icons/bs' +import { ReactComponent as HackertabLogo } from '../logo.svg' +import UserTags from './UserTags' import { SUPPORTED_SEARCH_ENGINES } from '../Constants' import SettingsModal from '../settings/SettingsModal' import { BsMoon } from 'react-icons/bs' @@ -117,4 +117,4 @@ function Header({ state, dispatcher, showSideBar, setShowSideBar, showSettings, ) } -export default Header; \ No newline at end of file +export default Header diff --git a/src/components/ListComponent.js b/src/components/ListComponent.js index d998b0dd..b9faf818 100644 --- a/src/components/ListComponent.js +++ b/src/components/ListComponent.js @@ -1,5 +1,5 @@ import React, { useState, useEffect } from 'react' -import CarbonAd from './CarbonAd' +import CarbonAd from '../features/carbonAds/components/CarbonAd' import Placeholder from './Placeholder' function ListComponent({ fetchData, refresh, renderItem, withAds, placeholder = }) { From 10ab7e69a3e646ca83d759c8a2a0f431ea6f945f Mon Sep 17 00:00:00 2001 From: medyo Date: Sun, 23 Oct 2022 15:21:14 +0100 Subject: [PATCH 07/96] optimize export on prod env only --- craco.config.js | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/craco.config.js b/craco.config.js index b303aa96..db60c98f 100644 --- a/craco.config.js +++ b/craco.config.js @@ -1,5 +1,9 @@ const path = require('path') +function isDevelopmentEnv() { + return process.env.NODE_ENV === 'development' +} + module.exports = { webpack: { alias: { @@ -10,10 +14,10 @@ module.exports = { filename: 'static/js/[name].js', }, optimization: { - runtimeChunk: false, + runtimeChunk: isDevelopmentEnv(), splitChunks: { chunks(chunk) { - return false + return isDevelopmentEnv() }, }, }, @@ -23,6 +27,10 @@ module.exports = { { plugin: { overrideWebpackConfig: ({ webpackConfig }) => { + if (isDevelopmentEnv()) { + return webpackConfig + } + let mcep webpackConfig.plugins.some((p) => { if (p.constructor.name === 'MiniCssExtractPlugin') { From fc59bda88f33c302a192fcd80370836dd51c485c Mon Sep 17 00:00:00 2001 From: medyo Date: Sun, 23 Oct 2022 15:21:46 +0100 Subject: [PATCH 08/96] add the app using QueryClientProvider --- src/index.js | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/index.js b/src/index.js index bf86ba54..45114ee9 100644 --- a/src/index.js +++ b/src/index.js @@ -6,15 +6,19 @@ import App from './App'; import AppWrapper from './configuration/AppWrapper' import AppErrorBoundary from './configuration/AppErrorBoundary' import ConfigurationWrapper from './configuration/ConfigurationWrapper' +import { QueryClientProvider } from '@tanstack/react-query' +import { queryClient } from 'src/lib/react-query' ReactDOM.render( - - - - - + + + + + + + , document.getElementById('root') From bc3a28dfcdb5cee7cfc2c306f5a040d4c4de7c86 Mon Sep 17 00:00:00 2001 From: medyo Date: Sun, 23 Oct 2022 15:21:53 +0100 Subject: [PATCH 09/96] add missing dependencies --- package.json | 25 ++++- yarn.lock | 287 +++++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 290 insertions(+), 22 deletions(-) diff --git a/package.json b/package.json index cbf55f8c..f1f55244 100644 --- a/package.json +++ b/package.json @@ -5,6 +5,7 @@ "dependencies": { "@amplitude/analytics-browser": "^1.5.5", "@craco/craco": "^6.4.5", + "@tanstack/react-query": "^4.13.0", "@testing-library/jest-dom": "^5.11.4", "@testing-library/react": "^11.1.0", "@testing-library/user-event": "^12.1.10", @@ -31,6 +32,7 @@ "react-tooltip": "^4.2.21", "styled-components": "2", "timeago.js": "^4.0.2", + "type-fest": "^1.2.0", "web-vitals": "^0.2.4" }, "proxy": "https://api.hackertab.dev/", @@ -41,6 +43,12 @@ "stores-build": "./script/stores_build.sh", "eject": "react-scripts eject" }, + "eslintConfig": { + "extends": [ + "react-app", + "react-app/jest" + ] + }, "browserslist": { "production": [ ">0.2%", @@ -55,10 +63,23 @@ }, "devDependencies": { "@types/chrome": "^0.0.198", - "@types/jest": "^29.1.2", "@types/node": "^18.11.0", "@types/react": "^18.0.21", "@types/react-dom": "^18.0.6", - "typescript": "^4.8.4" + "@types/jest": "^29.1.2", + "prettier": "^2.7.1", + "typescript": "^4.8.4", + "@typescript-eslint/eslint-plugin": "^5.40.1", + "@typescript-eslint/parser": "^5.40.1", + "eslint-config-airbnb": "19.0.4", + "eslint-config-airbnb-typescript": "^17.0.0", + "eslint-config-prettier": "^8.5.0", + "eslint-config-react-app": "^7.0.1", + "eslint-plugin-import": "^2.25.3", + "eslint-plugin-jest": "^27.1.3", + "eslint-plugin-jsx-a11y": "^6.5.1", + "eslint-plugin-prettier": "^4.2.1", + "eslint-plugin-react": "^7.28.0", + "eslint-plugin-react-hooks": "^4.3.0" } } diff --git a/yarn.lock b/yarn.lock index 08d5d99e..84d0c29a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -130,6 +130,15 @@ json5 "^2.2.1" semver "^6.3.0" +"@babel/eslint-parser@^7.16.3": + version "7.19.1" + resolved "https://registry.yarnpkg.com/@babel/eslint-parser/-/eslint-parser-7.19.1.tgz#4f68f6b0825489e00a24b41b6a1ae35414ecd2f4" + integrity sha512-AqNf2QWt1rtu2/1rLswy6CDP7H9Oh3mMhk177Y67Rg8d7RD9WfOLLv8CGn6tisFvS2htm86yIe1yLF6I1UDaGQ== + dependencies: + "@nicolo-ribaudo/eslint-scope-5-internals" "5.1.1-v1" + eslint-visitor-keys "^2.1.0" + semver "^6.3.0" + "@babel/generator@^7.12.1", "@babel/generator@^7.19.3", "@babel/generator@^7.19.4": version "7.19.5" resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.19.5.tgz#da3f4b301c8086717eee9cab14da91b1fa5dcca7" @@ -1684,6 +1693,13 @@ "@jridgewell/resolve-uri" "3.1.0" "@jridgewell/sourcemap-codec" "1.4.14" +"@nicolo-ribaudo/eslint-scope-5-internals@5.1.1-v1": + version "5.1.1-v1" + resolved "https://registry.yarnpkg.com/@nicolo-ribaudo/eslint-scope-5-internals/-/eslint-scope-5-internals-5.1.1-v1.tgz#dbf733a965ca47b1973177dc0bb6c889edcfb129" + integrity sha512-54/JRvkLIzzDWshCWfuhadfrfZVPiElY8Fcgmg1HroEly/EDSszzhBAsarCux+D/kOslTRquNzuyGSmUSTTHGg== + dependencies: + eslint-scope "5.1.1" + "@nodelib/fs.scandir@2.1.5": version "2.1.5" resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" @@ -1766,6 +1782,11 @@ estree-walker "^1.0.1" picomatch "^2.2.2" +"@rushstack/eslint-patch@^1.1.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@rushstack/eslint-patch/-/eslint-patch-1.2.0.tgz#8be36a1f66f3265389e90b5f9c9962146758f728" + integrity sha512-sXo/qW2/pAcmT43VoRKOJbDOfV3cYpq3szSVfIThQXNt+E4DfKj361vaAt3c88U5tPUxzEswam7GW48PJqtKAg== + "@sinclair/typebox@^0.24.1": version "0.24.46" resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.24.46.tgz#57501b58023776dbbae9e25619146286440be34c" @@ -1896,6 +1917,19 @@ "@svgr/plugin-svgo" "^5.4.0" loader-utils "^2.0.0" +"@tanstack/query-core@4.13.0": + version "4.13.0" + resolved "https://registry.yarnpkg.com/@tanstack/query-core/-/query-core-4.13.0.tgz#89153096d1fce42c0294fa1d1ae4b3e72aa5353b" + integrity sha512-PzmLQcEgC4rl2OzkiPHYPC9O79DFcMGaKsOzDEP+U4PJ+tbkcEP+Z+FQDlfvX8mCwYC7UNH7hXrQ5EdkGlJjVg== + +"@tanstack/react-query@^4.13.0": + version "4.13.0" + resolved "https://registry.yarnpkg.com/@tanstack/react-query/-/react-query-4.13.0.tgz#13797d590a6c0708545881e38aea5eb39b960c28" + integrity sha512-dI/5hJ/pGQ74P5hxBLC9h6K0/Cap2T3k0ZjjjFLBCNnohDYgl7LNmMopzrRzBHk2mMjf2hgXHIzcKNG8GOZ5hg== + dependencies: + "@tanstack/query-core" "4.13.0" + use-sync-external-store "^1.2.0" + "@testing-library/dom@^7.28.1": version "7.31.2" resolved "https://registry.yarnpkg.com/@testing-library/dom/-/dom-7.31.2.tgz#df361db38f5212b88555068ab8119f5d841a8c4a" @@ -2107,7 +2141,7 @@ expect "^29.0.0" pretty-format "^29.0.0" -"@types/json-schema@*", "@types/json-schema@^7.0.3", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.7", "@types/json-schema@^7.0.8": +"@types/json-schema@*", "@types/json-schema@^7.0.3", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.7", "@types/json-schema@^7.0.8", "@types/json-schema@^7.0.9": version "7.0.11" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.11.tgz#d421b6c527a3037f7c84433fd2c4229e016863d3" integrity sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ== @@ -2197,6 +2231,11 @@ resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.2.tgz#1a62f89525723dde24ba1b01b092bf5df8ad4d39" integrity sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew== +"@types/semver@^7.3.12": + version "7.3.12" + resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.3.12.tgz#920447fdd78d76b19de0438b7f60df3c4a80bf1c" + integrity sha512-WwA1MW0++RfXmCr12xeYOOC5baSC9mSb0ZqCquFzKhcoF4TvHu5MKOuXsncgZcpVFhB1pXd5hZmM0ryAoCp12A== + "@types/source-list-map@*": version "0.1.2" resolved "https://registry.yarnpkg.com/@types/source-list-map/-/source-list-map-0.1.2.tgz#0078836063ffaf17412349bba364087e0ac02ec9" @@ -2285,6 +2324,20 @@ semver "^7.3.5" tsutils "^3.21.0" +"@typescript-eslint/eslint-plugin@^5.40.1", "@typescript-eslint/eslint-plugin@^5.5.0": + version "5.40.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.40.1.tgz#3203a6ff396b1194083faaa6e5110c401201d7d5" + integrity sha512-FsWboKkWdytGiXT5O1/R9j37YgcjO8MKHSUmWnIEjVaz0krHkplPnYi7mwdb+5+cs0toFNQb0HIrN7zONdIEWg== + dependencies: + "@typescript-eslint/scope-manager" "5.40.1" + "@typescript-eslint/type-utils" "5.40.1" + "@typescript-eslint/utils" "5.40.1" + debug "^4.3.4" + ignore "^5.2.0" + regexpp "^3.2.0" + semver "^7.3.7" + tsutils "^3.21.0" + "@typescript-eslint/experimental-utils@4.33.0", "@typescript-eslint/experimental-utils@^4.0.1": version "4.33.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-4.33.0.tgz#6f2a786a4209fa2222989e9380b5331b2810f7fd" @@ -2308,6 +2361,13 @@ eslint-scope "^5.0.0" eslint-utils "^2.0.0" +"@typescript-eslint/experimental-utils@^5.0.0": + version "5.40.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-5.40.1.tgz#2fa6b4f768d42fe7174c34cd02fa79717e4e2bfe" + integrity sha512-lynjgnQuoCgxtYgYWjoQqijk0kYQNiztnVhoqha3N0kMYFVPURidzCq2vn9XvUUu2XxP130ZRKVDKyeGa2bhbw== + dependencies: + "@typescript-eslint/utils" "5.40.1" + "@typescript-eslint/parser@^4.5.0": version "4.33.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-4.33.0.tgz#dfe797570d9694e560528d18eecad86c8c744899" @@ -2318,6 +2378,16 @@ "@typescript-eslint/typescript-estree" "4.33.0" debug "^4.3.1" +"@typescript-eslint/parser@^5.40.1", "@typescript-eslint/parser@^5.5.0": + version "5.40.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.40.1.tgz#e7f8295dd8154d0d37d661ddd8e2f0ecfdee28dd" + integrity sha512-IK6x55va5w4YvXd4b3VrXQPldV9vQTxi5ov+g4pMANsXPTXOcfjx08CRR1Dfrcc51syPtXHF5bgLlMHYFrvQtg== + dependencies: + "@typescript-eslint/scope-manager" "5.40.1" + "@typescript-eslint/types" "5.40.1" + "@typescript-eslint/typescript-estree" "5.40.1" + debug "^4.3.4" + "@typescript-eslint/scope-manager@4.33.0": version "4.33.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-4.33.0.tgz#d38e49280d983e8772e29121cf8c6e9221f280a3" @@ -2326,6 +2396,24 @@ "@typescript-eslint/types" "4.33.0" "@typescript-eslint/visitor-keys" "4.33.0" +"@typescript-eslint/scope-manager@5.40.1": + version "5.40.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.40.1.tgz#a7a5197dfd234622a2421ea590ee0ccc02e18dfe" + integrity sha512-jkn4xsJiUQucI16OLCXrLRXDZ3afKhOIqXs4R3O+M00hdQLKR58WuyXPZZjhKLFCEP2g+TXdBRtLQ33UfAdRUg== + dependencies: + "@typescript-eslint/types" "5.40.1" + "@typescript-eslint/visitor-keys" "5.40.1" + +"@typescript-eslint/type-utils@5.40.1": + version "5.40.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.40.1.tgz#091e4ce3bebbdb68f4980bae9dee2e4e1725f601" + integrity sha512-DLAs+AHQOe6n5LRraXiv27IYPhleF0ldEmx6yBqBgBLaNRKTkffhV1RPsjoJBhVup2zHxfaRtan8/YRBgYhU9Q== + dependencies: + "@typescript-eslint/typescript-estree" "5.40.1" + "@typescript-eslint/utils" "5.40.1" + debug "^4.3.4" + tsutils "^3.21.0" + "@typescript-eslint/types@3.10.1": version "3.10.1" resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-3.10.1.tgz#1d7463fa7c32d8a23ab508a803ca2fe26e758727" @@ -2336,6 +2424,11 @@ resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.33.0.tgz#a1e59036a3b53ae8430ceebf2a919dc7f9af6d72" integrity sha512-zKp7CjQzLQImXEpLt2BUw1tvOMPfNoTAfb8l51evhYbOEEzdWyQNmHWWGPR6hwKJDAi+1VXSBmnhL9kyVTTOuQ== +"@typescript-eslint/types@5.40.1": + version "5.40.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.40.1.tgz#de37f4f64de731ee454bb2085d71030aa832f749" + integrity sha512-Icg9kiuVJSwdzSQvtdGspOlWNjVDnF3qVIKXdJ103o36yRprdl3Ge5cABQx+csx960nuMF21v8qvO31v9t3OHw== + "@typescript-eslint/typescript-estree@3.10.1": version "3.10.1" resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-3.10.1.tgz#fd0061cc38add4fad45136d654408569f365b853" @@ -2363,6 +2456,33 @@ semver "^7.3.5" tsutils "^3.21.0" +"@typescript-eslint/typescript-estree@5.40.1": + version "5.40.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.40.1.tgz#9a7d25492f02c69882ce5e0cd1857b0c55645d72" + integrity sha512-5QTP/nW5+60jBcEPfXy/EZL01qrl9GZtbgDZtDPlfW5zj/zjNrdI2B5zMUHmOsfvOr2cWqwVdWjobCiHcedmQA== + dependencies: + "@typescript-eslint/types" "5.40.1" + "@typescript-eslint/visitor-keys" "5.40.1" + debug "^4.3.4" + globby "^11.1.0" + is-glob "^4.0.3" + semver "^7.3.7" + tsutils "^3.21.0" + +"@typescript-eslint/utils@5.40.1", "@typescript-eslint/utils@^5.10.0", "@typescript-eslint/utils@^5.13.0": + version "5.40.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.40.1.tgz#3204fb73a559d3b7bab7dc9d3c44487c2734a9ca" + integrity sha512-a2TAVScoX9fjryNrW6BZRnreDUszxqm9eQ9Esv8n5nXApMW0zeANUYlwh/DED04SC/ifuBvXgZpIK5xeJHQ3aw== + dependencies: + "@types/json-schema" "^7.0.9" + "@types/semver" "^7.3.12" + "@typescript-eslint/scope-manager" "5.40.1" + "@typescript-eslint/types" "5.40.1" + "@typescript-eslint/typescript-estree" "5.40.1" + eslint-scope "^5.1.1" + eslint-utils "^3.0.0" + semver "^7.3.7" + "@typescript-eslint/visitor-keys@3.10.1": version "3.10.1" resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-3.10.1.tgz#cd4274773e3eb63b2e870ac602274487ecd1e931" @@ -2378,6 +2498,14 @@ "@typescript-eslint/types" "4.33.0" eslint-visitor-keys "^2.0.0" +"@typescript-eslint/visitor-keys@5.40.1": + version "5.40.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.40.1.tgz#f3d2bf5af192f4432b84cec6fdcb387193518754" + integrity sha512-A2DGmeZ+FMja0geX5rww+DpvILpwo1OsiQs0M+joPWJYsiEFBLsH0y1oFymPNul6Z5okSmHpP4ivkc2N0Cgfkw== + dependencies: + "@typescript-eslint/types" "5.40.1" + eslint-visitor-keys "^3.3.0" + "@webassemblyjs/ast@1.9.0": version "1.9.0" resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.9.0.tgz#bd850604b4042459a5a41cd7d338cbed695ed964" @@ -3145,7 +3273,7 @@ babel-preset-jest@^26.6.2: babel-plugin-jest-hoist "^26.6.2" babel-preset-current-node-syntax "^1.0.0" -babel-preset-react-app@^10.0.0: +babel-preset-react-app@^10.0.0, babel-preset-react-app@^10.0.1: version "10.0.1" resolved "https://registry.yarnpkg.com/babel-preset-react-app/-/babel-preset-react-app-10.0.1.tgz#ed6005a20a24f2c88521809fa9aea99903751584" integrity sha512-b0D9IZ1WhhCWkrTXyFuIIgqGzSkRIH5D5AmB0bXbzYAB1OBAwHcUeyWW2LorutLWF5btNo/N7r/cIdmvvKJlYg== @@ -3945,7 +4073,7 @@ concat-stream@^1.5.0: readable-stream "^2.2.2" typedarray "^0.0.6" -confusing-browser-globals@^1.0.10: +confusing-browser-globals@^1.0.10, confusing-browser-globals@^1.0.11: version "1.0.11" resolved "https://registry.yarnpkg.com/confusing-browser-globals/-/confusing-browser-globals-1.0.11.tgz#ae40e9b57cdd3915408a2805ebd3a5585608dc81" integrity sha512-JsPKdmh8ZkmnHxDk55FZ1TqVLvEQTvoByJZRN9jzI0UjxK/QgAmsphz7PGtqgPieQZ/CQcHWXCR7ATDNhGe+YA== @@ -4466,7 +4594,7 @@ debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.0, debug@^2.6.9: dependencies: ms "2.0.0" -debug@4, debug@^4.0.0, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1: +debug@4, debug@^4.0.0, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.4: version "4.3.4" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== @@ -5062,6 +5190,37 @@ escodegen@^2.0.0: optionalDependencies: source-map "~0.6.1" +eslint-config-airbnb-base@^15.0.0: + version "15.0.0" + resolved "https://registry.yarnpkg.com/eslint-config-airbnb-base/-/eslint-config-airbnb-base-15.0.0.tgz#6b09add90ac79c2f8d723a2580e07f3925afd236" + integrity sha512-xaX3z4ZZIcFLvh2oUNvcX5oEofXda7giYmuplVxoOg5A7EXJMrUyqRgR+mhDhPK8LZ4PttFOBvCYDbX3sUoUig== + dependencies: + confusing-browser-globals "^1.0.10" + object.assign "^4.1.2" + object.entries "^1.1.5" + semver "^6.3.0" + +eslint-config-airbnb-typescript@^17.0.0: + version "17.0.0" + resolved "https://registry.yarnpkg.com/eslint-config-airbnb-typescript/-/eslint-config-airbnb-typescript-17.0.0.tgz#360dbcf810b26bbcf2ff716198465775f1c49a07" + integrity sha512-elNiuzD0kPAPTXjFWg+lE24nMdHMtuxgYoD30OyMD6yrW1AhFZPAg27VX7d3tzOErw+dgJTNWfRSDqEcXb4V0g== + dependencies: + eslint-config-airbnb-base "^15.0.0" + +eslint-config-airbnb@19.0.4: + version "19.0.4" + resolved "https://registry.yarnpkg.com/eslint-config-airbnb/-/eslint-config-airbnb-19.0.4.tgz#84d4c3490ad70a0ffa571138ebcdea6ab085fdc3" + integrity sha512-T75QYQVQX57jiNgpF9r1KegMICE94VYwoFQyMGhrvc+lB8YF2E/M/PYDaQe1AJcWaEgqLE+ErXV1Og/+6Vyzew== + dependencies: + eslint-config-airbnb-base "^15.0.0" + object.assign "^4.1.2" + object.entries "^1.1.5" + +eslint-config-prettier@^8.5.0: + version "8.5.0" + resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-8.5.0.tgz#5a81680ec934beca02c7b1a61cf8ca34b66feab1" + integrity sha512-obmWKLUNCnhtQRKc+tmnYuQl0pFU1ibYJQ5BGhTVB08bHe9wC8qUeG7c08dj9XX+AuPj1YSGSQIHl1pnDHZR0Q== + eslint-config-react-app@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/eslint-config-react-app/-/eslint-config-react-app-6.0.0.tgz#ccff9fc8e36b322902844cbd79197982be355a0e" @@ -5069,6 +5228,26 @@ eslint-config-react-app@^6.0.0: dependencies: confusing-browser-globals "^1.0.10" +eslint-config-react-app@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/eslint-config-react-app/-/eslint-config-react-app-7.0.1.tgz#73ba3929978001c5c86274c017ea57eb5fa644b4" + integrity sha512-K6rNzvkIeHaTd8m/QEh1Zko0KI7BACWkkneSs6s9cKZC/J27X3eZR6Upt1jkmZ/4FK+XUOPPxMEN7+lbUXfSlA== + dependencies: + "@babel/core" "^7.16.0" + "@babel/eslint-parser" "^7.16.3" + "@rushstack/eslint-patch" "^1.1.0" + "@typescript-eslint/eslint-plugin" "^5.5.0" + "@typescript-eslint/parser" "^5.5.0" + babel-preset-react-app "^10.0.1" + confusing-browser-globals "^1.0.11" + eslint-plugin-flowtype "^8.0.3" + eslint-plugin-import "^2.25.3" + eslint-plugin-jest "^25.3.0" + eslint-plugin-jsx-a11y "^6.5.1" + eslint-plugin-react "^7.27.1" + eslint-plugin-react-hooks "^4.3.0" + eslint-plugin-testing-library "^5.0.1" + eslint-import-resolver-node@^0.3.6: version "0.3.6" resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.6.tgz#4048b958395da89668252001dbd9eca6b83bacbd" @@ -5092,7 +5271,15 @@ eslint-plugin-flowtype@^5.2.0: lodash "^4.17.15" string-natural-compare "^3.0.1" -eslint-plugin-import@^2.22.1: +eslint-plugin-flowtype@^8.0.3: + version "8.0.3" + resolved "https://registry.yarnpkg.com/eslint-plugin-flowtype/-/eslint-plugin-flowtype-8.0.3.tgz#e1557e37118f24734aa3122e7536a038d34a4912" + integrity sha512-dX8l6qUL6O+fYPtpNRideCFSpmWOUVx5QcaGLVqe/vlDiBSe4vYljDWDETwnyFzpl7By/WVIu6rcrniCgH9BqQ== + dependencies: + lodash "^4.17.21" + string-natural-compare "^3.0.1" + +eslint-plugin-import@^2.22.1, eslint-plugin-import@^2.25.3: version "2.26.0" resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.26.0.tgz#f812dc47be4f2b72b478a021605a59fc6fe8b88b" integrity sha512-hYfi3FXaM8WPLf4S1cikh/r4IxnO6zrhZbEGz2b660EJRbuxgpDS5gkCuYgGWg2xxh2rBuIr4Pvhve/7c31koA== @@ -5118,7 +5305,21 @@ eslint-plugin-jest@^24.1.0: dependencies: "@typescript-eslint/experimental-utils" "^4.0.1" -eslint-plugin-jsx-a11y@^6.3.1: +eslint-plugin-jest@^25.3.0: + version "25.7.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-25.7.0.tgz#ff4ac97520b53a96187bad9c9814e7d00de09a6a" + integrity sha512-PWLUEXeeF7C9QGKqvdSbzLOiLTx+bno7/HC9eefePfEb257QFHg7ye3dh80AZVkaa/RQsBB1Q/ORQvg2X7F0NQ== + dependencies: + "@typescript-eslint/experimental-utils" "^5.0.0" + +eslint-plugin-jest@^27.1.3: + version "27.1.3" + resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-27.1.3.tgz#9f359eeac0c720a825f658e7e261a9eef869dc8d" + integrity sha512-7DrIfYRQPa7JQd1Le8G/BJsfYHVUKQdJQ/6vULSp/4NjKZmSMJ/605G2hhScEra++SiH68zPEjLnrO74nHrMLg== + dependencies: + "@typescript-eslint/utils" "^5.10.0" + +eslint-plugin-jsx-a11y@^6.3.1, eslint-plugin-jsx-a11y@^6.5.1: version "6.6.1" resolved "https://registry.yarnpkg.com/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.6.1.tgz#93736fc91b83fdc38cc8d115deedfc3091aef1ff" integrity sha512-sXgFVNHiWffBq23uiS/JaP6eVR622DqwB4yTzKvGZGcPq6/yZ3WmOZfuBks/vHWo9GaFOqC2ZK4i6+C35knx7Q== @@ -5137,12 +5338,19 @@ eslint-plugin-jsx-a11y@^6.3.1: minimatch "^3.1.2" semver "^6.3.0" -eslint-plugin-react-hooks@^4.2.0: +eslint-plugin-prettier@^4.2.1: + version "4.2.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-4.2.1.tgz#651cbb88b1dab98bfd42f017a12fa6b2d993f94b" + integrity sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ== + dependencies: + prettier-linter-helpers "^1.0.0" + +eslint-plugin-react-hooks@^4.2.0, eslint-plugin-react-hooks@^4.3.0: version "4.6.0" resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz#4c3e697ad95b77e93f8646aaa1630c1ba607edd3" integrity sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g== -eslint-plugin-react@^7.21.5: +eslint-plugin-react@^7.21.5, eslint-plugin-react@^7.27.1, eslint-plugin-react@^7.28.0: version "7.31.10" resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.31.10.tgz#6782c2c7fe91c09e715d536067644bbb9491419a" integrity sha512-e4N/nc6AAlg4UKW/mXeYWd3R++qUano5/o+t+wnWxIf+bLsOaH3a4q74kX3nDjYym3VBN4HyO9nEn1GcAqgQOA== @@ -5169,15 +5377,14 @@ eslint-plugin-testing-library@^3.9.2: dependencies: "@typescript-eslint/experimental-utils" "^3.10.1" -eslint-scope@^4.0.3: - version "4.0.3" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-4.0.3.tgz#ca03833310f6889a3264781aa82e63eb9cfe7848" - integrity sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg== +eslint-plugin-testing-library@^5.0.1: + version "5.9.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-testing-library/-/eslint-plugin-testing-library-5.9.1.tgz#12e4bd34c48683ee98af4df2e3318ec9f51dcf8a" + integrity sha512-6BQp3tmb79jLLasPHJmy8DnxREe+2Pgf7L+7o09TSWPfdqqtQfRZmZNetr5mOs3yqZk/MRNxpN3RUpJe0wB4LQ== dependencies: - esrecurse "^4.1.0" - estraverse "^4.1.1" + "@typescript-eslint/utils" "^5.13.0" -eslint-scope@^5.0.0, eslint-scope@^5.1.1: +eslint-scope@5.1.1, eslint-scope@^5.0.0, eslint-scope@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== @@ -5185,6 +5392,14 @@ eslint-scope@^5.0.0, eslint-scope@^5.1.1: esrecurse "^4.3.0" estraverse "^4.1.1" +eslint-scope@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-4.0.3.tgz#ca03833310f6889a3264781aa82e63eb9cfe7848" + integrity sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg== + dependencies: + esrecurse "^4.1.0" + estraverse "^4.1.1" + eslint-utils@^2.0.0, eslint-utils@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-2.1.0.tgz#d2de5e03424e707dc10c74068ddedae708741b27" @@ -5204,11 +5419,16 @@ eslint-visitor-keys@^1.0.0, eslint-visitor-keys@^1.1.0, eslint-visitor-keys@^1.3 resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz#30ebd1ef7c2fdff01c3a4f151044af25fab0523e" integrity sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ== -eslint-visitor-keys@^2.0.0: +eslint-visitor-keys@^2.0.0, eslint-visitor-keys@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz#f65328259305927392c938ed44eb0a5c9b2bd303" integrity sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw== +eslint-visitor-keys@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz#f6480fa6b1f30efe2d1968aa8ac745b862469826" + integrity sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA== + eslint-webpack-plugin@^2.1.0: version "2.7.0" resolved "https://registry.yarnpkg.com/eslint-webpack-plugin/-/eslint-webpack-plugin-2.7.0.tgz#0525793a4f8c652c1c6d863995ce1e0f2dcbd143" @@ -5510,6 +5730,11 @@ fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== +fast-diff@^1.1.2: + version "1.2.0" + resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.2.0.tgz#73ee11982d86caaf7959828d519cfe927fac5f03" + integrity sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w== + fast-glob@^3.1.1, fast-glob@^3.2.9: version "3.2.12" resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.12.tgz#7f39ec99c2e6ab030337142da9e0c18f37afae80" @@ -5964,7 +6189,7 @@ globby@11.0.1: merge2 "^1.3.0" slash "^3.0.0" -globby@^11.0.3: +globby@^11.0.3, globby@^11.1.0: version "11.1.0" resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== @@ -8664,7 +8889,7 @@ object-visit@^1.0.0: dependencies: isobject "^3.0.0" -object.assign@^4.1.0, object.assign@^4.1.3, object.assign@^4.1.4: +object.assign@^4.1.0, object.assign@^4.1.2, object.assign@^4.1.3, object.assign@^4.1.4: version "4.1.4" resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.4.tgz#9673c7c7c351ab8c4d0b516f4343ebf4dfb7799f" integrity sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ== @@ -9788,6 +10013,18 @@ prepend-http@^1.0.0: resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc" integrity sha512-PhmXi5XmoyKw1Un4E+opM2KcsJInDvKyuOumcjjw3waw86ZNjHwVUOOWLc4bCzLdcKNaWBH9e99sbWzDQsVaYg== +prettier-linter-helpers@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz#d23d41fe1375646de2d0104d3454a3008802cf7b" + integrity sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w== + dependencies: + fast-diff "^1.1.2" + +prettier@^2.7.1: + version "2.7.1" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.7.1.tgz#e235806850d057f97bb08368a4f7d899f7760c64" + integrity sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g== + pretty-bytes@^5.3.0: version "5.6.0" resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-5.6.0.tgz#356256f643804773c82f64723fe78c92c62beaeb" @@ -10439,7 +10676,7 @@ regexp.prototype.flags@^1.2.0, regexp.prototype.flags@^1.4.1, regexp.prototype.f define-properties "^1.1.3" functions-have-names "^1.2.2" -regexpp@^3.1.0: +regexpp@^3.1.0, regexpp@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.2.0.tgz#0425a2768d8f23bad70ca4b90461fa2f1213e1b2" integrity sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg== @@ -10876,7 +11113,7 @@ semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.3.0: resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== -semver@^7.2.1, semver@^7.3.2, semver@^7.3.5: +semver@^7.2.1, semver@^7.3.2, semver@^7.3.5, semver@^7.3.7: version "7.3.8" resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.8.tgz#07a78feafb3f7b32347d725e33de7e2a2df67798" integrity sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A== @@ -11928,6 +12165,11 @@ type-fest@^0.8.1: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== +type-fest@^1.2.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-1.4.0.tgz#e9fb813fe3bf1744ec359d55d1affefa76f14be1" + integrity sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA== + type-is@~1.6.18: version "1.6.18" resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" @@ -12186,6 +12428,11 @@ url@^0.11.0: punycode "1.3.2" querystring "0.2.0" +use-sync-external-store@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz#7dbefd6ef3fe4e767a0cf5d7287aacfb5846928a" + integrity sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA== + use@^3.1.0: version "3.1.1" resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" From ac28ef21391d757558b696a4857d406a7689f843 Mon Sep 17 00:00:00 2001 From: Mehdi Sakout Date: Thu, 27 Oct 2022 18:39:44 +0100 Subject: [PATCH 10/96] typescript changelog feature --- package.json | 11 +- src/components/Changelog.js | 121 ------------------ src/components/Header.js | 2 +- src/features/changelog/api/getVersions.ts | 27 ++++ .../changelog/components/Changelog.tsx | 74 +++++++++++ src/features/changelog/index.ts | 2 + src/features/changelog/stores/changelog.ts | 17 +++ src/features/changelog/types/index.ts | 6 + src/lib/analytics.ts | 10 +- ...rencesContext.js => PreferencesContext.ts} | 6 +- src/utils/Os.ts | 8 ++ yarn.lock | 9 +- 12 files changed, 156 insertions(+), 137 deletions(-) delete mode 100644 src/components/Changelog.js create mode 100644 src/features/changelog/api/getVersions.ts create mode 100644 src/features/changelog/components/Changelog.tsx create mode 100644 src/features/changelog/index.ts create mode 100644 src/features/changelog/stores/changelog.ts create mode 100644 src/features/changelog/types/index.ts rename src/preferences/{PreferencesContext.js => PreferencesContext.ts} (69%) create mode 100644 src/utils/Os.ts diff --git a/package.json b/package.json index f1f55244..7d799e15 100644 --- a/package.json +++ b/package.json @@ -33,7 +33,8 @@ "styled-components": "2", "timeago.js": "^4.0.2", "type-fest": "^1.2.0", - "web-vitals": "^0.2.4" + "web-vitals": "^0.2.4", + "zustand": "^4.1.3" }, "proxy": "https://api.hackertab.dev/", "scripts": { @@ -63,12 +64,10 @@ }, "devDependencies": { "@types/chrome": "^0.0.198", + "@types/jest": "^29.1.2", "@types/node": "^18.11.0", "@types/react": "^18.0.21", "@types/react-dom": "^18.0.6", - "@types/jest": "^29.1.2", - "prettier": "^2.7.1", - "typescript": "^4.8.4", "@typescript-eslint/eslint-plugin": "^5.40.1", "@typescript-eslint/parser": "^5.40.1", "eslint-config-airbnb": "19.0.4", @@ -80,6 +79,8 @@ "eslint-plugin-jsx-a11y": "^6.5.1", "eslint-plugin-prettier": "^4.2.1", "eslint-plugin-react": "^7.28.0", - "eslint-plugin-react-hooks": "^4.3.0" + "eslint-plugin-react-hooks": "^4.3.0", + "prettier": "^2.7.1", + "typescript": "^4.8.4" } } diff --git a/src/components/Changelog.js b/src/components/Changelog.js deleted file mode 100644 index f9bc4e00..00000000 --- a/src/components/Changelog.js +++ /dev/null @@ -1,121 +0,0 @@ -import React, { useEffect, useState, useContext } from 'react' -import ReactTooltip from 'react-tooltip' -import { HiBell } from 'react-icons/hi' -import ReactMarkdown from 'react-markdown' -import axios from 'axios' -import { format } from 'timeago.js' -import BeatLoader from 'react-spinners/BeatLoader' -import { APP } from '../Constants' -import PreferencesContext from '../preferences/PreferencesContext' - -function Changelog({}) { - const tooltipId = 'tl-1' - const [changelogMarkdown, setChangelogMarkdown] = useState([]) - const [loading, setLoading] = useState(true) - const [error, setError] = useState(null) - const [localAppVersion, setLocalAppVersion] = useState('') - const preferences = useContext(PreferencesContext) - const { dispatcher, changelogMeta } = preferences - const [isChangelogRead, setIsChangelogRead] = useState(false) - - const afterShow = () => { - if (changelogMarkdown.length === 0) { - dispatcher({ type: 'setChangelogMeta', value: { shown: true, version: localAppVersion } }) - fetchChangelog() - } - } - - useEffect(() => { - setIsChangelogRead(changelogMeta?.shown == true && changelogMeta?.version == localAppVersion) - }, [localAppVersion, changelogMeta]) - - useEffect(() => { - try { - //setLocalAppVersion(chrome.runtime.getManifest().version) - } catch (e) { - setLocalAppVersion('') - } - }, []) - - const fetchChangelog = async () => { - setLoading(true) - setError(null) - setChangelogMarkdown([]) - - try { - const response = await axios.get(APP.changeLogLink) - const data = response.data - - let sameLocalVersionIndex = 0 - - if (localAppVersion) { - sameLocalVersionIndex = data.findIndex( - (item) => localAppVersion == item.name.replace(/[^\d.-]/g, '') - ) - } - - if (sameLocalVersionIndex == -1) { - sameLocalVersionIndex = 0 - } - - const mappedVersions = data.slice(sameLocalVersionIndex, data.length).map((item) => { - return { - version: item.name, - date: item.published_at, - body: item.body, - url: item.html_url, - } - }) - setChangelogMarkdown(mappedVersions) - } catch (e) { - setError(e) - } finally { - setLoading(false) - } - } - - return ( - <> - - {loading ? ( -
- -
- ) : error ? ( -

Failed to load the changelog

- ) : ( - changelogMarkdown.map((item) => { - return ( -
-
- window.open(item.url, '_blank')}> - {item.version} - - {format(new Date(item.date))} -
-
- -
-
- ) - }) - )} -
- - - - - ) -} - -export default Changelog diff --git a/src/components/Header.js b/src/components/Header.js index ca45647e..64890880 100644 --- a/src/components/Header.js +++ b/src/components/Header.js @@ -9,7 +9,7 @@ import SettingsModal from '../settings/SettingsModal' import { BsMoon } from 'react-icons/bs' import { IoMdSunny } from 'react-icons/io' import { trackSearchEngineUse } from 'src/lib/analytics' -import Changelog from './Changelog' +import {Changelog} from 'src/features/changelog' import { GoSearch } from 'react-icons/go' function SearchBar({ state }) { diff --git a/src/features/changelog/api/getVersions.ts b/src/features/changelog/api/getVersions.ts new file mode 100644 index 00000000..fe4c7093 --- /dev/null +++ b/src/features/changelog/api/getVersions.ts @@ -0,0 +1,27 @@ +import { useQuery } from '@tanstack/react-query'; +import { ExtractFnReturnType, QueryConfig } from 'src/lib/react-query'; +import { Version } from "../types"; +import { axios } from 'src/lib/axios'; + +const getAd = async (): Promise => { + + return axios.get('https://api.github.com/repos/medyo/hackertab.dev/releases') + .then(response => { + const versions = response.data as unknown as Version[]; + console.log("response.data", versions) + return versions + }) +} + +type QueryFnType = typeof getAd; + +type UseGetAdOptions = { + config?: QueryConfig; +}; +export const useGetVersions = ({ config }: UseGetAdOptions = {}) => { + return useQuery>({ + ...config, + queryKey: ['versions'], + queryFn: () => getAd(), + }); +} \ No newline at end of file diff --git a/src/features/changelog/components/Changelog.tsx b/src/features/changelog/components/Changelog.tsx new file mode 100644 index 00000000..a9b30eea --- /dev/null +++ b/src/features/changelog/components/Changelog.tsx @@ -0,0 +1,74 @@ +import React, { useEffect, useState } from 'react' +import ReactTooltip from 'react-tooltip' +import { HiBell } from 'react-icons/hi' +import ReactMarkdown from 'react-markdown' +import { format } from 'timeago.js' +import BeatLoader from 'react-spinners/BeatLoader' +import {useGetVersions} from "../api/getVersions"; +import {useChangelogStore} from "../stores/changelog"; +import {getAppVersion} from "src/utils/Os"; + +export const Changelog = () => { + const tooltipId = 'tl-1' + const [tooltipOpen, setTooltipShown] = useState(false); + const {isLoading, isError, data: versions} = useGetVersions({ + config: { + enabled: tooltipOpen + } + }); + + const {lastReadVersion, setVersionAsRead} = useChangelogStore(); + + const isChangelogRead = (): boolean => { + return lastReadVersion === getAppVersion(); + } + + useEffect(() => { + if (tooltipOpen) { + setVersionAsRead(getAppVersion()) + } + }, [tooltipOpen, setVersionAsRead]) + + return ( + <> + {setTooltipShown(true)}} + place="bottom" + className="changelogTooltip scrollable" + globalEventOff="click"> + {isLoading ? ( +
+ +
+ ) : isError || !versions.length ? ( +

Failed to load the changelog

+ ) : ( + versions.map((item) => { + return ( +
+
+ window.open(item.html_url, '_blank')}> + {item.name} + + {format(new Date(item.published_at))} +
+
+ +
+
+ ) + }) + )} +
+ + + + + ) +} \ No newline at end of file diff --git a/src/features/changelog/index.ts b/src/features/changelog/index.ts new file mode 100644 index 00000000..7d017bc4 --- /dev/null +++ b/src/features/changelog/index.ts @@ -0,0 +1,2 @@ +export * from "./types" +export * from "./components/Changelog" \ No newline at end of file diff --git a/src/features/changelog/stores/changelog.ts b/src/features/changelog/stores/changelog.ts new file mode 100644 index 00000000..b4462a03 --- /dev/null +++ b/src/features/changelog/stores/changelog.ts @@ -0,0 +1,17 @@ +import create from 'zustand'; +import { persist } from 'zustand/middleware' + +type ChangelogVersionStore = { + lastReadVersion: string | undefined | null; + setVersionAsRead: (versionName: string | undefined | null) => void; +}; + +export const useChangelogStore = create(persist((set) => ({ + lastReadVersion: undefined, + setVersionAsRead: (versionName: string | undefined | null) => + set(() => ({ + lastReadVersion: versionName, + })) +}),{ + name: 'changelog_storage', +})); diff --git a/src/features/changelog/types/index.ts b/src/features/changelog/types/index.ts new file mode 100644 index 00000000..ad2a7088 --- /dev/null +++ b/src/features/changelog/types/index.ts @@ -0,0 +1,6 @@ +export type Version = { + name: string; + published_at: string; + body: string; + html_url: string; +} \ No newline at end of file diff --git a/src/lib/analytics.ts b/src/lib/analytics.ts index 422abc3d..0ecfbddc 100644 --- a/src/lib/analytics.ts +++ b/src/lib/analytics.ts @@ -2,6 +2,7 @@ import AppStorage from '../services/localStorage'; import { init, track, identify, Identify } from '@amplitude/analytics-browser' import { isDevelopment } from 'src/utils/Environment'; import { ANALYTICS_SDK_KEY, ANALYTICS_ENDPOINT, LS_ANALYTICS_ID_KEY } from 'src/Constants' +import {getAppVersion} from "src/utils/Os"; enum Objects { PAGE = 'Page', @@ -305,14 +306,7 @@ const getRandomUserId = () => { return userId } -const getAppVersion = (): string | undefined => { - try { - var manifestData = chrome.runtime.getManifest() - return manifestData.version - } catch (e) { - return undefined - } -} + const getScreenResolution = (): string => { const realWidth = window.screen.width const realHeight = window.screen.height diff --git a/src/preferences/PreferencesContext.js b/src/preferences/PreferencesContext.ts similarity index 69% rename from src/preferences/PreferencesContext.js rename to src/preferences/PreferencesContext.ts index 8e8b859e..c97145db 100644 --- a/src/preferences/PreferencesContext.js +++ b/src/preferences/PreferencesContext.ts @@ -2,7 +2,11 @@ import React from 'react' const PreferencesContext = React.createContext({ userSelectedTags: [], - dispatcher: null + dispatcher: null, + changelogMeta: { + shown: false, + version: "", + } }); diff --git a/src/utils/Os.ts b/src/utils/Os.ts new file mode 100644 index 00000000..6e28dc76 --- /dev/null +++ b/src/utils/Os.ts @@ -0,0 +1,8 @@ +export const getAppVersion = (): string | undefined => { + try { + var manifestData = chrome.runtime.getManifest() + return manifestData.version + } catch (e) { + return undefined + } +} diff --git a/yarn.lock b/yarn.lock index 84d0c29a..485db560 100644 --- a/yarn.lock +++ b/yarn.lock @@ -12428,7 +12428,7 @@ url@^0.11.0: punycode "1.3.2" querystring "0.2.0" -use-sync-external-store@^1.2.0: +use-sync-external-store@1.2.0, use-sync-external-store@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz#7dbefd6ef3fe4e767a0cf5d7287aacfb5846928a" integrity sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA== @@ -13132,3 +13132,10 @@ yocto-queue@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== + +zustand@^4.1.3: + version "4.1.3" + resolved "https://registry.yarnpkg.com/zustand/-/zustand-4.1.3.tgz#72bc4c0ed8ed906fbd92c7c20cde8dd6114c018f" + integrity sha512-AdFyr6+4sVD6xlyc/ArQaOrleqzxJEBbAXglufZ5lgvisoz8GUN3icOrKOnX1uRSxmpmdVUQPen9hhymWIzhBg== + dependencies: + use-sync-external-store "1.2.0" From f524e4d0c12054212cb715f4d0e28d83b93f055b Mon Sep 17 00:00:00 2001 From: medyo Date: Thu, 27 Oct 2022 20:21:38 +0100 Subject: [PATCH 11/96] add changelog analytics event --- src/lib/analytics.ts | 33 ++++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/src/lib/analytics.ts b/src/lib/analytics.ts index 0ecfbddc..5fd87788 100644 --- a/src/lib/analytics.ts +++ b/src/lib/analytics.ts @@ -15,6 +15,7 @@ enum Objects { CARD = 'Card', SEARCH_ENGINE = 'Search Engine', LISTING_MODE = 'Listing Mode', + CHANGE_LOG = 'Change Log', } enum Verbs { @@ -206,6 +207,13 @@ export const trackCardDateRangeSelect = (sourceName: string, dateRange: string) }) } +export const trackChangeLogOpen = () => { + trackEvent({ + object: Objects.CHANGE_LOG, + verb: Verbs.OPEN + }) +} + // Identification export const identifyUserLanguages = (languages: string[]) => { @@ -233,7 +241,7 @@ export const identifyUserLinksInNewTab = (enabled: boolean) => { type trackEventProps = { object: Exclude, verb: Exclude, - attributes: { + attributes?: { //[P in Exclude]?: string; [P: string]: string; } @@ -242,17 +250,20 @@ type trackEventProps = { const trackEvent = ({ object, verb, attributes }: trackEventProps) => { try { const event = `${object}${_SEP_}${verb}` - Object.keys(attributes).map(attr => { - const value = attributes[attr]; - if (typeof value !== "number") { - attributes[attr] = value.toLowerCase(); - } - return attr; - }); - // Remove http and www from links - if (Object.keys(attributes).some((attr) => attr == Attributes.LINK)) { - attributes[Attributes.LINK] = attributes[Attributes.LINK].replace(/(https*:\/\/[www.]*)/, '') + if (attributes) { + Object.keys(attributes).map(attr => { + const value = attributes[attr]; + if (typeof value !== "number") { + attributes[attr] = value.toLowerCase(); + } + return attr; + }); + + // Remove http and www from links + if (Object.keys(attributes).some((attr) => attr == Attributes.LINK)) { + attributes[Attributes.LINK] = attributes[Attributes.LINK].replace(/(https*:\/\/[www.]*)/, '') + } } if (isDevelopment()) { From a0535363e8d303a89aef5faace674483b5a8b9d3 Mon Sep 17 00:00:00 2001 From: medyo Date: Thu, 27 Oct 2022 20:22:03 +0100 Subject: [PATCH 12/96] change `new` instead of the bell when a new version is published --- src/App.css | 4 ++ .../changelog/components/Changelog.tsx | 42 ++++++++++++------- 2 files changed, 32 insertions(+), 14 deletions(-) diff --git a/src/App.css b/src/App.css index 45e56af0..9f708500 100644 --- a/src/App.css +++ b/src/App.css @@ -717,6 +717,10 @@ Producthunt item color: white; } .changelogButton.active { + width: auto; + font-size: 12px; + padding:0 4px; + text-transform: lowercase; background-color: var(--tooltip-accent-color); } diff --git a/src/features/changelog/components/Changelog.tsx b/src/features/changelog/components/Changelog.tsx index a9b30eea..e6d979a5 100644 --- a/src/features/changelog/components/Changelog.tsx +++ b/src/features/changelog/components/Changelog.tsx @@ -7,27 +7,37 @@ import BeatLoader from 'react-spinners/BeatLoader' import {useGetVersions} from "../api/getVersions"; import {useChangelogStore} from "../stores/changelog"; import {getAppVersion} from "src/utils/Os"; +import { trackChangeLogOpen } from 'src/lib/analytics' -export const Changelog = () => { +export const Changelog = () => { const tooltipId = 'tl-1' - const [tooltipOpen, setTooltipShown] = useState(false); - const {isLoading, isError, data: versions} = useGetVersions({ + const [tooltipShown, setTooltipShown] = useState(false) + const { + isLoading, + isError, + data: versions, + } = useGetVersions({ config: { - enabled: tooltipOpen - } - }); + enabled: tooltipShown, + }, + }) - const {lastReadVersion, setVersionAsRead} = useChangelogStore(); + const { lastReadVersion, setVersionAsRead } = useChangelogStore() const isChangelogRead = (): boolean => { - return lastReadVersion === getAppVersion(); + return lastReadVersion === getAppVersion() } useEffect(() => { - if (tooltipOpen) { - setVersionAsRead(getAppVersion()) + const currentVersion = getAppVersion() + if (tooltipShown) { + trackChangeLogOpen() + + if (currentVersion) { + setVersionAsRead(currentVersion) + } } - }, [tooltipOpen, setVersionAsRead]) + }, [tooltipShown, setVersionAsRead]) return ( <> @@ -35,7 +45,9 @@ export const Changelog = () => { id={tooltipId} event="click" scrollHide={false} - afterShow={() => {setTooltipShown(true)}} + afterShow={() => { + setTooltipShown(true) + }} place="bottom" className="changelogTooltip scrollable" globalEventOff="click"> @@ -50,7 +62,9 @@ export const Changelog = () => { return (
- window.open(item.html_url, '_blank')}> + window.open(item.html_url, '_blank')}> {item.name} {format(new Date(item.published_at))} @@ -67,7 +81,7 @@ export const Changelog = () => { data-tip data-for={tooltipId} className={'changelogButton' + (!isChangelogRead() ? ' active' : '')}> - + {isChangelogRead() ? : `New`} ) From 9a1cdb9e75e832e70da8e755d21ecad8efedb215 Mon Sep 17 00:00:00 2001 From: medyo Date: Thu, 27 Oct 2022 20:22:23 +0100 Subject: [PATCH 13/96] remove debug line --- src/features/changelog/api/getVersions.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/features/changelog/api/getVersions.ts b/src/features/changelog/api/getVersions.ts index fe4c7093..bd9d683d 100644 --- a/src/features/changelog/api/getVersions.ts +++ b/src/features/changelog/api/getVersions.ts @@ -8,7 +8,6 @@ const getAd = async (): Promise => { return axios.get('https://api.github.com/repos/medyo/hackertab.dev/releases') .then(response => { const versions = response.data as unknown as Version[]; - console.log("response.data", versions) return versions }) } From 4b4ee4608b56432f19c03ea1c80ff7f5819868cd Mon Sep 17 00:00:00 2001 From: medyo Date: Thu, 27 Oct 2022 21:39:31 +0100 Subject: [PATCH 14/96] fix wrong identification attribute --- src/lib/analytics.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/analytics.ts b/src/lib/analytics.ts index 5fd87788..f5424a2b 100644 --- a/src/lib/analytics.ts +++ b/src/lib/analytics.ts @@ -217,7 +217,7 @@ export const trackChangeLogOpen = () => { // Identification export const identifyUserLanguages = (languages: string[]) => { - identifyUserProperty(Attributes.LANGUAGE, languages) + identifyUserProperty(Attributes.LANGUAGES, languages) } export const identifyUserListingMode = (listingMode: "compact" | "normal") => { From 97bc47c166ad6ef810233068f1541d8c53198869 Mon Sep 17 00:00:00 2001 From: medyo Date: Fri, 28 Oct 2022 11:25:33 +0100 Subject: [PATCH 15/96] migrate settings to typescript --- craco.config.js | 8 ++ package.json | 4 +- src/components/Header.js | 4 +- .../settings/components/SettingsModal.tsx} | 76 ++++++++++++------- .../settings/components}/settings.css | 0 src/features/settings/index.ts | 1 + src/preferences/PreferencesContext.ts | 35 +++++++-- src/types/index.ts | 4 + yarn.lock | 73 +++++++++++++----- 9 files changed, 148 insertions(+), 57 deletions(-) rename src/{settings/SettingsModal.js => features/settings/components/SettingsModal.tsx} (73%) rename src/{settings => features/settings/components}/settings.css (100%) create mode 100644 src/features/settings/index.ts create mode 100644 src/types/index.ts diff --git a/craco.config.js b/craco.config.js index db60c98f..22f34e28 100644 --- a/craco.config.js +++ b/craco.config.js @@ -1,4 +1,5 @@ const path = require('path') +const webpack = require('webpack') function isDevelopmentEnv() { return process.env.NODE_ENV === 'development' @@ -6,6 +7,13 @@ function isDevelopmentEnv() { module.exports = { webpack: { + plugins: { + add: [ + new webpack.DefinePlugin({ + process: { env: {} }, + }), + ], + }, alias: { '@': path.resolve(__dirname, 'src'), }, diff --git a/package.json b/package.json index 7d799e15..18ad2c4b 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,7 @@ "react-modal": "^3.12.1", "react-pro-sidebar": "^0.6.0", "react-scripts": "4.0.1", - "react-select": "^4.0.2", + "react-select": "^5.0.1", "react-spinners": "^0.10.4", "react-toggle": "^4.1.1", "react-tooltip": "^4.2.21", @@ -68,6 +68,8 @@ "@types/node": "^18.11.0", "@types/react": "^18.0.21", "@types/react-dom": "^18.0.6", + "@types/react-modal": "^3.13.1", + "@types/react-toggle": "^4.0.3", "@typescript-eslint/eslint-plugin": "^5.40.1", "@typescript-eslint/parser": "^5.40.1", "eslint-config-airbnb": "19.0.4", diff --git a/src/components/Header.js b/src/components/Header.js index 64890880..1d4f3aff 100644 --- a/src/components/Header.js +++ b/src/components/Header.js @@ -5,7 +5,7 @@ import { BsFillBookmarksFill } from 'react-icons/bs' import { ReactComponent as HackertabLogo } from '../logo.svg' import UserTags from './UserTags' import { SUPPORTED_SEARCH_ENGINES } from '../Constants' -import SettingsModal from '../settings/SettingsModal' +import { SettingsModal } from 'src/features/settings' import { BsMoon } from 'react-icons/bs' import { IoMdSunny } from 'react-icons/io' import { trackSearchEngineUse } from 'src/lib/analytics' @@ -15,7 +15,7 @@ import { GoSearch } from 'react-icons/go' function SearchBar({ state }) { const keywordsInputRef = React.useRef(null) const userSearchEngine = SUPPORTED_SEARCH_ENGINES.find( - (engine) => engine.label == state.searchEngine + (engine) => engine.label === state.searchEngine ) const handleSubmit = (e) => { diff --git a/src/settings/SettingsModal.js b/src/features/settings/components/SettingsModal.tsx similarity index 73% rename from src/settings/SettingsModal.js rename to src/features/settings/components/SettingsModal.tsx index 309901e2..ce5e2b8f 100644 --- a/src/settings/SettingsModal.js +++ b/src/features/settings/components/SettingsModal.tsx @@ -1,14 +1,14 @@ -import React, { useContext, useState } from "react"; -import ReactModal from 'react-modal'; -import "react-toggle/style.css" -import { VscClose } from "react-icons/vsc" -import Select from 'react-select' +import React, { useContext, useState } from 'react' +import ReactModal from 'react-modal' +import 'react-toggle/style.css' +import { VscClose } from 'react-icons/vsc' +import Select, { ActionMeta, MultiValue, SingleValue } from 'react-select' +import { SearchEngineType } from 'src/types' import Toggle from 'react-toggle' -import '../App.css'; -import './settings.css'; -import PreferencesContext from '../preferences/PreferencesContext'; -import ConfigurationContext from '../configuration/ConfigurationContext'; -import { SUPPORTED_CARDS, SUPPORTED_SEARCH_ENGINES, APP } from '../Constants' +import './settings.css' +import PreferencesContext from 'src/preferences/PreferencesContext' +import ConfigurationContext from 'src/configuration/ConfigurationContext' +import { SUPPORTED_CARDS, SUPPORTED_SEARCH_ENGINES, APP } from 'src/Constants' import { trackLanguageAdd, trackLanguageRemove, @@ -19,7 +19,17 @@ import { trackTabTarget, } from 'src/lib/analytics' -function SettingsModal({ showSettings, setShowSettings }) { +type SettingsModalProps = { + showSettings: boolean + setShowSettings: (show: boolean) => void +} + +type OptionType = { + value: string + label: string +} + +export const SettingsModal = ({ showSettings, setShowSettings }: SettingsModalProps) => { const { supportedTags } = useContext(ConfigurationContext) const preferences = useContext(PreferencesContext) const { dispatcher, cards, userSelectedTags, openLinksNewTab, listingMode, theme, searchEngine } = @@ -30,32 +40,41 @@ function SettingsModal({ showSettings, setShowSettings }) { setShowSettings(false) } - const onTagsSelectChange = (tags, metas) => { + const onTagsSelectChange = (tags: MultiValue, metas: ActionMeta) => { switch (metas.action) { case 'select-option': - trackLanguageAdd(metas.option.label) + if (metas.option?.label) { + trackLanguageAdd(metas.option.label) + } break case 'remove-value': - trackLanguageRemove(metas.removedValue.label) + if (metas.removedValue?.label) { + trackLanguageRemove(metas.removedValue.label) + } + break } dispatcher({ type: 'setUserSelectedTags', value: tags }) } - const onlistingModeChange = (e) => { + const onlistingModeChange = (e: React.ChangeEvent) => { const value = e.target.checked ? 'compact' : 'normal' trackListingModeSelect(value) dispatcher({ type: 'changelistingMode', value }) } - const onCardSelectChange = (cards, metas) => { + const onCardSelectChange = (cards: MultiValue, metas: ActionMeta) => { switch (metas.action) { case 'select-option': - trackSourceAdd(metas.option.label) + if (metas.option?.label) { + trackSourceAdd(metas.option.label) + } break case 'remove-value': - trackSourceRemove(metas.removedValue.label) + if (metas.removedValue?.label) { + trackSourceRemove(metas.removedValue.label) + } break } @@ -66,18 +85,22 @@ function SettingsModal({ showSettings, setShowSettings }) { dispatcher({ type: 'setCards', value: newCards }) } - const onSearchEngineSelectChange = (value) => { + const onSearchEngineSelectChange = (value: SingleValue) => { + if (!value) { + return + } + trackSearchEngineSelect(value.label) dispatcher({ type: 'setSearchEngine', value }) } - const onOpenLinksNewTabChange = (e) => { + const onOpenLinksNewTabChange = (e: React.ChangeEvent) => { const checked = e.target.checked trackTabTarget(checked) dispatcher({ type: 'setOpenLinksNewTab', value: checked }) } - const onDarkModeChange = (e) => { + const onDarkModeChange = () => { dispatcher({ type: 'toggleTheme' }) } @@ -127,7 +150,7 @@ function SettingsModal({ showSettings, setShowSettings }) { e.label == searchEngine)} + value={SUPPORTED_SEARCH_ENGINES.find((e) => e.label === searchEngine)} isMulti={false} isClearable={false} isSearchable={false} @@ -193,6 +216,5 @@ function SettingsModal({ showSettings, setShowSettings }) {
) + return
} - -export default SettingsModal diff --git a/src/settings/settings.css b/src/features/settings/components/settings.css similarity index 100% rename from src/settings/settings.css rename to src/features/settings/components/settings.css diff --git a/src/features/settings/index.ts b/src/features/settings/index.ts new file mode 100644 index 00000000..bcd0f2c8 --- /dev/null +++ b/src/features/settings/index.ts @@ -0,0 +1 @@ +export * from "./components/SettingsModal" \ No newline at end of file diff --git a/src/preferences/PreferencesContext.ts b/src/preferences/PreferencesContext.ts index c97145db..00e17b74 100644 --- a/src/preferences/PreferencesContext.ts +++ b/src/preferences/PreferencesContext.ts @@ -1,12 +1,33 @@ import React from 'react' -const PreferencesContext = React.createContext({ - userSelectedTags: [], - dispatcher: null, - changelogMeta: { - shown: false, - version: "", - } +type PreferencesContextProps = { + userSelectedTags: any[], + cards: any[], + openLinksNewTab: boolean, + listingMode: string, + searchEngine: string, + theme: string, + dispatcher: (value: any) => void; + changelogMeta: { + shown: boolean, + version: string + } +} + +const PreferencesContext = React.createContext({ + userSelectedTags: [], + listingMode: '', + theme: '', + searchEngine: '', + cards: [], + dispatcher: (value: any) => { + console.log("Not implemented") + }, + changelogMeta: { + shown: false, + version: "", + }, + openLinksNewTab: false, }); diff --git a/src/types/index.ts b/src/types/index.ts new file mode 100644 index 00000000..8b3da1c4 --- /dev/null +++ b/src/types/index.ts @@ -0,0 +1,4 @@ +export type SearchEngineType = { + url: string + label: string +} \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index 485db560..2027ef94 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1272,7 +1272,7 @@ resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.8.0.tgz#f580f9beb67176fa57aae70b08ed510e1b18980f" integrity sha512-G/YwXTkv7Den9mXDO7AhLWkE3q+I92B+VqAE+dYG4NGPaHZGvt3G8Q0p9vmE+sq7rTGphUbAvmQ9YpbfMQGGlA== -"@emotion/react@^11.1.1": +"@emotion/react@^11.8.1": version "11.10.4" resolved "https://registry.yarnpkg.com/@emotion/react/-/react-11.10.4.tgz#9dc6bccbda5d70ff68fdb204746c0e8b13a79199" integrity sha512-j0AkMpr6BL8gldJZ6XQsQ8DnS9TxEQu1R+OGmDZiWjBAJtCcbt0tS3I/YffoqHXxH6MjgI7KdMbYKw3MEiU9eA== @@ -1373,6 +1373,18 @@ minimatch "^3.0.4" strip-json-comments "^3.1.1" +"@floating-ui/core@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@floating-ui/core/-/core-1.0.1.tgz#00e64d74e911602c8533957af0cce5af6b2e93c8" + integrity sha512-bO37brCPfteXQfFY0DyNDGB3+IMe4j150KFQcgJ5aBP295p9nBGeHEs/p0czrRbtlHq4Px/yoPXO/+dOCcF4uA== + +"@floating-ui/dom@^1.0.1": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@floating-ui/dom/-/dom-1.0.3.tgz#b439c8a66436c2cae8d97e889f0b76cce757a6ec" + integrity sha512-6H1kwjkOZKabApNtXRiYHvMmYJToJ1DV7rQ3xc/WJpOABhQIOJJOdz2AOejj8X+gcybaFmBpisVTZxBZAM3V0w== + dependencies: + "@floating-ui/core" "^1.0.1" + "@gar/promisify@^1.0.1": version "1.1.3" resolved "https://registry.yarnpkg.com/@gar/promisify/-/promisify-1.1.3.tgz#555193ab2e3bb3b6adc3d551c9c030d9e860daf6" @@ -2210,6 +2222,27 @@ dependencies: "@types/react" "*" +"@types/react-modal@^3.13.1": + version "3.13.1" + resolved "https://registry.yarnpkg.com/@types/react-modal/-/react-modal-3.13.1.tgz#5b9845c205fccc85d9a77966b6e16dc70a60825a" + integrity sha512-iY/gPvTDIy6Z+37l+ibmrY+GTV4KQTHcCyR5FIytm182RQS69G5ps4PH2FxtC7bAQ2QRHXMevsBgck7IQruHNg== + dependencies: + "@types/react" "*" + +"@types/react-toggle@^4.0.3": + version "4.0.3" + resolved "https://registry.yarnpkg.com/@types/react-toggle/-/react-toggle-4.0.3.tgz#8db98ac8d2c5e8c03c2d3a42027555c1cd2289da" + integrity sha512-57QdMWeeQdRjM2/p+udgYerxUbSkmeUIW18kwUttcci6GHkgxoqCsDZfRtsCsAHcvvM5VBQdtDUEgLWo2e87mA== + dependencies: + "@types/react" "*" + +"@types/react-transition-group@^4.4.0": + version "4.4.5" + resolved "https://registry.yarnpkg.com/@types/react-transition-group/-/react-transition-group-4.4.5.tgz#aae20dcf773c5aa275d5b9f7cdbca638abc5e416" + integrity sha512-juKD/eiSM3/xZYzjuzH6ZwpP+/lejltmiS3QEzV/vmb/Q8+HfDmxu+Baga8UEMGBqV88Nbg4l2hY/K2DkyaLLA== + dependencies: + "@types/react" "*" + "@types/react@*", "@types/react@^18.0.21": version "18.0.21" resolved "https://registry.yarnpkg.com/@types/react/-/react-18.0.21.tgz#b8209e9626bb00a34c76f55482697edd2b43cc67" @@ -8165,10 +8198,10 @@ media-typer@0.3.0: resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" integrity sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ== -memoize-one@^5.0.0: - version "5.2.1" - resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-5.2.1.tgz#8337aa3c4335581839ec01c3d594090cebe8f00e" - integrity sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q== +memoize-one@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-6.0.0.tgz#b2591b871ed82948aee4727dc6abceeeac8c1045" + integrity sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw== memory-fs@^0.4.1: version "0.4.1" @@ -10107,7 +10140,7 @@ prompts@^2.0.1: kleur "^3.0.3" sisteransi "^1.0.5" -prop-types@^15.0.0, prop-types@^15.0.0-0, prop-types@^15.5.4, prop-types@^15.5.8, prop-types@^15.6.0, prop-types@^15.6.2, prop-types@^15.7.2, prop-types@^15.8.1: +prop-types@^15.0.0, prop-types@^15.0.0-0, prop-types@^15.5.4, prop-types@^15.6.0, prop-types@^15.6.2, prop-types@^15.7.2, prop-types@^15.8.1: version "15.8.1" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5" integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg== @@ -10355,13 +10388,6 @@ react-icons@^4.4.0: resolved "https://registry.yarnpkg.com/react-icons/-/react-icons-4.6.0.tgz#f83eda179af5d02c047449a20b702c858653d397" integrity sha512-rR/L9m9340yO8yv1QT1QurxWQvWpbNHqVX0fzMln2HEb9TEIrQRGsqiNFQfiv9/JEUbyHmHPlNTB2LWm2Ttz0g== -react-input-autosize@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/react-input-autosize/-/react-input-autosize-3.0.0.tgz#6b5898c790d4478d69420b55441fcc31d5c50a85" - integrity sha512-nL9uS7jEs/zu8sqwFE5MAPx6pPkNAriACQ2rGLlqmKr2sPGtN7TXTyDdQt4lbNXVx7Uzadb40x8qotIuru6Rhg== - dependencies: - prop-types "^15.5.8" - react-is@^16.13.1, react-is@^16.7.0: version "16.13.1" resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" @@ -10493,18 +10519,20 @@ react-scripts@4.0.1: optionalDependencies: fsevents "^2.1.3" -react-select@^4.0.2: - version "4.3.1" - resolved "https://registry.yarnpkg.com/react-select/-/react-select-4.3.1.tgz#389fc07c9bc7cf7d3c377b7a05ea18cd7399cb81" - integrity sha512-HBBd0dYwkF5aZk1zP81Wx5UsLIIT2lSvAY2JiJo199LjoLHoivjn9//KsmvQMEFGNhe58xyuOITjfxKCcGc62Q== +react-select@^5.0.1: + version "5.5.7" + resolved "https://registry.yarnpkg.com/react-select/-/react-select-5.5.7.tgz#87760030e6377a7ae3d0b1e419190af175ec2a0e" + integrity sha512-izQBXNhTPqXDw4gxzTbc9aLII4tCJ2pdMm6l/WVzKhfHm3RLErheqDNgeenU0XxzqbwT9swYO4CAYk5IzqLlYw== dependencies: "@babel/runtime" "^7.12.0" "@emotion/cache" "^11.4.0" - "@emotion/react" "^11.1.1" - memoize-one "^5.0.0" + "@emotion/react" "^11.8.1" + "@floating-ui/dom" "^1.0.1" + "@types/react-transition-group" "^4.4.0" + memoize-one "^6.0.0" prop-types "^15.6.0" - react-input-autosize "^3.0.0" react-transition-group "^4.3.0" + use-isomorphic-layout-effect "^1.1.2" react-slidedown@^2.4.5: version "2.4.7" @@ -12428,6 +12456,11 @@ url@^0.11.0: punycode "1.3.2" querystring "0.2.0" +use-isomorphic-layout-effect@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.1.2.tgz#497cefb13d863d687b08477d9e5a164ad8c1a6fb" + integrity sha512-49L8yCO3iGT/ZF9QttjwLF/ZD9Iwto5LnH5LmEdk/6cFmXddqi2ulF0edxTwjj+7mqvpVVGQWvbXZdn32wRSHA== + use-sync-external-store@1.2.0, use-sync-external-store@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz#7dbefd6ef3fe4e767a0cf5d7287aacfb5846928a" From 2f570b67f6da4a39cc63ffae0249a442c1e4a33c Mon Sep 17 00:00:00 2001 From: medyo Date: Fri, 28 Oct 2022 12:00:54 +0100 Subject: [PATCH 16/96] migrate placeholders to ts --- src/cards/ProductHuntCard.js | 2 +- src/components/ListComponent.js | 2 +- .../{Placeholder.js => placeholders/Placeholder.tsx} | 4 +--- .../ProductHuntPlaceholder.tsx} | 4 +--- src/components/placeholders/index.ts | 2 ++ 5 files changed, 6 insertions(+), 8 deletions(-) rename src/components/{Placeholder.js => placeholders/Placeholder.tsx} (87%) rename src/components/{ProductHuntPlaceholder.js => placeholders/ProductHuntPlaceholder.tsx} (85%) create mode 100644 src/components/placeholders/index.ts diff --git a/src/cards/ProductHuntCard.js b/src/cards/ProductHuntCard.js index 466ccb64..9b737f85 100644 --- a/src/cards/ProductHuntCard.js +++ b/src/cards/ProductHuntCard.js @@ -8,7 +8,7 @@ import PreferencesContext from '../preferences/PreferencesContext' import CardLink from '../components/CardLink' import CardItemWithActions from '../components/CardItemWithActions' import producthuntApi from '../services/producthunt' -import ProductHuntPlaceholder from '../components/ProductHuntPlaceholder' +import { ProductHuntPlaceholder } from '../components/placeholders' import { Attributes } from 'src/lib/analytics' const ProductItem = ({ item, index }) => { diff --git a/src/components/ListComponent.js b/src/components/ListComponent.js index b9faf818..ce81f51b 100644 --- a/src/components/ListComponent.js +++ b/src/components/ListComponent.js @@ -1,6 +1,6 @@ import React, { useState, useEffect } from 'react' import CarbonAd from '../features/carbonAds/components/CarbonAd' -import Placeholder from './Placeholder' +import { Placeholder } from 'src/components/placeholders' function ListComponent({ fetchData, refresh, renderItem, withAds, placeholder = }) { const [items, setItems] = useState([]) diff --git a/src/components/Placeholder.js b/src/components/placeholders/Placeholder.tsx similarity index 87% rename from src/components/Placeholder.js rename to src/components/placeholders/Placeholder.tsx index 2194adea..b347e6b7 100644 --- a/src/components/Placeholder.js +++ b/src/components/placeholders/Placeholder.tsx @@ -1,6 +1,6 @@ import React from 'react' -function Placeholder() { +export const Placeholder = () => { return (
@@ -13,5 +13,3 @@ function Placeholder() {
) } - -export default Placeholder diff --git a/src/components/ProductHuntPlaceholder.js b/src/components/placeholders/ProductHuntPlaceholder.tsx similarity index 85% rename from src/components/ProductHuntPlaceholder.js rename to src/components/placeholders/ProductHuntPlaceholder.tsx index 72d467dc..5f12a887 100644 --- a/src/components/ProductHuntPlaceholder.js +++ b/src/components/placeholders/ProductHuntPlaceholder.tsx @@ -1,6 +1,6 @@ import React from 'react' -function ProductHuntPlaceholder() { +export const ProductHuntPlaceholder = () => { return (
@@ -16,5 +16,3 @@ function ProductHuntPlaceholder() {
) } - -export default ProductHuntPlaceholder diff --git a/src/components/placeholders/index.ts b/src/components/placeholders/index.ts new file mode 100644 index 00000000..e5e12bc3 --- /dev/null +++ b/src/components/placeholders/index.ts @@ -0,0 +1,2 @@ +export * from "./Placeholder" +export * from "./ProductHuntPlaceholder" \ No newline at end of file From 46052d3440af3cd931286dbf76c032dae9c60f32 Mon Sep 17 00:00:00 2001 From: medyo Date: Fri, 28 Oct 2022 13:11:31 +0100 Subject: [PATCH 17/96] return data object from axios --- src/features/carbonAds/api/getAd.ts | 16 +++++++++++----- src/features/changelog/api/getVersions.ts | 2 +- src/lib/axios.ts | 4 +++- src/lib/interceptors/ResponseInterceptor.ts | 7 +++++++ 4 files changed, 22 insertions(+), 7 deletions(-) create mode 100644 src/lib/interceptors/ResponseInterceptor.ts diff --git a/src/features/carbonAds/api/getAd.ts b/src/features/carbonAds/api/getAd.ts index 8d64d9d1..c8601261 100644 --- a/src/features/carbonAds/api/getAd.ts +++ b/src/features/carbonAds/api/getAd.ts @@ -3,17 +3,23 @@ import { ExtractFnReturnType, QueryConfig } from 'src/lib/react-query'; import { Ad } from "../types"; import { axios } from 'src/lib/axios'; -const getAd = async (): Promise => { +type Response = { + ads: Ad[] +} + +const getAd = async (): Promise => { const userAgent = new URLSearchParams(navigator.userAgent).toString() - return axios.get('/monetization/', { + return axios.get('/monetization/', { params: { useragent: userAgent } }).then(response => { - if (response.data?.ads?.length) { - return response.data.ads[0]; - } + const data = response as unknown as Response; + if (!!data.ads.length) { + return data.ads[0]; + } + return null; }); } diff --git a/src/features/changelog/api/getVersions.ts b/src/features/changelog/api/getVersions.ts index bd9d683d..833408e9 100644 --- a/src/features/changelog/api/getVersions.ts +++ b/src/features/changelog/api/getVersions.ts @@ -7,7 +7,7 @@ const getAd = async (): Promise => { return axios.get('https://api.github.com/repos/medyo/hackertab.dev/releases') .then(response => { - const versions = response.data as unknown as Version[]; + const versions = response as unknown as Version[]; return versions }) } diff --git a/src/lib/axios.ts b/src/lib/axios.ts index af44a586..5e853e18 100644 --- a/src/lib/axios.ts +++ b/src/lib/axios.ts @@ -1,6 +1,8 @@ import Axios from 'axios'; import { getBaseApi } from 'src/utils/DataUtils' +import { ResponseInterceptor } from "./interceptors/ResponseInterceptor"; export const axios = Axios.create({ baseURL: getBaseApi(null) -}); \ No newline at end of file +}); +axios.interceptors.response.use(ResponseInterceptor); \ No newline at end of file diff --git a/src/lib/interceptors/ResponseInterceptor.ts b/src/lib/interceptors/ResponseInterceptor.ts new file mode 100644 index 00000000..e555b421 --- /dev/null +++ b/src/lib/interceptors/ResponseInterceptor.ts @@ -0,0 +1,7 @@ +import { AxiosResponse } from 'axios'; + +export const ResponseInterceptor = ( + response: AxiosResponse +): AxiosResponse => { + return response.data; +}; \ No newline at end of file From ccf28ce7a9642535623fee43775922abf0f868df Mon Sep 17 00:00:00 2001 From: medyo Date: Fri, 28 Oct 2022 13:12:22 +0100 Subject: [PATCH 18/96] remove unused showWidget --- src/App.js | 4 ++-- src/components/Footer.js | 10 +++------- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/src/App.js b/src/App.js index aaf88a9b..024c79fc 100644 --- a/src/App.js +++ b/src/App.js @@ -12,7 +12,7 @@ import PreferencesContext from './preferences/PreferencesContext' import { setupAnalytics, trackPageView, setupIdentification } from 'src/lib/analytics' function App() { - const { marketingBannerConfig = {}, feedbackWidget } = useContext(ConfigurationContext) + const { marketingBannerConfig = {} } = useContext(ConfigurationContext) const [showSideBar, setShowSideBar] = useState(false) const [showSettings, setShowSettings] = useState(false) const { dispatcher, ...state } = useContext(PreferencesContext) @@ -38,7 +38,7 @@ function App() { setShowSideBar(false)} /> -
+
) } diff --git a/src/components/Footer.js b/src/components/Footer.js index c247a655..942fde91 100644 --- a/src/components/Footer.js +++ b/src/components/Footer.js @@ -5,8 +5,6 @@ import { HiLightBulb } from 'react-icons/hi' import { trackPageView } from 'src/lib/analytics' function Footer({ feedbackWidget }) { - const { show: showFeedbackWidget } = feedbackWidget || { show: false } - const onSourceCodeClick = () => { trackPageView('Source Code') window.open(APP.repository, '_blank') @@ -32,11 +30,9 @@ function Footer({ feedbackWidget }) { return (