From ef24e724d8353b694def04e3b8fe4a74e198607f Mon Sep 17 00:00:00 2001 From: Yasuaki Uechi Date: Thu, 26 Mar 2020 20:22:06 +0900 Subject: [PATCH] feat: add uniqueness indicator --- web/package.json | 3 +- web/public/locales/en/translation.json | 5 + web/public/locales/ja/translation.json | 5 + web/src/App.tsx | 37 +++- web/src/components/cards/core.tsx | 31 +-- .../components/cards/providers/Cratesio.tsx | 1 + web/src/components/cards/providers/Linux.tsx | 2 + web/src/components/cards/providers/Ocaml.tsx | 1 + web/src/index.tsx | 24 ++- web/src/store.tsx | 36 ++++ web/src/util/analytics.ts | 5 +- web/src/util/i18n.ts | 2 +- yarn.lock | 193 ++++++++++++++++-- 13 files changed, 297 insertions(+), 48 deletions(-) create mode 100644 web/src/store.tsx diff --git a/web/package.json b/web/package.json index ed32607..74a036d 100644 --- a/web/package.json +++ b/web/package.json @@ -12,6 +12,7 @@ }, "dependencies": { "@sentry/browser": "^5.15.0", + "easy-peasy": "^3.3.0", "fetch-suspense": "^1.2.2", "framer-motion": "^1.10.2", "i18next": ">=19.3.3", @@ -21,6 +22,7 @@ "i18next-xhr-backend": "^3.2.2", "isomorphic-unfetch": "^3.0.0", "prop-types": "^15.7.2", + "rc-tooltip": "^4.0.3", "react": "^16.13.1", "react-dom": "^16.13.1", "react-ga": "^2.7.0", @@ -31,7 +33,6 @@ "react-router-dom": "^5.1.2", "react-scripts": "3.4.1", "react-spinners": "^0.8.1", - "react-tippy": "^1.3.4", "styled-components": "^5.0.1" }, "devDependencies": { diff --git a/web/public/locales/en/translation.json b/web/public/locales/en/translation.json index 93484e7..b0c2dd8 100644 --- a/web/public/locales/en/translation.json +++ b/web/public/locales/en/translation.json @@ -27,6 +27,11 @@ "nta": "Company (JP)", "ocaml": "OCaml" }, + "uniqueness": { + "high": "Pretty unique", + "moderate": "Moderately unique", + "low": "Not so unique" + }, "countryCode": "us", "try": "How about this?", "showMore": "show more", diff --git a/web/public/locales/ja/translation.json b/web/public/locales/ja/translation.json index c6298da..1fcee2e 100644 --- a/web/public/locales/ja/translation.json +++ b/web/public/locales/ja/translation.json @@ -27,6 +27,11 @@ "nta": "法人", "ocaml": "OCaml" }, + "uniqueness": { + "high": "とてもユニーク", + "moderate": "そこそこユニーク", + "low": "あまりユニークではない" + }, "countryCode": "jp", "try": "これはどう?", "showMore": "もっと見る", diff --git a/web/src/App.tsx b/web/src/App.tsx index 9f69178..276ad24 100644 --- a/web/src/App.tsx +++ b/web/src/App.tsx @@ -8,18 +8,18 @@ import {IoIosRocket, IoIosFlash} from 'react-icons/io'; import Welcome from './components/Welcome'; import Form from './components/Form'; import Cards from './components/cards'; +import Footer from './components/Footer'; import { ResultItem, ResultIcon, ResultName, - COLORS, + COLORS as ResultColor, AvailableIcon, } from './components/cards/core'; -import Footer from './components/Footer'; - import {mobile} from './util/css'; import {isStandalone} from './util/pwa'; import {sanitize} from './util/text'; +import {useStoreState} from './store'; export default function App() { return ( @@ -74,7 +74,8 @@ function Search() { - + + @@ -83,7 +84,7 @@ function Search() { - + @@ -96,6 +97,24 @@ function Search() { ); } +function Stat() { + const totalCount = useStoreState((state) => state.stats.totalCount); + const availableCount = useStoreState((state) => state.stats.availableCount); + const {t} = useTranslation(); + + const uniqueness = ((n) => { + if (n > 0.7 && n <= 1.0) { + return t('uniqueness.high'); + } else if (n > 0.4 && n <= 0.7) { + return t('uniqueness.moderate'); + } else { + return t('uniqueness.low'); + } + })(availableCount / totalCount); + + return {uniqueness}; +} + const GlobalStyle = createGlobalStyle` * { box-sizing: border-box; @@ -150,12 +169,18 @@ const Legend = styled.div` background-color: #f6f6fa; ${mobile} { + flex-direction: column; + align-items: center; margin-top: -80px; padding: 70px 0 30px; background-color: none; } - ${ResultItem} { + > * { margin: 0 10px 0; } `; + +const UniquenessIndicator = styled.div` + color: #7b7b7b; +`; diff --git a/web/src/components/cards/core.tsx b/web/src/components/cards/core.tsx index 915b88d..17cecea 100644 --- a/web/src/components/cards/core.tsx +++ b/web/src/components/cards/core.tsx @@ -1,8 +1,8 @@ import React, {useState, useEffect, Suspense} from 'react'; import styled from 'styled-components'; import useFetch from 'fetch-suspense'; -import {Tooltip} from 'react-tippy'; -import 'react-tippy/dist/tippy.css'; +import Tooltip from 'rc-tooltip'; +import 'rc-tooltip/assets/bootstrap.css'; import BarLoader from 'react-spinners/BarLoader'; import {GoInfo} from 'react-icons/go'; import {IoIosFlash} from 'react-icons/io'; @@ -11,6 +11,7 @@ import {OutboundLink} from 'react-ga'; import {sendError, sendExpandEvent} from '../../util/analytics'; import {mobile} from '../../util/css'; +import {useStoreActions} from '../../store'; export const COLORS = { available: '#6e00ff', @@ -105,6 +106,7 @@ export const DedicatedAvailability: React.FC<{ suffix = '', icon, }) => { + const increaseCounter = useStoreActions((actions) => actions.stats.add); const response = useFetch( `/availability/${service}/${encodeURIComponent(query || name)}`, ) as Response; @@ -113,6 +115,10 @@ export const DedicatedAvailability: React.FC<{ throw new APIError(`${service}: ${response.error}`); } + useEffect(() => { + increaseCounter(response.availability); + }, []); + return ( { + const increaseCounter = useStoreActions((actions) => actions.stats.add); const response = useFetch(target, undefined, {metadata: true}); if (response.status !== 404 && response.status !== 200) { @@ -155,6 +162,10 @@ export const ExistentialAvailability: React.FC<{ const availability = response.status === 404; + useEffect(() => { + increaseCounter(availability); + }, []); + return ( - + {icon} @@ -266,13 +271,11 @@ class ErrorBoundary extends React.Component< return ( diff --git a/web/src/components/cards/providers/Cratesio.tsx b/web/src/components/cards/providers/Cratesio.tsx index 26153f5..e18d215 100644 --- a/web/src/components/cards/providers/Cratesio.tsx +++ b/web/src/components/cards/providers/Cratesio.tsx @@ -19,6 +19,7 @@ const CratesioCard: React.FC<{query: string}> = ({query}) => { query={`crates.io/api/v1/crates/${name}`} service="existence" link={`https://crates.io/crates/${name}`} + message="Go to crates.io" icon={} /> )} diff --git a/web/src/components/cards/providers/Linux.tsx b/web/src/components/cards/providers/Linux.tsx index 8170ab2..35054ff 100644 --- a/web/src/components/cards/providers/Linux.tsx +++ b/web/src/components/cards/providers/Linux.tsx @@ -19,12 +19,14 @@ const LinuxCard: React.FC<{query: string}> = ({query}) => { } /> } /> diff --git a/web/src/components/cards/providers/Ocaml.tsx b/web/src/components/cards/providers/Ocaml.tsx index fe8791d..d846c1d 100644 --- a/web/src/components/cards/providers/Ocaml.tsx +++ b/web/src/components/cards/providers/Ocaml.tsx @@ -18,6 +18,7 @@ const OcamlCard: React.FC<{query: string}> = ({query}) => { name={name} query={`opam.ocaml.org/packages/${name}/`} service="existence" + message="Go to opam" link={`https://opam.ocaml.org/packages/${name}/`} icon={} /> diff --git a/web/src/index.tsx b/web/src/index.tsx index 210280a..e4bfcaf 100644 --- a/web/src/index.tsx +++ b/web/src/index.tsx @@ -1,25 +1,35 @@ import React from 'react'; import ReactDOM from 'react-dom'; import {Router} from 'react-router-dom'; +import {StoreProvider, createStore} from 'easy-peasy'; +import {createBrowserHistory} from 'history'; import App from './App'; import * as serviceWorker from './serviceWorker'; import {FullScreenSuspense} from './util/suspense'; -import {initHistoryWithGA, initSentry} from './util/analytics'; +import {wrapHistoryWithGA, initSentry} from './util/analytics'; import {initCrisp} from './util/crip'; +import {storeModel} from './store'; import './util/i18n'; initSentry(); initCrisp(); -const history = initHistoryWithGA(); +const store = createStore(storeModel); +const history = wrapHistoryWithGA(createBrowserHistory()); +history.listen(() => { + // reset stats counter + store.getActions().stats.reset(); +}); ReactDOM.render( - - - - - , + + + + + + + , document.getElementById('root'), ); diff --git a/web/src/store.tsx b/web/src/store.tsx new file mode 100644 index 0000000..8784330 --- /dev/null +++ b/web/src/store.tsx @@ -0,0 +1,36 @@ +import {action, createTypedHooks, Action} from 'easy-peasy'; + +interface StatsModel { + availableCount: number; + totalCount: number; + add: Action; + reset: Action; +} + +interface StoreModel { + stats: StatsModel; +} + +const statsModel: StatsModel = { + availableCount: 0, + totalCount: 0, + add: action((state, isAvailable) => { + state.totalCount += 1; + if (isAvailable) { + state.availableCount += 1; + } + }), + reset: action((state) => { + state.totalCount = 0; + state.availableCount = 0; + }), +}; + +export const storeModel: StoreModel = { + stats: statsModel, +}; + +const typedHooks = createTypedHooks(); +export const useStoreActions = typedHooks.useStoreActions; +export const useStoreDispatch = typedHooks.useStoreDispatch; +export const useStoreState = typedHooks.useStoreState; diff --git a/web/src/util/analytics.ts b/web/src/util/analytics.ts index e637f2c..57f3c49 100644 --- a/web/src/util/analytics.ts +++ b/web/src/util/analytics.ts @@ -1,11 +1,10 @@ import ReactGA from 'react-ga'; import * as Sentry from '@sentry/browser'; -import {createBrowserHistory} from 'history'; +import {History} from 'history'; const isProduction = process.env.NODE_ENV !== 'development'; -export function initHistoryWithGA() { - const history = createBrowserHistory(); +export function wrapHistoryWithGA(history: History) { if (isProduction) { ReactGA.initialize('UA-28919359-15'); ReactGA.pageview(window.location.pathname + window.location.search); diff --git a/web/src/util/i18n.ts b/web/src/util/i18n.ts index cf16117..f8adbef 100644 --- a/web/src/util/i18n.ts +++ b/web/src/util/i18n.ts @@ -5,7 +5,7 @@ import XHR from 'i18next-xhr-backend'; import LanguageDetector from 'i18next-browser-languagedetector'; import {initReactI18next} from 'react-i18next'; -const TRANSLATION_VERSION = '1.13'; +const TRANSLATION_VERSION = '1.14'; i18n .use(Backend) diff --git a/yarn.lock b/yarn.lock index 920d7bc..706969c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2015,6 +2015,13 @@ acorn@^7.1.1: resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.1.1.tgz#e35668de0b402f359de515c5482a1ab9f89a69bf" integrity sha512-add7dgA5ppRPxCFJoAGfMDi7PIBXq1RtGo7BhbLaxwrXPOmw8gq48Y9ozT01hUKy9byMjlR20EJhu5zlkErEkg== +add-dom-event-listener@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/add-dom-event-listener/-/add-dom-event-listener-1.1.0.tgz#6a92db3a0dd0abc254e095c0f1dc14acbbaae310" + integrity sha512-WCxx1ixHT0GQU9hb0KI/mhgRQhnU+U3GvwY6ZvVjYq8rsihIGoaIOUbY0yMPBxLH5MDtr0kz3fisWGNcbWW7Jw== + dependencies: + object-assign "4.x" + address@1.1.2, address@^1.0.1: version "1.1.2" resolved "https://registry.yarnpkg.com/address/-/address-1.1.2.tgz#bf1116c9c758c51b7a933d296b72c221ed9428b6" @@ -2543,7 +2550,7 @@ babel-preset-react-app@^9.1.2: babel-plugin-macros "2.8.0" babel-plugin-transform-react-remove-prop-types "0.4.24" -babel-runtime@^6.26.0: +babel-runtime@6.x, babel-runtime@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe" integrity sha1-llxwWGaOgrVde/4E/yM3vItWR/4= @@ -3145,6 +3152,11 @@ class-utils@^0.3.5: isobject "^3.0.0" static-extend "^0.1.1" +classnames@2.x, classnames@^2.2.6: + version "2.2.6" + resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.2.6.tgz#43935bffdd291f326dad0a205309b38d00f650ce" + integrity sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q== + clean-css@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-4.2.3.tgz#507b5de7d97b48ee53d84adb0160ff6216380f78" @@ -3333,11 +3345,23 @@ compare-versions@^3.5.1: resolved "https://registry.yarnpkg.com/compare-versions/-/compare-versions-3.6.0.tgz#1a5689913685e5a87637b8d3ffca75514ec41d62" integrity sha512-W6Af2Iw1z4CB7q4uU4hv646dW9GQuBM+YpC0UvUCWSD8w90SJjp+ujJuXaEMtAXBtSqGfMPuFOVn4/+FlaqfBA== +component-classes@^1.2.5: + version "1.2.6" + resolved "https://registry.yarnpkg.com/component-classes/-/component-classes-1.2.6.tgz#c642394c3618a4d8b0b8919efccbbd930e5cd691" + integrity sha1-xkI5TDYYpNiwuJGe/Mu9kw5c1pE= + dependencies: + component-indexof "0.0.3" + component-emitter@^1.2.1: version "1.3.0" resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0" integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg== +component-indexof@0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/component-indexof/-/component-indexof-0.0.3.tgz#11d091312239eb8f32c8f25ae9cb002ffe8d3c24" + integrity sha1-EdCRMSI5648yyPJa6csAL/6NPCQ= + compose-function@3.0.3: version "3.0.3" resolved "https://registry.yarnpkg.com/compose-function/-/compose-function-3.0.3.tgz#9ed675f13cc54501d30950a486ff6a7ba3ab185f" @@ -3581,6 +3605,14 @@ crypto-browserify@^3.11.0: randombytes "^2.0.0" randomfill "^1.0.3" +css-animation@^1.3.2: + version "1.6.1" + resolved "https://registry.yarnpkg.com/css-animation/-/css-animation-1.6.1.tgz#162064a3b0d51f958b7ff37b3d6d4de18e17039e" + integrity sha512-/48+/BaEaHRY6kNQ2OIPzKf9A6g8WjZYjhiNDNuIVbsm5tXCGIAsHDjB4Xu1C4vXJtUWZo26O68OQkDpNBaPog== + dependencies: + babel-runtime "6.x" + component-classes "^1.2.5" + css-blank-pseudo@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/css-blank-pseudo/-/css-blank-pseudo-0.1.4.tgz#dfdefd3254bf8a82027993674ccf35483bfcb3c5" @@ -3855,6 +3887,11 @@ data-urls@^1.0.0, data-urls@^1.1.0: whatwg-mimetype "^2.2.0" whatwg-url "^7.0.0" +debounce@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/debounce/-/debounce-1.2.0.tgz#44a540abc0ea9943018dc0eaa95cce87f65cd131" + integrity sha512-mYtLl1xfZLi1m4RtQYlZgJUNQjl4ZxVnHzIR8nLLgi4q1YT8o/WM+MK/f8yfcc9s5Ir5zRaPZyZU6xs1Syoocg== + debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.0, debug@^2.6.9: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" @@ -4102,6 +4139,11 @@ dom-accessibility-api@^0.4.2: resolved "https://registry.yarnpkg.com/dom-accessibility-api/-/dom-accessibility-api-0.4.3.tgz#93ca9002eb222fd5a343b6e5e6b9cf5929411c4c" integrity sha512-JZ8iPuEHDQzq6q0k7PKMGbrIdsgBB7TRrtVOUm4nSMCExlg5qQG4KXWTH2k90yggjM4tTumRGwTKJSldMzKyLA== +dom-align@^1.7.0: + version "1.11.1" + resolved "https://registry.yarnpkg.com/dom-align/-/dom-align-1.11.1.tgz#7592be99a660a36cdedc1d6eeb22b8109d758cae" + integrity sha512-hN42DmUgtweBx0iBjDLO4WtKOMcK8yBmPx/fgdsgQadLuzPu/8co3oLdK5yMmeM/vnUd3yDyV6qV8/NzxBexQg== + dom-converter@^0.2: version "0.2.0" resolved "https://registry.yarnpkg.com/dom-converter/-/dom-converter-0.2.0.tgz#6721a9daee2e293682955b6afe416771627bb768" @@ -4214,6 +4256,21 @@ duplexify@^3.4.2, duplexify@^3.6.0: readable-stream "^2.0.0" stream-shift "^1.0.0" +easy-peasy@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/easy-peasy/-/easy-peasy-3.3.0.tgz#1ae7cbaa834dad5aa404f1437726fb8c0eed3cef" + integrity sha512-wkTDAG+nRy+4g8Z3/k1vuTyrhxet19oY5MCmuRgOObm8dtZ2m+g5Mk/sdf3UWPuyx/sKIYH5Fy/HXab8iNKjTQ== + dependencies: + debounce "^1.2.0" + immer-peasy "3.1.3" + is-plain-object "^3.0.0" + memoizerific "^1.11.3" + prop-types "^15.6.2" + redux "^4.0.5" + redux-thunk "^2.3.0" + symbol-observable "^1.2.0" + ts-toolbelt "^6.1.6" + ecc-jsbn@~0.1.1: version "0.1.2" resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" @@ -5853,6 +5910,11 @@ ignore@^5.1.4: resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.4.tgz#84b7b3dbe64552b6ef0eca99f6743dbec6d97adf" integrity sha512-MzbUSahkTW1u7JpKKjY7LCARd1fU5W2rLdxlM4kdkayuCwZImjkpluF9CM1aLewYJguPDqewLam18Y6AU69A8A== +immer-peasy@3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/immer-peasy/-/immer-peasy-3.1.3.tgz#d0ea8d388f47ec6b15ab2ca19ffb9f0bf4310110" + integrity sha512-WzoZ96A93jOmcDOLNChMWAqy+ZU8vEYQx2DcKjgo7P5SToiJs+GL+5yQbWzH8X02Lhvv6xrGgVNa1xbki66Eow== + immer@1.10.0: version "1.10.0" resolved "https://registry.yarnpkg.com/immer/-/immer-1.10.0.tgz#bad67605ba9c810275d91e1c2a47d4582e98286d" @@ -6273,6 +6335,13 @@ is-plain-object@^2.0.1, is-plain-object@^2.0.3, is-plain-object@^2.0.4: dependencies: isobject "^3.0.1" +is-plain-object@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-3.0.0.tgz#47bfc5da1b5d50d64110806c199359482e75a928" + integrity sha512-tZIpofR+P05k8Aocp7UI/2UTa9lTJSebCXpFFoR9aibpokDj/uXBsJ8luUu0tTVYKkMU6URDUuOfJZ7koewXvg== + dependencies: + isobject "^4.0.0" + is-promise@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa" @@ -6404,6 +6473,11 @@ isobject@^3.0.0, isobject@^3.0.1: resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8= +isobject@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-4.0.0.tgz#3f1c9155e73b192022a80819bacd0343711697b0" + integrity sha512-S/2fF5wH8SJA/kmwr6HYhK/RI/OkhD84k8ntalo0iJjZikgq1XFvR5M8NPT1x5F7fBwCG3qHfnzeP/Vh/ZxCUA== + isomorphic-unfetch@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/isomorphic-unfetch/-/isomorphic-unfetch-3.0.0.tgz#de6d80abde487b17de2c400a7ef9e5ecc2efb362" @@ -7400,6 +7474,11 @@ map-cache@^0.2.2: resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" integrity sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8= +map-or-similar@^1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/map-or-similar/-/map-or-similar-1.5.0.tgz#6de2653174adfb5d9edc33c69d3e92a1b76faf08" + integrity sha1-beJlMXSt+12e3DPGnT6Sobdvrwg= + map-visit@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f" @@ -7440,6 +7519,13 @@ mem@^4.0.0: mimic-fn "^2.0.0" p-is-promise "^2.0.0" +memoizerific@^1.11.3: + version "1.11.3" + resolved "https://registry.yarnpkg.com/memoizerific/-/memoizerific-1.11.3.tgz#7c87a4646444c32d75438570905f2dbd1b1a805a" + integrity sha1-fIekZGREwy11Q4VwkF8tvRsagFo= + dependencies: + map-or-similar "^1.5.0" + memory-fs@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.4.1.tgz#3a9a20b8462523e447cfbc7e8bb80ed667bfc552" @@ -8014,7 +8100,7 @@ oauth-sign@~0.9.0: resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== -object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1: +object-assign@4.x, object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= @@ -8660,11 +8746,6 @@ popmotion@9.0.0-beta-8: style-value-types "^3.1.6" tslib "^1.10.0" -popper.js@^1.11.1: - version "1.16.1" - resolved "https://registry.yarnpkg.com/popper.js/-/popper.js-1.16.1.tgz#2a223cb3dc7b6213d740e40372be40de43e65b1b" - integrity sha512-Wb4p1J4zyFTbM+u6WuO4XstYx4Ky9Cewe4DWrel7B0w6VVICvPwdOpotjzcf6eD8TsckVnIMNONQyPIUFOUbCQ== - portfinder@^1.0.25: version "1.0.25" resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.25.tgz#254fd337ffba869f4b9d37edc298059cb4d35eca" @@ -9445,7 +9526,7 @@ prompts@^2.0.1: kleur "^3.0.3" sisteransi "^1.0.4" -prop-types@^15.5.4, prop-types@^15.6.2, prop-types@^15.7.2: +prop-types@15.x, prop-types@^15.5.10, prop-types@^15.5.4, prop-types@^15.6.2, prop-types@^15.7.2: version "15.7.2" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5" integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ== @@ -9572,7 +9653,7 @@ querystringify@^2.1.1: resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.1.1.tgz#60e5a5fd64a7f8bfa4d2ab2ed6fdf4c85bad154e" integrity sha512-w7fLxIRCRT7U8Qu53jQnJyPkYZIaR4n5151KMfcJlO/A9397Wxb1amJvROTK6TOnp7PfoAmg/qXiNHI+08jRfA== -raf@^3.4.1: +raf@^3.4.0, raf@^3.4.1: version "3.4.1" resolved "https://registry.yarnpkg.com/raf/-/raf-3.4.1.tgz#0742e99a4a6552f445d73e3ee0328af0ff1ede39" integrity sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA== @@ -9609,6 +9690,60 @@ raw-body@2.4.0: iconv-lite "0.4.24" unpipe "1.0.0" +rc-align@^3.0.0-rc.0: + version "3.0.0-rc.1" + resolved "https://registry.yarnpkg.com/rc-align/-/rc-align-3.0.0-rc.1.tgz#32d1fac860d12bb85e9b8cafbbdef79f3f537674" + integrity sha512-GbofumhCUb7SxP410j/fbtR2M9Zml+eoZSdaliZh6R3NhfEj5zP4jcO3HG3S9C9KIcXQQtd/cwVHkb9Y0KU7Hg== + dependencies: + classnames "2.x" + dom-align "^1.7.0" + rc-util "^4.12.0" + resize-observer-polyfill "^1.5.1" + +rc-animate@^2.10.2: + version "2.10.3" + resolved "https://registry.yarnpkg.com/rc-animate/-/rc-animate-2.10.3.tgz#163d5e29281a4ff82d53ee7918eeeac856b756f9" + integrity sha512-A9qQ5Y8BLlM7EhuCO3fWb/dChndlbWtY/P5QvPqBU7h4r5Q2QsvsbpTGgdYZATRDZbTRnJXXfVk9UtlyS7MBLg== + dependencies: + babel-runtime "6.x" + classnames "^2.2.6" + css-animation "^1.3.2" + prop-types "15.x" + raf "^3.4.0" + rc-util "^4.15.3" + react-lifecycles-compat "^3.0.4" + +rc-tooltip@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/rc-tooltip/-/rc-tooltip-4.0.3.tgz#728b760863643ec2e85827a2e7fb28d961b3b759" + integrity sha512-HNyBh9/fPdds0DXja8JQX0XTIHmZapB3lLzbdn74aNSxXG1KUkt+GK4X1aOTRY5X9mqm4uUKdeFrn7j273H8gw== + dependencies: + rc-trigger "^4.0.0" + +rc-trigger@^4.0.0: + version "4.0.2" + resolved "https://registry.yarnpkg.com/rc-trigger/-/rc-trigger-4.0.2.tgz#42fe7bdb6a5b34035e20fa9ebfad69ec948b56be" + integrity sha512-to5S1NhK10rWHIgQpoQdwIhuDc2Ok4R4/dh5NLrDt6C+gqkohsdBCYiPk97Z+NwGhRU8N+dbf251bivX8DkzQg== + dependencies: + classnames "^2.2.6" + prop-types "15.x" + raf "^3.4.1" + rc-align "^3.0.0-rc.0" + rc-animate "^2.10.2" + rc-util "^4.20.0" + +rc-util@^4.12.0, rc-util@^4.15.3, rc-util@^4.20.0: + version "4.20.1" + resolved "https://registry.yarnpkg.com/rc-util/-/rc-util-4.20.1.tgz#a5976eabfc3198ed9b8e79ffb8c53c231db36e77" + integrity sha512-EGlDg9KPN0POzmAR2hk9ZyFc3DmJIrXwlC8NoDxJguX2LTINnVqwadLIVauLfYgYISMiFYFrSHiFW+cqUhZ5dA== + dependencies: + add-dom-event-listener "^1.1.0" + babel-runtime "6.x" + prop-types "^15.5.10" + react-is "^16.12.0" + react-lifecycles-compat "^3.0.4" + shallowequal "^1.1.0" + rc@^1.2.8: version "1.2.8" resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" @@ -9716,6 +9851,11 @@ react-is@^16.12.0, react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.1, react-i resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== +react-lifecycles-compat@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362" + integrity sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA== + react-router-dom@^5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-5.1.2.tgz#06701b834352f44d37fbb6311f870f84c76b9c18" @@ -9819,13 +9959,6 @@ react-spinners@^0.8.1: dependencies: "@emotion/core" "^10.0.15" -react-tippy@^1.3.4: - version "1.3.4" - resolved "https://registry.yarnpkg.com/react-tippy/-/react-tippy-1.3.4.tgz#9db14375ef696017d33aaf24b444b3dbb0168b2a" - integrity sha512-56eLAtcNoRBOmMessnm3U6PF//OqbqKp1oxwjoOwi/JKqo/y132zNcIl8QQCMnS6ITa3c6ZVaRAq4K1FGhloJQ== - dependencies: - popper.js "^1.11.1" - react@^16.13.1: version "16.13.1" resolved "https://registry.yarnpkg.com/react/-/react-16.13.1.tgz#2e818822f1a9743122c063d6410d85c1e3afe48e" @@ -9929,6 +10062,19 @@ redent@^3.0.0: indent-string "^4.0.0" strip-indent "^3.0.0" +redux-thunk@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/redux-thunk/-/redux-thunk-2.3.0.tgz#51c2c19a185ed5187aaa9a2d08b666d0d6467622" + integrity sha512-km6dclyFnmcvxhAcrQV2AkZmPQjzPDjgVlQtR0EQjxZPyJ0BnMf3in1ryuR8A2qU0HldVRfxYXbFSKlI3N7Slw== + +redux@^4.0.5: + version "4.0.5" + resolved "https://registry.yarnpkg.com/redux/-/redux-4.0.5.tgz#4db5de5816e17891de8a80c424232d06f051d93f" + integrity sha512-VSz1uMAH24DM6MF72vcojpYPtrTUu3ByVWfPL1nPfVRb5mZVTve5GnNCUV53QM/BZ66xfWrm0CTWoM+Xlz8V1w== + dependencies: + loose-envify "^1.4.0" + symbol-observable "^1.2.0" + regenerate-unicode-properties@^8.2.0: version "8.2.0" resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-8.2.0.tgz#e5de7111d655e7ba60c057dbe9ff37c87e65cdec" @@ -10131,6 +10277,11 @@ requires-port@^1.0.0: resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" integrity sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8= +resize-observer-polyfill@^1.5.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz#0e9020dd3d21024458d4ebd27e23e40269810464" + integrity sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg== + resolve-cwd@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-2.0.0.tgz#00a9f7387556e27038eae232caa372a6a59b665a" @@ -11178,6 +11329,11 @@ swap-case@^1.1.0: lower-case "^1.1.1" upper-case "^1.1.1" +symbol-observable@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.2.0.tgz#c22688aed4eab3cdc2dfeacbb561660560a00804" + integrity sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ== + symbol-tree@^3.2.2: version "3.2.4" resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2" @@ -11417,6 +11573,11 @@ ts-pnp@1.1.6, ts-pnp@^1.1.6: resolved "https://registry.yarnpkg.com/ts-pnp/-/ts-pnp-1.1.6.tgz#389a24396d425a0d3162e96d2b4638900fdc289a" integrity sha512-CrG5GqAAzMT7144Cl+UIFP7mz/iIhiy+xQ6GGcnjTezhALT02uPMRw7tgDSESgB5MsfKt55+GPWw4ir1kVtMIQ== +ts-toolbelt@^6.1.6: + version "6.3.6" + resolved "https://registry.yarnpkg.com/ts-toolbelt/-/ts-toolbelt-6.3.6.tgz#2bde29106c013ed520c32f30e1248daf8fd4f5f9" + integrity sha512-eVzym+LyQodOCfyVyQDQ6FGYbO2Xf9Nc4dGLRKlKSUpAs+8qQWHG+grDiA3ciEuNPNZ0qJnNIYkdqBW1rCWuUA== + tslib@^1.10.0, tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3: version "1.11.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.11.1.tgz#eb15d128827fbee2841549e171f45ed338ac7e35"