From 7c9e877ca97b3782d4cb8208010840c06d716260 Mon Sep 17 00:00:00 2001 From: Teto Gomez Date: Mon, 27 Sep 2021 13:17:38 -0600 Subject: [PATCH 01/15] Refactor webapp (#794) * fix(webapp): refactor webapp project * fix(webapp): add components and refactor sidebar * fix(webapp): stable version with all pages * fix(webapp): mui migration v4 - v5 * fix(webapp): refactor compare tool and madele user data * fix(webapp): refactor chip avatar and finish compare styling * fix(webapp): remove radar component and create polar chart * fix(webapp): finish mobile ui for bp flow and bussines logic to vote * fix(webapp): Add styling eosrate webapp and add reponsive grid pages * fix(webapp): Add margin auto for lg breakpoint * fix(webapp): code review --- .env.example | 4 + hapi/src/libs/sync-bps.js | 10 +- hapi/src/libs/sync-proxies.js | 30 +- hapi/yarn.lock | 12 +- hasura/metadata/actions.graphql | 25 +- .../default/tables/public_producers.yaml | 1 + .../default/tables/public_proxies.yaml | 1 + .../down.sql | 4 + .../up.sql | 2 + .../down.sql | 4 + .../up.sql | 2 + webapp/.babelrc | 16 + webapp/.prettierrc | 13 + webapp/config-overrides.js | 18 +- webapp/jsconfig.json | 6 - webapp/package.json | 90 +- webapp/public/index.html | 7 +- webapp/src/App.test.js | 11 + webapp/src/app.js | 65 +- .../{bp-chip-avatar => BpChipAvatar}/index.js | 13 +- webapp/src/components/BpChipAvatar/styles.js | 9 + webapp/src/components/{card => Card}/index.js | 130 +- .../src/components/{card => Card}/styles.js | 83 +- .../CompareTool/CompareGraphView.js | 275 ++++ .../CompareTool/CompareSliderView.js | 84 ++ .../{compare-tool => CompareTool}/index.js | 95 +- webapp/src/components/CompareTool/styles.js | 277 ++++ .../{main-footer => Footer}/index.js | 34 +- webapp/src/components/Footer/styles.js | 38 + webapp/src/components/Header/index.js | 144 ++ webapp/src/components/Header/styles.js | 92 ++ .../index.js | 115 +- .../components/InputAutocomplete/styles.js | 61 + webapp/src/components/Loader/index.js | 20 + webapp/src/components/Loader/styles.js | 8 + webapp/src/components/Message/index.js | 48 + webapp/src/components/Message/styles.js | 8 + .../{mobile-search => MobileSearch}/index.js | 21 +- .../{mobile-search => MobileSearch}/styles.js | 0 webapp/src/components/PageTitle/index.js | 21 + .../index.js | 4 +- .../style.css | 0 webapp/src/components/PolarChart/index.js | 38 + webapp/src/components/PolarChart/styles.js | 42 + .../{rate-slider => RateSlider}/index.js | 42 +- webapp/src/components/Sidebar/index.js | 183 +++ webapp/src/components/Sidebar/styles.js | 98 ++ .../src/components/{table => Table}/index.js | 16 +- .../src/components/{video => Video}/index.js | 0 webapp/src/components/app-bar/index.js | 202 --- webapp/src/components/app-bar/styles.js | 82 -- webapp/src/components/bottom-navbar/index.js | 52 - webapp/src/components/bottom-navbar/styles.js | 9 - .../src/components/bp-chip-avatar/styles.js | 9 - webapp/src/components/button/index.js | 12 - webapp/src/components/checkbox/index.js | 21 - .../compare-tool/compare-graph-view.js | 354 ----- .../compare-tool/compare-slider-view.js | 73 - webapp/src/components/compare-tool/styles.js | 174 --- webapp/src/components/filter-select/index.js | 83 -- webapp/src/components/filter-select/styles.js | 17 - webapp/src/components/formControl/index.js | 7 - webapp/src/components/github-icon/index.js | 10 - webapp/src/components/icon/communityIcon.js | 10 +- webapp/src/components/icon/developmentIcon.js | 10 +- .../src/components/icon/infrastructureIcon.js | 10 +- .../src/components/icon/transparencyIcon.js | 10 +- webapp/src/components/icon/trustinessIcon.js | 10 +- .../components/input-autocomplete/styles.js | 43 - .../src/components/language-select/styles.js | 17 - .../index.js | 28 +- .../src/components/languageSelector/styles.js | 23 + webapp/src/components/layout/index.js | 76 - webapp/src/components/layout/styles.js | 28 - webapp/src/components/main-drawer/index.js | 190 --- webapp/src/components/main-drawer/styles.js | 47 - webapp/src/components/main-footer/styles.js | 30 - webapp/src/components/radar/index.js | 122 -- webapp/src/components/select/index.js | 32 - webapp/src/components/sign-in-dialog/index.js | 60 - .../src/components/sign-in-dialog/styles.js | 5 - webapp/src/components/sign-in-menu/index.js | 27 - webapp/src/components/spinner/index.js | 32 - webapp/src/components/spinner/styles.js | 32 - webapp/src/components/telegram-icon/index.js | 20 - webapp/src/components/textField/index.js | 13 - webapp/src/components/title-page/index.js | 19 - webapp/src/config/graphql.config.js | 1 + webapp/src/config/index.js | 20 +- webapp/src/config/main.config.js | 12 + webapp/src/config/polar-radar-config.js | 62 + webapp/src/config/radar-color-palette.js | 20 - webapp/src/config/radar.js | 27 - webapp/src/config/theme.js | 73 - webapp/src/config/ual.config.js | 32 + webapp/src/config/wallet-providers.js | 22 - webapp/src/context/models/index.js | 3 + webapp/src/context/models/producers.js | 69 + webapp/src/context/models/proxies.js | 156 +++ webapp/src/context/models/user.js | 76 + webapp/src/context/state.context.js | 254 ++++ webapp/src/gql/index.js | 4 + webapp/src/gql/producers.js | 94 ++ webapp/src/gql/proxies.js | 44 + webapp/src/gql/search.js | 14 + webapp/src/gql/user.js | 38 + webapp/src/graphql.js | 55 + webapp/src/hooks/useDebounce/index.js | 19 + webapp/src/i18n.js | 4 +- webapp/src/index.js | 53 +- webapp/src/language/en.json | 27 +- webapp/src/language/es.json | 19 +- webapp/src/language/ko.json | 567 ++++---- webapp/src/layouts/Dashboard/index.js | 52 + webapp/src/layouts/Dashboard/styles.js | 21 + webapp/src/layouts/index.js | 1 + .../models/BlockProducer/blockProducers.js | 297 ---- .../mutation_insert_user_rating.js | 15 - .../BlockProducer/mutation_update_rate.js | 16 - .../mutation_update_user_rating.js | 23 - .../BlockProducer/query_get_bp_rating_by.js | 16 - .../BlockProducer/query_get_eden_stats.js | 18 - .../BlockProducer/query_get_producer_by.js | 13 - webapp/src/models/Proxy/proxy.js | 207 --- webapp/src/models/Proxy/query_get_proxies.js | 22 - .../models/Proxy/query_get_proxy_by_owner.js | 22 - .../models/User/mutation_delete_user_rate.js | 13 - webapp/src/models/User/query_get_rates.js | 15 - webapp/src/models/User/user.js | 167 --- webapp/src/models/home.js | 35 - webapp/src/models/index.js | 7 - webapp/src/models/isLoading.js | 14 - webapp/src/models/location.js | 36 - webapp/src/models/settings.js | 19 - webapp/src/routes/Account/index.js | 284 ++++ webapp/src/routes/Account/styles.js | 101 ++ .../BlockProducers/BlockProducerProfile.js | 352 +++++ .../BlockProducerRate.js} | 463 +++--- .../BlockProducers/BottomSheetSelectedBps.js | 32 + .../FilterBox.js} | 16 +- .../GeneralInformationProfile.js} | 11 +- .../SliderRatingSection.js} | 37 +- webapp/src/routes/BlockProducers/index.js | 280 ++++ .../styles.js | 62 +- .../filter-box.js => Proxies/FilterBox.js} | 27 +- .../GeneralInformationProfile.js} | 6 +- .../ProxyProfile.js} | 187 +-- webapp/src/routes/Proxies/index.js | 221 +++ .../src/routes/{proxies => Proxies}/styles.js | 51 +- webapp/src/routes/Route404/index.js | 40 + webapp/src/routes/Route404/styles.js | 10 + .../routes/{settings => Settings}/index.js | 51 +- .../routes/{settings => Settings}/styles.js | 2 +- .../{termsOfUse => TermsOfUse}/index.js | 21 +- webapp/src/routes/TermsOfUse/styles.js | 15 + webapp/src/routes/about/index.js | 63 +- webapp/src/routes/about/styles.js | 10 +- webapp/src/routes/account/index.js | 307 ---- webapp/src/routes/account/styles.js | 39 - .../block-producers/block-producer-profile.js | 364 ----- .../bottom-sheet-selected-bps.js | 42 - .../block-producers/compare-tool-toggle.js | 44 - webapp/src/routes/block-producers/index.js | 300 ---- webapp/src/routes/help/index.js | 102 +- webapp/src/routes/help/styles.js | 11 +- webapp/src/routes/home/cover.js | 184 +-- webapp/src/routes/home/index.js | 97 +- webapp/src/routes/home/rateCategory.js | 72 +- webapp/src/routes/home/styles.js | 154 +- webapp/src/routes/home/subTopic.js | 28 +- webapp/src/routes/index.js | 150 +- webapp/src/routes/not-found/index.js | 42 - webapp/src/routes/not-found/styles.js | 43 - .../src/routes/proxies/compare-tool-toggle.js | 42 - webapp/src/routes/proxies/index.js | 245 ---- webapp/src/routes/termsOfUse/styles.js | 8 - webapp/src/serviceWorker.js | 43 +- webapp/src/services/api.js | 44 - webapp/src/services/bps.js | 99 -- webapp/src/services/eosjs-api.js | 14 - webapp/src/services/graphql.js | 42 - webapp/src/store.js | 21 - webapp/src/theme/breakpoints.js | 11 + webapp/src/theme/index.js | 28 + webapp/src/theme/palette.js | 22 + webapp/src/theme/props.js | 10 + webapp/src/theme/typography.js | 13 + ...Votes.js => convert-votes-to-eos-votes.js} | 4 +- webapp/src/utils/eosapi.js | 9 + .../utils/{eosjsUtils.js => eosjs-utils.js} | 4 +- .../{formatNumber.js => format-number.js} | 0 .../utils/format-with-thousand-separator.js | 13 + ...etAverageValue.js => get-average-value.js} | 4 +- webapp/src/utils/get-bp-radar-data.js | 20 + ...arLabelName.js => get-radar-label-name.js} | 2 +- ...sFromHex.js => get-rgb-colors-from-hex.js} | 0 webapp/src/utils/getBPRadarData.js | 18 - webapp/src/utils/getColorFromName.js | 18 - webapp/src/utils/index.js | 3 + webapp/src/utils/modeled-bp-data.js | 34 + webapp/src/utils/modeled-proxy-data.js | 77 + webapp/src/utils/on-img-error.js | 7 + .../src/utils/{sortedBy.js => sorted-by.js} | 2 +- webapp/src/utils/ualAuthenticators.js | 44 - ...tier.config.js => test.prettier.config.js} | 3 +- webapp/yarn.lock | 1237 +++++++++++------ 206 files changed, 6789 insertions(+), 6786 deletions(-) create mode 100644 hasura/migrations/default/1632090744903_alter_table_public_producers_add_column_candidate_name/down.sql create mode 100644 hasura/migrations/default/1632090744903_alter_table_public_producers_add_column_candidate_name/up.sql create mode 100644 hasura/migrations/default/1632094823972_alter_table_public_proxies_add_column_filter_name/down.sql create mode 100644 hasura/migrations/default/1632094823972_alter_table_public_proxies_add_column_filter_name/up.sql create mode 100644 webapp/.babelrc create mode 100644 webapp/.prettierrc delete mode 100644 webapp/jsconfig.json create mode 100644 webapp/src/App.test.js rename webapp/src/components/{bp-chip-avatar => BpChipAvatar}/index.js (79%) create mode 100644 webapp/src/components/BpChipAvatar/styles.js rename webapp/src/components/{card => Card}/index.js (62%) rename webapp/src/components/{card => Card}/styles.js (52%) create mode 100644 webapp/src/components/CompareTool/CompareGraphView.js create mode 100644 webapp/src/components/CompareTool/CompareSliderView.js rename webapp/src/components/{compare-tool => CompareTool}/index.js (63%) create mode 100644 webapp/src/components/CompareTool/styles.js rename webapp/src/components/{main-footer => Footer}/index.js (60%) create mode 100644 webapp/src/components/Footer/styles.js create mode 100644 webapp/src/components/Header/index.js create mode 100644 webapp/src/components/Header/styles.js rename webapp/src/components/{input-autocomplete => InputAutocomplete}/index.js (57%) create mode 100644 webapp/src/components/InputAutocomplete/styles.js create mode 100644 webapp/src/components/Loader/index.js create mode 100644 webapp/src/components/Loader/styles.js create mode 100644 webapp/src/components/Message/index.js create mode 100644 webapp/src/components/Message/styles.js rename webapp/src/components/{mobile-search => MobileSearch}/index.js (68%) rename webapp/src/components/{mobile-search => MobileSearch}/styles.js (100%) create mode 100644 webapp/src/components/PageTitle/index.js rename webapp/src/components/{parameter-range-selector => ParameterRangeSelector}/index.js (87%) rename webapp/src/components/{parameter-range-selector => ParameterRangeSelector}/style.css (100%) create mode 100644 webapp/src/components/PolarChart/index.js create mode 100644 webapp/src/components/PolarChart/styles.js rename webapp/src/components/{rate-slider => RateSlider}/index.js (60%) create mode 100644 webapp/src/components/Sidebar/index.js create mode 100644 webapp/src/components/Sidebar/styles.js rename webapp/src/components/{table => Table}/index.js (71%) rename webapp/src/components/{video => Video}/index.js (100%) delete mode 100644 webapp/src/components/app-bar/index.js delete mode 100644 webapp/src/components/app-bar/styles.js delete mode 100644 webapp/src/components/bottom-navbar/index.js delete mode 100644 webapp/src/components/bottom-navbar/styles.js delete mode 100644 webapp/src/components/bp-chip-avatar/styles.js delete mode 100644 webapp/src/components/button/index.js delete mode 100644 webapp/src/components/checkbox/index.js delete mode 100644 webapp/src/components/compare-tool/compare-graph-view.js delete mode 100644 webapp/src/components/compare-tool/compare-slider-view.js delete mode 100644 webapp/src/components/compare-tool/styles.js delete mode 100644 webapp/src/components/filter-select/index.js delete mode 100644 webapp/src/components/filter-select/styles.js delete mode 100644 webapp/src/components/formControl/index.js delete mode 100644 webapp/src/components/github-icon/index.js delete mode 100644 webapp/src/components/input-autocomplete/styles.js delete mode 100644 webapp/src/components/language-select/styles.js rename webapp/src/components/{language-select => languageSelector}/index.js (68%) create mode 100644 webapp/src/components/languageSelector/styles.js delete mode 100644 webapp/src/components/layout/index.js delete mode 100644 webapp/src/components/layout/styles.js delete mode 100644 webapp/src/components/main-drawer/index.js delete mode 100644 webapp/src/components/main-drawer/styles.js delete mode 100644 webapp/src/components/main-footer/styles.js delete mode 100644 webapp/src/components/radar/index.js delete mode 100644 webapp/src/components/select/index.js delete mode 100644 webapp/src/components/sign-in-dialog/index.js delete mode 100644 webapp/src/components/sign-in-dialog/styles.js delete mode 100644 webapp/src/components/sign-in-menu/index.js delete mode 100644 webapp/src/components/spinner/index.js delete mode 100644 webapp/src/components/spinner/styles.js delete mode 100644 webapp/src/components/telegram-icon/index.js delete mode 100644 webapp/src/components/textField/index.js delete mode 100644 webapp/src/components/title-page/index.js create mode 100644 webapp/src/config/graphql.config.js create mode 100644 webapp/src/config/main.config.js create mode 100644 webapp/src/config/polar-radar-config.js delete mode 100644 webapp/src/config/radar-color-palette.js delete mode 100644 webapp/src/config/radar.js delete mode 100644 webapp/src/config/theme.js create mode 100644 webapp/src/config/ual.config.js delete mode 100644 webapp/src/config/wallet-providers.js create mode 100644 webapp/src/context/models/index.js create mode 100644 webapp/src/context/models/producers.js create mode 100644 webapp/src/context/models/proxies.js create mode 100644 webapp/src/context/models/user.js create mode 100644 webapp/src/context/state.context.js create mode 100644 webapp/src/gql/index.js create mode 100644 webapp/src/gql/producers.js create mode 100644 webapp/src/gql/proxies.js create mode 100644 webapp/src/gql/search.js create mode 100644 webapp/src/gql/user.js create mode 100644 webapp/src/graphql.js create mode 100644 webapp/src/hooks/useDebounce/index.js create mode 100644 webapp/src/layouts/Dashboard/index.js create mode 100644 webapp/src/layouts/Dashboard/styles.js create mode 100644 webapp/src/layouts/index.js delete mode 100644 webapp/src/models/BlockProducer/blockProducers.js delete mode 100644 webapp/src/models/BlockProducer/mutation_insert_user_rating.js delete mode 100644 webapp/src/models/BlockProducer/mutation_update_rate.js delete mode 100644 webapp/src/models/BlockProducer/mutation_update_user_rating.js delete mode 100644 webapp/src/models/BlockProducer/query_get_bp_rating_by.js delete mode 100644 webapp/src/models/BlockProducer/query_get_eden_stats.js delete mode 100644 webapp/src/models/BlockProducer/query_get_producer_by.js delete mode 100644 webapp/src/models/Proxy/proxy.js delete mode 100644 webapp/src/models/Proxy/query_get_proxies.js delete mode 100644 webapp/src/models/Proxy/query_get_proxy_by_owner.js delete mode 100644 webapp/src/models/User/mutation_delete_user_rate.js delete mode 100644 webapp/src/models/User/query_get_rates.js delete mode 100644 webapp/src/models/User/user.js delete mode 100644 webapp/src/models/home.js delete mode 100644 webapp/src/models/index.js delete mode 100644 webapp/src/models/isLoading.js delete mode 100644 webapp/src/models/location.js delete mode 100644 webapp/src/models/settings.js create mode 100644 webapp/src/routes/Account/index.js create mode 100644 webapp/src/routes/Account/styles.js create mode 100644 webapp/src/routes/BlockProducers/BlockProducerProfile.js rename webapp/src/routes/{block-producers/block-producer-rate.js => BlockProducers/BlockProducerRate.js} (53%) create mode 100644 webapp/src/routes/BlockProducers/BottomSheetSelectedBps.js rename webapp/src/routes/{block-producers/filter-box.js => BlockProducers/FilterBox.js} (76%) rename webapp/src/routes/{block-producers/general-information-profile.js => BlockProducers/GeneralInformationProfile.js} (98%) rename webapp/src/routes/{block-producers/slider-rating-section.js => BlockProducers/SliderRatingSection.js} (87%) create mode 100644 webapp/src/routes/BlockProducers/index.js rename webapp/src/routes/{block-producers => BlockProducers}/styles.js (82%) rename webapp/src/routes/{proxies/filter-box.js => Proxies/FilterBox.js} (68%) rename webapp/src/routes/{proxies/general-information-profile.js => Proxies/GeneralInformationProfile.js} (97%) rename webapp/src/routes/{proxies/proxy-profile.js => Proxies/ProxyProfile.js} (59%) create mode 100644 webapp/src/routes/Proxies/index.js rename webapp/src/routes/{proxies => Proxies}/styles.js (77%) create mode 100644 webapp/src/routes/Route404/index.js create mode 100644 webapp/src/routes/Route404/styles.js rename webapp/src/routes/{settings => Settings}/index.js (55%) rename webapp/src/routes/{settings => Settings}/styles.js (61%) rename webapp/src/routes/{termsOfUse => TermsOfUse}/index.js (50%) create mode 100644 webapp/src/routes/TermsOfUse/styles.js delete mode 100644 webapp/src/routes/account/index.js delete mode 100644 webapp/src/routes/account/styles.js delete mode 100644 webapp/src/routes/block-producers/block-producer-profile.js delete mode 100644 webapp/src/routes/block-producers/bottom-sheet-selected-bps.js delete mode 100644 webapp/src/routes/block-producers/compare-tool-toggle.js delete mode 100644 webapp/src/routes/block-producers/index.js delete mode 100644 webapp/src/routes/not-found/index.js delete mode 100644 webapp/src/routes/not-found/styles.js delete mode 100644 webapp/src/routes/proxies/compare-tool-toggle.js delete mode 100644 webapp/src/routes/proxies/index.js delete mode 100644 webapp/src/routes/termsOfUse/styles.js delete mode 100644 webapp/src/services/api.js delete mode 100644 webapp/src/services/bps.js delete mode 100644 webapp/src/services/eosjs-api.js delete mode 100644 webapp/src/services/graphql.js delete mode 100644 webapp/src/store.js create mode 100644 webapp/src/theme/breakpoints.js create mode 100644 webapp/src/theme/index.js create mode 100644 webapp/src/theme/palette.js create mode 100644 webapp/src/theme/props.js create mode 100644 webapp/src/theme/typography.js rename webapp/src/utils/{convertVotesToEosVotes.js => convert-votes-to-eos-votes.js} (73%) create mode 100644 webapp/src/utils/eosapi.js rename webapp/src/utils/{eosjsUtils.js => eosjs-utils.js} (80%) rename webapp/src/utils/{formatNumber.js => format-number.js} (100%) create mode 100644 webapp/src/utils/format-with-thousand-separator.js rename webapp/src/utils/{getAverageValue.js => get-average-value.js} (79%) create mode 100644 webapp/src/utils/get-bp-radar-data.js rename webapp/src/utils/{getRadarLabelName.js => get-radar-label-name.js} (80%) rename webapp/src/utils/{getRgbColorsFromHex.js => get-rgb-colors-from-hex.js} (100%) delete mode 100644 webapp/src/utils/getBPRadarData.js delete mode 100644 webapp/src/utils/getColorFromName.js create mode 100644 webapp/src/utils/index.js create mode 100644 webapp/src/utils/modeled-bp-data.js create mode 100644 webapp/src/utils/modeled-proxy-data.js create mode 100644 webapp/src/utils/on-img-error.js rename webapp/src/utils/{sortedBy.js => sorted-by.js} (98%) delete mode 100644 webapp/src/utils/ualAuthenticators.js rename webapp/{prettier.config.js => test.prettier.config.js} (80%) diff --git a/.env.example b/.env.example index 7ccb1b1b..1c50cfe9 100644 --- a/.env.example +++ b/.env.example @@ -44,3 +44,7 @@ REACT_APP_EOS_API_PROTOCOL=https REACT_APP_EOS_CHAIN_ID=2a02a0053e5a8cf73a56ba0fda11e4d92e0238a4a2aa74fccf46d5a910746840 REACT_APP_BLOCK_EXPLORER=https://jungle3.bloks.io REACT_APP_NETWORK_MONITOR_URL=https://jungle.eosio.online/ +REACT_APP_VERSION=v1.4.21 +REACT_APP_MAINNET_VERSION=v1.4.21 +REACT_APP_EDEN_CONTRACT=genesisdeden +REACT_APP_UAL_APP_NAME=EOSRate diff --git a/hapi/src/libs/sync-bps.js b/hapi/src/libs/sync-bps.js index 3e0e0a16..7ce7d565 100644 --- a/hapi/src/libs/sync-bps.js +++ b/hapi/src/libs/sync-bps.js @@ -47,7 +47,8 @@ const getBlockProducersData = async () => { { owner: producer.owner, system: { ...producer }, - bpJson: {} + bpJson: {}, + candidateName: null } ] }, []) @@ -65,6 +66,9 @@ const getBlockProducersData = async () => { }) if (bp['producer_account_name'] && bp['producer_account_name'] !== '') { producer['bpJson'] = bp + producer['candidateName'] = bp.org + ? (bp.org.candidate_name || '').toLowerCase() + : null producersBPJSON.push(producer) } } catch (err) { @@ -83,8 +87,8 @@ const updateBlockProducersData = async () => { const producersData = await getBlockProducersData() producersData.forEach(async (bp) => { - const { owner, system, bpJson: bpjson } = bp - const bpData = { owner, system, bpjson } + const { owner, system, bpJson: bpjson, candidateName } = bp + const bpData = { owner, system, bpjson, candidate_name: candidateName } try { const saveBPResult = await (await massiveDB).producers.save(bpData) diff --git a/hapi/src/libs/sync-proxies.js b/hapi/src/libs/sync-proxies.js index 49943fe6..d3a7e9a6 100644 --- a/hapi/src/libs/sync-proxies.js +++ b/hapi/src/libs/sync-proxies.js @@ -4,10 +4,10 @@ const EosApi = require('eosjs-api') const fetch = require('node-fetch') const { massiveDB } = require('../config') -const HAPI_EOS_API_ENDPOINT = process.env.HAPI_EOS_API_ENDPOINT || 'https://jungle.eosio.cr' +const HAPI_EOS_API_ENDPOINT = + process.env.HAPI_EOS_API_ENDPOINT || 'https://jungle.eosio.cr' const HAPI_PROXY_CONTRACT = process.env.HAPI_PROXY_CONTRACT || 'proxyaccount' - const getProxiesData = async () => { console.log('==== Updating proxies ====') const eos = new JsonRpc(HAPI_EOS_API_ENDPOINT, { fetch }) @@ -19,7 +19,7 @@ const getProxiesData = async () => { let proxies try { - ({rows: proxies} = await eos.get_table_rows({ + ;({ rows: proxies } = await eos.get_table_rows({ json: true, code: HAPI_PROXY_CONTRACT, scope: HAPI_PROXY_CONTRACT, @@ -28,7 +28,7 @@ const getProxiesData = async () => { reverse: false, show_payer: false })) - } catch (err) { + } catch (err) { console.log(`Database connection error ${err}`) return [] } @@ -38,11 +38,25 @@ const getProxiesData = async () => { if (account && account.voter_info && account.voter_info.is_proxy) { proxy.voter_info = account.voter_info + try { - const resultProxySave = await (await massiveDB).proxies.save(proxy) - const dbResult = resultProxySave ? resultProxySave : await (await massiveDB).proxies.insert(proxy) - console.log(`Save or insert of ${proxy.owner} was ${dbResult ? 'SUCCESSFULL' : 'UNSUCCESSFULL'}`) - } catch (err) { console.log(`Error: ${err}`) } + const resultProxySave = await ( + await massiveDB + ).proxies.save({ + ...proxy, + filter_name: (proxy.name || null).toLowerCase() + }) + const dbResult = resultProxySave + ? resultProxySave + : await (await massiveDB).proxies.insert(proxy) + console.log( + `Save or insert of ${proxy.owner} was ${ + dbResult ? 'SUCCESSFULL' : 'UNSUCCESSFULL' + }` + ) + } catch (err) { + console.log(`Error: ${err}`) + } } else console.log(`${proxy.owner} is not a proxy`) }) } diff --git a/hapi/yarn.lock b/hapi/yarn.lock index 2976f26b..15495c77 100644 --- a/hapi/yarn.lock +++ b/hapi/yarn.lock @@ -56,9 +56,9 @@ "@babel/types" "^7.15.4" "@babel/helper-validator-identifier@^7.14.5", "@babel/helper-validator-identifier@^7.14.9": - version "7.14.9" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.9.tgz#6654d171b2024f6d8ee151bf2509699919131d48" - integrity sha512-pQYxPY0UP6IHISRitNe8bsijHex4TWZXi2HwKVsjPiltzlhse2znVcm9Ace510VT1kxIHjGJCZZQBX2gJDbo0g== + version "7.15.7" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.15.7.tgz#220df993bfe904a4a6b02ab4f3385a5ebf6e2389" + integrity sha512-K4JvCtQqad9OY2+yTU8w+E82ywk/fe+ELNlt1G8z3bVGlZfn/hOcQQsUhGhW/N+tb3fxK800wLtKOE/aM0m72w== "@babel/highlight@^7.10.4", "@babel/highlight@^7.14.5": version "7.14.5" @@ -70,9 +70,9 @@ js-tokens "^4.0.0" "@babel/parser@^7.15.4", "@babel/parser@^7.3.1": - version "7.15.6" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.15.6.tgz#043b9aa3c303c0722e5377fef9197f4cf1796549" - integrity sha512-S/TSCcsRuCkmpUuoWijua0Snt+f3ewU/8spLo+4AXJCZfT0bVCzLD5MuOKdrx0mlAptbKzn5AdgEIIKXxXkz9Q== + version "7.15.7" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.15.7.tgz#0c3ed4a2eb07b165dfa85b3cc45c727334c4edae" + integrity sha512-rycZXvQ+xS9QyIcJ9HXeDWf1uxqlbVFAUq0Rq0dbc50Zb/+wUe/ehyfzGfm9KZZF0kBejYgxltBXocP+gKdL2g== "@babel/template@^7.15.4": version "7.15.4" diff --git a/hasura/metadata/actions.graphql b/hasura/metadata/actions.graphql index 6e51e00a..469d1dcf 100644 --- a/hasura/metadata/actions.graphql +++ b/hasura/metadata/actions.graphql @@ -1,25 +1,28 @@ type Mutation { - rateProducer( + rateProducer ( ratingInput: RatingInput! ): RatingOutput } + + + input RatingInput { - user: String! - producer: String! - transaction: jsonb! + user : String! + producer : String! + transaction : jsonb! } type RatingOutput { - message: String! - resultEden: jsonb - uniq_rating: String - user: String - bp: String - ratings: jsonb + message : String! + resultEden : jsonb + uniq_rating : String + user : String + bp : String + ratings : jsonb } type deleteUserRateOutput { - message: String! + message : String! } diff --git a/hasura/metadata/databases/default/tables/public_producers.yaml b/hasura/metadata/databases/default/tables/public_producers.yaml index 3e856471..4736b5b2 100644 --- a/hasura/metadata/databases/default/tables/public_producers.yaml +++ b/hasura/metadata/databases/default/tables/public_producers.yaml @@ -5,6 +5,7 @@ select_permissions: - permission: columns: - bpjson + - candidate_name - general_info - owner - system diff --git a/hasura/metadata/databases/default/tables/public_proxies.yaml b/hasura/metadata/databases/default/tables/public_proxies.yaml index 24b9f599..8e99fd4b 100644 --- a/hasura/metadata/databases/default/tables/public_proxies.yaml +++ b/hasura/metadata/databases/default/tables/public_proxies.yaml @@ -5,6 +5,7 @@ select_permissions: - permission: columns: - background + - filter_name - logo_256 - name - owner diff --git a/hasura/migrations/default/1632090744903_alter_table_public_producers_add_column_candidate_name/down.sql b/hasura/migrations/default/1632090744903_alter_table_public_producers_add_column_candidate_name/down.sql new file mode 100644 index 00000000..a9e835d5 --- /dev/null +++ b/hasura/migrations/default/1632090744903_alter_table_public_producers_add_column_candidate_name/down.sql @@ -0,0 +1,4 @@ +-- Could not auto-generate a down migration. +-- Please write an appropriate down migration for the SQL below: +-- alter table "public"."producers" add column "candidate_name" text +-- null; diff --git a/hasura/migrations/default/1632090744903_alter_table_public_producers_add_column_candidate_name/up.sql b/hasura/migrations/default/1632090744903_alter_table_public_producers_add_column_candidate_name/up.sql new file mode 100644 index 00000000..0d3e3614 --- /dev/null +++ b/hasura/migrations/default/1632090744903_alter_table_public_producers_add_column_candidate_name/up.sql @@ -0,0 +1,2 @@ +alter table "public"."producers" add column "candidate_name" text + null; diff --git a/hasura/migrations/default/1632094823972_alter_table_public_proxies_add_column_filter_name/down.sql b/hasura/migrations/default/1632094823972_alter_table_public_proxies_add_column_filter_name/down.sql new file mode 100644 index 00000000..47328017 --- /dev/null +++ b/hasura/migrations/default/1632094823972_alter_table_public_proxies_add_column_filter_name/down.sql @@ -0,0 +1,4 @@ +-- Could not auto-generate a down migration. +-- Please write an appropriate down migration for the SQL below: +-- alter table "public"."proxies" add column "filter_name" text +-- null; diff --git a/hasura/migrations/default/1632094823972_alter_table_public_proxies_add_column_filter_name/up.sql b/hasura/migrations/default/1632094823972_alter_table_public_proxies_add_column_filter_name/up.sql new file mode 100644 index 00000000..62ea5024 --- /dev/null +++ b/hasura/migrations/default/1632094823972_alter_table_public_proxies_add_column_filter_name/up.sql @@ -0,0 +1,2 @@ +alter table "public"."proxies" add column "filter_name" text + null; diff --git a/webapp/.babelrc b/webapp/.babelrc new file mode 100644 index 00000000..b4fb7817 --- /dev/null +++ b/webapp/.babelrc @@ -0,0 +1,16 @@ +{ + "plugins": ["@babel/plugin-proposal-optional-chaining"], + "presets": [ + [ + "@babel/preset-env", + { + "loose": true, + "targets": { "esmodules": true }, + "useBuiltIns": "usage", + "corejs": 3, + "modules": false + } + ], + "@babel/preset-react" + ] +} diff --git a/webapp/.prettierrc b/webapp/.prettierrc new file mode 100644 index 00000000..1719afbd --- /dev/null +++ b/webapp/.prettierrc @@ -0,0 +1,13 @@ +{ + "trailingComma": "none", + "endOfLine": "auto", + "tabWidth": 2, + "singleQuote": true, + "semi": false, + "arrowParens": "avoid", + "printWidth": 80, + "useTabs": false, + "bracketSpacing": true, + "jsxBracketSameLine": false, + "jsxSingleQuote": true +} diff --git a/webapp/config-overrides.js b/webapp/config-overrides.js index 82cbba15..6bf9e732 100644 --- a/webapp/config-overrides.js +++ b/webapp/config-overrides.js @@ -1,8 +1,12 @@ -const { compose } = require('react-app-rewired') -const rewireEslint = require('react-app-rewire-eslint') -const rewireReactHotLoader = require('react-app-rewire-hot-loader') +// const { compose } = require('react-app-rewired') +// const rewireEslint = require('react-app-rewire-eslint') +// const rewireReactHotLoader = require('react-app-rewire-hot-loader') -module.exports = compose( - rewireEslint, - rewireReactHotLoader -) +// module.exports = compose( +// rewireEslint, +// rewireReactHotLoader +// ) + +const { useBabelRc, override } = require('customize-cra') + +module.exports = override(useBabelRc()) diff --git a/webapp/jsconfig.json b/webapp/jsconfig.json deleted file mode 100644 index 5875dc5b..00000000 --- a/webapp/jsconfig.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "compilerOptions": { - "baseUrl": "src" - }, - "include": ["src"] -} diff --git a/webapp/package.json b/webapp/package.json index 478a3e81..f0b6f68c 100644 --- a/webapp/package.json +++ b/webapp/package.json @@ -17,17 +17,20 @@ }, "husky": { "hooks": { - "pre-commit": "lint-staged" + "pre-commit": "lint-staged && CI=true yarn test" } }, "dependencies": { + "@apollo/client": "^3.3.21", + "@date-io/date-fns": "^2.11.0", + "@emotion/react": "^11.4.1", + "@emotion/styled": "^11.3.0", "@eoscostarica/eoscr-components": "^3.5.4", - "@material-ui/core": "^4.12.1", - "@material-ui/icons": "^4.9.1", - "@material-ui/lab": "^4.0.0-alpha.60", - "@reach/router": "^1.3.3", - "@rematch/core": "^2.0.0", - "@rematch/persist": "^2.0.0", + "@eoscostarica/ual-reactjs-renderer": "^0.3.1", + "@mui/icons-material": "^5.0.1", + "@mui/lab": "^5.0.0-alpha.48", + "@mui/material": "^5.0.1", + "@mui/styles": "^5.0.1", "apollo-cache-inmemory": "^1.6.5", "apollo-client": "^2.6.8", "apollo-link": "^1.2.13", @@ -36,36 +39,46 @@ "apollo-utilities": "^1.3.3", "chart.js": "^3.5.1", "classnames": "^2.3.1", + "core-js": "^3.15.2", + "date-fns": "^2.24.0", "env-cmd": "^10.1.0", "eosjs": "^22.1.0", + "eosjs-api": "^7.0.4", "filter-objects": "^2.1.1", "graphql": "^15.5.1", "graphql-tag": "^2.12.5", + "highcharts": "^9.2.2", + "highcharts-react-official": "^3.0.0", + "history": "^5.0.0", "i18n-iso-countries": "^6.8.0", - "i18next": "^20.3.3", + "i18next": "^20.3.4", "i18next-browser-languagedetector": "^6.1.2", "lodash.get": "^4.4.2", "lodash.isempty": "^4.4.0", "lodash.set": "^4.3.2", "lodash.uniq": "^4.5.0", "node-fetch": "^2.6.2", + "polished": "^4.1.3", + "prop-types": "^15.7.2", "qs": "^6.10.1", "random-color-rgb": "^1.1.1", "rc-slider": "^9.7.2", - "react": "17.0.2", + "react": "~17.0.2", "react-apollo": "^3.1.3", "react-autosuggest": "^10.1.0", "react-chartjs-2": "^3.0.4", - "react-dom": "17.0.2", + "react-dom": "~17.0.2", + "react-feather": "^2.0.9", "react-ga": "^3.3.0", "react-helmet": "^6.1.0", "react-highlighter": "^0.4.3", - "react-i18next": "^11.11.2", + "react-i18next": "^11.11.3", + "react-is": "^17.0.2", + "react-perfect-scrollbar": "^1.5.8", "react-placeholder": "^4.0.0", - "react-redux": "^7.2.4", - "react-router": "^5.2.1", - "redux": "^4.1.0", - "redux-persist": "^6.0.0", + "react-router": "^5.2.0", + "react-router-dom": "^5.2.0", + "react-scripts": "^4.0.3", "serve": "^12.0.0", "subscriptions-transport-ws": "^0.9.19", "text-encoding": "^0.7.0", @@ -79,18 +92,25 @@ "yup": "0.32.9" }, "devDependencies": { - "eslint-config-prettier": "^8.3.0", - "eslint-config-standard": "^16.0.3", + "@babel/eslint-parser": "^7.13.10", + "@babel/plugin-proposal-optional-chaining": "^7.13.8", + "@babel/preset-env": "^7.13.10", + "@babel/preset-react": "^7.12.13", + "customize-cra": "^1.0.0", + "env-cmd": "^10.1.0", + "eslint": "^7.22.0", + "eslint-config-prettier": "^8.1.0", + "eslint-config-standard": "^16.0.2", "eslint-config-standard-react": "^11.0.1", - "eslint-plugin-node": "^11.0.0", - "eslint-plugin-prettier": "^4.0.0", - "eslint-plugin-standard": "^5.0.0", - "husky": "^7.0.1", - "lint-staged": "^11.0.1", - "prettier": "^2.3.2", - "pretty-quick": "^3.1.1", - "react-scripts": "4.0.3", - "snazzy": "^9.0.0", + "eslint-plugin-import": "^2.22.1", + "eslint-plugin-node": "^11.1.0", + "eslint-plugin-prettier": "^3.3.1", + "eslint-plugin-promise": "^4.3.1", + "eslint-plugin-react": "^7.22.0", + "husky": "4.3.8", + "lint-staged": "^10.5.4", + "prettier": "^2.2.1", + "react-app-rewired": "^2.1.8", "standard": "^16.0.3" }, "resolutions": { @@ -105,16 +125,10 @@ "git add" ] }, - "browserslist": { - "development": [ - "last 2 chrome versions", - "last 2 firefox versions", - "last 2 edge versions" - ], - "production": [ - ">0.25%", - "not op_mini all", - "ie 11" - ] - } + "browserslist": [ + ">0.2%", + "not dead", + "not ie <= 11", + "not op_mini all" + ] } diff --git a/webapp/public/index.html b/webapp/public/index.html index 381e7da0..1430843c 100644 --- a/webapp/public/index.html +++ b/webapp/public/index.html @@ -27,9 +27,12 @@ Rate Block Producers - EOSIO Blockchain Ratings by EOS Costa Rica + { + const div = document.createElement('div') + ReactDOM.render(, div) + ReactDOM.unmountComponentAtNode(div) +}) diff --git a/webapp/src/app.js b/webapp/src/app.js index 0fb830b4..7a25fe56 100644 --- a/webapp/src/app.js +++ b/webapp/src/app.js @@ -1,33 +1,48 @@ -import React from 'react' -import PropTypes from 'prop-types' -import { useSelector } from 'react-redux' -import { Router } from '@reach/router' +import React, { Suspense, useMemo } from 'react' +import { BrowserRouter, Route, Switch } from 'react-router-dom' +import AdapterDateFns from '@mui/lab/AdapterDateFns' +import LocalizationProvider from '@mui/lab/LocalizationProvider' +import { ThemeProvider } from '@mui/material/styles' +import CssBaseline from '@mui/material/CssBaseline' -import Spinner from 'components/spinner' -import Layout from 'components/layout' -import NotFound from 'routes/not-found' -import routes from 'routes' +import routes from './routes' +import Loader from './components/Loader' +import DashboardLayout from './layouts/Dashboard' +import { useSharedState } from './context/state.context' +import getTheme from './theme' +import './i18n' -const App = ({ ual }) => { - const { isContentLoading } = useSelector((state) => state.isLoading) +const App = () => { + const [state] = useSharedState() - return ( - <> - - - - {(routes || []).map(({ path, Component }) => ( - - ))} - - - - + const renderRoute = ({ component: Component, ...route }, index) => ( + + + ) -} -App.propTypes = { - ual: PropTypes.object + const userRoutes = useMemo(() => routes()) + + const theme = useMemo(() => getTheme(state.useDarkMode), [state.useDarkMode]) + + return ( + + + + + + }> + {userRoutes.browser.map(renderRoute)} + + + + + + ) } export default App diff --git a/webapp/src/components/bp-chip-avatar/index.js b/webapp/src/components/BpChipAvatar/index.js similarity index 79% rename from webapp/src/components/bp-chip-avatar/index.js rename to webapp/src/components/BpChipAvatar/index.js index a3ac4565..facedd10 100644 --- a/webapp/src/components/bp-chip-avatar/index.js +++ b/webapp/src/components/BpChipAvatar/index.js @@ -1,9 +1,10 @@ import React, { memo } from 'react' import PropTypes from 'prop-types' -import Chip from '@material-ui/core/Chip' -import Avatar from '@material-ui/core/Avatar' +import clsx from 'clsx' +import Chip from '@mui/material/Chip' +import Avatar from '@mui/material/Avatar' import _get from 'lodash.get' -import { makeStyles } from '@material-ui/core/styles' +import { makeStyles } from '@mui/styles' import styles from './styles' @@ -17,14 +18,14 @@ const ProducerChipAvatar = ({ defaultName, isProxy }) => { - const backgroundColor = _get(data, 'data.pointBackgroundColor', '#597a81') + const backgroundColor = _get(data, 'data.color', '#597a81') const classes = useStyles({ color: backgroundColor }) return ( <> {isProxy && ( {!imageURL ? ( @@ -39,7 +40,7 @@ const ProducerChipAvatar = ({ )} {!isProxy && ( {!imageURL ? ( diff --git a/webapp/src/components/BpChipAvatar/styles.js b/webapp/src/components/BpChipAvatar/styles.js new file mode 100644 index 00000000..cb0913b5 --- /dev/null +++ b/webapp/src/components/BpChipAvatar/styles.js @@ -0,0 +1,9 @@ +export default props => ({ + rootChip: { + marginBottom: '8px !important', + color: 'white !important', + justifyContent: 'space-around !important', + width: 158, + backgroundColor: props => `${props.color} !important` + } +}) diff --git a/webapp/src/components/card/index.js b/webapp/src/components/Card/index.js similarity index 62% rename from webapp/src/components/card/index.js rename to webapp/src/components/Card/index.js index 12062d9a..ae493095 100644 --- a/webapp/src/components/card/index.js +++ b/webapp/src/components/Card/index.js @@ -1,24 +1,26 @@ -import React, { useState, forwardRef, useEffect } from 'react' +import React, { useState, forwardRef } from 'react' import PropTypes from 'prop-types' -import { makeStyles } from '@material-ui/styles' -import { useTheme } from '@material-ui/core/styles' -import useMediaQuery from '@material-ui/core/useMediaQuery' -import Card from '@material-ui/core/Card' -import Box from '@material-ui/core/Box' -import CardHeader from '@material-ui/core/CardHeader' +import clsx from 'clsx' +import { makeStyles } from '@mui/styles' +import { useTheme } from '@mui/material/styles' import { useTranslation } from 'react-i18next' -import Typography from '@material-ui/core/Typography' -import CardActions from '@material-ui/core/CardActions' -import Avatar from '@material-ui/core/Avatar' -import Button from '@material-ui/core/Button' -import Help from '@material-ui/icons/HelpOutlineRounded' -import Error from '@material-ui/icons/Error' -import Tooltip from '@material-ui/core/Tooltip' -import Grid from '@material-ui/core/Grid' -import { Link } from '@reach/router' -import KeyboardArrowRightIcon from '@material-ui/icons/KeyboardArrowRight' +import useMediaQuery from '@mui/material/useMediaQuery' +import Card from '@mui/material/Card' +import Box from '@mui/material/Box' +import CardHeader from '@mui/material/CardHeader' +import Typography from '@mui/material/Typography' +import CardActions from '@mui/material/CardActions' +import Avatar from '@mui/material/Avatar' +import Button from '@mui/material/Button' +import Help from '@mui/icons-material/HelpOutlineRounded' +import Error from '@mui/icons-material/Error' +import Tooltip from '@mui/material/Tooltip' +import Grid from '@mui/material/Grid' +import { Link } from 'react-router-dom' +import KeyboardArrowRightIcon from '@mui/icons-material/KeyboardArrowRight' -import Radar from 'components/radar' +// import Radar from '../Radar' +import PolarChart from '../PolarChart' import styles from './styles' @@ -53,25 +55,25 @@ const CardData = ({ average, rate, showOptions, - isNewRate, - ...props + isNewRate }) => { const { t } = useTranslation('translations') const [open, setOpen] = useState(false) const classes = useStyles() const theme = useTheme() const isMobile = useMediaQuery(theme.breakpoints.only('xs')) - const isDesktop = useMediaQuery('(min-width:770px)') - const [sizes, setSizes] = useState() + // const isDesktop = useMediaQuery('(min-width:770px)') + // const [sizes, setSizes] = useState() - const handleTooltip = (e) => { + const handleTooltip = e => { setOpen(!open) e.preventDefault() } - useEffect(() => { - setSizes(isDesktop ? 400 : '95%') - }, [isDesktop]) + // useEffect(() => { + // // setSizes(isDesktop ? 400 : '95%') + // // console.log({ sizes }) + // }, [isDesktop]) return ( @@ -93,29 +95,31 @@ const CardData = ({ } title={ -
+ {title || owner} -
+ } subheader={ -
- {owner} - + + + {owner} + + {t('view')} -
+ } /> -
-
+ + {!title && ( )} -
- + + + + {showOptions && ( - + {`${t('rateCard')}:`} - {rate || 0} + + {rate || 0} + {`${t('averageCard')}:`} - {average} + + {average} + )} -
+ {useRateButton && ( <> @@ -193,9 +196,10 @@ const CardData = ({ {!useRateButton && ( <> + + + )} + {!isProxy && ( + + + + setIsCollapsedView(event.target.checked) + } + value='isCollapsedView' + /> + } + label={t('compareToolCollapsedSwitch')} + /> + + + )} + + + {selected.length > 0 ? ( + + ) : ( + + + {t('noSelectedBP')} + + + )} + + + {!isProxy && ( + + + + + )} + + + + {selected.length > 0 ? ( + + ) : ( + + {t('noSelectedBP')} + + )} + + + + ) +} + +CompareGraphView.propTypes = { + removeBP: PropTypes.func.isRequired, + selected: PropTypes.array.isRequired, + isProxy: PropTypes.bool, + userInfo: PropTypes.object, + handleOnClear: PropTypes.func, + handleOnClose: PropTypes.func, + onHandleVote: PropTypes.func, + setIsCollapsedView: PropTypes.func, + isCollapsedView: PropTypes.bool +} + +CompareGraphView.defaultProps = { + isProxy: false, + userInfo: { proxy: '', producers: [], isUser: false }, + onHandleVote: () => {}, + handleOnClear: () => {}, + handleOnClose: () => {}, + setIsCollapsedView: () => {}, + isCollapsedView: true +} + +CompareBodyList.propTypes = { + isProxy: PropTypes.bool, + selectedData: PropTypes.array, + classes: PropTypes.object.isRequired, + removeBP: PropTypes.func.isRequired +} + +TooltipWrapper.propTypes = { + classes: PropTypes.object, + isClickable: PropTypes.bool, + open: PropTypes.bool, + onHandleTooltip: PropTypes.func, + t: PropTypes.any, + userHasVote: PropTypes.bool, + isUser: PropTypes.bool.apply +} + +export default CompareGraphView diff --git a/webapp/src/components/CompareTool/CompareSliderView.js b/webapp/src/components/CompareTool/CompareSliderView.js new file mode 100644 index 00000000..0a7cacd3 --- /dev/null +++ b/webapp/src/components/CompareTool/CompareSliderView.js @@ -0,0 +1,84 @@ +import React from 'react' +import { makeStyles } from '@mui/styles' +// import useMediaQuery from '@mui/material/useMediaQuery' +import CloseIcon from '@mui/icons-material/Close' +import { useTranslation } from 'react-i18next' +import PropTypes from 'prop-types' +import Typography from '@mui/material/Typography' +import Box from '@mui/material/Box' +import _get from 'lodash.get' + +import PolarChart from '../PolarChart' + +import styles from './styles' + +const useStyles = makeStyles(styles) + +const CompareSliderView = ({ + selected, + className, + isProxy, + optionalLabel, + handleOnClose +}) => { + const { t } = useTranslation('translations') + const classes = useStyles() + // const isDesktop = useMediaQuery('(min-width:767px)') + // const [sizes, setSizes] = useState() + + // useEffect(() => { + // // setSizes(isDesktop ? 400 : '95%') + // }, [isDesktop]) + + return ( + + + + + {isProxy ? optionalLabel : t('compareToolTitle')} + + + + + + + + + {selected.map((bp, index) => { + if (!bp) return null + + const name = isProxy + ? _get(bp, 'owner') + : _get(bp, 'bpjson.producer_account_name') + + return ( + + + + + + + {name} + + + ) + })} + + + ) +} + +CompareSliderView.propTypes = { + selected: PropTypes.array.isRequired, + className: PropTypes.string, + isProxy: PropTypes.bool, + handleOnClose: PropTypes.func, + optionalLabel: PropTypes.string +} + +CompareSliderView.defaultProps = {} + +export default CompareSliderView diff --git a/webapp/src/components/compare-tool/index.js b/webapp/src/components/CompareTool/index.js similarity index 63% rename from webapp/src/components/compare-tool/index.js rename to webapp/src/components/CompareTool/index.js index 71c1f022..2e8bd232 100644 --- a/webapp/src/components/compare-tool/index.js +++ b/webapp/src/components/CompareTool/index.js @@ -1,21 +1,26 @@ -import React, { useState } from 'react' +import React, { useState, forwardRef } from 'react' import PropTypes from 'prop-types' -import { makeStyles } from '@material-ui/core/styles' -import Button from '@material-ui/core/Button' -import FormControlLabel from '@material-ui/core/FormControlLabel' +import { makeStyles } from '@mui/styles' import { useTranslation } from 'react-i18next' +import Button from '@mui/material/Button' +import Box from '@mui/material/Box' +import FormControlLabel from '@mui/material/FormControlLabel' import _get from 'lodash.get' -import Switch from '@material-ui/core/Switch' -import Snackbar from '@material-ui/core/Snackbar' -import MuiAlert from '@material-ui/lab/Alert' +import Switch from '@mui/material/Switch' +import Snackbar from '@mui/material/Snackbar' +import MuiAlert from '@mui/material/Alert' import clsx from 'clsx' -import CompareGraphView from './compare-graph-view' -import CompareSliderView from './compare-slider-view' +import CompareGraphView from './CompareGraphView' +import CompareSliderView from './CompareSliderView' import styles from './styles' const useStyles = makeStyles(styles) +const Alert = forwardRef(function Alert(props, ref) { + return +}) + const CompareTool = ({ removeBP, list, @@ -34,7 +39,7 @@ const CompareTool = ({ const { t } = useTranslation('translations') const classes = useStyles() const [isCollapsedView, setIsCollapsedView] = useState(true) - const selectedData = selected.map((name) => + const selectedData = selected.map(name => list.find(({ owner }) => name === owner) ) const { proxy, producers } = _get(userInfo, 'voter_info', { @@ -42,11 +47,7 @@ const CompareTool = ({ producers: [] }) - function Alert(props) { - return - } - - const handleClose = (event, reason) => { + const handleClose = (e, reason) => { if (reason === 'clickaway') { return } @@ -61,19 +62,19 @@ const CompareTool = ({ : selectedData return ( -
+ -
+ ) } return ( -
{isCollapsedView ? ( @@ -81,7 +82,7 @@ const CompareTool = ({ removeBP={removeBP} selected={selectedData} isProxy={isProxy} - userInfo={{ proxy, producers, isUser: Boolean(userInfo) }} + userInfo={{ proxy, producers, isUser: !!userInfo }} handleOnClear={handleOnClear} handleOnClose={handleOnClose} onHandleVote={onHandleVote} @@ -89,27 +90,31 @@ const CompareTool = ({ setIsCollapsedView={setIsCollapsedView} /> ) : ( - + )} -
- {!isCollapsedView && ( - <> - setIsCollapsedView(event.target.checked)} - value='isCollapsedView' - /> - } - label={t('compareToolCollapsedSwitch')} - /> - + {!isCollapsedView && ( + + setIsCollapsedView(event.target.checked)} + value='isCollapsedView' + color='primary' + /> + } + label={t('compareToolCollapsedSwitch')} + /> + @@ -119,19 +124,19 @@ const CompareTool = ({ onClick={onHandleVote} className={classes.btnRate} variant='contained' - size='large' + color='secondary' > {t('voteToolToggle')} - - )} -
+ + + )} - + {message.txError} @@ -140,11 +145,15 @@ const CompareTool = ({ autoHideDuration={4000} onClose={handleClose} > - + {t('success')} -
+ ) } diff --git a/webapp/src/components/CompareTool/styles.js b/webapp/src/components/CompareTool/styles.js new file mode 100644 index 00000000..db627240 --- /dev/null +++ b/webapp/src/components/CompareTool/styles.js @@ -0,0 +1,277 @@ +export default theme => ({ + // index + root: { + padding: theme.spacing(2), + background: theme.palette.surface.main, + width: '100%', + position: 'relative' + }, + compareGraphView: { + paddingTop: 0, + height: '100%', + [theme.breakpoints.up('md')]: { + paddingTop: theme.spacing(2) + } + }, + wrapperDesktop: { + display: 'flex', + flexDirection: 'column', + height: 'calc(100% - 75px)', + [theme.breakpoints.up('md')]: { + flexDirection: 'row' + } + }, + btnClear: { + textAlign: 'center', + width: 200 + }, + footer: { + display: 'flex', + paddingTop: theme.spacing(2), + flexDirection: 'column', + width: '100%', + height: 'calc(50% - 170px)', + justifyContent: 'space-between', + alignItems: 'center', + [theme.breakpoints.up('md')]: { + flexDirection: 'row', + justifyContent: 'space-evenly', + margin: 'auto', + bottom: 0, + width: 'calc(50% - 16px)' + } + }, + modalHeader: { + display: 'flex', + justifyContent: 'space-between', + marginTop: theme.spacing(1), + marginBottom: theme.spacing(2) + }, + switch: { + [theme.breakpoints.up('md')]: { + float: 'right' + } + }, + switchBox: { + textAlign: 'center', + height: 60 + }, + btnRate: { + width: 100, + [theme.breakpoints.up('md')]: { + float: 'right', + marginRight: 20, + '&:hover': { + backgroundColor: theme.palette.secondary.dark + } + } + }, + chipMessage: { + [theme.breakpoints.up('sm')]: { + float: 'right', + marginTop: 5, + marginRight: 5 + } + }, + errorColor: { + backgroundColor: theme.palette.error.main + }, + errorChip: { + border: `1px solid ${theme.palette.error.main}` + }, + labelErrorColor: { + color: theme.palette.error.main + }, + // slider view + bpName: { + paddingTop: 10, + textAlign: 'center' + }, + slider: { + display: 'flex', + flexWrap: 'nowrap', + overflowX: 'auto', + '-webkit-overflow-scrolling': 'touch', + '&::-webkit-scrollbar': { + display: 'none' + } + }, + sliderCard: { + flex: '0 0 auto', + width: 360, + paddingRight: 16 + }, + // graph view + bpItem: { + width: '75%', + padding: '0 0 0 10px', + display: 'flex', + justifyContent: 'space-between', + '&:hover': { + backgroundColor: theme.palette.primary.submenu + } + }, + bpNameWrapper: { + height: 48, + paddingTop: 14 + }, + bpColorCode: { + display: 'inline-block', + width: 15, + height: 15, + verticalAlign: 'text-bottom' + }, + title: { + textDecoration: 'none', + color: theme.palette.primary.main + }, + avatar: { + backgroundColor: theme.palette.surface.main + }, + helpIcon: { + width: '90%', + height: '90%' + }, + cardHeader: { + borderBottom: `1px solid ${theme.palette.primary.light}` + }, + titleLock: { + display: 'flex', + justifyContent: 'stretch', + alignItems: 'center' + }, + headerVotingCompare: { + display: 'flex', + justifyContent: 'space-between', + flexDirection: 'column' + }, + marginRightElem: { + marginRight: 10 + }, + icon: { + color: theme.palette.primary.submenu, + fontSize: 30, + '&:hover': { + cursor: 'pointer' + } + }, + containerList: { + display: 'flex', + justifyContent: 'space-between', + height: '100%', + width: '100%', + minHeight: 50, + flexWrap: 'wrap', + [theme.breakpoints.up('sm')]: { + marginBottom: 38, + justifyContent: 'space-around' + }, + [theme.breakpoints.up('md')]: { + justifyContent: 'space-between', + marginBottom: 0 + } + }, + centerBox: { + margin: 'auto', + width: '45%', + padding: '5px', + [theme.breakpoints.down('sm')]: { + width: '100%' + } + }, + buttonsBox: { + justifyContent: 'space-between', + display: 'flex', + alignItems: 'center', + [theme.breakpoints.up('md')]: { + justifyContent: 'center' + } + }, + boxCloseIcon: { + justifyContent: 'flex-end', + display: 'flex', + alignItems: 'center', + height: '100%' + }, + btnRateProxies: { + backgroundColor: theme.palette.secondary.main, + color: '#ffffff', + width: '100px', + padding: '5px 20px 5px 20px', + [theme.breakpoints.up('sm')]: { + '&:hover': { + backgroundColor: theme.palette.secondary.dark + } + } + }, + reliefGrid: { + [theme.breakpoints.up('md')]: { + border: '1px solid #f8f8f8', + boxShadow: + 'inset 2px 2px 2px #fff, inset -1px 0 2px rgba(0,0,0,.1), 1px 3px 3px rgba(0,0,0,.1)', + backgroundColor: '#fff' + } + }, + compareBodyListDesktop: { + display: 'none', + [theme.breakpoints.up('md')]: { + display: 'flex' + } + }, + compareBodyListMobile: { + display: 'flex', + [theme.breakpoints.up('md')]: { + display: 'none' + } + }, + noBPSelected: { + padding: theme.spacing(4, 4, 0, 3), + textAlign: 'center' + }, + bodyModalView: { + height: 'calc(100% - 100px)', + display: 'flex', + justifyContent: 'space-between', + flexDirection: 'column' + }, + topModalView: { + marginBottom: theme.spacing(2) + }, + btnBox: { + width: '100%', + display: 'flex', + justifyContent: 'space-between' + }, + alert: { + width: '100%' + }, + proxyVote: { + width: '100%', + display: 'flex', + flexDirection: 'column', + alignItems: 'center' + }, + chartWrapper: { + '& .highcharts-container ': { + height: '400px !important', + width: '340px !important', + '& > svg': { + height: '400px !important', + width: '340px !important' + }, + [theme.breakpoints.up('sm')]: { + height: '400px !important', + width: '600px !important', + '& > svg': { + height: '400px !important', + width: '600px !important' + } + } + } + }, + overrideBreakpoint: { + [theme.breakpoints.up('md')]: { + margin: `${theme.spacing(0, 1, 1, 1)} !important` + } + } +}) diff --git a/webapp/src/components/main-footer/index.js b/webapp/src/components/Footer/index.js similarity index 60% rename from webapp/src/components/main-footer/index.js rename to webapp/src/components/Footer/index.js index fc378f6c..cddfa99a 100644 --- a/webapp/src/components/main-footer/index.js +++ b/webapp/src/components/Footer/index.js @@ -1,24 +1,24 @@ -import React from 'react' -import { makeStyles } from '@material-ui/styles' -import AppBar from '@material-ui/core/AppBar' -import Toolbar from '@material-ui/core/Toolbar' -import Typography from '@material-ui/core/Typography' +import React, { memo } from 'react' import { useTranslation } from 'react-i18next' -import IconButton from '@material-ui/core/IconButton' - -import TelegramIcon from 'components/telegram-icon' -import GithubIcon from 'components/github-icon' +// import AppBar from '@mui/material/AppBar' +import Toolbar from '@mui/material/Toolbar' +import Typography from '@mui/material/Typography' +import IconButton from '@mui/material/IconButton' +import GitHubIcon from '@mui/icons-material/GitHub' +import TelegramIcon from '@mui/icons-material/Telegram' +import Box from '@mui/material/Box' +import { makeStyles } from '@mui/styles' import styles from './styles' const useStyles = makeStyles(styles) -const MainFooter = () => { - const { t } = useTranslation('footer') +const Footer = () => { const classes = useStyles() + const { t } = useTranslation('footer') return ( - + { className={classes.eoscostaricaLogo} /> -
+ { target='_blank' color='inherit' > - + - + - + ) } -export default MainFooter +export default memo(Footer) diff --git a/webapp/src/components/Footer/styles.js b/webapp/src/components/Footer/styles.js new file mode 100644 index 00000000..ee158934 --- /dev/null +++ b/webapp/src/components/Footer/styles.js @@ -0,0 +1,38 @@ +export default theme => ({ + root: { + padding: theme.spacing(1), + backgroundColor: theme.palette.primary.main + }, + listItem: { + display: 'inline-block', + width: 'auto', + paddingLeft: theme.spacing(2), + paddingRight: theme.spacing(2), + '&:hover, &:active:': { + color: theme.palette.action.selected + } + }, + grow: { + flexGrow: 1 + }, + eoscostaricaLogo: { + height: 36, + width: 'auto' + }, + link: { + color: theme.palette.common.white, + textDecoration: 'none' + }, + legend: { + display: 'flex', + width: 150, + lineHeight: '1.4 !important', + fontSize: '8px !important', + fontWeight: '500 !important', + fontStretch: 'normal', + letterSpacing: '1.1px !important', + textAlign: 'right !important', + color: 'rgba(255, 255, 255, 0.6)', + paddingRight: theme.spacing(2) + } +}) diff --git a/webapp/src/components/Header/index.js b/webapp/src/components/Header/index.js new file mode 100644 index 00000000..24bd8a93 --- /dev/null +++ b/webapp/src/components/Header/index.js @@ -0,0 +1,144 @@ +import React, { memo, useState } from 'react' +import { makeStyles } from '@mui/styles' +import PropTypes from 'prop-types' +import { useTranslation } from 'react-i18next' +import { useHistory, Link } from 'react-router-dom' +import AppBar from '@mui/material/AppBar' +import IconButton from '@mui/material/IconButton' +import Box from '@mui/material/Box' +import Typography from '@mui/material/Typography' +import SearchIcon from '@material-ui/icons/Search' +import Toolbar from '@mui/material/Toolbar' +import MenuIcon from '@mui/icons-material/Menu' +import FingerprintIcon from '@mui/icons-material/Fingerprint' +import ExitIcon from '@mui/icons-material/ExitToApp' + +import { useSharedState } from '../../context/state.context' +import MobileSearch from '../../components/MobileSearch' + +import InputAutocomplete from '../InputAutocomplete' +import LanguageSelector from '../LanguageSelector' + +import styles from './styles' + +const useStyles = makeStyles(styles) + +const AuthButton = memo(({ user, onLogin, onSignOut }) => { + const { t } = useTranslation('translations') + const classes = useStyles() + + return ( + <> + {user && ( + + + {t('signOut')} + + )} + {!user && ( + + + + {t('appBarSignIn')} + + + )} + + ) +}) + +AuthButton.displayName = 'AuthButton' + +AuthButton.propTypes = { + user: PropTypes.any, + onLogin: PropTypes.func, + onSignOut: PropTypes.func +} + +const Header = memo(({ onDrawerToggle }) => { + const classes = useStyles() + const history = useHistory() + const [state, { login, logout }] = useSharedState() + const [isSearchOpen, setIsSearchOpen] = useState() + + const stage = 'false' // TODO: add to context + + const handleLogin = () => { + login() + } + + const handleSignOut = () => { + logout() + history.push('/') + } + + const handleOpenSearch = () => { + setIsSearchOpen(true) + } + + const handleCloseSearch = () => { + setIsSearchOpen(false) + } + + return ( + + + + + + + + EOS Rate + + + + + + + + + + + + + + + + + + + + ) +}) + +Header.displayName = 'Header' + +Header.propTypes = { + onDrawerToggle: PropTypes.func +} + +export default Header diff --git a/webapp/src/components/Header/styles.js b/webapp/src/components/Header/styles.js new file mode 100644 index 00000000..069ddf63 --- /dev/null +++ b/webapp/src/components/Header/styles.js @@ -0,0 +1,92 @@ +export default theme => ({ + appBar: { + boxShadow: theme.shadows[0], + borderBottom: `1px solid ${theme.palette.divider}`, + [theme.breakpoints.up('md')]: { + boxShadow: theme.shadows[4], + borderBottom: 0 + } + }, + toolbar: { + padding: 0, + justifyContent: 'space-between', + paddingLeft: `${theme.spacing(1)} !important`, + paddingRight: `${theme.spacing(1)} !important`, + [theme.breakpoints.up('md')]: { + padding: theme.spacing(0, 2) + } + }, + typography: { + color: theme.palette.text.primary, + flexGrow: 1 + }, + desktopSection: { + display: 'none', + height: 54, + alignItems: 'center', + justifyContent: 'space-between', + '& svg, & span': { + color: theme.palette.common.white + }, + [theme.breakpoints.up('md')]: { + display: 'flex' + } + }, + mobileSection: { + display: 'flex', + [theme.breakpoints.up('md')]: { + display: 'none' + } + }, + boxLogo: { + display: 'flex', + '& svg': { + color: theme.palette.common.white + }, + '& img': { + width: 145 + }, + [theme.breakpoints.up('md')]: { + '& img': { + width: 180 + } + } + }, + boxSearch: { + display: 'none', + [theme.breakpoints.up('md')]: { + display: 'flex' + } + }, + onSignOut: { + '& svg': { + color: theme.palette.common.white + } + }, + onLogin: { + '& svg': { + color: theme.palette.common.white + } + }, + textBtn: { + display: 'none', + [theme.breakpoints.up('md')]: { + display: 'flex', + color: theme.palette.common.white, + fontFamily: 'Roboto', + fontStyle: 'normal', + fontWeight: 'normal', + fontSize: 20, + lineHeight: '23px', + marginLeft: `${theme.spacing(0.5)} !important` + } + }, + link: { + display: 'flex' + }, + mobileSearch: { + '& svg': { + color: theme.palette.common.white + } + } +}) diff --git a/webapp/src/components/input-autocomplete/index.js b/webapp/src/components/InputAutocomplete/index.js similarity index 57% rename from webapp/src/components/input-autocomplete/index.js rename to webapp/src/components/InputAutocomplete/index.js index 8e23156e..0cc7ca58 100644 --- a/webapp/src/components/input-autocomplete/index.js +++ b/webapp/src/components/InputAutocomplete/index.js @@ -1,18 +1,21 @@ import React, { useEffect, useState } from 'react' +import { useLazyQuery } from '@apollo/client' import PropTypes from 'prop-types' -import { useDispatch, useSelector } from 'react-redux' -import { navigate } from '@reach/router' +import { useHistory } from 'react-router-dom' import Highlight from 'react-highlighter' import Autosuggest from 'react-autosuggest' -import filterObjects from 'filter-objects' -import { makeStyles } from '@material-ui/styles' +import { makeStyles } from '@mui/styles' import { useTranslation } from 'react-i18next' -import SearchIcon from '@material-ui/icons/Search' -import TextField from '@material-ui/core/TextField' -import InputAdornment from '@material-ui/core/InputAdornment' -import Paper from '@material-ui/core/Paper' +import SearchIcon from '@mui/icons-material/Search' +import TextField from '@mui/material/TextField' +import InputAdornment from '@mui/material/InputAdornment' +import Paper from '@mui/material/Paper' +import Box from '@mui/material/Box' import _get from 'lodash.get' -import MenuItem from '@material-ui/core/MenuItem' +import MenuItem from '@mui/material/MenuItem' + +import useDebounce from '../../hooks/useDebounce' +import { GET_ITEM_BY_NAME } from '../../gql' import styles from './styles' @@ -20,61 +23,63 @@ const useStyles = makeStyles(styles) const InputAutocomplete = ({ ...props }) => { const classes = useStyles() + const history = useHistory() const { t } = useTranslation('translations') - const dispatch = useDispatch() - const { list } = useSelector((state) => state.blockProducers) - const { proxies } = useSelector((state) => state.proxies) + const [searchText, setSearchText] = useState('') + const debouncedAccount = useDebounce(searchText, 300) + const [getData, { loading, data }] = useLazyQuery(GET_ITEM_BY_NAME, { + fetchPolicy: 'network-only' + }) const [suggestions, setSuggestions] = useState([]) - const [text, setText] = useState('') - const [data, setData] = useState([]) useEffect(() => { - const getData = async () => { - await dispatch.blockProducers.getBPs() - await dispatch.proxies.getProxies() + if (loading || !data) { + return } - getData() - }, []) - - useEffect(() => { - const bpsList = (list || []).map((bp) => { + const { producers, proxies } = data + const bpsList = (producers || []).map(bp => { const name = _get(bp, 'bpjson.org.candidate_name', bp.owner) - return { name, owner: bp.owner, path: '/block-producers/' } + return { owner: bp.owner, name, path: '/block-producers/' } }) - const proxiesList = (proxies || []).map((proxy) => { - const name = _get(proxy, 'name', proxy.owner) - - return { name, owner: proxy.owner, path: '/proxies/' } + const proxiesList = (proxies || []).map(proxy => { + return { ...proxy, path: '/proxies/' } }) - setData([...bpsList, ...proxiesList]) - }, [list, proxies]) + setSuggestions([...bpsList, ...proxiesList]) + }, [data, loading]) + + useEffect(() => { + const getDataAsync = async () => { + await getData({ variables: { name: `%${debouncedAccount}%` } }) + } + + if (debouncedAccount.length) { + getDataAsync(debouncedAccount) + } + }, [debouncedAccount]) - const renderInputComponent = (inputProps) => { + const renderInputComponent = inputProps => { const { inputRef = () => {}, ref, classes, ...other } = inputProps - const { hideSearchIcon, isFocused } = props + const { hideSearchIcon, isFocused = true } = props return ( { + inputRef: node => { ref(node) inputRef(node) }, - disableUnderline: true, + disableunderline: 'true', fullWidth: true, startAdornment: hideSearchIcon ? null : ( - ), - classes: { - input: classes.input - } + ) }} classes={{ root: classes.root @@ -96,52 +101,40 @@ const InputAutocomplete = ({ ...props }) => { ) - const getSuggestions = (list, value) => { - return filterObjects.filter( - { - name: new RegExp(`${value.trim()}`, 'gi') - }, - list - ) - } - const getSuggestionValue = ({ name }) => name - const handleSuggestionsFetchRequested = - (list) => - ({ value }) => - setSuggestions(getSuggestions(list, value)) + const handleSuggestionsFetchRequested = ({ value }) => { + setSearchText(value) + } const handleSuggestionsClearRequested = () => { - setText('') + setSearchText('') setSuggestions([]) } const handleSelected = (event, { newValue }) => { - setText(newValue) + setSearchText(newValue) } - const handleSelectedSuggestion = (event, { suggestion }) => { - navigate(`${suggestion.path}${suggestion.owner}`) + const handleSelectedSuggestion = (e, { suggestion }) => { + history.push(`${suggestion.path}${suggestion.owner}`) props.onItemSelected && props.onItemSelected() } return ( -
+ { - handleSuggestionsFetchRequested(data)(event) - }} + onSuggestionsFetchRequested={handleSuggestionsFetchRequested} onSuggestionsClearRequested={() => handleSuggestionsClearRequested()} getSuggestionValue={getSuggestionValue} renderSuggestion={renderSuggestion} inputProps={{ classes, placeholder: t('searchAutocomplete'), - value: text, + value: searchText, onChange: handleSelected }} theme={{ @@ -150,13 +143,13 @@ const InputAutocomplete = ({ ...props }) => { suggestionsList: classes.suggestionsList, suggestion: classes.suggestion }} - renderSuggestionsContainer={(options) => ( + renderSuggestionsContainer={options => ( {options.children} )} /> -
+ ) } diff --git a/webapp/src/components/InputAutocomplete/styles.js b/webapp/src/components/InputAutocomplete/styles.js new file mode 100644 index 00000000..7d3fa7c7 --- /dev/null +++ b/webapp/src/components/InputAutocomplete/styles.js @@ -0,0 +1,61 @@ +export default theme => ({ + root: { + flexGrow: 1, + '& input': { + color: theme.palette.common.white, + fontFamily: 'Roboto', + fontStyle: 'normal', + fontWeight: 'normal', + fontSize: 20, + lineHeight: '23px' + }, + '& .MuiOutlinedInput-notchedOutline': { + borderColor: 'transparent !important' + } + }, + container: { + position: 'relative', + margin: 'auto', + borderRadius: 4, + width: '100%', + [theme.breakpoints.up('md')]: { + width: 344, + backgroundColor: 'rgba(0, 0, 0, 0.50)', + '&:hover': { + backgroundColor: 'rgba(0, 0, 0, 0.45)' + } + } + }, + suggestionsContainerOpen: { + position: 'absolute', + zIndex: 1, + marginTop: theme.spacing(1), + left: '-24px', + right: 0, + width: '100vw', + [theme.breakpoints.up('md')]: { + left: 0, + width: 'auto' + } + }, + highlightMatch: { + fontWeight: 600 + }, + suggestion: { + display: 'block' + }, + suggestionsList: { + margin: 0, + padding: 0, + listStyleType: 'none' + }, + inputAdornment: { + margin: '5px 25px 5px 0', + [theme.breakpoints.up('md')]: { + margin: '5px 25px' + } + }, + searchIcon: { + color: theme.palette.common.white + } +}) diff --git a/webapp/src/components/Loader/index.js b/webapp/src/components/Loader/index.js new file mode 100644 index 00000000..a680fb2b --- /dev/null +++ b/webapp/src/components/Loader/index.js @@ -0,0 +1,20 @@ +import React from 'react' +import { makeStyles } from '@mui/styles' +import CircularProgress from '@mui/material/CircularProgress' +import Box from '@mui/material/Box' + +import styles from './styles' + +const useStyles = makeStyles(styles) + +const Loader = () => { + const classes = useStyles() + + return ( + + + + ) +} + +export default Loader diff --git a/webapp/src/components/Loader/styles.js b/webapp/src/components/Loader/styles.js new file mode 100644 index 00000000..218ab7a8 --- /dev/null +++ b/webapp/src/components/Loader/styles.js @@ -0,0 +1,8 @@ +export default () => ({ + root: { + justifyContent: 'center', + alignItems: 'center', + display: 'flex', + minHeight: '100%' + } +}) diff --git a/webapp/src/components/Message/index.js b/webapp/src/components/Message/index.js new file mode 100644 index 00000000..06a1908c --- /dev/null +++ b/webapp/src/components/Message/index.js @@ -0,0 +1,48 @@ +import React, { useEffect, useState } from 'react' +import { makeStyles } from '@mui/styles' +import Snackbar from '@mui/material/Snackbar' +import Alert from '@mui/material/Alert' + +import { useSharedState } from '../../context/state.context' + +import styles from './styles' + +const useStyles = makeStyles(styles) + +const Message = () => { + const [open, setOpen] = useState(false) + const [{ message }, { hideMessage }] = useSharedState() + const classes = useStyles() + + const handleClose = (event, reason) => { + if (reason === 'clickaway') { + return + } + + setOpen(false) + hideMessage() + } + + useEffect(() => { + if (open === !!message) { + return + } + + setOpen(!!message) + }, [message]) + + return ( + + + {message?.content} + + + ) +} + +export default Message diff --git a/webapp/src/components/Message/styles.js b/webapp/src/components/Message/styles.js new file mode 100644 index 00000000..72e960da --- /dev/null +++ b/webapp/src/components/Message/styles.js @@ -0,0 +1,8 @@ +export default theme => ({ + alert: { + '& a': { + color: theme.palette.info.contrastText, + lineBreak: 'anywhere' + } + } +}) diff --git a/webapp/src/components/mobile-search/index.js b/webapp/src/components/MobileSearch/index.js similarity index 68% rename from webapp/src/components/mobile-search/index.js rename to webapp/src/components/MobileSearch/index.js index 2eb0c9b2..e19694c5 100644 --- a/webapp/src/components/mobile-search/index.js +++ b/webapp/src/components/MobileSearch/index.js @@ -1,14 +1,14 @@ import React, { forwardRef } from 'react' import PropTypes from 'prop-types' -import { makeStyles } from '@material-ui/styles' -import Dialog from '@material-ui/core/Dialog' -import AppBar from '@material-ui/core/AppBar' -import Toolbar from '@material-ui/core/Toolbar' -import IconButton from '@material-ui/core/IconButton' -import CloseIcon from '@material-ui/icons/Close' -import Slide from '@material-ui/core/Slide' +import { makeStyles } from '@mui/styles' +import Dialog from '@mui/material/Dialog' +import AppBar from '@mui/material/AppBar' +import Toolbar from '@mui/material/Toolbar' +import IconButton from '@mui/material/IconButton' +import CloseIcon from '@mui/icons-material/Close' +import Slide from '@mui/material/Slide' -import InputAutocomplete from 'components/input-autocomplete' +import InputAutocomplete from '../InputAutocomplete' import styles from './styles' @@ -46,4 +46,9 @@ MobileSearch.propTypes = { onClose: PropTypes.func } +MobileSearch.defaultProps = { + isOpen: false, + onClose: () => {} +} + export default MobileSearch diff --git a/webapp/src/components/mobile-search/styles.js b/webapp/src/components/MobileSearch/styles.js similarity index 100% rename from webapp/src/components/mobile-search/styles.js rename to webapp/src/components/MobileSearch/styles.js diff --git a/webapp/src/components/PageTitle/index.js b/webapp/src/components/PageTitle/index.js new file mode 100644 index 00000000..3cd0705a --- /dev/null +++ b/webapp/src/components/PageTitle/index.js @@ -0,0 +1,21 @@ +import React, { memo } from 'react' +import Helmet from 'react-helmet' +import PropTypes from 'prop-types' + +import { mainConfig } from '../../config' + +const PageTitle = ({ title }) => ( + + {title} + +) + +PageTitle.propTypes = { + title: PropTypes.string +} + +PageTitle.defaultProps = { + title: mainConfig.title +} + +export default memo(PageTitle) diff --git a/webapp/src/components/parameter-range-selector/index.js b/webapp/src/components/ParameterRangeSelector/index.js similarity index 87% rename from webapp/src/components/parameter-range-selector/index.js rename to webapp/src/components/ParameterRangeSelector/index.js index 385bb173..40d244da 100644 --- a/webapp/src/components/parameter-range-selector/index.js +++ b/webapp/src/components/ParameterRangeSelector/index.js @@ -1,5 +1,5 @@ import React from 'react' -import { useTheme } from '@material-ui/core/styles' +import { useTheme } from '@mui/material/styles' import Slider, { createSliderWithTooltip } from 'rc-slider' import './style.css' @@ -14,7 +14,7 @@ const ParameterRangeSelector = ({ ...props }) => { min={0} max={100} trackStyle={[{ backgroundColor: theme.palette.secondary.dark }]} - tipFormatter={(value) => `${value ? value / 10 : 0}`} + tipFormatter={value => `${value ? value / 10 : 0}`} handleStyle={[ { backgroundColor: theme.palette.secondary.main, diff --git a/webapp/src/components/parameter-range-selector/style.css b/webapp/src/components/ParameterRangeSelector/style.css similarity index 100% rename from webapp/src/components/parameter-range-selector/style.css rename to webapp/src/components/ParameterRangeSelector/style.css diff --git a/webapp/src/components/PolarChart/index.js b/webapp/src/components/PolarChart/index.js new file mode 100644 index 00000000..fa381525 --- /dev/null +++ b/webapp/src/components/PolarChart/index.js @@ -0,0 +1,38 @@ +import React, { useState } from 'react' +import PropTypes from 'prop-types' +import { makeStyles } from '@mui/styles' +import Box from '@mui/material/Box' +import HighchartsReact from 'highcharts-react-official' +import Highcharts from 'highcharts' +import HighchartsMore from 'highcharts/highcharts-more' + +import { polarCharConfig } from '../../config' + +import styles from './styles' + +HighchartsMore(Highcharts) + +const useStyles = makeStyles(styles) + +const PolarChart = ({ data = [] }) => { + const classes = useStyles() + const [options] = useState(polarCharConfig.options) + + return ( + + + + ) +} + +PolarChart.propTypes = { + data: PropTypes.array +} + +export default PolarChart diff --git a/webapp/src/components/PolarChart/styles.js b/webapp/src/components/PolarChart/styles.js new file mode 100644 index 00000000..6ccc4a36 --- /dev/null +++ b/webapp/src/components/PolarChart/styles.js @@ -0,0 +1,42 @@ +export default theme => ({ + highchartsFigure: { + margin: '1em auto', + '& .highcharts-container ': { + margin: '1em auto' + + // height: '400px !important', + // width: '350px !important', + // border: '2px dashed purple', + + // '& > svg': { + // fill: '#94d31b', + // height: '400px !important', + // width: '350px !important' + // }, + + // [theme.breakpoints.up('sm')]: { + // border: '2px solid green', + // height: '400px !important', + // width: '600px !important', + // '& > svg': { + // fill: '#94d31b', + // height: '400px !important', + // width: '600px !important' + // } + // }, + // [theme.breakpoints.up('md')]: { + // border: '2px solid blue', + // height: '400px !important', + // width: '400px !important', + // '& > svg': { + // fill: '#94d31b', + // height: '400px !important', + // width: '450px !important' + // } + // }, + // [theme.breakpoints.up('lg')]: { + // border: '2px solid orange' + // } + } + } +}) diff --git a/webapp/src/components/rate-slider/index.js b/webapp/src/components/RateSlider/index.js similarity index 60% rename from webapp/src/components/rate-slider/index.js rename to webapp/src/components/RateSlider/index.js index 25920ab7..2a66958d 100644 --- a/webapp/src/components/rate-slider/index.js +++ b/webapp/src/components/RateSlider/index.js @@ -1,13 +1,13 @@ -import { withStyles } from '@material-ui/core/styles' -import Slider from '@material-ui/core/Slider' +import { styled } from '@mui/material/styles' +import Slider from '@mui/material/Slider' -const RateSlider = withStyles({ - root: { - color: '#597a81', - height: 2, - padding: '15px 0' - }, - thumb: { +const RateSlider = styled(Slider)({ + color: '#597a81', + height: 2, + padding: '15px 0', + '& .MuiSlider-thumb': { + width: 15, + height: 15, backgroundColor: '#597a81', boxShadow: '0 3px 1px rgba(0,0,0,0.1),0 4px 8px rgba(0,0,0,0.13),0 0 0 1px rgba(0,0,0,0.02)', @@ -21,33 +21,35 @@ const RateSlider = withStyles({ } } }, - active: {}, - valueLabel: { + '& .MuiSlider-valueLabel': { left: 'auto', - top: -15, + top: 0, + background: 'transparent', '& *': { background: 'transparent', - color: '#000' + color: '#000', + fontSize: 12, + fontWeight: '400' } }, - track: { - height: 2 + '& .MuiSlider-track': { + height: 0 }, - rail: { + '& .MuiSlider-rail': { height: 2, opacity: 0.5, backgroundColor: '#010318' }, - mark: { + '& .MuiSlider-mark': { backgroundColor: '#010318', height: 8, width: 1, - marginTop: -3 + marginTop: 0 }, - markActive: { + '& .MuiSlider-markActive': { opacity: 1, backgroundColor: 'currentColor' } -})(Slider) +}) export default RateSlider diff --git a/webapp/src/components/Sidebar/index.js b/webapp/src/components/Sidebar/index.js new file mode 100644 index 00000000..9133ccbe --- /dev/null +++ b/webapp/src/components/Sidebar/index.js @@ -0,0 +1,183 @@ +import React, { memo, useState, useEffect } from 'react' +import PropTypes from 'prop-types' +import { NavLink as RouterNavLink, useHistory } from 'react-router-dom' +import { useTranslation } from 'react-i18next' +import Box from '@mui/material/Box' +import Drawer from '@mui/material/Drawer' +import Divider from '@mui/material/Divider' +import Chip from '@mui/material/Chip' +import List from '@mui/material/List' +import MuiListItem from '@mui/material/ListItem' +import ListItemIcon from '@mui/material/ListItemIcon' +import ListItemText from '@mui/material/ListItemText' +import Collapse from '@mui/material/Collapse' +import Typography from '@mui/material/Typography' +import AccountIcon from '@mui/icons-material/AccountCircle' +import { makeStyles } from '@mui/styles' +import Scrollbar from 'react-perfect-scrollbar' +import 'react-perfect-scrollbar/dist/css/styles.css' + +import { useSharedState } from '../../context/state.context' + +import styles from './styles' + +const useStyles = makeStyles(styles) + +const NavLink = React.forwardRef((props, ref) => ( + +)) + +NavLink.displayName = 'NavLink' + +const ExternalLink = React.forwardRef(({ to, children, className }, ref) => ( + + {children} + +)) + +ExternalLink.displayName = 'NavLink' + +ExternalLink.propTypes = { + to: PropTypes.string, + children: PropTypes.node, + className: PropTypes.string +} + +const ListItem = ({ + childrens, + name, + path, + icon, + badge, + handleOnClick, + openMenu, + isUserLogged, + handleSortBy +}) => { + const classes = useStyles() + const { t: tSort } = useTranslation('sortInput') + const { t } = useTranslation('translations') + + const sortBy = 'generalRate' // get this value form context + + if (name === 'myAccount' && !isUserLogged) return <> + + return ( + + handleOnClick(name)} + > + {icon && {icon}} + + {badge && } + + {childrens && ( + + {childrens.map(({ value }, index) => ( + handleSortBy(value, name)} // setSortBy(value)} + > + + + ))} + + )} + + ) +} + +ListItem.propTypes = { + childrens: PropTypes.array, + name: PropTypes.string, + path: PropTypes.string, + icon: PropTypes.node, + badge: PropTypes.string, + handleOnClick: PropTypes.func, + openMenu: PropTypes.bool, + isUserLogged: PropTypes.bool, + handleSortBy: PropTypes.func +} + +const Sidebar = ({ routes, ...props }) => { + const history = useHistory() + const classes = useStyles() + const [state, { setSortBy }] = useSharedState() + const [openMenu, setOpenMenu] = useState(false) + + const handleOnClick = name => { + setOpenMenu(name === 'blockProducers') + } + + useEffect(() => { + setOpenMenu(history.location.pathname === '/block-producers') + }, []) + + return ( + + + {state.user ? ( + <> + + Welcome + + {state.user?.accountName || ''} + + + ) : ( + eos rate history.push('/')} + /> + )} + + + + + {routes.map((route, index) => ( + + ))} + + + + ) +} + +Sidebar.propTypes = { + routes: PropTypes.array +} + +export default memo(Sidebar) diff --git a/webapp/src/components/Sidebar/styles.js b/webapp/src/components/Sidebar/styles.js new file mode 100644 index 00000000..cde376c0 --- /dev/null +++ b/webapp/src/components/Sidebar/styles.js @@ -0,0 +1,98 @@ +export default theme => ({ + brand: { + backgroundColor: theme.palette.background.paper, + display: 'flex', + justifyContent: 'center', + flexDirection: 'column', + height: 169, + '& img': { + height: 'fit-content', + width: '95%' + }, + '& img:hover': { + cursor: 'pointer' + } + }, + scrollbar: { + backgroundColor: theme.palette.background.paper + }, + badge: { + fontWeight: theme.typography.fontWeightBold, + height: '20px', + backgroundColor: theme.palette.primary.main, + '& span.MuiChip-label, & span.MuiChip-label:hover': { + cursor: 'pointer', + color: theme.palette.primary.contrastText, + padding: theme.spacing(0, 1) + } + }, + listItem: { + display: 'flex', + flexDirection: 'column', + '& p': { + fonWeight: theme.typography.fontWeightBold, + paddingLeft: theme.spacing(2), + cursor: 'default' + }, + '& .MuiBox-root': { + width: '100%', + display: 'flex', + alignItems: 'center', + justifyContent: 'center' + }, + '& .MuiCollapse-container': { + width: '100%', + paddingLeft: theme.spacing(2) + }, + '& .MuiListItemText-root .MuiTypography-root': { + fontSize: theme.typography.subtitle2.fontSize + }, + '& .active': { + backgroundColor: theme.palette.action.selected, + borderRadius: 4 + }, + '& .MuiListItem-button:hover': { + borderRadius: 4 + } + }, + linkSidebar: { + padding: theme.spacing(2, 1), + '& > svg': { + display: 'none' + } + }, + navBox: { + paddingLeft: theme.spacing(1), + paddingRight: theme.spacing(1) + }, + subMenu: { + borderRadius: 4 + }, + subMenuWrapper: { + backgroundColor: theme.palette.surface.dark + }, + welcome: { + fontStyle: 'normal', + fontWeight: '500', + fontSize: '20px !important', + lineHeight: '23px', + letterSpacing: '0.15px', + color: 'rgba(0, 0, 0, 0.87)', + marginBottom: `${theme.spacing(1)} !important`, + marginLeft: `${theme.spacing(2)} !important` + }, + userName: { + fontStyle: 'normal', + fontWeight: 'normal', + fontSize: '14px !important', + lineHeight: '20px', + letterSpacing: '0.25px', + color: 'rgba(0, 0, 0, 0.6)', + marginLeft: `${theme.spacing(2)} !important` + }, + icon: { + fontSize: '48px !important', + marginBottom: theme.spacing(2), + marginLeft: theme.spacing(2) + } +}) diff --git a/webapp/src/components/table/index.js b/webapp/src/components/Table/index.js similarity index 71% rename from webapp/src/components/table/index.js rename to webapp/src/components/Table/index.js index 565448a2..64d6e2ca 100644 --- a/webapp/src/components/table/index.js +++ b/webapp/src/components/Table/index.js @@ -1,11 +1,11 @@ import React from 'react' import PropTypes from 'prop-types' -import Table from '@material-ui/core/Table' -import TableBody from '@material-ui/core/TableBody' -import TableCell from '@material-ui/core/TableCell' -import TableContainer from '@material-ui/core/TableContainer' -import TableHead from '@material-ui/core/TableHead' -import TableRow from '@material-ui/core/TableRow' +import Table from '@mui/material/Table' +import TableBody from '@mui/material/TableBody' +import TableCell from '@mui/material/TableCell' +import TableContainer from '@mui/material/TableContainer' +import TableHead from '@mui/material/TableHead' +import TableRow from '@mui/material/TableRow' const BasicTable = ({ rows, heads }) => { return ( @@ -13,7 +13,7 @@ const BasicTable = ({ rows, heads }) => { - {heads.map((head) => ( + {heads.map(head => ( { - {rows.map((row) => ( + {rows.map(row => ( {row.rater} {row.amount} diff --git a/webapp/src/components/video/index.js b/webapp/src/components/Video/index.js similarity index 100% rename from webapp/src/components/video/index.js rename to webapp/src/components/Video/index.js diff --git a/webapp/src/components/app-bar/index.js b/webapp/src/components/app-bar/index.js deleted file mode 100644 index 144fd232..00000000 --- a/webapp/src/components/app-bar/index.js +++ /dev/null @@ -1,202 +0,0 @@ -import React, { useEffect, useState } from 'react' -import PropTypes from 'prop-types' -import { useTranslation } from 'react-i18next' -import AccountCircleIcon from '@material-ui/icons/AccountCircle' -import { useDispatch, useSelector } from 'react-redux' -import AppBar from '@material-ui/core/AppBar' -import CircularProgress from '@material-ui/core/CircularProgress' -import FingerprintIcon from '@material-ui/icons/Fingerprint' -import IconButton from '@material-ui/core/IconButton' -import LogoutIcon from '@material-ui/icons/ExitToApp' -import MenuIcon from '@material-ui/icons/Menu' -import SearchIcon from '@material-ui/icons/Search' -import Toolbar from '@material-ui/core/Toolbar' -import Typography from '@material-ui/core/Typography' -import LockOpenOutlinedIcon from '@material-ui/icons/LockOpenOutlined' -import LockOutlinedIcon from '@material-ui/icons/LockOutlined' -import { alpha } from '@material-ui/core/styles' -import { makeStyles } from '@material-ui/styles' -import { Link } from '@reach/router' -import Tooltip from '@material-ui/core/Tooltip' -import Box from '@material-ui/core/Box' - -import InputAutocomplete from 'components/input-autocomplete' -import LanguageSelect from 'components/language-select' -import MobileSearch from 'components/mobile-search' -import { stage } from '../../config' - -import styles from './styles' - -const useStyles = makeStyles((theme) => styles(theme, alpha)) - -const MainTopBar = ({ - isSearchOpen, - handleDrawerToggle, - handleSearchDialogOpen, - handleSearchDialogClose, - ual -}) => { - const classes = useStyles() - const dispatch = useDispatch() - const { t } = useTranslation('translations') - const { data: user } = useSelector((state) => state.user) - const [mayVote, setMayVote] = useState(false) - - const handleSetUser = () => dispatch.user.removeBlockProducersVotedByUser() - - const StyleTooltip = makeStyles((theme) => ({ - arrow: { - color: 'rgba(97, 97, 97, 0.9)', - marginLeft: 30 - }, - tooltip: { - boxShadow: theme.shadows[1], - width: 140, - fontSize: 14, - textAlign: 'center' - } - })) - - function SpecialTooltip(props) { - const classes = StyleTooltip() - - return - } - - useEffect(() => { - const getData = async () => { - if (ual.activeUser) { - await dispatch.user.getUserChainData({ ual }) - } else { - handleSetUser() - } - } - - if (ual) getData() - }, [ual]) - - useEffect(async () => { - if (!user) setMayVote(false) - else if ( - user.voter_info && - (user.voter_info.producers.length > 20 || - user.voter_info.proxy.length > 0) - ) - setMayVote(true) - }, [user]) - - return ( - - - - - - - EOS Rate - -
-
- -
-
- - - - - {user && ( - <> - {!user.edenMember && ( - <> - {mayVote && ( - - - - )} - {!mayVote && ( - - - - )} - - )} - {user.edenMember && ( - - eden icon - - )} - - )} - - - {ual.activeUser ? ( - <> - - - - - {ual.activeUser.accountName} - - - - { - ual.logout() - handleSetUser() - }} - > - - - - ) : ( - <> - ual.showModal()}> - {ual.loading ? ( - - ) : ( - <> - - - {t('appBarSignIn')} - - - )} - - - )} - - - - ) -} - -MainTopBar.propTypes = { - handleDrawerToggle: PropTypes.func, - handleSearchDialogOpen: PropTypes.func, - handleSearchDialogClose: PropTypes.func, - isSearchOpen: PropTypes.bool, - ual: PropTypes.object -} - -export default MainTopBar diff --git a/webapp/src/components/app-bar/styles.js b/webapp/src/components/app-bar/styles.js deleted file mode 100644 index 9dbc02da..00000000 --- a/webapp/src/components/app-bar/styles.js +++ /dev/null @@ -1,82 +0,0 @@ -export default (theme, alpha) => ({ - root: { - flexGrow: 1 - }, - link: { - color: 'white', - textDecoration: 'none' - }, - linkHover: { - '&:hover': { - backgroundColor: 'rgba(255, 255, 255, 0.1)', - borderRadius: 10 - } - }, - grow: { - flexGrow: 1 - }, - title: { - width: 140, - [theme.breakpoints.up('sm')]: { - display: 'block', - width: 210 - } - }, - menuButton: { - marginLeft: -18, - [theme.breakpoints.up('sm')]: { - marginRight: 15 - } - }, - search: { - position: 'relative', - flexGrow: 1, - borderRadius: theme.shape.borderRadius, - backgroundColor: alpha(theme.palette.common.white, 0.15), - '&:hover': { - backgroundColor: alpha(theme.palette.common.white, 0.25) - }, - marginRight: theme.spacing(2), - marginLeft: 0, - width: '100%', - display: 'none', - [theme.breakpoints.up('md')]: { - display: 'block', - width: 'auto' - } - }, - mobileSearch: { - [theme.breakpoints.up('md')]: { - display: 'none' - } - }, - inputRoot: { - color: 'inherit', - width: '100%' - }, - inputInput: { - paddingTop: theme.spacing(1), - paddingRight: theme.spacing(1), - paddingBottom: theme.spacing(1), - paddingLeft: theme.spacing(10), - transition: theme.transitions.create('width'), - width: '100%', - [theme.breakpoints.up('md')]: { - width: 200 - } - }, - sessionText: { - marginLeft: 5, - display: 'none', - [theme.breakpoints.up('sm')]: { - display: 'inline' - } - }, - logoStyle: { - width: 110, - [theme.breakpoints.up('sm')]: { - display: 'block', - width: 180 - } - } -}) diff --git a/webapp/src/components/bottom-navbar/index.js b/webapp/src/components/bottom-navbar/index.js deleted file mode 100644 index 08919a63..00000000 --- a/webapp/src/components/bottom-navbar/index.js +++ /dev/null @@ -1,52 +0,0 @@ -import React, { useState } from 'react' -import { makeStyles } from '@material-ui/styles' -import BottomNavigation from '@material-ui/core/BottomNavigation' -import BottomNavigationAction from '@material-ui/core/BottomNavigationAction' -import RestoreIcon from '@material-ui/icons/Restore' -import ShippingIcon from '@material-ui/icons/ControlPoint' -import { useTranslation } from 'react-i18next' -import SettingsIcon from '@material-ui/icons/Settings' -import { navigate } from '@reach/router' - -import styles from './styles' - -const useStyles = makeStyles(styles) - -const SimpleBottomNavigation = () => { - const [value] = useState(0) - const classes = useStyles() - const { t } = useTranslation('translations') - - const handleChange = (event, valueRoute) => { - event.preventDefault() - const routes = ['/recents', '/', '/settings'] - - navigate(routes[valueRoute]) - } - - return ( - <> - - } - /> - } - /> - } - /> - - - ) -} - -export default SimpleBottomNavigation diff --git a/webapp/src/components/bottom-navbar/styles.js b/webapp/src/components/bottom-navbar/styles.js deleted file mode 100644 index 6230aaef..00000000 --- a/webapp/src/components/bottom-navbar/styles.js +++ /dev/null @@ -1,9 +0,0 @@ -export default () => ({ - root: { - width: '100%', - background: '#fafafa', - position: 'fixed', - bottom: 0, - left: 0 - } -}) diff --git a/webapp/src/components/bp-chip-avatar/styles.js b/webapp/src/components/bp-chip-avatar/styles.js deleted file mode 100644 index 3007a7ca..00000000 --- a/webapp/src/components/bp-chip-avatar/styles.js +++ /dev/null @@ -1,9 +0,0 @@ -export default (props) => ({ - root: { - margin: 8, - color: 'white', - justifyContent: 'space-around', - width: 158, - backgroundColor: (props) => props.color - } -}) diff --git a/webapp/src/components/button/index.js b/webapp/src/components/button/index.js deleted file mode 100644 index 18c2dc7f..00000000 --- a/webapp/src/components/button/index.js +++ /dev/null @@ -1,12 +0,0 @@ -import React from 'react' -import { Button as MaterialButton } from '@material-ui/core' - -import FormControl from '../formControl' - -const Button = ({ ...props }) => ( - - - -) - -export default Button diff --git a/webapp/src/components/checkbox/index.js b/webapp/src/components/checkbox/index.js deleted file mode 100644 index 0e7fcc04..00000000 --- a/webapp/src/components/checkbox/index.js +++ /dev/null @@ -1,21 +0,0 @@ -import React from 'react' -import { Field } from 'formik' -import { InputLabel } from '@material-ui/core' -import { Checkbox as MaterialCheckbox } from 'formik-material-ui' -import PropTypes from 'prop-types' - -import FormControl from '../formControl' - -const Checkbox = ({ ...props }) => ( - - - {props.label} - -) - -Checkbox.propTypes = { - name: PropTypes.string.isRequired, - label: PropTypes.string.isRequired -} - -export default Checkbox diff --git a/webapp/src/components/compare-tool/compare-graph-view.js b/webapp/src/components/compare-tool/compare-graph-view.js deleted file mode 100644 index 4acf1088..00000000 --- a/webapp/src/components/compare-tool/compare-graph-view.js +++ /dev/null @@ -1,354 +0,0 @@ -import React, { useState, useEffect } from 'react' -import PropTypes from 'prop-types' -import { makeStyles } from '@material-ui/core/styles' -import Grid from '@material-ui/core/Grid' -import Typography from '@material-ui/core/Typography' -import FormControlLabel from '@material-ui/core/FormControlLabel' -import LockOpenIcon from '@material-ui/icons/LockOpenOutlined' -import LockIcon from '@material-ui/icons/LockOutlined' -import Button from '@material-ui/core/Button' -import Tooltip from '@material-ui/core/Tooltip' -import Box from '@material-ui/core/Box' -import withWidth from '@material-ui/core/withWidth' -import { useMediaQuery } from '@material-ui/core' -import { useTranslation } from 'react-i18next' -import Switch from '@material-ui/core/Switch' -import CloseIcon from '@material-ui/icons/Close' -import _get from 'lodash.get' - -import Radar from 'components/radar' -import ProducerChipAvatar from 'components/bp-chip-avatar' - -import styles from './styles' - -const useStyles = makeStyles(styles) - -const CompareBodyList = ({ isProxy, selectedData, classes, removeBP }) => { - if (!selectedData.length) return null - - if (isProxy) { - const proxy = selectedData[0] - const producers = _get(proxy, 'voter_info.producers', []) - - return ( - <> - {producers.map((producer) => { - const imageURL = _get(producer, 'bpjson.org.branding.logo_256', null) - - return ( - - ) - })} - - ) - } - - return ( -
- {selectedData.map((data) => { - const imageURL = _get(data, 'bpjson.org.branding.logo_256', null) - - return ( - - ) - })} -
- ) -} - -const TooltipWrapper = ({ - open, - onHandleTooltip, - isClickable, - t, - classes, - userHasVote, - isUser -}) => { - const message = userHasVote ? t('availableToRate') : t('notAvailableToRate') - - if (isClickable) { - return ( - - {userHasVote ? ( - - ) : ( - - )} - - ) - } - - return ( - - {userHasVote ? ( - - ) : ( - - )} - - ) -} - -const CompareGraphView = ({ - removeBP, - selected, - className, - isProxy, - userInfo, - width, - handleOnClear, - handleOnClose, - onHandleVote, - setIsCollapsedView, - isCollapsedView, - ...props -}) => { - const { t } = useTranslation('translations') - const classes = useStyles() - const isDesktop = useMediaQuery('(min-width:767px)') - const mobileMedium = useMediaQuery('(min-height:711px)') - const [sizes, setSizes] = useState() - - useEffect(() => { - setSizes(isDesktop ? 400 : '95%') - }, [isDesktop]) - - return ( - - - - - - {selected.length > 0 - ? `${t('voteToolTitle')} (${selected.length} ${t('chosen')})` - : `${t('voteToolTitle')} (${t('noBPSelected')})`} - - - {t('voteToolDescription')} - - - - - {isDesktop && ( - - - - - - )} - - - ({ - ...data, - backgroundColor: data.backgroundColor.replace('.9', '.2') - })) - }} - /> - - - - {isProxy && selected.length > 0 && ( - - - - {selected[0].name} - - - - - - - )} - {!isProxy && ( - - setIsCollapsedView(event.target.checked) - } - value='isCollapsedView' - /> - } - label={t('compareToolCollapsedSwitch')} - /> - )} - - - {!isDesktop && ( - - {selected.length > 0 ? ( - - ) : ( - - {t('noSelectedBP')} - - )} - - )} - {!isProxy && ( - - - - - - - - - - - - - )} - - {isDesktop && ( - - {selected.length > 0 ? ( - - ) : ( - - {t('noSelectedBP')} - - )} - - )} - - ) -} - -CompareGraphView.propTypes = { - width: PropTypes.oneOf(['lg', 'md', 'sm', 'xl', 'xs']).isRequired, - removeBP: PropTypes.func.isRequired, - selected: PropTypes.array.isRequired, - className: PropTypes.string, - isProxy: PropTypes.bool, - userInfo: PropTypes.object, - handleOnClear: PropTypes.func, - handleOnClose: PropTypes.func, - onHandleVote: PropTypes.func, - setIsCollapsedView: PropTypes.func, - isCollapsedView: PropTypes.bool -} - -CompareGraphView.defaultProps = { - className: '', - isProxy: false, - userInfo: { proxy: '', producers: [], isUser: false }, - onHandleVote: () => {}, - handleOnClear: () => {}, - handleOnClose: () => {}, - setIsCollapsedView: () => {}, - isCollapsedView: true -} - -CompareBodyList.propTypes = { - isProxy: PropTypes.bool, - selectedData: PropTypes.array, - classes: PropTypes.object.isRequired, - removeBP: PropTypes.func.isRequired -} - -TooltipWrapper.propTypes = { - classes: PropTypes.object, - isClickable: PropTypes.bool, - open: PropTypes.bool, - onHandleTooltip: PropTypes.func, - t: PropTypes.any, - userHasVote: PropTypes.bool, - isUser: PropTypes.bool.apply -} - -export default withWidth()(CompareGraphView) diff --git a/webapp/src/components/compare-tool/compare-slider-view.js b/webapp/src/components/compare-tool/compare-slider-view.js deleted file mode 100644 index cad38fd3..00000000 --- a/webapp/src/components/compare-tool/compare-slider-view.js +++ /dev/null @@ -1,73 +0,0 @@ -import React, { useState, useEffect } from 'react' -import { makeStyles } from '@material-ui/core/styles' -import Typography from '@material-ui/core/Typography' -import { useMediaQuery } from '@material-ui/core' -import { useTranslation } from 'react-i18next' -import PropTypes from 'prop-types' -import _get from 'lodash.get' - -import Radar from 'components/radar' - -import styles from './styles' - -const useStyles = makeStyles(styles) - -const CompareSliderView = ({ - selected, - className, - isProxy, - optionalLabel, - ...props -}) => { - const { t } = useTranslation('translations') - const classes = useStyles() - const isDesktop = useMediaQuery('(min-width:767px)') - const [sizes, setSizes] = useState() - - useEffect(() => { - setSizes(isDesktop ? 400 : '95%') - }, [isDesktop]) - - return ( -
- - {isProxy ? optionalLabel : t('compareToolTitle')} - -
- {selected.map((bp) => { - if (!bp) return null - - const name = isProxy - ? _get(bp, 'owner') - : _get(bp, 'bpjson.producer_account_name') - - return ( -
- - - {name} - -
- ) - })} -
-
- ) -} - -CompareSliderView.propTypes = { - selected: PropTypes.array.isRequired, - className: PropTypes.string, - isProxy: PropTypes.bool, - optionalLabel: PropTypes.string -} - -CompareSliderView.defaultProps = {} - -export default CompareSliderView diff --git a/webapp/src/components/compare-tool/styles.js b/webapp/src/components/compare-tool/styles.js deleted file mode 100644 index cf0026b8..00000000 --- a/webapp/src/components/compare-tool/styles.js +++ /dev/null @@ -1,174 +0,0 @@ -export default (theme) => ({ - // index - root: { - padding: theme.spacing(2), - background: theme.palette.surface.main, - width: '100%', - position: 'relative' - }, - footer: { - display: 'flex', - flexDirection: 'row', - justifyContent: 'center', - width: '100%', - [theme.breakpoints.up('sm')]: { - flexDirection: 'row', - justifyContent: 'space-evenly', - margin: 'auto', - bottom: 0, - width: 'calc(50% - 16px)' - } - }, - switch: { - [theme.breakpoints.up('sm')]: { - float: 'right' - } - }, - btnRate: { - backgroundColor: theme.palette.secondary.main, - marginBottom: 5, - color: '#ffffff', - padding: '5px 20px 5px 20px', - [theme.breakpoints.up('sm')]: { - float: 'right', - marginRight: 20, - '&:hover': { - backgroundColor: theme.palette.secondary.dark - } - } - }, - chipMessage: { - [theme.breakpoints.up('sm')]: { - float: 'right', - marginTop: 5, - marginRight: 5 - } - }, - errorColor: { - backgroundColor: 'red' - }, - errorChip: { - border: '1px solid red' - }, - labelErrorColor: { - color: 'red' - }, - // slider view - bpName: { - paddingTop: 10, - textAlign: 'center' - }, - slider: { - display: 'flex', - flexWrap: 'nowrap', - overflowX: 'auto', - '-webkit-overflow-scrolling': 'touch', - '&::-webkit-scrollbar': { - display: 'none' - } - }, - sliderCard: { - flex: '0 0 auto', - width: 360, - paddingRight: 16 - }, - // graph view - bpItem: { - width: '75%', - padding: '0 0 0 10px', - display: 'flex', - justifyContent: 'space-between', - '&:hover': { - backgroundColor: theme.palette.primary.submenu - } - }, - bpNameWrapper: { - height: 48, - paddingTop: 14 - }, - bpColorCode: { - display: 'inline-block', - width: 15, - height: 15, - verticalAlign: 'text-bottom' - }, - title: { - textDecoration: 'none', - color: theme.palette.primary.main - }, - avatar: { - backgroundColor: theme.palette.surface.main - }, - helpIcon: { - width: '90%', - height: '90%' - }, - cardHeader: { - borderBottom: `1px solid ${theme.palette.primary.light}` - }, - titleLock: { - display: 'flex', - justifyContent: 'stretch', - alignItems: 'center' - }, - headerVotingCompare: { - display: 'flex', - justifyContent: 'space-between', - alignItems: 'center' - }, - marginRightElem: { - marginRight: 10 - }, - icon: { - color: theme.palette.primary.submenu, - fontSize: 30, - '&:hover': { - cursor: 'pointer' - } - }, - containerList: { - height: '100%', - overflow: 'auto', - [theme.breakpoints.up('sm')]: { - marginBottom: 38 - } - }, - centerBox: { - margin: 'auto', - width: '45%', - padding: '5px', - [theme.breakpoints.down('sm')]: { - width: '100%' - } - }, - buttonsBox: { - [theme.breakpoints.down('sm')]: { - bottom: 0, - position: 'absolute', - left: 0 - } - }, - boxCloseIcon: { - justifyContent: 'flex-end', - display: 'flex', - alignItems: 'center', - height: '100%' - }, - btnRateProxies: { - backgroundColor: theme.palette.secondary.main, - color: '#ffffff', - width: '100px', - padding: '5px 20px 5px 20px', - [theme.breakpoints.up('sm')]: { - '&:hover': { - backgroundColor: theme.palette.secondary.dark - } - } - }, - reliefGrid: { - border: '1px solid #f8f8f8', - boxShadow: - 'inset 2px 2px 2px #fff, inset -1px 0 2px rgba(0,0,0,.1), 1px 3px 3px rgba(0,0,0,.1)', - backgroundColor: '#fff' - } -}) diff --git a/webapp/src/components/filter-select/index.js b/webapp/src/components/filter-select/index.js deleted file mode 100644 index eac51368..00000000 --- a/webapp/src/components/filter-select/index.js +++ /dev/null @@ -1,83 +0,0 @@ -import React, { useState, useEffect } from 'react' -import PropTypes from 'prop-types' -import { useTranslation } from 'react-i18next' -import Typography from '@material-ui/core/Typography' -import { makeStyles } from '@material-ui/styles' -import IconButton from '@material-ui/core/IconButton' -import Menu from '@material-ui/core/Menu' -import MenuItem from '@material-ui/core/MenuItem' -import FilterListIcon from '@material-ui/icons/FilterList' - -import styles from './styles' - -const useStyles = makeStyles(styles) - -const FilterSelect = ({ style, alt, onHandleApplySortBy }) => { - const { t, i18n } = useTranslation('sortInput') - const classes = useStyles() - const [anchorEl, setAnchorEl] = useState(null) - const [sort, setSort] = useState(t('sortby')) - - const handleClick = (event) => { - setAnchorEl(event.currentTarget) - } - - const handleClose = (item) => { - setAnchorEl(null) - - if (typeof item === 'string') { - setSort(t(item)) - onHandleApplySortBy(item) - } - } - - const filters = [ - { value: 'alphabetical', label: t('alphabetical') }, - { value: 'generalRate', label: t('generalRate') }, - { value: 'infrastructure', label: t('infrastructure') }, - { value: 'community', label: t('community') }, - { value: 'trustiness', label: t('trustiness') }, - { value: 'development', label: t('development') }, - { value: 'transparency', label: t('transparency') }, - { value: 'vote', label: t('vote') }, - { value: 'ratings', label: t('ratings') } - ] - - useEffect(() => { - setSort(t(sort)) - }, [i18n.language]) - - return ( - <> - - - - {sort || ''} - - - - {filters.length && - filters.map((item) => ( - handleClose(item.value)} - > - {item.label} - - ))} - - - ) -} - -FilterSelect.propTypes = { - alt: PropTypes.string, - style: PropTypes.any, - onHandleApplySortBy: PropTypes.func -} - -export default FilterSelect diff --git a/webapp/src/components/filter-select/styles.js b/webapp/src/components/filter-select/styles.js deleted file mode 100644 index e157e04f..00000000 --- a/webapp/src/components/filter-select/styles.js +++ /dev/null @@ -1,17 +0,0 @@ -export default (theme) => ({ - wrapper: { - color: 'inherit' - }, - sortText: { - fontSize: '1rem', - marginLeft: 3, - display: 'none', - [theme.breakpoints.up('sm')]: { - display: 'inline' - } - }, - iconFilter: { - width: 24, - height: 24 - } -}) diff --git a/webapp/src/components/formControl/index.js b/webapp/src/components/formControl/index.js deleted file mode 100644 index 1e5ea39d..00000000 --- a/webapp/src/components/formControl/index.js +++ /dev/null @@ -1,7 +0,0 @@ -import React from 'react' - -const FormControl = ({ ...props }) => ( -
-) - -export default FormControl diff --git a/webapp/src/components/github-icon/index.js b/webapp/src/components/github-icon/index.js deleted file mode 100644 index deb15905..00000000 --- a/webapp/src/components/github-icon/index.js +++ /dev/null @@ -1,10 +0,0 @@ -import React from 'react' -import SvgIcon from '@material-ui/core/SvgIcon' - -const GithubIcon = () => ( - - - -) - -export default GithubIcon diff --git a/webapp/src/components/icon/communityIcon.js b/webapp/src/components/icon/communityIcon.js index 9e3dd354..4a50594a 100644 --- a/webapp/src/components/icon/communityIcon.js +++ b/webapp/src/components/icon/communityIcon.js @@ -1,12 +1,12 @@ -import React from 'react' -import SvgIcon from '@material-ui/core/SvgIcon' -import { makeStyles } from '@material-ui/core/styles' +import React, { memo } from 'react' +import SvgIcon from '@mui/material/SvgIcon' +import { makeStyles } from '@mui/styles' import styles from './styles' const useStyles = makeStyles(styles) -const CommunityIcon = (props) => { +const CommunityIcon = props => { const classes = useStyles() return ( @@ -28,4 +28,4 @@ const CommunityIcon = (props) => { ) } -export default CommunityIcon +export default memo(CommunityIcon) diff --git a/webapp/src/components/icon/developmentIcon.js b/webapp/src/components/icon/developmentIcon.js index 0b42b407..85530568 100644 --- a/webapp/src/components/icon/developmentIcon.js +++ b/webapp/src/components/icon/developmentIcon.js @@ -1,12 +1,12 @@ -import React from 'react' -import SvgIcon from '@material-ui/core/SvgIcon' -import { makeStyles } from '@material-ui/core/styles' +import React, { memo } from 'react' +import SvgIcon from '@mui/material/SvgIcon' +import { makeStyles } from '@mui/styles' import styles from './styles' const useStyles = makeStyles(styles) -const DevelopmentIcon = (props) => { +const DevelopmentIcon = props => { const classes = useStyles() return ( @@ -22,4 +22,4 @@ const DevelopmentIcon = (props) => { ) } -export default DevelopmentIcon +export default memo(DevelopmentIcon) diff --git a/webapp/src/components/icon/infrastructureIcon.js b/webapp/src/components/icon/infrastructureIcon.js index 22bc3888..44c65188 100644 --- a/webapp/src/components/icon/infrastructureIcon.js +++ b/webapp/src/components/icon/infrastructureIcon.js @@ -1,12 +1,12 @@ -import React from 'react' -import SvgIcon from '@material-ui/core/SvgIcon' -import { makeStyles } from '@material-ui/core/styles' +import React, { memo } from 'react' +import SvgIcon from '@mui/material/SvgIcon' +import { makeStyles } from '@mui/styles' import styles from './styles' const useStyles = makeStyles(styles) -const InfrastructureIcon = (props) => { +const InfrastructureIcon = props => { const classes = useStyles() return ( @@ -32,4 +32,4 @@ const InfrastructureIcon = (props) => { ) } -export default InfrastructureIcon +export default memo(InfrastructureIcon) diff --git a/webapp/src/components/icon/transparencyIcon.js b/webapp/src/components/icon/transparencyIcon.js index 954a6fd1..93d3322c 100644 --- a/webapp/src/components/icon/transparencyIcon.js +++ b/webapp/src/components/icon/transparencyIcon.js @@ -1,12 +1,12 @@ -import React from 'react' -import SvgIcon from '@material-ui/core/SvgIcon' -import { makeStyles } from '@material-ui/core/styles' +import React, { memo } from 'react' +import SvgIcon from '@mui/material/SvgIcon' +import { makeStyles } from '@mui/styles' import styles from './styles' const useStyles = makeStyles(styles) -const TransparencyIcon = (props) => { +const TransparencyIcon = props => { const classes = useStyles() return ( @@ -42,4 +42,4 @@ const TransparencyIcon = (props) => { ) } -export default TransparencyIcon +export default memo(TransparencyIcon) diff --git a/webapp/src/components/icon/trustinessIcon.js b/webapp/src/components/icon/trustinessIcon.js index 6d8db0b2..69361270 100644 --- a/webapp/src/components/icon/trustinessIcon.js +++ b/webapp/src/components/icon/trustinessIcon.js @@ -1,12 +1,12 @@ -import React from 'react' -import SvgIcon from '@material-ui/core/SvgIcon' -import { makeStyles } from '@material-ui/core/styles' +import React, { memo } from 'react' +import SvgIcon from '@mui/material/SvgIcon' +import { makeStyles } from '@mui/styles' import styles from './styles' const useStyles = makeStyles(styles) -const TrustinessIcon = (props) => { +const TrustinessIcon = props => { const classes = useStyles() return ( @@ -20,4 +20,4 @@ const TrustinessIcon = (props) => { ) } -export default TrustinessIcon +export default memo(TrustinessIcon) diff --git a/webapp/src/components/input-autocomplete/styles.js b/webapp/src/components/input-autocomplete/styles.js deleted file mode 100644 index 9116f94d..00000000 --- a/webapp/src/components/input-autocomplete/styles.js +++ /dev/null @@ -1,43 +0,0 @@ -export default (theme) => ({ - root: { - flexGrow: 1 - }, - container: { - position: 'relative' - }, - input: { - color: 'white' - }, - suggestionsContainerOpen: { - position: 'absolute', - zIndex: 1, - marginTop: theme.spacing(1), - left: '-24px', - right: 0, - width: '100vw', - [theme.breakpoints.up('md')]: { - left: 0, - width: 'auto' - } - }, - highlightMatch: { - fontWeight: 600 - }, - suggestion: { - display: 'block' - }, - suggestionsList: { - margin: 0, - padding: 0, - listStyleType: 'none' - }, - inputAdornment: { - margin: '5px 25px 5px 0', - [theme.breakpoints.up('md')]: { - margin: '5px 25px' - } - }, - searchIcon: { - fill: 'white' - } -}) diff --git a/webapp/src/components/language-select/styles.js b/webapp/src/components/language-select/styles.js deleted file mode 100644 index 29599438..00000000 --- a/webapp/src/components/language-select/styles.js +++ /dev/null @@ -1,17 +0,0 @@ -export default (theme) => ({ - wrapper: { - color: 'inherit' - }, - languageText: { - fontSize: '1rem', - marginLeft: theme.spacing(0.5), - display: 'none', - [theme.breakpoints.up('sm')]: { - display: 'inline' - } - }, - iconLanguage: { - width: 24, - height: 24 - } -}) diff --git a/webapp/src/components/language-select/index.js b/webapp/src/components/languageSelector/index.js similarity index 68% rename from webapp/src/components/language-select/index.js rename to webapp/src/components/languageSelector/index.js index 94d3f96e..3af9a09e 100644 --- a/webapp/src/components/language-select/index.js +++ b/webapp/src/components/languageSelector/index.js @@ -1,27 +1,27 @@ -import React, { useState } from 'react' +import React, { useState, memo } from 'react' import PropTypes from 'prop-types' -import { Language as LanguageIcon } from '@material-ui/icons' +import LanguageIcon from '@mui/icons-material/Language' import { useTranslation } from 'react-i18next' -import Typography from '@material-ui/core/Typography' -import { makeStyles } from '@material-ui/styles' -import IconButton from '@material-ui/core/IconButton' -import Menu from '@material-ui/core/Menu' -import MenuItem from '@material-ui/core/MenuItem' +import Typography from '@mui/material/Typography' +import { makeStyles } from '@mui/styles' +import IconButton from '@mui/material/IconButton' +import Menu from '@mui/material/Menu' +import MenuItem from '@mui/material/MenuItem' import styles from './styles' const useStyles = makeStyles(styles) -const LanguageSelect = ({ style, alt }) => { +const LanguageSelector = ({ style, alt }) => { const { i18n } = useTranslation('translations') const classes = useStyles() const [anchorEl, setAnchorEl] = useState(null) - const handleClick = (event) => { + const handleClick = event => { setAnchorEl(event.currentTarget) } - const handleClose = (item) => { + const handleClose = item => { setAnchorEl(null) if (typeof item === 'string') { localStorage.setItem('LANGUAGE', item) @@ -48,13 +48,13 @@ const LanguageSelect = ({ style, alt }) => { <> - + {(i18n.language || '').toLocaleUpperCase().substring(0, 2)} {languages.length && - languages.map((item) => ( + languages.map(item => ( handleClose(item.value)} @@ -67,9 +67,9 @@ const LanguageSelect = ({ style, alt }) => { ) } -LanguageSelect.propTypes = { +LanguageSelector.propTypes = { alt: PropTypes.string, style: PropTypes.any } -export default LanguageSelect +export default memo(LanguageSelector) diff --git a/webapp/src/components/languageSelector/styles.js b/webapp/src/components/languageSelector/styles.js new file mode 100644 index 00000000..723874c5 --- /dev/null +++ b/webapp/src/components/languageSelector/styles.js @@ -0,0 +1,23 @@ +export default theme => ({ + wrapper: { + color: 'inherit' + }, + languageText: { + display: 'none', + [theme.breakpoints.up('md')]: { + marginLeft: `${theme.spacing(0.5)} !important`, + display: 'inline', + color: theme.palette.common.white, + fontFamily: 'Roboto', + fontStyle: 'normal', + fontWeight: 'normal', + fontSize: 20, + lineHeight: '23px' + } + }, + iconLanguage: { + width: 24, + height: 24, + color: theme.palette.common.white + } +}) diff --git a/webapp/src/components/layout/index.js b/webapp/src/components/layout/index.js deleted file mode 100644 index 4b6cc191..00000000 --- a/webapp/src/components/layout/index.js +++ /dev/null @@ -1,76 +0,0 @@ -import React, { useState, useEffect } from 'react' -import PropTypes from 'prop-types' -import { makeStyles } from '@material-ui/styles' -import Hidden from '@material-ui/core/Hidden' -import classnames from 'classnames' - -import MainTopBar from 'components/app-bar' -import MainDrawer from 'components/main-drawer' -import MainFooter from 'components/main-footer' -import { InitGA, LogPageView } from 'config/google-analitycs-module' - -import styles from './styles' - -const useStyles = makeStyles(styles) - -const Layout = ({ children, ual }) => { - const classes = useStyles() - const [state, setState] = useState({ - isNavOpen: false, - isSearchOpen: false - }) - - const handleDrawerToggle = () => - setState({ ...state, isNavOpen: !state.isNavOpen }) - - const handleSearchDialogOpen = () => - setState({ ...state, isSearchOpen: true }) - - const handleSearchDialogClose = () => - setState({ ...state, isSearchOpen: false }) - - useEffect(() => { - InitGA() - LogPageView() - }, []) - - return ( -
- - - - - - - -
-
-
{children}
- -
-
- ) -} - -Layout.propTypes = { - children: PropTypes.object, - ual: PropTypes.object -} - -export default Layout diff --git a/webapp/src/components/layout/styles.js b/webapp/src/components/layout/styles.js deleted file mode 100644 index 944a28e8..00000000 --- a/webapp/src/components/layout/styles.js +++ /dev/null @@ -1,28 +0,0 @@ -export default (theme) => ({ - root: { - flexGrow: 1, - height: '100vh', - zIndex: 1, - overflow: 'hidden', - position: 'relative', - display: 'flex', - width: '100%' - }, - desktopDrawer: { - width: 240, - transition: 'width 225ms cubic-bezier(0, 0, 0.2, 1) 0ms' - }, - desktopDrawerHidden: { - width: 0 - }, - toolbar: theme.mixins.toolbar, - content: { - overflow: 'auto', - flexGrow: 1, - backgroundColor: theme.palette.background.default, - position: 'relative' - }, - contentWrapper: { - minHeight: 'calc(100vh - 128px)' - } -}) diff --git a/webapp/src/components/main-drawer/index.js b/webapp/src/components/main-drawer/index.js deleted file mode 100644 index 2ef20cf3..00000000 --- a/webapp/src/components/main-drawer/index.js +++ /dev/null @@ -1,190 +0,0 @@ -import React, { Fragment } from 'react' -import PropTypes from 'prop-types' -import { useSelector, useDispatch } from 'react-redux' -import Drawer from '@material-ui/core/Drawer' -import List from '@material-ui/core/List' -import Divider from '@material-ui/core/Divider' -import Box from '@material-ui/core/Box' -import Collapse from '@material-ui/core/Collapse' -import { makeStyles } from '@material-ui/styles' -import { useTheme } from '@material-ui/core/styles' -import ListItem from '@material-ui/core/ListItem' -import ListItemText from '@material-ui/core/ListItemText' -import Link from '@material-ui/core/Link' -import { useTranslation } from 'react-i18next' -import { appVersion } from '../../config' -import classnames from 'classnames' -import LaunchIcon from '@material-ui/icons/Launch' - -import routes from 'routes' - -import styles from './styles' - -const useStyles = makeStyles(styles) - -const Menu = ({ onClick, currentPathname, links, sortBy, setSortBy }) => { - const { t } = useTranslation('sortInput') - const classes = useStyles() - - return ( - - {links - .filter(({ label }) => label) - .map(({ to, label, target, collapsedItems }) => { - const isSelected = currentPathname === to - - return ( - - {(label === 'About' || label.includes('Versi')) && ( - - )} - onClick && onClick(!!collapsedItems)} - > - onClick && onClick(!!collapsedItems) - }} - selected={isSelected} - className={classnames({ [classes.linkSelected]: isSelected })} - > - {!label.includes('Versi') && } - {label.includes('Versi') && ( - <> - - - - )} - - - {collapsedItems && !!collapsedItems.length && ( - - {collapsedItems.map(({ value }, index) => ( - setSortBy(value)} - > - {t(value)} - - ))} - - )} - - ) - })} - - ) -} - -const MainDrawer = ({ - variant = 'desktop', - onClose, - open = false, - ...props -}) => { - const { t } = useTranslation('translations') - const classes = useStyles() - const theme = useTheme() - const dispatch = useDispatch() - const { sortBy } = useSelector((state) => state.blockProducers) - const { pathname: currentPathname } = useSelector((state) => state.location) - - const handleSortBy = (val) => dispatch.blockProducers.setSortBy(val) - - return ( - <> - - {variant === 'mobile' && ( - - { - if (!isCollapsible) { - onClose() - } - }} - currentPathname={currentPathname} - links={routes.map((route) => ({ - to: route.path, - label: - route.drawerLabel !== 'version' - ? t(route.drawerLabel) - : `${t(route.drawerLabel)} ${appVersion}`, - collapsedItems: route.drawerComponents, - target: route.target - }))} - sortBy={sortBy} - setSortBy={handleSortBy} - /> - - )} - {variant === 'desktop' && ( - - ({ - to: route.path, - label: - route.drawerLabel !== 'version' - ? t(route.drawerLabel) - : `${t(route.drawerLabel)} ${appVersion}`, - collapsedItems: route.drawerComponents, - target: route.target - }))} - sortBy={sortBy} - setSortBy={handleSortBy} - /> - - )} - - ) -} - -Menu.propTypes = { - links: PropTypes.array, - onClick: PropTypes.func, - currentPathname: PropTypes.string, - setSortBy: PropTypes.func, - sortBy: PropTypes.string -} - -MainDrawer.propTypes = { - theme: PropTypes.object, - variant: PropTypes.string, - onClose: PropTypes.func, - open: PropTypes.bool -} - -export default MainDrawer diff --git a/webapp/src/components/main-drawer/styles.js b/webapp/src/components/main-drawer/styles.js deleted file mode 100644 index 5764107a..00000000 --- a/webapp/src/components/main-drawer/styles.js +++ /dev/null @@ -1,47 +0,0 @@ -export default (theme) => ({ - toolbar: theme.mixins.toolbar, - drawerPaper: { - width: 240, - height: '100vh', - [theme.breakpoints.up('md')]: { - position: 'relative' - } - }, - innerList: { - backgroundColor: theme.palette.surface.main, - '& li': { - paddingLeft: theme.spacing(3), - '&:hover': { - cursor: 'pointer', - backgroundColor: '#adbcbf' - } - } - }, - heading: { - fontSize: theme.typography.pxToRem(15), - fontWeight: theme.typography.fontWeightRegular - }, - selectedItem: { - backgroundColor: theme.palette.surface.main - }, - link: { - textDecoration: 'none', - color: '#443f56' - }, - linkSelected: { - backgroundColor: '#ced7d8 !important', - color: '#443f5b' - }, - sortSelected: { - backgroundColor: '#adbcbf !important', - color: '#443f5b' - }, - divider: { - marginBottom: theme.spacing(2) - }, - iconLink: { - marginLeft: '10px', - width: '20px', - color: theme.palette.secondary.main - } -}) diff --git a/webapp/src/components/main-footer/styles.js b/webapp/src/components/main-footer/styles.js deleted file mode 100644 index 8b5bb79d..00000000 --- a/webapp/src/components/main-footer/styles.js +++ /dev/null @@ -1,30 +0,0 @@ -export default (theme) => ({ - root: { - position: 'static', - bottom: 0, - top: 'auto' - }, - grow: { - flexGrow: 1 - }, - eoscostaricaLogo: { - height: 36, - width: 'auto' - }, - link: { - color: theme.palette.common.white, - textDecoration: 'none' - }, - legend: { - display: 'flex', - width: 150, - lineHeight: 1.4, - fontSize: 8, - fontWeight: 500, - fontStretch: 'normal', - letterSpacing: 1.1, - textAlign: 'right', - color: 'rgba(255, 255, 255, 0.6)', - paddingRight: theme.spacing(2) - } -}) diff --git a/webapp/src/components/radar/index.js b/webapp/src/components/radar/index.js deleted file mode 100644 index 3147718d..00000000 --- a/webapp/src/components/radar/index.js +++ /dev/null @@ -1,122 +0,0 @@ -import React, { useEffect, useState } from 'react' -import PropTypes from 'prop-types' -import { useTranslation } from 'react-i18next' -import { Radar } from 'react-chartjs-2' - -import getRadarLabelName from 'utils/getRadarLabelName' - -const RadarData = ({ bpData, height, showLabel, width, ...props }) => { - const { t } = useTranslation('translations') - const labels = getRadarLabelName(t) - const [sizes, setSizes] = useState({ width: '100%', height: '100%' }) - const bpValidData = - bpData.datasets && bpData.datasets.length - ? { ...bpData, labels } - : { labels, datasets: [{ data: [0, 0, 0, 0, 0] }] } - - useEffect(() => { - if (!width && !height) return - - setSizes({ width, height }) - }, [width, height]) - - return ( - - `${data.labels[tooltipItem.index]}: ${ - data.datasets[tooltipItem.datasetIndex].data[tooltipItem.index] - }`, - title: (tooltipItem, data) => { - const titleModeled = tooltipItem.reduce( - (acc, current, index) => { - if (current.datasetIndex === acc.prevDatasetIndex) return acc - - const label = `${acc.title} ${index ? '||' : ''} ${ - data.datasets[current.datasetIndex].label - }` - - return { - title: label, - prevDatasetIndex: current.datasetIndex - } - }, - { title: '', prevDatasetIndex: null } - ) - - return titleModeled.title - } - } - } - }} - /> - ) -} - -RadarData.propTypes = { - bpData: PropTypes.object, - height: PropTypes.any, - width: PropTypes.any, - showLabel: PropTypes.bool -} - -RadarData.defaultProps = { - showLabel: false -} - -export default RadarData diff --git a/webapp/src/components/select/index.js b/webapp/src/components/select/index.js deleted file mode 100644 index 76d84959..00000000 --- a/webapp/src/components/select/index.js +++ /dev/null @@ -1,32 +0,0 @@ -import React from 'react' -import { Field } from 'components/checkbox/node_modules/formik' -import { InputLabel } from '@material-ui/core' -import { Select as MaterialSelect } from 'components/checkbox/node_modules/formik-material-ui' -import PropTypes from 'prop-types' - -import FormControl from '../formControl' - -const Select = ({ ...props }) => ( - - - {props.label} - - - -) - -Select.propTypes = { - name: PropTypes.string.isRequired, - label: PropTypes.string.isRequired -} - -export default Select diff --git a/webapp/src/components/sign-in-dialog/index.js b/webapp/src/components/sign-in-dialog/index.js deleted file mode 100644 index dbe60c8a..00000000 --- a/webapp/src/components/sign-in-dialog/index.js +++ /dev/null @@ -1,60 +0,0 @@ -import React, { useEffect, useState } from 'react' -import PropTypes from 'prop-types' -import { makeStyles } from '@material-ui/core/styles' -import { useTranslation } from 'react-i18next' -import Button from '@material-ui/core/Button' -import DialogActions from '@material-ui/core/DialogActions' -import DialogContent from '@material-ui/core/DialogContent' -import DialogContentText from '@material-ui/core/DialogContentText' -import DialogTitle from '@material-ui/core/DialogTitle' -import Dialog from '@material-ui/core/Dialog' -import LinearProgress from '@material-ui/core/LinearProgress' -import red from '@material-ui/core/colors/red' - -import styles from './styles' - -const useStyles = makeStyles(() => styles(red)) - -const SignInDialog = ({ connecting, error, provider }) => { - const [errorDialogOpen, setErrorDialogOpen] = useState(Boolean(error)) - const { t } = useTranslation('translations') - const classes = useStyles() - - useEffect(() => setErrorDialogOpen(Boolean(error)), [error]) - - return ( - <> - - - {provider ? `${t('connectingWith')} ${provider}` : t('connecting')} - - - - - - - - {t('connectingErrorTitle')} - - - - {error} - - - - - - - - ) -} - -SignInDialog.propTypes = { - connecting: PropTypes.bool.isRequired, - error: PropTypes.string, - provider: PropTypes.string -} - -export default SignInDialog diff --git a/webapp/src/components/sign-in-dialog/styles.js b/webapp/src/components/sign-in-dialog/styles.js deleted file mode 100644 index 94d552ae..00000000 --- a/webapp/src/components/sign-in-dialog/styles.js +++ /dev/null @@ -1,5 +0,0 @@ -export default (red) => ({ - errorMsg: { - color: red[500] - } -}) diff --git a/webapp/src/components/sign-in-menu/index.js b/webapp/src/components/sign-in-menu/index.js deleted file mode 100644 index 06101976..00000000 --- a/webapp/src/components/sign-in-menu/index.js +++ /dev/null @@ -1,27 +0,0 @@ -import React from 'react' -import PropTypes from 'prop-types' -import Menu from '@material-ui/core/Menu' - -const SignInMenu = ({ anchorEl, handleClick, handleClose }) => { - return ( - - ) -} - -SignInMenu.propTypes = { - anchorEl: PropTypes.object, - handleClick: PropTypes.func.isRequired, - handleClose: PropTypes.func.isRequired -} - -export default SignInMenu diff --git a/webapp/src/components/spinner/index.js b/webapp/src/components/spinner/index.js deleted file mode 100644 index 30de5f62..00000000 --- a/webapp/src/components/spinner/index.js +++ /dev/null @@ -1,32 +0,0 @@ -import React from 'react' -import PropTypes from 'prop-types' -import { makeStyles } from '@material-ui/styles' -import CircularProgress from '@material-ui/core/CircularProgress' - -import styles from './styles' - -const useStyles = makeStyles(styles) - -const IsLoading = ({ isLoading }) => { - const classes = useStyles() - - return isLoading ? ( -
-
-
-
- -
-
-
- ) : null -} - -IsLoading.propTypes = { - isLoading: PropTypes.bool -} - -export default IsLoading diff --git a/webapp/src/components/spinner/styles.js b/webapp/src/components/spinner/styles.js deleted file mode 100644 index bfd8850d..00000000 --- a/webapp/src/components/spinner/styles.js +++ /dev/null @@ -1,32 +0,0 @@ -export default (theme) => ({ - blockContainer: { - '&:focus': { - outline: 'none' - }, - bottom: 0, - cursor: 'wait', - height: '100%', - left: 0, - overflow: 'hidden', - position: 'fixed', - right: 0, - top: 0, - zIndex: 99999 - }, - blockOverlay: { - backgroundColor: '#fff', - height: '100%', - opacity: 0.3, - width: '100%' - }, - circularProgressContainer: { - alignContent: 'center', - background: 'transparent', - display: 'flex', - justifyContent: 'center', - position: 'absolute', - top: theme.spacing(10), - width: '100%', - zIndex: 999999 - } -}) diff --git a/webapp/src/components/telegram-icon/index.js b/webapp/src/components/telegram-icon/index.js deleted file mode 100644 index c6caea5f..00000000 --- a/webapp/src/components/telegram-icon/index.js +++ /dev/null @@ -1,20 +0,0 @@ -import React from 'react' -import SvgIcon from '@material-ui/core/SvgIcon' - -const TelegramIcon = () => ( - - - -) - -export default TelegramIcon diff --git a/webapp/src/components/textField/index.js b/webapp/src/components/textField/index.js deleted file mode 100644 index 23643068..00000000 --- a/webapp/src/components/textField/index.js +++ /dev/null @@ -1,13 +0,0 @@ -import React from 'react' -import { Field } from 'formik' -import { TextField as MaterialTextField } from 'formik-material-ui' - -import FormControl from '../formControl' - -const TextField = (props) => ( - - - -) - -export default TextField diff --git a/webapp/src/components/title-page/index.js b/webapp/src/components/title-page/index.js deleted file mode 100644 index d959e4c3..00000000 --- a/webapp/src/components/title-page/index.js +++ /dev/null @@ -1,19 +0,0 @@ -import React from 'react' -import Helmet from 'react-helmet' -import PropTypes from 'prop-types' - -const TitlePage = ({ title }) => ( - - {title} - -) - -TitlePage.propTypes = { - title: PropTypes.string -} - -TitlePage.defaultProps = { - title: 'EOS RATE' -} - -export default TitlePage diff --git a/webapp/src/config/graphql.config.js b/webapp/src/config/graphql.config.js new file mode 100644 index 00000000..6f3e8d49 --- /dev/null +++ b/webapp/src/config/graphql.config.js @@ -0,0 +1 @@ +export const url = process.env.REACT_APP_GRAPHQL_HTTP_URL diff --git a/webapp/src/config/index.js b/webapp/src/config/index.js index c8d4a555..0b05d2f5 100644 --- a/webapp/src/config/index.js +++ b/webapp/src/config/index.js @@ -1,14 +1,6 @@ -export const appName = 'EOSRate' -export const stage = process.env.REACT_APP_MAINNET_VERSION -export const contract = process.env.REACT_APP_RATING_CONTRACT || 'rateproducer' -export const appVersion = - process.env.REACT_APP_VERSION.split('/').pop() || '1.0.0' -export const contractEden = - process.env.REACT_APP_EDEN_CONTRACT || 'genesis.eden' -export const eosApiHost = process.env.REACT_APP_EOS_API_HOST -export const eosApiPort = process.env.REACT_APP_EOS_API_PORT -export const eosApiProtocol = process.env.REACT_APP_EOS_API_PROTOCOL -export const eosApiUri = `${process.env.REACT_APP_EOS_API_PROTOCOL}://${process.env.REACT_APP_EOS_API_HOST}:${process.env.REACT_APP_EOS_API_PORT}` -export const eosChainId = process.env.REACT_APP_EOS_CHAIN_ID -export const blockExplorer = process.env.REACT_APP_BLOCK_EXPLORER -export const networkMonitor = process.env.REACT_APP_NETWORK_MONITOR_URL +import * as graphqlConfig from './graphql.config' +import * as mainConfig from './main.config' +import * as ualConfig from './ual.config' +import * as polarCharConfig from './polar-radar-config' + +export { graphqlConfig, mainConfig, ualConfig, polarCharConfig } diff --git a/webapp/src/config/main.config.js b/webapp/src/config/main.config.js new file mode 100644 index 00000000..e6a8c3a8 --- /dev/null +++ b/webapp/src/config/main.config.js @@ -0,0 +1,12 @@ +export const appVersion = process.env.REACT_APP_TAG || 'v1.0' +export const name = process.env.REACT_APP_NAME +export const title = process.env.REACT_APP_TITLE +export const logo = process.env.REACT_APP_LOGO +export const footerLinks = JSON.parse( + process.env.REACT_APP_FOOTER_LINKS || '[]' +) +export const blockExplorer = process.env.REACT_APP_BLOCK_EXPLORER +export const contract = process.env.REACT_APP_RATING_CONTRACT || 'rateproducer' +export const contractEden = + process.env.REACT_APP_EDEN_CONTRACT || 'genesis.eden' +export const networkMonitor = process.env.REACT_APP_NETWORK_MONITOR_URL diff --git a/webapp/src/config/polar-radar-config.js b/webapp/src/config/polar-radar-config.js new file mode 100644 index 00000000..22fecbcc --- /dev/null +++ b/webapp/src/config/polar-radar-config.js @@ -0,0 +1,62 @@ +export const options = { + chart: { + polar: true + }, + credits: { + enabled: false + }, + legend: { + enabled: false + }, + exporting: { + enabled: false + }, + title: { + text: '' + }, + pane: { + startAngle: 0, + endAngle: 360 + }, + xAxis: { + gridLineWidth: 3, + gridLineColor: '#e5e5e5', + lineColor: '#e5e5e5', + categories: [ + 'community', + 'development', + 'infrastructure', + 'transparency', + 'trustiness' + ], + lineWidth: 3, + startOnTick: true, + tickmarkPlacement: 'on', + labels: { + align: 'center' + } + }, + yAxis: { + gridLineWidth: 3, + gridLineColor: '#e5e5e5', + min: 0, + max: 11, + endOnTick: false, + tickInterval: 2, + gridLineInterpolation: 'circle', + labels: { + enabled: false + } + }, + + plotOptions: { + followPointer: true, + series: { + pointStart: 0 + }, + column: { + pointPadding: 0, + groupPadding: 0 + } + } +} diff --git a/webapp/src/config/radar-color-palette.js b/webapp/src/config/radar-color-palette.js deleted file mode 100644 index de592878..00000000 --- a/webapp/src/config/radar-color-palette.js +++ /dev/null @@ -1,20 +0,0 @@ -// Palette generated with http://vrl.cs.brown.edu/color - -export default [ - '#366d7a', - '#46a08a', - '#7dc384', - '#ffe6a7', - '#fc8c71', - '#fc2c44', - '#a6541d', - '#638123', - '#15b71e', - '#2975de', - '#08a9e5', - '#895ae7', - '#e978b1', - '#fa41c7', - '#b195b0', - '#9d1cf4' -] diff --git a/webapp/src/config/radar.js b/webapp/src/config/radar.js deleted file mode 100644 index 9278edb6..00000000 --- a/webapp/src/config/radar.js +++ /dev/null @@ -1,27 +0,0 @@ -import { Chart } from 'react-chartjs-2' -import get from 'lodash.get' - -const renderBackgroundColor = (chart) => { - const { ctx, config, scales } = chart - const { - r: { xCenter, yCenter, drawingArea: radius } - } = scales - const backgroundColor = get( - config, - 'options.chartArea.backgroundColor', - false - ) - - ctx.save() - ctx.arc(xCenter, yCenter, radius, 0, Math.PI * 2) - - if (backgroundColor) ctx.fillStyle = backgroundColor - - ctx.fill() - ctx.restore() -} - -Chart.register({ - id: Chart.name, - beforeDraw: renderBackgroundColor -}) diff --git a/webapp/src/config/theme.js b/webapp/src/config/theme.js deleted file mode 100644 index b7a085a3..00000000 --- a/webapp/src/config/theme.js +++ /dev/null @@ -1,73 +0,0 @@ -import { createTheme } from '@material-ui/core/styles' - -const theme = createTheme({ - typography: { - useNextVariants: true - }, - palette: { - type: 'light', - background: { - default: '#eeeeee' - }, - primary: { - light: '#787291', - main: '#443f56', - dark: '#221e38', - sectionBackground: '#ffffff', - submenu: '#597a81' - }, - secondary: { - light: '#8ba2a6', - main: '#597a81', - dark: '#222f32' - }, - surface: { - light: '#ffffff', - main: '#ffffff', - dark: '#f8f8f8' - } - }, - overrides: { - root: { - fontSize: '2em' - }, - MuiListItem: { - button: { - // color: 'black', - '&:hover': { - // backgroundColor: '#5cf68a', - // color: 'black' - } - }, - root: { - '&$selected': { - // color: 'black', - // backgroundColor: '#5cf68a' - } - } - }, - MuiListItemText: { - primary: { - // color: 'inherit' - } - }, - MuiSelect: { - root: { - paddingTop: 8 - } - }, - MuiInput: { - root: { - height: 50, - fontSize: 20 - } - }, - MuiButton: { - containedSecondary: { - // color: '#fff' - } - } - } -}) - -export default theme diff --git a/webapp/src/config/ual.config.js b/webapp/src/config/ual.config.js new file mode 100644 index 00000000..5caa0376 --- /dev/null +++ b/webapp/src/config/ual.config.js @@ -0,0 +1,32 @@ +import { TokenPocket } from 'ual-token-pocket' +import { Anchor } from 'ual-anchor' +import { Scatter } from 'ual-scatter' +import { Ledger } from 'ual-ledger' +import { Lynx } from 'ual-lynx' +import { MeetOne } from 'ual-meetone' + +export const endpoint = `${process.env.REACT_APP_EOS_API_PROTOCOL}://${ + process.env.REACT_APP_EOS_API_HOST +}${process.env.REACT_APP_EOS_API_PORT ? ':' : ''}${ + process.env.REACT_APP_EOS_API_PORT +}` +export const appName = process.env.REACT_APP_UAL_APP_NAME || 'app' +export const network = { + chainId: process.env.REACT_APP_EOS_CHAIN_ID || '', + rpcEndpoints: [ + { + blockchain: 'eos', + protocol: process.env.REACT_APP_EOS_API_PROTOCOL, + host: process.env.REACT_APP_EOS_API_HOST, + port: parseInt(process.env.REACT_APP_EOS_API_PORT) + } + ] +} +export const authenticators = [ + new TokenPocket([network]), + new Anchor([network], { appName }), + new Lynx([network]), + new Ledger([network]), + new MeetOne([network.chainId]), + new Scatter([network], { appName }) +] diff --git a/webapp/src/config/wallet-providers.js b/webapp/src/config/wallet-providers.js deleted file mode 100644 index 156b8fc4..00000000 --- a/webapp/src/config/wallet-providers.js +++ /dev/null @@ -1,22 +0,0 @@ -/** - * The order of the objects in this array is determinant and strictly related to the order of `walletProviders` declared - * for the `accessContext` in `hooks/wallet/index.js`, so please keep the same order here and there (alphabetical). - */ -export default [ - { - id: 'lynx', - name: 'Lynx' - }, - { - id: 'meetone', - name: 'MEET.ONE' - }, - { - id: 'scatter', - name: 'Scatter' - }, - { - id: 'tokenpocket', - name: 'Token Pocket' - } -] diff --git a/webapp/src/context/models/index.js b/webapp/src/context/models/index.js new file mode 100644 index 00000000..2440ef8c --- /dev/null +++ b/webapp/src/context/models/index.js @@ -0,0 +1,3 @@ +export * from './proxies' +export * from './user' +export * from './producers' diff --git a/webapp/src/context/models/producers.js b/webapp/src/context/models/producers.js new file mode 100644 index 00000000..710d9cae --- /dev/null +++ b/webapp/src/context/models/producers.js @@ -0,0 +1,69 @@ +import { client } from '../../graphql' +import { + GET_BLOCK_PRODUCERS, + GET_EDEN_RATING, + GET_PRODUCER_BY_OWNER +} from '../../gql' +import getBpDataModeled from '../../utils/modeled-bp-data' + +export const getProducers = async limit => { + const { + data: { list, info } + } = await client.query({ + variables: { limit }, + query: GET_BLOCK_PRODUCERS, + fetchPolicy: 'network-only' + }) + + if (!list.length) return [] + + const promiseResolved = await Promise.all( + list.map(({ owner }) => { + return client.query({ + variables: { + bp: owner + }, + query: GET_EDEN_RATING, + fetchPolicy: 'network-only' + }) + }) + ) + + const resultProducers = list.map((producer, index) => { + const edenRate = promiseResolved[index].data.edenRatingsStats[0] || {} + + return getBpDataModeled({ + ...producer, + edenRate + }) + }) + + return { data: resultProducers, rows: info.producers.count } +} + +export const getProducer = async owner => { + const { + data: { producer } + } = await client.query({ + variables: { account: owner }, + query: GET_PRODUCER_BY_OWNER, + fetchPolicy: 'network-only' + }) + + if (!producer.length) return null + + const { + data: { edenRatingsStats } + } = await client.query({ + variables: { + bp: owner + }, + query: GET_EDEN_RATING, + fetchPolicy: 'network-only' + }) + + return getBpDataModeled({ + ...producer[0], + edenRate: edenRatingsStats.length ? { ...edenRatingsStats[0] } : {} + }) +} diff --git a/webapp/src/context/models/proxies.js b/webapp/src/context/models/proxies.js new file mode 100644 index 00000000..827e8f0d --- /dev/null +++ b/webapp/src/context/models/proxies.js @@ -0,0 +1,156 @@ +import _get from 'lodash.get' + +import { client } from '../../graphql' +import { + GET_PROXIES, + GET_PRODUCER_BY_PRODUCER_LIST, + GET_PROXY_BY_OWNER +} from '../../gql' +import calculateEosFromVotes from '../../utils/convert-votes-to-eos-votes' +import getBPRadarData from '../../utils/get-bp-radar-data' +import getBpDataModeled from '../../utils/modeled-bp-data' + +const getResultModeled = (proxies, promiseResolved) => + proxies.map((proxy, index) => { + const producers = promiseResolved[index].data.producerList + const rateInfo = [] + const proxiedVoteEOS = calculateEosFromVotes( + _get(proxy, 'voter_info.last_vote_weight', 0) + ) + const totalVoteEOS = calculateEosFromVotes( + _get(proxy, 'voter_info.proxied_vote_weight', 0) + ) + const producersDataModeled = producers.map(producer => { + const modeledBp = getBpDataModeled(producer) + + rateInfo.push(modeledBp.system.parameters) + + return modeledBp + }) + + const averageParams = rateInfo.reduce( + (acc, current, index) => { + const community = acc.community + current.community + const development = acc.development + current.development + const infrastructure = acc.infrastructure + current.infrastructure + const transparency = acc.transparency + current.transparency + const trustiness = acc.trustiness + current.trustiness + + if (index + 1 === rateInfo.length) { + return { + community: community / rateInfo.length, + development: development / rateInfo.length, + infrastructure: infrastructure / rateInfo.length, + transparency: transparency / rateInfo.length, + trustiness: trustiness / rateInfo.length + } + } + + return { + community, + development, + infrastructure, + transparency, + trustiness + } + }, + { + community: 0, + development: 0, + infrastructure: 0, + transparency: 0, + trustiness: 0 + } + ) + + return { + ...proxy, + voter_info: { + ...proxy.voter_info, + producers: producersDataModeled + }, + averageParams, + data: getBPRadarData({ + name: proxy.owner, + parameters: averageParams + }), + proxiedVoteEOS, + totalVoteEOS + } + }) + +export const getProxies = async limit => { + const { + data: { proxies, info } + } = await client.query({ + variables: { limit }, + query: GET_PROXIES, + fetchPolicy: 'network-only' + }) + + if (!proxies.length) return [] + + const promiseResolved = await Promise.all( + proxies.map(({ voter_info: voterInfo }) => { + if (!voterInfo.producers.length) { + return new Promise(resolve => { + setTimeout(resolve, 100, { + data: { + producerList: [] + } + }) + }) + } + + return client.query({ + variables: { + producerList: voterInfo.producers + }, + query: GET_PRODUCER_BY_PRODUCER_LIST, + fetchPolicy: 'network-only' + }) + }) + ) + + const resultProxies = getResultModeled(proxies, promiseResolved) + + return { data: resultProxies, rows: info.proxies.count } +} + +export const getProxy = async account => { + const { + data: { proxy } + } = await client.query({ + variables: { account }, + query: GET_PROXY_BY_OWNER, + fetchPolicy: 'network-only' + }) + + if (!proxy.length) return null + + const promiseResolved = await Promise.all( + proxy.map(({ voter_info: voterInfo }) => { + if (!voterInfo.producers.length) { + return new Promise(resolve => { + setTimeout(resolve, 100, { + data: { + producerList: [] + } + }) + }) + } + + return client.query({ + variables: { + producerList: voterInfo.producers + }, + query: GET_PRODUCER_BY_PRODUCER_LIST, + fetchPolicy: 'network-only' + }) + }) + ) + + const resultProxies = getResultModeled(proxy, promiseResolved) + + return resultProxies[0] +} diff --git a/webapp/src/context/models/user.js b/webapp/src/context/models/user.js new file mode 100644 index 00000000..817c7da9 --- /dev/null +++ b/webapp/src/context/models/user.js @@ -0,0 +1,76 @@ +import _get from 'lodash.get' + +import { getRpc, getAccountName } from '../../utils/eosjs-utils' +import { mainConfig } from '../../config' +import { client } from '../../graphql' +import { GET_USER_RATING, GET_PRODUCER_BY_PRODUCER_LIST } from '../../gql' + +export const getUserDataModeled = async ual => { + let userRates = [] + let edenMember = false + let listBPAccount = [] + + const accountName = await getAccountName(ual) + const rpc = getRpc(ual) + + const account = await rpc.get_account(accountName) + const { rows: edenMembers } = await rpc.get_table_rows({ + json: true, + code: mainConfig.contractEden, + scope: 0, + table: 'member', + lower_bound: accountName, + limit: 1, + reverse: false, + show_payer: false + }) + + if (edenMembers.length && edenMembers[0][1].account === accountName) { + edenMember = true + } + + const { + data: { userRatings } + } = await client.query({ + variables: { user: accountName }, + query: GET_USER_RATING, + fetchPolicy: 'network-only' + }) + + const producers = _get(account, 'voter_info.producers', []) + const proxy = _get(account, 'voter_info.proxy', '') + + if (userRatings.length) { + listBPAccount = userRatings.map(({ bp }) => bp) + const { + data: { producerList } + } = await client.query({ + variables: { + producerList: listBPAccount + }, + query: GET_PRODUCER_BY_PRODUCER_LIST, + fetchPolicy: 'network-only' + }) + + userRates = userRatings.map(bpRated => { + const item = (producerList || []).find( + ({ owner }) => bpRated.bp === owner + ) + + return { ...item, ...bpRated } + }) + } + + return { + ...ual.activeUser, + userData: { + ...account, + hasProxy: Boolean(proxy.length), + producersCount: producers.length, + userRates, + edenMember, + listBPAccount, + proxyAccount: proxy + } + } +} diff --git a/webapp/src/context/state.context.js b/webapp/src/context/state.context.js new file mode 100644 index 00000000..34e64772 --- /dev/null +++ b/webapp/src/context/state.context.js @@ -0,0 +1,254 @@ +import React, { useEffect } from 'react' +import PropTypes from 'prop-types' + +// import getProxyDataModeled from '../utils/modeled-proxy-data' + +import { + getProxies, + getProxy, + getUserDataModeled, + getProducers, + getProducer +} from './models' + +const SharedStateContext = React.createContext() + +const initialValue = { + useDarkMode: false, + user: null, + blockProducers: { data: [], rows: 0 }, + selectedProducers: [], + blockProducer: null, + compareBPToolVisible: false, + sortBlockProducersBy: null, + proxies: { data: [], rows: 0 }, + selectedProxies: [], + proxy: null, + compareProxyToolVisible: false +} + +const sharedStateReducer = (state, action) => { + switch (action.type) { + case 'ual': + return { + ...state, + ual: action.ual + } + + case 'userChange': + return { + ...state, + user: action.user + } + + case 'set': { + return { + ...state, + ...action.payload + } + } + + case 'showMessage': + return { + ...state, + message: action.payload + } + + case 'hideMessage': + return { + ...state, + message: null + } + + case 'login': + state.ual.showModal() + + return state + + case 'logout': + state.ual.logout() + + return state + + case 'setProducers': + return { + ...state, + blockProducers: action.blockProducers + } + + case 'setProducer': + return { + ...state, + blockProducer: action.blockProducer + } + + case 'setSortProducersBy': + return { + ...state, + sortBlockProducersBy: action.sortBy + } + + case 'setCompareBPTool': + return { + ...state, + compareBPToolVisible: action.isVisible + } + + case 'setSelectedProducers': + return { + ...state, + selectedProducers: action.selectedProducers + } + + case 'setProxies': + return { + ...state, + proxies: action.proxies + } + + case 'setProxy': + return { + ...state, + proxy: action.proxy + } + + case 'setCompareProxyTool': + return { + ...state, + compareProxyToolVisible: action.isVisible + } + + case 'setSelectedProxies': + return { + ...state, + selectedProxies: action.selectedProxies + } + + default: { + throw new Error(`Unsupported action type: ${action.type}`) + } + } +} + +export const SharedStateProvider = ({ children, ual, ...props }) => { + const [state, dispatch] = React.useReducer(sharedStateReducer, { + ...initialValue, + ual + }) + const value = React.useMemo(() => [state, dispatch], [state]) + + useEffect(() => { + const load = async () => { + if (ual.activeUser) { + const user = await getUserDataModeled(ual) + + dispatch({ type: 'userChange', user }) + } else { + dispatch({ type: 'userChange', user: ual.activeUser }) + } + + dispatch({ type: 'ual', ual }) + } + + load() + }, [ual?.activeUser]) + + return ( + + {children} + + ) +} + +SharedStateProvider.propTypes = { + children: PropTypes.node, + ual: PropTypes.any +} + +export const useSharedState = () => { + const context = React.useContext(SharedStateContext) + + if (!context) { + throw new Error(`useSharedState must be used within a SharedStateContext`) + } + + const [state, dispatch] = context + const setState = payload => dispatch({ type: 'set', payload }) + const showMessage = payload => dispatch({ type: 'showMessage', payload }) + const hideMessage = () => dispatch({ type: 'hideMessage' }) + const login = () => dispatch({ type: 'login' }) + const logout = () => dispatch({ type: 'logout' }) + const setUser = async () => { + const user = await getUserDataModeled(state.ual) + + dispatch({ type: 'userChange', user }) + } + const setSortBy = (sortBy, page) => { + if (page === 'blockProducers') { + dispatch({ type: 'setSortProducersBy', sortBy }) + } else { + // dispatch({ type: 'setSortProducersBy', sortBy }) + } + } + + // Block Producers Action + const setProducers = async limit => { + const blockProducers = await getProducers(limit) + + dispatch({ type: 'setProducers', blockProducers }) + } + const setProducer = async account => { + const blockProducer = await getProducer(account) + + dispatch({ type: 'setProducer', blockProducer }) + } + const setCompareBPTool = isVisible => { + dispatch({ type: 'setCompareBPTool', isVisible }) + } + + const setSelectedProducers = selectedProducers => + dispatch({ type: 'setSelectedProducers', selectedProducers }) + + // Proxies Actions + const setProxies = async limit => { + const proxies = await getProxies(limit) + + dispatch({ type: 'setProxies', proxies }) + } + const setProxy = async (data, saveDirectly = false) => { + let proxy = data + + if (!saveDirectly) { + proxy = await getProxy(data) + } + + dispatch({ type: 'setProxy', proxy }) + } + + const setCompareProxyTool = isVisible => + dispatch({ type: 'setCompareProxyTool', isVisible }) + + const setSelectedProxies = selectedProxies => + dispatch({ type: 'setSelectedProxies', selectedProxies }) + + return [ + state, + { + setState, + showMessage, + hideMessage, + login, + logout, + setUser, + setProducers, + setProducer, + setCompareBPTool, + setSelectedProducers, + setSortBy, + setProxies, + setProxy, + setCompareProxyTool, + setSelectedProxies + } + ] +} diff --git a/webapp/src/gql/index.js b/webapp/src/gql/index.js new file mode 100644 index 00000000..361fcfc2 --- /dev/null +++ b/webapp/src/gql/index.js @@ -0,0 +1,4 @@ +export * from './search' +export * from './producers' +export * from './proxies' +export * from './user' diff --git a/webapp/src/gql/producers.js b/webapp/src/gql/producers.js new file mode 100644 index 00000000..d8160d26 --- /dev/null +++ b/webapp/src/gql/producers.js @@ -0,0 +1,94 @@ +import { gql } from '@apollo/client' + +export const GET_BLOCK_PRODUCERS = gql` + query blockProducers($limit: Int = 15) { + info: producers_list_aggregate( + where: { system: { _contains: { is_active: 1 } } } + ) { + producers: aggregate { + count + } + } + list: producers_list( + where: { system: { _contains: { is_active: 1 } } } + limit: $limit + order_by: [{ bpjson: desc }, { total_votes: desc }] + ) { + owner + system + bpjson + average + community + development + infrastructure + trustiness + transparency + ratings_cntr + general_info + eden_average + eden_ratings_cntr + } + } +` + +export const GET_PRODUCER_BY_OWNER = gql` + query blockProducers($account: String) { + producer: producers_list( + where: { + _and: [ + { system: { _contains: { is_active: 1 } } } + { owner: { _eq: $account } } + ] + } + ) { + owner + system + bpjson + average + community + development + infrastructure + trustiness + transparency + ratings_cntr + general_info + eden_average + eden_ratings_cntr + } + } +` + +export const GET_PRODUCER_BY_PRODUCER_LIST = gql` + query getProducerList($producerList: [String!]) { + producerList: producers_list(where: { owner: { _in: $producerList } }) { + owner + system + bpjson + average + community + development + infrastructure + trustiness + transparency + ratings_cntr + general_info + eden_average + eden_ratings_cntr + } + } +` + +export const GET_EDEN_RATING = gql` + query getEdenRating($bp: String) { + edenRatingsStats: eden_ratings_stats(where: { bp: { _eq: $bp } }) { + bp + average + ratings_cntr + infrastructure + transparency + trustiness + development + community + } + } +` diff --git a/webapp/src/gql/proxies.js b/webapp/src/gql/proxies.js new file mode 100644 index 00000000..554a0ba9 --- /dev/null +++ b/webapp/src/gql/proxies.js @@ -0,0 +1,44 @@ +import { gql } from '@apollo/client' + +export const GET_PROXIES = gql` + query proxies($limit: Int = 15) { + info: proxies_aggregate { + proxies: aggregate { + count + } + } + proxies(limit: $limit) { + background + logo_256 + name + owner + philosophy + slogan + steemit + telegram + twitter + voter_info + website + wechat + } + } +` + +export const GET_PROXY_BY_OWNER = gql` + query proxy($account: String) { + proxy: proxies(where: { owner: { _eq: $account } }) { + background + logo_256 + name + owner + philosophy + slogan + steemit + telegram + twitter + voter_info + website + wechat + } + } +` diff --git a/webapp/src/gql/search.js b/webapp/src/gql/search.js new file mode 100644 index 00000000..83872fa9 --- /dev/null +++ b/webapp/src/gql/search.js @@ -0,0 +1,14 @@ +import { gql } from '@apollo/client' + +export const GET_ITEM_BY_NAME = gql` + query getProducerAndProxies($name: String) { + producers(where: { candidate_name: { _like: $name } }) { + owner + bpjson + } + proxies(where: { filter_name: { _like: $name } }) { + name + owner + } + } +` diff --git a/webapp/src/gql/user.js b/webapp/src/gql/user.js new file mode 100644 index 00000000..c59bc8e6 --- /dev/null +++ b/webapp/src/gql/user.js @@ -0,0 +1,38 @@ +import { gql } from '@apollo/client' + +export const GET_USER_RATING = gql` + query getRates($user: String) { + userRatings: user_ratings( + where: { user: { _eq: $user } } + order_by: { tx_data: asc } + ) { + bp + ratings + uniq_rating + user + tx_data + } + } +` + +export const DELETE_USER_RATE = gql` + mutation deleteUserRate($user: String!, $bpName: String!) { + delete_user_ratings( + where: { _and: [{ user: { _eq: $user } }, { bp: { _eq: $bpName } }] } + ) { + affected_rows + } + } +` +export const GET_RATING_BY_BP = gql` + query getRating($user: String, $bp: String) { + userRatings: user_ratings( + where: { _and: [{ user: { _eq: $user } }, { bp: { _eq: $bp } }] } + ) { + user + bp + ratings + tx_data + } + } +` diff --git a/webapp/src/graphql.js b/webapp/src/graphql.js new file mode 100644 index 00000000..72068020 --- /dev/null +++ b/webapp/src/graphql.js @@ -0,0 +1,55 @@ +import { + split, + HttpLink, + ApolloLink, + ApolloClient, + InMemoryCache, + from +} from '@apollo/client' +import { getMainDefinition } from '@apollo/client/utilities' +import { WebSocketLink } from '@apollo/client/link/ws' + +import { graphqlConfig } from './config' + +const httpLink = new HttpLink({ + uri: graphqlConfig.url +}) + +const wsLink = new WebSocketLink({ + uri: graphqlConfig.url.replace(/^http?/, 'ws').replace(/^https?/, 'wss'), + options: { + lazy: true, + reconnect: true + } +}) + +const splitLink = split( + ({ query }) => { + const definition = getMainDefinition(query) + + return ( + definition.kind === 'OperationDefinition' && + definition.operation === 'subscription' + ) + }, + wsLink, + httpLink +) + +const authMiddleware = new ApolloLink((operation, forward) => { + operation.setContext(({ headers = {} }) => ({ + headers: { + ...headers, + Authorization: localStorage.getItem('token') + ? `Bearer ${localStorage.getItem('token')}` + : 'pasa' + } + })) + + return forward(operation) +}) + +export const client = new ApolloClient({ + link: from([authMiddleware, splitLink]), + cache: new InMemoryCache() +}) diff --git a/webapp/src/hooks/useDebounce/index.js b/webapp/src/hooks/useDebounce/index.js new file mode 100644 index 00000000..5bf99498 --- /dev/null +++ b/webapp/src/hooks/useDebounce/index.js @@ -0,0 +1,19 @@ +import { useState, useEffect } from 'react' + +const useDebounce = (value, delay) => { + const [debouncedValue, setDebouncedValue] = useState(value) + + useEffect(() => { + const handler = setTimeout(() => { + setDebouncedValue(value) + }, delay) + + return () => { + clearTimeout(handler) + } + }, [value, delay]) + + return debouncedValue +} + +export default useDebounce diff --git a/webapp/src/i18n.js b/webapp/src/i18n.js index 0ddd9673..46a38172 100644 --- a/webapp/src/i18n.js +++ b/webapp/src/i18n.js @@ -7,10 +7,10 @@ i18n .use(LanguageDetector) .use(initReactI18next) .init({ + load: 'unspecific', resources, + fallbackNS: 'common', fallbackLng: 'en', - lng: localStorage.getItem('LANGUAGE') || 'en', - caches: ['localStorage', 'cookie'], interpolation: { escapeValue: false } diff --git a/webapp/src/index.js b/webapp/src/index.js index 27a20817..815eb6b5 100644 --- a/webapp/src/index.js +++ b/webapp/src/index.js @@ -1,39 +1,32 @@ import React from 'react' -import ReactDOM from 'react-dom' -import { Provider } from 'react-redux' -import { getPersistor } from '@rematch/persist' -import { MuiThemeProvider, CssBaseline } from '@material-ui/core' -import { UALProvider, withUAL } from 'ual-reactjs-renderer' -import { PersistGate } from 'redux-persist/lib/integration/react' +import { render } from 'react-dom' +import { UALProvider, withUAL } from '@eoscostarica/ual-reactjs-renderer' +import { ApolloProvider } from '@apollo/client' -import { authenticators, network } from './utils/ualAuthenticators' -import store from './store' -import theme from './config/theme' import App from './app' +import { client } from './graphql' import * as serviceWorker from './serviceWorker' +import { ualConfig } from './config' +import { SharedStateProvider } from './context/state.context' -import './config/radar' -import './i18n' +const SharedStateProviderWithUAL = withUAL(SharedStateProvider) -const persistor = getPersistor() -const AppWithUAL = withUAL(App) - -ReactDOM.render( - - - - - - - - - - , +render( + + + + + + + , document.getElementById('root') ) -serviceWorker.unregister() +// If you want your app to work offline and load faster, you can change +// unregister() to register() below. Note this comes with some pitfalls. +// Learn more about service workers: http://bit.ly/CRA-PWA +serviceWorker.register() diff --git a/webapp/src/language/en.json b/webapp/src/language/en.json index a0d19c42..ac70e4fe 100644 --- a/webapp/src/language/en.json +++ b/webapp/src/language/en.json @@ -54,19 +54,20 @@ "notFound": "Not found", "noBpJson": "No BP.json file provided.", - "drawerLinkHome": "Home", - "drawerLinkAllBPs": "Block Producers", - "drawerLinkNetworkMonitor": "EOS Network Monitor", - "drawerLinkSettings": "Settings", - "drawerLinkAccount": "Account", - "drawerLinkAllProxies": "Proxies", - "drawerLinkAbout": "About", - "drawerLinkRicardianContract": "Ricardian Contract", - "drawerLinkHelp": "Help", + "home": "Home", + "myAccount": "My Account", + "blockProducers": "Block Producers", + "networkMonitor": "EOS Network Monitor", + "settings": "Settings", + "account": "Account", + "proxies": "Proxies", + "about": "About", + "ricardianContract": "Ricardian Contract", + "help": "Help", "lockedRating": "You must vote for at least 21 block producers or a proxy to unlock ratings", "edenMemberMessage": "Eden member. Ratings unlocked.", "unlockedRating": "You have voted for 21 bps or a proxy and have unlocked ratings", - "success" : "Success!", + "success": "Success!", "appBarSignIn": "Sign In", "connecting": "Connecting", @@ -165,7 +166,7 @@ "community": "Community", "development": "Development", "voteWithoutLogin": "You need to login to execute this action", - "success" : "Success!" + "success": "Success!" }, "bpRatePage": { @@ -192,7 +193,7 @@ "edenRates": "Eden Rating", "rateWithoutLogin": "You need to login to rate this block producer", "noBlockProducer": "This BP Does Not Exist.", - "success" : "Success!", + "success": "Success!", "title": "Rate EOS Block Producer Infrastructure and Community Reputation", "infoMessage": "Support the network by voting for your favorite BPs or proxy, once you have voted for 21 BPs you can start rating." }, @@ -237,7 +238,7 @@ "totalVotes": "Total Votes", "voteWithoutLogin": "You need to login to vote for this proxy", "labelTool": "votes for", - "success" : "Success!", + "success": "Success!", "title": "Block Producer Community Ratings for", "proxyProfile": "Reviews on EOS proxy account", "interview": "BP interview:", diff --git a/webapp/src/language/es.json b/webapp/src/language/es.json index e4a80567..15bd721d 100644 --- a/webapp/src/language/es.json +++ b/webapp/src/language/es.json @@ -54,15 +54,16 @@ "not-found": "Recurso no encontrado", "noBpJson": "No encontramos un bp.json!", - "drawerLinkHome": "Página Principal", - "drawerLinkAllBPs": "Productores de Bloques", - "drawerLinkNetworkMonitor": "Monitor de Red EOS", - "drawerLinkSettings": "Configuración", - "drawerLinkAccount": "Cuenta", - "drawerLinkAllProxies": "Proxies", - "drawerLinkAbout": "Acerca de EOS Rate", - "drawerLinkRicardianContract": "Contratos Ricardianos", - "drawerLinkHelp": "Ayuda", + "home": "Página Principal", + "myAccount": "Mi Cuenta", + "blockProducers": "Productores de Bloques", + "networkMonitor": "Monitor de Red EOS", + "settings": "Configuración", + "account": "Cuenta", + "proxies": "Proxies", + "about": "Acerca de EOS Rate", + "ricardianContract": "Contratos Ricardianos", + "help": "Ayuda", "lockedRating": "Debes votar por al menos 21 productores de bloques o un proxy para desbloquear calificaciones", "edenMemberMessage": "Miembro de Eden. Calificaciones desbloqueadas.", "unlockedRating": "Ha votado por 21 bps o un proxy y ha desbloqueado calificaciones", diff --git a/webapp/src/language/ko.json b/webapp/src/language/ko.json index 85622fee..c8bfe3b5 100644 --- a/webapp/src/language/ko.json +++ b/webapp/src/language/ko.json @@ -1,305 +1,306 @@ { - "translations": { - "community": "커뮤니티 참여율", - "development": "개발지원 참여율", - "infrastructure": "인프라구축 참여율", - "transparency": "투명성", - "trustiness": "신뢰성", + "translations": { + "community": "커뮤니티 참여율", + "development": "개발지원 참여율", + "infrastructure": "인프라구축 참여율", + "transparency": "투명성", + "trustiness": "신뢰성", - "bpsTitle": "EOS 블럭생산자 순위 목록 - EOS Rate", - "proxiesTitle": "EOS 투표대리인 목록 과 투표툴 - EOS Rate", - "availableToRate": "여러분께서 직접 블럭생산자들을 평가 할 수 있습니다", - "notAvailableToRate": "투표대리인에게 투표권한을 위임하거나, 21개 이상의 블럭생산자들에게 직접 투표가 필요합니다", - "voteWithoutLogin": "투표를 하기 위해서 EOS계정에 로그인이 필요합니다", - "btnVoteBPs": "투표", - "clearSelection": "모든선택 취소", - "loadMore": "더 보기", - "view": "추가정보", - "rate": "평가", - "updateRatingButton": "평가 내용 업데이트하기", - "remove": "투표 철회", - "addToVote": "투표대상 추가", - "selected": "선택됨", - "details": "세부사항", - "voting": "투표", + "bpsTitle": "EOS 블럭생산자 순위 목록 - EOS Rate", + "proxiesTitle": "EOS 투표대리인 목록 과 투표툴 - EOS Rate", + "availableToRate": "여러분께서 직접 블럭생산자들을 평가 할 수 있습니다", + "notAvailableToRate": "투표대리인에게 투표권한을 위임하거나, 21개 이상의 블럭생산자들에게 직접 투표가 필요합니다", + "voteWithoutLogin": "투표를 하기 위해서 EOS계정에 로그인이 필요합니다", + "btnVoteBPs": "투표", + "clearSelection": "모든선택 취소", + "loadMore": "더 보기", + "view": "추가정보", + "rate": "평가", + "updateRatingButton": "평가 내용 업데이트하기", + "remove": "투표 철회", + "addToVote": "투표대상 추가", + "selected": "선택됨", + "details": "세부사항", + "voting": "투표", - "compareToolTitle": "비교 도구", - "compareToolToggle": "비교", - "voteToolToggle": "투표", - "compareToolCollapsedSwitch": "그래프 모아보기", - "voteToolTitle": "투표 도구", - "noBPSelected": "선택된 블럭생산자가 없습니다", - "noSelectedBP": "아직 블록생산자가 선택되지 않았습니다. '투표대상에 추가'를 클릭하고 투표를 진행할 수 있습니다", - "voteToolDescription": "EOS 계정에 로그인한 후 선택한 블록생산자에게 투표하십시오", - "chosen": "선택됨", - "averageCard": "평균점수", - "rateCard": "평가횟수", + "compareToolTitle": "비교 도구", + "compareToolToggle": "비교", + "voteToolToggle": "투표", + "compareToolCollapsedSwitch": "그래프 모아보기", + "voteToolTitle": "투표 도구", + "noBPSelected": "선택된 블럭생산자가 없습니다", + "noSelectedBP": "아직 블록생산자가 선택되지 않았습니다. '투표대상에 추가'를 클릭하고 투표를 진행할 수 있습니다", + "voteToolDescription": "EOS 계정에 로그인한 후 선택한 블록생산자에게 투표하십시오", + "chosen": "선택됨", + "averageCard": "평균점수", + "rateCard": "평가횟수", - "loginUsername": "사용자 이름", - "loginPassword": "비밀번호", - "loginSignin": "로그인", - "loginValidationUsername": "사용자이름이 필요합니다", - "loginValidationPassword": "비밀번호가 필요합니다", + "loginUsername": "사용자 이름", + "loginPassword": "비밀번호", + "loginSignin": "로그인", + "loginValidationUsername": "사용자이름이 필요합니다", + "loginValidationPassword": "비밀번호가 필요합니다", - "settingsTitle": "설정", - "settingsLanguages": "English/Spanish/한국어", - "settingsNotifications": "알림", + "settingsTitle": "설정", + "settingsLanguages": "English/Spanish/한국어", + "settingsNotifications": "알림", - "navigationRecents": "최근", - "navigationRate": "평가", - "navigationSettings": "설정", + "navigationRecents": "최근", + "navigationRate": "평가", + "navigationSettings": "설정", - "searchAutocomplete": "탐색...", + "searchAutocomplete": "탐색...", - "notFound": "찾을 수 없음", - "noBpJson": "BP.json 파일이 제공되지 않았습니다", + "notFound": "찾을 수 없음", + "noBpJson": "BP.json 파일이 제공되지 않았습니다", - "drawerLinkHome": "홈", - "drawerLinkAllBPs": "블럭 생산자", - "drawerLinkNetworkMonitor": "EOS 네트워크 모니터", - "drawerLinkSettings": "설정", - "drawerLinkAccount": "계정", - "drawerLinkAllProxies": "투표 대리인", - "drawerLinkAbout": "EOS Rate 정보", - "drawerLinkRicardianContract": "리카르디안 계약서", - "drawerLinkHelp": "도움말", - "lockedRating": "평가를 잠금 해제하려면 투표대리인에게 투표권한을 위임하거나, 21개 이상의 블럭생산자들에게 직접 투표가 필요합니다", - "edenMemberMessage": "Eden 멤버. 평가 잠금해제", - "unlockedRating": "21개 이상의 블럭생산자들에게 직접 투표했거나, 투표대리인에게 투표권한을 위임하였으므로 평가가 잠금 해제되었습니다", - "success": "성공!", - "appBarSignIn": "로그인", + "home": "홈", + "myAccount": "내 계정", + "blockProducers": "블럭 생산자", + "networkMonitor": "EOS 네트워크 모니터", + "settings": "설정", + "account": "계정", + "proxies": "투표 대리인", + "about": "EOS Rate 정보", + "ricardianContract": "리카르디안 계약서", + "help": "도움말", + "lockedRating": "평가를 잠금 해제하려면 투표대리인에게 투표권한을 위임하거나, 21개 이상의 블럭생산자들에게 직접 투표가 필요합니다", + "edenMemberMessage": "Eden 멤버. 평가 잠금해제", + "unlockedRating": "21개 이상의 블럭생산자들에게 직접 투표했거나, 투표대리인에게 투표권한을 위임하였으므로 평가가 잠금 해제되었습니다", + "success": "성공!", + "appBarSignIn": "로그인", - "connecting": "연결", - "connectingWith": "와 연결", - "connectingErrorTitle": "에러", - "connectingErrorActionBtn": "에러 해결", + "connecting": "연결", + "connectingWith": "와 연결", + "connectingErrorTitle": "에러", + "connectingErrorActionBtn": "에러 해결", - "hideComparisonTool": "비교 도구 숨김", - "showComparisonTool": "비교 도구 표시", - "language": "언어" - }, + "hideComparisonTool": "비교 도구 숨김", + "showComparisonTool": "비교 도구 표시", + "language": "언어" + }, - "sortInput": { - "vote": "최고득표 순서", - "alphabetical": "알파벳 순서", - "ratings": "평가횟수 순서", - "generalRate": "일반 최고평점 순서", - "edenRate": "Eden 최고평점 순서", - "community": "커뮤니티 참여율", - "development": "개발지원 참여율", - "infrastructure": "인프라구축 참여율", - "transparency": "투명성", - "trustiness": "신뢰성" - }, + "sortInput": { + "vote": "최고득표 순서", + "alphabetical": "알파벳 순서", + "ratings": "평가횟수 순서", + "generalRate": "일반 최고평점 순서", + "edenRate": "Eden 최고평점 순서", + "community": "커뮤니티 참여율", + "development": "개발지원 참여율", + "infrastructure": "인프라구축 참여율", + "transparency": "투명성", + "trustiness": "신뢰성" + }, - "not-found": { - "graphic": "헉! 이런!", - "description": "뭔가 잘못 된 것 같습니다!", - "recoveryCta": "홈을 클릭하세요" - }, + "not-found": { + "graphic": "헉! 이런!", + "description": "뭔가 잘못 된 것 같습니다!", + "recoveryCta": "홈을 클릭하세요" + }, - "home": { - "title": "EOS 블록생산자 평가 및 블럭생산자 투표 포털 - EOS Rate", - "cover": { - "title": "당신의 목소리를 들려주세요. 블럭생산자들을 평가하세요", - "paragraph": { - "subtitle1": "EOS Rate란? ", - "text1": "EOS Rate는 EOS 토큰 보유자가 클릭 몇 번으로 블록 생산자들을 평가할 수 있는 오픈 소스 dApp입니다. 사용자는 평가 시스템 및 투표 포털에 액세스할 수 있으므로 토큰 보유자가 정보에 입각한 결정을 더 쉽게 내릴 수 있습니다.", - "text2": "EOS Rate는 평가결과를 수집하여 글로벌 다수의 의견('대중의 지혜')을 포착하고, 투표 패턴이 유권자의 정서를 진정으로 반영하는지 측정합니다.", - "subtitle2": "EOS Rate는 어떻게 작동합니까?", - "text3": "평가를 제출하려면 토큰 보유자가 EOS 지갑으로 로그인해야 합니다. 이는 하나의 계정이 블럭생산자당 하나의 평가 제출만 나타낼 수 있음을 의미합니다. 평가는 EOS 블록체인에 안전하게 저장되어 불변성을 보장합니다.", - "text4": "EOS Rate 포털에 액세스하여 평가를 제출하고 당신의 목소리를 높이십시오." - }, - "cta": "지금 평가 시작" - }, - "subTopic": { - "videoUrl": "https://www.youtube.com/embed/saZnZqJsMhk", - "title": "진정한 민주주의", - "paragraph1": "여러분이 가장 대표성을 가졌다고 생각하는 BPs 찾아 보세요.", - "paragraph2": "EOS Rate는 커뮤니티의 투명성을 기반으로 구축 되었습니다.각각의 BPs들의 프로파일을 생성합니다. 원형(LEAF-Liquid EOS Attribute Factors)의 내부에서 EOS 토큰 홀더들이 투표로 선택된 내용들이 시작적으로 보여줌으로서 객관적이고 직관적인 선택을 할 수 있도록 도와 줍니다.", - "subtitle": "자 그럼 평가를 시작 하세요!", - "text": "사용하는 도중에 질문사항이나 건의 사항이 있다면 우리에게 연락 해 주세요", - "telegramGroup": "텔레그램 그룹" - }, - "ratingCategory": { - "title": "평가내역 카테고리", - "transparency": { - "title": "투명도", - "description": "오너쉽 기반의 공시의 투명성은 bp.json,리워드 사용공개,재무상대공개로 가능합니다." - }, - "infrastructure": { - "title": "인프라", - "description": "EOS 인프라의 안정성과 신뢰도 구축 ." - }, - "trustiness": { - "title": "신뢰도", - "description": "EOS 커뮤니티의 협업과 함께 구축된 평판." - }, - "community": { - "title": "커뮤니티", - "description": "커뮤니의 가치는 SNS상의 대화,헤커톤,컨프런스,세미나,개발자 전용 공간 제공,유용한 컨텐츠 제공으로 인한 교육과 건전한 토론은 커뮤니티의 새로운 가치를 만들고 성장 할 수 있습니다." - }, - "development": { - "title": "개발", - "description": "기술정보 - 오픈소스 기반의 사용정보,스크립트,프레임워크,월렛,투표포탈,메트릭스,등등등." - } - } - }, + "home": { + "title": "EOS 블록생산자 평가 및 블럭생산자 투표 포털 - EOS Rate", + "cover": { + "title": "당신의 목소리를 들려주세요. 블럭생산자들을 평가하세요", + "paragraph": { + "subtitle1": "EOS Rate란? ", + "text1": "EOS Rate는 EOS 토큰 보유자가 클릭 몇 번으로 블록 생산자들을 평가할 수 있는 오픈 소스 dApp입니다. 사용자는 평가 시스템 및 투표 포털에 액세스할 수 있으므로 토큰 보유자가 정보에 입각한 결정을 더 쉽게 내릴 수 있습니다.", + "text2": "EOS Rate는 평가결과를 수집하여 글로벌 다수의 의견('대중의 지혜')을 포착하고, 투표 패턴이 유권자의 정서를 진정으로 반영하는지 측정합니다.", + "subtitle2": "EOS Rate는 어떻게 작동합니까?", + "text3": "평가를 제출하려면 토큰 보유자가 EOS 지갑으로 로그인해야 합니다. 이는 하나의 계정이 블럭생산자당 하나의 평가 제출만 나타낼 수 있음을 의미합니다. 평가는 EOS 블록체인에 안전하게 저장되어 불변성을 보장합니다.", + "text4": "EOS Rate 포털에 액세스하여 평가를 제출하고 당신의 목소리를 높이십시오." + }, + "cta": "지금 평가 시작" + }, + "subTopic": { + "videoUrl": "https://www.youtube.com/embed/saZnZqJsMhk", + "title": "진정한 민주주의", + "paragraph1": "여러분이 가장 대표성을 가졌다고 생각하는 BPs 찾아 보세요.", + "paragraph2": "EOS Rate는 커뮤니티의 투명성을 기반으로 구축 되었습니다.각각의 BPs들의 프로파일을 생성합니다. 원형(LEAF-Liquid EOS Attribute Factors)의 내부에서 EOS 토큰 홀더들이 투표로 선택된 내용들이 시작적으로 보여줌으로서 객관적이고 직관적인 선택을 할 수 있도록 도와 줍니다.", + "subtitle": "자 그럼 평가를 시작 하세요!", + "text": "사용하는 도중에 질문사항이나 건의 사항이 있다면 우리에게 연락 해 주세요", + "telegramGroup": "텔레그램 그룹" + }, + "ratingCategory": { + "title": "평가내역 카테고리", + "transparency": { + "title": "투명도", + "description": "오너쉽 기반의 공시의 투명성은 bp.json,리워드 사용공개,재무상대공개로 가능합니다." + }, + "infrastructure": { + "title": "인프라", + "description": "EOS 인프라의 안정성과 신뢰도 구축 ." + }, + "trustiness": { + "title": "신뢰도", + "description": "EOS 커뮤니티의 협업과 함께 구축된 평판." + }, + "community": { + "title": "커뮤니티", + "description": "커뮤니의 가치는 SNS상의 대화,헤커톤,컨프런스,세미나,개발자 전용 공간 제공,유용한 컨텐츠 제공으로 인한 교육과 건전한 토론은 커뮤니티의 새로운 가치를 만들고 성장 할 수 있습니다." + }, + "development": { + "title": "개발", + "description": "기술정보 - 오픈소스 기반의 사용정보,스크립트,프레임워크,월렛,투표포탈,메트릭스,등등등." + } + } + }, - "account": { - "account_name": "어카운트", - "active": "액티브", - "activity": "액티비티", - "authority": "권한", - "core_liquid_balance": "리퀴드 발란스", - "inactive": "비활성", - "logout": "로그아웃", - "title": "어카운트 프로파일t", - "yourRating": "당신의 평가", - "unpublish": "평가 지우기", - "youRated": "이미 평가된", - "infrastructure": "인프라", - "transparency": "투명도", - "trustiness": "신뢰도", - "community": "커뮤니티", - "development": "개발", - "voteWithoutLogin": "로그인을 하여 실행 할 수 있습니다", - "success": "성공!" - }, + "account": { + "account_name": "어카운트", + "active": "액티브", + "activity": "액티비티", + "authority": "권한", + "core_liquid_balance": "리퀴드 발란스", + "inactive": "비활성", + "logout": "로그아웃", + "title": "어카운트 프로파일t", + "yourRating": "당신의 평가", + "unpublish": "평가 지우기", + "youRated": "이미 평가된", + "infrastructure": "인프라", + "transparency": "투명도", + "trustiness": "신뢰도", + "community": "커뮤니티", + "development": "개발", + "voteWithoutLogin": "로그인을 하여 실행 할 수 있습니다", + "success": "성공!" + }, - "bpRatePage": { - "allBPs": "모든 BPs 리스트", - "subTitle": "BPs 평가r", - "subText": "슬라이드 기능을 사용하여 BPs 평가하기.", - "rateText": "특정 카테고리 부분에 대한 정보가 부족할경우 선택을 하지 않고 비활성화 상태로 두셔도 됩니다.", - "helpText": "선호하는 월렛으로 로그인하여 BPs 평가를 공개 하세요.", - "publishRatingButton": "평가내용 공개하기", - "updateRatingButton": "평가 내용 업데이트하기", - "cancelRatingButton": "취소", - "transparency": "투명도", - "transparencyTooltip": "오너쉽의 공개로 인한 투명성.", - "infrastructure": "인프라", - "infrastructureTooltip": "EOS 인프라의 안정성과 신뢰도 .", - "trustiness": "신뢰도", - "trustinessTooltip": "EOS 커뮤니티와의 협업으로 형성된 평판.", - "community": "커뮤니티", - "communityTooltip": "커뮤니티는 교육과 이벤트 및 유용한 컨텐츠를 통해서 가치를 올릴 수 있습니다.", - "development": "개발", - "developmentTooltip": "기술정보 - 오픈소스 기반의 사용정보,스크립트,프레임워크,월렛,투표포탈,메트릭스,등등등.", - "globalRate": "기본적인 평가", - "myRate": "나의 평가내역", - "edenRates": "Eden 평가내역", - "rateWithoutLogin": "BPs 평가를 하기 위해서는 로그인이 필요 합니다", - "noBlockProducer": "존재하지 않는 BP.", - "success": "성공!", - "title": "BPs의 인프라와 커뮤니티 평판 평가하기", - "infoMessage": "여러분이 선호하는 BPs에게 직접 투표 혹은 프록시를 통해서 네트워크를 지지하세요,21BPs에게 투표된 평가를 시작 할 수 있습니다." - }, + "bpRatePage": { + "allBPs": "모든 BPs 리스트", + "subTitle": "BPs 평가r", + "subText": "슬라이드 기능을 사용하여 BPs 평가하기.", + "rateText": "특정 카테고리 부분에 대한 정보가 부족할경우 선택을 하지 않고 비활성화 상태로 두셔도 됩니다.", + "helpText": "선호하는 월렛으로 로그인하여 BPs 평가를 공개 하세요.", + "publishRatingButton": "평가내용 공개하기", + "updateRatingButton": "평가 내용 업데이트하기", + "cancelRatingButton": "취소", + "transparency": "투명도", + "transparencyTooltip": "오너쉽의 공개로 인한 투명성.", + "infrastructure": "인프라", + "infrastructureTooltip": "EOS 인프라의 안정성과 신뢰도 .", + "trustiness": "신뢰도", + "trustinessTooltip": "EOS 커뮤니티와의 협업으로 형성된 평판.", + "community": "커뮤니티", + "communityTooltip": "커뮤니티는 교육과 이벤트 및 유용한 컨텐츠를 통해서 가치를 올릴 수 있습니다.", + "development": "개발", + "developmentTooltip": "기술정보 - 오픈소스 기반의 사용정보,스크립트,프레임워크,월렛,투표포탈,메트릭스,등등등.", + "globalRate": "기본적인 평가", + "myRate": "나의 평가내역", + "edenRates": "Eden 평가내역", + "rateWithoutLogin": "BPs 평가를 하기 위해서는 로그인이 필요 합니다", + "noBlockProducer": "존재하지 않는 BP.", + "success": "성공!", + "title": "BPs의 인프라와 커뮤니티 평판 평가하기", + "infoMessage": "여러분이 선호하는 BPs에게 직접 투표 혹은 프록시를 통해서 네트워크를 지지하세요,21BPs에게 투표된 평가를 시작 할 수 있습니다." + }, - "footer": { - "legend": "기여하고 싶으신가요? 이 서비스 dapp은 오픈소스 입니다" - }, + "footer": { + "legend": "기여하고 싶으신가요? 이 서비스 dapp은 오픈소스 입니다" + }, - "profile": { - "generalInformation": "기본적인 정보", - "eosRates": "기본적인 평가", - "edenRates": "Eden 평가", - "raters": "평가자", - "amount": "평가", - "rankings": "평균", - "social": "소셜", - "additionalResource": "추가 리소스", - "researchPortal": "EOS 블록 프로듀서 연구 포털", - "bpValidator": "블록 생산자 검증자", - "bpInterviews": "블록 프로듀서 인터뷰", - "account": "어카운트", - "location": "지역", - "status": "상태", - "website": "웹사이트", - "votes": "투표", - "rates": "평가", - "average": "평균", - "websiteInfo": "제공된 웹사이트", - "buttonRate": "선택한 BP 평가", - "buttonVote": "선택한 프록시 투표", - "updateRatingButton": "평가 내용 업데이트하기", - "allBP": "모든 BPs", - "allP": "모든 프록시", - "noBpJson": "선택한 BP의 bp.json 파일을 찾을 수 없습니다.", - "noCountryName": "공개된 지역 없음.", - "noBlockProducer": "선택한 BP 정보 없음.", - "noWebSiteInfo": "제공된 웹사이트 정보 없음.", - "proxyVotes": "프록시 투표", - "philosophy": "철학", - "slogan": "슬로건", - "background": "백그라운드", - "totalVotes": "토탈 득표수", - "voteWithoutLogin": "로그인하여 선택한 프록시를 투표 할 수 있습니다", - "labelTool": "투표하기r", - "success": "성공!", - "title": "BPs 커뮤니티 평가하기", - "proxyProfile": "EOS 프록시 어카운트 리뷰", - "interview": "BP 인터뷰:", - "additionalResources": "자원지원" - }, + "profile": { + "generalInformation": "기본적인 정보", + "eosRates": "기본적인 평가", + "edenRates": "Eden 평가", + "raters": "평가자", + "amount": "평가", + "rankings": "평균", + "social": "소셜", + "additionalResource": "추가 리소스", + "researchPortal": "EOS 블록 프로듀서 연구 포털", + "bpValidator": "블록 생산자 검증자", + "bpInterviews": "블록 프로듀서 인터뷰", + "account": "어카운트", + "location": "지역", + "status": "상태", + "website": "웹사이트", + "votes": "투표", + "rates": "평가", + "average": "평균", + "websiteInfo": "제공된 웹사이트", + "buttonRate": "선택한 BP 평가", + "buttonVote": "선택한 프록시 투표", + "updateRatingButton": "평가 내용 업데이트하기", + "allBP": "모든 BPs", + "allP": "모든 프록시", + "noBpJson": "선택한 BP의 bp.json 파일을 찾을 수 없습니다.", + "noCountryName": "공개된 지역 없음.", + "noBlockProducer": "선택한 BP 정보 없음.", + "noWebSiteInfo": "제공된 웹사이트 정보 없음.", + "proxyVotes": "프록시 투표", + "philosophy": "철학", + "slogan": "슬로건", + "background": "백그라운드", + "totalVotes": "토탈 득표수", + "voteWithoutLogin": "로그인하여 선택한 프록시를 투표 할 수 있습니다", + "labelTool": "투표하기r", + "success": "성공!", + "title": "BPs 커뮤니티 평가하기", + "proxyProfile": "EOS 프록시 어카운트 리뷰", + "interview": "BP 인터뷰:", + "additionalResources": "자원지원" + }, - "about": { - "tabTitle": "BP의 EOS 평가진행과 EOS 투표 툴 제공", - "title": "EOS RATE: EOS 메인넷의 평가내역", - "subtitle1": "EOS 메인넷은 무엇인가?", - "body1": { - "paragraph1": "만약 여러분이 EOSio 커뮤니티에 속해 있거나 EOSio블록체인에 대해서 정보를 읽어 봤다면 EOS 메인넷에 관하여 들어 봤을 것 입니다. EOS 메인넷은 EOSio블록체인 플랫폼의 가장 먼저 런칭을 하였고 가장 중요한 퍼블릭 네트워크라는 것을 의미 합니다. 또한 이 글을 읽고 있다면 블록체인의 용어에 대해서 잘 알 고 있을 것이라고 판단이 됩니다.", - "paragraph2": "EOSIO는 댄 라리머에 의해 개발된 DPoS를 기반으로 하는 합의 메커니즘을 기본적으로 사용 합니다.EOSio에서 DPoS는 EOS토큰 홀더(보유자)들이 BPs 로 불리는 EOS 네트워크를 대표하는 집단에게 투표 하는 과정이 있습니다.EOS 메인넷은 가장 많은 투표를 획득한 21BPs에 의해서 운영이 됩니다.", - "paragraph3": "DPoS는 21개의 투표 네트워크 및 거래소에서 투표로 선출된 BPs노드가 가 직접 블록을 생성하며 리워드를 받을 수 있습니다.EOSio는 DPoS를 사용하여 확장을 함을 목표로 합니다. 그렇다보니 당연히 DPoS의 BPs들은 POW(Proof-of-Work)나 POSProof-of-Stake)보다 더빠르게 합의를 이룰 수 있습니다. 이더리움과 비교한다면 EOS 노드들은 초당 4000이상의 빠른 트랜잭션의 검증을 달성 할 수 있습니다." - }, - "subtitle2": "강력한 권한은 강력한 책임을 필요로 합니다", - "body2": { - "paragraph1": "그럼에도 불구하고 사람들은 DPoS와 EOS 메인넷을 두고 중앙집권화로 발생되는 문제점들을 가지고 있다고 주장들을 합니다. 예를들어 BPs의 의해 어카운트 동결된 내용에 대한 근본 원인을 파악하지 않고 단순하게 동결의 결과만을 보고서 눈살을 찌부리는 것과 같습니다. 또한 그들은 네트워크의 성능저하에 관련된 의견 불일 치와 같은 주장을 합니다.", - "paragraph2": "결론적으로 EOS메인넷의 토큰 홀더들은 EOS 메인넷의 투명도와 민주적인 투표과정을 통해서 선택된 21BPs들을 선택 할 수 있습니다.이 선출된 BPs들은 EOS 메인넷의 커뮤니티를 위해서 보호를 하며 최상의 기술 능력을 구현을 해야만 합니다.", - "paragraph3": "EOS 평가제공 툴을 이용하여 토큰 홀더들의 투표된 내역을 확일 가능합니다. 그렇지만 EOS 메인넷에서 이루어 지는 투표 파워는 토큰 홀더들의 보유 수량에 의해서 결정이 됩니다, 이말의 의미는 토큰 홀더의 보유 수량이 낮다면 그만큼 의견이 적게 반영 된다는 것을 의미 합니다.그러므로 EOS Rate라는 오픈소스프로젝트의 아이디어를 제공하여 EOS 메인넷에서 가장 투명하고 신뢰가 가는 투표과정을 구현 하고자 합니다." - }, - "subtitle3": "EOS Rate란 무엇인가?", - "body3": { - "paragraph1": "EOS Rate는 커뮤니티의 투명성일 기반으로 구축 되었습니다.각각의 BPs들의 프로파일을 생성합니다. 원형(LEAF-Liquid EOS Attribute Factors)의 내부에서 EOS 토큰 홀더들이 투표로 선택된 내용들이 시작적으로 보여줌으로서 객관적이고 직관적인 선택을 할 수 있도록 도와 줍니다.", - "paragraph2": "더불어 EOS 평가의 제공으로 커뮤니티의 반영된 의견, 즉 '많은 사람들의 지혜' 를 반영하는데 많은 도움이 됩니다.글로벌의 모든 내용들을 모으고 투표 패턴이 토큰홀더의 정서를 반영하는의 데이터를 투명하게 제공하고자 합니다.EOS Rate Dapp은 LEAF (Liquid EOS Attribute Factors) 라는 공개된 데이터를 제공하여 토큰홀더가 판단하기 쉬운 원형의 그래픽과 함께 BPs의 프로파일을 제공합니다.", - "paragraph3": "안전하고 투명한 평가를 제출 하기 위해서는 반드시 EOS 월렛을 연동을 필요로 합니다.평가된 기록은 기존의 기록된 평가에 추가적으로 반영되어 업데이트된 그래픽으로 확인 가능합니다.그래서 EOS 평가내용의 프로세스는 우리 모두에게 좋은 결정을 할 수 있도록 정보를 제공 합니다.", - "paragraph4": "추가적으로, 토큰 홀더는 5가지의 카테고리에 평가를 제출 할 수 있습니다:", - "paragraph5": "토큰홀더의 평가된 기록은 기존의 기록된 평가에 추가적으로 반영되어 업데이트된 그래픽으로 확인 가능합니다.그래서 EOS 평가내용의 프로세스는 우리 모두에게 좋은 결정을 할 수 있도록 정보를 제공 합니다:" - }, - "categories": { - "transparency": { - "title": "투명성", - "description": "투명성은 bp.json, BPs 리워드 사용부분, 재무상태 공개와 같은 오너쉽 공개로 가능합니다." - }, - "infrastructure": { - "title": "인프라", - "description": "EOS 인프라의 안정성과 신뢰도 구축." - }, - "trustiness": { - "title": "신뢰", - "description": "EOS 커뮤니티와의 협업과 평판을 만들 수 있습니다." - }, - "community": { - "title": "커뮤니티", - "description": "커뮤니의 가치는 SNS상의 대화,헤커톤,컨프런스,세미나,개발자 전용 공간 제공,유용한 컨텐츠 제공으로 인한 교육과 건전한 토론은 커뮤니티의 새로운 가치를 만들고 성장 할 수 있습니다" - }, - "development": { - "title": "개발지원", - "description": "기술정보 - 오픈소스 기반의 사용정보,스크립트,프레임워크,월렛,투표포탈,메트릭스,등등등" - } - } - }, + "about": { + "tabTitle": "BP의 EOS 평가진행과 EOS 투표 툴 제공", + "title": "EOS RATE: EOS 메인넷의 평가내역", + "subtitle1": "EOS 메인넷은 무엇인가?", + "body1": { + "paragraph1": "만약 여러분이 EOSio 커뮤니티에 속해 있거나 EOSio블록체인에 대해서 정보를 읽어 봤다면 EOS 메인넷에 관하여 들어 봤을 것 입니다. EOS 메인넷은 EOSio블록체인 플랫폼의 가장 먼저 런칭을 하였고 가장 중요한 퍼블릭 네트워크라는 것을 의미 합니다. 또한 이 글을 읽고 있다면 블록체인의 용어에 대해서 잘 알 고 있을 것이라고 판단이 됩니다.", + "paragraph2": "EOSIO는 댄 라리머에 의해 개발된 DPoS를 기반으로 하는 합의 메커니즘을 기본적으로 사용 합니다.EOSio에서 DPoS는 EOS토큰 홀더(보유자)들이 BPs 로 불리는 EOS 네트워크를 대표하는 집단에게 투표 하는 과정이 있습니다.EOS 메인넷은 가장 많은 투표를 획득한 21BPs에 의해서 운영이 됩니다.", + "paragraph3": "DPoS는 21개의 투표 네트워크 및 거래소에서 투표로 선출된 BPs노드가 가 직접 블록을 생성하며 리워드를 받을 수 있습니다.EOSio는 DPoS를 사용하여 확장을 함을 목표로 합니다. 그렇다보니 당연히 DPoS의 BPs들은 POW(Proof-of-Work)나 POSProof-of-Stake)보다 더빠르게 합의를 이룰 수 있습니다. 이더리움과 비교한다면 EOS 노드들은 초당 4000이상의 빠른 트랜잭션의 검증을 달성 할 수 있습니다." + }, + "subtitle2": "강력한 권한은 강력한 책임을 필요로 합니다", + "body2": { + "paragraph1": "그럼에도 불구하고 사람들은 DPoS와 EOS 메인넷을 두고 중앙집권화로 발생되는 문제점들을 가지고 있다고 주장들을 합니다. 예를들어 BPs의 의해 어카운트 동결된 내용에 대한 근본 원인을 파악하지 않고 단순하게 동결의 결과만을 보고서 눈살을 찌부리는 것과 같습니다. 또한 그들은 네트워크의 성능저하에 관련된 의견 불일 치와 같은 주장을 합니다.", + "paragraph2": "결론적으로 EOS메인넷의 토큰 홀더들은 EOS 메인넷의 투명도와 민주적인 투표과정을 통해서 선택된 21BPs들을 선택 할 수 있습니다.이 선출된 BPs들은 EOS 메인넷의 커뮤니티를 위해서 보호를 하며 최상의 기술 능력을 구현을 해야만 합니다.", + "paragraph3": "EOS 평가제공 툴을 이용하여 토큰 홀더들의 투표된 내역을 확일 가능합니다. 그렇지만 EOS 메인넷에서 이루어 지는 투표 파워는 토큰 홀더들의 보유 수량에 의해서 결정이 됩니다, 이말의 의미는 토큰 홀더의 보유 수량이 낮다면 그만큼 의견이 적게 반영 된다는 것을 의미 합니다.그러므로 EOS Rate라는 오픈소스프로젝트의 아이디어를 제공하여 EOS 메인넷에서 가장 투명하고 신뢰가 가는 투표과정을 구현 하고자 합니다." + }, + "subtitle3": "EOS Rate란 무엇인가?", + "body3": { + "paragraph1": "EOS Rate는 커뮤니티의 투명성일 기반으로 구축 되었습니다.각각의 BPs들의 프로파일을 생성합니다. 원형(LEAF-Liquid EOS Attribute Factors)의 내부에서 EOS 토큰 홀더들이 투표로 선택된 내용들이 시작적으로 보여줌으로서 객관적이고 직관적인 선택을 할 수 있도록 도와 줍니다.", + "paragraph2": "더불어 EOS 평가의 제공으로 커뮤니티의 반영된 의견, 즉 '많은 사람들의 지혜' 를 반영하는데 많은 도움이 됩니다.글로벌의 모든 내용들을 모으고 투표 패턴이 토큰홀더의 정서를 반영하는의 데이터를 투명하게 제공하고자 합니다.EOS Rate Dapp은 LEAF (Liquid EOS Attribute Factors) 라는 공개된 데이터를 제공하여 토큰홀더가 판단하기 쉬운 원형의 그래픽과 함께 BPs의 프로파일을 제공합니다.", + "paragraph3": "안전하고 투명한 평가를 제출 하기 위해서는 반드시 EOS 월렛을 연동을 필요로 합니다.평가된 기록은 기존의 기록된 평가에 추가적으로 반영되어 업데이트된 그래픽으로 확인 가능합니다.그래서 EOS 평가내용의 프로세스는 우리 모두에게 좋은 결정을 할 수 있도록 정보를 제공 합니다.", + "paragraph4": "추가적으로, 토큰 홀더는 5가지의 카테고리에 평가를 제출 할 수 있습니다:", + "paragraph5": "토큰홀더의 평가된 기록은 기존의 기록된 평가에 추가적으로 반영되어 업데이트된 그래픽으로 확인 가능합니다.그래서 EOS 평가내용의 프로세스는 우리 모두에게 좋은 결정을 할 수 있도록 정보를 제공 합니다:" + }, + "categories": { + "transparency": { + "title": "투명성", + "description": "투명성은 bp.json, BPs 리워드 사용부분, 재무상태 공개와 같은 오너쉽 공개로 가능합니다." + }, + "infrastructure": { + "title": "인프라", + "description": "EOS 인프라의 안정성과 신뢰도 구축." + }, + "trustiness": { + "title": "신뢰", + "description": "EOS 커뮤니티와의 협업과 평판을 만들 수 있습니다." + }, + "community": { + "title": "커뮤니티", + "description": "커뮤니의 가치는 SNS상의 대화,헤커톤,컨프런스,세미나,개발자 전용 공간 제공,유용한 컨텐츠 제공으로 인한 교육과 건전한 토론은 커뮤니티의 새로운 가치를 만들고 성장 할 수 있습니다" + }, + "development": { + "title": "개발지원", + "description": "기술정보 - 오픈소스 기반의 사용정보,스크립트,프레임워크,월렛,투표포탈,메트릭스,등등등" + } + } + }, - "help": { - "tabTitle": "EOS 커뮤니티 오픈소스에 도움을 주셔서 감사합니다 - EOS Rate", - "title": "EOS Rate를 이용해주셔서 감사합니다", - "paragraph": "EOS Rate는 여전히 진행중인 프로젝트 입니다,사용하는 과정에 오류가 있다면 아래의 링크로 의견을 전달해 주세요", - "githubEOSCR": "EOS Costa Rica 깃허브", - "telegramChannel": "텔레그램 채널", - "websiteEOSCR": "EOS Costa Rica 웹사이트" - }, + "help": { + "tabTitle": "EOS 커뮤니티 오픈소스에 도움을 주셔서 감사합니다 - EOS Rate", + "title": "EOS Rate를 이용해주셔서 감사합니다", + "paragraph": "EOS Rate는 여전히 진행중인 프로젝트 입니다,사용하는 과정에 오류가 있다면 아래의 링크로 의견을 전달해 주세요", + "githubEOSCR": "EOS Costa Rica 깃허브", + "telegramChannel": "텔레그램 채널", + "websiteEOSCR": "EOS Costa Rica 웹사이트" + }, - "termsOfUse": { - "tabTitle": "Ricardian Contracts for EOS Rate Smart Contract" - } + "termsOfUse": { + "tabTitle": "Ricardian Contracts for EOS Rate Smart Contract" + } } diff --git a/webapp/src/layouts/Dashboard/index.js b/webapp/src/layouts/Dashboard/index.js new file mode 100644 index 00000000..afd3a775 --- /dev/null +++ b/webapp/src/layouts/Dashboard/index.js @@ -0,0 +1,52 @@ +import React, { useState } from 'react' +import PropTypes from 'prop-types' +import Box from '@mui/material/Box' +import { makeStyles } from '@mui/styles' + +import Sidebar from '../../components/Sidebar' +import Header from '../../components/Header' +import Footer from '../../components/Footer' +import Message from '../../components/Message' + +import styles from './styles' + +const drawerWidth = 260 +const useStyles = makeStyles(theme => styles(theme, drawerWidth)) + +const Dashboard = ({ children, routes }) => { + const classes = useStyles() + const [mobileOpen, setMobileOpen] = useState(false) + + const handleDrawerToggle = () => { + setMobileOpen(!mobileOpen) + } + + return ( + + + + + +
+ + {children} +
+ + + + + ) +} + +Dashboard.propTypes = { + children: PropTypes.node, + routes: PropTypes.array +} + +export default Dashboard diff --git a/webapp/src/layouts/Dashboard/styles.js b/webapp/src/layouts/Dashboard/styles.js new file mode 100644 index 00000000..469499a8 --- /dev/null +++ b/webapp/src/layouts/Dashboard/styles.js @@ -0,0 +1,21 @@ +export default (theme, drawerWidth) => ({ + root: { + display: 'flex', + minHeight: '100vh' + }, + mainContent: { + flex: 1, + display: 'flex', + flexDirection: 'column', + maxWidth: '100%', + overflow: 'hidden', + height: '100vh' + }, + childContent: { + display: 'flex', + flexDirection: 'column', + justifyContent: 'space-between', + height: '100%', + overflow: 'scroll' + } +}) diff --git a/webapp/src/layouts/index.js b/webapp/src/layouts/index.js new file mode 100644 index 00000000..ad42f122 --- /dev/null +++ b/webapp/src/layouts/index.js @@ -0,0 +1 @@ +export { default as DashboardLayout } from './Dashboard' diff --git a/webapp/src/models/BlockProducer/blockProducers.js b/webapp/src/models/BlockProducer/blockProducers.js deleted file mode 100644 index cb89cbec..00000000 --- a/webapp/src/models/BlockProducer/blockProducers.js +++ /dev/null @@ -1,297 +0,0 @@ -import filterObjects from 'filter-objects' -import uniq from 'lodash.uniq' - -import apolloClient from 'services/graphql' -import { getAllBPs } from 'services/bps' -import { getRpc } from 'utils/eosjsUtils' - -import QUERY_PRODUCER from './query_get_producer_by' -import QUERY_RATING from './query_get_bp_rating_by' -import QUERY_EDEN_RATING from './query_get_eden_stats' -import MUTATION_UPDATE_RATING from './mutation_update_rate' -import { contract } from '../../config' - -const initialState = { - filters: {}, - list: [], - filtered: [], - sortBy: null, - selected: [], - compareTool: false, - producer: null, - userRate: null, - edenRate: null, - transaction: null, - showSortSelected: false -} - -const Proxies = { - state: initialState, - reducers: { - toggleCompareTool(state) { - return { - ...state, - compareTool: !state.compareTool - } - }, - setShowSortSelected(state, showSortSelected) { - return { - ...state, - showSortSelected - } - }, - setBPs(state, list) { - // Whenever we get a new list, clear filters - return { - ...state, - filters: {}, - filtered: [], - list: list.map((bp) => ({ ...bp })) - } - }, - updateBPList(state, list) { - return { - ...state, - list - } - }, - addToSelected(state, producerAccountName) { - return { - ...state, - selected: uniq([...state.selected, producerAccountName]) - } - }, - addArrayToSelected(state, producerAccountNames) { - return { - ...state, - selected: uniq([...state.selected, ...producerAccountNames]) - } - }, - removeSelected(state, producerAccountName) { - return { - ...state, - selected: state.selected.filter( - (selected) => selected !== producerAccountName - ) - } - }, - clearSelected(state) { - return { - ...state, - selected: [] - } - }, - clearFilters(state) { - return { - ...state, - filtered: [], - filters: {} - } - }, - setFiltered(state, filtered, filters) { - return { - ...state, - filtered: [...filtered], - filters: { ...filters } - } - }, - setSortBy(state, sort) { - return { - ...state, - sortBy: sort - } - }, - addProducer(state, producer) { - return { ...state, producer } - }, - addUserRate(state, userRate) { - return { ...state, userRate } - }, - addEdenRate(state, edenRate) { - return { ...state, edenRate } - }, - addTransaction(state, transaction) { - return { ...state, transaction } - } - }, - effects: (dispatch) => ({ - async getBPs() { - return getAllBPs({ - setBPs: (state) => this.setBPs(state) - }) - }, - async applyFilter(filters, state) { - this.setFiltered( - filterObjects.filter(filters, state.blockProducers.list), - filters - ) - }, - async saveLastTransaction(transaction) { - this.addTransaction(transaction) - }, - async getBlockProducerByOwner(owner, state) { - try { - dispatch.isLoading.storeIsContentLoading(true) - - const { - data: { producers } - } = await apolloClient.query({ - variables: { owner }, - query: QUERY_PRODUCER - }) - - if (!producers.length) { - this.addProducer(null) - dispatch.isLoading.storeIsContentLoading(false) - - return - } - - const blockProducer = producers[0] - const bpData = - blockProducer.owner && - (state.blockProducers.list || []).find( - ({ owner }) => owner === blockProducer.owner - ) - - this.addProducer({ - ...blockProducer, - average: bpData ? bpData.average : 0, - ratings_cntr: bpData ? bpData.ratings_cntr : 0, - general_info: bpData ? bpData.general_info : {}, - system: { - ...blockProducer.system, - votesInEos: bpData ? bpData.system.votesInEos : 0, - parameters: bpData ? bpData.system.parameters : {} - }, - data: bpData ? bpData.data : [] - }) - dispatch.isLoading.storeIsContentLoading(false) - } catch (error) { - console.error('getBlockProducerByOwner', error) - dispatch.isLoading.storeIsContentLoading(false) - } - }, - async getBlockProducerRatingByOwner({ bp, userAccount }, state) { - try { - dispatch.isLoading.storeIsContentLoading(true) - - const { - data: { user_ratings: userRatings } - } = await apolloClient.query({ - variables: { bp, user: userAccount }, - query: QUERY_RATING - }) - - this.addUserRate(userRatings.length ? userRatings[0].ratings : null) - - dispatch.isLoading.storeIsContentLoading(false) - } catch (error) { - console.error('getBlockProducerRatingByOwner', error) - dispatch.isLoading.storeIsContentLoading(false) - } - }, - async getBlockProducerEdenRating({ bp }, state) { - try { - dispatch.isLoading.storeIsContentLoading(true) - - const { - data: { eden_ratings_stats: edenRatings } - } = await apolloClient.query({ - variables: { bp }, - query: QUERY_EDEN_RATING, - fetchPolicy: 'network-only' - }) - - this.addEdenRate(edenRatings.length > 0 ? edenRatings[0] : null) - - dispatch.isLoading.storeIsContentLoading(false) - } catch (error) { - console.error('getBlockProducerEdenRating', error) - dispatch.isLoading.storeIsContentLoading(false) - } - }, - async mutationInsertUserRating( - { ual, user, bp, result, ...ratings }, - state - ) { - try { - dispatch.isLoading.storeIsContentLoading(true) - - const { - data: { rateProducer } - } = await apolloClient.mutate({ - variables: { - ratingInput: { - producer: bp, - user, - transaction: state.blockProducers.transaction - } - }, - mutation: MUTATION_UPDATE_RATING - }) - - const rpc = getRpc(ual) - - const { rows: rateStat } = await rpc.get_table_rows({ - json: true, - code: contract, - scope: contract, - table: 'stats', - lower_bound: bp, - limit: 1, - reverse: false, - show_payer: false - }) - - const producerUpdatedList = state.blockProducers.list.map( - (producer) => { - if (rateStat.length && producer.owner === rateStat[0].bp) { - const parameters = { - community: rateStat[0].community, - development: rateStat[0].development, - infrastructure: rateStat[0].infrastructure, - transparency: rateStat[0].transparency, - trustiness: rateStat[0].trustiness - } - const graphData = Object.values(parameters) - - return { - ...producer, - average: rateStat[0].average, - ratings_cntr: rateStat[0].ratings_cntr, - system: { - ...producer.system, - parameters - }, - data: { - ...producer.data, - data: graphData - } - } - } - - return producer - } - ) - const currentBP = producerUpdatedList.find( - (producer) => producer.owner === bp - ) - - this.addProducer(currentBP) - this.addEdenRate(rateProducer.resultEden) - this.updateBPList(producerUpdatedList) - this.getBlockProducerRatingByOwner({ bp, userAccount: user }) - dispatch.user.getUserRates({ - userRate: { ...rateProducer, ...currentBP } - }) - dispatch.isLoading.storeIsContentLoading(false) - } catch (error) { - console.error('mutationInsertUserRating', error) - dispatch.isLoading.storeIsContentLoading(false) - } - } - }) -} - -export default Proxies diff --git a/webapp/src/models/BlockProducer/mutation_insert_user_rating.js b/webapp/src/models/BlockProducer/mutation_insert_user_rating.js deleted file mode 100644 index ae0aab64..00000000 --- a/webapp/src/models/BlockProducer/mutation_insert_user_rating.js +++ /dev/null @@ -1,15 +0,0 @@ -import gql from 'graphql-tag' - -const MUTATION_INSERT_USER_RATING = gql` - mutation saveUserRating($objects: [user_ratings_insert_input!]!) { - insert_user_ratings(objects: $objects) { - returning { - user - bp - ratings - } - } - } -` - -export default MUTATION_INSERT_USER_RATING diff --git a/webapp/src/models/BlockProducer/mutation_update_rate.js b/webapp/src/models/BlockProducer/mutation_update_rate.js deleted file mode 100644 index a48f1d7e..00000000 --- a/webapp/src/models/BlockProducer/mutation_update_rate.js +++ /dev/null @@ -1,16 +0,0 @@ -import gql from 'graphql-tag' - -const MUTATION_UPDATE_RATING = gql` - mutation updateRating($ratingInput: RatingInput!) { - rateProducer(ratingInput: $ratingInput) { - message - resultEden - uniq_rating - user - bp - ratings - } - } -` - -export default MUTATION_UPDATE_RATING diff --git a/webapp/src/models/BlockProducer/mutation_update_user_rating.js b/webapp/src/models/BlockProducer/mutation_update_user_rating.js deleted file mode 100644 index c40d1579..00000000 --- a/webapp/src/models/BlockProducer/mutation_update_user_rating.js +++ /dev/null @@ -1,23 +0,0 @@ -import gql from 'graphql-tag' - -const MUTATION_UPDATE_USER_RATING = gql` - mutation updateUserRating( - $userRating: user_ratings_set_input - $user: String - $bp: String - ) { - update_user_ratings( - _set: $userRating - where: { _and: [{ user: { _eq: $user } }, { bp: { _eq: $bp } }] } - ) { - returning { - user - bp - ratings - uniq_rating - } - } - } -` - -export default MUTATION_UPDATE_USER_RATING diff --git a/webapp/src/models/BlockProducer/query_get_bp_rating_by.js b/webapp/src/models/BlockProducer/query_get_bp_rating_by.js deleted file mode 100644 index c80144d6..00000000 --- a/webapp/src/models/BlockProducer/query_get_bp_rating_by.js +++ /dev/null @@ -1,16 +0,0 @@ -import gql from 'graphql-tag' - -const QUERY_RATING = gql` - query getRating($user: String, $bp: String) { - user_ratings( - where: { _and: [{ user: { _eq: $user } }, { bp: { _eq: $bp } }] } - ) { - user - bp - ratings - tx_data - } - } -` - -export default QUERY_RATING diff --git a/webapp/src/models/BlockProducer/query_get_eden_stats.js b/webapp/src/models/BlockProducer/query_get_eden_stats.js deleted file mode 100644 index 68a0b1c4..00000000 --- a/webapp/src/models/BlockProducer/query_get_eden_stats.js +++ /dev/null @@ -1,18 +0,0 @@ -import gql from 'graphql-tag' - -const QUERY_EDEN_RATING = gql` - query getEdenRating($bp: String) { - eden_ratings_stats(where: { bp: { _eq: $bp } }) { - bp - average - ratings_cntr - infrastructure - transparency - trustiness - development - community - } - } -` - -export default QUERY_EDEN_RATING diff --git a/webapp/src/models/BlockProducer/query_get_producer_by.js b/webapp/src/models/BlockProducer/query_get_producer_by.js deleted file mode 100644 index cfdf0a4a..00000000 --- a/webapp/src/models/BlockProducer/query_get_producer_by.js +++ /dev/null @@ -1,13 +0,0 @@ -import gql from 'graphql-tag' - -const QUERY_PRODUCER = gql` - query getProducer($owner: String) { - producers(where: { owner: { _eq: $owner } }) { - bpjson - owner - system - } - } -` - -export default QUERY_PRODUCER diff --git a/webapp/src/models/Proxy/proxy.js b/webapp/src/models/Proxy/proxy.js deleted file mode 100644 index 063b03eb..00000000 --- a/webapp/src/models/Proxy/proxy.js +++ /dev/null @@ -1,207 +0,0 @@ -import _get from 'lodash.get' -import filterObjects from 'filter-objects' - -import calculateEosFromVotes from 'utils/convertVotesToEosVotes' -import getBPRadarData from 'utils/getBPRadarData' -import apolloClient from 'services/graphql' - -import QUERY_GET_PROXIES from './query_get_proxies' -import QUERY_GET_PROXY_BY_OWNER from './query_get_proxy_by_owner' - -const initialState = { - proxies: [], - compareTool: false, - proxy: null, - filters: {}, - filtered: [], - selected: [] -} - -const Proxies = { - state: initialState, - reducers: { - toggleCompareTool(state) { - return { - ...state, - compareTool: !state.compareTool - } - }, - addProxies(state, proxies) { - return { - ...state, - proxies, - filters: {}, - filtered: [] - } - }, - addProxy(state, proxy) { - return { ...state, proxy } - }, - addToSelected(state, owner) { - return { - ...state, - selected: [owner] - } - }, - removeSelected(state) { - return { - ...state, - selected: [] - } - }, - clearFilters(state) { - return { - ...state, - filtered: [], - filters: {} - } - }, - setFiltered(state, filtered, filters) { - return { - ...state, - filtered: [...filtered], - filters: { ...filters } - } - } - }, - effects: (dispatch) => ({ - async applyFilter(filters, state) { - this.setFiltered( - filterObjects.filter(filters, state.proxies.proxies), - filters - ) - }, - async getProxies(payload, { blockProducers: { list } }) { - try { - dispatch.isLoading.storeIsContentLoading(true) - - const { - data: { proxies } - } = await apolloClient.query({ - variables: {}, - query: QUERY_GET_PROXIES - }) - - if (!proxies.length) { - this.addProxies(null) - dispatch.isLoading.storeIsContentLoading(false) - - return - } - const proxiesModeled = proxies.map((proxy) => { - const rateInfo = [] - const proxyProducers = _get(proxy, 'voter_info.producers', []) - const proxiedVoteEOS = calculateEosFromVotes( - _get(proxy, 'voter_info.last_vote_weight', 0) - ) - const totalVoteEOS = calculateEosFromVotes( - _get(proxy, 'voter_info.proxied_vote_weight', 0) - ) - const producersDataModeled = proxyProducers.map((owner) => { - const producer = list.find((bp) => bp.owner === owner) - - if (producer) { - const { - system: { parameters } - } = producer - - rateInfo.push(parameters) - - return producer - } - - return { owner } - }) - - const averageParams = rateInfo.reduce( - (acc, current, index) => { - const community = acc.community + current.community - const development = acc.development + current.development - const infrastructure = acc.infrastructure + current.infrastructure - const transparency = acc.transparency + current.transparency - const trustiness = acc.trustiness + current.trustiness - - if (index + 1 === rateInfo.length) { - return { - community: community / rateInfo.length, - development: development / rateInfo.length, - infrastructure: infrastructure / rateInfo.length, - transparency: transparency / rateInfo.length, - trustiness: trustiness / rateInfo.length - } - } - - return { - community, - development, - infrastructure, - transparency, - trustiness - } - }, - { - community: 0, - development: 0, - infrastructure: 0, - transparency: 0, - trustiness: 0 - } - ) - - return { - ...proxy, - voter_info: { - ...proxy.voter_info, - producers: producersDataModeled - }, - averageParams, - data: getBPRadarData({ - name: proxy.owner, - parameters: averageParams - }), - proxiedVoteEOS, - totalVoteEOS - } - }) - - this.addProxies(proxiesModeled) - dispatch.isLoading.storeIsContentLoading(false) - } catch (error) { - console.error('getProxies', error) - dispatch.isLoading.storeIsContentLoading(false) - } - }, - async getProxyByOwner(payload, state) { - try { - dispatch.isLoading.storeIsContentLoading(true) - - const { - data: { proxies } - } = await apolloClient.query({ - variables: { owner: payload }, - query: QUERY_GET_PROXY_BY_OWNER - }) - - if (!proxies.length) { - this.addProxy(null) - dispatch.isLoading.storeIsContentLoading(false) - - return - } - - const proxy = proxies[0] - const proxyModeled = state.proxies.proxies.find( - ({ owner }) => owner === proxy.owner - ) - - this.addProxy({ ...proxy, ...proxyModeled }) - dispatch.isLoading.storeIsContentLoading(false) - } catch (error) { - console.error('getProxy', error) - dispatch.isLoading.storeIsContentLoading(false) - } - } - }) -} - -export default Proxies diff --git a/webapp/src/models/Proxy/query_get_proxies.js b/webapp/src/models/Proxy/query_get_proxies.js deleted file mode 100644 index 2d374bf5..00000000 --- a/webapp/src/models/Proxy/query_get_proxies.js +++ /dev/null @@ -1,22 +0,0 @@ -import gql from 'graphql-tag' - -const QUERY_GET_PROXIES = gql` - query getProxies { - proxies { - background - logo_256 - name - owner - philosophy - slogan - steemit - telegram - twitter - voter_info - website - wechat - } - } -` - -export default QUERY_GET_PROXIES diff --git a/webapp/src/models/Proxy/query_get_proxy_by_owner.js b/webapp/src/models/Proxy/query_get_proxy_by_owner.js deleted file mode 100644 index 0fdca974..00000000 --- a/webapp/src/models/Proxy/query_get_proxy_by_owner.js +++ /dev/null @@ -1,22 +0,0 @@ -import gql from 'graphql-tag' - -const QUERY_GET_PROXY_BY_OWNER = gql` - query getProxiesByOwner($owner: String!) { - proxies(where: { owner: { _eq: $owner } }) { - background - logo_256 - name - owner - philosophy - slogan - steemit - telegram - twitter - voter_info - website - wechat - } - } -` - -export default QUERY_GET_PROXY_BY_OWNER diff --git a/webapp/src/models/User/mutation_delete_user_rate.js b/webapp/src/models/User/mutation_delete_user_rate.js deleted file mode 100644 index 4e835cd7..00000000 --- a/webapp/src/models/User/mutation_delete_user_rate.js +++ /dev/null @@ -1,13 +0,0 @@ -import gql from 'graphql-tag' - -const MUTATION_DELETE_USER_RATE = gql` - mutation deleteUserRate($user: String!, $bpName: String!) { - delete_user_ratings( - where: { _and: [{ user: { _eq: $user } }, { bp: { _eq: $bpName } }] } - ) { - affected_rows - } - } -` - -export default MUTATION_DELETE_USER_RATE diff --git a/webapp/src/models/User/query_get_rates.js b/webapp/src/models/User/query_get_rates.js deleted file mode 100644 index 0e031ce7..00000000 --- a/webapp/src/models/User/query_get_rates.js +++ /dev/null @@ -1,15 +0,0 @@ -import gql from 'graphql-tag' - -const QUERY_RATING = gql` - query getRates($user: String) { - user_ratings(where: { user: { _eq: $user } }, order_by: { tx_data: asc }) { - bp - ratings - uniq_rating - user - tx_data - } - } -` - -export default QUERY_RATING diff --git a/webapp/src/models/User/user.js b/webapp/src/models/User/user.js deleted file mode 100644 index 7e3f348c..00000000 --- a/webapp/src/models/User/user.js +++ /dev/null @@ -1,167 +0,0 @@ -import _get from 'lodash.get' - -import apolloClient from 'services/graphql' -import { getRpc, getAccountName } from 'utils/eosjsUtils' - -import { contractEden } from '../../config' -import QUERY_GET_RATES from './query_get_rates' -import MUTATION_DELETE_USER_RATE from './mutation_delete_user_rate' - -const initialState = { - data: null -} - -const user = { - state: initialState, - - reducers: { - setUser(state, data) { - return { - ...state, - data - } - } - }, - - effects: (dispatch) => ({ - async getUserChainData({ ual }, { user, blockProducers, isLoading }) { - try { - dispatch.isLoading.storeIsContentLoading(true) - - const accountName = await getAccountName(ual) - - if (user.data && user.data.account_name === accountName) { - dispatch.isLoading.storeIsContentLoading(false) - return - } - - let account = null - let userRates = [] - let edenMember = false - const rpc = getRpc(ual) - - if (accountName.length) { - account = await rpc.get_account(accountName) - - const { rows: edenMembers } = await rpc.get_table_rows({ - json: true, - code: contractEden, - scope: 0, - table: 'member', - lower_bound: accountName, - limit: 1, - reverse: false, - show_payer: false - }) - - if (edenMembers[0][1].account === accountName) { - edenMember = true - } - } - - const { - data: { user_ratings: userRatings } - } = await apolloClient.query({ - variables: { user: accountName }, - query: QUERY_GET_RATES - }) - - const producers = _get(account, 'voter_info.producers', []) - const proxy = _get(account, 'voter_info.proxy', '') - userRates = userRatings - - if (userRatings.length) { - userRates = userRatings.map((bpRated) => { - const item = blockProducers.list.find( - ({ owner }) => bpRated.bp === owner - ) - - return { ...item, ...bpRated } - }) - } - - account - ? this.setUser({ - ...account, - hasProxy: Boolean(proxy.length), - producersCount: producers.length, - userRates, - edenMember - }) - : this.setUser(null) - - if (producers.length) { - const filterBPs = producers.filter((bpName) => - blockProducers.list.find(({ owner }) => bpName === owner) - ) - - dispatch.blockProducers.addArrayToSelected(filterBPs) - } - proxy.length && dispatch.proxies.addToSelected(proxy) - - if ((producers.length || proxy.length) && !blockProducers.compareTool) { - dispatch.blockProducers.toggleCompareTool() - } - dispatch.isLoading.storeIsContentLoading(false) - } catch (error) { - console.error('getUserChainData', error) - dispatch.isLoading.storeIsContentLoading(false) - this.setUser(null) - } - }, - async removeBlockProducersVotedByUser() { - this.setUser(null) - dispatch.blockProducers.clearSelected() - }, - async deleteUserRate({ user, bpName }, state) { - try { - dispatch.isLoading.storeIsContentLoading(true) - - const { - data: { - delete_user_ratings: { affected_rows: affectedRows } - } - } = await apolloClient.mutate({ - variables: { user, bpName }, - mutation: MUTATION_DELETE_USER_RATE - }) - - if (affectedRows) { - const { - data: { userRates } - } = state.user - const rates = userRates.filter(({ owner }) => owner !== bpName) - - this.setUser({ ...state.user.data, userRates: rates }) - } - - dispatch.isLoading.storeIsContentLoading(false) - } catch (error) { - console.error('deleteUserRate', error) - dispatch.isLoading.storeIsContentLoading(false) - } - }, - async getUserRates({ userRate }, { user }) { - try { - dispatch.isLoading.storeIsContentLoading(true) - - const { message, ...bpRate } = userRate - const userRatesFiltered = user.data.userRates.filter( - ({ owner }) => owner !== bpRate.bp - ) - - this.setUser({ - ...user.data, - userRates: [...userRatesFiltered, bpRate] - }) - dispatch.isLoading.storeIsContentLoading(false) - } catch (error) { - console.error('getUserRates', error) - dispatch.isLoading.storeIsContentLoading(false) - this.setUser(null) - } - } - }) -} - -export default user diff --git a/webapp/src/models/home.js b/webapp/src/models/home.js deleted file mode 100644 index 6aa6d7d6..00000000 --- a/webapp/src/models/home.js +++ /dev/null @@ -1,35 +0,0 @@ -import { findBPById } from 'services/bps' -import getBPRadarData from 'utils/getBPRadarData' - -const initialState = { - isPlaying: false, - blockProducer: null -} - -const home = { - state: initialState, - - reducers: { - setBP(state, blockProducer) { - return { - ...state, - blockProducer - } - } - }, - - effects: { - async getBlockData() { - const blockProducer = await findBPById(0) - this.setBP({ - ...blockProducer, - data: getBPRadarData({ - name: blockProducer.org.candidate_name, - parameters: blockProducer.parameters - }) - }) - } - } -} - -export default home diff --git a/webapp/src/models/index.js b/webapp/src/models/index.js deleted file mode 100644 index 83516b31..00000000 --- a/webapp/src/models/index.js +++ /dev/null @@ -1,7 +0,0 @@ -export { default as settings } from './settings' -export { default as location } from './location' -export { default as blockProducers } from './BlockProducer/blockProducers' -export { default as proxies } from './Proxy/proxy' -export { default as home } from './home' -export { default as user } from './User/user' -export { default as isLoading } from './isLoading' diff --git a/webapp/src/models/isLoading.js b/webapp/src/models/isLoading.js deleted file mode 100644 index 1bc20bfa..00000000 --- a/webapp/src/models/isLoading.js +++ /dev/null @@ -1,14 +0,0 @@ -export default { - state: { - isContentLoading: false - }, - - reducers: { - storeIsContentLoading(state, isLoading) { - return { - ...state, - isContentLoading: isLoading - } - } - } -} diff --git a/webapp/src/models/location.js b/webapp/src/models/location.js deleted file mode 100644 index 17c295e2..00000000 --- a/webapp/src/models/location.js +++ /dev/null @@ -1,36 +0,0 @@ -const initialState = { - pathname: window.location.pathname, - data: {} -} - -const location = { - state: initialState, - - reducers: { - setLocation(state, pathname, data = {}) { - return { - ...state, - pathname, - data - } - } - } -} - -export const locationChangeListener = ({ dispatch, getState }) => { - let { - location: { pathname: currentPathname } - } = window - - window.setInterval(() => { - const { - location: { pathname } - } = window - if (currentPathname !== pathname) { - currentPathname = pathname - dispatch.location.setLocation(pathname) - } - }, 400) -} - -export default location diff --git a/webapp/src/models/settings.js b/webapp/src/models/settings.js deleted file mode 100644 index bc6153c0..00000000 --- a/webapp/src/models/settings.js +++ /dev/null @@ -1,19 +0,0 @@ -// Initial state -const initialState = { - language: 'en', - notifications: true -} - -const settings = { - state: initialState, - reducers: { - setSettings(state, { key, value }) { - return { - ...state, - [key]: value - } - } - } -} - -export default settings diff --git a/webapp/src/routes/Account/index.js b/webapp/src/routes/Account/index.js new file mode 100644 index 00000000..7ad180dd --- /dev/null +++ b/webapp/src/routes/Account/index.js @@ -0,0 +1,284 @@ +import React, { useState, forwardRef } from 'react' +import { useTranslation } from 'react-i18next' +import { useMutation } from '@apollo/client' +import clsx from 'clsx' +import Button from '@mui/material/Button' +import Paper from '@mui/material/Paper' +import Box from '@mui/material/Box' +import Typography from '@mui/material/Typography' +import { makeStyles } from '@mui/styles' +import Avatar from '@mui/material/Avatar' +import MuiAlert from '@mui/material//Alert' +import IconButton from '@mui/material/IconButton' +import CloseIcon from '@mui/icons-material/Close' +import Accordion from '@mui/material/Accordion' +import AccordionSummary from '@mui/material/AccordionSummary' +import AccordionDetails from '@mui/material/AccordionDetails' +import ExpandMoreIcon from '@mui/icons-material/ExpandMore' +import Snackbar from '@mui/material/Snackbar' +import Link from '@mui/material/Link' +import _get from 'lodash.get' + +import { DELETE_USER_RATE } from '../../gql' +import { mainConfig } from '../../config' +import TitlePage from '../../components/PageTitle' +import { useSharedState } from '../../context/state.context' +import formatNumber from '../../utils/format-number' + +import styles from './styles' + +const useStyles = makeStyles(styles) +const VOTE_INDICATORS = [ + 'community', + 'development', + 'infrastructure', + 'transparency', + 'trustiness' +] + +const INIT_RATING_STATE_DATA = { + processing: false, + txError: null, + txSuccess: false +} + +const Alert = forwardRef(function Alert(props, ref) { + return +}) + +const Account = () => { + const { t } = useTranslation('account') + const classes = useStyles() + const [deleteUserRate] = useMutation(DELETE_USER_RATE) + const [state, { logout, setUser }] = useSharedState() + const [ratingState, setRatingState] = useState(INIT_RATING_STATE_DATA) + const [showMessage, setShowMessage] = useState(false) + + const onHandleDeleteUserRate = async bpName => { + try { + if (!state.user) { + setShowMessage(true) + + return + } + + const transaction = { + actions: [ + { + account: mainConfig.contract, + name: 'rmrate', + authorization: [ + { + actor: state.user.accountName, + permission: 'active' + } + ], + data: { user: state.user.accountName, bp: bpName } + } + ] + } + + await state.ual.activeUser.signTransaction(transaction, { + broadcast: true + }) + + await deleteUserRate({ + variables: { + user: state.user.accountName, + bpName + } + }) + + await setUser() + + setRatingState({ + ...ratingState, + txError: null, + processing: true, + txSuccess: true + }) + } catch (error) { + setRatingState({ + ...ratingState, + processing: false, + txError: error.cause ? error.cause.message : error + }) + } + } + + const handleClose = (e, reason) => { + if (reason === 'clickaway') { + return + } + + setShowMessage(false) + setRatingState({ + ...ratingState, + processing: false, + txError: null, + txSuccess: false + }) + } + + return ( + + + + + {t('title')} + + + + + {state.user + ? `${state.user.accountName}: ${ + state.user?.userData?.core_liquid_balance || 0 + }` + : 'accountName: 0'} + + + {(state.user ? state.user?.userData?.userRates || [] : []).map( + rate => { + const imageURL = _get( + rate, + 'bpjson.org.branding.logo_256', + null + ) + const BPName = _get( + rate, + 'bpjson.org.candidate_name', + rate.bp + ) + const date = _get( + rate, + 'tx_data.transaction.transactionDate', + '' + ).substring(0, 10) + + return ( + + } + aria-controls='panel1a-content' + id='panel1a-header' + > + + + {!imageURL ? ( + 'BP' + ) : ( + + )} + + + {date.length > 1 + ? `${t('youRated')} ${BPName} - ${date}` + : `${t('youRated')} ${BPName}`} + + + + + + {t('yourRating')} + + {VOTE_INDICATORS.map(value => ( + + {t(value)}: + + {formatNumber(rate.ratings[value], 0)} + + + ))} + + {rate.tx_data && ( + + {rate.tx_data.transaction.transactionId} + + )} + + + + onHandleDeleteUserRate(rate.bp)} + > + + {t('unpublish')} + + + + + + ) + } + )} + + + + + {t('voteWithoutLogin')} + + + + + {ratingState.txError} + + + + + {t('success')} + + + + + + + ) +} + +export default Account diff --git a/webapp/src/routes/Account/styles.js b/webapp/src/routes/Account/styles.js new file mode 100644 index 00000000..c54604a2 --- /dev/null +++ b/webapp/src/routes/Account/styles.js @@ -0,0 +1,101 @@ +export default theme => ({ + container: { + padding: theme.spacing(3, 2), + color: theme.palette.common.white + }, + account: { + padding: theme.spacing(2) + }, + title: { + marginBottom: '12.5px !important', + fontWeight: 'normal', + fontStretch: 'normal', + fontStyle: 'normal', + lineHeight: '1.17', + letterSpacing: 'normal', + textAlign: 'left', + color: theme.palette.primary.dark, + [theme.breakpoints.down('sm')]: { + fontSize: '2.03rem !important', + marginBottom: 0 + } + }, + box: { + height: 'calc(100% - 55px)', + display: 'flex', + flexDirection: 'column', + justifyContent: 'space-between' + }, + bold: { + marginBottom: `${theme.spacing(1)} !important`, + fontWeight: 'bold', + fontStretch: 'normal', + fontStyle: 'normal', + lineHeight: '23px !important', + letterSpacing: '0.15px !important', + textAlign: 'left', + color: theme.palette.primary.dark, + fontSize: '18px !important' + }, + button: { + marginTop: `${theme.spacing(3)} !important` + }, + rateList: { + marginTop: theme.spacing(3), + '& hr': { + width: '100%' + } + }, + avatar: { + backgroundColor: theme.palette.surface.main + }, + link: { + overflow: 'hidden', + textOverflow: 'ellipsis', + whiteSpace: 'nowrap', + display: 'block', + width: '100%', + color: '#1a73e8' + }, + accordionTitle: { + marginLeft: `${theme.spacing(1)} !important` + }, + row: { + display: 'flex', + justifyContent: 'space-between', + marginBottom: theme.spacing(1), + width: '80%' + }, + remove: { + display: 'flex', + justifyContent: 'flex-end', + '& svg': { + fontSize: 16, + color: '#CD4729' + }, + '& p': { + fontStyle: 'normal', + fontWeight: '500', + fontSize: '14px', + lineHeight: '16px', + display: 'flex', + alignItems: 'center', + textAlign: 'center', + letterSpacing: '1px', + textTransform: 'uppercase', + color: '#CD4729' + } + }, + yourRate: { + fontStyle: 'normal', + fontWeight: '500 !important', + lineHeight: '24px', + color: theme.palette.common.black, + marginBottom: `${theme.spacing(1)} !important` + }, + boxWrapper: { + alignItems: 'center', + display: 'flex' + }, + alert: { width: '100%' } +}) diff --git a/webapp/src/routes/BlockProducers/BlockProducerProfile.js b/webapp/src/routes/BlockProducers/BlockProducerProfile.js new file mode 100644 index 00000000..a10386af --- /dev/null +++ b/webapp/src/routes/BlockProducers/BlockProducerProfile.js @@ -0,0 +1,352 @@ +import React, { useState, useEffect, forwardRef, Fragment } from 'react' +import PropTypes from 'prop-types' +import { useTranslation } from 'react-i18next' +import { Link, useParams } from 'react-router-dom' +import Avatar from '@mui/material/Avatar' +import Button from '@mui/material/Button' +import Grid from '@mui/material/Grid' +import Snackbar from '@mui/material/Snackbar' +import Typography from '@mui/material/Typography' +import { makeStyles } from '@mui/styles' +import MuiAlert from '@mui/material/Alert' +import KeyboardArrowLeft from '@mui/icons-material/KeyboardArrowLeft' +import AccountCircle from '@mui/icons-material/AccountCircle' +import CloseIcon from '@mui/icons-material/Close' +import _get from 'lodash.get' +import Box from '@mui/material/Box' +import useMediaQuery from '@mui/material/useMediaQuery' +import IconButton from '@mui/material/IconButton' +import { Link as MLink } from '@mui/material' + +import { mainConfig } from '../../config' +import getBPRadarData from '../../utils/get-bp-radar-data' +import TitlePage from '../../components/PageTitle' +import PolarChart from '../../components/PolarChart' +import Table from '../../components/Table' +import getAverageValue from '../../utils/get-average-value' +import { useSharedState } from '../../context/state.context' + +import { + SocialNetworks, + GeneralInformation, + WebsiteLegend, + AdditionalResources +} from './GeneralInformationProfile' +import styles from './styles' + +const useStyles = makeStyles(styles) + +const Alert = forwardRef(function Alert(props, ref) { + return +}) + +const ProfileTitle = ({ + classes, + hasInformation, + producer, + t, + bpTitle, + isContentLoading +}) => { + if (!isContentLoading && !producer) { + return ( + + {t('noBlockProducer')} + + ) + } + + return ( + <> + + {bpTitle} + + {!hasInformation && ( + + {t('noBpJson')} + + )} + + ) +} + +const BlockProducerProfile = () => { + const { t } = useTranslation('profile') + const { account } = useParams() + const classes = useStyles() + const [state, { setProducer }] = useSharedState() + const isMobile = useMediaQuery('(max-width:768px)') + const [isRated, setIsRated] = useState(false) + const [bpHasInformation, setBpHasInformation] = useState(false) + const [blockProducerLogo, setBlockProducerLogo] = useState(null) + const [webInfo, setWebInfo] = useState(null) + const [polarChartData, setPolarChartData] = useState([]) + const [blockProducerTitle, setBlockProducerTitle] = useState('No Title') + const [open, setOpen] = useState(false) + + const location = { state: { transactionId: 12 } } /// Check this logic + + const getRatingData = edenRate => ({ + community: edenRate.community || 0, + development: edenRate.development || 0, + infrastructure: edenRate.development || 0, + transparency: edenRate.transparency || 0, + trustiness: edenRate.trustiness || 0 + }) + + const setProfileData = bp => { + const userDataSet = getBPRadarData({ + name: t('edenRates'), + parameters: getRatingData(bp.edenRate) + }) + + setBpHasInformation(!!Object.values(bp.bpjson).length) + setBlockProducerLogo(_get(bp, 'bpjson.org.branding.logo_256', null)) + setBlockProducerTitle( + _get(bp, 'bpjson.org.candidate_name', _get(bp, 'system.owner', 'No Data')) + ) + setWebInfo(_get(bp, 'general_info', null)) + setPolarChartData([{ ...bp.data, name: t('eosRates') }, userDataSet]) + } + + const handleClose = (e, reason) => { + if (reason === 'clickaway') { + return + } + setOpen(false) + } + + useEffect(() => { + const getBpData = async () => { + if (state.blockProducers.data.length) { + // TODO: do a double check if this is necessary + const bp = state.blockProducers.data.find( + ({ owner }) => owner === account + ) + + setProfileData(bp) + + return + } + + await setProducer(account) + } + + getBpData() + }, [account]) + + useEffect(() => { + if (!state.blockProducer) { + return + } + + setProfileData(state.blockProducer) + }, [state.blockProducer]) + + useEffect(() => { + if (state.user && state.blockProducer) { + const { userRates = [] } = state.user.userData + + setIsRated( + userRates.some(rate => rate.owner === state.blockProducer.owner) + ) + } + }, [state.user, state.blockProducer]) + + // useEffect(() => { + // if (location.state.transactionId) setOpen(true) + // else setOpen(false) + // }, []) + + return ( + + + + + + + + + + + {blockProducerLogo ? ( + + + + ) : ( + + )} + + + + {!isMobile && ( + + + + + + + + + )} + + + + + + + + +
+ + + {isMobile && ( + <> + + + + + + + + + + )} + + + + + + + + + + } + /> + + ) +} + +ProfileTitle.propTypes = { + classes: PropTypes.object, + hasInformation: PropTypes.bool, + producer: PropTypes.object, + t: PropTypes.any, + bpTitle: PropTypes.string, + isContentLoading: PropTypes.bool +} + +export default BlockProducerProfile diff --git a/webapp/src/routes/block-producers/block-producer-rate.js b/webapp/src/routes/BlockProducers/BlockProducerRate.js similarity index 53% rename from webapp/src/routes/block-producers/block-producer-rate.js rename to webapp/src/routes/BlockProducers/BlockProducerRate.js index bfaf2018..b9526050 100644 --- a/webapp/src/routes/block-producers/block-producer-rate.js +++ b/webapp/src/routes/BlockProducers/BlockProducerRate.js @@ -1,33 +1,29 @@ /* eslint-disable react/display-name */ import React, { useState, useEffect, forwardRef, useRef } from 'react' -import PropTypes from 'prop-types' import { useTranslation } from 'react-i18next' -import { useDispatch, useSelector } from 'react-redux' -import { Link } from '@reach/router' -import { - useMediaQuery, - Avatar, - Button, - Grid, - CircularProgress, - Typography -} from '@material-ui/core' -import AccountCircle from '@material-ui/icons/AccountCircle' -import KeyboardArrowLeft from '@material-ui/icons/KeyboardArrowLeft' +import { Link, useParams } from 'react-router-dom' +import useMediaQuery from '@mui/material/useMediaQuery' +import Avatar from '@mui/material/Avatar' +import Button from '@mui/material/Button' +import Grid from '@mui/material/Grid' +import CircularProgress from '@mui/material/CircularProgress' +import Typography from '@mui/material/Typography' +import AccountCircle from '@mui/icons-material/AccountCircle' +import KeyboardArrowLeft from '@mui/icons-material/KeyboardArrowLeft' import _get from 'lodash.get' import classNames from 'classnames' -import Snackbar from '@material-ui/core/Snackbar' -import MuiAlert from '@material-ui/lab/Alert' -import { makeStyles } from '@material-ui/core/styles' -import formatNumber from 'utils/formatNumber' -import Box from '@material-ui/core/Box' - -import TitlePage from 'components/title-page' -import Radar from 'components/radar' -import { contract } from '../../config' -import getBPRadarData from 'utils/getBPRadarData' - -import SliderRatingSection from './slider-rating-section' +import Snackbar from '@mui/material/Snackbar' +import MuiAlert from '@mui/material/Alert' +import { makeStyles } from '@mui/styles' +import Box from '@mui/material/Box' + +import TitlePage from '../../components/PageTitle' +import PolarChart from '../../components/PolarChart' +import getBPRadarData from '../../utils/get-bp-radar-data' +import { useSharedState } from '../../context/state.context' +import { mainConfig } from '../../config' + +import SliderRatingSection from './SliderRatingSection' import styles from './styles' const useStyles = makeStyles(styles) @@ -48,39 +44,36 @@ const INIT_RATING_STATE_DATA = { txSuccess: false } -const BlockProducerRate = ({ account, ual }) => { +const Alert = forwardRef(function Alert(props, ref) { + return +}) + +const BlockProducerRate = () => { + const classes = useStyles() + const { account } = useParams() + const { t } = useTranslation('bpRatePage') + const [state, { setProducer }] = useSharedState() const [ratingState, setRatingState] = useState(INIT_RATING_STATE_DATA) - const [isNewRate, setIsNewRate] = useState(true) + const [isRated, setIsRated] = useState(true) + const [blockProducerLogo, setBlockProducerLogo] = useState(null) + const [blockProducerTitle, setBlockProducerTitle] = useState('No Title') + const [polarChartData, setPolarChartData] = useState([]) const [showMessage, setShowMessage] = useState(false) const [showAlert, setShowAlert] = useState(false) const linkBack = useRef(null) - const { t } = useTranslation('bpRatePage') - const dispatch = useDispatch() - const { producer, userRate, edenRate } = useSelector( - (state) => state.blockProducers - ) - const { data: user } = useSelector((state) => state.user) - const classes = useStyles() - const accountName = _get(ual, 'activeUser.accountName', null) - const bpData = _get(producer, 'data', {}) const [lastTransactionId, setLastTransactionId] = useState(undefined) - const isDesktop = useMediaQuery('(min-width:769px)') + + // const isDesktop = useMediaQuery('(min-width:769px)') const isMobile = useMediaQuery('(max-width:767px)') - const [sizes, setSizes] = useState() + // const [sizes, setSizes] = useState() - const handleStateChange = (parameter) => (event, value) => { + const handleStateChange = parameter => (event, value) => { setRatingState({ ...ratingState, [parameter]: value }) } - const bPLogo = _get(producer, 'bpjson.org.branding.logo_256', null) - - useEffect(() => { - setSizes(isDesktop ? 425 : '100%') - }, [isDesktop]) - - function Alert(props) { - return - } + // useEffect(() => { + // // setSizes(isDesktop ? 425 : '100%') + // }, [isDesktop]) const handleClose = (event, reason) => { if (reason === 'clickaway') { @@ -106,130 +99,62 @@ const BlockProducerRate = ({ account, ual }) => { } useEffect(() => { - const getData = async () => { - if (account) { - dispatch.blockProducers.getBlockProducerByOwner(account) - } - - if (accountName) { - await dispatch.user.getUserChainData({ ual }) - - dispatch.blockProducers.getBlockProducerRatingByOwner({ - bp: account, - userAccount: accountName - }) - setShowMessage(false) - } - } - - getData() - }, [accountName, account, ual, setShowMessage]) - - useEffect(() => { - if (userRate) { - setRatingState({ - ...ratingState, - community: accountName ? userRate.community : 1, - development: accountName ? userRate.development : 1, - infra: accountName ? userRate.infrastructure : 1, - transparency: accountName ? userRate.transparency : 1, - trustiness: accountName ? userRate.trustiness : 1 - }) - setIsNewRate(false) - } else { - setRatingState(INIT_RATING_STATE_DATA) - setIsNewRate(true) - } - }, [userRate, accountName, setRatingState]) - - useEffect(() => { - dispatch.blockProducers.setShowSortSelected(false) + // dispatch.blockProducers.setShowSortSelected(false) }, []) - useEffect(() => { - if (user && user.edenMember) { - setShowAlert(false) - } else if (user && (user.hasProxy || user.producersCount >= 21)) { - setShowAlert(false) - } else { - user && setShowAlert(true) - } - }, [user, setShowAlert]) - - const getRatingData = (useString = false) => { - const { - community, - communityEnabled, - development, - developmentEnabled, - infra, - infraEnabled, - transparency, - transparencyEnabled, - trustiness, - trustinessEnabled - } = ratingState - - if (useString) { - return { - community: formatNumber(communityEnabled ? community : 0, 0).toString(), - development: formatNumber( - developmentEnabled ? development : 0, - 0 - ).toString(), - infrastructure: formatNumber(infraEnabled ? infra : 0, 0).toString(), - transparency: formatNumber( - transparencyEnabled ? transparency : 0, - 0 - ).toString(), - trustiness: formatNumber( - trustinessEnabled ? trustiness : 0, - 0 - ).toString() - } - } - - return { - community: communityEnabled ? community : 0, - development: developmentEnabled ? development : 0, - infrastructure: infraEnabled ? infra : 0, - transparency: transparencyEnabled ? transparency : 0, - trustiness: trustinessEnabled ? trustiness : 0 - } - } - - const userDataSet = getBPRadarData({ - name: t('myRate'), - parameters: getRatingData() - }) - - const getEdenRatingData = () => { - if (edenRate) { - return { - community: edenRate.community, - development: edenRate.development, - infrastructure: edenRate.development, - transparency: edenRate.transparency, - trustiness: edenRate.trustiness - } - } - return { - community: 0, - development: 0, - infrastructure: 0, - transparency: 0, - trustiness: 0 - } - } - - const edenDataSet = getBPRadarData({ - name: t('edenRates'), - parameters: getEdenRatingData() + // const getRatingData = (useString = false) => { + // const { + // community, + // communityEnabled, + // development, + // developmentEnabled, + // infra, + // infraEnabled, + // transparency, + // transparencyEnabled, + // trustiness, + // trustinessEnabled + // } = ratingState + + // if (useString) { + // return { + // community: formatNumber(communityEnabled ? community : 0, 0).toString(), + // development: formatNumber( + // developmentEnabled ? development : 0, + // 0 + // ).toString(), + // infrastructure: formatNumber(infraEnabled ? infra : 0, 0).toString(), + // transparency: formatNumber( + // transparencyEnabled ? transparency : 0, + // 0 + // ).toString(), + // trustiness: formatNumber( + // trustinessEnabled ? trustiness : 0, + // 0 + // ).toString() + // } + // } + + // return { + // community: communityEnabled ? community : 0, + // development: developmentEnabled ? development : 0, + // infrastructure: infraEnabled ? infra : 0, + // transparency: transparencyEnabled ? transparency : 0, + // trustiness: trustinessEnabled ? trustiness : 0 + // } + // } + + const getRatingData = rate => ({ + community: parseFloat(rate.community || 0), + development: parseFloat(rate.development || 0), + infrastructure: parseFloat(rate.development || 0), + transparency: parseFloat(rate.transparency || 0), + trustiness: parseFloat(rate.trustiness || 0) }) const transact = async () => { try { - if (!accountName) { + if (!state.user.accountName) { setShowMessage(true) return @@ -240,13 +165,17 @@ const BlockProducerRate = ({ account, ual }) => { { authorization: [ { - actor: accountName, + actor: state.user.accountName, permission: 'active' } ], - account: contract, + account: mainConfig.contract, name: 'rate', - data: { user: accountName, bp: account, ...getRatingData(true) } + data: { + user: state.user.accountName, + bp: account, + ...getRatingData(true) + } } ] } @@ -258,25 +187,25 @@ const BlockProducerRate = ({ account, ual }) => { txSuccess: false }) - const result = await ual.activeUser.signTransaction(transaction, { + const result = await state.ual.activeUser.signTransaction(transaction, { broadcast: true }) - await dispatch.blockProducers.saveLastTransaction({ - transaction: { - transactionId: result.transaction.transaction_id, - transactionDate: result.transaction.processed.block_time - } - }) + // await dispatch.blockProducers.saveLastTransaction({ + // transaction: { + // transactionId: result.transaction.transaction_id, + // transactionDate: result.transaction.processed.block_time + // } + // }) setLastTransactionId(result.transactionId) - await dispatch.blockProducers.mutationInsertUserRating({ - ual, - user: accountName, - bp: account, - ...getRatingData(false), - result - }) + // await dispatch.blockProducers.mutationInsertUserRating({ + // ual, + // user: accountName, + // bp: account, + // ...getRatingData(false), + // result + // }) setRatingState({ ...ratingState, @@ -294,14 +223,76 @@ const BlockProducerRate = ({ account, ual }) => { } } + const setProfileData = (bp, userDataSet) => { + const edenDataSet = getBPRadarData({ + name: t('edenRates'), + parameters: getRatingData(bp.edenRate) + }) + + setBlockProducerTitle( + `${t('title')} ${ + _get(bp, 'bpjson.org.candidate_name') || + _get(bp, 'system.owner', t('noBlockProducer')) + } - EOS Rate` + ) + setBlockProducerLogo(_get(bp, 'bpjson.org.branding.logo_256', null)) + setPolarChartData([ + { ...bp.data, name: t('eosRates') }, + edenDataSet, + userDataSet + ]) + } + + useEffect(() => { + const getBpData = async () => { + if (state.blockProducers.data.length) { + // TODO: do a double check if this is necessary + const bp = state.blockProducers.data.find( + ({ owner }) => owner === account + ) + + setProfileData(bp, {}) + + return + } + + await setProducer(account) + } + + getBpData() + }, [account]) + + useEffect(() => { + if (state.user && state.blockProducer) { + const { userRates = [] } = state.user.userData + const bpRated = userRates.find( + rate => rate.owner === state.blockProducer.owner + ) + const parameters = getRatingData(bpRated.ratings) + const userDataSet = getBPRadarData({ + name: t('myRate'), + parameters: getRatingData(bpRated.ratings) + }) + + if ( + state.user.userData.edenMember || + state.user.userData.hasProxy || + state.user.userData.producersCount >= 21 + ) { + setShowAlert(false) + } else { + setShowAlert(true) + } + + setProfileData(state.blockProducer, userDataSet) + setIsRated(!!bpRated) + setRatingState({ ...INIT_RATING_STATE_DATA, ...parameters }) + } + }, [state.user, state.blockProducer]) + return ( - + { {t('allBPs')} - {bPLogo ? ( + {blockProducerLogo ? ( - + ) : ( )} - {_get(producer, 'bpjson.org.candidate_name') || - _get(producer, 'system.owner', t('noBlockProducer'))} + {_get(state.blockProducer, 'bpjson.org.candidate_name') || + _get(state.blockProducer, 'system.owner', t('noBlockProducer'))} @@ -357,27 +352,18 @@ const BlockProducerRate = ({ account, ual }) => { {t('subText')} {t('helpText')} {t('rateText')} + {isMobile && ( - + )} + { {ratingState.txError} - @@ -442,20 +436,10 @@ const BlockProducerRate = ({ account, ual }) => { > {!isMobile && ( - + )} + { )} @@ -533,9 +525,4 @@ const BlockProducerRate = ({ account, ual }) => { ) } -BlockProducerRate.propTypes = { - account: PropTypes.string, - ual: PropTypes.object -} - export default BlockProducerRate diff --git a/webapp/src/routes/BlockProducers/BottomSheetSelectedBps.js b/webapp/src/routes/BlockProducers/BottomSheetSelectedBps.js new file mode 100644 index 00000000..fb78ac4c --- /dev/null +++ b/webapp/src/routes/BlockProducers/BottomSheetSelectedBps.js @@ -0,0 +1,32 @@ +import React from 'react' +import PropTypes from 'prop-types' +import Drawer from '@mui/material/Drawer' +import { makeStyles } from '@mui/styles' + +import styles from './styles' + +const useStyles = makeStyles(styles) + +const SelectedBpsBottomSheet = ({ open, children, classesStyle }) => { + const classes = useStyles() + + return ( + + {children} + + ) +} + +SelectedBpsBottomSheet.propTypes = { + open: PropTypes.bool, + classesStyle: PropTypes.oneOfType([PropTypes.object, PropTypes.string]), + children: PropTypes.node +} + +export default SelectedBpsBottomSheet diff --git a/webapp/src/routes/block-producers/filter-box.js b/webapp/src/routes/BlockProducers/FilterBox.js similarity index 76% rename from webapp/src/routes/block-producers/filter-box.js rename to webapp/src/routes/BlockProducers/FilterBox.js index 3506cc8f..69a4673d 100644 --- a/webapp/src/routes/block-producers/filter-box.js +++ b/webapp/src/routes/BlockProducers/FilterBox.js @@ -1,14 +1,14 @@ import React, { useState, useEffect } from 'react' -import { makeStyles } from '@material-ui/core/styles' -import List from '@material-ui/core/List' -import Typography from '@material-ui/core/Typography' -import ListSubheader from '@material-ui/core/ListSubheader' -import ListItem from '@material-ui/core/ListItem' +import { makeStyles } from '@mui/material/styles' +import List from '@mui/material/List' +import Typography from '@mui/material/Typography' +import ListSubheader from '@mui/material/ListSubheader' +import ListItem from '@mui/material/ListItem' import ParameterRangeSelector from 'components/parameter-range-selector' import bpParameters from 'config/comparison-parameters' -const useStyles = makeStyles((theme) => ({ +const useStyles = makeStyles(theme => ({ nested: { paddingLeft: theme.spacing(2), color: 'white' @@ -34,7 +34,7 @@ const FilterBox = () => { ) }, []) - const handleValueChange = (parameter) => (value) => + const handleValueChange = parameter => value => setParameters({ [parameter]: value }) @@ -44,7 +44,7 @@ const FilterBox = () => { className={classes.nested} subheader={Filter Parameters} > - {bpParameters.map((parameter) => ( + {bpParameters.map(parameter => ( { return defaultMessage } - +// refactor this TODO const SocialNetworks = ({ classes, producer }) => { const { t } = useTranslation('profile') const github = _get(producer, 'bpjson.org.social.github') diff --git a/webapp/src/routes/block-producers/slider-rating-section.js b/webapp/src/routes/BlockProducers/SliderRatingSection.js similarity index 87% rename from webapp/src/routes/block-producers/slider-rating-section.js rename to webapp/src/routes/BlockProducers/SliderRatingSection.js index f4084420..b7876732 100644 --- a/webapp/src/routes/block-producers/slider-rating-section.js +++ b/webapp/src/routes/BlockProducers/SliderRatingSection.js @@ -1,11 +1,15 @@ import React from 'react' import PropTypes from 'prop-types' import classNames from 'classnames' -import { Grid, Switch, Tooltip, Typography } from '@material-ui/core' -import { makeStyles } from '@material-ui/core/styles' -import HelpOutline from '@material-ui/icons/HelpOutline' +import Grid from '@mui/material/Grid' +import Switch from '@mui/material/Switch' +import Tooltip from '@mui/material/Tooltip' +import Typography from '@mui/material/Typography' +import Box from '@mui/material/Box' +import { makeStyles } from '@mui/styles' +import HelpOutline from '@mui/icons-material/HelpOutline' -import RateSlider from 'components/rate-slider' +import RateSlider from '../../components/RateSlider' import styles from './styles' @@ -49,7 +53,7 @@ const SliderRatingSection = ({ -
+ -
+
-
+ -
+
-
+ -
+
-
+ -
+
-
+ -
+
) diff --git a/webapp/src/routes/BlockProducers/index.js b/webapp/src/routes/BlockProducers/index.js new file mode 100644 index 00000000..a5be5c92 --- /dev/null +++ b/webapp/src/routes/BlockProducers/index.js @@ -0,0 +1,280 @@ +import React, { useEffect, useState, useRef } from 'react' +import { makeStyles } from '@mui/styles' +import { useTranslation } from 'react-i18next' +import Grid from '@mui/material/Grid' +import Box from '@mui/material/Box' +import Button from '@mui/material/Button' +import Typography from '@mui/material/Typography' +import Collapse from '@mui/material/Collapse' +import ThumbUpAltIcon from '@mui/icons-material/ThumbUpAlt' +import clsx from 'clsx' +import _get from 'lodash.get' + +import TitlePage from '../../components/PageTitle' +import CompareTool from '../../components/CompareTool' +import Card from '../../components/Card' +import getAverageValue from '../../utils/get-average-value' +import { useSharedState } from '../../context/state.context' + +import styles from './styles' +import SelectedBpsBottomSheet from './BottomSheetSelectedBps' + +const useStyles = makeStyles(styles) + +const AllBps = () => { + const { t } = useTranslation('translations') + const [state, { setProducers, setCompareBPTool, setSelectedProducers }] = + useSharedState() + const classes = useStyles() + const myRef = useRef(null) + const [currentlyVisible, setCurrentlyVisible] = useState(30) + const [hasMoreRows, setMoreRows] = useState(false) + + const [ratingState, setRatingState] = useState({ + txError: null, + txSuccess: false, + showChipMessage: false + }) + + // const sortedBPs = applySortBy(sortBy, blockProducers) + + const loadMore = () => setCurrentlyVisible(currentlyVisible + 12) + // const goToTop = () => document.getElementById('mainContent').scrollTo(0, 0) + + const handleToggleCompareTool = () => { + setCompareBPTool(!state.compareBPToolVisible) + } + + const handleToggleSelected = (item, isAddItem = false) => { + if (isAddItem) { + setSelectedProducers([...state.selectedProducers, item]) + } else { + const removeSelected = state.selectedProducers.filter( + bpName => bpName !== item + ) + + setSelectedProducers(removeSelected) + } + } + + const handleOpenDesktopVotingTool = () => { + console.log('handleOpenDesktopVotingTool') + + // goToTop() + !state.compareBPToolVisible && setCompareBPTool(true) + } + + const handleOnClear = () => { + setSelectedProducers([]) + state.compareBPToolVisible && setCompareBPTool(false) + } + + const handleOnClose = () => { + state.compareBPToolVisible && setCompareBPTool(false) + } + + const handleSetRatingState = () => { + setRatingState({ + ...ratingState, + txError: null, + txSuccess: false, + showChipMessage: false + }) + } + + const sendVoteBps = async BPs => { + if (!state.user) return + + const transaction = { + actions: [ + { + account: 'eosio', + name: 'voteproducer', + authorization: [ + { + actor: state.user.accountName, + permission: 'active' + } + ], + data: { + voter: state.user.accountName, + proxy: '', + producers: BPs.sort() + } + } + ] + } + + try { + await state.ual.activeUser.signTransaction(transaction, { + broadcast: true + }) + + setRatingState({ + ...ratingState, + txSuccess: true, + showChipMessage: true + }) + + setTimeout(() => { + setRatingState({ + ...ratingState, + txError: null, + txSuccess: false, + showChipMessage: false + }) + }, 2000) + } catch (error) { + console.warn(error) + + setRatingState({ + ...ratingState, + txError: error && error.cause ? error.cause.message : error, + showChipMessage: true + }) + } + } + + useEffect(() => { + const getData = async () => { + !state.blockProducers.data.length && + (await setProducers(currentlyVisible)) + } + + getData() + }, []) + + useEffect(() => { + if (!state.blockProducers.data.length) { + return + } + + setMoreRows(state.blockProducers.rows > currentlyVisible) + }, [state.blockProducers]) + + state.user && + console.log({ + isRated: state.user.userData.userRates.some( + ({ owner }) => owner === 'eoscostarica' + ) + }) + + return ( + + + + sendVoteBps(state.selectedProducers || [])} + userInfo={state.user} + message={ratingState} + setMessage={handleSetRatingState} + handleOnClose={handleOnClose} + handleOnClear={handleOnClear} + /> + + + + + {(state.blockProducers.data || []).map(blockProducer => ( + + () => { + if (isAdding) { + if ( + !state.selectedProducers.length && + !state.compareBPToolVisible + ) { + handleToggleCompareTool() + } + + handleToggleSelected(producerAccountName, isAdding) + } else { + if ( + state.selectedProducers.length === 1 && + state.compareBPToolVisible + ) { + handleToggleCompareTool() + } + + handleToggleSelected(producerAccountName, isAdding) + } + }} + data={blockProducer} + imageURL={_get(blockProducer, 'bpjson.org.branding.logo_256')} + owner={_get(blockProducer, 'owner')} + title={_get(blockProducer, 'bpjson.org.candidate_name')} + pathLink='block-producers' + buttonLabel={t('addToVote')} + average={getAverageValue(_get(blockProducer, 'average', 0))} + rate={_get(blockProducer, 'ratings_cntr', 0)} + isNewRate={ + state.user && + state.user.userData.userRates.some( + ({ owner }) => owner === blockProducer.owner + ) + } + /> + + ))} + + + {state.selectedProducers.length > 0 && ( + + + + + + )} + + sendVoteBps(state.selectedProducers || [])} + userInfo={state.user} + message={ratingState} + setMessage={handleSetRatingState} + handleOnClose={handleOnClose} + handleOnClear={handleOnClear} + /> + + + + + + ) +} + +export default AllBps diff --git a/webapp/src/routes/block-producers/styles.js b/webapp/src/routes/BlockProducers/styles.js similarity index 82% rename from webapp/src/routes/block-producers/styles.js rename to webapp/src/routes/BlockProducers/styles.js index cfa5b4c8..7dc13733 100644 --- a/webapp/src/routes/block-producers/styles.js +++ b/webapp/src/routes/BlockProducers/styles.js @@ -1,9 +1,8 @@ -export default (theme) => ({ +export default theme => ({ // index style - root: { + rootBP: { position: 'relative', - maxWidth: '100%', - margin: 'auto' + maxWidth: '100%' }, compareToggleButton: { position: 'fixed', @@ -17,10 +16,31 @@ export default (theme) => ({ background: theme.palette.surface.main, color: theme.palette.primary.main }, - wrapper: { - padding: theme.spacing(1), + wrapperGrid: { maxWidth: '100%', - margin: 'auto' + margin: '0 auto' + }, + gridRow: { + display: 'flex', + flexFlow: 'row wrap', + justifyContent: 'center' + }, + gridItem: { + flexBasis: '100%', + '-ms-flex': 'auto', + width: '100%', + position: 'relative', + padding: 10, + boxSizing: 'border-box', + [theme.breakpoints.up('sm')]: { + flexBasis: '50%' + }, + [theme.breakpoints.up('md')]: { + flexBasis: '33.33%' + }, + [theme.breakpoints.up('lg')]: { + flexBasis: '20%' + } }, compareTool: { paddingTop: '0 !important', @@ -38,8 +58,12 @@ export default (theme) => ({ bpCard: { backgroundColor: theme.palette.primary.light }, + loadMoreBtnBox: { + display: 'flex', + justifyContent: 'center', + padding: theme.spacing(2, 0) + }, loadMoreButton: { - color: '#443f56', display: 'block', margin: `${theme.spacing(2)}px auto`, '&:hover': { @@ -47,11 +71,17 @@ export default (theme) => ({ color: 'white' } }, - hidden: { - opacity: 0, - transform: 'scaleY(0)', - minHeight: 0, - height: 0 + hiddenMobile: { + display: 'none', + [theme.breakpoints.up('md')]: { + display: 'flex' + } + }, + hiddenDesktop: { + display: 'flex', + [theme.breakpoints.up('md')]: { + display: 'none' + } }, // slider rating sliderWrapper: { @@ -218,7 +248,7 @@ export default (theme) => ({ zIndex: 999, maxWidth: '100%', '& > button': { - backgroundColor: 'black', + backgroundColor: theme.palette.common.black, color: 'white', borderRadius: '24px 0 0 0' } @@ -273,5 +303,9 @@ export default (theme) => ({ '& .MuiAlert-icon': { alignItems: 'center' } + }, + linkRate: { + marginLeft: `${theme.spacing(2)} !important`, // !isDesktop ? 16 : 0, + padding: `${theme.spacing(1, 2)} !important` } }) diff --git a/webapp/src/routes/proxies/filter-box.js b/webapp/src/routes/Proxies/FilterBox.js similarity index 68% rename from webapp/src/routes/proxies/filter-box.js rename to webapp/src/routes/Proxies/FilterBox.js index 8a987362..cb7051b7 100644 --- a/webapp/src/routes/proxies/filter-box.js +++ b/webapp/src/routes/Proxies/FilterBox.js @@ -1,14 +1,14 @@ import React, { useState, useEffect } from 'react' -import { makeStyles } from '@material-ui/core/styles' -import List from '@material-ui/core/List' -import Typography from '@material-ui/core/Typography' -import ListSubheader from '@material-ui/core/ListSubheader' -import ListItem from '@material-ui/core/ListItem' +import { makeStyles } from '@mui/styles' +import List from '@mui/material/List' +import Typography from '@mui/material/Typography' +import ListSubheader from '@mui/material/ListSubheader' +import ListItem from '@mui/material/ListItem' -import ParameterRangeSelector from 'components/parameter-range-selector' +import ParameterRangeSelector from '../../components/ParameterRangeSelector' import bpParameters from 'config/comparison-parameters' -const useStyles = makeStyles((theme) => ({ +const useStyles = makeStyles(theme => ({ nested: { paddingLeft: theme.spacing(2), color: 'white' @@ -34,17 +34,20 @@ const FilterBox = () => { ) }, []) - const handleValueChange = (parameter) => (value) => - setState({ - [parameter]: value - }) + const handleValueChange = parameter => value => { + // setState({ + // [parameter]: value + // }) + + console.log({ parameter, value }) + } return ( Filter Parameters} > - {bpParameters.map((parameter) => ( + {bpParameters.map(parameter => ( { const { t } = useTranslation('profile') diff --git a/webapp/src/routes/proxies/proxy-profile.js b/webapp/src/routes/Proxies/ProxyProfile.js similarity index 59% rename from webapp/src/routes/proxies/proxy-profile.js rename to webapp/src/routes/Proxies/ProxyProfile.js index d08de354..76132cda 100644 --- a/webapp/src/routes/proxies/proxy-profile.js +++ b/webapp/src/routes/Proxies/ProxyProfile.js @@ -1,57 +1,57 @@ import React, { useEffect, forwardRef, useState } from 'react' -import PropTypes from 'prop-types' -import { useDispatch, useSelector } from 'react-redux' import classNames from 'classnames' import { useTranslation } from 'react-i18next' -import { Link } from '@reach/router' -import CircularProgress from '@material-ui/core/CircularProgress' -import Avatar from '@material-ui/core/Avatar' -import Button from '@material-ui/core/Button' -import Grid from '@material-ui/core/Grid' -import { Box, useMediaQuery } from '@material-ui/core' -import Typography from '@material-ui/core/Typography' -import { makeStyles } from '@material-ui/core/styles' -import Snackbar from '@material-ui/core/Snackbar' -import MuiAlert from '@material-ui/lab/Alert' -import KeyboardArrowLeft from '@material-ui/icons/KeyboardArrowLeft' -import AccountCircle from '@material-ui/icons/AccountCircle' +import { Link, useParams } from 'react-router-dom' +import CircularProgress from '@mui/material/CircularProgress' +import Avatar from '@mui/material/Avatar' +import Button from '@mui/material/Button' +import Grid from '@mui/material/Grid' +import useMediaQuery from '@mui/material/useMediaQuery' +import Box from '@mui/material/Box' +import Typography from '@mui/material/Typography' +import { makeStyles } from '@mui/styles' +import Snackbar from '@mui/material/Snackbar' +import MuiAlert from '@mui/material/Alert' +import KeyboardArrowLeft from '@mui/icons-material/KeyboardArrowLeft' +import AccountCircle from '@mui/icons-material/AccountCircle' import _get from 'lodash.get' -import TitlePage from 'components/title-page' -import CompareTool from 'components/compare-tool' -import Radar from 'components/radar' -import { - SocialNetworks, - GeneralInformation -} from './general-information-profile' +import TitlePage from '../../components/PageTitle' +import CompareTool from '../../components/CompareTool' +import PolarChart from '../../components/PolarChart' +import { useSharedState } from '../../context/state.context' +import { SocialNetworks, GeneralInformation } from './GeneralInformationProfile' import styles from './styles' const useStyles = makeStyles(styles) -const ProxyProfile = ({ account, ual, ...props }) => { +const Alert = forwardRef(function Alert(props, ref) { + return +}) + +const ProxyProfile = () => { const { t } = useTranslation('profile') const classes = useStyles() - const dispatch = useDispatch() - const { proxy } = useSelector((state) => state.proxies) + const { account } = useParams() + const [state, { setProxy }] = useSharedState() + const [proxyLogo, setProxyLogo] = useState(null) + const [proxySlogan, setProxySlogan] = useState(null) + const [polarChartData, setPolarChartData] = useState([]) + const [producers, setProducers] = useState([]) + const [proxyTitle, setProxyTitle] = useState('No Title') const [showMessage, setShowMessage] = useState(false) const isDesktop = useMediaQuery('(min-width:767px)') const isMobile = useMediaQuery('(max-width:768px)') const [openDesktopVotingTool, setOpenDesktopVotingTool] = useState(isDesktop) - const [sizes, setSizes] = useState() const [ratingState, setRatingState] = useState({ processing: false, txError: null, txSuccess: false }) - const logo = _get(proxy, 'logo_256', null) - const ProxyTitle = _get(proxy, 'name', _get(proxy, 'owner', 'No Data')) - const accountName = _get(ual, 'activeUser.accountName', null) - const slogan = _get(proxy, 'slogan', null) - const producers = _get(proxy, 'voter_info.producers', []) - const sendVoteProxy = async (proxy) => { - if (!accountName) { + const sendVoteProxy = async proxy => { + if (!state.user.accountName) { setShowMessage(true) return @@ -64,12 +64,12 @@ const ProxyProfile = ({ account, ual, ...props }) => { name: 'voteproducer', authorization: [ { - actor: accountName, + actor: state.user.accountName, permission: 'active' } ], data: { - voter: accountName, + voter: state.user.accountName, proxy, producers: [] } @@ -85,7 +85,7 @@ const ProxyProfile = ({ account, ual, ...props }) => { txSuccess: false }) - await ual.activeUser.signTransaction(transaction, { + await state.ual.activeUser.signTransaction(transaction, { broadcast: true }) @@ -113,10 +113,6 @@ const ProxyProfile = ({ account, ual, ...props }) => { } } - function Alert(props) { - return - } - const handleClose = (event, reason) => { if (reason === 'clickaway') { return @@ -136,23 +132,43 @@ const ProxyProfile = ({ account, ual, ...props }) => { } useEffect(() => { - const getData = async () => { - await dispatch.proxies.getProxies() - await dispatch.proxies.getProxyByOwner(account) + if (state.proxy) { + setProxyLogo(_get(state.proxy, 'logo_256', null)) + setProxyTitle( + _get(state.proxy, 'name', _get(state.proxy, 'owner', 'No Data')) + ) + setProxySlogan(_get(state.proxy, 'slogan', null)) + setProducers(_get(state.proxy, 'voter_info.producers', [])) + setPolarChartData([state.proxy.data]) } + }, [state.proxy]) + + useEffect(() => { + const getProxyData = async () => { + if (state.proxies.data.length) { + // TODO: do a double check if this is necessary + const proxySelected = state.proxies.data.find( + ({ owner }) => owner === account + ) - if (accountName) setShowMessage(false) + setProxy(proxySelected, true) - getData() - }, [account, accountName, setShowMessage]) + return + } - useEffect(() => { - setSizes(isDesktop ? 400 : '95%') - }, [isDesktop]) + await setProxy(account) + } + + getProxyData() + }, [account]) + + // useEffect(() => { + // setSizes(isDesktop ? 400 : '95%') + // }, [isDesktop]) return ( - + @@ -211,9 +223,9 @@ const ProxyProfile = ({ account, ual, ...props }) => { { {!isMobile && ( - + @@ -284,27 +290,24 @@ const ProxyProfile = ({ account, ual, ...props }) => { )} - {proxy && openDesktopVotingTool && Boolean(producers.length) && ( - console.log('remove')} - className={classes.compareTool} - list={[proxy]} - selected={[account]} - isProxy - useOnlySliderView - optionalLabel={`${ProxyTitle} ${t('labelTool')}:`} - handleOnClose={handleOnClose} - /> - )} + {state.proxy && + openDesktopVotingTool && + Boolean(producers.length) && ( + console.log('remove')} + className={classes.compareTool} + list={[state.proxy]} + selected={[account]} + isProxy + useOnlySliderView + optionalLabel={`${proxyTitle} ${t('labelTool')}:`} + handleOnClose={handleOnClose} + /> + )} ) } -ProxyProfile.propTypes = { - account: PropTypes.string, - ual: PropTypes.object -} - export default ProxyProfile diff --git a/webapp/src/routes/Proxies/index.js b/webapp/src/routes/Proxies/index.js new file mode 100644 index 00000000..6bc28de6 --- /dev/null +++ b/webapp/src/routes/Proxies/index.js @@ -0,0 +1,221 @@ +import React, { useEffect, useState } from 'react' +import PropTypes from 'prop-types' +import Button from '@mui/material/Button' +import Box from '@mui/material/Box' +import Collapse from '@mui/material/Collapse' +import { makeStyles } from '@mui/styles' +import { useTranslation } from 'react-i18next' +import _get from 'lodash.get' + +import { useSharedState } from '../../context/state.context' +import TitlePage from '../../components/PageTitle' +import Card from '../../components/Card' +import CompareTool from '../../components/CompareTool' +import SelectedBpsBottomSheet from './../BlockProducers/BottomSheetSelectedBps' + +import styles from './styles' + +const useStyles = makeStyles(styles) + +const AllProxies = ({ ual = {} }) => { + const { t } = useTranslation('translations') + const classes = useStyles() + const [state, { setProxies, setCompareProxyTool, setSelectedProxies }] = + useSharedState() + const [currentlyVisible, setCurrentlyVisible] = useState(30) + const [hasMoreRows, setMoreRows] = useState(false) + const [ratingState, setRatingState] = useState({ + processing: false, + txError: null, + txSuccess: false + }) + + const loadMore = () => setCurrentlyVisible(currentlyVisible + 12) + // const goToTop = () => document.getElementById('mainContent').scrollTo(0, 0) + + const handleToggleCompareTool = () => { + setCompareProxyTool(!state.compareProxyToolVisible) + } + + const handleToggleSelected = () => { + setSelectedProxies([]) + } + + const handleOpenDesktopVotingTool = (isAdding, producerAccountName) => { + console.log({ isAdding, producerAccountName }) + + setSelectedProxies([producerAccountName]) + setCompareProxyTool(true) + } + + const handleSetRatingState = () => { + setRatingState({ + ...ratingState, + txError: null, + txSuccess: false, + showChipMessage: false + }) + } + + const sendVoteProxy = async () => { + if (!state.user.accountName) return + + const transaction = { + actions: [ + { + account: 'eosio', + name: 'voteproducer', + authorization: [ + { + actor: state.user.accountName, + permission: 'active' + } + ], + data: { + voter: state.user.accountName, + proxy: state.proxy, + producers: [] + } + } + ] + } + + try { + setRatingState({ + ...ratingState, + txError: null, + processing: true, + txSuccess: false + }) + + await ual.activeUser.signTransaction(transaction, { + broadcast: true + }) + + setRatingState({ + ...ratingState, + processing: false, + txSuccess: true + }) + + setTimeout(() => { + setRatingState({ + ...ratingState, + txError: null, + txSuccess: false + }) + }, 2000) + } catch (error) { + console.warn(error) + setRatingState({ + ...ratingState, + processing: false, + txError: error.message ? error.message : error + }) + } + } + + useEffect(() => { + const getProxiesData = async () => { + !state.proxies.data.length && (await setProxies(currentlyVisible)) + } + + getProxiesData() + }, []) + + useEffect(() => { + if (!state.proxies.data.length) { + return + } + + setMoreRows(state.proxies.rows > currentlyVisible) + }, [state.proxies]) + + return ( + + + + { + handleToggleCompareTool() + handleToggleSelected() + }} + /> + + + + + {(state.proxies.data || []).map(proxy => ( + + + + ))} + + + + { + handleToggleCompareTool() + handleToggleSelected() + }} + /> + + + + + + ) +} + +AllProxies.propTypes = { + ual: PropTypes.object +} + +export default AllProxies diff --git a/webapp/src/routes/proxies/styles.js b/webapp/src/routes/Proxies/styles.js similarity index 77% rename from webapp/src/routes/proxies/styles.js rename to webapp/src/routes/Proxies/styles.js index f6c475cb..7b00968a 100644 --- a/webapp/src/routes/proxies/styles.js +++ b/webapp/src/routes/Proxies/styles.js @@ -1,4 +1,4 @@ -export default (theme) => ({ +export default theme => ({ // index root: { position: 'relative' @@ -15,16 +15,38 @@ export default (theme) => ({ background: theme.palette.surface.main, color: theme.palette.primary.main }, - wrapper: { - padding: theme.spacing(1), + wrapperGrid: { maxWidth: '100%', - margin: 'auto' + margin: '0 auto' + }, + gridRow: { + display: 'flex', + flexFlow: 'row wrap', + justifyContent: 'center' + }, + gridItem: { + flexBasis: '100%', + '-ms-flex': 'auto', + width: '100%', + position: 'relative', + padding: 10, + boxSizing: 'border-box', + [theme.breakpoints.up('sm')]: { + flexBasis: '50%' + }, + [theme.breakpoints.up('md')]: { + flexBasis: '33.33%' + }, + [theme.breakpoints.up('lg')]: { + flexBasis: '20%' + } }, compareTool: { - minHeight: 340, + paddingTop: '0 !important', transform: 'scaleY(1)', transformOrigin: 'top', opacity: 1, + height: '100%', transition: [ 'opacity 0.25s ease', 'height 0.25s ease', @@ -164,12 +186,29 @@ export default (theme) => ({ '&:after': { content: 'close-quote' } }, reliefGrid: { - margin: '0 30px 30px 30px', + // margin: '0 30px 30px 30px', padding: '20px', border: '1px solid #f8f8f', borderRadius: '6px', boxShadow: 'inset 2px 2px 2px #fff, inset -1px 0 2px rgba(0,0,0,.1), 1px 1px 3px rgba(0,0,0,.1)', backgroundColor: '#fff' + }, + hiddenDesktop: { + display: 'flex', + [theme.breakpoints.up('md')]: { + display: 'none' + } + }, + hiddenMobile: { + display: 'none', + [theme.breakpoints.up('md')]: { + display: 'flex' + } + }, + loadMoreBtnBox: { + display: 'flex', + justifyContent: 'center', + padding: theme.spacing(2, 0) } }) diff --git a/webapp/src/routes/Route404/index.js b/webapp/src/routes/Route404/index.js new file mode 100644 index 00000000..211d4532 --- /dev/null +++ b/webapp/src/routes/Route404/index.js @@ -0,0 +1,40 @@ +import React from 'react' +import { Button, Typography } from '@material-ui/core' +import { makeStyles } from '@mui/styles' +import { Link } from 'react-router-dom' +import Helmet from 'react-helmet' + +import styles from './styles' + +const useStyles = makeStyles(styles) + +const Route404 = () => { + const classes = useStyles() + + return ( +
+ + + 404 + + + Page not found. + + + The page you are looking for might have been removed. + + + +
+ ) +} + +export default Route404 diff --git a/webapp/src/routes/Route404/styles.js b/webapp/src/routes/Route404/styles.js new file mode 100644 index 00000000..754598c1 --- /dev/null +++ b/webapp/src/routes/Route404/styles.js @@ -0,0 +1,10 @@ +export default theme => ({ + wrapper: { + padding: theme.spacing(6), + textAlign: 'center', + background: 'transparent', + [theme.breakpoints.up('md')]: { + padding: theme.spacing(10) + } + } +}) diff --git a/webapp/src/routes/settings/index.js b/webapp/src/routes/Settings/index.js similarity index 55% rename from webapp/src/routes/settings/index.js rename to webapp/src/routes/Settings/index.js index 8f8502b9..b8ed820c 100644 --- a/webapp/src/routes/settings/index.js +++ b/webapp/src/routes/Settings/index.js @@ -1,19 +1,18 @@ -import React, { useState, useEffect } from 'react' +import React from 'react' import PropTypes from 'prop-types' -import { makeStyles } from '@material-ui/core/styles' -import { useDispatch, useSelector } from 'react-redux' -import List from '@material-ui/core/List' -import ListItem from '@material-ui/core/ListItem' -import ListItemIcon from '@material-ui/core/ListItemIcon' -import ListItemSecondaryAction from '@material-ui/core/ListItemSecondaryAction' -import ListItemText from '@material-ui/core/ListItemText' +import { makeStyles } from '@mui/styles' +import List from '@mui/material/List' +import ListItem from '@mui/material/ListItem' +import ListItemIcon from '@mui/material/ListItemIcon' +import ListItemSecondaryAction from '@mui/material/ListItemSecondaryAction' +import ListItemText from '@mui/material/ListItemText' import { useTranslation } from 'react-i18next' -import Typography from '@material-ui/core/Typography' -import Switch from '@material-ui/core/Switch' -import Language from '@material-ui/icons/Language' -import NotificationsIcon from '@material-ui/icons/Notifications' +import Typography from '@mui/material/Typography' +import Switch from '@mui/material/Switch' +import Language from '@mui/icons-material/Language' +import NotificationsIcon from '@mui/icons-material/Notifications' -const useStyles = makeStyles((theme) => ({ +const useStyles = makeStyles(theme => ({ root: { padding: theme.spacing(3) } @@ -22,21 +21,27 @@ const useStyles = makeStyles((theme) => ({ const Settings = ({ i18n }) => { const { t } = useTranslation('translations') const classes = useStyles() - const { language, notifications } = useSelector((state) => state.settings) - const dispatch = useDispatch() + // const { language, notifications } = useSelector(state => state.settings) + // const dispatch = useDispatch() + // delete this + const language = '' + const notifications = '' + // end delete this const handleToggle = (value, currentValue) => () => { if (value === 'language') { - if (currentValue === 'en' || 'ko' ) - const lang = 'es' - else if (currentValue === 'es' || 'ko') - const lang = 'en' - + let lang = '' + + // eslint-disable-next-line no-constant-condition + if (currentValue === 'en' || 'ko') lang = 'es' + // eslint-disable-next-line no-constant-condition + else if (currentValue === 'es' || 'ko') lang = 'en' + i18n.changeLanguage(lang) localStorage.setItem('LANGUAGE', lang) - dispatch.settings.setSettings({ key: value, value: lang }) - } else if (value === 'notifications') - dispatch.settings.setSettings({ key: value, value: !currentValue }) + // dispatch.settings.setSettings({ key: value, value: lang }) + } else if (value === 'notifications') console.log('test') + // dispatch.settings.setSettings({ key: value, value: !currentValue }) } return ( diff --git a/webapp/src/routes/settings/styles.js b/webapp/src/routes/Settings/styles.js similarity index 61% rename from webapp/src/routes/settings/styles.js rename to webapp/src/routes/Settings/styles.js index a8f7391c..610a21fc 100644 --- a/webapp/src/routes/settings/styles.js +++ b/webapp/src/routes/Settings/styles.js @@ -1,4 +1,4 @@ -export default (theme) => ({ +export default theme => ({ root: { padding: theme.spacing(3) } diff --git a/webapp/src/routes/termsOfUse/index.js b/webapp/src/routes/TermsOfUse/index.js similarity index 50% rename from webapp/src/routes/termsOfUse/index.js rename to webapp/src/routes/TermsOfUse/index.js index 860bc434..91669341 100644 --- a/webapp/src/routes/termsOfUse/index.js +++ b/webapp/src/routes/TermsOfUse/index.js @@ -1,10 +1,11 @@ import React from 'react' -import Box from '@material-ui/core/Box' -import { makeStyles } from '@material-ui/styles' +import Box from '@mui/material/Box' +import { makeStyles } from '@mui/styles' import { useTranslation } from 'react-i18next' import { RicardianContract } from '@eoscostarica/eoscr-components' -import { contract } from '../../config' -import TitlePage from 'components/title-page' + +import { mainConfig } from '../../config' +import TitlePage from '../../components/PageTitle' import styles from './styles' const useStyles = makeStyles(styles) @@ -15,11 +16,13 @@ const TermsOfUse = () => { return ( - - + + + + ) } diff --git a/webapp/src/routes/TermsOfUse/styles.js b/webapp/src/routes/TermsOfUse/styles.js new file mode 100644 index 00000000..89141f77 --- /dev/null +++ b/webapp/src/routes/TermsOfUse/styles.js @@ -0,0 +1,15 @@ +export default theme => ({ + root: { + padding: theme.spacing(3), + display: 'flex', + justifyContent: 'center', + width: '100%', + '& a': { + lineBreak: 'anywhere' + } + }, + wrapper: { + maxWidth: 1024, + width: '100%' + } +}) diff --git a/webapp/src/routes/about/index.js b/webapp/src/routes/about/index.js index 3353c5ac..95fe3d2f 100644 --- a/webapp/src/routes/about/index.js +++ b/webapp/src/routes/about/index.js @@ -1,12 +1,10 @@ -import React from 'react' -import Typography from '@material-ui/core/Typography' -import { makeStyles } from '@material-ui/styles' +import React, { memo } from 'react' +import Typography from '@mui/material/Typography' +import { makeStyles } from '@mui/styles' import { useTranslation } from 'react-i18next' -import Grid from '@material-ui/core/Grid' -import Box from '@material-ui/core/Box' -import classNames from 'classnames' +import Box from '@mui/material/Box' -import TitlePage from 'components/title-page' +import TitlePage from '../../components/PageTitle' import styles from './styles' @@ -19,16 +17,9 @@ const About = () => { return ( - - - + + + {t('title')} {t('subtitle1')} @@ -40,18 +31,11 @@ const About = () => { {t('body1.paragraph3')} - - + + - - + + {t('subtitle2')} {t('body2.paragraph1')} @@ -62,18 +46,11 @@ const About = () => { {t('body2.paragraph3')} - - + + - - + + {t('subtitle3')} {t('body3.paragraph1')} @@ -126,11 +103,11 @@ const About = () => { src='/EOS-Rate-Infographic.jpg' alt='EOS block producer ratings' /> - - -
+ + + ) } -export default About +export default memo(About) diff --git a/webapp/src/routes/about/styles.js b/webapp/src/routes/about/styles.js index c14f01d5..d04373d9 100644 --- a/webapp/src/routes/about/styles.js +++ b/webapp/src/routes/about/styles.js @@ -1,7 +1,9 @@ -export default (theme) => ({ +export default theme => ({ wrapperContainers: { color: '#433F5B', padding: theme.spacing(6, 2), + maxWidth: 1024, + width: '100%', '& h6': { marginBottom: theme.spacing(1) }, @@ -10,6 +12,8 @@ export default (theme) => ({ } }, firstContainer: { + display: 'flex', + justifyContent: 'center', backgroundColor: theme.palette.surface.main, '& h5': { fontSize: theme.typography.h4.fontSize, @@ -17,12 +21,16 @@ export default (theme) => ({ } }, middleContainer: { + display: 'flex', + justifyContent: 'center', backgroundColor: theme.palette.surface.main, '& img': { width: '100%' } }, lastContainer: { + display: 'flex', + justifyContent: 'center', backgroundColor: '#f5f5f5' } }) diff --git a/webapp/src/routes/account/index.js b/webapp/src/routes/account/index.js deleted file mode 100644 index 733dd478..00000000 --- a/webapp/src/routes/account/index.js +++ /dev/null @@ -1,307 +0,0 @@ -import React, { useEffect, useState } from 'react' -import PropTypes from 'prop-types' -import { useTranslation } from 'react-i18next' -import classNames from 'classnames' -import Button from '@material-ui/core/Button' -import Paper from '@material-ui/core/Paper' -import Grid from '@material-ui/core/Grid' -import Box from '@material-ui/core/Box' -import Typography from '@material-ui/core/Typography' -import { makeStyles } from '@material-ui/styles' -import { useDispatch, useSelector } from 'react-redux' -import Avatar from '@material-ui/core/Avatar' -import MuiAlert from '@material-ui/lab/Alert' -import IconButton from '@material-ui/core/IconButton' -import CloseIcon from '@material-ui/icons/Close' -import Accordion from '@material-ui/core/Accordion' -import AccordionSummary from '@material-ui/core/AccordionSummary' -import AccordionDetails from '@material-ui/core/AccordionDetails' -import ExpandMoreIcon from '@material-ui/icons/ExpandMore' -import Snackbar from '@material-ui/core/Snackbar' -import { useMediaQuery } from '@material-ui/core' -import Link from '@material-ui/core/Link' -import _get from 'lodash.get' - -import TitlePage from 'components/title-page' -import { contract, blockExplorer } from '../../config' -import styles from './styles' -import formatNumber from '../../utils/formatNumber' - -const useStyles = makeStyles(styles) - -const INIT_RATING_STATE_DATA = { - processing: false, - txError: null, - txSuccess: false -} - -const Account = ({ ual }) => { - const { t } = useTranslation('account') - const dispatch = useDispatch() - const classes = useStyles() - const [ratingState, setRatingState] = useState(INIT_RATING_STATE_DATA) - const [showMessage, setShowMessage] = useState(false) - const isDesktop = useMediaQuery('(min-width:769px)') - const { data: user } = useSelector((state) => state.user) - - const onHandleDeleteUserRate = async (bpName) => { - try { - if (!user) { - setShowMessage(true) - - return - } - - const transaction = { - actions: [ - { - account: contract, - name: 'rmrate', - authorization: [ - { - actor: user.account_name, - permission: 'active' - } - ], - data: { user: user.account_name, bp: bpName } - } - ] - } - - await ual.activeUser.signTransaction(transaction, { - broadcast: true - }) - - await dispatch.user.deleteUserRate({ - user: user.account_name, - bpName - }) - - await dispatch.user.getUserChainData({ ual }) - - setRatingState({ - ...ratingState, - txError: null, - processing: true, - txSuccess: true - }) - } catch (error) { - setRatingState({ - ...ratingState, - processing: false, - txError: error.cause ? error.cause.message : error - }) - } - } - - const handleClose = (event, reason) => { - if (reason === 'clickaway') { - return - } - - setShowMessage(false) - setRatingState({ - ...ratingState, - processing: false, - txError: null, - txSuccess: false - }) - } - - function Alert(props) { - return - } - - useEffect(() => { - const getAccountInfo = async () => { - if (ual.activeUser) { - await dispatch.user.getUserChainData({ ual }) - } - } - - getAccountInfo() - }, [ual.activeUser, ual]) - - return ( - - - - - - {t('title')} - - - - {user - ? `${user.account_name}: ${user.core_liquid_balance}` - : 'accountName: 0'} - - - {(user ? user.userRates : []).map((rate) => { - const imageURL = _get( - rate, - 'bpjson.org.branding.logo_256', - null - ) - const BPName = _get(rate, 'bpjson.org.candidate_name', rate.bp) - const date = _get( - rate, - 'tx_data.transaction.transactionDate', - '' - ).substring(0, 10) - - return ( - - } - aria-controls='panel1a-content' - id='panel1a-header' - > - - - {!imageURL ? ( - 'BP' - ) : ( - - )} - - - {date.length > 1 - ? `${t('youRated')} ${BPName} - ${date}` - : `${t('youRated')} ${BPName}`} - - - - - - - - {t('yourRating')} - - - - - {`${t('community')}: ${formatNumber( - rate.ratings.community, - 0 - )}`} - - - - - {`${t('development')}: ${formatNumber( - rate.ratings.development, - 0 - )}`} - - - - - {`${t('infrastructure')}: ${formatNumber( - rate.ratings.infrastructure, - 0 - )}`} - - - - - {`${t('transparency')}: ${formatNumber( - rate.ratings.transparency, - 0 - )}`} - - - - - {`${t('trustiness')}: ${formatNumber( - rate.ratings.trustiness, - 0 - )}`} - {' '} - - - {rate.tx_data && ( - - {rate.tx_data.transaction.transactionId} - - )} - - - - onHandleDeleteUserRate(rate.bp)} - style={{ fontSize: '1.2em', color: '#cd4729' }} - > - - {t('unpublish')} - - - - - - - ) - })} - - - - {t('voteWithoutLogin')} - - - - - {ratingState.txError} - - - - - {t('success')} - - - - - - - - ) -} - -Account.propTypes = { - ual: PropTypes.object -} - -export default Account diff --git a/webapp/src/routes/account/styles.js b/webapp/src/routes/account/styles.js deleted file mode 100644 index 53554e27..00000000 --- a/webapp/src/routes/account/styles.js +++ /dev/null @@ -1,39 +0,0 @@ -export default (theme) => ({ - container: { - padding: theme.spacing(3), - color: '#ffffff' - }, - account: { - padding: theme.spacing(3, 4) - }, - title: { - textAlign: 'center' - }, - box: { - padding: theme.spacing(3, 0) - }, - bold: { - fontWeight: 'bold', - wordBreak: 'break-all' - }, - button: { - marginBottom: theme.spacing(1), - marginTop: theme.spacing(1) - }, - rateList: { - '& hr': { - width: '100%' - } - }, - avatar: { - backgroundColor: theme.palette.surface.main - }, - link: { - overflow: 'hidden', - textOverflow: 'ellipsis', - whiteSpace: 'nowrap', - display: 'block', - width: '100%', - color: '#1a73e8' - } -}) diff --git a/webapp/src/routes/block-producers/block-producer-profile.js b/webapp/src/routes/block-producers/block-producer-profile.js deleted file mode 100644 index e7cb4e14..00000000 --- a/webapp/src/routes/block-producers/block-producer-profile.js +++ /dev/null @@ -1,364 +0,0 @@ -import React, { useState, useEffect, forwardRef, Fragment } from 'react' -import PropTypes from 'prop-types' -import { useDispatch, useSelector } from 'react-redux' -import { useTranslation } from 'react-i18next' -import { Link, useLocation } from '@reach/router' -import Avatar from '@material-ui/core/Avatar' -import Button from '@material-ui/core/Button' -import Grid from '@material-ui/core/Grid' -import Snackbar from '@material-ui/core/Snackbar' -import Typography from '@material-ui/core/Typography' -import { makeStyles } from '@material-ui/core/styles' -import MuiAlert from '@material-ui/lab/Alert' -import KeyboardArrowLeft from '@material-ui/icons/KeyboardArrowLeft' -import AccountCircle from '@material-ui/icons/AccountCircle' -import CloseIcon from '@material-ui/icons/Close' -import _get from 'lodash.get' -import { - Box, - useMediaQuery, - IconButton, - Link as MLink -} from '@material-ui/core' - -import { blockExplorer } from '../../config' -import getBPRadarData from 'utils/getBPRadarData' -import TitlePage from 'components/title-page' -import Radar from 'components/radar' -import Table from 'components/table' -import { - SocialNetworks, - GeneralInformation, - WebsiteLegend, - AdditionalResources -} from './general-information-profile' -import getAverageValue from 'utils/getAverageValue' -import styles from './styles' - -const useStyles = makeStyles(styles) - -const ProfileTitle = ({ - classes, - hasInformation, - producer, - t, - bpTitle, - isContentLoading -}) => { - if (!isContentLoading && !producer) { - return ( - - {t('noBlockProducer')} - - ) - } - - return ( - <> - - {bpTitle} - - {!hasInformation && ( - - {t('noBpJson')} - - )} - - ) -} - -const BlockProducerProfile = ({ account, ual, ...props }) => { - const { t } = useTranslation('profile') - const classes = useStyles() - const dispatch = useDispatch() - const isDesktop = useMediaQuery('(min-width:767px)') - const isMobile = useMediaQuery('(max-width:768px)') - const accountName = _get(ual, 'activeUser.accountName', null) - const location = useLocation() - const [sizes, setSizes] = useState() - const [isNewRate, setIsNewRate] = useState(true) - const [open, setOpen] = useState(false) - const { - list: blockProducers, - producer, - edenRate, - userRate - } = useSelector((state) => state.blockProducers) - const { isContentLoading } = useSelector((state) => state.isLoading) - const bpHasInformation = Boolean( - producer && Object.values(producer.bpjson).length - ) - const bPLogo = - bpHasInformation && _get(producer, 'bpjson.org.branding.logo_256', null) - - const BlockProducerTitle = _get( - producer, - 'bpjson.org.candidate_name', - _get(producer, 'system.owner', 'No Data') - ) - - const webInfo = _get(producer, 'general_info', null) - - const getRatingData = () => { - if (edenRate) { - return { - community: edenRate.community, - development: edenRate.development, - infrastructure: edenRate.development, - transparency: edenRate.transparency, - trustiness: edenRate.trustiness - } - } - return { - community: 0, - development: 0, - infrastructure: 0, - transparency: 0, - trustiness: 0 - } - } - - const userDataSet = getBPRadarData({ - name: t('edenRates'), - parameters: getRatingData() - }) - - const handleClose = (event, reason) => { - if (reason === 'clickaway') { - return - } - setOpen(false) - } - - function Alert(props) { - return - } - - useEffect(() => { - setSizes(isDesktop ? 400 : '100%') - }, [isDesktop]) - - useEffect(() => { - const getData = async () => { - !blockProducers.length && (await dispatch.blockProducers.getBPs()) - dispatch.blockProducers.getBlockProducerByOwner(account) - dispatch.blockProducers.getBlockProducerEdenRating({ - bp: account - }) - dispatch.blockProducers.getBlockProducerRatingByOwner({ - bp: account, - userAccount: accountName - }) - } - - getData() - }, [account, blockProducers.length]) - - useEffect(() => { - dispatch.blockProducers.setShowSortSelected(false) - }, []) - - useEffect(() => { - if (userRate) setIsNewRate(false) - else setIsNewRate(true) - }, [userRate]) - - useEffect(() => { - if (location.state.transactionId) setOpen(true) - else setOpen(false) - }, []) - - return ( - - - - - - - - - - - {bPLogo ? ( - - - - ) : ( - - )} - - - - {!isMobile && ( - - - - - - - - - )} - - - - - - - - -
- - - {isMobile && ( - - - - - )} - {isMobile && ( - - - - - )} - - - - - - - - - - } - /> - - ) -} - -BlockProducerProfile.propTypes = { - account: PropTypes.string, - ual: PropTypes.object -} - -ProfileTitle.propTypes = { - classes: PropTypes.object, - hasInformation: PropTypes.bool, - producer: PropTypes.object, - t: PropTypes.any, - bpTitle: PropTypes.string, - isContentLoading: PropTypes.bool -} - -export default BlockProducerProfile diff --git a/webapp/src/routes/block-producers/bottom-sheet-selected-bps.js b/webapp/src/routes/block-producers/bottom-sheet-selected-bps.js deleted file mode 100644 index 10ca0fd5..00000000 --- a/webapp/src/routes/block-producers/bottom-sheet-selected-bps.js +++ /dev/null @@ -1,42 +0,0 @@ -import React from 'react' -import PropTypes from 'prop-types' -import Drawer from '@material-ui/core/Drawer' -import Grid from '@material-ui/core/Grid' -import IconButton from '@material-ui/core/IconButton' -import { makeStyles } from '@material-ui/core/styles' -import CloseIcon from '@material-ui/icons/Close' - -import styles from './styles' - -const useStyles = makeStyles(styles) - -const SelectedBpsBottomSheet = ({ open, setOpen, children }) => { - const classesStyle = useStyles() - - return ( - - - - - setOpen(false)}> - - - - - {children} - - ) -} - -SelectedBpsBottomSheet.propTypes = { - open: PropTypes.bool, - setOpen: PropTypes.func, - children: PropTypes.node -} - -export default SelectedBpsBottomSheet diff --git a/webapp/src/routes/block-producers/compare-tool-toggle.js b/webapp/src/routes/block-producers/compare-tool-toggle.js deleted file mode 100644 index 1974ed5c..00000000 --- a/webapp/src/routes/block-producers/compare-tool-toggle.js +++ /dev/null @@ -1,44 +0,0 @@ -import React from 'react' -import { makeStyles } from '@material-ui/core/styles' -import { useDispatch, useSelector } from 'react-redux' -import { useTranslation } from 'react-i18next' -import List from '@material-ui/core/List' -import ListItem from '@material-ui/core/ListItem' -import ListItemText from '@material-ui/core/ListItemText' -import ListItemSecondaryAction from '@material-ui/core/ListItemSecondaryAction' -import VisibilityIcon from '@material-ui/icons/Visibility' -import VisibilityOffIcon from '@material-ui/icons/VisibilityOff' - -import styles from './styles' - -const useStyles = makeStyles(styles) - -const CompareToolToggle = () => { - const { t } = useTranslation('translations') - const classes = useStyles() - const { compareTool, selected } = useSelector((state) => state.blockProducers) - const dispatch = useDispatch() - - const handleToggleCompareTool = () => { - dispatch.blockProducers.toggleCompareTool() - } - - return ( - - handleToggleCompareTool()} - > - - - {compareTool ? : } - - - - ) -} - -export default CompareToolToggle diff --git a/webapp/src/routes/block-producers/index.js b/webapp/src/routes/block-producers/index.js deleted file mode 100644 index ada12bfc..00000000 --- a/webapp/src/routes/block-producers/index.js +++ /dev/null @@ -1,300 +0,0 @@ -import React, { useEffect, useState, useRef } from 'react' -import PropTypes from 'prop-types' -import { useDispatch, useSelector } from 'react-redux' -import Grid from '@material-ui/core/Grid' -import Button from '@material-ui/core/Button' -import Typography from '@material-ui/core/Typography' -import ThumbUpAltIcon from '@material-ui/icons/ThumbUpAlt' -import { makeStyles } from '@material-ui/core/styles' -import { useTranslation } from 'react-i18next' -import classNames from 'classnames' -import _get from 'lodash.get' - -import TitlePage from 'components/title-page' -import CompareTool from 'components/compare-tool' -import getAverageValue from 'utils/getAverageValue' -import { useMediaQuery } from '@material-ui/core' -import applySortBy from 'utils/sortedBy' -import Card from 'components/card' - -import styles from './styles' -import SelectedBpsBottomSheet from './bottom-sheet-selected-bps' - -const useStyles = makeStyles(styles) - -const AllBps = ({ ual }) => { - const { t } = useTranslation('translations') - const dispatch = useDispatch() - const classes = useStyles() - const myRef = useRef(null) - const [currentlyVisible, setCurrentlyVisible] = useState(30) - const [openVoteDrawer, setOpenVoteDrawer] = useState(false) - const { data: user } = useSelector((state) => state.user) - const isDesktop = useMediaQuery('(min-width:600px)', { - defaultMatches: false - }) - const isTablet = useMediaQuery('(max-width:1024px)', { - defaultMatches: false - }) - const [openDesktopVotingTool, setOpenDesktopVotingTool] = useState(isDesktop) - const { - list: blockProducers, - selected: selectedBPs, - compareTool: compareToolVisible, - sortBy - } = useSelector((state) => state.blockProducers) - - const [ratingState, setRatingState] = useState({ - txError: null, - txSuccess: false, - showChipMessage: false - }) - const sortedBPs = applySortBy(sortBy, blockProducers) - const shownList = sortedBPs && sortedBPs.slice(0, currentlyVisible) - const hasMore = blockProducers && currentlyVisible < blockProducers.length - const accountName = _get(ual, 'activeUser.accountName', null) - - const loadMore = () => setCurrentlyVisible(currentlyVisible + 12) - const goToTop = () => document.getElementById('mainContent').scrollTo(0, 0) - - const handleToggleCompareTool = () => { - dispatch.blockProducers.toggleCompareTool() - } - - const handleToggleSelected = (item, isAddItem = false) => { - if (isAddItem) { - dispatch.blockProducers.addToSelected(item) - } else { - dispatch.blockProducers.removeSelected(item) - } - } - - const handleOpenDesktopVotingTool = (value) => { - goToTop() - setOpenDesktopVotingTool(value) - } - - const handleOnClear = () => { - handleToggleCompareTool() - dispatch.blockProducers.clearSelected() - setOpenDesktopVotingTool(false) - } - - const handleOnClose = () => { - setOpenDesktopVotingTool(false) - } - - const handleSetRatingState = () => { - setRatingState({ - ...ratingState, - txError: null, - txSuccess: false, - showChipMessage: false - }) - } - - const handleSetIsNewRate = (owner) => { - if (user) { - for (const userRate of user.userRates) { - if (userRate.owner === owner) { - return true - } - } - return false - } - } - - const sendVoteBps = async (BPs) => { - if (!accountName) return - - const transaction = { - actions: [ - { - account: 'eosio', - name: 'voteproducer', - authorization: [ - { - actor: accountName, - permission: 'active' - } - ], - data: { - voter: accountName, - proxy: '', - producers: BPs.sort() - } - } - ] - } - - try { - dispatch.isLoading.storeIsContentLoading(true) - - await ual.activeUser.signTransaction(transaction, { - broadcast: true - }) - - setRatingState({ - ...ratingState, - txSuccess: true, - showChipMessage: true - }) - - dispatch.isLoading.storeIsContentLoading(false) - - setTimeout(() => { - setRatingState({ - ...ratingState, - txError: null, - txSuccess: false, - showChipMessage: false - }) - }, 2000) - } catch (error) { - console.warn(error) - - setRatingState({ - ...ratingState, - txError: error && error.cause ? error.cause.message : error, - showChipMessage: true - }) - dispatch.isLoading.storeIsContentLoading(false) - } - } - - const cmprTool = () => ( - sendVoteBps(selectedBPs || [])} - userInfo={user} - message={ratingState} - setMessage={handleSetRatingState} - handleOnClose={handleOnClose} - handleOnClear={handleOnClear} - /> - ) - - useEffect(() => { - const getData = async () => { - !blockProducers.length && (await dispatch.blockProducers.getBPs()) - } - - getData() - }, [blockProducers.length]) - - useEffect(() => { - const getUserData = async () => { - if (ual.activeUser && !user) { - await dispatch.user.getUserChainData({ ual }) - } - } - - dispatch.blockProducers.setShowSortSelected(true) - getUserData() - }, [user, ual.activeUser, ual]) - - return ( -
- - {isDesktop && openDesktopVotingTool && cmprTool()} - - {(shownList || []).map((blockProducer) => ( - - () => { - if (isAdding) { - if (!(selectedBPs || []).length && !compareToolVisible) { - handleToggleCompareTool() - } - - handleToggleSelected(producerAccountName, isAdding) - } else { - if ((selectedBPs || []).length === 1 && compareToolVisible) { - handleToggleCompareTool() - } - - handleToggleSelected(producerAccountName, isAdding) - } - }} - data={blockProducer} - imageURL={_get(blockProducer, 'bpjson.org.branding.logo_256')} - owner={_get(blockProducer, 'owner')} - title={_get(blockProducer, 'bpjson.org.candidate_name')} - pathLink='block-producers' - buttonLabel={t('addToVote')} - average={getAverageValue(_get(blockProducer, 'average', 0))} - rate={_get(blockProducer, 'ratings_cntr', 0)} - isNewRate={handleSetIsNewRate(blockProducer.owner)} - /> - - ))} - - {selectedBPs && selectedBPs.length > 0 && ( - - - - - - )} - - {cmprTool()} - - -
- ) -} - -AllBps.propTypes = { - ual: PropTypes.object -} - -export default AllBps - -export const blockProducersDrawer = [ - { value: 'alphabetical' }, - { value: 'generalRate' }, - { value: 'edenRate' }, - { value: 'infrastructure' }, - { value: 'community' }, - { value: 'trustiness' }, - { value: 'development' }, - { value: 'transparency' }, - { value: 'vote' }, - { value: 'ratings' } -] diff --git a/webapp/src/routes/help/index.js b/webapp/src/routes/help/index.js index 3516becf..b8544f80 100644 --- a/webapp/src/routes/help/index.js +++ b/webapp/src/routes/help/index.js @@ -1,16 +1,15 @@ import React from 'react' -import Typography from '@material-ui/core/Typography' -import { makeStyles } from '@material-ui/styles' +import Typography from '@mui/material/Typography' +import { makeStyles } from '@mui/styles' import { useTranslation } from 'react-i18next' -import Grid from '@material-ui/core/Grid' -import Box from '@material-ui/core/Box' -import classNames from 'classnames' -import Link from '@material-ui/core/Link' -import HttpIcon from '@material-ui/icons/Http' -import TelegramIcon from '@material-ui/icons/Telegram' -import GitHubIcon from '@material-ui/icons/GitHub' +import Grid from '@mui/material/Grid' +import Box from '@mui/material/Box' +import Link from '@mui/material/Link' +import HttpIcon from '@mui/icons-material/Http' +import TelegramIcon from '@mui/icons-material/Telegram' +import GitHubIcon from '@mui/icons-material/GitHub' -import TitlePage from 'components/title-page' +import TitlePage from '../../components/PageTitle' import styles from './styles' @@ -23,54 +22,45 @@ const Help = () => { return ( - - - - {t('title')} - - {t('paragraph')} - + + + {t('title')} + + {t('paragraph')} + - - - - {t('githubEOSCR')} - - - - - - {t('telegramChannel')} - - - - - - {t('websiteEOSCR')} - - - + + + + {t('githubEOSCR')} + + + + + + {t('telegramChannel')} + + + + + + {t('websiteEOSCR')} + + - + ) } diff --git a/webapp/src/routes/help/styles.js b/webapp/src/routes/help/styles.js index 7cd96895..a46fbde5 100644 --- a/webapp/src/routes/help/styles.js +++ b/webapp/src/routes/help/styles.js @@ -1,15 +1,18 @@ -export default (theme) => ({ +export default theme => ({ wrapperContainers: { color: '#433F5B', + display: 'flex', + justifyContent: 'center', + width: '100%', padding: theme.spacing(6, 2), '& h6': { marginBottom: theme.spacing(1) - }, - [theme.breakpoints.up('sm')]: { - padding: theme.spacing(6, 4) } }, firstContainer: { + maxWidth: 1024, + width: '100%', + '& h5': { fontSize: theme.typography.h4.fontSize, marginBottom: 12.5 diff --git a/webapp/src/routes/home/cover.js b/webapp/src/routes/home/cover.js index 22a8f27f..4d51eb51 100644 --- a/webapp/src/routes/home/cover.js +++ b/webapp/src/routes/home/cover.js @@ -1,131 +1,101 @@ -import React, { forwardRef, useState, useEffect } from 'react' +import React, { forwardRef, memo } from 'react' import { useTranslation } from 'react-i18next' -import Typography from '@material-ui/core/Typography' -import Button from '@material-ui/core/Button' -import { useMediaQuery } from '@material-ui/core' -import Grid from '@material-ui/core/Grid' -import { makeStyles } from '@material-ui/core/styles' -import { Link } from '@reach/router' -import PropTypes from 'prop-types' +import Typography from '@mui/material/Typography' +import Button from '@mui/material/Button' +// import useMediaQuery from '@mui/material/useMediaQuery' +import Box from '@mui/material/Box' +import { makeStyles } from '@mui/styles' +import { Link } from 'react-router-dom' -import Radar from 'components/radar' +// import Radar from '../../components/Radar' +import PolarChart from '../../components/PolarChart' import styles from './styles' -// eslint-disable-next-line react/display-name -const bpLink = forwardRef((props, ref) => ) +const refBPLink = (props, ref) => +const bpLink = forwardRef(refBPLink) + const useStyles = makeStyles(styles) -const HomeCover = ({ blockProducer }) => { +const HomeCover = () => { const { t } = useTranslation('home') const classes = useStyles() - const isDesktop = useMediaQuery('(min-width:769px)') - const isTablet = useMediaQuery('(min-width:540px)') - const isBigTablet = useMediaQuery('(max-width:1023px)') - const [sizes, setSizes] = useState() + // const isDesktop = useMediaQuery('(min-width:769px)') + // const [sizes, setSizes] = useState() - useEffect(() => { - setSizes(isDesktop ? 400 : '95%') - }, [isDesktop]) + // useEffect(() => { + // // setSizes(isDesktop ? 400 : '95%') + // }, [isDesktop]) return ( - - - - {t('cover.title')} - - - {!isDesktop && ( - - - - - - - - - )} - - - {t('cover.paragraph.subtitle1')} - - - {t('cover.paragraph.text1')} - - - {t('cover.paragraph.text2')} - - - {t('cover.paragraph.subtitle2')} - - - {t('cover.paragraph.text3')} - - - {t('cover.paragraph.text4')} - - {isDesktop && ( -
+ + + {t('cover.title')} + + + + + + + + + + + + + {t('cover.paragraph.subtitle1')} + + + {t('cover.paragraph.text1')} + + + {t('cover.paragraph.text2')} + + + {t('cover.paragraph.subtitle2')} + + + {t('cover.paragraph.text3')} + + + {t('cover.paragraph.text4')} + + -
- )} -
- {isDesktop && ( - -
- -
-
- )} -
+ + + + + + + ) } -HomeCover.propTypes = { - blockProducer: PropTypes.object.isRequired -} - -export default HomeCover +export default memo(HomeCover) diff --git a/webapp/src/routes/home/index.js b/webapp/src/routes/home/index.js index f787218a..70d51c74 100644 --- a/webapp/src/routes/home/index.js +++ b/webapp/src/routes/home/index.js @@ -1,81 +1,50 @@ -import React, { useEffect } from 'react' -import { makeStyles } from '@material-ui/core/styles' +import React from 'react' +import { makeStyles } from '@mui/styles' import { useTranslation } from 'react-i18next' -import { useDispatch, useSelector } from 'react-redux' -import Grid from '@material-ui/core/Grid' +import Box from '@mui/material/Box' import classNames from 'classnames' -import TitlePage from 'components/title-page' +import TitlePage from '../../components/PageTitle' import styles from './styles' -import Cover from './cover' -import SubTopic from './subTopic' -import RateCategory from './rateCategory' +import Cover from './Cover' +import SubTopic from './SubTopic' +import RateCategory from './RateCategory' const useStyles = makeStyles(styles) const Home = () => { const { t } = useTranslation('home') const classes = useStyles() - const dispatch = useDispatch() - const { blockProducer } = useSelector((state) => state.home) - - useEffect(() => { - dispatch.home.getBlockData() - }, []) - - useEffect(() => { - dispatch.blockProducers.setShowSortSelected(false) - }) return ( - <> + - - - {blockProducer && ( - - - - )} - - - - {blockProducer && ( - - - - )} - - - - - - - - - + + + + + + + + + + ) } diff --git a/webapp/src/routes/home/rateCategory.js b/webapp/src/routes/home/rateCategory.js index e28fd62a..6ef9f064 100644 --- a/webapp/src/routes/home/rateCategory.js +++ b/webapp/src/routes/home/rateCategory.js @@ -1,14 +1,14 @@ -import React from 'react' +import React, { memo } from 'react' import { useTranslation } from 'react-i18next' -import Typography from '@material-ui/core/Typography' -import { makeStyles } from '@material-ui/core/styles' -import Grid from '@material-ui/core/Grid' +import Typography from '@mui/material/Typography' +import { makeStyles } from '@mui/styles' +import Box from '@mui/material/Box' -import CommunityIcon from 'components/icon/communityIcon' -import TransparencyIcon from 'components/icon/transparencyIcon' -import TrustinessIcon from 'components/icon/trustinessIcon' -import InfrastructureIcon from 'components/icon/infrastructureIcon' -import DevelopmentIcon from 'components/icon/developmentIcon' +import CommunityIcon from '../../components/icon/communityIcon' +import TransparencyIcon from '../../components/icon/transparencyIcon' +import TrustinessIcon from '../../components/icon/trustinessIcon' +import InfrastructureIcon from '../../components/icon/infrastructureIcon' +import DevelopmentIcon from '../../components/icon/developmentIcon' import styles from './styles' @@ -19,19 +19,17 @@ const RatingCategory = () => { const classes = useStyles() return ( - - - - {t('ratingCategory.title')} - - - -
+ + + {t('ratingCategory.title')} + + + {t('ratingCategory.transparency.title')} -
+ { > {t('ratingCategory.transparency.description')} -
- -
+ + + {t('ratingCategory.infrastructure.title')} -
+ { > {t('ratingCategory.infrastructure.description')} -
- -
+ + + {t('ratingCategory.trustiness.title')} -
+ { > {t('ratingCategory.trustiness.description')} -
- -
+ + + {t('ratingCategory.community.title')} -
+ { > {t('ratingCategory.community.description')} -
- -
+ + + {t('ratingCategory.development.title')} -
+ { > {t('ratingCategory.development.description')} -
-
+ + ) } -export default RatingCategory +export default memo(RatingCategory) diff --git a/webapp/src/routes/home/styles.js b/webapp/src/routes/home/styles.js index e1325eb5..9c7097d3 100644 --- a/webapp/src/routes/home/styles.js +++ b/webapp/src/routes/home/styles.js @@ -1,4 +1,4 @@ -export default (theme) => ({ +export default theme => ({ spacingContainers: { padding: theme.spacing(8, 2), [theme.breakpoints.down('sm')]: { @@ -6,13 +6,19 @@ export default (theme) => ({ } }, mainCoverContainer: { - backgroundColor: theme.palette.surface.main + backgroundColor: theme.palette.surface.main, + display: 'flex', + justifyContent: 'center' }, mainSubTopicContainer: { - backgroundColor: theme.palette.surface.main + backgroundColor: theme.palette.surface.main, + display: 'flex', + justifyContent: 'center' }, rateCategoryContainer: { - backgroundColor: '#f5f5f5' + backgroundColor: '#f5f5f5', + display: 'flex', + justifyContent: 'center' }, coverContainer: { padding: 0, @@ -20,40 +26,118 @@ export default (theme) => ({ maxWidth: '1024px', backgroundColor: theme.palette.surface.main }, - coverTitle: { - marginBottom: 12.5, + mainTitle: { + marginBottom: '12.5px !important', + fontWeight: 'normal', + fontStretch: 'normal', + fontStyle: 'normal', + lineHeight: '1.17', + letterSpacing: 'normal', + textAlign: 'left', + color: theme.palette.primary.dark, [theme.breakpoints.down('sm')]: { - fontSize: '2.03rem', + fontSize: '2.03rem !important', marginBottom: 0 } }, + btnWrapper: { + display: 'flex', + justifyContent: 'center' + }, + btnMobile: { + width: '100%', + [theme.breakpoints.up('sm')]: { + width: 336 + } + }, ctaContainer: { - textAlign: 'center' + textAlign: 'center', + display: 'none', + [theme.breakpoints.up('md')]: { + display: 'flex', + justifyContent: 'center' + } }, chartContainer: { - maxWidth: '400px', width: '100%', - display: 'flex', - alignItems: 'center' + display: 'none', + alignItems: 'center', + [theme.breakpoints.up('md')]: { + display: 'flex', + width: '45%', + '& .highcharts-container ': { + height: '400px !important', + width: '400px !important', + '& > svg': { + height: '400px !important', + width: '400px !important' + } + } + } + }, + chartContainerMobile: { + '& .highcharts-container ': { + height: '400px !important', + width: '350px !important', + '& > svg': { + height: '400px !important', + width: '350px !important' + }, + [theme.breakpoints.up('sm')]: { + height: '400px !important', + width: '600px !important', + '& > svg': { + height: '400px !important', + width: '600px !important' + } + } + } }, subtitle: { - marginBottom: theme.spacing(1) + marginBottom: `${theme.spacing(1)} !important`, + fontWeight: '500', + fontStretch: 'normal', + fontStyle: 'normal', + lineHeight: '23px !important', + letterSpacing: '0.15px !important', + textAlign: 'left', + color: theme.palette.primary.dark, + fontSize: 20 }, leftCoverBox: { display: 'flex', flexDirection: 'column', - justifyContent: 'space-between' + justifyContent: 'space-between', + '& .MuiTypography-body2': { + lineHeight: '28px', + letterSpacing: '0.44px', + fontSize: 16, + color: theme.palette.common.black + }, + [theme.breakpoints.up('md')]: { + width: '55%' + } }, ratingContainer: { maxWidth: '1024px' }, ratingTitle: { - fontSize: theme.typography.h4.fontSize, + fontWeight: '500', + fontStretch: 'normal', + fontStyle: 'normal', + lineHeight: '23px !important', + letterSpacing: '0.15px !important', + textAlign: 'left', + color: theme.palette.primary.dark, + fontSize: 20, display: 'flex', marginBottom: 12.5 }, paragraph: { - marginLeft: theme.spacing(4.5) + marginLeft: `${theme.spacing(4.5)} !important`, + lineHeight: '28px !important', + letterSpacing: '0.44px !important', + color: theme.palette.common.black }, subTitleContainer: { display: 'flex', @@ -66,26 +150,44 @@ export default (theme) => ({ color: '#433F5B' }, subTopicContainer: { - maxWidth: '1024px' - }, - title: { - fontSize: theme.typography.h4.fontSize, - color: theme.palette.grey[600], - marginBottom: 12.5 + maxWidth: '1024px', + display: 'flex', + flexDirection: 'column', + [theme.breakpoints.up('md')]: { + flexDirection: 'row', + justifyContent: 'space-between' + } }, ratingParagraph: { color: theme.palette.grey[600] }, - topicSubtitle: { - marginBottom: theme.spacing(1), - color: theme.palette.grey[600] - }, gridContent: { - padding: '2%' + padding: '2%', + width: '100%', + [theme.breakpoints.up('md')]: { + width: '50%' + } + }, + videoBox: { + width: '100%', + [theme.breakpoints.up('md')]: { + width: '50%' + } }, link: { color: theme.palette.grey[600], fontWeight: '500', textDecoration: 'none' + }, + mobileView: { + display: 'flex', + flexDirection: 'column', + margin: '-10px 0 25px 0', + [theme.breakpoints.up('md')]: { + display: 'none' + } + }, + desktopView: { + display: 'flex' } }) diff --git a/webapp/src/routes/home/subTopic.js b/webapp/src/routes/home/subTopic.js index ee3b61d1..fd224d5b 100644 --- a/webapp/src/routes/home/subTopic.js +++ b/webapp/src/routes/home/subTopic.js @@ -1,10 +1,10 @@ -import React from 'react' +import React, { memo } from 'react' import { useTranslation } from 'react-i18next' -import Typography from '@material-ui/core/Typography' -import { makeStyles } from '@material-ui/core/styles' -import Grid from '@material-ui/core/Grid' +import Typography from '@mui/material/Typography' +import { makeStyles } from '@mui/styles' +import Box from '@mui/material/Box' -import Video from 'components/video' +import Video from '../../components/Video' import styles from './styles' @@ -15,9 +15,9 @@ const SubTopic = () => { const classes = useStyles() return ( - - - + + + {t('subTopic.title')} @@ -38,7 +38,7 @@ const SubTopic = () => { > {t('subTopic.paragraph2')} - + {t('subTopic.subtitle')} @@ -58,12 +58,12 @@ const SubTopic = () => { {t('subTopic.telegramGroup')}. - - + + - + + ) } -export default SubTopic +export default memo(SubTopic) diff --git a/webapp/src/routes/index.js b/webapp/src/routes/index.js index c33dc5b8..48de689f 100644 --- a/webapp/src/routes/index.js +++ b/webapp/src/routes/index.js @@ -1,82 +1,132 @@ -import Home from './home' -import Account from './account' -import BlockProducerProfile from './block-producers/block-producer-profile' -import BlockProducerRate from './block-producers/block-producer-rate' -import AllBps, { blockProducersDrawer } from './block-producers' -import AllProxies, { proxiesDrawer } from './proxies' -import ProxyProfile from './proxies/proxy-profile' -import Help from './help' -import TermsOfUse from './termsOfUse' -import About from './about' -import { networkMonitor } from '../config' +// eslint-disable-next-line no-unused-vars +import React, { lazy } from 'react' +import { + Activity as ActivityIcon, + Grid as GridIcon, + Home as HomeIcon, + Server as ServerIcon, + FileText as FileTextIcon, + User as UserIcon, + Info as InfoIcon, + HelpCircle as HelpIcon, + GitMerge as GitMergeIcon +} from 'react-feather' -export default [ +import { mainConfig } from '../config' + +const filters = [ + { value: 'alphabetical' }, + { value: 'generalRate' }, + { value: 'edenRate' }, + { value: 'infrastructure' }, + { value: 'community' }, + { value: 'trustiness' }, + { value: 'development' }, + { value: 'transparency' }, + { value: 'vote' }, + { value: 'ratings' } +] +const Home = lazy(() => import('./Home')) +const BlockProducers = lazy(() => import('./BlockProducers')) +const BlockProducerProfile = lazy(() => + import('./BlockProducers/BlockProducerProfile') +) +const BlockProducerRate = lazy(() => + import('./BlockProducers/BlockProducerRate') +) +const Proxies = lazy(() => import('./Proxies')) +const ProxyProfile = lazy(() => import('./Proxies/ProxyProfile')) +const About = lazy(() => import('./About')) +const Help = lazy(() => import('./Help')) +const Page404 = lazy(() => import('./Route404')) +const TermsOfUse = lazy(() => import('./TermsOfUse')) +const Account = lazy(() => import('./Account')) + +const routes = [ { + name: 'home', + icon: , + component: Home, path: '/', - Component: Home, - drawerLabel: 'drawerLinkHome', - target: '_self' + exact: true }, { - path: '/block-producers', - Component: AllBps, - drawerLabel: 'drawerLinkAllBPs', - drawerComponents: blockProducersDrawer, - target: '_self' + name: 'myAccount', + icon: , + path: '/account', + component: Account, + exact: true }, { - path: 'block-producers/:account', - Component: BlockProducerProfile, - target: '_self' + name: 'blockProducers', + icon: , + component: BlockProducers, + path: '/block-producers', + childrens: filters, + exact: true }, { - path: 'block-producers/:account/rate', - Component: BlockProducerRate, - target: '_self' + path: '/block-producers/:account', + component: BlockProducerProfile, + exact: true }, { - path: '/proxies', - Component: AllProxies, - drawerLabel: 'drawerLinkAllProxies', - drawerComponents: proxiesDrawer, - target: '_self' + path: '/block-producers/:account/rate', + component: BlockProducerRate, + exact: true }, { - path: 'proxies/:account', - Component: ProxyProfile, - target: '_self' + path: '/proxies', + icon: , + component: Proxies, + name: 'proxies', + exact: true }, { - path: '/account', - Component: Account, - target: '_self' + path: '/proxies/:account', + component: ProxyProfile, + exact: true }, { - path: networkMonitor, - drawerLabel: 'drawerLinkNetworkMonitor', + path: mainConfig.networkMonitor, + icon: , + name: 'networkMonitor', target: '_blank' }, { + name: 'about', + icon: , + component: About, path: '/about', - Component: About, - drawerLabel: 'drawerLinkAbout', - target: '_self' + exact: true }, { path: '/ricardian-contract', - Component: TermsOfUse, - drawerLabel: 'drawerLinkRicardianContract', - target: '_self' + component: TermsOfUse, + icon: , + name: 'ricardianContract', + exact: true }, { + name: 'help', + icon: , + component: Help, path: '/help', - Component: Help, - drawerLabel: 'drawerLinkHelp', - target: '_self' + exact: true }, { - path: 'https://github.com/eoscostarica/eos-rate/releases', - drawerLabel: 'version', + name: 'version', + badge: mainConfig.appVersion, + path: 'https://github.com/eoscostarica/full-stack-boilerplate/tags', + icon: , target: '_blank' + }, + { + component: Page404 } ] + +export default () => ({ + sidebar: routes.filter(route => !!route.name), + browser: routes.filter(route => !!route.component) +}) diff --git a/webapp/src/routes/not-found/index.js b/webapp/src/routes/not-found/index.js deleted file mode 100644 index 96135dbe..00000000 --- a/webapp/src/routes/not-found/index.js +++ /dev/null @@ -1,42 +0,0 @@ -import React, { forwardRef } from 'react' -import { useTranslation } from 'react-i18next' -import { makeStyles } from '@material-ui/core/styles' -import Typography from '@material-ui/core/Typography' -import Button from '@material-ui/core/Button' -import { Link } from '@reach/router' - -import styles from './styles' - -const useStyles = makeStyles(styles) - -const NotFound = () => { - const { t } = useTranslation('not-found') - const classes = useStyles() - - return ( -
-
-
- 404 - {t('graphic')} -
- - {t('description')} - - -
-
- ) -} - -export default NotFound diff --git a/webapp/src/routes/not-found/styles.js b/webapp/src/routes/not-found/styles.js deleted file mode 100644 index 48b37ef0..00000000 --- a/webapp/src/routes/not-found/styles.js +++ /dev/null @@ -1,43 +0,0 @@ -export default (theme) => ({ - root: { - width: '100%', - height: 'calc(100vh - 128px)', - display: 'flex', - alignItems: 'center', - flexDirection: 'column', - justifyContent: 'space-around' - }, - container: { - margin: theme.spacing(2), - height: '100%', - width: '50%', - background: theme.palette.primary.sectionBackground, - display: 'flex', - alignItems: 'center', - flexDirection: 'column', - '& > *': { - marginTop: theme.spacing(4) - } - }, - graphic: { - borderRadius: '50%', - background: theme.palette.primary.dark, - color: 'white', - display: 'flex', - flexDirection: 'column', - justifyContent: 'center', - alignItems: 'center', - width: '200px', - height: '200px', - '& > span': { - fontWeight: '600', - lineHeight: 1 - }, - '& > span:first-child': { - fontSize: '4rem' - }, - '& > span:nth-child(2)': { - fontSize: '1.8rem' - } - } -}) diff --git a/webapp/src/routes/proxies/compare-tool-toggle.js b/webapp/src/routes/proxies/compare-tool-toggle.js deleted file mode 100644 index a6477efb..00000000 --- a/webapp/src/routes/proxies/compare-tool-toggle.js +++ /dev/null @@ -1,42 +0,0 @@ -import React from 'react' -import { makeStyles } from '@material-ui/core/styles' -import { useDispatch, useSelector } from 'react-redux' -import { useTranslation } from 'react-i18next' -import List from '@material-ui/core/List' -import ListItem from '@material-ui/core/ListItem' -import ListItemText from '@material-ui/core/ListItemText' -import ListItemSecondaryAction from '@material-ui/core/ListItemSecondaryAction' -import VisibilityIcon from '@material-ui/icons/Visibility' -import VisibilityOffIcon from '@material-ui/icons/VisibilityOff' - -import styles from './styles' - -const useStyles = makeStyles(styles) - -const CompareToolToggle = () => { - const { t } = useTranslation('translations') - const classes = useStyles() - const dispatch = useDispatch() - const { compareTool, selected } = useSelector((state) => state.blockProducers) - - const handleToggleCompareTool = () => { - dispatch.blockProducers.toggleCompareTool() - } - - return ( - - handleToggleCompareTool()} - > - - - {compareTool ? : } - - - - ) -} - -export default CompareToolToggle diff --git a/webapp/src/routes/proxies/index.js b/webapp/src/routes/proxies/index.js deleted file mode 100644 index b8c51ae0..00000000 --- a/webapp/src/routes/proxies/index.js +++ /dev/null @@ -1,245 +0,0 @@ -import React, { useEffect, useState } from 'react' -import PropTypes from 'prop-types' -import { useDispatch, useSelector } from 'react-redux' -import Grid from '@material-ui/core/Grid' -import Button from '@material-ui/core/Button' -import { useMediaQuery } from '@material-ui/core' -import { makeStyles } from '@material-ui/core/styles' -import { useTranslation } from 'react-i18next' -import classNames from 'classnames' -import _get from 'lodash.get' - -import TitlePage from 'components/title-page' -import Card from 'components/card' -import CompareTool from 'components/compare-tool' - -import styles from './styles' -import SelectedBpsBottomSheet from './../block-producers/bottom-sheet-selected-bps' - -const useStyles = makeStyles(styles) - -const AllProxies = ({ ual }) => { - const { t } = useTranslation('translations') - const classes = useStyles() - const dispatch = useDispatch() - const { data: user } = useSelector((state) => state.user) - const { - compareTool: compareToolVisible, - selected: selectedProxies, - filtered, - proxies - } = useSelector((state) => state.proxies) - const [currentlyVisible, setCurrentlyVisible] = useState(30) - const proxiesList = filtered && filtered.length ? filtered : proxies - const shownList = proxiesList && proxiesList.slice(0, currentlyVisible) - const hasMore = proxiesList && currentlyVisible < proxiesList.length - const isDesktop = useMediaQuery('(min-width:600px)') - const isTablet = useMediaQuery('(max-width:1024px)', { - defaultMatches: false - }) - const accountName = _get(ual, 'activeUser.accountName', null) - const [openVoteDrawer, setOpenVoteDrawer] = useState(false) - const [openDesktopVotingTool, setOpenDesktopVotingTool] = useState(isDesktop) - const [ratingState, setRatingState] = useState({ - processing: false, - txError: null, - txSuccess: false - }) - - const loadMore = () => setCurrentlyVisible(currentlyVisible + 12) - const goToTop = () => document.getElementById('mainContent').scrollTo(0, 0) - - const handleToggleCompareTool = () => { - dispatch.proxies.toggleCompareTool() - } - - const handleToggleSelected = (item, isAddItem = false) => { - if (isAddItem) { - dispatch.proxies.addToSelected(item) - } else { - dispatch.proxies.removeSelected(item) - } - } - - const handleOnClose = () => { - setOpenDesktopVotingTool(false) - } - - const handleOpenDesktopVotingTool = ( - isAdding, - producerAccountName, - value - ) => { - if (isAdding) { - if (!(selectedProxies || []).length && !compareToolVisible) - handleToggleCompareTool() - handleToggleSelected(producerAccountName, isAdding) - isDesktop ? setOpenDesktopVotingTool(value) : setOpenVoteDrawer(value) - goToTop() - } else if (!isAdding) { - if ((selectedProxies || []).length === 1 && compareToolVisible) - handleToggleCompareTool() - handleToggleSelected() - } - } - - const handleSetRatingState = () => { - setRatingState({ - ...ratingState, - txError: null, - txSuccess: false, - showChipMessage: false - }) - } - - const sendVoteProxy = async () => { - if (!accountName) return - - const transaction = { - actions: [ - { - account: 'eosio', - name: 'voteproducer', - authorization: [ - { - actor: accountName, - permission: 'active' - } - ], - data: { - voter: accountName, - proxy: selectedProxies[0], - producers: [] - } - } - ] - } - - try { - setRatingState({ - ...ratingState, - txError: null, - processing: true, - txSuccess: false - }) - - await ual.activeUser.signTransaction(transaction, { - broadcast: true - }) - - setRatingState({ - ...ratingState, - processing: false, - txSuccess: true - }) - - setTimeout(() => { - setRatingState({ - ...ratingState, - txError: null, - txSuccess: false - }) - }, 2000) - } catch (error) { - console.warn(error) - setRatingState({ - ...ratingState, - processing: false, - txError: error.message ? error.message : error - }) - } - } - - const cmprTool = () => ( - { - handleToggleCompareTool() - handleToggleSelected() - }} - handleOnClose={handleOnClose} - /> - ) - - useEffect(() => { - const getData = async () => { - await dispatch.blockProducers.getBPs() - await dispatch.proxies.getProxies() - } - - getData() - }, []) - - useEffect(() => { - const getUserData = async () => { - if (ual.activeUser && !user) { - await dispatch.user.getUserChainData({ ual }) - } - } - - dispatch.blockProducers.setShowSortSelected(false) - getUserData() - }, [user, ual.activeUser, ual]) - - return ( -
- - {isDesktop && openDesktopVotingTool && cmprTool()} - - {(shownList || []).map((proxy) => ( - - - - ))} - - - {cmprTool()} - - -
- ) -} - -AllProxies.propTypes = { - ual: PropTypes.object -} - -export default AllProxies - -export const proxiesDrawer = [] diff --git a/webapp/src/routes/termsOfUse/styles.js b/webapp/src/routes/termsOfUse/styles.js deleted file mode 100644 index 157eaebc..00000000 --- a/webapp/src/routes/termsOfUse/styles.js +++ /dev/null @@ -1,8 +0,0 @@ -export default (theme) => ({ - root: { - padding: theme.spacing(3), - '& a': { - lineBreak: 'anywhere' - } - } -}) diff --git a/webapp/src/serviceWorker.js b/webapp/src/serviceWorker.js index b6dce8c0..c1057e91 100644 --- a/webapp/src/serviceWorker.js +++ b/webapp/src/serviceWorker.js @@ -1,12 +1,15 @@ -// In production, we register a service worker to serve assets from local cache. +/* eslint-disable */ +// This optional code is used to register a service worker. +// register() is not called by default. // This lets the app load faster on subsequent visits in production, and gives // it offline capabilities. However, it also means that developers (and users) -// will only see deployed updates on the "N+1" visit to a page, since previously -// cached resources are updated in the background. +// will only see deployed updates on subsequent visits to a page, after all the +// existing tabs open on the page have been closed, since previously cached +// resources are updated in the background. -// To learn more about the benefits of this model, read https://goo.gl/KwvDNy. -// This link also includes instructions on opting out of this behavior. +// To learn more about the benefits of this model and instructions on how to +// opt-in, read http://bit.ly/CRA-PWA const isLocalhost = Boolean( window.location.hostname === 'localhost' || @@ -21,11 +24,11 @@ const isLocalhost = Boolean( export function register(config) { if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) { // The URL constructor is available in all browsers that support SW. - const publicUrl = new URL(process.env.PUBLIC_URL, window.location) + const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href) if (publicUrl.origin !== window.location.origin) { // Our service worker won't work if PUBLIC_URL is on a different origin // from what our page is served on. This might happen if a CDN is used to - // serve assets; see https://github.com/facebook/create-react-app/issues/2374 + // serve assets see https://github.com/facebook/create-react-app/issues/2374 return } @@ -41,11 +44,11 @@ export function register(config) { navigator.serviceWorker.ready.then(() => { console.log( 'This web app is being served cache-first by a service ' + - 'worker. To learn more, visit https://goo.gl/SC7cgQ' + 'worker. To learn more, visit http://bit.ly/CRA-PWA' ) }) } else { - // Is not local host. Just register service worker + // Is not localhost. Just register service worker registerValidSW(swUrl, config) } }) @@ -58,17 +61,22 @@ function registerValidSW(swUrl, config) { .then((registration) => { registration.onupdatefound = () => { const installingWorker = registration.installing + if (installingWorker == null) { + return + } installingWorker.onstatechange = () => { if (installingWorker.state === 'installed') { if (navigator.serviceWorker.controller) { - // At this point, the old content will have been purged and - // the fresh content will have been added to the cache. - // It's the perfect time to display a "New content is - // available; please refresh." message in your web app. - console.log('New content is available; please refresh.') + // At this point, the updated precached content has been fetched, + // but the previous service worker will still serve the older + // content until all client tabs are closed. + console.log( + 'New content is available and will be used when all ' + + 'tabs for this page are closed. See http://bit.ly/CRA-PWA.' + ) // Execute callback - if (config.onUpdate) { + if (config && config.onUpdate) { config.onUpdate(registration) } } else { @@ -78,7 +86,7 @@ function registerValidSW(swUrl, config) { console.log('Content is cached for offline use.') // Execute callback - if (config.onSuccess) { + if (config && config.onSuccess) { config.onSuccess(registration) } } @@ -96,9 +104,10 @@ function checkValidServiceWorker(swUrl, config) { fetch(swUrl) .then((response) => { // Ensure service worker exists, and that we really are getting a JS file. + const contentType = response.headers.get('content-type') if ( response.status === 404 || - response.headers.get('content-type').indexOf('javascript') === -1 + (contentType != null && contentType.indexOf('javascript') === -1) ) { // No service worker found. Probably a different app. Reload the page. navigator.serviceWorker.ready.then((registration) => { diff --git a/webapp/src/services/api.js b/webapp/src/services/api.js deleted file mode 100644 index e9c1eae0..00000000 --- a/webapp/src/services/api.js +++ /dev/null @@ -1,44 +0,0 @@ -import qs from 'qs' -import store from '../store' - -const http = (method) => (endpoint, body, options = {}) => { - const token = store.getState().session - ? store.getState().session.accessToken - : null - - const params = { - method, - headers: { - Accept: 'application/json', - 'Content-Type': 'application/json' - } - } - - if (token) { - params.headers.Authorization = `Bearer ${token}` - } - - if (body) { - if (method === 'GET') { - endpoint = `${endpoint}?${qs.stringify(body)}` - } else { - params.body = JSON.stringify(body) - } - } - - return fetch(`${process.env.REACT_APP_EOS_API_URL}/${endpoint}`, params) - .then((response) => - response.json().then((payload) => ({ payload, response })) - ) - .then(({ response, payload }) => - response.ok ? payload : Promise.reject(payload) - ) -} - -export default { - get: http('GET'), - post: http('POST'), - put: http('PUT'), - patch: http('PATCH'), - delete: http('DELETE') -} diff --git a/webapp/src/services/bps.js b/webapp/src/services/bps.js deleted file mode 100644 index 2371b499..00000000 --- a/webapp/src/services/bps.js +++ /dev/null @@ -1,99 +0,0 @@ -import gql from 'graphql-tag' -import _get from 'lodash.get' - -import mockedBPs from 'mock/bps' -import client from 'services/graphql' -import getBPRadarData from 'utils/getBPRadarData' -import calculateEosFromVotes from 'utils/convertVotesToEosVotes' - -export const getAllBPs = ({ nameFilter = null, setBPs = () => {} } = {}) => { - const containsActive = { - system: { - _contains: { - is_active: 1 - } - } - } - const nameFilerObject = { - _or: { candidate_name: { _ilike: `%${nameFilter}%` } } - } - const whereFilter = nameFilter - ? { ...containsActive, ...nameFilerObject } - : { ...containsActive } - - return client - .subscribe({ - query: gql` - subscription blockProducers($where: producers_list_bool_exp!) { - producers_list( - where: $where - order_by: [{ bpjson: desc }, { total_votes: desc }] - ) { - owner - system - bpjson - average - community - development - infrastructure - trustiness - transparency - ratings_cntr - general_info - eden_average - eden_ratings_cntr - } - } - `, - variables: { - where: whereFilter - } - }) - .subscribe({ - next({ data: { producers_list: producers } }) { - const BPs = producers.map((producer) => { - const { - community, - trustiness, - development, - transparency, - infrastructure, - ...bp - } = producer - const parameters = { - community: community || 0, - development: development || 0, - infrastructure: infrastructure || 0, - transparency: transparency || 0, - trustiness: trustiness || 0 - } - const votesInEos = calculateEosFromVotes( - _get(bp, 'system.total_votes', 0) - ) - return { - ...bp, - system: { - ...bp.system, - votesInEos, - parameters - }, - data: getBPRadarData({ - name: _get(bp, 'bpjson.org.candidate_name', bp.owner), - parameters - }) - } - }) - - return setBPs(BPs) - }, - error(err) { - console.error('err', err) - } - }) -} - -export const findBPs = async (filter = {}) => mockedBPs - -export const findBPById = async (id) => mockedBPs[id] - -window.getAllBPs = getAllBPs diff --git a/webapp/src/services/eosjs-api.js b/webapp/src/services/eosjs-api.js deleted file mode 100644 index 6c653d24..00000000 --- a/webapp/src/services/eosjs-api.js +++ /dev/null @@ -1,14 +0,0 @@ -import { Api, JsonRpc } from 'eosjs' -import { JsSignatureProvider } from 'eosjs/dist/eosjs-jssig' -import { TextEncoder, TextDecoder } from 'text-encoding' -import fetch from 'node-fetch' - -const signatureProvider = new JsSignatureProvider([]) - -const rpc = new JsonRpc( - process.env.REACT_APP_EOS_API_URL || 'https://jungle.eosio.cr', - { fetch } -) -const api = new Api({ rpc, signatureProvider, textDecoder: new TextDecoder(), textEncoder: new TextEncoder() }) - -export default { api, rpc } diff --git a/webapp/src/services/graphql.js b/webapp/src/services/graphql.js deleted file mode 100644 index 8984deda..00000000 --- a/webapp/src/services/graphql.js +++ /dev/null @@ -1,42 +0,0 @@ -import ApolloClient from 'apollo-client' -import { WebSocketLink } from 'apollo-link-ws' -import { HttpLink } from 'apollo-link-http' -import { split } from 'apollo-link' -import { getMainDefinition } from 'apollo-utilities' -import { InMemoryCache } from 'apollo-cache-inmemory' - -// Create an http link: -const httpLink = new HttpLink({ - uri: process.env.REACT_APP_GRAPHQL_HTTP_URL, - credentials: 'same-origin' -}) - -// Create a WebSocket link: -const wsLink = new WebSocketLink({ - uri: process.env.REACT_APP_GRAPHQL_WS_URL, - options: { - reconnect: true - } -}) - -// using the ability to split links, you can send data to each link -// depending on what kind of operation is being sent -const link = split( - // split based on operation type - ({ query }) => { - const { kind, operation } = getMainDefinition(query) - return kind === 'OperationDefinition' && operation === 'subscription' - }, - wsLink, - httpLink -) - -// Instantiate client -const apolloClient = new ApolloClient({ - link, - cache: new InMemoryCache({ - addTypename: false - }) -}) - -export default apolloClient diff --git a/webapp/src/store.js b/webapp/src/store.js deleted file mode 100644 index 967c8dd6..00000000 --- a/webapp/src/store.js +++ /dev/null @@ -1,21 +0,0 @@ -import { init } from '@rematch/core' -import createPersistPlugin from '@rematch/persist' -import storage from 'redux-persist/lib/storage' - -import { locationChangeListener } from 'models/location' -import * as models from 'models' - -const persistPlugin = createPersistPlugin({ - key: 'root', - storage, - whitelist: ['blockProducers', 'settings'] -}) - -const store = init({ - models, - plugins: [persistPlugin] -}) - -locationChangeListener(store) - -export default store diff --git a/webapp/src/theme/breakpoints.js b/webapp/src/theme/breakpoints.js new file mode 100644 index 00000000..6d0880fe --- /dev/null +++ b/webapp/src/theme/breakpoints.js @@ -0,0 +1,11 @@ +const breakpoints = { + values: { + xs: 0, + sm: 600, + md: 1024, + lg: 1440, + xl: 1920 + } +} + +export default breakpoints diff --git a/webapp/src/theme/index.js b/webapp/src/theme/index.js new file mode 100644 index 00000000..85d3ddc0 --- /dev/null +++ b/webapp/src/theme/index.js @@ -0,0 +1,28 @@ +import { createTheme } from '@mui/material/styles' + +import palette from './palette' +import breakpoints from './breakpoints' +import typography from './typography' + +export default useDarkMode => + createTheme({ + breakpoints, + typography, + palette: { type: useDarkMode ? 'dark' : 'light', ...palette }, + overrides: { + root: { + fontSize: '2em' + }, + MuiSelect: { + root: { + paddingTop: 8 + } + }, + MuiInput: { + root: { + height: 50, + fontSize: 20 + } + } + } + }) diff --git a/webapp/src/theme/palette.js b/webapp/src/theme/palette.js new file mode 100644 index 00000000..3b962664 --- /dev/null +++ b/webapp/src/theme/palette.js @@ -0,0 +1,22 @@ +export default { + background: { + default: '#eeeeee' + }, + primary: { + light: '#787291', + main: '#443f56', + dark: 'rgba(0, 0, 0, 0.87)', + sectionBackground: '#ffffff', + submenu: '#597a81' + }, + secondary: { + light: '#8ba2a6', + main: '#597a81', + dark: '#222f32' + }, + surface: { + light: '#ffffff', + main: '#ffffff', + dark: '#f8f8f8' + } +} diff --git a/webapp/src/theme/props.js b/webapp/src/theme/props.js new file mode 100644 index 00000000..449c53bc --- /dev/null +++ b/webapp/src/theme/props.js @@ -0,0 +1,10 @@ +const props = { + MuiButtonBase: { + disableRipple: true + }, + MuiCardHeader: { + titleTypographyProps: { variant: 'h6' } + } +} + +export default props diff --git a/webapp/src/theme/typography.js b/webapp/src/theme/typography.js new file mode 100644 index 00000000..78a23298 --- /dev/null +++ b/webapp/src/theme/typography.js @@ -0,0 +1,13 @@ +const typography = { + fontFamily: ['Roboto', 'sans-serif'].join(','), + body1: { + fontWeight: 400, + letterSpacing: 0.44 + }, + overline: { + letterSpacing: 1.5, + fontSize: 10 + } +} + +export default typography diff --git a/webapp/src/utils/convertVotesToEosVotes.js b/webapp/src/utils/convert-votes-to-eos-votes.js similarity index 73% rename from webapp/src/utils/convertVotesToEosVotes.js rename to webapp/src/utils/convert-votes-to-eos-votes.js index c9a5a454..50ce8b9e 100644 --- a/webapp/src/utils/convertVotesToEosVotes.js +++ b/webapp/src/utils/convert-votes-to-eos-votes.js @@ -4,9 +4,9 @@ const TIMESTAMP_EPOCH = 946684800 -const castToNumber = (value) => (!isNaN(Number(value)) ? value / 1 : 0) +const castToNumber = value => (!isNaN(Number(value)) ? value / 1 : 0) -export default (votes) => { +export default votes => { const date = Date.now() / 1000 - TIMESTAMP_EPOCH const weight = date / (86400 * 7) / 52 // 86400 = seconds per day 24*3600 return castToNumber(votes) / 2 ** weight / 10000 diff --git a/webapp/src/utils/eosapi.js b/webapp/src/utils/eosapi.js new file mode 100644 index 00000000..0700054e --- /dev/null +++ b/webapp/src/utils/eosapi.js @@ -0,0 +1,9 @@ +import EosApi from 'eosjs-api' + +import { ualConfig } from '../config' + +export const eosApi = EosApi({ + httpEndpoint: ualConfig.endpoint, + verbose: false, + fetchConfiguration: {} +}) diff --git a/webapp/src/utils/eosjsUtils.js b/webapp/src/utils/eosjs-utils.js similarity index 80% rename from webapp/src/utils/eosjsUtils.js rename to webapp/src/utils/eosjs-utils.js index 846b8332..daf2aa27 100644 --- a/webapp/src/utils/eosjsUtils.js +++ b/webapp/src/utils/eosjs-utils.js @@ -1,6 +1,6 @@ import { JsonRpc } from 'eosjs' -const getRpc = (ual) => { +const getRpc = ual => { const endpoint = ual.chains[0].rpcEndpoints[0] const rpcEndpoint = ual.activeUser.buildRpcEndpoint(endpoint) @@ -8,7 +8,7 @@ const getRpc = (ual) => { return new JsonRpc(rpcEndpoint) } -const getAccountName = async (ual) => { +const getAccountName = async ual => { return await ual.activeUser.getAccountName(ual) } diff --git a/webapp/src/utils/formatNumber.js b/webapp/src/utils/format-number.js similarity index 100% rename from webapp/src/utils/formatNumber.js rename to webapp/src/utils/format-number.js diff --git a/webapp/src/utils/format-with-thousand-separator.js b/webapp/src/utils/format-with-thousand-separator.js new file mode 100644 index 00000000..be5d3e82 --- /dev/null +++ b/webapp/src/utils/format-with-thousand-separator.js @@ -0,0 +1,13 @@ +export const formatWithThousandSeparator = (value, precision) => { + if (!value || isNaN(value)) { + return value + } + + let newValue = parseFloat(value) + + if (precision >= 0) { + newValue = newValue.toFixed(precision) + } + + return newValue.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',') +} diff --git a/webapp/src/utils/getAverageValue.js b/webapp/src/utils/get-average-value.js similarity index 79% rename from webapp/src/utils/getAverageValue.js rename to webapp/src/utils/get-average-value.js index 58520868..de08733f 100644 --- a/webapp/src/utils/getAverageValue.js +++ b/webapp/src/utils/get-average-value.js @@ -1,4 +1,4 @@ -const validateNumber = (average) => { +const validateNumber = average => { const value = average.toFixed(2) if (value % 1 === 0) return parseInt(value) @@ -6,7 +6,7 @@ const validateNumber = (average) => { return value } -export default (value) => { +export default value => { let average = value if (typeof average === 'string') { diff --git a/webapp/src/utils/get-bp-radar-data.js b/webapp/src/utils/get-bp-radar-data.js new file mode 100644 index 00000000..481589f5 --- /dev/null +++ b/webapp/src/utils/get-bp-radar-data.js @@ -0,0 +1,20 @@ +import getRgbColorsFromHex from './get-rgb-colors-from-hex' + +export default ({ name, parameters }) => { + const { r, g, b } = getRgbColorsFromHex(name) + + return { + // label: name, + name, + type: 'area', + // lineTension: 0.3, + // borderJoinStyle: 'round', + // backgroundColor: `rgba(${r}, ${g}, ${b}, .6)`, + // borderColor: `rgba(${r}, ${g}, ${b}, .6)`, + color: `rgba(${r}, ${g}, ${b}, .6)`, + // pointBorderColor: '#fff', + // pointHoverBackgroundColor: '#fff', + // pointHoverBorderColor: `rgba(${r}, ${g}, ${b}, 1)`, + data: Object.values(parameters) + } +} diff --git a/webapp/src/utils/getRadarLabelName.js b/webapp/src/utils/get-radar-label-name.js similarity index 80% rename from webapp/src/utils/getRadarLabelName.js rename to webapp/src/utils/get-radar-label-name.js index 0a3b73ec..f591fb45 100644 --- a/webapp/src/utils/getRadarLabelName.js +++ b/webapp/src/utils/get-radar-label-name.js @@ -1,4 +1,4 @@ -const getComparisonParameter = (t) => { +const getComparisonParameter = t => { return [ t('community'), t('development'), diff --git a/webapp/src/utils/getRgbColorsFromHex.js b/webapp/src/utils/get-rgb-colors-from-hex.js similarity index 100% rename from webapp/src/utils/getRgbColorsFromHex.js rename to webapp/src/utils/get-rgb-colors-from-hex.js diff --git a/webapp/src/utils/getBPRadarData.js b/webapp/src/utils/getBPRadarData.js deleted file mode 100644 index 393cb8f3..00000000 --- a/webapp/src/utils/getBPRadarData.js +++ /dev/null @@ -1,18 +0,0 @@ -import getRgbColorsFromHex from 'utils/getRgbColorsFromHex' - -export default ({ name, parameters }) => { - const { r, g, b } = getRgbColorsFromHex(name) - - return { - label: name, - lineTension: 0.3, - borderJoinStyle: 'round', - backgroundColor: `rgba(${r}, ${g}, ${b}, .6)`, - borderColor: `rgba(${r}, ${g}, ${b}, .6)`, - pointBackgroundColor: `rgba(${r}, ${g}, ${b}, .6)`, - pointBorderColor: '#fff', - pointHoverBackgroundColor: '#fff', - pointHoverBorderColor: `rgba(${r}, ${g}, ${b}, 1)`, - data: Object.values(parameters) - } -} diff --git a/webapp/src/utils/getColorFromName.js b/webapp/src/utils/getColorFromName.js deleted file mode 100644 index 19e0391d..00000000 --- a/webapp/src/utils/getColorFromName.js +++ /dev/null @@ -1,18 +0,0 @@ -const hashCode = str => { - let hash = 0 - for (let i = 0; i < str.length; i++) { - hash = str.charCodeAt(i) + ((hash << 5) - hash) - } - return hash -} - -const intToRGB = i => { - const c = (i & 0x00ffffff).toString(16).toUpperCase() - - return '00000'.substring(0, 6 - c.length) + c -} - -export default name => - intToRGB(hashCode(name)) - .match(/(..?)/g) - .map(value => parseInt(value, 16)) diff --git a/webapp/src/utils/index.js b/webapp/src/utils/index.js new file mode 100644 index 00000000..58f0f1e3 --- /dev/null +++ b/webapp/src/utils/index.js @@ -0,0 +1,3 @@ +export * from './eosapi' +export * from './format-with-thousand-separator' +export * from './on-img-error' diff --git a/webapp/src/utils/modeled-bp-data.js b/webapp/src/utils/modeled-bp-data.js new file mode 100644 index 00000000..c73132b1 --- /dev/null +++ b/webapp/src/utils/modeled-bp-data.js @@ -0,0 +1,34 @@ +import _get from 'lodash.get' + +import getBPRadarData from './get-bp-radar-data' +import calculateEosFromVotes from './convert-votes-to-eos-votes' + +export default ({ + community, + trustiness, + development, + transparency, + infrastructure, + ...bp +}) => { + const parameters = { + community: community || 0, + development: development || 0, + infrastructure: infrastructure || 0, + transparency: transparency || 0, + trustiness: trustiness || 0 + } + const votesInEos = calculateEosFromVotes(_get(bp, 'system.total_votes', 0)) + return { + ...bp, + system: { + ...bp.system, + votesInEos, + parameters + }, + data: getBPRadarData({ + name: _get(bp, 'bpjson.org.candidate_name', bp.owner), + parameters + }) + } +} diff --git a/webapp/src/utils/modeled-proxy-data.js b/webapp/src/utils/modeled-proxy-data.js new file mode 100644 index 00000000..b23e6e7e --- /dev/null +++ b/webapp/src/utils/modeled-proxy-data.js @@ -0,0 +1,77 @@ +import _get from 'lodash.get' + +import calculateEosFromVotes from './convert-votes-to-eos-votes' +import getBPRadarData from './get-bp-radar-data' +import getBpDataModeled from './modeled-bp-data' + +export default proxy => { + const rateInfo = [] + const proxyProducers = _get(proxy, 'voter_info.producers', []) + const proxiedVoteEOS = calculateEosFromVotes( + _get(proxy, 'voter_info.last_vote_weight', 0) + ) + const totalVoteEOS = calculateEosFromVotes( + _get(proxy, 'voter_info.proxied_vote_weight', 0) + ) + const producersDataModeled = proxyProducers.map(bp => { + const producer = getBpDataModeled(bp) + + const { + system: { parameters } + } = producer + + rateInfo.push(parameters) + + return producer + }) + + const averageParams = rateInfo.reduce( + (acc, current, index) => { + const community = acc.community + current.community + const development = acc.development + current.development + const infrastructure = acc.infrastructure + current.infrastructure + const transparency = acc.transparency + current.transparency + const trustiness = acc.trustiness + current.trustiness + + if (index + 1 === rateInfo.length) { + return { + community: community / rateInfo.length, + development: development / rateInfo.length, + infrastructure: infrastructure / rateInfo.length, + transparency: transparency / rateInfo.length, + trustiness: trustiness / rateInfo.length + } + } + + return { + community, + development, + infrastructure, + transparency, + trustiness + } + }, + { + community: 0, + development: 0, + infrastructure: 0, + transparency: 0, + trustiness: 0 + } + ) + + return { + ...proxy, + voter_info: { + ...proxy.voter_info, + producers: producersDataModeled + }, + averageParams, + data: getBPRadarData({ + name: proxy.owner, + parameters: averageParams + }), + proxiedVoteEOS, + totalVoteEOS + } +} diff --git a/webapp/src/utils/on-img-error.js b/webapp/src/utils/on-img-error.js new file mode 100644 index 00000000..4425ed4f --- /dev/null +++ b/webapp/src/utils/on-img-error.js @@ -0,0 +1,7 @@ +export const onImgError = defaultLogo => ev => { + if (ev.target.src === defaultLogo) { + return + } + + ev.target.src = defaultLogo +} diff --git a/webapp/src/utils/sortedBy.js b/webapp/src/utils/sorted-by.js similarity index 98% rename from webapp/src/utils/sortedBy.js rename to webapp/src/utils/sorted-by.js index dab2b0b5..1a888ba7 100644 --- a/webapp/src/utils/sortedBy.js +++ b/webapp/src/utils/sorted-by.js @@ -10,7 +10,7 @@ const _sortValues = (firstValues, secondValues, path) => { export default (sortBy, blockProducers) => { switch (sortBy) { case 'alphabetical': { - const _getValidName = (bp) => { + const _getValidName = bp => { const name = _get(bp, 'bpjson.org.candidate_name', null) if (name && name.length) return name.toUpperCase() diff --git a/webapp/src/utils/ualAuthenticators.js b/webapp/src/utils/ualAuthenticators.js deleted file mode 100644 index 5102b5a8..00000000 --- a/webapp/src/utils/ualAuthenticators.js +++ /dev/null @@ -1,44 +0,0 @@ -import { Scatter } from 'ual-scatter' -import { Ledger } from 'ual-ledger' -import { Lynx } from 'ual-lynx' -import { TokenPocket } from 'ual-token-pocket' -import { MeetOne } from 'ual-meetone' -import { Anchor } from 'ual-anchor' - -import { - appName, - eosChainId, - eosApiProtocol, - eosApiHost, - eosApiPort -} from '../config' - -export const network = { - chainId: - eosChainId || - '2a02a0053e5a8cf73a56ba0fda11e4d92e0238a4a2aa74fccf46d5a910746840', - rpcEndpoints: [ - { - blockchain: 'eos', - protocol: eosApiProtocol || 'https', - host: eosApiHost || 'jungle.eosio.cr', - port: parseInt(eosApiPort || '443') - } - ] -} - -const lynx = new Lynx([network]) -const ledger = new Ledger([network]) -const tokenPocket = new TokenPocket([network]) -const meetOne = new MeetOne([network.chainId]) -const scatter = new Scatter([network], { appName }) -const anchor = new Anchor([network], { appName }) - -export const authenticators = [ - lynx, - ledger, - scatter, - tokenPocket, - meetOne, - anchor -] diff --git a/webapp/prettier.config.js b/webapp/test.prettier.config.js similarity index 80% rename from webapp/prettier.config.js rename to webapp/test.prettier.config.js index a63208a7..69967801 100644 --- a/webapp/prettier.config.js +++ b/webapp/test.prettier.config.js @@ -7,5 +7,6 @@ module.exports = { trailingComma: 'none', bracketSpacing: true, jsxBracketSameLine: false, - jsxSingleQuote: true + jsxSingleQuote: true, + endOfLine: 'auto' } diff --git a/webapp/yarn.lock b/webapp/yarn.lock index 535c7a0d..c9530e0e 100644 --- a/webapp/yarn.lock +++ b/webapp/yarn.lock @@ -2,6 +2,24 @@ # yarn lockfile v1 +"@apollo/client@^3.3.21": + version "3.4.13" + resolved "https://registry.yarnpkg.com/@apollo/client/-/client-3.4.13.tgz#81670c27b376e80e3845ecf6468e534d908fa5b5" + integrity sha512-/nH8z/0X6WJ+wtUREHTlKQGX4lo6u3XkF1hy+k4eCxLZzT5+VRw1rm92iIkj1H85vep/eE/KV3DdRq1x3t9NnQ== + dependencies: + "@graphql-typed-document-node/core" "^3.0.0" + "@wry/context" "^0.6.0" + "@wry/equality" "^0.5.0" + "@wry/trie" "^0.3.0" + graphql-tag "^2.12.3" + hoist-non-react-statics "^3.3.2" + optimism "^0.16.1" + prop-types "^15.7.2" + symbol-observable "^4.0.0" + ts-invariant "^0.9.0" + tslib "^2.3.0" + zen-observable-ts "~1.1.0" + "@apollo/react-common@^3.1.4": version "3.1.4" resolved "https://registry.yarnpkg.com/@apollo/react-common/-/react-common-3.1.4.tgz#ec13c985be23ea8e799c9ea18e696eccc97be345" @@ -140,6 +158,15 @@ semver "^6.3.0" source-map "^0.5.0" +"@babel/eslint-parser@^7.13.10": + version "7.15.7" + resolved "https://registry.yarnpkg.com/@babel/eslint-parser/-/eslint-parser-7.15.7.tgz#2dc3d0ff0ea22bb1e08d93b4eeb1149bf1c75f2d" + integrity sha512-yJkHyomClm6A2Xzb8pdAo4HzYMSXFn1O5zrCYvbFP0yQFvHueLedV8WiEno8yJOKStjUXzBZzJFeWQ7b3YMsqQ== + dependencies: + eslint-scope "^5.1.1" + eslint-visitor-keys "^2.1.0" + semver "^6.3.0" + "@babel/generator@^7.12.1", "@babel/generator@^7.15.4", "@babel/generator@^7.6.0": version "7.15.4" resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.15.4.tgz#85acb159a267ca6324f9793986991ee2022a05b0" @@ -253,18 +280,18 @@ "@babel/types" "^7.15.4" "@babel/helper-module-transforms@^7.12.1", "@babel/helper-module-transforms@^7.14.5", "@babel/helper-module-transforms@^7.15.4": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.15.4.tgz#962cc629a7f7f9a082dd62d0307fa75fe8788d7c" - integrity sha512-9fHHSGE9zTC++KuXLZcB5FKgvlV83Ox+NLUmQTawovwlJ85+QMhk1CnVk406CQVj97LaWod6KVjl2Sfgw9Aktw== + version "7.15.7" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.15.7.tgz#7da80c8cbc1f02655d83f8b79d25866afe50d226" + integrity sha512-ZNqjjQG/AuFfekFTY+7nY4RgBSklgTu970c7Rj3m/JOhIu5KPBUuTA9AY6zaKcUvk4g6EbDXdBnhi35FAssdSw== dependencies: "@babel/helper-module-imports" "^7.15.4" "@babel/helper-replace-supers" "^7.15.4" "@babel/helper-simple-access" "^7.15.4" "@babel/helper-split-export-declaration" "^7.15.4" - "@babel/helper-validator-identifier" "^7.14.9" + "@babel/helper-validator-identifier" "^7.15.7" "@babel/template" "^7.15.4" "@babel/traverse" "^7.15.4" - "@babel/types" "^7.15.4" + "@babel/types" "^7.15.6" "@babel/helper-optimise-call-expression@^7.15.4": version "7.15.4" @@ -318,10 +345,10 @@ dependencies: "@babel/types" "^7.15.4" -"@babel/helper-validator-identifier@^7.14.5", "@babel/helper-validator-identifier@^7.14.9": - version "7.14.9" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.9.tgz#6654d171b2024f6d8ee151bf2509699919131d48" - integrity sha512-pQYxPY0UP6IHISRitNe8bsijHex4TWZXi2HwKVsjPiltzlhse2znVcm9Ace510VT1kxIHjGJCZZQBX2gJDbo0g== +"@babel/helper-validator-identifier@^7.14.5", "@babel/helper-validator-identifier@^7.14.9", "@babel/helper-validator-identifier@^7.15.7": + version "7.15.7" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.15.7.tgz#220df993bfe904a4a6b02ab4f3385a5ebf6e2389" + integrity sha512-K4JvCtQqad9OY2+yTU8w+E82ywk/fe+ELNlt1G8z3bVGlZfn/hOcQQsUhGhW/N+tb3fxK800wLtKOE/aM0m72w== "@babel/helper-validator-option@^7.12.1", "@babel/helper-validator-option@^7.14.5": version "7.14.5" @@ -357,9 +384,9 @@ js-tokens "^4.0.0" "@babel/parser@^7.1.0", "@babel/parser@^7.12.3", "@babel/parser@^7.15.4", "@babel/parser@^7.15.5", "@babel/parser@^7.6.0", "@babel/parser@^7.7.0": - version "7.15.6" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.15.6.tgz#043b9aa3c303c0722e5377fef9197f4cf1796549" - integrity sha512-S/TSCcsRuCkmpUuoWijua0Snt+f3ewU/8spLo+4AXJCZfT0bVCzLD5MuOKdrx0mlAptbKzn5AdgEIIKXxXkz9Q== + version "7.15.7" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.15.7.tgz#0c3ed4a2eb07b165dfa85b3cc45c727334c4edae" + integrity sha512-rycZXvQ+xS9QyIcJ9HXeDWf1uxqlbVFAUq0Rq0dbc50Zb/+wUe/ehyfzGfm9KZZF0kBejYgxltBXocP+gKdL2g== "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.15.4": version "7.15.4" @@ -505,7 +532,7 @@ "@babel/helper-skip-transparent-expression-wrappers" "^7.12.1" "@babel/plugin-syntax-optional-chaining" "^7.8.0" -"@babel/plugin-proposal-optional-chaining@^7.12.1", "@babel/plugin-proposal-optional-chaining@^7.14.5": +"@babel/plugin-proposal-optional-chaining@^7.12.1", "@babel/plugin-proposal-optional-chaining@^7.13.8", "@babel/plugin-proposal-optional-chaining@^7.14.5": version "7.14.5" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.14.5.tgz#fa83651e60a360e3f13797eef00b8d519695b603" integrity sha512-ycz+VOzo2UbWNI1rQXxIuMOzrDdHGrI23fRiz/Si2R4kv2XZQ1BK8ccdHwehMKBlcH/joGW/tzrUmo67gbJHlQ== @@ -610,7 +637,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-jsx@^7.14.5": +"@babel/plugin-syntax-jsx@^7.12.13", "@babel/plugin-syntax-jsx@^7.14.5": version "7.14.5" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.14.5.tgz#000e2e25d8673cce49300517a3eda44c263e4201" integrity sha512-ohuFIsOMXJnbOMRfX7/w7LocdR6R7whhuRD4ax8IipLcLPlZGJKkBxgHp++U4N/vKyU16/YDQr2f5seajD3jIw== @@ -1143,7 +1170,7 @@ js-levenshtein "^1.1.3" semver "^5.3.0" -"@babel/preset-env@^7.12.1", "@babel/preset-env@^7.8.4": +"@babel/preset-env@^7.12.1", "@babel/preset-env@^7.13.10", "@babel/preset-env@^7.8.4": version "7.15.6" resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.15.6.tgz#0f3898db9d63d320f21b17380d8462779de57659" integrity sha512-L+6jcGn7EWu7zqaO2uoTDjjMBW+88FXzV8KvrBl2z6MtRNxlsmUNRlZPaNNPUTgqhyC5DHNFk/2Jmra+ublZWw== @@ -1257,7 +1284,7 @@ "@babel/plugin-transform-react-jsx-source" "^7.12.1" "@babel/plugin-transform-react-pure-annotations" "^7.12.1" -"@babel/preset-react@^7.12.5": +"@babel/preset-react@^7.12.13", "@babel/preset-react@^7.12.5": version "7.14.5" resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.14.5.tgz#0fbb769513f899c2c56f3a882fa79673c2d4ab3c" integrity sha512-XFxBkjyObLvBaAvkx1Ie95Iaq4S/GUEIrejyrntQ/VCMKUYvKLoyKxOBzJ2kjA3b6rC9/KL6KXfDC2GqvLiNqQ== @@ -1299,7 +1326,7 @@ dependencies: regenerator-runtime "^0.13.2" -"@babel/runtime@^7.1.2", "@babel/runtime@^7.10.1", "@babel/runtime@^7.10.2", "@babel/runtime@^7.10.5", "@babel/runtime@^7.11.1", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.0", "@babel/runtime@^7.12.1", "@babel/runtime@^7.12.13", "@babel/runtime@^7.12.5", "@babel/runtime@^7.14.5", "@babel/runtime@^7.14.6", "@babel/runtime@^7.3.1", "@babel/runtime@^7.4.4", "@babel/runtime@^7.5.5", "@babel/runtime@^7.7.2", "@babel/runtime@^7.8.3", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2": +"@babel/runtime@^7.1.2", "@babel/runtime@^7.10.1", "@babel/runtime@^7.10.2", "@babel/runtime@^7.10.5", "@babel/runtime@^7.11.1", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.0", "@babel/runtime@^7.12.1", "@babel/runtime@^7.12.13", "@babel/runtime@^7.12.5", "@babel/runtime@^7.13.10", "@babel/runtime@^7.14.0", "@babel/runtime@^7.14.5", "@babel/runtime@^7.14.6", "@babel/runtime@^7.15.4", "@babel/runtime@^7.3.1", "@babel/runtime@^7.4.4", "@babel/runtime@^7.5.5", "@babel/runtime@^7.7.2", "@babel/runtime@^7.7.6", "@babel/runtime@^7.8.3", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2": version "7.15.4" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.15.4.tgz#fd17d16bfdf878e6dd02d19753a39fa8a8d9c84a" integrity sha512-99catp6bHCaxr4sJ/DbTGgHS4+Rs2RVd2g7iOap6SLGPDknRK9ztKNsE/Fg6QhSeh1FGE5f6gHGQmvvn3I3xhw== @@ -1361,6 +1388,68 @@ resolved "https://registry.yarnpkg.com/@csstools/normalize.css/-/normalize.css-10.1.0.tgz#f0950bba18819512d42f7197e56c518aa491cf18" integrity sha512-ij4wRiunFfaJxjB0BdrYHIH8FxBJpOwNPhhAcunlmPdXudL1WQV1qoP9un6JsEBAgQH+7UXyyjh0g7jTxXK6tg== +"@date-io/core@^2.11.0": + version "2.11.0" + resolved "https://registry.yarnpkg.com/@date-io/core/-/core-2.11.0.tgz#28580cda1c8228ab2c7ed6aee673ef0495f913e6" + integrity sha512-DvPBnNoeuLaoSJZaxgpu54qzRhRKjSYVyQjhznTFrllKuDpm0sDFjHo6lvNLCM/cfMx2gb2PM2zY2kc9C8nmuw== + +"@date-io/date-fns@^2.10.6", "@date-io/date-fns@^2.11.0": + version "2.11.0" + resolved "https://registry.yarnpkg.com/@date-io/date-fns/-/date-fns-2.11.0.tgz#142fbf954eda7ad66514af7a2802d78c4ea40053" + integrity sha512-mPQ71plBeFrArvBSHtjWMHXA89IUbZ6kuo2dsjlRC/1uNOybo91spIb+wTu03NxKTl8ut07s0jJ9svF71afpRg== + dependencies: + "@date-io/core" "^2.11.0" + +"@date-io/dayjs@^2.10.6": + version "2.11.0" + resolved "https://registry.yarnpkg.com/@date-io/dayjs/-/dayjs-2.11.0.tgz#41f4b4b9629612e6012accffd848875d1aeffb74" + integrity sha512-w67vRK56NZJIKhJM/CrNbfnIcuMvR3ApfxzNZiCZ5w29sxgBDeKuX4M+P7A9r5HXOMGcsOcpgaoTDINNGkdpGQ== + dependencies: + "@date-io/core" "^2.11.0" + +"@date-io/luxon@^2.10.6": + version "2.11.1" + resolved "https://registry.yarnpkg.com/@date-io/luxon/-/luxon-2.11.1.tgz#31a72f7b5e163c74e8a3b29d8f16c4c30de6ed43" + integrity sha512-JUXo01kdPQxLORxqdENrgdUhooKgDUggsNRSdi2BcUhASIY2KGwwWXu8ikVHHGkw+DUF4FOEKGfkQd0RHSvX6g== + dependencies: + "@date-io/core" "^2.11.0" + +"@date-io/moment@^2.10.6": + version "2.11.0" + resolved "https://registry.yarnpkg.com/@date-io/moment/-/moment-2.11.0.tgz#850f8dd090d401845b39276d034dbabe20224ef5" + integrity sha512-QSL+83qezQ9Ty0dtFgAkk6eC0GMl/lgYfDajeVUDB3zVA2A038hzczRLBg29ifnBGhQMPABxuOafgWwhDjlarg== + dependencies: + "@date-io/core" "^2.11.0" + +"@emotion/babel-plugin@^11.3.0": + version "11.3.0" + resolved "https://registry.yarnpkg.com/@emotion/babel-plugin/-/babel-plugin-11.3.0.tgz#3a16850ba04d8d9651f07f3fb674b3436a4fb9d7" + integrity sha512-UZKwBV2rADuhRp+ZOGgNWg2eYgbzKzQXfQPtJbu/PLy8onurxlNCLvxMQEvlr1/GudguPI5IU9qIY1+2z1M5bA== + dependencies: + "@babel/helper-module-imports" "^7.12.13" + "@babel/plugin-syntax-jsx" "^7.12.13" + "@babel/runtime" "^7.13.10" + "@emotion/hash" "^0.8.0" + "@emotion/memoize" "^0.7.5" + "@emotion/serialize" "^1.0.2" + babel-plugin-macros "^2.6.1" + convert-source-map "^1.5.0" + escape-string-regexp "^4.0.0" + find-root "^1.1.0" + source-map "^0.5.7" + stylis "^4.0.3" + +"@emotion/cache@^11.4.0": + version "11.4.0" + resolved "https://registry.yarnpkg.com/@emotion/cache/-/cache-11.4.0.tgz#293fc9d9a7a38b9aad8e9337e5014366c3b09ac0" + integrity sha512-Zx70bjE7LErRO9OaZrhf22Qye1y4F7iDl+ITjet0J+i+B88PrAOBkKvaAWhxsZf72tDLajwCgfCjJ2dvH77C3g== + dependencies: + "@emotion/memoize" "^0.7.4" + "@emotion/sheet" "^1.0.0" + "@emotion/utils" "^1.0.0" + "@emotion/weak-memoize" "^0.2.5" + stylis "^4.0.3" + "@emotion/hash@^0.8.0": version "0.8.0" resolved "https://registry.yarnpkg.com/@emotion/hash/-/hash-0.8.0.tgz#bbbff68978fefdbe68ccb533bc8cbe1d1afb5413" @@ -1373,16 +1462,78 @@ dependencies: "@emotion/memoize" "0.7.4" +"@emotion/is-prop-valid@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@emotion/is-prop-valid/-/is-prop-valid-1.1.0.tgz#29ef6be1e946fb4739f9707def860f316f668cde" + integrity sha512-9RkilvXAufQHsSsjQ3PIzSns+pxuX4EW8EbGeSPjZMHuMx6z/MOzb9LpqNieQX4F3mre3NWS2+X3JNRHTQztUQ== + dependencies: + "@emotion/memoize" "^0.7.4" + "@emotion/memoize@0.7.4": version "0.7.4" resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.7.4.tgz#19bf0f5af19149111c40d98bb0cf82119f5d9eeb" integrity sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw== -"@emotion/unitless@^0.7.0": +"@emotion/memoize@^0.7.4", "@emotion/memoize@^0.7.5": + version "0.7.5" + resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.7.5.tgz#2c40f81449a4e554e9fc6396910ed4843ec2be50" + integrity sha512-igX9a37DR2ZPGYtV6suZ6whr8pTFtyHL3K/oLUotxpSVO2ASaprmAe2Dkq7tBo7CRY7MMDrAa9nuQP9/YG8FxQ== + +"@emotion/react@^11.4.1": + version "11.4.1" + resolved "https://registry.yarnpkg.com/@emotion/react/-/react-11.4.1.tgz#a1b0b767b5bad57515ffb0cad9349614d27f4d57" + integrity sha512-pRegcsuGYj4FCdZN6j5vqCALkNytdrKw3TZMekTzNXixRg4wkLsU5QEaBG5LC6l01Vppxlp7FE3aTHpIG5phLg== + dependencies: + "@babel/runtime" "^7.13.10" + "@emotion/cache" "^11.4.0" + "@emotion/serialize" "^1.0.2" + "@emotion/sheet" "^1.0.2" + "@emotion/utils" "^1.0.0" + "@emotion/weak-memoize" "^0.2.5" + hoist-non-react-statics "^3.3.1" + +"@emotion/serialize@^1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@emotion/serialize/-/serialize-1.0.2.tgz#77cb21a0571c9f68eb66087754a65fa97bfcd965" + integrity sha512-95MgNJ9+/ajxU7QIAruiOAdYNjxZX7G2mhgrtDWswA21VviYIRP1R5QilZ/bDY42xiKsaktP4egJb3QdYQZi1A== + dependencies: + "@emotion/hash" "^0.8.0" + "@emotion/memoize" "^0.7.4" + "@emotion/unitless" "^0.7.5" + "@emotion/utils" "^1.0.0" + csstype "^3.0.2" + +"@emotion/sheet@^1.0.0", "@emotion/sheet@^1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@emotion/sheet/-/sheet-1.0.2.tgz#1d9ffde531714ba28e62dac6a996a8b1089719d0" + integrity sha512-QQPB1B70JEVUHuNtzjHftMGv6eC3Y9wqavyarj4x4lg47RACkeSfNo5pxIOKizwS9AEFLohsqoaxGQj4p0vSIw== + +"@emotion/styled@^11.3.0": + version "11.3.0" + resolved "https://registry.yarnpkg.com/@emotion/styled/-/styled-11.3.0.tgz#d63ee00537dfb6ff612e31b0e915c5cf9925a207" + integrity sha512-fUoLcN3BfMiLlRhJ8CuPUMEyKkLEoM+n+UyAbnqGEsCd5IzKQ7VQFLtzpJOaCD2/VR2+1hXQTnSZXVJeiTNltA== + dependencies: + "@babel/runtime" "^7.13.10" + "@emotion/babel-plugin" "^11.3.0" + "@emotion/is-prop-valid" "^1.1.0" + "@emotion/serialize" "^1.0.2" + "@emotion/utils" "^1.0.0" + +"@emotion/unitless@^0.7.0", "@emotion/unitless@^0.7.5": version "0.7.5" resolved "https://registry.yarnpkg.com/@emotion/unitless/-/unitless-0.7.5.tgz#77211291c1900a700b8a78cfafda3160d76949ed" integrity sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg== +"@emotion/utils@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@emotion/utils/-/utils-1.0.0.tgz#abe06a83160b10570816c913990245813a2fd6af" + integrity sha512-mQC2b3XLDs6QCW+pDQDiyO/EdGZYOygE8s5N5rrzjSI4M3IejPE/JPndCBwRT9z982aqQNi6beWs1UeayrQxxA== + +"@emotion/weak-memoize@^0.2.5": + version "0.2.5" + resolved "https://registry.yarnpkg.com/@emotion/weak-memoize/-/weak-memoize-0.2.5.tgz#8eed982e2ee6f7f4e44c253e12962980791efd46" + integrity sha512-6U71C2Wp7r5XtFtQzYrW5iKFT67OixrSxjI4MptCHzdSVlgabczzqLe0ZSgnub/5Kp4hSbpDB1tMytZY9pwxxA== + "@eoscostarica/eoscr-components@^3.5.4": version "3.5.4" resolved "https://registry.yarnpkg.com/@eoscostarica/eoscr-components/-/eoscr-components-3.5.4.tgz#9a7d05d03f2c21a297215b3530f671fdcf38cadc" @@ -1413,6 +1564,22 @@ "@types/node" "*" typescript "*" +"@eoscostarica/ual-reactjs-renderer@^0.3.1": + version "0.3.1" + resolved "https://registry.yarnpkg.com/@eoscostarica/ual-reactjs-renderer/-/ual-reactjs-renderer-0.3.1.tgz#4f056ea9a14557aee86f16626cf5a25da3e8fed9" + integrity sha512-ulEv8hSuZwDOqapqY9JNug6iUTsaXbCJTllFAwGjy0Yk6hOnztcR9+6s/KdIHEpCpVJ1g53rOFznHxw/je8klQ== + dependencies: + "@react-icons/all-files" "^4.1.0" + i18next "14.0.1" + i18next-browser-languagedetector "2.2.4" + prop-types "15.7.2" + react "16.13.0" + react-dom "16.13.0" + react-icons "4.1.0" + react-tooltip "3.9.2" + styled-components "4.4.1" + universal-authenticator-library "0.3.0" + "@eslint/eslintrc@^0.2.1": version "0.2.2" resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-0.2.2.tgz#d01fc791e2fc33e88a29d6f3dc7e93d0cd784b76" @@ -1449,6 +1616,11 @@ resolved "https://registry.yarnpkg.com/@gar/promisify/-/promisify-1.1.2.tgz#30aa825f11d438671d585bd44e7fd564535fc210" integrity sha512-82cpyJyKRoQoRi+14ibCeGPu0CwypgtBAdBhq1WfvagpCZNKqwXbKwXllYSMG91DhmG4jt9gN8eP6lGOtozuaw== +"@graphql-typed-document-node/core@^3.0.0": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@graphql-typed-document-node/core/-/core-3.1.0.tgz#0eee6373e11418bfe0b5638f654df7a4ca6a3950" + integrity sha512-wYn6r8zVZyQJ6rQaALBEln5B1pzxb9shV5Ef97kTvn6yVGrqyXVnDqnU24MXnFubR+rZjBY9NWuxX3FB2sTsjg== + "@greymass/eosio@^0.4.0", "@greymass/eosio@^0.4.3": version "0.4.9" resolved "https://registry.yarnpkg.com/@greymass/eosio/-/eosio-0.4.9.tgz#429b0426c0781421903e866612b383953e10e414" @@ -1750,7 +1922,7 @@ resolved "https://registry.yarnpkg.com/@ledgerhq/logs/-/logs-4.72.0.tgz#43df23af013ad1135407e5cf33ca6e4c4c7708d5" integrity sha512-o+TYF8vBcyySRsb2kqBDv/KMeme8a2nwWoG+lAWzbDmWfb2/MrVWYCVYDYvjXdSoI/Cujqy1i0gIDrkdxa9chA== -"@material-ui/core@^4.12.1", "@material-ui/core@^4.12.3": +"@material-ui/core@^4.12.3": version "4.12.3" resolved "https://registry.yarnpkg.com/@material-ui/core/-/core-4.12.3.tgz#80d665caf0f1f034e52355c5450c0e38b099d3ca" integrity sha512-sdpgI/PL56QVsEJldwEe4FFaFTLUqN+rd7sSZiRCdx2E/C7z5yK0y/khAWVBH24tXwto7I1hCzNWfJGZIYJKnw== @@ -1768,7 +1940,7 @@ react-is "^16.8.0 || ^17.0.0" react-transition-group "^4.4.0" -"@material-ui/icons@^4.11.2", "@material-ui/icons@^4.9.1": +"@material-ui/icons@^4.11.2": version "4.11.2" resolved "https://registry.yarnpkg.com/@material-ui/icons/-/icons-4.11.2.tgz#b3a7353266519cd743b6461ae9fdfcb1b25eb4c5" integrity sha512-fQNsKX2TxBmqIGJCSi3tGTO/gZ+eJgWmMJkgDiOfyNaunNaxcklJQFaFogYcFl0qFuaEz1qaXYXboa/bUXVSOQ== @@ -1832,6 +2004,134 @@ prop-types "^15.7.2" react-is "^16.8.0 || ^17.0.0" +"@mui/core@5.0.0-alpha.48": + version "5.0.0-alpha.48" + resolved "https://registry.yarnpkg.com/@mui/core/-/core-5.0.0-alpha.48.tgz#ed9517bd3d2c2da12142f1958df2503567be459a" + integrity sha512-H/QQwKsr2EqPAnP35DGDpWihk5BOFYGhO52rIHb3XKOfoUjDCrCHBy2kvr3dLWJDmJXr/QzYj3AX10n5XzlaMg== + dependencies: + "@babel/runtime" "^7.15.4" + "@emotion/is-prop-valid" "^1.1.0" + "@mui/utils" "^5.0.1" + clsx "^1.1.1" + prop-types "^15.7.2" + react-is "^17.0.2" + +"@mui/icons-material@^5.0.1": + version "5.0.1" + resolved "https://registry.yarnpkg.com/@mui/icons-material/-/icons-material-5.0.1.tgz#fb7ffeba0b3604aab4a9b91644d2fc1aabb3b4f1" + integrity sha512-AZehR/Uvi9VodsNPk9ae1lENKrf1evqx9suiP6VIqu7NxjZOlw/m/yA2gRAMmLEmIGr7EChfi/wcXuq6BpM9vw== + dependencies: + "@babel/runtime" "^7.15.4" + +"@mui/lab@^5.0.0-alpha.48": + version "5.0.0-alpha.48" + resolved "https://registry.yarnpkg.com/@mui/lab/-/lab-5.0.0-alpha.48.tgz#e48c95e9f11351a76a672095594aeb2453d7414d" + integrity sha512-ukYcx1ReSy4taQBMIPTkOaSz+CwgxYih3XwTCGTv84atRWMFhfqJO3Ofe8rQ5/innMDbBlSPkjaiMSag8d3QeQ== + dependencies: + "@babel/runtime" "^7.15.4" + "@date-io/date-fns" "^2.10.6" + "@date-io/dayjs" "^2.10.6" + "@date-io/luxon" "^2.10.6" + "@date-io/moment" "^2.10.6" + "@mui/core" "5.0.0-alpha.48" + "@mui/system" "^5.0.1" + "@mui/utils" "^5.0.1" + clsx "^1.1.1" + prop-types "^15.7.2" + react-is "^17.0.2" + react-transition-group "^4.4.2" + rifm "^0.12.0" + +"@mui/material@^5.0.1": + version "5.0.1" + resolved "https://registry.yarnpkg.com/@mui/material/-/material-5.0.1.tgz#5690cd5bf7d9de48008269c89b22c7d7495cbc6c" + integrity sha512-+/JJzRcORUf5MiZnzuqsPFRgxm3/0CUi1wE97ZQ2y7r+EnDVsjJLcjAH9Q9GY3k9zkPIpYb9Hig/+HT6AGZRnQ== + dependencies: + "@babel/runtime" "^7.15.4" + "@mui/core" "5.0.0-alpha.48" + "@mui/system" "^5.0.1" + "@mui/types" "^7.0.0" + "@mui/utils" "^5.0.1" + "@popperjs/core" "^2.4.4" + "@types/react-transition-group" "^4.4.3" + clsx "^1.1.1" + csstype "^3.0.9" + hoist-non-react-statics "^3.3.2" + prop-types "^15.7.2" + react-is "^17.0.2" + react-transition-group "^4.4.2" + +"@mui/private-theming@^5.0.1": + version "5.0.1" + resolved "https://registry.yarnpkg.com/@mui/private-theming/-/private-theming-5.0.1.tgz#50a0ea6ad5a8d1d78072859c4bdaaa6b6584d986" + integrity sha512-R8Cf2+32cG1OXFAqTighA5Mx9R5BQ57cN1ZVaNgfgdbI87Yig2fVMdFSPrw3txcjKlnwsvFJF8AdwQMqq1tJ3Q== + dependencies: + "@babel/runtime" "^7.15.4" + "@mui/utils" "^5.0.1" + prop-types "^15.7.2" + +"@mui/styled-engine@^5.0.1": + version "5.0.1" + resolved "https://registry.yarnpkg.com/@mui/styled-engine/-/styled-engine-5.0.1.tgz#401e3e0ff846ad1b1e7e097c8050b36d7b68343e" + integrity sha512-j40nCbaKr1HAZYqpX61XvZYsadYskjo3u6+pRFFaewSViAkkD1rjjbubpnh15nqVfYmijtHMZJ9/l1x1hamvfQ== + dependencies: + "@babel/runtime" "^7.15.4" + "@emotion/cache" "^11.4.0" + prop-types "^15.7.2" + +"@mui/styles@^5.0.1": + version "5.0.1" + resolved "https://registry.yarnpkg.com/@mui/styles/-/styles-5.0.1.tgz#1634d08d892b5c7e85c9f84e4fc8bc02a5fb0f7a" + integrity sha512-hCtR2ZVOkoIhpTan02I4UEShnZxe59WwhKRJqauMs/addXByhAHHCNheTdiV++Irl/fyyFObmzPM0CUD3q6FIA== + dependencies: + "@babel/runtime" "^7.15.4" + "@emotion/hash" "^0.8.0" + "@mui/private-theming" "^5.0.1" + "@mui/types" "^7.0.0" + "@mui/utils" "^5.0.1" + clsx "^1.1.1" + csstype "^3.0.9" + hoist-non-react-statics "^3.3.2" + jss "^10.8.0" + jss-plugin-camel-case "^10.8.0" + jss-plugin-default-unit "^10.8.0" + jss-plugin-global "^10.8.0" + jss-plugin-nested "^10.8.0" + jss-plugin-props-sort "^10.8.0" + jss-plugin-rule-value-function "^10.8.0" + jss-plugin-vendor-prefixer "^10.8.0" + prop-types "^15.7.2" + +"@mui/system@^5.0.1": + version "5.0.1" + resolved "https://registry.yarnpkg.com/@mui/system/-/system-5.0.1.tgz#2a8592d116c5a05b6991316d772937d100fc7e0a" + integrity sha512-pGNKUpjK5hm4apZAUZu7LugemBPoZnNvNNCI2miI/BXxqyx41mL9+iT9p6Qe9uDOh8Z6GUbLIzvOjSTP+ECRZw== + dependencies: + "@babel/runtime" "^7.15.4" + "@mui/private-theming" "^5.0.1" + "@mui/styled-engine" "^5.0.1" + "@mui/types" "^7.0.0" + "@mui/utils" "^5.0.1" + clsx "^1.1.1" + csstype "^3.0.9" + prop-types "^15.7.2" + +"@mui/types@^7.0.0": + version "7.0.0" + resolved "https://registry.yarnpkg.com/@mui/types/-/types-7.0.0.tgz#a7398502bc9c508875aafcbe28aea599b2c3d203" + integrity sha512-M/tkF2pZ4uoPhZ8pnNhlVnOFtz6F3dnYKIsnj8MuXKT6d26IE2u0UjA8B0275ggN74dR9rlHG5xJt5jgDx/Ung== + +"@mui/utils@^5.0.1": + version "5.0.1" + resolved "https://registry.yarnpkg.com/@mui/utils/-/utils-5.0.1.tgz#d4f0f41b82db6ac273920a1b5b6a4de7879271f5" + integrity sha512-GWO104N+o9KG5fKiTEYnAg7kONKEg3vLN+VROAU0f3it6lFGLCVPcQYex/1gJ4QAy96u6Ez8/Hmmhi1+3cX0tQ== + dependencies: + "@babel/runtime" "^7.15.4" + "@types/prop-types" "^15.7.4" + "@types/react-is" "^16.7.1 || ^17.0.0" + prop-types "^15.7.2" + react-is "^17.0.2" + "@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" @@ -1881,27 +2181,15 @@ schema-utils "^2.6.5" source-map "^0.7.3" -"@reach/router@^1.3.3": - version "1.3.4" - resolved "https://registry.yarnpkg.com/@reach/router/-/router-1.3.4.tgz#d2574b19370a70c80480ed91f3da840136d10f8c" - integrity sha512-+mtn9wjlB9NN2CNnnC/BRYtwdKBfSyyasPYraNAyvaV1occr/5NnB4CVzjEZipNHwYebQwcndGUmpFzxAUoqSA== - dependencies: - create-react-context "0.3.0" - invariant "^2.2.3" - prop-types "^15.6.1" - react-lifecycles-compat "^3.0.4" - -"@rematch/core@^2.0.0": - version "2.1.0" - resolved "https://registry.yarnpkg.com/@rematch/core/-/core-2.1.0.tgz#e067ed78a6895d17e3cc2e15aa0db5148c9c6279" - integrity sha512-izr4LlXsHp1gfK8v05FNvqSthX64cCj59/x3tu+3qNXSuSM7d1/YXAlUtBJIoX9RApr+d1mqA7CCAteUjZrdLg== +"@popperjs/core@^2.4.4": + version "2.10.1" + resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.10.1.tgz#728ecd95ab207aab8a9a4e421f0422db329232be" + integrity sha512-HnUhk1Sy9IuKrxEMdIRCxpIqPw6BFsbYSEUO9p/hNw5sMld/+3OLMWQP80F8/db9qsv3qUjs7ZR5bS/R+iinXw== -"@rematch/persist@^2.0.0": - version "2.1.0" - resolved "https://registry.yarnpkg.com/@rematch/persist/-/persist-2.1.0.tgz#11f61567765e014acfa261e9800b9be15100b420" - integrity sha512-xSXyiegkMN5Aso4MgSzpLyiqPAalrjjk5Hc+6NkotUja2+Kn7uPyG8TZ3hBwzyLEK68SeZmY0Mm182ii+B3B1Q== - dependencies: - redux-persist "^6.0.0" +"@react-icons/all-files@^4.1.0": + version "4.1.0" + resolved "https://registry.yarnpkg.com/@react-icons/all-files/-/all-files-4.1.0.tgz#477284873a0821928224b6fc84c62d2534d6650b" + integrity sha512-hxBI2UOuVaI3O/BhQfhtb4kcGn9ft12RWAFVMUeNjqqhLsHvFtzIkFaptBJpFDANTKoDfdVoHTKZDlwKCACbMQ== "@rollup/plugin-node-resolve@^7.1.1": version "7.1.3" @@ -2221,14 +2509,6 @@ dependencies: "@types/node" "*" -"@types/hoist-non-react-statics@^3.3.0": - version "3.3.1" - resolved "https://registry.yarnpkg.com/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz#1124aafe5118cb591977aeb1ceaaed1070eb039f" - integrity sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA== - dependencies: - "@types/react" "*" - hoist-non-react-statics "^3.3.0" - "@types/html-minifier-terser@^5.0.0": version "5.1.2" resolved "https://registry.yarnpkg.com/@types/html-minifier-terser/-/html-minifier-terser-5.1.2.tgz#693b316ad323ea97eed6b38ed1a3cc02b1672b57" @@ -2254,9 +2534,9 @@ "@types/istanbul-lib-report" "*" "@types/jest@*": - version "27.0.1" - resolved "https://registry.yarnpkg.com/@types/jest/-/jest-27.0.1.tgz#fafcc997da0135865311bb1215ba16dba6bdf4ca" - integrity sha512-HTLpVXHrY69556ozYkcq47TtQJXpcWAWfkoqz+ZGz2JnmZhzlRjprCIyFnetSy8gpDWwTTGBcRVv1J1I1vBrHw== + version "27.0.2" + resolved "https://registry.yarnpkg.com/@types/jest/-/jest-27.0.2.tgz#ac383c4d4aaddd29bbf2b916d8d105c304a5fcd7" + integrity sha512-4dRxkS/AFX0c5XW6IPMNOydLn2tEhNhJV7DnYK+0bjoJZ+QTmfucBlihX7aoEsh/ocYtkLC73UbnBXBXIxsULA== dependencies: jest-diff "^27.0.0" pretty-format "^27.0.0" @@ -2276,15 +2556,15 @@ resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.173.tgz#9d3b674c67a26cf673756f6aca7b429f237f91ed" integrity sha512-vv0CAYoaEjCw/mLy96GBTnRoZrSxkGE0BKzKimdR8P3OzrNYNvBgtW7p055A+E8C31vXNUhWKoFCbhq7gbyhFg== -"@types/minimatch@*", "@types/minimatch@^3.0.3": +"@types/minimatch@*": version "3.0.5" resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.5.tgz#1001cc5e6a3704b83c236027e77f2f58ea010f40" integrity sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ== "@types/node@*", "@types/node@>=6": - version "16.9.2" - resolved "https://registry.yarnpkg.com/@types/node/-/node-16.9.2.tgz#81f5a039d6ed1941f8cc57506c74e7c2b8fc64b9" - integrity sha512-ZHty/hKoOLZvSz6BtP1g7tc7nUeJhoCf3flLjh8ZEv1vFKBWHXcnMbJMyN/pftSljNyy0kNW/UqI3DccnBnZ8w== + version "16.9.6" + resolved "https://registry.yarnpkg.com/@types/node/-/node-16.9.6.tgz#040a64d7faf9e5d9e940357125f0963012e66f04" + integrity sha512-YHUZhBOMTM3mjFkXVcK+WwAcYmyhe1wL4lfqNtzI0b3qAy7yuSetnM7QJazgE5PFmgVTNGiLOgRFfJMqW7XpSQ== "@types/normalize-package-data@^2.4.0": version "2.4.1" @@ -2301,7 +2581,7 @@ resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.3.2.tgz#fc8c2825e4ed2142473b4a81064e6e081463d1b3" integrity sha512-eI5Yrz3Qv4KPUa/nSIAi0h+qX0XyewOliug5F2QAtuRg6Kjg6jfmxe1GIwoIRhZspD1A0RP8ANrPwvEXXtRFog== -"@types/prop-types@*": +"@types/prop-types@*", "@types/prop-types@^15.7.4": version "15.7.4" resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.4.tgz#fcf7205c25dff795ee79af1e30da2c9790808f11" integrity sha512-rZ5drC/jWjrArrS8BR6SIr4cWpW09RNTYt9AMZo3Jwwif+iacXAqgVjm0B0Bv/S1jhDXKHqRVNCbACkJ89RAnQ== @@ -2311,17 +2591,14 @@ resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.5.tgz#75a2a8e7d8ab4b230414505d92335d1dcb53a6df" integrity sha512-L28j2FcJfSZOnL1WBjDYp2vUHCeIFlyYI/53EwD/rKUBQ7MtUUfbQWiyKJGpcnv4/WgrhWsFKrcPstcAt/J0tQ== -"@types/react-redux@^7.1.16": - version "7.1.18" - resolved "https://registry.yarnpkg.com/@types/react-redux/-/react-redux-7.1.18.tgz#2bf8fd56ebaae679a90ebffe48ff73717c438e04" - integrity sha512-9iwAsPyJ9DLTRH+OFeIrm9cAbIj1i2ANL3sKQFATqnPWRbg+jEFXyZOKHiQK/N86pNRXbb4HRxAxo0SIX1XwzQ== +"@types/react-is@^16.7.1 || ^17.0.0": + version "17.0.2" + resolved "https://registry.yarnpkg.com/@types/react-is/-/react-is-17.0.2.tgz#abc4d910bff5b0bc6b3e1bec57575f6b63fd4e05" + integrity sha512-2+L0ilcAEG8udkDnvx8B0upwXFBbNnVwOsSCTxW3SDOkmar9NyEeLG0ZLa3uOEw9zyYf/fQapcnfXAVmDKlyHw== dependencies: - "@types/hoist-non-react-statics" "^3.3.0" "@types/react" "*" - hoist-non-react-statics "^3.3.0" - redux "^4.0.0" -"@types/react-transition-group@^4.2.0": +"@types/react-transition-group@^4.2.0", "@types/react-transition-group@^4.4.3": version "4.4.3" resolved "https://registry.yarnpkg.com/@types/react-transition-group/-/react-transition-group-4.4.3.tgz#b0994da0a7023d67dbb4a8910a62112bc00d5688" integrity sha512-fUx5muOWSYP8Bw2BUQ9M9RK9+W1XBK/7FLJ8PTQpnpTEkn0ccyMffyEQvan4C3h53gHdx7KE5Qrxi/LnUGQtdg== @@ -2329,9 +2606,9 @@ "@types/react" "*" "@types/react@*": - version "17.0.21" - resolved "https://registry.yarnpkg.com/@types/react/-/react-17.0.21.tgz#069c43177cd419afaab5ce26bb4e9056549f7ea6" - integrity sha512-GzzXCpOthOjXvrAUFQwU/svyxu658cwu00Q9ugujS4qc1zXgLFaO0kS2SLOaMWLt2Jik781yuHCWB7UcYdGAeQ== + version "17.0.24" + resolved "https://registry.yarnpkg.com/@types/react/-/react-17.0.24.tgz#7e1b3f78d0fc53782543f9bce6d949959a5880bd" + integrity sha512-eIpyco99gTH+FTI3J7Oi/OH8MZoFMJuztNRimDOJwH4iGIsKV2qkGnk4M9VzlaVWeEEWLWSQRy0FEA0Kz218cg== dependencies: "@types/prop-types" "*" "@types/scheduler" "*" @@ -2418,33 +2695,33 @@ dependencies: "@types/yargs-parser" "*" -"@types/zen-observable@^0.8.0": +"@types/zen-observable@0.8.3", "@types/zen-observable@^0.8.0": version "0.8.3" resolved "https://registry.yarnpkg.com/@types/zen-observable/-/zen-observable-0.8.3.tgz#781d360c282436494b32fe7d9f7f8e64b3118aa3" integrity sha512-fbF6oTd4sGGy0xjHPKAt+eS2CrxJ3+6gQ3FGcBoIJR2TLAyCkCyI8JqZNy+FeON0AhVgNJoUumVoZQjBFUqHkw== "@typescript-eslint/eslint-plugin@^4.5.0": - version "4.31.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.31.1.tgz#e938603a136f01dcabeece069da5fb2e331d4498" - integrity sha512-UDqhWmd5i0TvPLmbK5xY3UZB0zEGseF+DHPghZ37Sb83Qd3p8ujhvAtkU4OF46Ka5Pm5kWvFIx0cCTBFKo0alA== + version "4.31.2" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.31.2.tgz#9f41efaee32cdab7ace94b15bd19b756dd099b0a" + integrity sha512-w63SCQ4bIwWN/+3FxzpnWrDjQRXVEGiTt9tJTRptRXeFvdZc/wLiz3FQUwNQ2CVoRGI6KUWMNUj/pk63noUfcA== dependencies: - "@typescript-eslint/experimental-utils" "4.31.1" - "@typescript-eslint/scope-manager" "4.31.1" + "@typescript-eslint/experimental-utils" "4.31.2" + "@typescript-eslint/scope-manager" "4.31.2" debug "^4.3.1" functional-red-black-tree "^1.0.1" regexpp "^3.1.0" semver "^7.3.5" tsutils "^3.21.0" -"@typescript-eslint/experimental-utils@4.31.1", "@typescript-eslint/experimental-utils@^4.0.1": - version "4.31.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-4.31.1.tgz#0c900f832f270b88e13e51753647b02d08371ce5" - integrity sha512-NtoPsqmcSsWty0mcL5nTZXMf7Ei0Xr2MT8jWjXMVgRK0/1qeQ2jZzLFUh4QtyJ4+/lPUyMw5cSfeeME+Zrtp9Q== +"@typescript-eslint/experimental-utils@4.31.2", "@typescript-eslint/experimental-utils@^4.0.1": + version "4.31.2" + resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-4.31.2.tgz#98727a9c1e977dd5d20c8705e69cd3c2a86553fa" + integrity sha512-3tm2T4nyA970yQ6R3JZV9l0yilE2FedYg8dcXrTar34zC9r6JB7WyBQbpIVongKPlhEMjhQ01qkwrzWy38Bk1Q== dependencies: "@types/json-schema" "^7.0.7" - "@typescript-eslint/scope-manager" "4.31.1" - "@typescript-eslint/types" "4.31.1" - "@typescript-eslint/typescript-estree" "4.31.1" + "@typescript-eslint/scope-manager" "4.31.2" + "@typescript-eslint/types" "4.31.2" + "@typescript-eslint/typescript-estree" "4.31.2" eslint-scope "^5.1.1" eslint-utils "^3.0.0" @@ -2460,32 +2737,32 @@ eslint-utils "^2.0.0" "@typescript-eslint/parser@^4.5.0": - version "4.31.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-4.31.1.tgz#8f9a2672033e6f6d33b1c0260eebdc0ddf539064" - integrity sha512-dnVZDB6FhpIby6yVbHkwTKkn2ypjVIfAR9nh+kYsA/ZL0JlTsd22BiDjouotisY3Irmd3OW1qlk9EI5R8GrvRQ== + version "4.31.2" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-4.31.2.tgz#54aa75986e3302d91eff2bbbaa6ecfa8084e9c34" + integrity sha512-EcdO0E7M/sv23S/rLvenHkb58l3XhuSZzKf6DBvLgHqOYdL6YFMYVtreGFWirxaU2mS1GYDby3Lyxco7X5+Vjw== dependencies: - "@typescript-eslint/scope-manager" "4.31.1" - "@typescript-eslint/types" "4.31.1" - "@typescript-eslint/typescript-estree" "4.31.1" + "@typescript-eslint/scope-manager" "4.31.2" + "@typescript-eslint/types" "4.31.2" + "@typescript-eslint/typescript-estree" "4.31.2" debug "^4.3.1" -"@typescript-eslint/scope-manager@4.31.1": - version "4.31.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-4.31.1.tgz#0c21e8501f608d6a25c842fcf59541ef4f1ab561" - integrity sha512-N1Uhn6SqNtU2XpFSkD4oA+F0PfKdWHyr4bTX0xTj8NRx1314gBDRL1LUuZd5+L3oP+wo6hCbZpaa1in6SwMcVQ== +"@typescript-eslint/scope-manager@4.31.2": + version "4.31.2" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-4.31.2.tgz#1d528cb3ed3bcd88019c20a57c18b897b073923a" + integrity sha512-2JGwudpFoR/3Czq6mPpE8zBPYdHWFGL6lUNIGolbKQeSNv4EAiHaR5GVDQaLA0FwgcdcMtRk+SBJbFGL7+La5w== dependencies: - "@typescript-eslint/types" "4.31.1" - "@typescript-eslint/visitor-keys" "4.31.1" + "@typescript-eslint/types" "4.31.2" + "@typescript-eslint/visitor-keys" "4.31.2" "@typescript-eslint/types@3.10.1": version "3.10.1" resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-3.10.1.tgz#1d7463fa7c32d8a23ab508a803ca2fe26e758727" integrity sha512-+3+FCUJIahE9q0lDi1WleYzjCwJs5hIsbugIgnbB+dSCYUxl8L6PwmsyOPFZde2hc1DlTo/xnkOgiTLSyAbHiQ== -"@typescript-eslint/types@4.31.1": - version "4.31.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.31.1.tgz#5f255b695627a13401d2fdba5f7138bc79450d66" - integrity sha512-kixltt51ZJGKENNW88IY5MYqTBA8FR0Md8QdGbJD2pKZ+D5IvxjTYDNtJPDxFBiXmka2aJsITdB1BtO1fsgmsQ== +"@typescript-eslint/types@4.31.2": + version "4.31.2" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.31.2.tgz#2aea7177d6d744521a168ed4668eddbd912dfadf" + integrity sha512-kWiTTBCTKEdBGrZKwFvOlGNcAsKGJSBc8xLvSjSppFO88AqGxGNYtF36EuEYG6XZ9vT0xX8RNiHbQUKglbSi1w== "@typescript-eslint/typescript-estree@3.10.1": version "3.10.1" @@ -2501,13 +2778,13 @@ semver "^7.3.2" tsutils "^3.17.1" -"@typescript-eslint/typescript-estree@4.31.1": - version "4.31.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-4.31.1.tgz#4a04d5232cf1031232b7124a9c0310b577a62d17" - integrity sha512-EGHkbsUvjFrvRnusk6yFGqrqMBTue5E5ROnS5puj3laGQPasVUgwhrxfcgkdHNFECHAewpvELE1Gjv0XO3mdWg== +"@typescript-eslint/typescript-estree@4.31.2": + version "4.31.2" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-4.31.2.tgz#abfd50594d8056b37e7428df3b2d185ef2d0060c" + integrity sha512-ieBq8U9at6PvaC7/Z6oe8D3czeW5d//Fo1xkF/s9394VR0bg/UaMYPdARiWyKX+lLEjY3w/FNZJxitMsiWv+wA== dependencies: - "@typescript-eslint/types" "4.31.1" - "@typescript-eslint/visitor-keys" "4.31.1" + "@typescript-eslint/types" "4.31.2" + "@typescript-eslint/visitor-keys" "4.31.2" debug "^4.3.1" globby "^11.0.3" is-glob "^4.0.1" @@ -2521,12 +2798,12 @@ dependencies: eslint-visitor-keys "^1.1.0" -"@typescript-eslint/visitor-keys@4.31.1": - version "4.31.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-4.31.1.tgz#f2e7a14c7f20c4ae07d7fc3c5878c4441a1da9cc" - integrity sha512-PCncP8hEqKw6SOJY+3St4LVtoZpPPn+Zlpm7KW5xnviMhdqcsBty4Lsg4J/VECpJjw1CkROaZhH4B8M1OfnXTQ== +"@typescript-eslint/visitor-keys@4.31.2": + version "4.31.2" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-4.31.2.tgz#7d5b4a4705db7fe59ecffb273c1d082760f635cc" + integrity sha512-PrBId7EQq2Nibns7dd/ch6S6/M4/iwLM9McbgeEbCXfxdwRUNxJ4UNreJ6Gh3fI2GNKNrWnQxKL7oCPmngKBug== dependencies: - "@typescript-eslint/types" "4.31.1" + "@typescript-eslint/types" "4.31.2" eslint-visitor-keys "^2.0.0" "@webassemblyjs/ast@1.9.0": @@ -2682,6 +2959,13 @@ "@types/node" ">=6" tslib "^1.9.3" +"@wry/context@^0.6.0": + version "0.6.1" + resolved "https://registry.yarnpkg.com/@wry/context/-/context-0.6.1.tgz#c3c29c0ad622adb00f6a53303c4f965ee06ebeb2" + integrity sha512-LOmVnY1iTU2D8tv4Xf6MVMZZ+juIJ87Kt/plMijjN20NMAXGmH4u8bS1t0uT74cZ5gwpocYueV58YwyI8y+GKw== + dependencies: + tslib "^2.3.0" + "@wry/equality@^0.1.2", "@wry/equality@^0.1.9": version "0.1.11" resolved "https://registry.yarnpkg.com/@wry/equality/-/equality-0.1.11.tgz#35cb156e4a96695aa81a9ecc4d03787bc17f1790" @@ -2689,6 +2973,20 @@ dependencies: tslib "^1.9.3" +"@wry/equality@^0.5.0": + version "0.5.2" + resolved "https://registry.yarnpkg.com/@wry/equality/-/equality-0.5.2.tgz#72c8a7a7d884dff30b612f4f8464eba26c080e73" + integrity sha512-oVMxbUXL48EV/C0/M7gLVsoK6qRHPS85x8zECofEZOVvxGmIPLA9o5Z27cc2PoAyZz1S2VoM2A7FLAnpfGlneA== + dependencies: + tslib "^2.3.0" + +"@wry/trie@^0.3.0": + version "0.3.1" + resolved "https://registry.yarnpkg.com/@wry/trie/-/trie-0.3.1.tgz#2279b790f15032f8bcea7fc944d27988e5b3b139" + integrity sha512-WwB53ikYudh9pIorgxrkHKrQZcCqNM/Q/bDzZBffEaGUKGuHrRb3zZUT9Sh2qw9yogC7SsdRmQ1ER0pqvd3bfw== + dependencies: + tslib "^2.3.0" + "@xtuc/ieee754@^1.2.0": version "1.2.0" resolved "https://registry.yarnpkg.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790" @@ -2879,7 +3177,7 @@ ansi-regex@^4.1.0: resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997" integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg== -ansi-regex@^5.0.0: +ansi-regex@^5.0.0, ansi-regex@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== @@ -3048,11 +3346,6 @@ arr-union@^3.1.0: resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" integrity sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ= -array-differ@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/array-differ/-/array-differ-3.0.0.tgz#3cbb3d0f316810eafcc47624734237d6aee4ae6b" - integrity sha512-THtfYS6KtME/yIAhKjZ2ul7XI96lQGHRputJQHO80LAWQnuGP4iCIN8vdMRboGbIEYBwU33q8Tch1os2+X0kMg== - array-flatten@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" @@ -3305,7 +3598,7 @@ babel-plugin-jest-hoist@^26.6.2: "@types/babel__core" "^7.0.0" "@types/babel__traverse" "^7.0.6" -babel-plugin-macros@2.8.0: +babel-plugin-macros@2.8.0, babel-plugin-macros@^2.6.1: version "2.8.0" resolved "https://registry.yarnpkg.com/babel-plugin-macros/-/babel-plugin-macros-2.8.0.tgz#0f958a7cc6556b1e65344465d99111a1e5e10138" integrity sha512-SEP5kJpfGYqYKpBrj5XU3ahw5p5GOHJ0U5ssOSQ/WBVdwkD2Dzlce95exQTs3jOVWPPKLBN2rlEWkCK7dSmLvg== @@ -3329,12 +3622,12 @@ babel-plugin-polyfill-corejs2@^0.2.2: semver "^6.1.1" babel-plugin-polyfill-corejs3@^0.2.2: - version "0.2.4" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.2.4.tgz#68cb81316b0e8d9d721a92e0009ec6ecd4cd2ca9" - integrity sha512-z3HnJE5TY/j4EFEa/qpQMSbcUJZ5JQi+3UFjXzn6pQCmIKc5Ug5j98SuYyH+m4xQnvKlMDIW4plLfgyVnd0IcQ== + version "0.2.5" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.2.5.tgz#2779846a16a1652244ae268b1e906ada107faf92" + integrity sha512-ninF5MQNwAX9Z7c9ED+H2pGt1mXdP4TqzlHKyPIYmJIYz0N+++uwdM7RnJukklhzJ54Q84vA4ZJkgs7lu5vqcw== dependencies: "@babel/helper-define-polyfill-provider" "^0.2.2" - core-js-compat "^3.14.0" + core-js-compat "^3.16.2" babel-plugin-polyfill-regenerator@^0.2.2: version "0.2.2" @@ -3713,15 +4006,15 @@ browserslist@4.14.2: node-releases "^1.1.61" browserslist@^4.0.0, browserslist@^4.12.0, browserslist@^4.16.6, browserslist@^4.17.0, browserslist@^4.3.4, browserslist@^4.6.2, browserslist@^4.6.4: - version "4.17.0" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.17.0.tgz#1fcd81ec75b41d6d4994fb0831b92ac18c01649c" - integrity sha512-g2BJ2a0nEYvEFQC208q8mVAhfNwpZ5Mu8BwgtCdZKO3qx98HChmeg448fPdUzld8aFmfLgVh7yymqV+q1lJZ5g== + version "4.17.1" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.17.1.tgz#a98d104f54af441290b7d592626dd541fa642eb9" + integrity sha512-aLD0ZMDSnF4lUt4ZDNgqi5BUn9BZ7YdQdI/cYlILrhdSSZJLU9aNZoD5/NBmM4SK34APB2e83MOsRt1EnkuyaQ== dependencies: - caniuse-lite "^1.0.30001254" - colorette "^1.3.0" - electron-to-chromium "^1.3.830" + caniuse-lite "^1.0.30001259" + electron-to-chromium "^1.3.846" escalade "^3.1.1" - node-releases "^1.1.75" + nanocolors "^0.1.5" + node-releases "^1.1.76" bs58@4.0.1, bs58@^4.0.1: version "4.0.1" @@ -3934,10 +4227,12 @@ caniuse-api@^3.0.0: lodash.memoize "^4.1.2" lodash.uniq "^4.5.0" -caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000981, caniuse-lite@^1.0.30001109, caniuse-lite@^1.0.30001125, caniuse-lite@^1.0.30001254: - version "1.0.30001258" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001258.tgz#b604eed80cc54a578e4bf5a02ae3ed49f869d252" - integrity sha512-RBByOG6xWXUp0CR2/WU2amXz3stjKpSl5J1xU49F1n2OxD//uBZO4wCKUiG+QMGf7CHGfDDcqoKriomoGVxTeA== +caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000981, caniuse-lite@^1.0.30001109, caniuse-lite@^1.0.30001125, caniuse-lite@^1.0.30001259: + version "1.0.30001260" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001260.tgz#e3be3f34ddad735ca4a2736fa9e768ef34316270" + integrity sha512-Fhjc/k8725ItmrvW5QomzxLeojewxvqiYCKeFcfFEhut28IVLdpHU19dneOmltZQIE5HNbawj1HYD+1f2bM1Dg== + dependencies: + nanocolors "^0.1.0" capture-exit@^2.0.0: version "2.0.0" @@ -3977,7 +4272,7 @@ chalk@^3.0.0: ansi-styles "^4.1.0" supports-color "^7.1.0" -chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.1: +chalk@^4.0.0, chalk@^4.1.0: version "4.1.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== @@ -4213,7 +4508,7 @@ color@^3.0.0: color-convert "^1.9.3" color-string "^1.6.0" -colorette@^1.2.1, colorette@^1.2.2, colorette@^1.3.0, colorette@^1.4.0: +colorette@^1.2.1, colorette@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.4.0.tgz#5190fbb87276259a86ad700bff2c6d6faa3fca40" integrity sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g== @@ -4235,10 +4530,10 @@ commander@^4.0.0, commander@^4.1.1: resolved "https://registry.yarnpkg.com/commander/-/commander-4.1.1.tgz#9fd602bd936294e9e9ef46a3f4d6964044b18068" integrity sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA== -commander@^7.2.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7" - integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw== +commander@^6.2.0: + version "6.2.1" + resolved "https://registry.yarnpkg.com/commander/-/commander-6.2.1.tgz#0792eb682dfbc325999bb2b84fddddba110ac73c" + integrity sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA== common-tags@^1.8.0: version "1.8.0" @@ -4250,6 +4545,11 @@ commondir@^1.0.1: resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" integrity sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs= +compare-versions@^3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/compare-versions/-/compare-versions-3.6.0.tgz#1a5689913685e5a87637b8d3ffca75514ec41d62" + integrity sha512-W6Af2Iw1z4CB7q4uU4hv646dW9GQuBM+YpC0UvUCWSD8w90SJjp+ujJuXaEMtAXBtSqGfMPuFOVn4/+FlaqfBA== + component-emitter@^1.2.1: version "1.3.0" resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0" @@ -4310,16 +4610,6 @@ concat-stream@^1.5.0: readable-stream "^2.2.2" typedarray "^0.0.6" -concat-stream@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-2.0.0.tgz#414cf5af790a48c60ab9be4527d56d5e41133cb1" - integrity sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A== - dependencies: - buffer-from "^1.0.0" - inherits "^2.0.3" - readable-stream "^3.0.2" - typedarray "^0.0.6" - confusing-browser-globals@^1.0.10: version "1.0.10" resolved "https://registry.yarnpkg.com/confusing-browser-globals/-/confusing-browser-globals-1.0.10.tgz#30d1e7f3d1b882b25ec4933d1d1adac353d20a59" @@ -4379,7 +4669,7 @@ convert-source-map@^0.3.3: resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-0.3.5.tgz#f1d802950af7dd2631a1febe0596550c86ab3190" integrity sha1-8dgClQr33SYxof6+BZZVDIarMZA= -convert-source-map@^1.1.0, convert-source-map@^1.4.0, convert-source-map@^1.6.0, convert-source-map@^1.7.0: +convert-source-map@^1.1.0, convert-source-map@^1.4.0, convert-source-map@^1.5.0, convert-source-map@^1.6.0, convert-source-map@^1.7.0: version "1.8.0" resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.8.0.tgz#f3373c32d21b4d780dd8004514684fb791ca4369" integrity sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA== @@ -4418,28 +4708,28 @@ copy-descriptor@^0.1.0: resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= -core-js-compat@^3.14.0, core-js-compat@^3.16.0, core-js-compat@^3.6.2: - version "3.17.3" - resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.17.3.tgz#b39c8e4dec71ecdc735c653ce5233466e561324e" - integrity sha512-+in61CKYs4hQERiADCJsdgewpdl/X0GhEX77pjKgbeibXviIt2oxEjTc8O2fqHX8mDdBrDvX8MYD/RYsBv4OiA== +core-js-compat@^3.16.0, core-js-compat@^3.16.2, core-js-compat@^3.6.2: + version "3.18.0" + resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.18.0.tgz#fb360652201e8ac8da812718c008cd0482ed9b42" + integrity sha512-tRVjOJu4PxdXjRMEgbP7lqWy1TWJu9a01oBkn8d+dNrhgmBwdTkzhHZpVJnEmhISLdoJI1lX08rcBcHi3TZIWg== dependencies: browserslist "^4.17.0" semver "7.0.0" core-js-pure@^3.16.0: - version "3.17.3" - resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.17.3.tgz#98ea3587188ab7ef4695db6518eeb71aec42604a" - integrity sha512-YusrqwiOTTn8058JDa0cv9unbXdIiIgcgI9gXso0ey4WgkFLd3lYlV9rp9n7nDCsYxXsMDTjA4m1h3T348mdlQ== + version "3.18.0" + resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.18.0.tgz#e5187347bae66448c9e2d67c01c34c4df3261dc5" + integrity sha512-ZnK+9vyuMhKulIGqT/7RHGRok8RtkHMEX/BGPHkHx+ouDkq+MUvf9mfIgdqhpmPDu8+V5UtRn/CbCRc9I4lX4w== core-js@^2.4.0, core-js@^2.6.5: version "2.6.12" resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.12.tgz#d9333dfa7b065e347cc5682219d6f690859cc2ec" integrity sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ== -core-js@^3.6.5: - version "3.17.3" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.17.3.tgz#8e8bd20e91df9951e903cabe91f9af4a0895bc1e" - integrity sha512-lyvajs+wd8N1hXfzob1LdOCCHFU4bGMbqqmLn1Q4QlCpDqWPpGf+p0nj+LNrvDDG33j0hZXw2nsvvVpHysxyNw== +core-js@^3.15.2, core-js@^3.6.5: + version "3.18.0" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.18.0.tgz#9af3f4a6df9ba3428a3fb1b171f1503b3f40cc49" + integrity sha512-WJeQqq6jOYgVgg4NrXKL0KLQhi0CT4ZOCvFL+3CQ5o7I6J8HkT5wd53EadMfqTDp1so/MT1J+w2ujhWcCJtN7w== core-util-is@~1.0.0: version "1.0.3" @@ -4539,14 +4829,6 @@ create-react-class@^15.6.2: loose-envify "^1.3.1" object-assign "^4.1.1" -create-react-context@0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/create-react-context/-/create-react-context-0.3.0.tgz#546dede9dc422def0d3fc2fe03afe0bc0f4f7d8c" - integrity sha512-dNldIoSuNSvlTJ7slIKC/ZFGKexBMBrrcc+TTe1NdmROnaASuLPvqpwj9v4XS4uXZ8+YPu0sNmShX2rXI5LNsw== - dependencies: - gud "^1.0.0" - warning "^4.0.3" - cross-fetch@^3.0.4: version "3.1.4" resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.1.4.tgz#9723f3a3a247bf8b89039f3a380a9244e8fa2f39" @@ -4554,7 +4836,7 @@ cross-fetch@^3.0.4: dependencies: node-fetch "2.6.1" -cross-spawn@7.0.3, cross-spawn@^7.0.0, cross-spawn@^7.0.2, cross-spawn@^7.0.3: +cross-spawn@7.0.3, cross-spawn@^7.0.0, cross-spawn@^7.0.2: version "7.0.3" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== @@ -4873,11 +5155,18 @@ csstype@^2.5.2: resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.18.tgz#980a8b53085f34af313410af064f2bd241784218" integrity sha512-RSU6Hyeg14am3Ah4VZEmeX8H7kLwEEirXe6aU2IPfKNvhXwTflK5HQRDNI0ypQXoqmm+QPyG2IaPuQE5zMwSIQ== -csstype@^3.0.2: +csstype@^3.0.2, csstype@^3.0.9: version "3.0.9" resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.0.9.tgz#6410af31b26bd0520933d02cbc64fce9ce3fbf0b" integrity sha512-rpw6JPxK6Rfg1zLOYCSwle2GFOOsnjmDYDaBwEcwoOg4qlsIVCN789VkBZDJAGi4T07gI4YSutR43t9Zz4Lzuw== +customize-cra@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/customize-cra/-/customize-cra-1.0.0.tgz#73286563631aa08127ad4d30a2e3c89cf4e93c8d" + integrity sha512-DbtaLuy59224U+xCiukkxSq8clq++MOtJ1Et7LED1fLszWe88EoblEYFBJ895sB1mC6B4uu3xPT/IjClELhMbA== + dependencies: + lodash.flow "^3.5.0" + cyclist@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-1.0.1.tgz#596e9698fd0c80e12038c2b82d6eb1b35b6224d9" @@ -4905,6 +5194,11 @@ data-urls@^2.0.0: whatwg-mimetype "^2.3.0" whatwg-url "^8.0.0" +date-fns@^2.24.0: + version "2.24.0" + resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.24.0.tgz#7d86dc0d93c87b76b63d213b4413337cfd1c105d" + integrity sha512-6ujwvwgPID6zbI0o7UbURi2vlLDR9uP26+tW6Lg+Ji3w7dd0i3DOcjcClLjLPranT60SSEFBwdSyYwn/ZkPIuw== + 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" @@ -4912,7 +5206,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.1, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1: +debug@4, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.2.0, debug@^4.3.1: version "4.3.2" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.2.tgz#f0a49c18ac8779e31d4a0c6029dfb76873c7428b" integrity sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw== @@ -5300,10 +5594,10 @@ ejs@^2.6.1: resolved "https://registry.yarnpkg.com/ejs/-/ejs-2.7.4.tgz#48661287573dcc53e366c7a1ae52c3a120eec9ba" integrity sha512-7vmuyh5+kuUyJKePhQfRQBhXV5Ce+RnaeeQArKu1EAMpL3WbgMt5WG6uQZpEVvYSSsxMXRKOewtDk9RaTKXRlA== -electron-to-chromium@^1.3.564, electron-to-chromium@^1.3.830: - version "1.3.842" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.842.tgz#641e414012dded277468892c0156cb01984f4f6f" - integrity sha512-P/nDMPIYdb2PyqCQwhTXNi5JFjX1AsDVR0y6FrHw752izJIAJ+Pn5lugqyBq4tXeRSZBMBb2ZGvRGB1djtELEQ== +electron-to-chromium@^1.3.564, electron-to-chromium@^1.3.846: + version "1.3.849" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.849.tgz#45a65a392565abc5b864624b9753393336426f4b" + integrity sha512-RweyW60HPOqIcxoKTGr38Yvtf2aliSUqX8dB3e9geJ0Bno0YLjcOX5F7/DPVloBkJWaPZ7xOM1A0Yme2T1A34w== elliptic@6.5.0: version "6.5.0" @@ -5552,7 +5846,7 @@ error-stack-parser@^2.0.6: dependencies: stackframe "^1.1.1" -es-abstract@^1.17.2, es-abstract@^1.18.0-next.1, es-abstract@^1.18.0-next.2, es-abstract@^1.18.2: +es-abstract@^1.17.2, es-abstract@^1.18.0-next.1, es-abstract@^1.18.0-next.2, es-abstract@^1.18.1, es-abstract@^1.18.2: version "1.18.6" resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.18.6.tgz#2c44e3ea7a6255039164d26559777a6d978cb456" integrity sha512-kAeIT4cku5eNLNuUKhlmtuk1/TRZvQoYccn6TO0cSVdf1kzB0T7+dYuVK9MWM7l+/53W2Q8M7N2c6MQvhXFcUQ== @@ -5653,7 +5947,7 @@ escodegen@^2.0.0: optionalDependencies: source-map "~0.6.1" -eslint-config-prettier@^8.3.0: +eslint-config-prettier@^8.1.0: version "8.3.0" resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-8.3.0.tgz#f7471b20b6fe8a9a9254cc684454202886a2dd7a" integrity sha512-BgZuLUSeKzvlL/VUjx/Yb787VQ26RU3gGjA3iiFvdsp/2bMfVIWUVP7tjxtjS0e+HP409cPlPvNkQloz8C91ew== @@ -5680,7 +5974,7 @@ eslint-config-standard@16.0.2: resolved "https://registry.yarnpkg.com/eslint-config-standard/-/eslint-config-standard-16.0.2.tgz#71e91727ac7a203782d0a5ca4d1c462d14e234f6" integrity sha512-fx3f1rJDsl9bY7qzyX8SAtP8GBSk6MfXFaTfaGgk12aAYW4gJSyRm7dM790L6cbXv63fvjY4XeSzXnb4WM+SKw== -eslint-config-standard@^16.0.3: +eslint-config-standard@^16.0.2: version "16.0.3" resolved "https://registry.yarnpkg.com/eslint-config-standard/-/eslint-config-standard-16.0.3.tgz#6c8761e544e96c531ff92642eeb87842b8488516" integrity sha512-x4fmJL5hGqNJKGHSjnLdgA6U6h1YW/G2dW9fA+cyVur4SK6lyue8+UgNKWlZtUDTXvgKDD/Oa3GQjmB5kjtVvg== @@ -5781,7 +6075,7 @@ eslint-plugin-jsx-a11y@^6.3.1: jsx-ast-utils "^3.1.0" language-tags "^1.0.5" -eslint-plugin-node@^11.0.0, eslint-plugin-node@~11.1.0: +eslint-plugin-node@^11.1.0, eslint-plugin-node@~11.1.0: version "11.1.0" resolved "https://registry.yarnpkg.com/eslint-plugin-node/-/eslint-plugin-node-11.1.0.tgz#c95544416ee4ada26740a30474eefc5402dc671d" integrity sha512-oUwtPJ1W0SKD0Tr+wqu92c5xuCeQqB3hSCHasn/ZgjFdA9iDGNkNf2Zi9ztY7X+hNuMib23LNGRm6+uN+KLE3g== @@ -5793,13 +6087,18 @@ eslint-plugin-node@^11.0.0, eslint-plugin-node@~11.1.0: resolve "^1.10.1" semver "^6.1.0" -eslint-plugin-prettier@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-4.0.0.tgz#8b99d1e4b8b24a762472b4567992023619cb98e0" - integrity sha512-98MqmCJ7vJodoQK359bqQWaxOE0CS8paAz/GgjaZLyex4TTk3g9HugoO89EqWCrFiOqn9EVvcoo7gZzONCWVwQ== +eslint-plugin-prettier@^3.3.1: + version "3.4.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-3.4.1.tgz#e9ddb200efb6f3d05ffe83b1665a716af4a387e5" + integrity sha512-htg25EUYUeIhKHXjOinK4BgCcDwtLHjqaxCDsMy5nbnUMkKFvIhMVCp+5GFUXQ4Nr8lBsPqtGAqBenbpFqAA2g== dependencies: prettier-linter-helpers "^1.0.0" +eslint-plugin-promise@^4.3.1: + version "4.3.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-4.3.1.tgz#61485df2a359e03149fdafc0a68b0e030ad2ac45" + integrity sha512-bY2sGqyptzFBDLh/GMbAxfdJC+b0f23ME63FOE4+Jao0oZ3E1LEwFtWJX/1pGMJLiTtrSSern2CRM/g+dfc0eQ== + eslint-plugin-promise@~4.2.1: version "4.2.1" resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-4.2.1.tgz#845fd8b2260ad8f82564c1222fce44ad71d9418a" @@ -5810,23 +6109,24 @@ eslint-plugin-react-hooks@^4.2.0: resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.2.0.tgz#8c229c268d468956334c943bb45fc860280f5556" integrity sha512-623WEiZJqxR7VdxFCKLI6d6LLpwJkGPYKODnkH3D7WpOG5KM8yWueBd8TLsNAetEJNF5iJmolaAKO3F8yzyVBQ== -eslint-plugin-react@^7.21.5: - version "7.25.2" - resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.25.2.tgz#d567a217d306b76dd110561f28074e2328ae38f8" - integrity sha512-elx4585wgmryanJK4C5IoSKQyVZ+e7H0t2JOOtJNBql0cuercvSShvRReuLBbfx8687yW5yv+UL7pXwMsd6adQ== +eslint-plugin-react@^7.21.5, eslint-plugin-react@^7.22.0: + version "7.26.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.26.0.tgz#3ae019a35d542b98e5af9e2f96b89c232c74b55b" + integrity sha512-dceliS5itjk4EZdQYtLMz6GulcsasguIs+VTXuiC7Q5IPIdGTkyfXVdmsQOqEhlD9MciofH4cMcT1bw1WWNxCQ== dependencies: array-includes "^3.1.3" array.prototype.flatmap "^1.2.4" doctrine "^2.1.0" estraverse "^5.2.0" - has "^1.0.3" jsx-ast-utils "^2.4.1 || ^3.0.0" minimatch "^3.0.4" object.entries "^1.1.4" object.fromentries "^2.0.4" + object.hasown "^1.0.0" object.values "^1.1.4" prop-types "^15.7.2" resolve "^2.0.0-next.3" + semver "^6.3.0" string.prototype.matchall "^4.0.5" eslint-plugin-react@~7.21.5: @@ -5846,11 +6146,6 @@ eslint-plugin-react@~7.21.5: resolve "^1.18.1" string.prototype.matchall "^4.0.2" -eslint-plugin-standard@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-standard/-/eslint-plugin-standard-5.0.0.tgz#c43f6925d669f177db46f095ea30be95476b1ee4" - integrity sha512-eSIXPc9wBM4BrniMzJRBm2uoVuXz2EPa+NXPk2+itrVt+r5SbKFERx/IgrK/HmfjddyKVz2f+j+7gBRvu19xLg== - eslint-plugin-testing-library@^3.9.2: version "3.10.2" resolved "https://registry.yarnpkg.com/eslint-plugin-testing-library/-/eslint-plugin-testing-library-3.10.2.tgz#609ec2b0369da7cf2e6d9edff5da153cc31d87bd" @@ -5893,7 +6188,7 @@ 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== @@ -5910,7 +6205,7 @@ eslint-webpack-plugin@^2.5.2: normalize-path "^3.0.0" schema-utils "^3.0.0" -eslint@^7.11.0: +eslint@^7.11.0, eslint@^7.22.0: version "7.32.0" resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.32.0.tgz#c6d328a14be3fb08c8d1d21e12c02fdb7a2a812d" integrity sha512-VHZ8gX+EDfz+97jGcgyGCyRia/dPOd6Xh9yPv8Bl1+SoaIwD+a/vlrOmGRUyOYu7MwUhc7CxqeaDZU13S4+EpA== @@ -6118,7 +6413,7 @@ execa@^1.0.0: signal-exit "^3.0.0" strip-eof "^1.0.0" -execa@^4.0.0: +execa@^4.0.0, execa@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/execa/-/execa-4.1.0.tgz#4e5491ad1572f2f17a77d388c6c857135b22847a" integrity sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA== @@ -6133,21 +6428,6 @@ execa@^4.0.0: signal-exit "^3.0.2" strip-final-newline "^2.0.0" -execa@^5.0.0: - version "5.1.1" - resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd" - integrity sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg== - dependencies: - cross-spawn "^7.0.3" - get-stream "^6.0.0" - human-signals "^2.1.0" - is-stream "^2.0.0" - merge-stream "^2.0.0" - npm-run-path "^4.0.1" - onetime "^5.1.2" - signal-exit "^3.0.3" - strip-final-newline "^2.0.0" - exit@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" @@ -6215,9 +6495,9 @@ express@^4.17.1: vary "~1.1.2" ext@^1.1.2: - version "1.5.0" - resolved "https://registry.yarnpkg.com/ext/-/ext-1.5.0.tgz#e93b97ae0cb23f8370380f6107d2d2b7887687ad" - integrity sha512-+ONcYoWj/SoQwUofMr94aGu05Ou4FepKi7N7b+O8T4jVfyIsZQV1/xeS8jpaBzF0csAk0KLXoHCxU7cKYZjo1Q== + version "1.6.0" + resolved "https://registry.yarnpkg.com/ext/-/ext-1.6.0.tgz#3871d50641e874cc172e2b53f919842d19db4c52" + integrity sha512-sdBImtzkq2HpkdRLtlLWDa6w4DX22ijZLKx8BMPUuKe1c5lbN6xwQDQCxSfxBQnHZ13ls/FH0MQZx/q/gr6FQg== dependencies: type "^2.5.0" @@ -6438,6 +6718,11 @@ find-cache-dir@^3.3.1: make-dir "^3.0.2" pkg-dir "^4.1.0" +find-root@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/find-root/-/find-root-1.1.0.tgz#abcfc8ba76f708c42a97b3d685b7e9450bfb9ce4" + integrity sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng== + find-up@4.1.0, find-up@^4.0.0, find-up@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" @@ -6460,6 +6745,21 @@ find-up@^3.0.0: dependencies: locate-path "^3.0.0" +find-up@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" + integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== + dependencies: + locate-path "^6.0.0" + path-exists "^4.0.0" + +find-versions@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/find-versions/-/find-versions-4.0.0.tgz#3c57e573bf97769b8cb8df16934b627915da4965" + integrity sha512-wgpWy002tA+wgmO27buH/9KzyEOQnKsG/R0yrcjPT9BOFm0zRBVQbZ95nRGXWMywS8YR5knRbpohio0bcJABxQ== + dependencies: + semver-regex "^3.1.2" + flat-cache@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-2.0.1.tgz#5d296d6f04bda44a4630a301413bdbc2ec085ec0" @@ -6698,11 +6998,6 @@ get-stream@^5.0.0: dependencies: pump "^3.0.0" -get-stream@^6.0.0: - version "6.0.1" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" - integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== - get-symbol-description@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/get-symbol-description/-/get-symbol-description-1.0.0.tgz#7fdb81c900101fbd564dd5f1a30af5aadc1e58d6" @@ -6732,9 +7027,9 @@ glob-parent@^5.0.0, glob-parent@^5.1.2, glob-parent@~5.1.2: is-glob "^4.0.1" glob@^7.0.3, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6: - version "7.1.7" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.7.tgz#3b193e9233f01d42d0b3f78294bbeeb418f94a90" - integrity sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ== + version "7.2.0" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023" + integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q== dependencies: fs.realpath "^1.0.0" inflight "^1.0.4" @@ -6826,7 +7121,7 @@ graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6 resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.8.tgz#e412b8d33f5e006593cbd3cee6df9f2cebbe802a" integrity sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg== -graphql-tag@^2.12.5: +graphql-tag@^2.12.3, graphql-tag@^2.12.5: version "2.12.5" resolved "https://registry.yarnpkg.com/graphql-tag/-/graphql-tag-2.12.5.tgz#5cff974a67b417747d05c8d9f5f3cb4495d0db8f" integrity sha512-5xNhP4063d16Pz3HBtKprutsPrmHZi5IdUGOWRxA2B6VF7BIRGOHZ5WQvDmJXZuPcBg7rYwaFxvQYjqkSdR3TQ== @@ -6834,20 +7129,15 @@ graphql-tag@^2.12.5: tslib "^2.1.0" graphql@^15.5.1: - version "15.5.3" - resolved "https://registry.yarnpkg.com/graphql/-/graphql-15.5.3.tgz#c72349017d5c9f5446a897fe6908b3186db1da00" - integrity sha512-sM+jXaO5KinTui6lbK/7b7H/Knj9BpjGxZ+Ki35v7YbUJxxdBCUqNM0h3CRVU1ZF9t5lNiBzvBCSYPvIwxPOQA== + version "15.6.0" + resolved "https://registry.yarnpkg.com/graphql/-/graphql-15.6.0.tgz#e69323c6a9780a1a4b9ddf7e35ca8904bb04df02" + integrity sha512-WJR872Zlc9hckiEPhXgyUftXH48jp2EjO5tgBBOyNMRJZ9fviL2mJBD6CAysk6N5S0r9BTs09Qk39nnJBkvOXQ== growly@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/growly/-/growly-1.3.0.tgz#f10748cbe76af964b7c96c93c6bcc28af120c081" integrity sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE= -gud@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/gud/-/gud-1.0.0.tgz#a489581b17e6a70beca9abe3ae57de7a499852c0" - integrity sha512-zGEOVKFM5sVPPrYs7J5/hYEw2Pof8KCyOwyhG8sAF26mCAeUFAcYPu1mwB7hhpIP29zOIBaDqwuHdLp0jvZXjw== - gzip-size@5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/gzip-size/-/gzip-size-5.1.1.tgz#cb9bee692f87c0612b232840a873904e4c135274" @@ -6958,6 +7248,16 @@ hex-color-regex@^1.1.0: resolved "https://registry.yarnpkg.com/hex-color-regex/-/hex-color-regex-1.1.0.tgz#4c06fccb4602fe2602b3c93df82d7e7dbf1a8a8e" integrity sha512-l9sfDFsuqtOqKDsQdqrMRk0U85RZc0RtOR9yPI7mRVOa4FsR/BVnZ0shmQRM96Ji99kYZP/7hn1cedc1+ApsTQ== +highcharts-react-official@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/highcharts-react-official/-/highcharts-react-official-3.0.0.tgz#f2e81ed59d299c3473a0dd5ba5df24028875226a" + integrity sha512-VefJgDY2hkT9gfppsQGrRF2g5u8d9dtfHGcx2/xqiP+PkZXCqalw9xOeKVCRvJKTOh0coiDFwvVjOvB7KaGl4A== + +highcharts@^9.2.2: + version "9.2.2" + resolved "https://registry.yarnpkg.com/highcharts/-/highcharts-9.2.2.tgz#4ace4aa7c4d2b4051115d9be70bfd2038559d656" + integrity sha512-OMEdFCaG626ES1JEcKAvJTpxAOMuchy0XuAplmnOs0Yu7NMd2RMfTLFQ2fCJOxo3ubSdm/RVQwKAWC+5HYThnw== + history@^4.9.0: version "4.10.1" resolved "https://registry.yarnpkg.com/history/-/history-4.10.1.tgz#33371a65e3a83b267434e2b3f3b1b4c58aad4cf3" @@ -6970,6 +7270,13 @@ history@^4.9.0: tiny-warning "^1.0.0" value-equal "^1.0.1" +history@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/history/-/history-5.0.1.tgz#de35025ed08bce0db62364b47ebbf9d97b5eb06a" + integrity sha512-5qC/tFUKfVci5kzgRxZxN5Mf1CV8NmJx9ByaPX0YTLx5Vz3Svh7NYp6eA4CpDq4iA9D0C1t8BNIfvQIrUI3mVw== + dependencies: + "@babel/runtime" "^7.7.6" + hmac-drbg@^1.0.0, hmac-drbg@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" @@ -6979,7 +7286,7 @@ hmac-drbg@^1.0.0, hmac-drbg@^1.0.1: minimalistic-assert "^1.0.0" minimalistic-crypto-utils "^1.0.1" -hoist-non-react-statics@^3.1.0, hoist-non-react-statics@^3.3.0, hoist-non-react-statics@^3.3.2: +hoist-non-react-statics@^3.1.0, hoist-non-react-statics@^3.3.0, hoist-non-react-statics@^3.3.1, hoist-non-react-statics@^3.3.2: version "3.3.2" resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45" integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw== @@ -7166,15 +7473,21 @@ human-signals@^1.1.1: resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-1.1.1.tgz#c5b1cd14f50aeae09ab6c59fe63ba3395fe4dfa3" integrity sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw== -human-signals@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" - integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== - -husky@^7.0.1: - version "7.0.2" - resolved "https://registry.yarnpkg.com/husky/-/husky-7.0.2.tgz#21900da0f30199acca43a46c043c4ad84ae88dff" - integrity sha512-8yKEWNX4z2YsofXAMT7KvA1g8p+GxtB1ffV8XtpAEGuXNAbCV5wdNKH+qTpw8SM9fh4aMPDR+yQuKfgnreyZlg== +husky@4.3.8: + version "4.3.8" + resolved "https://registry.yarnpkg.com/husky/-/husky-4.3.8.tgz#31144060be963fd6850e5cc8f019a1dfe194296d" + integrity sha512-LCqqsB0PzJQ/AlCgfrfzRe3e3+NvmefAdKQhRYpxS4u6clblBoDdzzvHi8fmxKRzvMxPY/1WZWzomPZww0Anow== + dependencies: + chalk "^4.0.0" + ci-info "^2.0.0" + compare-versions "^3.6.0" + cosmiconfig "^7.0.0" + find-versions "^4.0.0" + opencollective-postinstall "^2.0.2" + pkg-dir "^5.0.0" + please-upgrade-node "^3.2.0" + slash "^3.0.0" + which-pm-runs "^1.0.0" hyphenate-style-name@^1.0.3: version "1.0.4" @@ -7205,7 +7518,7 @@ i18next@14.0.1: resolved "https://registry.yarnpkg.com/i18next/-/i18next-14.0.1.tgz#c5f0292ea6389394b6056f597b75f1f9aa03124f" integrity sha512-wsKfQuYsy4RdCaqqN71eDjWMhizhTfQSIBGttEA7vcboQrUfpQlCezrSzrtmoW9F9tmVyNs38iBgLYLMhRSeIQ== -i18next@^20.3.3: +i18next@^20.3.4: version "20.6.1" resolved "https://registry.yarnpkg.com/i18next/-/i18next-20.6.1.tgz#535e5f6e5baeb685c7d25df70db63bf3cc0aa345" integrity sha512-yCMYTMEJ9ihCwEQQ3phLo7I/Pwycf8uAx+sRHwwk5U9Aui/IZYgQRyMqXafQOw5QQ7DM1Z+WyEXWIqSuJHhG2A== @@ -7376,7 +7689,7 @@ internal-slot@^1.0.3: has "^1.0.3" side-channel "^1.0.4" -invariant@^2.2.2, invariant@^2.2.3: +invariant@^2.2.2: version "2.2.4" resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA== @@ -7800,9 +8113,9 @@ isomorphic-ws@^4.0.1: integrity sha512-BhBvN2MBpWTaSHdWRb/bwdZJ1WaehQ2L1KngkCkfLUGF0mAWAT1sQUQacEmQ0jXkFw/czDXPNQSL5u2/Krsz1w== istanbul-lib-coverage@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.0.tgz#f5944a37c70b550b02a78a5c3b2055b280cec8ec" - integrity sha512-UiUIqxMgRDET6eR+o5HbfRYP1l0hqkWOs7vNxC/mggutCMUIhWMm8gAHb8tHlyfD3/l6rlgNA5cKdDzEAf6hEg== + version "3.0.1" + resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.1.tgz#e8900b3ed6069759229cf30f7067388d148aeb5e" + integrity sha512-GvCYYTxaCPqwMjobtVcVKvSHtAGe48MNhGjpK8LtVF8K0ISX7hCKl85LgtuaSneWVyQmaGcW3iXVV3GaZSLpmQ== istanbul-lib-instrument@^4.0.0, istanbul-lib-instrument@^4.0.3: version "4.0.3" @@ -8416,70 +8729,70 @@ jsonfile@^6.0.1: optionalDependencies: graceful-fs "^4.1.6" -jss-plugin-camel-case@^10.5.1: - version "10.7.1" - resolved "https://registry.yarnpkg.com/jss-plugin-camel-case/-/jss-plugin-camel-case-10.7.1.tgz#e7f7097cf97e9deec599cef3275e213452318b93" - integrity sha512-+ioIyWvmAfgDCWXsQcW1NMnLBvRinOVFkSYJUgewQ6TynOcSj5F1bSU23B7z0p1iqK0PPHIU62xY1iNJD33WGA== +jss-plugin-camel-case@^10.5.1, jss-plugin-camel-case@^10.8.0: + version "10.8.0" + resolved "https://registry.yarnpkg.com/jss-plugin-camel-case/-/jss-plugin-camel-case-10.8.0.tgz#575fd849202d36713a6970796458e375754446c7" + integrity sha512-yxlXrXwcCdGw+H4BC187dEu/RFyW8joMcWfj8Rk9UPgWTKu2Xh7Sib4iW3xXjHe/t5phOHF1rBsHleHykWix7g== dependencies: "@babel/runtime" "^7.3.1" hyphenate-style-name "^1.0.3" - jss "10.7.1" + jss "10.8.0" -jss-plugin-default-unit@^10.5.1: - version "10.7.1" - resolved "https://registry.yarnpkg.com/jss-plugin-default-unit/-/jss-plugin-default-unit-10.7.1.tgz#826270e2ee38d7024a281ac67c30d6944f124786" - integrity sha512-tW+dfYVNARBQb/ONzBwd8uyImigyzMiAEDai+AbH5rcHg5h3TtqhAkxx06iuZiT/dZUiFdSKlbe3q9jZGAPIwA== +jss-plugin-default-unit@^10.5.1, jss-plugin-default-unit@^10.8.0: + version "10.8.0" + resolved "https://registry.yarnpkg.com/jss-plugin-default-unit/-/jss-plugin-default-unit-10.8.0.tgz#98db5962e62abbf43f1cc111e62cb70ffb09db59" + integrity sha512-9XJV546cY9zV9OvIE/v/dOaxSi4062VfYQQfwbplRExcsU2a79Yn+qDz/4ciw6P4LV1Naq90U+OffAGRHfNq/Q== dependencies: "@babel/runtime" "^7.3.1" - jss "10.7.1" + jss "10.8.0" -jss-plugin-global@^10.5.1: - version "10.7.1" - resolved "https://registry.yarnpkg.com/jss-plugin-global/-/jss-plugin-global-10.7.1.tgz#9725c46d662aac2e596a0a8741944c060e2b90a1" - integrity sha512-FbxCnu44IkK/bw8X3CwZKmcAnJqjAb9LujlAc/aP0bMSdVa3/MugKQRyeQSu00uGL44feJJDoeXXiHOakBr/Zw== +jss-plugin-global@^10.5.1, jss-plugin-global@^10.8.0: + version "10.8.0" + resolved "https://registry.yarnpkg.com/jss-plugin-global/-/jss-plugin-global-10.8.0.tgz#0c2b0c056087f5846d600f3332eeb7a1a8b9c9f2" + integrity sha512-H/8h/bHd4e7P0MpZ9zaUG8NQSB2ie9rWo/vcCP6bHVerbKLGzj+dsY22IY3+/FNRS8zDmUyqdZx3rD8k4nmH4w== dependencies: "@babel/runtime" "^7.3.1" - jss "10.7.1" + jss "10.8.0" -jss-plugin-nested@^10.5.1: - version "10.7.1" - resolved "https://registry.yarnpkg.com/jss-plugin-nested/-/jss-plugin-nested-10.7.1.tgz#35563a7a710a45307fd6b9742ffada1d72a62eb7" - integrity sha512-RNbICk7FlYKaJyv9tkMl7s6FFfeLA3ubNIFKvPqaWtADK0KUaPsPXVYBkAu4x1ItgsWx67xvReMrkcKA0jSXfA== +jss-plugin-nested@^10.5.1, jss-plugin-nested@^10.8.0: + version "10.8.0" + resolved "https://registry.yarnpkg.com/jss-plugin-nested/-/jss-plugin-nested-10.8.0.tgz#7ef9a815e9c9fbede41a8f52ce75cffb4c3b86d5" + integrity sha512-MhmINZkSxyFILcFBuDoZmP1+wj9fik/b9SsjoaggkGjdvMQCES21mj4K5ZnRGVm448gIXyi9j/eZjtDzhaHUYQ== dependencies: "@babel/runtime" "^7.3.1" - jss "10.7.1" + jss "10.8.0" tiny-warning "^1.0.2" -jss-plugin-props-sort@^10.5.1: - version "10.7.1" - resolved "https://registry.yarnpkg.com/jss-plugin-props-sort/-/jss-plugin-props-sort-10.7.1.tgz#1d12b26048541ed3a2ed1b69f7fc231605728362" - integrity sha512-eyd5FhA+J0QrpqXxO7YNF/HMSXXl4pB0EmUdY4vSJI4QG22F59vQ6AHtP6fSwhmBdQ98Qd9gjfO+RMxcE39P1A== +jss-plugin-props-sort@^10.5.1, jss-plugin-props-sort@^10.8.0: + version "10.8.0" + resolved "https://registry.yarnpkg.com/jss-plugin-props-sort/-/jss-plugin-props-sort-10.8.0.tgz#2a83e8ca80d72828495bad57b485f7d55a33543b" + integrity sha512-VY+Wt5WX5GMsXDmd+Ts8+O16fpiCM81svbox++U3LDbJSM/g9FoMx3HPhwUiDfmgHL9jWdqEuvSl/JAk+mh6mQ== dependencies: "@babel/runtime" "^7.3.1" - jss "10.7.1" + jss "10.8.0" -jss-plugin-rule-value-function@^10.5.1: - version "10.7.1" - resolved "https://registry.yarnpkg.com/jss-plugin-rule-value-function/-/jss-plugin-rule-value-function-10.7.1.tgz#123eb796eb9982f8efa7a7e362daddd90c0c69fe" - integrity sha512-fGAAImlbaHD3fXAHI3ooX6aRESOl5iBt3LjpVjxs9II5u9tzam7pqFUmgTcrip9VpRqYHn8J3gA7kCtm8xKwHg== +jss-plugin-rule-value-function@^10.5.1, jss-plugin-rule-value-function@^10.8.0: + version "10.8.0" + resolved "https://registry.yarnpkg.com/jss-plugin-rule-value-function/-/jss-plugin-rule-value-function-10.8.0.tgz#e011ed180789229e7ea8f75c222d34810bcab520" + integrity sha512-R8N8Ma6Oye1F9HroiUuHhVjpPsVq97uAh+rMI6XwKLqirIu2KFb5x33hPj+vNBMxSHc9jakhf5wG0BbQ7fSDOg== dependencies: "@babel/runtime" "^7.3.1" - jss "10.7.1" + jss "10.8.0" tiny-warning "^1.0.2" -jss-plugin-vendor-prefixer@^10.5.1: - version "10.7.1" - resolved "https://registry.yarnpkg.com/jss-plugin-vendor-prefixer/-/jss-plugin-vendor-prefixer-10.7.1.tgz#217821be2d6dacee31d2d464886760ba7742e19a" - integrity sha512-1UHFmBn7hZNsHXTkLLOL8abRl8vi+D1EVzWD4WmLFj55vawHZfnH1oEz6TUf5Y61XHv0smdHabdXds6BgOXe3A== +jss-plugin-vendor-prefixer@^10.5.1, jss-plugin-vendor-prefixer@^10.8.0: + version "10.8.0" + resolved "https://registry.yarnpkg.com/jss-plugin-vendor-prefixer/-/jss-plugin-vendor-prefixer-10.8.0.tgz#024b6d77be50b68e5dfca2c75f68091d8b722d61" + integrity sha512-G1zD0J8dFwKZQ+GaZaay7A/Tg7lhDw0iEkJ/iFFA5UPuvZFpMprCMQttXcTBhLlhhWnyZ8YPn4yqp+amrhQekw== dependencies: "@babel/runtime" "^7.3.1" css-vendor "^2.0.8" - jss "10.7.1" + jss "10.8.0" -jss@10.7.1, jss@^10.5.1: - version "10.7.1" - resolved "https://registry.yarnpkg.com/jss/-/jss-10.7.1.tgz#16d846e1a22fb42e857b99f9c6a0c5a27341c804" - integrity sha512-5QN8JSVZR6cxpZNeGfzIjqPEP+ZJwJJfZbXmeABNdxiExyO+eJJDy6WDtqTf8SDKnbL5kZllEpAP71E/Lt7PXg== +jss@10.8.0, jss@^10.5.1, jss@^10.8.0: + version "10.8.0" + resolved "https://registry.yarnpkg.com/jss/-/jss-10.8.0.tgz#5063ee73aabd9f228ea3849df7962f0d2e213a42" + integrity sha512-6fAMLJrVQ8epM5ghghxWqCwRR0ZamP2cKbOAtzPudcCMSNdAqtvmzQvljUZYR8OXJIeb/IpZeOXA1sDXms4R1w== dependencies: "@babel/runtime" "^7.3.1" csstype "^3.0.2" @@ -8579,30 +8892,31 @@ lines-and-columns@^1.1.6: resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.1.6.tgz#1c00c743b433cd0a4e80758f7b64a57440d9ff00" integrity sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA= -lint-staged@^11.0.1: - version "11.1.2" - resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-11.1.2.tgz#4dd78782ae43ee6ebf2969cad9af67a46b33cd90" - integrity sha512-6lYpNoA9wGqkL6Hew/4n1H6lRqF3qCsujVT0Oq5Z4hiSAM7S6NksPJ3gnr7A7R52xCtiZMcEUNNQ6d6X5Bvh9w== +lint-staged@^10.5.4: + version "10.5.4" + resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-10.5.4.tgz#cd153b5f0987d2371fc1d2847a409a2fe705b665" + integrity sha512-EechC3DdFic/TdOPgj/RB3FicqE6932LTHCUm0Y2fsD9KGlLB+RwJl2q1IYBIvEsKzDOgn0D4gll+YxG5RsrKg== dependencies: - chalk "^4.1.1" + chalk "^4.1.0" cli-truncate "^2.1.0" - commander "^7.2.0" + commander "^6.2.0" cosmiconfig "^7.0.0" - debug "^4.3.1" + debug "^4.2.0" + dedent "^0.7.0" enquirer "^2.3.6" - execa "^5.0.0" - listr2 "^3.8.2" - log-symbols "^4.1.0" - micromatch "^4.0.4" + execa "^4.1.0" + listr2 "^3.2.2" + log-symbols "^4.0.0" + micromatch "^4.0.2" normalize-path "^3.0.0" please-upgrade-node "^3.2.0" string-argv "0.3.1" stringify-object "^3.3.0" -listr2@^3.8.2: - version "3.12.1" - resolved "https://registry.yarnpkg.com/listr2/-/listr2-3.12.1.tgz#75e515b86c66b60baf253542cc0dced6b60fedaf" - integrity sha512-oB1DlXlCzGPbvWhqYBZUQEPJKqsmebQWofXG6Mpbe3uIvoNl8mctBEojyF13ZyqwQ91clCWXpwsWp+t98K4FOQ== +listr2@^3.2.2: + version "3.12.2" + resolved "https://registry.yarnpkg.com/listr2/-/listr2-3.12.2.tgz#2d55cc627111603ad4768a9e87c9c7bb9b49997e" + integrity sha512-64xC2CJ/As/xgVI3wbhlPWVPx0wfTqbUAkpb7bjDi0thSWMqrf07UFhrfsGoo8YSXmF049Rp9C0cjLC8rZxK9A== dependencies: cli-truncate "^2.1.0" colorette "^1.4.0" @@ -8698,6 +9012,13 @@ locate-path@^5.0.0: dependencies: p-locate "^4.1.0" +locate-path@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" + integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== + dependencies: + p-locate "^5.0.0" + lodash-es@^4.17.15: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.21.tgz#43e626c46e6591b7750beb2b50117390c609e3ee" @@ -8723,7 +9044,7 @@ lodash.debounce@^4.0.8: resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" integrity sha1-gteb/zCmfEAF/9XiUVMArZyk168= -lodash.flow@^3.3.0: +lodash.flow@^3.3.0, lodash.flow@^3.5.0: version "3.5.0" resolved "https://registry.yarnpkg.com/lodash.flow/-/lodash.flow-3.5.0.tgz#87bf40292b8cf83e4e8ce1a3ae4209e20071675a" integrity sha1-h79AKSuM+D5OjOGjrkIJ4gBxZ1o= @@ -8783,7 +9104,7 @@ lodash.uniq@^4.5.0: resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== -log-symbols@^4.1.0: +log-symbols@^4.0.0: version "4.1.0" resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503" integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg== @@ -9195,11 +9516,6 @@ move-concurrently@^1.0.1: rimraf "^2.5.4" run-queue "^1.0.3" -mri@^1.1.5: - version "1.2.0" - resolved "https://registry.yarnpkg.com/mri/-/mri-1.2.0.tgz#6721480fec2a11a4889861115a48b6cbe7cc8f0b" - integrity sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA== - ms@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" @@ -9233,17 +9549,6 @@ multicast-dns@^6.0.1: dns-packet "^1.3.1" thunky "^1.0.2" -multimatch@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/multimatch/-/multimatch-4.0.0.tgz#8c3c0f6e3e8449ada0af3dd29efb491a375191b3" - integrity sha512-lDmx79y1z6i7RNx0ZGCPq1bzJ6ZoDDKbvh7jxr9SJcWLkShMzXrHbYVpTdnhNM5MXpDUxCQ4DgqVttVXlBgiBQ== - dependencies: - "@types/minimatch" "^3.0.3" - array-differ "^3.0.0" - array-union "^2.1.0" - arrify "^2.0.1" - minimatch "^3.0.4" - nan@^2.12.1: version "2.15.0" resolved "https://registry.yarnpkg.com/nan/-/nan-2.15.0.tgz#3f34a473ff18e15c1b5626b62903b5ad6e665fee" @@ -9254,7 +9559,12 @@ nanoclone@^0.2.1: resolved "https://registry.yarnpkg.com/nanoclone/-/nanoclone-0.2.1.tgz#dd4090f8f1a110d26bb32c49ed2f5b9235209ed4" integrity sha512-wynEP02LmIbLpcYw8uBKpcfF6dmg2vcpKqxeH5UcoKEYdExslsdUA4ugFauuaeYdTB76ez6gJW8XAZ6CgkXYxA== -nanoid@^3.1.23: +nanocolors@^0.1.0, nanocolors@^0.1.5: + version "0.1.12" + resolved "https://registry.yarnpkg.com/nanocolors/-/nanocolors-0.1.12.tgz#8577482c58cbd7b5bb1681db4cf48f11a87fd5f6" + integrity sha512-2nMHqg1x5PU+unxX7PGY7AuYxl2qDx7PSrTRjizr8sxdd3l/3hBuWWaki62qmtYm2U5i4Z5E7GbjlyDFhs9/EQ== + +nanoid@^3.1.25: version "3.1.25" resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.25.tgz#09ca32747c0e543f0e1814b7d3793477f9c8e152" integrity sha512-rdwtIXaXCLFAQbnfqDRnI6jaRHp9fTcYBjtFKE8eezcZ7LuLjhUaQGNeMXf1HmRoCH32CLz6XwX0TtxEOS/A3Q== @@ -9337,9 +9647,11 @@ node-fetch@^1.0.1: is-stream "^1.0.1" node-fetch@^2.6.2, node-fetch@~2.6.1: - version "2.6.2" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.2.tgz#986996818b73785e47b1965cc34eb093a1d464d0" - integrity sha512-aLoxToI6RfZ+0NOjmWAgn9+LEd30YCkJKFSyWacNZdEKTit/ZMcKjGkTRo8uWEsnIb/hfKecNPEbln02PdWbcA== + version "2.6.5" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.5.tgz#42735537d7f080a7e5f78b6c549b7146be1742fd" + integrity sha512-mmlIVHJEu5rnIxgEgez6b9GgWXbkZj5YZ7fx+2r94a2E+Uirsp6HsPTPlomfdHtpt/B0cdKviwkoaM6pyvUOpQ== + dependencies: + whatwg-url "^5.0.0" node-forge@^0.10.0: version "0.10.0" @@ -9397,10 +9709,10 @@ node-notifier@^8.0.0: uuid "^8.3.0" which "^2.0.2" -node-releases@^1.1.61, node-releases@^1.1.75: - version "1.1.75" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.75.tgz#6dd8c876b9897a1b8e5a02de26afa79bb54ebbfe" - integrity sha512-Qe5OUajvqrqDSy6wrWFmMwfJ0jVgwiw4T3KqmbTcZ62qW0gQkheXYhcFM1+lOVcGUoRxcEcfyvFMAnDgaF1VWw== +node-releases@^1.1.61, node-releases@^1.1.76: + version "1.1.76" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.76.tgz#df245b062b0cafbd5282ab6792f7dccc2d97f36e" + integrity sha512-9/IECtNr8dXNmPWmFXepT0/7o5eolGesHUa3mtr0KlgnCvnZxwh2qensKL42JJY2vQKC3nIBXetFAqR+PW1CmA== normalize-package-data@^2.3.2, normalize-package-data@^2.5.0: version "2.5.0" @@ -9451,7 +9763,7 @@ npm-run-path@^2.0.0: dependencies: path-key "^2.0.0" -npm-run-path@^4.0.0, npm-run-path@^4.0.1: +npm-run-path@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw== @@ -9564,6 +9876,14 @@ object.getownpropertydescriptors@^2.0.3, object.getownpropertydescriptors@^2.1.0 define-properties "^1.1.3" es-abstract "^1.18.0-next.2" +object.hasown@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/object.hasown/-/object.hasown-1.0.0.tgz#bdbade33cfacfb25d7f26ae2b6cb870bf99905c2" + integrity sha512-qYMF2CLIjxxLGleeM0jrcB4kiv3loGVAjKQKvH8pSU/i2VcRRvUNmxbD+nEMmrXRfORhuVJuH8OtSYCZoue3zA== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.18.1" + object.pick@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" @@ -9604,7 +9924,7 @@ once@^1.3.0, once@^1.3.1, once@^1.4.0: dependencies: wrappy "1" -onetime@^5.1.0, onetime@^5.1.2: +onetime@^5.1.0: version "5.1.2" resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== @@ -9619,6 +9939,11 @@ open@^7.0.2: is-docker "^2.0.0" is-wsl "^2.1.1" +opencollective-postinstall@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/opencollective-postinstall/-/opencollective-postinstall-2.0.3.tgz#7a0fff978f6dbfa4d006238fbac98ed4198c3259" + integrity sha512-8AV/sCtuzUeTo8gQK5qDZzARrulB3egtLzFgteqB2tcT4Mw7B8Kt7JcDHmltjz6FOAHsvTevk70gZEbhM4ZS9Q== + opn@^5.5.0: version "5.5.0" resolved "https://registry.yarnpkg.com/opn/-/opn-5.5.0.tgz#fc7164fab56d235904c51c3b27da6758ca3b9bfc" @@ -9633,6 +9958,14 @@ optimism@^0.10.0: dependencies: "@wry/context" "^0.4.0" +optimism@^0.16.1: + version "0.16.1" + resolved "https://registry.yarnpkg.com/optimism/-/optimism-0.16.1.tgz#7c8efc1f3179f18307b887e18c15c5b7133f6e7d" + integrity sha512-64i+Uw3otrndfq5kaoGNoY7pvOhSsjFEN4bdEFh80MWVk/dbgJfMv7VFDeCT8LxNAlEVhQmdVEbfE7X2nWNIIg== + dependencies: + "@wry/context" "^0.6.0" + "@wry/trie" "^0.3.0" + optimize-css-assets-webpack-plugin@5.0.4: version "5.0.4" resolved "https://registry.yarnpkg.com/optimize-css-assets-webpack-plugin/-/optimize-css-assets-webpack-plugin-5.0.4.tgz#85883c6528aaa02e30bbad9908c92926bb52dc90" @@ -9729,6 +10062,13 @@ p-locate@^4.1.0: dependencies: p-limit "^2.2.0" +p-locate@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" + integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== + dependencies: + p-limit "^3.0.2" + p-map@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/p-map/-/p-map-2.1.0.tgz#310928feef9c9ecc65b68b17693018a665cea175" @@ -9948,6 +10288,11 @@ pbkdf2@^3.0.3: safe-buffer "^5.0.1" sha.js "^2.4.8" +perfect-scrollbar@^1.5.0: + version "1.5.2" + resolved "https://registry.yarnpkg.com/perfect-scrollbar/-/perfect-scrollbar-1.5.2.tgz#41167ac6bc95e3a5e87a7402fa36fdacca9bc298" + integrity sha512-McHAinFkyzKbBZrFtb4MT2mxkehp15KvOX/UrjB8C5EZZXHTHgyETo5IGFYtHRTI2Pb2bsV0OE0YnkjT9Cw3aw== + performance-now@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" @@ -10021,6 +10366,13 @@ pkg-dir@^4.1.0, pkg-dir@^4.2.0: dependencies: find-up "^4.0.0" +pkg-dir@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-5.0.0.tgz#a02d6aebe6ba133a928f74aec20bafdfe6b8e760" + integrity sha512-NPE8TDbzl/3YQYY7CSS228s3g2ollTFnc+Qi3tqmqJp9Vg2ovUpixcJEo2HJScN2Ez+kEaal6y70c0ehqJBJeA== + dependencies: + find-up "^5.0.0" + pkg-up@3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/pkg-up/-/pkg-up-3.1.0.tgz#100ec235cc150e4fd42519412596a28512a0def5" @@ -10049,6 +10401,13 @@ pnp-webpack-plugin@1.6.4: dependencies: ts-pnp "^1.1.6" +polished@^4.1.3: + version "4.1.3" + resolved "https://registry.yarnpkg.com/polished/-/polished-4.1.3.tgz#7a3abf2972364e7d97770b827eec9a9e64002cfc" + integrity sha512-ocPAcVBUOryJEKe0z2KLd1l9EBa1r5mSwlKpExmrLzsnIzJo4axsoU9O2BjOTkDGDT4mZ0WFE5XKTlR3nLnZOA== + dependencies: + "@babel/runtime" "^7.14.0" + popper.js@1.16.1-lts: version "1.16.1-lts" resolved "https://registry.yarnpkg.com/popper.js/-/popper.js-1.16.1-lts.tgz#cf6847b807da3799d80ee3d6d2f90df8a3f50b05" @@ -10718,12 +11077,12 @@ postcss@7.0.36, postcss@^7, postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.14, pos supports-color "^6.1.0" postcss@^8.1.0: - version "8.3.6" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.3.6.tgz#2730dd76a97969f37f53b9a6096197be311cc4ea" - integrity sha512-wG1cc/JhRgdqB6WHEuyLTedf3KIRuD0hG6ldkFEZNCjRxiC+3i6kkWUUbiJQayP28iwG35cEmAbe98585BYV0A== + version "8.3.7" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.3.7.tgz#ec88563588c8da8e58e7226f7633b51ae221eeda" + integrity sha512-9SaY7nnyQ63/WittqZYAvkkYPyKxchMKH71UDzeTmWuLSvxTRpeEeABZAzlCi55cuGcoFyoV/amX2BdsafQidQ== dependencies: - colorette "^1.2.2" - nanoid "^3.1.23" + nanocolors "^0.1.5" + nanoid "^3.1.25" source-map-js "^0.6.2" prelude-ls@^1.2.1: @@ -10748,7 +11107,7 @@ prettier-linter-helpers@^1.0.0: dependencies: fast-diff "^1.1.2" -prettier@^2.3.2: +prettier@^2.2.1: version "2.4.1" resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.4.1.tgz#671e11c89c14a4cfc876ce564106c4a6726c9f5c" integrity sha512-9fbDAXSBcc6Bs1mZrDYb3XKzDLm4EXXL9sC1LqKP5rZkT6KRr/rf9amVUcODVXgguK/isJz0d0hP72WeaKWsvA== @@ -10786,18 +11145,6 @@ pretty-format@^27.0.0, pretty-format@^27.2.0: ansi-styles "^5.0.0" react-is "^17.0.1" -pretty-quick@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/pretty-quick/-/pretty-quick-3.1.1.tgz#93ca4e2dd38cc4e970e3f54a0ead317a25454688" - integrity sha512-ZYLGiMoV2jcaas3vTJrLvKAYsxDoXQBUn8OSTxkl67Fyov9lyXivJTl0+2WVh+y6EovGcw7Lm5ThYpH+Sh3XxQ== - dependencies: - chalk "^3.0.0" - execa "^4.0.0" - find-up "^4.1.0" - ignore "^5.1.4" - mri "^1.1.5" - multimatch "^4.0.0" - process-nextick-args@~2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" @@ -11139,6 +11486,13 @@ react-app-polyfill@^2.0.0: regenerator-runtime "^0.13.7" whatwg-fetch "^3.4.1" +react-app-rewired@^2.1.8: + version "2.1.8" + resolved "https://registry.yarnpkg.com/react-app-rewired/-/react-app-rewired-2.1.8.tgz#e192f93b98daf96889418d33d3e86cf863812b56" + integrity sha512-wjXPdKPLscA7mn0I1de1NHrbfWdXz4S1ladaGgHVKdn1hTgKK5N6EdGIJM0KrS6bKnJBj7WuqJroDTsPKKr66Q== + dependencies: + semver "^5.6.0" + react-async-script@^1.1.1: version "1.2.0" resolved "https://registry.yarnpkg.com/react-async-script/-/react-async-script-1.2.0.tgz#ab9412a26f0b83f5e2e00de1d2befc9400834b21" @@ -11205,7 +11559,7 @@ react-dev-utils@^11.0.3: strip-ansi "6.0.0" text-table "0.2.0" -react-dom@16.13.0, react-dom@17.0.2: +react-dom@16.13.0, react-dom@17.0.2, react-dom@~17.0.2: version "17.0.2" resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-17.0.2.tgz#ecffb6845e3ad8dbfcdc498f0d0a939736502c23" integrity sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA== @@ -11215,9 +11569,9 @@ react-dom@16.13.0, react-dom@17.0.2: scheduler "^0.20.2" react-dropzone@^11.4.0: - version "11.4.0" - resolved "https://registry.yarnpkg.com/react-dropzone/-/react-dropzone-11.4.0.tgz#bbf3b2491341864c91c218a606a7f2568e5a94a8" - integrity sha512-5NRpAN4ZmpEn0kvtkO18rPInE7n4eVjGeTLP/c0JcGAnV+5yrpr5QHdPH27M05SP2tsjkRoRf02DCK/4fxbsog== + version "11.4.2" + resolved "https://registry.yarnpkg.com/react-dropzone/-/react-dropzone-11.4.2.tgz#1eb99e9def4cc7520f4f58e85c853ce52c483d56" + integrity sha512-ocYzYn7Qgp0tFc1gQtUTOaHHSzVTwhWHxxY+r7cj2jJTPfMTZB5GWSJHdIVoxsl+EQENpjJ/6Zvcw0BqKZQ+Eg== dependencies: attr-accept "^2.2.1" file-selector "^0.2.2" @@ -11233,6 +11587,13 @@ react-fast-compare@^3.1.1: resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-3.2.0.tgz#641a9da81b6a6320f270e89724fb45a0b39e43bb" integrity sha512-rtGImPZ0YyLrscKI9xTpV8psd6I8VAtjKCzQDlzyDvqJA8XOW78TXYQwNRNd8g8JZnDu8q9Fu/1v4HPAVwVdHA== +react-feather@^2.0.9: + version "2.0.9" + resolved "https://registry.yarnpkg.com/react-feather/-/react-feather-2.0.9.tgz#6e42072130d2fa9a09d4476b0e61b0ed17814480" + integrity sha512-yMfCGRkZdXwIs23Zw/zIWCJO3m3tlaUvtHiXlW+3FH7cIT6fiK1iJ7RJWugXq7Fso8ZaQyUm92/GOOHXvkiVUw== + dependencies: + prop-types "^15.7.2" + react-file-download@^0.3.5: version "0.3.5" resolved "https://registry.yarnpkg.com/react-file-download/-/react-file-download-0.3.5.tgz#7a4e75874528806bfa53ddddd98b4da427d3a897" @@ -11271,7 +11632,7 @@ react-highlighter@^0.4.3: escape-string-regexp "^1.0.5" prop-types "^15.6.0" -react-i18next@^11.11.2: +react-i18next@^11.11.3: version "11.12.0" resolved "https://registry.yarnpkg.com/react-i18next/-/react-i18next-11.12.0.tgz#2a053321b9b7a876d5baa7af55a12d986117bffc" integrity sha512-M9BT+hqVG03ywrl+L7CK74ugK+4jIo7AeKJ17+g9BoqJz2+/aVbs8SIVXT4KMQ1rjIdcw+GcSRDy1CXjcz6tLQ== @@ -11286,17 +11647,22 @@ react-icons@3.9.0: dependencies: camelcase "^5.0.0" +react-icons@4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/react-icons/-/react-icons-4.1.0.tgz#9ca9bcbf2e3aee8e86e378bb9d465842947bbfc3" + integrity sha512-FCXBg1JbbR0vWALXIxmFAfozHdVIJmmwCD81Jk0EKOt7Ax4AdBNcaRkWhR0NaKy9ugJgoY3fFvo0PHpte55pXg== + react-identicons@^1.2.5: version "1.2.5" resolved "https://registry.yarnpkg.com/react-identicons/-/react-identicons-1.2.5.tgz#3502249e49d88f4e3500092694410a984bb102fa" integrity sha512-x7prkDoc2pD7wSl2C1pGxS+XAoSdq1ABWJWTBUimVTDVJArKOLd0B4wRUJpDm4r+9y7pgf8ylyPGsmlWSV5n2g== -react-is@^16.12.0, react-is@^16.13.1, react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.1: +react-is@^16.12.0, react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.1: version "16.13.1" resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== -"react-is@^16.8.0 || ^17.0.0", react-is@^17.0.1: +"react-is@^16.8.0 || ^17.0.0", react-is@^17.0.1, react-is@^17.0.2: version "17.0.2" resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0" integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w== @@ -11316,29 +11682,38 @@ react-lifecycles-compat@^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-perfect-scrollbar@^1.5.8: + version "1.5.8" + resolved "https://registry.yarnpkg.com/react-perfect-scrollbar/-/react-perfect-scrollbar-1.5.8.tgz#380959387a325c5c9d0268afc08b3f73ed5b3078" + integrity sha512-bQ46m70gp/HJtiBOF3gRzBISSZn8FFGNxznTdmTG8AAwpxG1bJCyn7shrgjEvGSQ5FJEafVEiosY+ccER11OSA== + dependencies: + perfect-scrollbar "^1.5.0" + prop-types "^15.6.1" + react-placeholder@^4.0.0: version "4.1.0" resolved "https://registry.yarnpkg.com/react-placeholder/-/react-placeholder-4.1.0.tgz#943128820b3b0a6f94371655aadec18d306e05e3" integrity sha512-z1HGD86NWJTYTQumHsmGH9jkozv4QHa9dju/vHVUd4f1svu23pf5v7QoBLBfs3kA1S9GLJaCeRMHLbO2SCdz5A== -react-redux@^7.2.4: - version "7.2.5" - resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-7.2.5.tgz#213c1b05aa1187d9c940ddfc0b29450957f6a3b8" - integrity sha512-Dt29bNyBsbQaysp6s/dN0gUodcq+dVKKER8Qv82UrpeygwYeX1raTtil7O/fftw/rFqzaf6gJhDZRkkZnn6bjg== - dependencies: - "@babel/runtime" "^7.12.1" - "@types/react-redux" "^7.1.16" - hoist-non-react-statics "^3.3.2" - loose-envify "^1.4.0" - prop-types "^15.7.2" - react-is "^16.13.1" - react-refresh@^0.8.3: version "0.8.3" resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.8.3.tgz#721d4657672d400c5e3c75d063c4a85fb2d5d68f" integrity sha512-X8jZHc7nCMjaCqoU+V2I0cOhNW+QMBwSUkeXnTi8IPe6zaRWfn60ZzvFDZqWPfmSJfjub7dDW1SP0jaHWLu/hg== -react-router@^5.2.1: +react-router-dom@^5.2.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-5.3.0.tgz#da1bfb535a0e89a712a93b97dd76f47ad1f32363" + integrity sha512-ObVBLjUZsphUUMVycibxgMdh5jJ1e3o+KpAZBVeHcNQZ4W+uUGGWsokurzlF4YOldQYRQL4y6yFRWM4m3svmuQ== + dependencies: + "@babel/runtime" "^7.12.13" + history "^4.9.0" + loose-envify "^1.3.1" + prop-types "^15.6.2" + react-router "5.2.1" + tiny-invariant "^1.0.2" + tiny-warning "^1.0.0" + +react-router@5.2.1, react-router@^5.2.0: version "5.2.1" resolved "https://registry.yarnpkg.com/react-router/-/react-router-5.2.1.tgz#4d2e4e9d5ae9425091845b8dbc6d9d276239774d" integrity sha512-lIboRiOtDLFdg1VTemMwud9vRVuOCZmUIT/7lUoZiSpPODiiH1UQlfXy+vPLC/7IWdFYnhRwAyNqA/+I7wnvKQ== @@ -11354,7 +11729,7 @@ react-router@^5.2.1: tiny-invariant "^1.0.2" tiny-warning "^1.0.0" -react-scripts@4.0.3: +react-scripts@^4.0.3: version "4.0.3" resolved "https://registry.yarnpkg.com/react-scripts/-/react-scripts-4.0.3.tgz#b1cafed7c3fa603e7628ba0f187787964cb5d345" integrity sha512-S5eO4vjUzUisvkIPB7jVsKtuH2HhWcASREYWHAQ1FP5HyCv3xgn+wpILAEWkmy+A+tTNbSZClhxjT3qz6g4L1A== @@ -11449,7 +11824,7 @@ react-tooltip@3.9.2: classnames "^2.2.5" prop-types "^15.6.0" -react-transition-group@^4.4.0: +react-transition-group@^4.4.0, react-transition-group@^4.4.2: version "4.4.2" resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-4.4.2.tgz#8b59a56f09ced7b55cbd53c36768b922890d5470" integrity sha512-/RNYfRAMlZwDSr6z4zNKV6xu53/e2BuaBbGhbyYIXTrmgu/bGHzmqOs7mJSJBHy9Ud+ApHx3QjrkKSp1pxvlFg== @@ -11471,7 +11846,7 @@ react-virtualized@^9.22.3: prop-types "^15.7.2" react-lifecycles-compat "^3.0.4" -react@16.13.0, react@17.0.2: +react@16.13.0, react@17.0.2, react@~17.0.2: version "17.0.2" resolved "https://registry.yarnpkg.com/react/-/react-17.0.2.tgz#d0b5cc516d29eb3eee383f75b62864cfb6800037" integrity sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA== @@ -11545,7 +11920,7 @@ read-pkg@^5.2.0: string_decoder "~1.1.1" util-deprecate "~1.0.1" -readable-stream@^3.0.2, readable-stream@^3.0.6, readable-stream@^3.6.0: +readable-stream@^3.0.6, readable-stream@^3.6.0: version "3.6.0" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== @@ -11585,18 +11960,6 @@ redent@^3.0.0: indent-string "^4.0.0" strip-indent "^3.0.0" -redux-persist@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/redux-persist/-/redux-persist-6.0.0.tgz#b4d2972f9859597c130d40d4b146fecdab51b3a8" - integrity sha512-71LLMbUq2r02ng2We9S215LtPu3fY0KgaGE0k8WRgl6RkqxtGfl7HUozz1Dftwsb0D/5mZ8dwAaPbtnzfvbEwQ== - -redux@^4.0.0, redux@^4.1.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/redux/-/redux-4.1.1.tgz#76f1c439bb42043f985fbd9bf21990e60bd67f47" - integrity sha512-hZQZdDEM25UY2P493kPYuKqviVwZ58lEmGQNeQ+gXa+U0gYPUBf7NKYazbe3m+bs/DzM/ahN12DbF+NG8i0CWw== - dependencies: - "@babel/runtime" "^7.9.2" - regenerate-unicode-properties@^9.0.0: version "9.0.0" resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-9.0.0.tgz#54d09c7115e1f53dc2314a974b32c1c344efe326" @@ -11872,6 +12235,11 @@ rgba-regex@^1.0.0: resolved "https://registry.yarnpkg.com/rgba-regex/-/rgba-regex-1.0.0.tgz#43374e2e2ca0968b0ef1523460b7d730ff22eeb3" integrity sha1-QzdOLiyglosO8VI0YLfXMP8i7rM= +rifm@^0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/rifm/-/rifm-0.12.0.tgz#8d3a9dc0de9c190e0de9bdc8861a91a221dc1341" + integrity sha512-PqOl+Mo2lyqrKiD34FPlnQ+ksD3F+a62TQlphiZshgriyHdfjn6jGyqUZhd+s3nsMYXwXYDdjrrv8wX7QsOG3g== + rimraf@2.6.3: version "2.6.3" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" @@ -12084,6 +12452,11 @@ semver-compare@^1.0.0: resolved "https://registry.yarnpkg.com/semver-compare/-/semver-compare-1.0.0.tgz#0dee216a1c941ab37e9efb1788f6afc5ff5537fc" integrity sha1-De4hahyUGrN+nvsXiPavxf9VN/w= +semver-regex@^3.1.2: + version "3.1.3" + resolved "https://registry.yarnpkg.com/semver-regex/-/semver-regex-3.1.3.tgz#b2bcc6f97f63269f286994e297e229b6245d0dc3" + integrity sha512-Aqi54Mk9uYTjVexLnR67rTyBusmwd04cLkHy9hNvk3+G3nT2Oyg7E0l4XVbOaNwIvQ3hHeYxGcyEy+mKreyBFQ== + "semver@2 || 3 || 4 || 5", semver@^5.3.0, semver@^5.4.1, semver@^5.5.0, semver@^5.5.1, semver@^5.6.0: version "5.7.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" @@ -12295,7 +12668,7 @@ side-channel@^1.0.4: get-intrinsic "^1.0.2" object-inspect "^1.9.0" -signal-exit@^3.0.0, signal-exit@^3.0.2, signal-exit@^3.0.3: +signal-exit@^3.0.0, signal-exit@^3.0.2: version "3.0.4" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.4.tgz#366a4684d175b9cab2081e3681fda3747b6c51d7" integrity sha512-rqYhcAnZ6d/vTPGghdrw7iumdcbXpsk1b8IG/rz+VWV51DM0p7XCtMoJ3qhPLIbp3tvyt3pKRbaaEMZYpHto8Q== @@ -12374,19 +12747,6 @@ snapdragon@^0.8.1: source-map-resolve "^0.5.0" use "^3.1.0" -snazzy@^9.0.0: - version "9.0.0" - resolved "https://registry.yarnpkg.com/snazzy/-/snazzy-9.0.0.tgz#663639d059efd96c89f2aa63272acfacc5feda1f" - integrity sha512-8QZmJb11OiYaUP90Nnjqcj/LEpO8CLgChnP87Wqjv5tNB4djwHaz27VO2usSRR0NmViapeGW04p0aWAMhxxLXg== - dependencies: - chalk "^4.1.0" - inherits "^2.0.4" - minimist "^1.2.5" - readable-stream "^3.6.0" - standard-json "^1.1.0" - strip-ansi "^6.0.0" - text-table "^0.2.0" - sockjs-client@^1.5.0: version "1.5.2" resolved "https://registry.yarnpkg.com/sockjs-client/-/sockjs-client-1.5.2.tgz#4bc48c2da9ce4769f19dc723396b50f5c12330a3" @@ -12462,7 +12822,7 @@ source-map@0.6.1, source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.0, sourc resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== -source-map@^0.5.0, source-map@^0.5.6: +source-map@^0.5.0, source-map@^0.5.6, source-map@^0.5.7: version "0.5.7" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= @@ -12579,13 +12939,6 @@ standard-engine@^14.0.1: pkg-conf "^3.1.0" xdg-basedir "^4.0.0" -standard-json@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/standard-json/-/standard-json-1.1.0.tgz#33ac0d2eccaddb0556f5ae28c43a35624cf1fb25" - integrity sha512-nkonX+n5g3pyVBvJZmvRlFtT/7JyLbNh4CtrYC3Qfxihgs8PKX52f6ONKQXORStuBWJ5PI83EUrNXme7LKfiTQ== - dependencies: - concat-stream "^2.0.0" - standard@^16.0.3: version "16.0.3" resolved "https://registry.yarnpkg.com/standard/-/standard-16.0.3.tgz#a854c0dd2dea6b9f0b8d20c65260210bd0cee619" @@ -12686,13 +13039,13 @@ string-width@^3.0.0, string-width@^3.1.0: strip-ansi "^5.1.0" string-width@^4.1.0, string-width@^4.2.0: - version "4.2.2" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.2.tgz#dafd4f9559a7585cfba529c6a0a4f73488ebd4c5" - integrity sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA== + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== dependencies: emoji-regex "^8.0.0" is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.0" + strip-ansi "^6.0.1" string.prototype.matchall@^4.0.2, string.prototype.matchall@^4.0.5: version "4.0.5" @@ -12747,7 +13100,7 @@ stringify-object@^3.3.0: is-obj "^1.0.1" is-regexp "^1.0.0" -strip-ansi@6.0.0, strip-ansi@^6.0.0: +strip-ansi@6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.0.tgz#0b1571dd7669ccd4f3e06e14ef1eed26225ae532" integrity sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w== @@ -12775,6 +13128,13 @@ strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: dependencies: ansi-regex "^4.1.0" +strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + strip-bom@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" @@ -12866,6 +13226,11 @@ stylis@^3.5.0: resolved "https://registry.yarnpkg.com/stylis/-/stylis-3.5.4.tgz#f665f25f5e299cf3d64654ab949a57c768b73fbe" integrity sha512-8/3pSmthWM7lsPBKv7NXkzn2Uc9W7NotcwGNpJaa3k7WMM1XDCA4MgT5k/8BIexd5ydZdboXtU90XH9Ec4Bv/Q== +stylis@^4.0.3: + version "4.0.10" + resolved "https://registry.yarnpkg.com/stylis/-/stylis-4.0.10.tgz#446512d1097197ab3f02fb3c258358c3f7a14240" + integrity sha512-m3k+dk7QeJw660eIKRRn3xPF6uuvHs/FFzjX3HQ5ove0qYsiygoAhwn5a3IYKaZPo5LrYD0rfVmtv1gNY1uYwg== + subscriptions-transport-ws@^0.9.19: version "0.9.19" resolved "https://registry.yarnpkg.com/subscriptions-transport-ws/-/subscriptions-transport-ws-0.9.19.tgz#10ca32f7e291d5ee8eb728b9c02e43c52606cdcf" @@ -12935,6 +13300,11 @@ symbol-observable@^1.0.2, symbol-observable@^1.0.4: resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.2.0.tgz#c22688aed4eab3cdc2dfeacbb561660560a00804" integrity sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ== +symbol-observable@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-4.0.0.tgz#5b425f192279e87f2f9b937ac8540d1984b39205" + integrity sha512-b19dMThMV4HVFynSAM1++gBHAbk2Tc/osgLIBZMKsyqh34jb2e8Os7T6ZW/Bt3pJFdBTd2JwAnAAEQV7rSNvcQ== + symbol-tree@^3.2.4: version "3.2.4" resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2" @@ -13048,9 +13418,9 @@ terser@^4.1.2, terser@^4.6.2, terser@^4.6.3: source-map-support "~0.5.12" terser@^5.3.4: - version "5.8.0" - resolved "https://registry.yarnpkg.com/terser/-/terser-5.8.0.tgz#c6d352f91aed85cc6171ccb5e84655b77521d947" - integrity sha512-f0JH+6yMpneYcRJN314lZrSwu9eKkUFEHLN/kNy8ceh8gaRiLgFPJqrB9HsXjhEGdv4e/ekjTOFxIlL6xlma8A== + version "5.9.0" + resolved "https://registry.yarnpkg.com/terser/-/terser-5.9.0.tgz#47d6e629a522963240f2b55fcaa3c99083d2c351" + integrity sha512-h5hxa23sCdpzcye/7b8YqbE5OwKca/ni0RQz1uRX3tGh8haaGHqcuSqbGRybuAKNdntZ0mDgFNXPJ48xQ2RXKQ== dependencies: commander "^2.20.0" source-map "~0.7.2" @@ -13200,6 +13570,11 @@ tr46@^2.1.0: dependencies: punycode "^2.1.1" +tr46@~0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" + integrity sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o= + tryer@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/tryer/-/tryer-1.0.1.tgz#f2c85406800b9b0f74c9f7465b81eaad241252f8" @@ -13217,6 +13592,13 @@ ts-invariant@^0.4.0, ts-invariant@^0.4.4: dependencies: tslib "^1.9.3" +ts-invariant@^0.9.0: + version "0.9.3" + resolved "https://registry.yarnpkg.com/ts-invariant/-/ts-invariant-0.9.3.tgz#4b41e0a80c2530a56ce4b8fd4e14183aaac0efa8" + integrity sha512-HinBlTbFslQI0OHP07JLsSXPibSegec6r9ai5xxq/qHYCsIQbzpymLpDhAUsnXcSrDEcd0L62L8vsOEdzM0qlA== + dependencies: + tslib "^2.1.0" + ts-pnp@1.2.0, ts-pnp@^1.1.6: version "1.2.0" resolved "https://registry.yarnpkg.com/ts-pnp/-/ts-pnp-1.2.0.tgz#a500ad084b0798f1c3071af391e65912c86bca92" @@ -13237,7 +13619,7 @@ tslib@^1.10.0, tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3: resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== -tslib@^2.0.3, tslib@^2.1.0: +tslib@^2.0.3, tslib@^2.1.0, tslib@^2.3.0: version "2.3.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.1.tgz#e8a335add5ceae51aa261d32a490158ef042ef01" integrity sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw== @@ -13731,13 +14113,6 @@ walker@^1.0.7, walker@~1.0.5: dependencies: makeerror "1.0.x" -warning@^4.0.3: - version "4.0.3" - resolved "https://registry.yarnpkg.com/warning/-/warning-4.0.3.tgz#16e9e077eb8a86d6af7d64aa1e05fd85b4678ca3" - integrity sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w== - dependencies: - loose-envify "^1.0.0" - watchpack-chokidar2@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/watchpack-chokidar2/-/watchpack-chokidar2-2.0.1.tgz#38500072ee6ece66f3769936950ea1771be1c957" @@ -13768,6 +14143,11 @@ web-vitals@^1.0.1: resolved "https://registry.yarnpkg.com/web-vitals/-/web-vitals-1.1.2.tgz#06535308168986096239aa84716e68b4c6ae6d1c" integrity sha512-PFMKIY+bRSXlMxVAQ+m2aw9c/ioUYfDgrYot0YUa+/xa0sakubWhSDyxAKwzymvXVdF4CZI71g06W+mqhzu6ig== +webidl-conversions@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" + integrity sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE= + webidl-conversions@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-5.0.0.tgz#ae59c8a00b121543a2acc65c0434f57b0fc11aff" @@ -13914,6 +14294,14 @@ whatwg-mimetype@^2.3.0: resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz#3d4b1e0312d2079879f826aff18dbeeca5960fbf" integrity sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g== +whatwg-url@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" + integrity sha1-lmRU6HZUYuN2RNNib2dCzotwll0= + dependencies: + tr46 "~0.0.3" + webidl-conversions "^3.0.0" + whatwg-url@^8.0.0, whatwg-url@^8.5.0: version "8.7.0" resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-8.7.0.tgz#656a78e510ff8f3937bc0bcbe9f5c0ac35941b77" @@ -13939,6 +14327,11 @@ which-module@^2.0.0: resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= +which-pm-runs@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/which-pm-runs/-/which-pm-runs-1.0.0.tgz#670b3afbc552e0b55df6b7780ca74615f23ad1cb" + integrity sha1-Zws6+8VS4LVd9rd4DKdGFfI60cs= + which@^1.2.9, which@^1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" @@ -14313,7 +14706,15 @@ zen-observable-ts@^0.8.21: tslib "^1.9.3" zen-observable "^0.8.0" -zen-observable@^0.8.0: +zen-observable-ts@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/zen-observable-ts/-/zen-observable-ts-1.1.0.tgz#2d1aa9d79b87058e9b75698b92791c1838551f83" + integrity sha512-1h4zlLSqI2cRLPJUHJFL8bCWHhkpuXkF+dbGkRaWjgDIG26DmzyshUMrdV/rL3UnR+mhaX4fRq8LPouq0MYYIA== + dependencies: + "@types/zen-observable" "0.8.3" + zen-observable "0.8.15" + +zen-observable@0.8.15, zen-observable@^0.8.0: version "0.8.15" resolved "https://registry.yarnpkg.com/zen-observable/-/zen-observable-0.8.15.tgz#96415c512d8e3ffd920afd3889604e30b9eaac15" integrity sha512-PQ2PC7R9rslx84ndNBZB/Dkv8V8fZEpk83RLgXtYd0fwUgEjseMn1Dgajh2x6S8QbZAFa9p2qVCEuYZNgve0dQ== From f64d4c025dbf4a8206575bd88157553dce596a45 Mon Sep 17 00:00:00 2001 From: AngeloCG97 <51149817+AngeloCG97@users.noreply.github.com> Date: Mon, 27 Sep 2021 14:29:36 -0600 Subject: [PATCH 02/15] fix(structure-files): change names to folders and files (#795) * fix(structure-files): change names to folders and files --- .../components/{languageSelector => LanguageSelector}/index.js | 0 .../components/{languageSelector => LanguageSelector}/styles.js | 0 webapp/src/routes/{about => About}/index.js | 0 webapp/src/routes/{about => About}/styles.js | 0 webapp/src/routes/{help => Help}/index.js | 0 webapp/src/routes/{help => Help}/styles.js | 0 webapp/src/routes/{home/cover.js => Home/Cover.js} | 0 webapp/src/routes/{home/rateCategory.js => Home/RateCategory.js} | 0 webapp/src/routes/{home/subTopic.js => Home/SubTopic.js} | 0 webapp/src/routes/{home => Home}/index.js | 0 webapp/src/routes/{home => Home}/styles.js | 0 11 files changed, 0 insertions(+), 0 deletions(-) rename webapp/src/components/{languageSelector => LanguageSelector}/index.js (100%) rename webapp/src/components/{languageSelector => LanguageSelector}/styles.js (100%) rename webapp/src/routes/{about => About}/index.js (100%) rename webapp/src/routes/{about => About}/styles.js (100%) rename webapp/src/routes/{help => Help}/index.js (100%) rename webapp/src/routes/{help => Help}/styles.js (100%) rename webapp/src/routes/{home/cover.js => Home/Cover.js} (100%) rename webapp/src/routes/{home/rateCategory.js => Home/RateCategory.js} (100%) rename webapp/src/routes/{home/subTopic.js => Home/SubTopic.js} (100%) rename webapp/src/routes/{home => Home}/index.js (100%) rename webapp/src/routes/{home => Home}/styles.js (100%) diff --git a/webapp/src/components/languageSelector/index.js b/webapp/src/components/LanguageSelector/index.js similarity index 100% rename from webapp/src/components/languageSelector/index.js rename to webapp/src/components/LanguageSelector/index.js diff --git a/webapp/src/components/languageSelector/styles.js b/webapp/src/components/LanguageSelector/styles.js similarity index 100% rename from webapp/src/components/languageSelector/styles.js rename to webapp/src/components/LanguageSelector/styles.js diff --git a/webapp/src/routes/about/index.js b/webapp/src/routes/About/index.js similarity index 100% rename from webapp/src/routes/about/index.js rename to webapp/src/routes/About/index.js diff --git a/webapp/src/routes/about/styles.js b/webapp/src/routes/About/styles.js similarity index 100% rename from webapp/src/routes/about/styles.js rename to webapp/src/routes/About/styles.js diff --git a/webapp/src/routes/help/index.js b/webapp/src/routes/Help/index.js similarity index 100% rename from webapp/src/routes/help/index.js rename to webapp/src/routes/Help/index.js diff --git a/webapp/src/routes/help/styles.js b/webapp/src/routes/Help/styles.js similarity index 100% rename from webapp/src/routes/help/styles.js rename to webapp/src/routes/Help/styles.js diff --git a/webapp/src/routes/home/cover.js b/webapp/src/routes/Home/Cover.js similarity index 100% rename from webapp/src/routes/home/cover.js rename to webapp/src/routes/Home/Cover.js diff --git a/webapp/src/routes/home/rateCategory.js b/webapp/src/routes/Home/RateCategory.js similarity index 100% rename from webapp/src/routes/home/rateCategory.js rename to webapp/src/routes/Home/RateCategory.js diff --git a/webapp/src/routes/home/subTopic.js b/webapp/src/routes/Home/SubTopic.js similarity index 100% rename from webapp/src/routes/home/subTopic.js rename to webapp/src/routes/Home/SubTopic.js diff --git a/webapp/src/routes/home/index.js b/webapp/src/routes/Home/index.js similarity index 100% rename from webapp/src/routes/home/index.js rename to webapp/src/routes/Home/index.js diff --git a/webapp/src/routes/home/styles.js b/webapp/src/routes/Home/styles.js similarity index 100% rename from webapp/src/routes/home/styles.js rename to webapp/src/routes/Home/styles.js From 7dac4e2c6928763e5027e637a28551e54092ef41 Mon Sep 17 00:00:00 2001 From: Teto Gomez Date: Mon, 27 Sep 2021 15:02:22 -0600 Subject: [PATCH 03/15] fix(webapp): add permission for public aggregate tables (#796) --- .../metadata/databases/default/tables/public_producers_list.yaml | 1 + hasura/metadata/databases/default/tables/public_proxies.yaml | 1 + 2 files changed, 2 insertions(+) diff --git a/hasura/metadata/databases/default/tables/public_producers_list.yaml b/hasura/metadata/databases/default/tables/public_producers_list.yaml index 5ad3726a..f0852461 100644 --- a/hasura/metadata/databases/default/tables/public_producers_list.yaml +++ b/hasura/metadata/databases/default/tables/public_producers_list.yaml @@ -3,6 +3,7 @@ table: schema: public select_permissions: - permission: + allow_aggregations: true columns: - owner - bpjson diff --git a/hasura/metadata/databases/default/tables/public_proxies.yaml b/hasura/metadata/databases/default/tables/public_proxies.yaml index 8e99fd4b..8bcd84ad 100644 --- a/hasura/metadata/databases/default/tables/public_proxies.yaml +++ b/hasura/metadata/databases/default/tables/public_proxies.yaml @@ -3,6 +3,7 @@ table: schema: public select_permissions: - permission: + allow_aggregations: true columns: - background - filter_name From 59467700bfe7e81525df4f43727ef3018926eea5 Mon Sep 17 00:00:00 2001 From: Teto Gomez Date: Thu, 30 Sep 2021 09:45:48 -0600 Subject: [PATCH 04/15] fix(webapp): add filters and styling compare tool (#799) * fix(webapp): add filters and styling compare tool * fix(webapp): delete commented code * fix(webapp): delete commented code --- .../CompareTool/CompareGraphView.js | 146 ++++----- .../CompareTool/CompareSliderView.js | 13 +- webapp/src/components/CompareTool/index.js | 56 ++-- webapp/src/components/CompareTool/styles.js | 116 ++++--- webapp/src/components/FilterBanner/index.js | 77 +++++ webapp/src/components/FilterBanner/styles.js | 14 + webapp/src/components/Sidebar/index.js | 62 +--- webapp/src/config/filters.js | 12 + webapp/src/config/index.js | 3 +- webapp/src/config/polar-radar-config.js | 8 +- webapp/src/context/models/producers.js | 4 +- webapp/src/context/state.context.js | 14 +- webapp/src/gql/producers.js | 4 +- webapp/src/routes/BlockProducers/index.js | 42 +-- webapp/src/routes/BlockProducers/styles.js | 19 +- webapp/src/routes/index.js | 13 - webapp/yarn.lock | 307 ++++++++++-------- 17 files changed, 494 insertions(+), 416 deletions(-) create mode 100644 webapp/src/components/FilterBanner/index.js create mode 100644 webapp/src/components/FilterBanner/styles.js create mode 100644 webapp/src/config/filters.js diff --git a/webapp/src/components/CompareTool/CompareGraphView.js b/webapp/src/components/CompareTool/CompareGraphView.js index 78382b2b..639a77ec 100644 --- a/webapp/src/components/CompareTool/CompareGraphView.js +++ b/webapp/src/components/CompareTool/CompareGraphView.js @@ -132,86 +132,61 @@ const CompareGraphView = ({ - - - ({ ...data }))} /> - - {isProxy && selected.length > 0 && ( - - - {selected[0].name} - - - - - - )} - {!isProxy && ( - - - - setIsCollapsedView(event.target.checked) - } - value='isCollapsedView' - /> - } - label={t('compareToolCollapsedSwitch')} - /> - + + ({ ...data }))} /> + + {isProxy && selected.length > 0 && ( + + + {selected[0].name} + + + - )} - - - {selected.length > 0 ? ( - - ) : ( - - - {t('noSelectedBP')} - - - )} - + )} {!isProxy && ( - - - + + + + setIsCollapsedView(event.target.checked) + } + value='isCollapsedView' + /> + } + label={t('compareToolCollapsedSwitch')} + /> + )} + + + {selected.length > 0 ? ( + + ) : ( + + {t('noSelectedBP')} + + )} + @@ -229,6 +204,27 @@ const CompareGraphView = ({ )} + {!isProxy && ( + + + + + )} ) } diff --git a/webapp/src/components/CompareTool/CompareSliderView.js b/webapp/src/components/CompareTool/CompareSliderView.js index 0a7cacd3..df28339a 100644 --- a/webapp/src/components/CompareTool/CompareSliderView.js +++ b/webapp/src/components/CompareTool/CompareSliderView.js @@ -1,12 +1,12 @@ import React from 'react' import { makeStyles } from '@mui/styles' -// import useMediaQuery from '@mui/material/useMediaQuery' import CloseIcon from '@mui/icons-material/Close' import { useTranslation } from 'react-i18next' import PropTypes from 'prop-types' import Typography from '@mui/material/Typography' import Box from '@mui/material/Box' import _get from 'lodash.get' +import clsx from 'clsx' import PolarChart from '../PolarChart' @@ -23,15 +23,9 @@ const CompareSliderView = ({ }) => { const { t } = useTranslation('translations') const classes = useStyles() - // const isDesktop = useMediaQuery('(min-width:767px)') - // const [sizes, setSizes] = useState() - - // useEffect(() => { - // // setSizes(isDesktop ? 400 : '95%') - // }, [isDesktop]) return ( - + @@ -56,10 +50,9 @@ const CompareSliderView = ({ key={`slider-card-${name}-${index}`} className={classes.sliderCard} > - + - {name} diff --git a/webapp/src/components/CompareTool/index.js b/webapp/src/components/CompareTool/index.js index 2e8bd232..5be3ceb4 100644 --- a/webapp/src/components/CompareTool/index.js +++ b/webapp/src/components/CompareTool/index.js @@ -74,9 +74,7 @@ const CompareTool = ({ } return ( - + {isCollapsedView ? ( ) : ( - - )} - {!isCollapsedView && ( - - setIsCollapsedView(event.target.checked)} - value='isCollapsedView' - color='primary' - /> - } - label={t('compareToolCollapsedSwitch')} - /> + + + + setIsCollapsedView(event.target.checked)} + value='isCollapsedView' + color={isCollapsedView ? 'primary' : 'secondary'} + /> + } + label={t('compareToolCollapsedSwitch')} + /> + + setIsCollapsedView(event.target.checked)} + value='isCollapsedView' + color={isCollapsedView ? 'primary' : 'secondary'} + /> + } + label={t('compareToolCollapsedSwitch')} + /> + + {filtersConfig.filters.map(filter => ( + handleClose(filter)}> + {t(filter.value)} + + ))} + + + ) +} + +FilterBanner.propTypes = { + title: PropTypes.string, + page: PropTypes.string, + onFilterChange: PropTypes.func +} + +export default FilterBanner diff --git a/webapp/src/components/FilterBanner/styles.js b/webapp/src/components/FilterBanner/styles.js new file mode 100644 index 00000000..021314ff --- /dev/null +++ b/webapp/src/components/FilterBanner/styles.js @@ -0,0 +1,14 @@ +export default theme => ({ + filterBanner: { + display: 'flex', + justifyContent: 'space-between', + padding: theme.spacing(1, 1, 0, 1), + alignItems: 'center' + }, + pageTitle: { + textTransform: 'uppercase', + fontWeight: '500 !important', + fontSize: '0.875rem !important', + lineHeight: '1.75' + } +}) diff --git a/webapp/src/components/Sidebar/index.js b/webapp/src/components/Sidebar/index.js index 9133ccbe..f14f0cb1 100644 --- a/webapp/src/components/Sidebar/index.js +++ b/webapp/src/components/Sidebar/index.js @@ -1,16 +1,14 @@ -import React, { memo, useState, useEffect } from 'react' +import React, { memo } from 'react' import PropTypes from 'prop-types' import { NavLink as RouterNavLink, useHistory } from 'react-router-dom' import { useTranslation } from 'react-i18next' import Box from '@mui/material/Box' import Drawer from '@mui/material/Drawer' import Divider from '@mui/material/Divider' -import Chip from '@mui/material/Chip' import List from '@mui/material/List' import MuiListItem from '@mui/material/ListItem' import ListItemIcon from '@mui/material/ListItemIcon' import ListItemText from '@mui/material/ListItemText' -import Collapse from '@mui/material/Collapse' import Typography from '@mui/material/Typography' import AccountIcon from '@mui/icons-material/AccountCircle' import { makeStyles } from '@mui/styles' @@ -49,23 +47,10 @@ ExternalLink.propTypes = { className: PropTypes.string } -const ListItem = ({ - childrens, - name, - path, - icon, - badge, - handleOnClick, - openMenu, - isUserLogged, - handleSortBy -}) => { +const ListItem = ({ childrens, name, path, icon, isUserLogged }) => { const classes = useStyles() - const { t: tSort } = useTranslation('sortInput') const { t } = useTranslation('translations') - const sortBy = 'generalRate' // get this value form context - if (name === 'myAccount' && !isUserLogged) return <> return ( @@ -78,32 +63,10 @@ const ListItem = ({ activeClassName='active' className={classes.linkSidebar} href={path} - onClick={() => handleOnClick(name)} > {icon && {icon}} - {badge && } - {childrens && ( - - {childrens.map(({ value }, index) => ( - handleSortBy(value, name)} // setSortBy(value)} - > - - - ))} - - )} ) } @@ -113,26 +76,13 @@ ListItem.propTypes = { name: PropTypes.string, path: PropTypes.string, icon: PropTypes.node, - badge: PropTypes.string, - handleOnClick: PropTypes.func, - openMenu: PropTypes.bool, - isUserLogged: PropTypes.bool, - handleSortBy: PropTypes.func + isUserLogged: PropTypes.bool } const Sidebar = ({ routes, ...props }) => { const history = useHistory() const classes = useStyles() - const [state, { setSortBy }] = useSharedState() - const [openMenu, setOpenMenu] = useState(false) - - const handleOnClick = name => { - setOpenMenu(name === 'blockProducers') - } - - useEffect(() => { - setOpenMenu(history.location.pathname === '/block-producers') - }, []) + const [state] = useSharedState() return ( @@ -163,11 +113,7 @@ const Sidebar = ({ routes, ...props }) => { path={route.path} icon={route.icon} badge={route.badge} - childrens={route.childrens} - handleOnClick={handleOnClick} - openMenu={openMenu} isUserLogged={!!state.user} - handleSortBy={setSortBy} /> ))} diff --git a/webapp/src/config/filters.js b/webapp/src/config/filters.js new file mode 100644 index 00000000..30a20f3d --- /dev/null +++ b/webapp/src/config/filters.js @@ -0,0 +1,12 @@ +export const filters = [ + { sort: 'candidate_name', value: 'alphabetical' }, + { sort: 'average', value: 'generalRate' }, + { sort: 'eden_average', value: 'edenRate' }, + { sort: 'infrastructure', value: 'infrastructure' }, + { sort: 'community', value: 'community' }, + { sort: 'trustiness', value: 'trustiness' }, + { sort: 'development', value: 'development' }, + { sort: 'transparency', value: 'transparency' }, + { sort: 'total_votes', value: 'vote' }, + { sort: 'ratings_cntr', value: 'ratings' } +] diff --git a/webapp/src/config/index.js b/webapp/src/config/index.js index 0b05d2f5..632429e5 100644 --- a/webapp/src/config/index.js +++ b/webapp/src/config/index.js @@ -2,5 +2,6 @@ import * as graphqlConfig from './graphql.config' import * as mainConfig from './main.config' import * as ualConfig from './ual.config' import * as polarCharConfig from './polar-radar-config' +import * as filtersConfig from './filters' -export { graphqlConfig, mainConfig, ualConfig, polarCharConfig } +export { graphqlConfig, mainConfig, ualConfig, polarCharConfig, filtersConfig } diff --git a/webapp/src/config/polar-radar-config.js b/webapp/src/config/polar-radar-config.js index 22fecbcc..f9a553ac 100644 --- a/webapp/src/config/polar-radar-config.js +++ b/webapp/src/config/polar-radar-config.js @@ -1,6 +1,7 @@ export const options = { chart: { - polar: true + polar: true, + width: 350 }, credits: { enabled: false @@ -33,7 +34,10 @@ export const options = { startOnTick: true, tickmarkPlacement: 'on', labels: { - align: 'center' + align: 'center', + style: { + fontSize: '12px' + } } }, yAxis: { diff --git a/webapp/src/context/models/producers.js b/webapp/src/context/models/producers.js index 710d9cae..a22f67a5 100644 --- a/webapp/src/context/models/producers.js +++ b/webapp/src/context/models/producers.js @@ -6,11 +6,11 @@ import { } from '../../gql' import getBpDataModeled from '../../utils/modeled-bp-data' -export const getProducers = async limit => { +export const getProducers = async (limit, orderBy) => { const { data: { list, info } } = await client.query({ - variables: { limit }, + variables: { limit, orderBy }, query: GET_BLOCK_PRODUCERS, fetchPolicy: 'network-only' }) diff --git a/webapp/src/context/state.context.js b/webapp/src/context/state.context.js index 34e64772..9a01de44 100644 --- a/webapp/src/context/state.context.js +++ b/webapp/src/context/state.context.js @@ -20,7 +20,7 @@ const initialValue = { selectedProducers: [], blockProducer: null, compareBPToolVisible: false, - sortBlockProducersBy: null, + sortBlockProducersBy: { sort: 'total_votes', value: 'vote' }, proxies: { data: [], rows: 0 }, selectedProxies: [], proxy: null, @@ -184,16 +184,20 @@ export const useSharedState = () => { dispatch({ type: 'userChange', user }) } const setSortBy = (sortBy, page) => { - if (page === 'blockProducers') { + if (page === 'bp') { dispatch({ type: 'setSortProducersBy', sortBy }) } else { - // dispatch({ type: 'setSortProducersBy', sortBy }) + // dispatch({ type: 'setSortProxiesBy', sortBy }) } } // Block Producers Action - const setProducers = async limit => { - const blockProducers = await getProducers(limit) + const setProducers = async (limit, orderBy = null) => { + const filter = orderBy || state.sortBlockProducersBy.sort + const blockProducers = await getProducers(limit, [ + { [filter]: 'desc_nulls_last' }, + { bpjson: 'desc' } + ]) dispatch({ type: 'setProducers', blockProducers }) } diff --git a/webapp/src/gql/producers.js b/webapp/src/gql/producers.js index d8160d26..16763e37 100644 --- a/webapp/src/gql/producers.js +++ b/webapp/src/gql/producers.js @@ -1,7 +1,7 @@ import { gql } from '@apollo/client' export const GET_BLOCK_PRODUCERS = gql` - query blockProducers($limit: Int = 15) { + query blockProducers($limit: Int = 15, $orderBy: [producers_list_order_by!]) { info: producers_list_aggregate( where: { system: { _contains: { is_active: 1 } } } ) { @@ -12,7 +12,7 @@ export const GET_BLOCK_PRODUCERS = gql` list: producers_list( where: { system: { _contains: { is_active: 1 } } } limit: $limit - order_by: [{ bpjson: desc }, { total_votes: desc }] + order_by: $orderBy ) { owner system diff --git a/webapp/src/routes/BlockProducers/index.js b/webapp/src/routes/BlockProducers/index.js index a5be5c92..8f2b6d3f 100644 --- a/webapp/src/routes/BlockProducers/index.js +++ b/webapp/src/routes/BlockProducers/index.js @@ -13,6 +13,7 @@ import _get from 'lodash.get' import TitlePage from '../../components/PageTitle' import CompareTool from '../../components/CompareTool' import Card from '../../components/Card' +import FilterBanner from '../../components/FilterBanner' import getAverageValue from '../../utils/get-average-value' import { useSharedState } from '../../context/state.context' @@ -36,13 +37,11 @@ const AllBps = () => { showChipMessage: false }) - // const sortedBPs = applySortBy(sortBy, blockProducers) - const loadMore = () => setCurrentlyVisible(currentlyVisible + 12) // const goToTop = () => document.getElementById('mainContent').scrollTo(0, 0) - const handleToggleCompareTool = () => { - setCompareBPTool(!state.compareBPToolVisible) + const handleOnFliterChange = async filter => { + await setProducers(currentlyVisible, filter) } const handleToggleSelected = (item, isAddItem = false) => { @@ -58,8 +57,6 @@ const AllBps = () => { } const handleOpenDesktopVotingTool = () => { - console.log('handleOpenDesktopVotingTool') - // goToTop() !state.compareBPToolVisible && setCompareBPTool(true) } @@ -152,13 +149,6 @@ const AllBps = () => { setMoreRows(state.blockProducers.rows > currentlyVisible) }, [state.blockProducers]) - state.user && - console.log({ - isRated: state.user.userData.userRates.some( - ({ owner }) => owner === 'eoscostarica' - ) - }) - return ( @@ -181,7 +171,11 @@ const AllBps = () => { handleOnClear={handleOnClear} /> - + {(state.blockProducers.data || []).map(blockProducer => ( @@ -194,25 +188,7 @@ const AllBps = () => { blockProducer.owner )} toggleSelection={(isAdding, producerAccountName) => () => { - if (isAdding) { - if ( - !state.selectedProducers.length && - !state.compareBPToolVisible - ) { - handleToggleCompareTool() - } - - handleToggleSelected(producerAccountName, isAdding) - } else { - if ( - state.selectedProducers.length === 1 && - state.compareBPToolVisible - ) { - handleToggleCompareTool() - } - - handleToggleSelected(producerAccountName, isAdding) - } + handleToggleSelected(producerAccountName, isAdding) }} data={blockProducer} imageURL={_get(blockProducer, 'bpjson.org.branding.logo_256')} diff --git a/webapp/src/routes/BlockProducers/styles.js b/webapp/src/routes/BlockProducers/styles.js index 7dc13733..aacf1f25 100644 --- a/webapp/src/routes/BlockProducers/styles.js +++ b/webapp/src/routes/BlockProducers/styles.js @@ -43,17 +43,8 @@ export default theme => ({ } }, compareTool: { - paddingTop: '0 !important', - transform: 'scaleY(1)', - transformOrigin: 'top', - opacity: 1, height: '100%', - transition: [ - 'opacity 0.25s ease', - 'height 0.25s ease', - 'transform 0.25s ease', - 'min-height 0.25s ease' - ] + paddingTop: 0 }, bpCard: { backgroundColor: theme.palette.primary.light @@ -73,13 +64,15 @@ export default theme => ({ }, hiddenMobile: { display: 'none', - [theme.breakpoints.up('md')]: { + [theme.breakpoints.up('sm')]: { display: 'flex' } }, hiddenDesktop: { display: 'flex', - [theme.breakpoints.up('md')]: { + overflow: 'hidden', + maxHeight: '100vh', + [theme.breakpoints.up('sm')]: { display: 'none' } }, @@ -262,7 +255,7 @@ export default theme => ({ }, paperAnchor: { right: '0', - overflowY: 'initial' + overflowY: 'hidden' }, reliefGrid: { margin: '10px 16px 30px 16px', diff --git a/webapp/src/routes/index.js b/webapp/src/routes/index.js index 48de689f..2061d0a5 100644 --- a/webapp/src/routes/index.js +++ b/webapp/src/routes/index.js @@ -14,18 +14,6 @@ import { import { mainConfig } from '../config' -const filters = [ - { value: 'alphabetical' }, - { value: 'generalRate' }, - { value: 'edenRate' }, - { value: 'infrastructure' }, - { value: 'community' }, - { value: 'trustiness' }, - { value: 'development' }, - { value: 'transparency' }, - { value: 'vote' }, - { value: 'ratings' } -] const Home = lazy(() => import('./Home')) const BlockProducers = lazy(() => import('./BlockProducers')) const BlockProducerProfile = lazy(() => @@ -62,7 +50,6 @@ const routes = [ icon: , component: BlockProducers, path: '/block-producers', - childrens: filters, exact: true }, { diff --git a/webapp/yarn.lock b/webapp/yarn.lock index c9530e0e..e30b2e8c 100644 --- a/webapp/yarn.lock +++ b/webapp/yarn.lock @@ -3,9 +3,9 @@ "@apollo/client@^3.3.21": - version "3.4.13" - resolved "https://registry.yarnpkg.com/@apollo/client/-/client-3.4.13.tgz#81670c27b376e80e3845ecf6468e534d908fa5b5" - integrity sha512-/nH8z/0X6WJ+wtUREHTlKQGX4lo6u3XkF1hy+k4eCxLZzT5+VRw1rm92iIkj1H85vep/eE/KV3DdRq1x3t9NnQ== + version "3.4.15" + resolved "https://registry.yarnpkg.com/@apollo/client/-/client-3.4.15.tgz#0aa05ff2bb54092919b501ef348ade6330911670" + integrity sha512-CnlT9i7TgHagkKQNvti81A9KcbIMqgpUPGJJL6bg5spTsB2R/5J6E7qiPcMvXuuXwR2xe4FmE4Ey4HizStb8Hg== dependencies: "@graphql-typed-document-node/core" "^3.0.0" "@wry/context" "^0.6.0" @@ -1632,6 +1632,17 @@ hash.js "^1.0.0" tslib "^2.0.3" +"@greymass/eosio@^0.5.0": + version "0.5.0" + resolved "https://registry.yarnpkg.com/@greymass/eosio/-/eosio-0.5.0.tgz#04d7c5f6375254d5acafc7d3a309501c9638615b" + integrity sha512-BE3/Z2p7wWRBFw/PqgzSN/bv+4QV5KSk7rlOT7CsnS8KCc25nCWfeimw4fZa+i5T1z2uycfQqQB9BnGj57xo6A== + dependencies: + bn.js "^4.11.9" + brorand "^1.1.0" + elliptic "^6.5.4" + hash.js "^1.0.0" + tslib "^2.0.3" + "@hapi/address@2.x.x": version "2.1.4" resolved "https://registry.yarnpkg.com/@hapi/address/-/address-2.1.4.tgz#5d67ed43f3fd41a69d4b9ff7b56e7c0d1d0a81e5" @@ -1865,10 +1876,10 @@ "@types/yargs" "^15.0.0" chalk "^4.0.0" -"@jest/types@^27.1.1": - version "27.1.1" - resolved "https://registry.yarnpkg.com/@jest/types/-/types-27.1.1.tgz#77a3fc014f906c65752d12123a0134359707c0ad" - integrity sha512-yqJPDDseb0mXgKqmNqypCsb85C22K1aY5+LUxh7syIM9n/b0AsaltxNy+o6tt29VcfGDpYEve175bm3uOhcehA== +"@jest/types@^27.2.4": + version "27.2.4" + resolved "https://registry.yarnpkg.com/@jest/types/-/types-27.2.4.tgz#2430042a66e00dc5b140c3636f4474d464c21ee8" + integrity sha512-IDO2ezTxeMvQAHxzG/ZvEyA47q0aVfzT95rGFl7bZs/Go0aIucvfDbS2rmnoEdXxlLQhcolmoG/wvL/uKx4tKA== dependencies: "@types/istanbul-lib-coverage" "^2.0.0" "@types/istanbul-reports" "^3.0.0" @@ -2004,10 +2015,10 @@ prop-types "^15.7.2" react-is "^16.8.0 || ^17.0.0" -"@mui/core@5.0.0-alpha.48": - version "5.0.0-alpha.48" - resolved "https://registry.yarnpkg.com/@mui/core/-/core-5.0.0-alpha.48.tgz#ed9517bd3d2c2da12142f1958df2503567be459a" - integrity sha512-H/QQwKsr2EqPAnP35DGDpWihk5BOFYGhO52rIHb3XKOfoUjDCrCHBy2kvr3dLWJDmJXr/QzYj3AX10n5XzlaMg== +"@mui/core@5.0.0-alpha.49": + version "5.0.0-alpha.49" + resolved "https://registry.yarnpkg.com/@mui/core/-/core-5.0.0-alpha.49.tgz#e74d6ec7f83f85b55d48aa05ea6b7cefff88ce1b" + integrity sha512-bZ7UgH84AuKf/IT0U+knHEelDxLV0lNVFg7rKkkDfXEwUpTtAZEtZPFJjNngapSB/4MuFjaFsttex+0DGC5Z1Q== dependencies: "@babel/runtime" "^7.15.4" "@emotion/is-prop-valid" "^1.1.0" @@ -2024,17 +2035,17 @@ "@babel/runtime" "^7.15.4" "@mui/lab@^5.0.0-alpha.48": - version "5.0.0-alpha.48" - resolved "https://registry.yarnpkg.com/@mui/lab/-/lab-5.0.0-alpha.48.tgz#e48c95e9f11351a76a672095594aeb2453d7414d" - integrity sha512-ukYcx1ReSy4taQBMIPTkOaSz+CwgxYih3XwTCGTv84atRWMFhfqJO3Ofe8rQ5/innMDbBlSPkjaiMSag8d3QeQ== + version "5.0.0-alpha.49" + resolved "https://registry.yarnpkg.com/@mui/lab/-/lab-5.0.0-alpha.49.tgz#fd26e4f76c1b28b7884c9e89bd710e7b34a99af2" + integrity sha512-AKTh3gAsP5GaveAoBAjEvyuuyFMYzyfUAwo7wvz9A/EiTnkc+2QXsSO7W4ykTIjNoIGBrTd9bTV/YQNK6FpPMw== dependencies: "@babel/runtime" "^7.15.4" "@date-io/date-fns" "^2.10.6" "@date-io/dayjs" "^2.10.6" "@date-io/luxon" "^2.10.6" "@date-io/moment" "^2.10.6" - "@mui/core" "5.0.0-alpha.48" - "@mui/system" "^5.0.1" + "@mui/core" "5.0.0-alpha.49" + "@mui/system" "^5.0.2" "@mui/utils" "^5.0.1" clsx "^1.1.1" prop-types "^15.7.2" @@ -2043,13 +2054,13 @@ rifm "^0.12.0" "@mui/material@^5.0.1": - version "5.0.1" - resolved "https://registry.yarnpkg.com/@mui/material/-/material-5.0.1.tgz#5690cd5bf7d9de48008269c89b22c7d7495cbc6c" - integrity sha512-+/JJzRcORUf5MiZnzuqsPFRgxm3/0CUi1wE97ZQ2y7r+EnDVsjJLcjAH9Q9GY3k9zkPIpYb9Hig/+HT6AGZRnQ== + version "5.0.2" + resolved "https://registry.yarnpkg.com/@mui/material/-/material-5.0.2.tgz#380cf0ef42c538a68158b4da19c317178b22d10f" + integrity sha512-LD2xHSjTLmbN0UoCuKTu09L/7JjpEzg+Cophf+dVJOTNoK7VI0Eqv3bmpF/9pDIk5dVKmeU9Eh4t2lW1ZifM6A== dependencies: "@babel/runtime" "^7.15.4" - "@mui/core" "5.0.0-alpha.48" - "@mui/system" "^5.0.1" + "@mui/core" "5.0.0-alpha.49" + "@mui/system" "^5.0.2" "@mui/types" "^7.0.0" "@mui/utils" "^5.0.1" "@popperjs/core" "^2.4.4" @@ -2102,10 +2113,10 @@ jss-plugin-vendor-prefixer "^10.8.0" prop-types "^15.7.2" -"@mui/system@^5.0.1": - version "5.0.1" - resolved "https://registry.yarnpkg.com/@mui/system/-/system-5.0.1.tgz#2a8592d116c5a05b6991316d772937d100fc7e0a" - integrity sha512-pGNKUpjK5hm4apZAUZu7LugemBPoZnNvNNCI2miI/BXxqyx41mL9+iT9p6Qe9uDOh8Z6GUbLIzvOjSTP+ECRZw== +"@mui/system@^5.0.2": + version "5.0.2" + resolved "https://registry.yarnpkg.com/@mui/system/-/system-5.0.2.tgz#9999ab61801810ea01c44588fd0dcc1f64dfcedc" + integrity sha512-K6wMbiSEYSMeYUw7zmZ2/50JFthqtuTz4OADyKc4ic2RP8ubAf/duH/nkJ4gtsKcewU4RIub0HQHl5F77WVp4Q== dependencies: "@babel/runtime" "^7.15.4" "@mui/private-theming" "^5.0.1" @@ -2552,9 +2563,9 @@ integrity sha1-7ihweulOEdK4J7y+UnC86n8+ce4= "@types/lodash@^4.14.165": - version "4.14.173" - resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.173.tgz#9d3b674c67a26cf673756f6aca7b429f237f91ed" - integrity sha512-vv0CAYoaEjCw/mLy96GBTnRoZrSxkGE0BKzKimdR8P3OzrNYNvBgtW7p055A+E8C31vXNUhWKoFCbhq7gbyhFg== + version "4.14.175" + resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.175.tgz#b78dfa959192b01fae0ad90e166478769b215f45" + integrity sha512-XmdEOrKQ8a1Y/yxQFOMbC47G/V2VDO1GvMRnl4O75M4GW/abC5tnfzadQYkqEveqRM1dEJGFFegfPNA2vvx2iw== "@types/minimatch@*": version "3.0.5" @@ -2562,9 +2573,9 @@ integrity sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ== "@types/node@*", "@types/node@>=6": - version "16.9.6" - resolved "https://registry.yarnpkg.com/@types/node/-/node-16.9.6.tgz#040a64d7faf9e5d9e940357125f0963012e66f04" - integrity sha512-YHUZhBOMTM3mjFkXVcK+WwAcYmyhe1wL4lfqNtzI0b3qAy7yuSetnM7QJazgE5PFmgVTNGiLOgRFfJMqW7XpSQ== + version "16.10.2" + resolved "https://registry.yarnpkg.com/@types/node/-/node-16.10.2.tgz#5764ca9aa94470adb4e1185fe2e9f19458992b2e" + integrity sha512-zCclL4/rx+W5SQTzFs9wyvvyCwoK9QtBpratqz2IYJ3O8Umrn0m3nsTv0wQBk9sRGpvUe9CwPDrQFB10f1FIjQ== "@types/normalize-package-data@^2.4.0": version "2.4.1" @@ -2577,9 +2588,9 @@ integrity sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA== "@types/prettier@^2.0.0": - version "2.3.2" - resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.3.2.tgz#fc8c2825e4ed2142473b4a81064e6e081463d1b3" - integrity sha512-eI5Yrz3Qv4KPUa/nSIAi0h+qX0XyewOliug5F2QAtuRg6Kjg6jfmxe1GIwoIRhZspD1A0RP8ANrPwvEXXtRFog== + version "2.4.1" + resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.4.1.tgz#e1303048d5389563e130f5bdd89d37a99acb75eb" + integrity sha512-Fo79ojj3vdEZOHg3wR9ksAMRz4P3S5fDB5e/YWZiFnyFQI1WY2Vftu9XoXVVtJfxB7Bpce/QTqWSSntkz2Znrw== "@types/prop-types@*", "@types/prop-types@^15.7.4": version "15.7.4" @@ -2606,9 +2617,9 @@ "@types/react" "*" "@types/react@*": - version "17.0.24" - resolved "https://registry.yarnpkg.com/@types/react/-/react-17.0.24.tgz#7e1b3f78d0fc53782543f9bce6d949959a5880bd" - integrity sha512-eIpyco99gTH+FTI3J7Oi/OH8MZoFMJuztNRimDOJwH4iGIsKV2qkGnk4M9VzlaVWeEEWLWSQRy0FEA0Kz218cg== + version "17.0.25" + resolved "https://registry.yarnpkg.com/@types/react/-/react-17.0.25.tgz#8b88c226e54910762decc9de2aa36b4dc9240503" + integrity sha512-IXrzSOr3CVbEQgmjEdCWF57J7CVaJ7lL/n4penxHm8h0XIcr0AxqGucogh2zj3qRxgk4M4JImOP/MfomkPOhvQ== dependencies: "@types/prop-types" "*" "@types/scheduler" "*" @@ -2701,27 +2712,28 @@ integrity sha512-fbF6oTd4sGGy0xjHPKAt+eS2CrxJ3+6gQ3FGcBoIJR2TLAyCkCyI8JqZNy+FeON0AhVgNJoUumVoZQjBFUqHkw== "@typescript-eslint/eslint-plugin@^4.5.0": - version "4.31.2" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.31.2.tgz#9f41efaee32cdab7ace94b15bd19b756dd099b0a" - integrity sha512-w63SCQ4bIwWN/+3FxzpnWrDjQRXVEGiTt9tJTRptRXeFvdZc/wLiz3FQUwNQ2CVoRGI6KUWMNUj/pk63noUfcA== + version "4.32.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.32.0.tgz#46d2370ae9311092f2a6f7246d28357daf2d4e89" + integrity sha512-+OWTuWRSbWI1KDK8iEyG/6uK2rTm3kpS38wuVifGUTDB6kjEuNrzBI1MUtxnkneuWG/23QehABe2zHHrj+4yuA== dependencies: - "@typescript-eslint/experimental-utils" "4.31.2" - "@typescript-eslint/scope-manager" "4.31.2" + "@typescript-eslint/experimental-utils" "4.32.0" + "@typescript-eslint/scope-manager" "4.32.0" debug "^4.3.1" functional-red-black-tree "^1.0.1" + ignore "^5.1.8" regexpp "^3.1.0" semver "^7.3.5" tsutils "^3.21.0" -"@typescript-eslint/experimental-utils@4.31.2", "@typescript-eslint/experimental-utils@^4.0.1": - version "4.31.2" - resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-4.31.2.tgz#98727a9c1e977dd5d20c8705e69cd3c2a86553fa" - integrity sha512-3tm2T4nyA970yQ6R3JZV9l0yilE2FedYg8dcXrTar34zC9r6JB7WyBQbpIVongKPlhEMjhQ01qkwrzWy38Bk1Q== +"@typescript-eslint/experimental-utils@4.32.0", "@typescript-eslint/experimental-utils@^4.0.1": + version "4.32.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-4.32.0.tgz#53a8267d16ca5a79134739129871966c56a59dc4" + integrity sha512-WLoXcc+cQufxRYjTWr4kFt0DyEv6hDgSaFqYhIzQZ05cF+kXfqXdUh+//kgquPJVUBbL3oQGKQxwPbLxHRqm6A== dependencies: "@types/json-schema" "^7.0.7" - "@typescript-eslint/scope-manager" "4.31.2" - "@typescript-eslint/types" "4.31.2" - "@typescript-eslint/typescript-estree" "4.31.2" + "@typescript-eslint/scope-manager" "4.32.0" + "@typescript-eslint/types" "4.32.0" + "@typescript-eslint/typescript-estree" "4.32.0" eslint-scope "^5.1.1" eslint-utils "^3.0.0" @@ -2737,32 +2749,32 @@ eslint-utils "^2.0.0" "@typescript-eslint/parser@^4.5.0": - version "4.31.2" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-4.31.2.tgz#54aa75986e3302d91eff2bbbaa6ecfa8084e9c34" - integrity sha512-EcdO0E7M/sv23S/rLvenHkb58l3XhuSZzKf6DBvLgHqOYdL6YFMYVtreGFWirxaU2mS1GYDby3Lyxco7X5+Vjw== + version "4.32.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-4.32.0.tgz#751ecca0e2fecd3d44484a9b3049ffc1871616e5" + integrity sha512-lhtYqQ2iEPV5JqV7K+uOVlPePjClj4dOw7K4/Z1F2yvjIUvyr13yJnDzkK6uon4BjHYuHy3EG0c2Z9jEhFk56w== dependencies: - "@typescript-eslint/scope-manager" "4.31.2" - "@typescript-eslint/types" "4.31.2" - "@typescript-eslint/typescript-estree" "4.31.2" + "@typescript-eslint/scope-manager" "4.32.0" + "@typescript-eslint/types" "4.32.0" + "@typescript-eslint/typescript-estree" "4.32.0" debug "^4.3.1" -"@typescript-eslint/scope-manager@4.31.2": - version "4.31.2" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-4.31.2.tgz#1d528cb3ed3bcd88019c20a57c18b897b073923a" - integrity sha512-2JGwudpFoR/3Czq6mPpE8zBPYdHWFGL6lUNIGolbKQeSNv4EAiHaR5GVDQaLA0FwgcdcMtRk+SBJbFGL7+La5w== +"@typescript-eslint/scope-manager@4.32.0": + version "4.32.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-4.32.0.tgz#e03c8668f8b954072b3f944d5b799c0c9225a7d5" + integrity sha512-DK+fMSHdM216C0OM/KR1lHXjP1CNtVIhJ54kQxfOE6x8UGFAjha8cXgDMBEIYS2XCYjjCtvTkjQYwL3uvGOo0w== dependencies: - "@typescript-eslint/types" "4.31.2" - "@typescript-eslint/visitor-keys" "4.31.2" + "@typescript-eslint/types" "4.32.0" + "@typescript-eslint/visitor-keys" "4.32.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" integrity sha512-+3+FCUJIahE9q0lDi1WleYzjCwJs5hIsbugIgnbB+dSCYUxl8L6PwmsyOPFZde2hc1DlTo/xnkOgiTLSyAbHiQ== -"@typescript-eslint/types@4.31.2": - version "4.31.2" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.31.2.tgz#2aea7177d6d744521a168ed4668eddbd912dfadf" - integrity sha512-kWiTTBCTKEdBGrZKwFvOlGNcAsKGJSBc8xLvSjSppFO88AqGxGNYtF36EuEYG6XZ9vT0xX8RNiHbQUKglbSi1w== +"@typescript-eslint/types@4.32.0": + version "4.32.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.32.0.tgz#52c633c18da47aee09449144bf59565ab36df00d" + integrity sha512-LE7Z7BAv0E2UvqzogssGf1x7GPpUalgG07nGCBYb1oK4mFsOiFC/VrSMKbZQzFJdN2JL5XYmsx7C7FX9p9ns0w== "@typescript-eslint/typescript-estree@3.10.1": version "3.10.1" @@ -2778,13 +2790,13 @@ semver "^7.3.2" tsutils "^3.17.1" -"@typescript-eslint/typescript-estree@4.31.2": - version "4.31.2" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-4.31.2.tgz#abfd50594d8056b37e7428df3b2d185ef2d0060c" - integrity sha512-ieBq8U9at6PvaC7/Z6oe8D3czeW5d//Fo1xkF/s9394VR0bg/UaMYPdARiWyKX+lLEjY3w/FNZJxitMsiWv+wA== +"@typescript-eslint/typescript-estree@4.32.0": + version "4.32.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-4.32.0.tgz#db00ccc41ccedc8d7367ea3f50c6994b8efa9f3b" + integrity sha512-tRYCgJ3g1UjMw1cGG8Yn1KzOzNlQ6u1h9AmEtPhb5V5a1TmiHWcRyF/Ic+91M4f43QeChyYlVTcf3DvDTZR9vw== dependencies: - "@typescript-eslint/types" "4.31.2" - "@typescript-eslint/visitor-keys" "4.31.2" + "@typescript-eslint/types" "4.32.0" + "@typescript-eslint/visitor-keys" "4.32.0" debug "^4.3.1" globby "^11.0.3" is-glob "^4.0.1" @@ -2798,12 +2810,12 @@ dependencies: eslint-visitor-keys "^1.1.0" -"@typescript-eslint/visitor-keys@4.31.2": - version "4.31.2" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-4.31.2.tgz#7d5b4a4705db7fe59ecffb273c1d082760f635cc" - integrity sha512-PrBId7EQq2Nibns7dd/ch6S6/M4/iwLM9McbgeEbCXfxdwRUNxJ4UNreJ6Gh3fI2GNKNrWnQxKL7oCPmngKBug== +"@typescript-eslint/visitor-keys@4.32.0": + version "4.32.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-4.32.0.tgz#455ba8b51242f2722a497ffae29313f33b14cb7f" + integrity sha512-e7NE0qz8W+atzv3Cy9qaQ7BTLwWsm084Z0c4nIO2l3Bp6u9WIgdqCgyPyV5oSPDMIW3b20H59OOCmVk3jw3Ptw== dependencies: - "@typescript-eslint/types" "4.31.2" + "@typescript-eslint/types" "4.32.0" eslint-visitor-keys "^2.0.0" "@webassemblyjs/ast@1.9.0": @@ -3504,13 +3516,13 @@ attr-accept@^2.2.1: integrity sha512-7prDjvt9HmqiZ0cl5CRjtS84sEyhsHP2coDkaZKRKVfCDo9s7iw7ChVmar78Gu9pC4SoR/28wFu/G5JJhTnqEg== autoprefixer@^9.6.1: - version "9.8.6" - resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-9.8.6.tgz#3b73594ca1bf9266320c5acf1588d74dea74210f" - integrity sha512-XrvP4VVHdRBCdX1S3WXVD8+RyG9qeb1D5Sn1DeLiG2xfSpzellk5k54xbUERJ3M5DggQxes39UGOTP8CFrEGbg== + version "9.8.7" + resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-9.8.7.tgz#e3c12de18a800af1a1a8155fbc01dc7de29ea184" + integrity sha512-7Hg99B1eTH5+LgmUBUSmov1Z3bsggQJS7v3IMGo6wcScnbRuvtMc871J9J+4bSbIqa9LSX/zypFXJ8sXHpMJeQ== dependencies: browserslist "^4.12.0" caniuse-lite "^1.0.30001109" - colorette "^1.2.1" + nanocolors "^0.2.8" normalize-range "^0.1.2" num2fraction "^1.2.2" postcss "^7.0.32" @@ -4005,7 +4017,7 @@ browserslist@4.14.2: escalade "^3.0.2" node-releases "^1.1.61" -browserslist@^4.0.0, browserslist@^4.12.0, browserslist@^4.16.6, browserslist@^4.17.0, browserslist@^4.3.4, browserslist@^4.6.2, browserslist@^4.6.4: +browserslist@^4.0.0, browserslist@^4.12.0, browserslist@^4.16.6, browserslist@^4.17.1, browserslist@^4.3.4, browserslist@^4.6.2, browserslist@^4.6.4: version "4.17.1" resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.17.1.tgz#a98d104f54af441290b7d592626dd541fa642eb9" integrity sha512-aLD0ZMDSnF4lUt4ZDNgqi5BUn9BZ7YdQdI/cYlILrhdSSZJLU9aNZoD5/NBmM4SK34APB2e83MOsRt1EnkuyaQ== @@ -4228,11 +4240,9 @@ caniuse-api@^3.0.0: lodash.uniq "^4.5.0" caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000981, caniuse-lite@^1.0.30001109, caniuse-lite@^1.0.30001125, caniuse-lite@^1.0.30001259: - version "1.0.30001260" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001260.tgz#e3be3f34ddad735ca4a2736fa9e768ef34316270" - integrity sha512-Fhjc/k8725ItmrvW5QomzxLeojewxvqiYCKeFcfFEhut28IVLdpHU19dneOmltZQIE5HNbawj1HYD+1f2bM1Dg== - dependencies: - nanocolors "^0.1.0" + version "1.0.30001261" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001261.tgz#96d89813c076ea061209a4e040d8dcf0c66a1d01" + integrity sha512-vM8D9Uvp7bHIN0fZ2KQ4wnmYFpJo/Etb4Vwsuc+ka0tfGDHvOPrFm6S/7CCNLSOkAUjenT2HnUPESdOIL91FaA== capture-exit@^2.0.0: version "2.0.0" @@ -4508,7 +4518,7 @@ color@^3.0.0: color-convert "^1.9.3" color-string "^1.6.0" -colorette@^1.2.1, colorette@^1.4.0: +colorette@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.4.0.tgz#5190fbb87276259a86ad700bff2c6d6faa3fca40" integrity sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g== @@ -4709,17 +4719,17 @@ copy-descriptor@^0.1.0: integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= core-js-compat@^3.16.0, core-js-compat@^3.16.2, core-js-compat@^3.6.2: - version "3.18.0" - resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.18.0.tgz#fb360652201e8ac8da812718c008cd0482ed9b42" - integrity sha512-tRVjOJu4PxdXjRMEgbP7lqWy1TWJu9a01oBkn8d+dNrhgmBwdTkzhHZpVJnEmhISLdoJI1lX08rcBcHi3TZIWg== + version "3.18.1" + resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.18.1.tgz#01942a0877caf9c6e5007c027183cf0bdae6a191" + integrity sha512-XJMYx58zo4W0kLPmIingVZA10+7TuKrMLPt83+EzDmxFJQUMcTVVmQ+n5JP4r6Z14qSzhQBRi3NSWoeVyKKXUg== dependencies: - browserslist "^4.17.0" + browserslist "^4.17.1" semver "7.0.0" core-js-pure@^3.16.0: - version "3.18.0" - resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.18.0.tgz#e5187347bae66448c9e2d67c01c34c4df3261dc5" - integrity sha512-ZnK+9vyuMhKulIGqT/7RHGRok8RtkHMEX/BGPHkHx+ouDkq+MUvf9mfIgdqhpmPDu8+V5UtRn/CbCRc9I4lX4w== + version "3.18.1" + resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.18.1.tgz#097d34d24484be45cea700a448d1e74622646c80" + integrity sha512-kmW/k8MaSuqpvA1xm2l3TVlBuvW+XBkcaOroFUpO3D4lsTGQWBTb/tBDCf/PNkkPLrwgrkQRIYNPB0CeqGJWGQ== core-js@^2.4.0, core-js@^2.6.5: version "2.6.12" @@ -4727,9 +4737,9 @@ core-js@^2.4.0, core-js@^2.6.5: integrity sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ== core-js@^3.15.2, core-js@^3.6.5: - version "3.18.0" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.18.0.tgz#9af3f4a6df9ba3428a3fb1b171f1503b3f40cc49" - integrity sha512-WJeQqq6jOYgVgg4NrXKL0KLQhi0CT4ZOCvFL+3CQ5o7I6J8HkT5wd53EadMfqTDp1so/MT1J+w2ujhWcCJtN7w== + version "3.18.1" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.18.1.tgz#289d4be2ce0085d40fc1244c0b1a54c00454622f" + integrity sha512-vJlUi/7YdlCZeL6fXvWNaLUPh/id12WXj3MbkMw5uOyF0PfWPBNOCNbs53YqgrvtujLNlt9JQpruyIKkUZ+PKA== core-util-is@~1.0.0: version "1.0.3" @@ -5595,9 +5605,9 @@ ejs@^2.6.1: integrity sha512-7vmuyh5+kuUyJKePhQfRQBhXV5Ce+RnaeeQArKu1EAMpL3WbgMt5WG6uQZpEVvYSSsxMXRKOewtDk9RaTKXRlA== electron-to-chromium@^1.3.564, electron-to-chromium@^1.3.846: - version "1.3.849" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.849.tgz#45a65a392565abc5b864624b9753393336426f4b" - integrity sha512-RweyW60HPOqIcxoKTGr38Yvtf2aliSUqX8dB3e9geJ0Bno0YLjcOX5F7/DPVloBkJWaPZ7xOM1A0Yme2T1A34w== + version "1.3.854" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.854.tgz#003f0b9c80eccc35be0ef04a0e0b1c31a10b90d5" + integrity sha512-00/IIC1mFPkq32MhUJyLdcTp7+wsKK2G3Sb65GSas9FKJQGYkDcZ4GwJkkxf5YyM3ETvl6n+toV8OmtXl4IA/g== elliptic@6.5.0: version "6.5.0" @@ -5717,11 +5727,11 @@ env-cmd@^10.1.0: cross-spawn "^7.0.0" eosio-signing-request@^2.2.0, eosio-signing-request@^2.2.1: - version "2.2.2" - resolved "https://registry.yarnpkg.com/eosio-signing-request/-/eosio-signing-request-2.2.2.tgz#281cfe0843dc80205c89003d5638baf70fdcc449" - integrity sha512-lxRBHYkk2rAnnZrFnTqweD1FLH3usL5oE24m3+1zNK2vJHRVlIyUk7tlUlmax78j8+FE54Po8LQCQ8TrCSSFGg== + version "2.3.1" + resolved "https://registry.yarnpkg.com/eosio-signing-request/-/eosio-signing-request-2.3.1.tgz#9a0b09ec0dcb5cbd461516779fb47890af7365ef" + integrity sha512-74ouYaB00+Rq4lUxQMRtB9mXU+yd6vW9I6Iq3e8480CO0axaZc7h0ru2GBqO92InclmTnEFDYhr/MFK5yADiJg== dependencies: - "@greymass/eosio" "^0.4.0" + "@greymass/eosio" "^0.5.0" tslib "^2.0.3" eosjs-api@^7.0.4: @@ -5847,9 +5857,9 @@ error-stack-parser@^2.0.6: stackframe "^1.1.1" es-abstract@^1.17.2, es-abstract@^1.18.0-next.1, es-abstract@^1.18.0-next.2, es-abstract@^1.18.1, es-abstract@^1.18.2: - version "1.18.6" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.18.6.tgz#2c44e3ea7a6255039164d26559777a6d978cb456" - integrity sha512-kAeIT4cku5eNLNuUKhlmtuk1/TRZvQoYccn6TO0cSVdf1kzB0T7+dYuVK9MWM7l+/53W2Q8M7N2c6MQvhXFcUQ== + version "1.18.7" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.18.7.tgz#122daaa523d0a10b0f1be8ed4ce1ee68330c5bb2" + integrity sha512-uFG1gyVX91tZIiDWNmPsL8XNpiCk/6tkB7MZphoSJflS4w+KgWyQ2gjCVDnsPxFAo9WjRXG3eqONNYdfbJjAtw== dependencies: call-bind "^1.0.2" es-to-primitive "^1.2.1" @@ -6052,9 +6062,9 @@ eslint-plugin-import@~2.22.1: tsconfig-paths "^3.9.0" eslint-plugin-jest@^24.1.0: - version "24.4.2" - resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-24.4.2.tgz#9e8cf05ee6a0e3025e6149df2f36950abfa8d5bf" - integrity sha512-jNMnqwX75z0RXRMXkxwb/+9ylKJYJLJ8nT8nBT0XFM5qx4IQGxP4edMawa0qGkSbHae0BDPBmi8I2QF0/F04XQ== + version "24.5.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-24.5.0.tgz#a223a0040a19af749a161807254f0e47f5bfdcc3" + integrity sha512-Cm+XdX7Nms2UXGRnivHFVcM3ZmlKheHvc9VD78iZLO1XcqB59WbVjrMSiesCbHDlToxWjMJDiJMgc1CzFE13Vg== dependencies: "@typescript-eslint/experimental-utils" "^4.0.1" @@ -6801,9 +6811,9 @@ flush-write-stream@^1.0.0: readable-stream "^2.3.6" flux@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/flux/-/flux-4.0.1.tgz#7843502b02841d4aaa534af0b373034a1f75ee5c" - integrity sha512-emk4RCvJ8RzNP2lNpphKnG7r18q8elDYNAPx7xn+bDeOIo9FFfxEfIQ2y6YbQNmnsGD3nH1noxtLE64Puz1bRQ== + version "4.0.2" + resolved "https://registry.yarnpkg.com/flux/-/flux-4.0.2.tgz#d71dcaf6cb51ca059f303f3d964d6f325d444952" + integrity sha512-u/ucO5ezm3nBvdaSGkWpDlzCePoV+a9x3KHmy13TV/5MzOaCZDN8Mfd94jmf0nOi8ZZay+nOKbBUkOe2VNaupQ== dependencies: fbemitter "^3.0.0" fbjs "^3.0.0" @@ -7568,7 +7578,7 @@ ignore@^4.0.6: resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== -ignore@^5.1.1, ignore@^5.1.4: +ignore@^5.1.1, ignore@^5.1.4, ignore@^5.1.8: version "5.1.8" resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.8.tgz#f150a8b50a34289b33e22f5889abd4d8016f0e57" integrity sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw== @@ -7812,9 +7822,9 @@ is-color-stop@^1.0.0: rgba-regex "^1.0.0" is-core-module@^2.0.0, is-core-module@^2.2.0, is-core-module@^2.6.0: - version "2.6.0" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.6.0.tgz#d7553b2526fe59b92ba3e40c8df757ec8a709e19" - integrity sha512-wShG8vs60jKfPWpF2KZRaAtvt3a20OAn7+IJ6hLPECpSABLcKtFKTTI4ZtH5QcBruBHlq+WsdHWyz0BCZW7svQ== + version "2.7.0" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.7.0.tgz#3c0ef7d31b4acfc574f80c58409d568a836848e3" + integrity sha512-ByY+tjCciCr+9nLryBYcSD50EOGWt95c7tIsKTG1J2ixKKXPvF7Ej3AVd+UfDydAJom3biBGDBALaO79ktwgEQ== dependencies: has "^1.0.3" @@ -7907,9 +7917,9 @@ is-glob@^3.1.0: is-extglob "^2.1.0" is-glob@^4.0.0, is-glob@^4.0.1, is-glob@~4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc" - integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg== + version "4.0.3" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" + integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== dependencies: is-extglob "^2.1.1" @@ -8248,14 +8258,14 @@ jest-diff@^26.6.2: pretty-format "^26.6.2" jest-diff@^27.0.0: - version "27.2.0" - resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-27.2.0.tgz#bda761c360f751bab1e7a2fe2fc2b0a35ce8518c" - integrity sha512-QSO9WC6btFYWtRJ3Hac0sRrkspf7B01mGrrQEiCW6TobtViJ9RWL0EmOs/WnBsZDsI/Y2IoSHZA2x6offu0sYw== + version "27.2.4" + resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-27.2.4.tgz#171c51d3d2c105c457100fee6e7bf7cee51c8d8c" + integrity sha512-bLAVlDSCR3gqUPGv+4nzVpEXGsHh98HjUL7Vb2hVyyuBDoQmja8eJb0imUABsuxBeUVmf47taJSAd9nDrwWKEg== dependencies: chalk "^4.0.0" diff-sequences "^27.0.6" jest-get-type "^27.0.6" - pretty-format "^27.2.0" + pretty-format "^27.2.4" jest-docblock@^26.0.0: version "26.0.0" @@ -9559,15 +9569,20 @@ nanoclone@^0.2.1: resolved "https://registry.yarnpkg.com/nanoclone/-/nanoclone-0.2.1.tgz#dd4090f8f1a110d26bb32c49ed2f5b9235209ed4" integrity sha512-wynEP02LmIbLpcYw8uBKpcfF6dmg2vcpKqxeH5UcoKEYdExslsdUA4ugFauuaeYdTB76ez6gJW8XAZ6CgkXYxA== -nanocolors@^0.1.0, nanocolors@^0.1.5: +nanocolors@^0.1.5: version "0.1.12" resolved "https://registry.yarnpkg.com/nanocolors/-/nanocolors-0.1.12.tgz#8577482c58cbd7b5bb1681db4cf48f11a87fd5f6" integrity sha512-2nMHqg1x5PU+unxX7PGY7AuYxl2qDx7PSrTRjizr8sxdd3l/3hBuWWaki62qmtYm2U5i4Z5E7GbjlyDFhs9/EQ== +nanocolors@^0.2.2, nanocolors@^0.2.8: + version "0.2.12" + resolved "https://registry.yarnpkg.com/nanocolors/-/nanocolors-0.2.12.tgz#4d05932e70116078673ea4cc6699a1c56cc77777" + integrity sha512-SFNdALvzW+rVlzqexid6epYdt8H9Zol7xDoQarioEFcFN0JHo4CYNztAxmtfgGTVRCmFlEOqqhBpoFGKqSAMug== + nanoid@^3.1.25: - version "3.1.25" - resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.25.tgz#09ca32747c0e543f0e1814b7d3793477f9c8e152" - integrity sha512-rdwtIXaXCLFAQbnfqDRnI6jaRHp9fTcYBjtFKE8eezcZ7LuLjhUaQGNeMXf1HmRoCH32CLz6XwX0TtxEOS/A3Q== + version "3.1.28" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.28.tgz#3c01bac14cb6c5680569014cc65a2f26424c6bd4" + integrity sha512-gSu9VZ2HtmoKYe/lmyPFES5nknFrHa+/DT9muUFWFMi6Jh9E1I7bkvlQ8xxf1Kos9pi9o8lBnIOkatMhKX/YUw== nanomatch@^1.2.9: version "1.2.13" @@ -11067,7 +11082,7 @@ postcss-values-parser@^2.0.0, postcss-values-parser@^2.0.1: indexes-of "^1.0.1" uniq "^1.0.1" -postcss@7.0.36, postcss@^7, postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.14, postcss@^7.0.17, postcss@^7.0.2, postcss@^7.0.26, postcss@^7.0.27, postcss@^7.0.32, postcss@^7.0.5, postcss@^7.0.6: +postcss@7.0.36: version "7.0.36" resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.36.tgz#056f8cffa939662a8f5905950c07d5285644dfcb" integrity sha512-BebJSIUMwJHRH0HAQoxN4u1CN86glsrwsW0q7T+/m44eXOUAxSNdHRkNZPYz5vVUbg17hFgOQDE7fZk7li3pZw== @@ -11076,12 +11091,20 @@ postcss@7.0.36, postcss@^7, postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.14, pos source-map "^0.6.1" supports-color "^6.1.0" +postcss@^7, postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.14, postcss@^7.0.17, postcss@^7.0.2, postcss@^7.0.26, postcss@^7.0.27, postcss@^7.0.32, postcss@^7.0.5, postcss@^7.0.6: + version "7.0.38" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.38.tgz#5365a9c5126643d977046ad239f60eadda2491d6" + integrity sha512-wNrSHWjHDQJR/IZL5IKGxRtFgrYNaAA/UrkW2WqbtZO6uxSLMxMN+s2iqUMwnAWm3fMROlDYZB41dr0Mt7vBwQ== + dependencies: + nanocolors "^0.2.2" + source-map "^0.6.1" + postcss@^8.1.0: - version "8.3.7" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.3.7.tgz#ec88563588c8da8e58e7226f7633b51ae221eeda" - integrity sha512-9SaY7nnyQ63/WittqZYAvkkYPyKxchMKH71UDzeTmWuLSvxTRpeEeABZAzlCi55cuGcoFyoV/amX2BdsafQidQ== + version "8.3.8" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.3.8.tgz#9ebe2a127396b4b4570ae9f7770e7fb83db2bac1" + integrity sha512-GT5bTjjZnwDifajzczOC+r3FI3Cu+PgPvrsjhQdRqa2kTJ4968/X9CUce9xttIB0xOs5c6xf0TCWZo/y9lF6bA== dependencies: - nanocolors "^0.1.5" + nanocolors "^0.2.2" nanoid "^3.1.25" source-map-js "^0.6.2" @@ -11135,13 +11158,13 @@ pretty-format@^26.6.0, pretty-format@^26.6.2: ansi-styles "^4.0.0" react-is "^17.0.1" -pretty-format@^27.0.0, pretty-format@^27.2.0: - version "27.2.0" - resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-27.2.0.tgz#ee37a94ce2a79765791a8649ae374d468c18ef19" - integrity sha512-KyJdmgBkMscLqo8A7K77omgLx5PWPiXJswtTtFV7XgVZv2+qPk6UivpXXO+5k6ZEbWIbLoKdx1pZ6ldINzbwTA== +pretty-format@^27.0.0, pretty-format@^27.2.4: + version "27.2.4" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-27.2.4.tgz#08ea39c5eab41b082852d7093059a091f6ddc748" + integrity sha512-NUjw22WJHldzxyps2YjLZkUj6q1HvjqFezkB9Y2cklN8NtVZN/kZEXGZdFw4uny3oENzV5EEMESrkI0YDUH8vg== dependencies: - "@jest/types" "^27.1.1" - ansi-regex "^5.0.0" + "@jest/types" "^27.2.4" + ansi-regex "^5.0.1" ansi-styles "^5.0.0" react-is "^17.0.1" @@ -12669,9 +12692,9 @@ side-channel@^1.0.4: object-inspect "^1.9.0" signal-exit@^3.0.0, signal-exit@^3.0.2: - version "3.0.4" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.4.tgz#366a4684d175b9cab2081e3681fda3747b6c51d7" - integrity sha512-rqYhcAnZ6d/vTPGghdrw7iumdcbXpsk1b8IG/rz+VWV51DM0p7XCtMoJ3qhPLIbp3tvyt3pKRbaaEMZYpHto8Q== + version "3.0.5" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.5.tgz#9e3e8cc0c75a99472b44321033a7702e7738252f" + integrity sha512-KWcOiKeQj6ZyXx7zq4YxSMgHRlod4czeBQZrPb8OKcohcqAXShm7E20kEMle9WBt26hFcAf0qLOcp5zmY7kOqQ== simple-swizzle@^0.2.2: version "0.2.2" From 98f2bd3eb75f4ff391b436941b11e235b0ca1cd9 Mon Sep 17 00:00:00 2001 From: Teto Gomez Date: Fri, 1 Oct 2021 09:20:18 -0600 Subject: [PATCH 05/15] fix(webapp): add GA and styling UI (#801) --- .../components/InputAutocomplete/styles.js | 1 + webapp/src/config/polar-radar-config.js | 12 +++++------ webapp/src/layouts/Dashboard/index.js | 10 ++++++++-- webapp/src/routes/BlockProducers/index.js | 7 +++++-- webapp/src/routes/BlockProducers/styles.js | 5 +---- webapp/src/routes/Proxies/index.js | 5 +++-- webapp/src/routes/Proxies/styles.js | 5 +---- webapp/src/theme/breakpoints.js | 1 + webapp/src/utils/get-bp-radar-data.js | 8 -------- webapp/src/utils/modeled-bp-data.js | 20 ++++++++++++++----- 10 files changed, 41 insertions(+), 33 deletions(-) diff --git a/webapp/src/components/InputAutocomplete/styles.js b/webapp/src/components/InputAutocomplete/styles.js index 7d3fa7c7..03a2ffb3 100644 --- a/webapp/src/components/InputAutocomplete/styles.js +++ b/webapp/src/components/InputAutocomplete/styles.js @@ -20,6 +20,7 @@ export default theme => ({ width: '100%', [theme.breakpoints.up('md')]: { width: 344, + height: 58, backgroundColor: 'rgba(0, 0, 0, 0.50)', '&:hover': { backgroundColor: 'rgba(0, 0, 0, 0.45)' diff --git a/webapp/src/config/polar-radar-config.js b/webapp/src/config/polar-radar-config.js index f9a553ac..97dea2df 100644 --- a/webapp/src/config/polar-radar-config.js +++ b/webapp/src/config/polar-radar-config.js @@ -24,11 +24,11 @@ export const options = { gridLineColor: '#e5e5e5', lineColor: '#e5e5e5', categories: [ - 'community', - 'development', - 'infrastructure', - 'transparency', - 'trustiness' + 'Community', + 'Development', + 'Infrastructure', + 'Transparency', + 'Trustiness' ], lineWidth: 3, startOnTick: true, @@ -44,7 +44,7 @@ export const options = { gridLineWidth: 3, gridLineColor: '#e5e5e5', min: 0, - max: 11, + max: 10, endOnTick: false, tickInterval: 2, gridLineInterpolation: 'circle', diff --git a/webapp/src/layouts/Dashboard/index.js b/webapp/src/layouts/Dashboard/index.js index afd3a775..d4861f23 100644 --- a/webapp/src/layouts/Dashboard/index.js +++ b/webapp/src/layouts/Dashboard/index.js @@ -1,4 +1,4 @@ -import React, { useState } from 'react' +import React, { useState, useEffect } from 'react' import PropTypes from 'prop-types' import Box from '@mui/material/Box' import { makeStyles } from '@mui/styles' @@ -7,6 +7,7 @@ import Sidebar from '../../components/Sidebar' import Header from '../../components/Header' import Footer from '../../components/Footer' import Message from '../../components/Message' +import { InitGA, LogPageView } from '../../config/google-analitycs-module' import styles from './styles' @@ -21,6 +22,11 @@ const Dashboard = ({ children, routes }) => { setMobileOpen(!mobileOpen) } + useEffect(() => { + InitGA() + LogPageView() + }, []) + return ( @@ -34,7 +40,7 @@ const Dashboard = ({ children, routes }) => {
- + {children}
diff --git a/webapp/src/routes/BlockProducers/index.js b/webapp/src/routes/BlockProducers/index.js index 8f2b6d3f..169bc0fc 100644 --- a/webapp/src/routes/BlockProducers/index.js +++ b/webapp/src/routes/BlockProducers/index.js @@ -38,7 +38,10 @@ const AllBps = () => { }) const loadMore = () => setCurrentlyVisible(currentlyVisible + 12) - // const goToTop = () => document.getElementById('mainContent').scrollTo(0, 0) + + const goToTop = () => { + document.getElementById('childContent').scrollTo(0, 0) + } const handleOnFliterChange = async filter => { await setProducers(currentlyVisible, filter) @@ -57,7 +60,7 @@ const AllBps = () => { } const handleOpenDesktopVotingTool = () => { - // goToTop() + goToTop() !state.compareBPToolVisible && setCompareBPTool(true) } diff --git a/webapp/src/routes/BlockProducers/styles.js b/webapp/src/routes/BlockProducers/styles.js index aacf1f25..56ab75fa 100644 --- a/webapp/src/routes/BlockProducers/styles.js +++ b/webapp/src/routes/BlockProducers/styles.js @@ -35,11 +35,8 @@ export default theme => ({ [theme.breakpoints.up('sm')]: { flexBasis: '50%' }, - [theme.breakpoints.up('md')]: { + [theme.breakpoints.up('mdd')]: { flexBasis: '33.33%' - }, - [theme.breakpoints.up('lg')]: { - flexBasis: '20%' } }, compareTool: { diff --git a/webapp/src/routes/Proxies/index.js b/webapp/src/routes/Proxies/index.js index 6bc28de6..7cd0de1f 100644 --- a/webapp/src/routes/Proxies/index.js +++ b/webapp/src/routes/Proxies/index.js @@ -30,8 +30,9 @@ const AllProxies = ({ ual = {} }) => { txSuccess: false }) - const loadMore = () => setCurrentlyVisible(currentlyVisible + 12) - // const goToTop = () => document.getElementById('mainContent').scrollTo(0, 0) + const loadMore = () => { + setCurrentlyVisible(currentlyVisible + 12) + } const handleToggleCompareTool = () => { setCompareProxyTool(!state.compareProxyToolVisible) diff --git a/webapp/src/routes/Proxies/styles.js b/webapp/src/routes/Proxies/styles.js index 7b00968a..d1274872 100644 --- a/webapp/src/routes/Proxies/styles.js +++ b/webapp/src/routes/Proxies/styles.js @@ -34,11 +34,8 @@ export default theme => ({ [theme.breakpoints.up('sm')]: { flexBasis: '50%' }, - [theme.breakpoints.up('md')]: { + [theme.breakpoints.up('mdd')]: { flexBasis: '33.33%' - }, - [theme.breakpoints.up('lg')]: { - flexBasis: '20%' } }, compareTool: { diff --git a/webapp/src/theme/breakpoints.js b/webapp/src/theme/breakpoints.js index 6d0880fe..0de9c042 100644 --- a/webapp/src/theme/breakpoints.js +++ b/webapp/src/theme/breakpoints.js @@ -3,6 +3,7 @@ const breakpoints = { xs: 0, sm: 600, md: 1024, + mdd: 1110, lg: 1440, xl: 1920 } diff --git a/webapp/src/utils/get-bp-radar-data.js b/webapp/src/utils/get-bp-radar-data.js index 481589f5..4c550dcc 100644 --- a/webapp/src/utils/get-bp-radar-data.js +++ b/webapp/src/utils/get-bp-radar-data.js @@ -4,17 +4,9 @@ export default ({ name, parameters }) => { const { r, g, b } = getRgbColorsFromHex(name) return { - // label: name, name, type: 'area', - // lineTension: 0.3, - // borderJoinStyle: 'round', - // backgroundColor: `rgba(${r}, ${g}, ${b}, .6)`, - // borderColor: `rgba(${r}, ${g}, ${b}, .6)`, color: `rgba(${r}, ${g}, ${b}, .6)`, - // pointBorderColor: '#fff', - // pointHoverBackgroundColor: '#fff', - // pointHoverBorderColor: `rgba(${r}, ${g}, ${b}, 1)`, data: Object.values(parameters) } } diff --git a/webapp/src/utils/modeled-bp-data.js b/webapp/src/utils/modeled-bp-data.js index c73132b1..bbb60358 100644 --- a/webapp/src/utils/modeled-bp-data.js +++ b/webapp/src/utils/modeled-bp-data.js @@ -3,6 +3,16 @@ import _get from 'lodash.get' import getBPRadarData from './get-bp-radar-data' import calculateEosFromVotes from './convert-votes-to-eos-votes' +const formatDecimal = number => { + if (!number) return 0 + + if (number % 1 !== 0) { + return parseFloat(number.toFixed(1)) + } + + return number +} + export default ({ community, trustiness, @@ -12,11 +22,11 @@ export default ({ ...bp }) => { const parameters = { - community: community || 0, - development: development || 0, - infrastructure: infrastructure || 0, - transparency: transparency || 0, - trustiness: trustiness || 0 + community: formatDecimal(community), + trustiness: formatDecimal(trustiness), + development: formatDecimal(development), + transparency: formatDecimal(transparency), + infrastructure: formatDecimal(infrastructure) } const votesInEos = calculateEosFromVotes(_get(bp, 'system.total_votes', 0)) return { From 6ef2c008b373bed3d8641a4b7d2f29811ac3faac Mon Sep 17 00:00:00 2001 From: AngeloCG97 <51149817+AngeloCG97@users.noreply.github.com> Date: Sun, 3 Oct 2021 18:29:13 -0600 Subject: [PATCH 06/15] Fix(ratingPage): fix rating function (#802) * feat(gql): add producers query * feat(models): add new functions to mdels * feat(bpProfilePage): model necessary data * fix(BPRatePage): fix rating process --- webapp/src/context/models/producers.js | 101 ++++++- webapp/src/context/models/user.js | 22 +- webapp/src/context/state.context.js | 81 +++++- webapp/src/gql/producers.js | 83 ++++++ .../BlockProducers/BlockProducerProfile.js | 26 +- .../BlockProducers/BlockProducerRate.js | 261 +++++++++--------- .../BlockProducers/SliderRatingSection.js | 4 +- 7 files changed, 420 insertions(+), 158 deletions(-) diff --git a/webapp/src/context/models/producers.js b/webapp/src/context/models/producers.js index a22f67a5..4bb10cef 100644 --- a/webapp/src/context/models/producers.js +++ b/webapp/src/context/models/producers.js @@ -2,9 +2,13 @@ import { client } from '../../graphql' import { GET_BLOCK_PRODUCERS, GET_EDEN_RATING, - GET_PRODUCER_BY_OWNER + GET_PRODUCER_BY_OWNER, + QUERY_RATING, + MUTATION_UPDATE_RATING } from '../../gql' import getBpDataModeled from '../../utils/modeled-bp-data' +import { mainConfig } from '../../config' +import { getRpc } from '../../utils/eosjs-utils' export const getProducers = async (limit, orderBy) => { const { @@ -41,6 +45,101 @@ export const getProducers = async (limit, orderBy) => { return { data: resultProducers, rows: info.producers.count } } +export const getBlockProducerRatingByOwner = async ( + { bp, userAccount }, + state +) => { + try { + const { + data: { user_ratings: userRatings } + } = await client.query({ + variables: { bp, user: userAccount }, + query: QUERY_RATING + }) + + return userRatings.length ? userRatings[0].ratings : null + } catch (error) { + console.error('getBlockProducerRatingByOwner', error) + } +} + +export const mutationInsertUserRating = async ( + { ual, user, bp, result, transaction, blockProducers, ...ratings }, + state +) => { + try { + const { + data: { rateProducer } + } = await client.mutate({ + variables: { + ratingInput: { + producer: bp, + user, + transaction: transaction + } + }, + mutation: MUTATION_UPDATE_RATING + }) + + const rpc = getRpc(ual) + + const { rows: rateStat } = await rpc.get_table_rows({ + json: true, + code: mainConfig.contract, + scope: mainConfig.contract, + table: 'stats', + lower_bound: bp, + limit: 1, + reverse: false, + show_payer: false + }) + + const producerUpdatedList = blockProducers.data.map(producer => { + if (rateStat.length && producer.owner === rateStat[0].bp) { + const parameters = { + community: rateStat[0].community, + development: rateStat[0].development, + infrastructure: rateStat[0].infrastructure, + transparency: rateStat[0].transparency, + trustiness: rateStat[0].trustiness + } + const graphData = Object.values(parameters) + + return { + ...producer, + average: rateStat[0].average, + ratings_cntr: rateStat[0].ratings_cntr, + system: { + ...producer.system, + parameters + }, + data: { + ...producer.data, + data: graphData + } + } + } + + return producer + }) + let currentBP = producerUpdatedList.find(producer => producer.owner === bp) + currentBP = { ...currentBP, ...rateProducer.resultEden } + const userRate = await getBlockProducerRatingByOwner({ + bp, + userAccount: user + }) + + return { + currentBP, + producerUpdatedList, + rateProducer, + userRate + } + } catch (error) { + console.error('mutationInsertUserRating', error) + } +} + export const getProducer = async owner => { const { data: { producer } diff --git a/webapp/src/context/models/user.js b/webapp/src/context/models/user.js index 817c7da9..76115855 100644 --- a/webapp/src/context/models/user.js +++ b/webapp/src/context/models/user.js @@ -5,6 +5,23 @@ import { mainConfig } from '../../config' import { client } from '../../graphql' import { GET_USER_RATING, GET_PRODUCER_BY_PRODUCER_LIST } from '../../gql' +export const getUserRates = ({ userRate, user }) => { + try { + const { message, ...bpRate } = userRate + const userRatesFiltered = user.userData.userRates.filter( + ({ owner }) => owner !== bpRate.bp + ) + + return { + ...user.data, + userRates: [...userRatesFiltered, bpRate] + } + } catch (error) { + console.error('getUserRates', error) + return null + } +} + export const getUserDataModeled = async ual => { let userRates = [] let edenMember = false @@ -25,7 +42,10 @@ export const getUserDataModeled = async ual => { show_payer: false }) - if (edenMembers.length && edenMembers[0][1].account === accountName) { + if ( + edenMembers.length > 0 && + edenMembers[0].value[1].account === accountName + ) { edenMember = true } diff --git a/webapp/src/context/state.context.js b/webapp/src/context/state.context.js index 9a01de44..9cb8af90 100644 --- a/webapp/src/context/state.context.js +++ b/webapp/src/context/state.context.js @@ -8,7 +8,9 @@ import { getProxy, getUserDataModeled, getProducers, - getProducer + getProducer, + mutationInsertUserRating, + getUserRates } from './models' const SharedStateContext = React.createContext() @@ -19,6 +21,7 @@ const initialValue = { blockProducers: { data: [], rows: 0 }, selectedProducers: [], blockProducer: null, + transaction: null, compareBPToolVisible: false, sortBlockProducersBy: { sort: 'total_votes', value: 'vote' }, proxies: { data: [], rows: 0 }, @@ -124,6 +127,12 @@ const sharedStateReducer = (state, action) => { selectedProxies: action.selectedProxies } + case 'setLastTransaction': + return { + ...state, + transaction: action.transaction + } + default: { throw new Error(`Unsupported action type: ${action.type}`) } @@ -178,8 +187,12 @@ export const useSharedState = () => { const hideMessage = () => dispatch({ type: 'hideMessage' }) const login = () => dispatch({ type: 'login' }) const logout = () => dispatch({ type: 'logout' }) - const setUser = async () => { - const user = await getUserDataModeled(state.ual) + const setUser = async tempUser => { + let user = tempUser + + if (!user) { + user = await getUserDataModeled(state.ual) + } dispatch({ type: 'userChange', user }) } @@ -192,20 +205,62 @@ export const useSharedState = () => { } // Block Producers Action - const setProducers = async (limit, orderBy = null) => { + const setProducers = async (limit, orderBy = null, bpList) => { const filter = orderBy || state.sortBlockProducersBy.sort - const blockProducers = await getProducers(limit, [ - { [filter]: 'desc_nulls_last' }, - { bpjson: 'desc' } - ]) + let blockProducers = bpList + + if (!blockProducers) + blockProducers = await getProducers(limit, [ + { [filter]: 'desc_nulls_last' }, + { bpjson: 'desc' } + ]) dispatch({ type: 'setProducers', blockProducers }) } - const setProducer = async account => { - const blockProducer = await getProducer(account) + + const setProducer = async (item, saveDirectly = false) => { + let blockProducer = item + + if (!saveDirectly) { + blockProducer = await getProducer(item) + } dispatch({ type: 'setProducer', blockProducer }) } + + const handleMutationInsertUserRating = async ({ + ual, + user, + bp, + result, + ...ratings + }) => { + const ratingData = await mutationInsertUserRating({ + ual, + user, + bp, + result, + transaction: state.transaction, + blockProducers: state.blockProducers, + ...ratings + }) + + setProducer(ratingData.currentBP, true) + setProducers(30, null, { + ...state.blockProducers, + data: ratingData.producerUpdatedList + }) + const userRates = getUserRates({ + userRate: { ...ratingData.rateProducer, ...ratingData.currentBP }, + user: state.user + }) + + setUser({ + ...state.user, + userData: { ...state.user.userData, ...userRates } + }) + } + const setCompareBPTool = isVisible => { dispatch({ type: 'setCompareBPTool', isVisible }) } @@ -213,6 +268,10 @@ export const useSharedState = () => { const setSelectedProducers = selectedProducers => dispatch({ type: 'setSelectedProducers', selectedProducers }) + const setLastTransaction = transaction => { + dispatch({ type: 'setLastTransaction', transaction }) + } + // Proxies Actions const setProxies = async limit => { const proxies = await getProxies(limit) @@ -246,8 +305,10 @@ export const useSharedState = () => { setUser, setProducers, setProducer, + handleMutationInsertUserRating, setCompareBPTool, setSelectedProducers, + setLastTransaction, setSortBy, setProxies, setProxy, diff --git a/webapp/src/gql/producers.js b/webapp/src/gql/producers.js index 16763e37..ec751825 100644 --- a/webapp/src/gql/producers.js +++ b/webapp/src/gql/producers.js @@ -92,3 +92,86 @@ export const GET_EDEN_RATING = gql` } } ` + +export const MUTATION_INSERT_USER_RATING = gql` + mutation saveUserRating($objects: [user_ratings_insert_input!]!) { + insert_user_ratings(objects: $objects) { + returning { + user + bp + ratings + } + } + } +` + +export const MUTATION_UPDATE_RATING = gql` + mutation updateRating($ratingInput: RatingInput!) { + rateProducer(ratingInput: $ratingInput) { + message + resultEden + uniq_rating + user + bp + ratings + } + } +` + +export const MUTATION_UPDATE_USER_RATING = gql` + mutation updateUserRating( + $userRating: user_ratings_set_input + $user: String + $bp: String + ) { + update_user_ratings( + _set: $userRating + where: { _and: [{ user: { _eq: $user } }, { bp: { _eq: $bp } }] } + ) { + returning { + user + bp + ratings + uniq_rating + } + } + } +` + +export const QUERY_RATING = gql` + query getRating($user: String, $bp: String) { + user_ratings( + where: { _and: [{ user: { _eq: $user } }, { bp: { _eq: $bp } }] } + ) { + user + bp + ratings + tx_data + } + } +` + +export const QUERY_EDEN_RATING = gql` + query getEdenRating($bp: String) { + eden_ratings_stats(where: { bp: { _eq: $bp } }) { + bp + average + ratings_cntr + infrastructure + transparency + trustiness + development + community + } + } +` + +export const QUERY_PRODUCER = gql` + query getProducer($owner: String) { + producers(where: { owner: { _eq: $owner } }) { + bpjson + owner + system + } + } +` diff --git a/webapp/src/routes/BlockProducers/BlockProducerProfile.js b/webapp/src/routes/BlockProducers/BlockProducerProfile.js index a10386af..48b3b101 100644 --- a/webapp/src/routes/BlockProducers/BlockProducerProfile.js +++ b/webapp/src/routes/BlockProducers/BlockProducerProfile.js @@ -74,7 +74,7 @@ const BlockProducerProfile = () => { const { t } = useTranslation('profile') const { account } = useParams() const classes = useStyles() - const [state, { setProducer }] = useSharedState() + const [state, { setProducer, setLastTransaction }] = useSharedState() const isMobile = useMediaQuery('(max-width:768px)') const [isRated, setIsRated] = useState(false) const [bpHasInformation, setBpHasInformation] = useState(false) @@ -84,8 +84,6 @@ const BlockProducerProfile = () => { const [blockProducerTitle, setBlockProducerTitle] = useState('No Title') const [open, setOpen] = useState(false) - const location = { state: { transactionId: 12 } } /// Check this logic - const getRatingData = edenRate => ({ community: edenRate.community || 0, development: edenRate.development || 0, @@ -114,6 +112,7 @@ const BlockProducerProfile = () => { return } setOpen(false) + setLastTransaction(null) } useEffect(() => { @@ -123,8 +122,8 @@ const BlockProducerProfile = () => { const bp = state.blockProducers.data.find( ({ owner }) => owner === account ) - setProfileData(bp) + setProducer(bp, true) return } @@ -132,7 +131,7 @@ const BlockProducerProfile = () => { await setProducer(account) } - getBpData() + if (state.blockProducers) getBpData() }, [account]) useEffect(() => { @@ -145,18 +144,17 @@ const BlockProducerProfile = () => { useEffect(() => { if (state.user && state.blockProducer) { - const { userRates = [] } = state.user.userData - setIsRated( - userRates.some(rate => rate.owner === state.blockProducer.owner) + state.user?.userData?.userRates.some( + rate => rate.owner === state.blockProducer.owner + ) ) } }, [state.user, state.blockProducer]) - // useEffect(() => { - // if (location.state.transactionId) setOpen(true) - // else setOpen(false) - // }, []) + useEffect(() => { + setOpen(!!state.transaction) + }, []) return ( @@ -319,9 +317,9 @@ const BlockProducerProfile = () => { rel='noopener' target='_blank' style={{ color: 'white' }} - href={`${mainConfig.AdditionalResourcesblockExplorer}/transaction/${location.state.transactionId}`} + href={`${mainConfig.AdditionalResourcesblockExplorer}/transaction/${state.transaction?.transactionId}`} > - {location.state.transactionId} + {state.transaction?.transactionId} { const classes = useStyles() const { account } = useParams() + const history = useHistory() const { t } = useTranslation('bpRatePage') - const [state, { setProducer }] = useSharedState() + const [ + state, + { setProducer, setLastTransaction, handleMutationInsertUserRating } + ] = useSharedState() const [ratingState, setRatingState] = useState(INIT_RATING_STATE_DATA) const [isRated, setIsRated] = useState(true) const [blockProducerLogo, setBlockProducerLogo] = useState(null) @@ -60,21 +65,12 @@ const BlockProducerRate = () => { const [polarChartData, setPolarChartData] = useState([]) const [showMessage, setShowMessage] = useState(false) const [showAlert, setShowAlert] = useState(false) - const linkBack = useRef(null) - const [lastTransactionId, setLastTransactionId] = useState(undefined) - - // const isDesktop = useMediaQuery('(min-width:769px)') const isMobile = useMediaQuery('(max-width:767px)') - // const [sizes, setSizes] = useState() const handleStateChange = parameter => (event, value) => { setRatingState({ ...ratingState, [parameter]: value }) } - // useEffect(() => { - // // setSizes(isDesktop ? 425 : '100%') - // }, [isDesktop]) - const handleClose = (event, reason) => { if (reason === 'clickaway') { return @@ -90,66 +86,62 @@ const BlockProducerRate = () => { } const handleSetLastTransactionId = (event, reason) => { - linkComponent() - setLastTransactionId(undefined) + history.push({ + pathname: `/block-producers/${account}` + }) } - const linkComponent = () => { - linkBack.current.click() + const getRatingData = (useString = false) => { + const { + community, + communityEnabled, + development, + developmentEnabled, + infrastructure, + infraEnabled, + transparency, + transparencyEnabled, + trustiness, + trustinessEnabled + } = ratingState + + if (useString) { + return { + community: formatNumber(communityEnabled ? community : 0, 0).toString(), + development: formatNumber( + developmentEnabled ? development : 0, + 0 + ).toString(), + infrastructure: formatNumber( + infraEnabled ? infrastructure : 0, + 0 + ).toString(), + transparency: formatNumber( + transparencyEnabled ? transparency : 0, + 0 + ).toString(), + trustiness: formatNumber( + trustinessEnabled ? trustiness : 0, + 0 + ).toString() + } + } + + return { + community: communityEnabled ? community : 0, + development: developmentEnabled ? development : 0, + infrastructure: infraEnabled ? infrastructure : 0, + transparency: transparencyEnabled ? transparency : 0, + trustiness: trustinessEnabled ? trustiness : 0 + } } - useEffect(() => { - // dispatch.blockProducers.setShowSortSelected(false) - }, []) - - // const getRatingData = (useString = false) => { - // const { - // community, - // communityEnabled, - // development, - // developmentEnabled, - // infra, - // infraEnabled, - // transparency, - // transparencyEnabled, - // trustiness, - // trustinessEnabled - // } = ratingState - - // if (useString) { - // return { - // community: formatNumber(communityEnabled ? community : 0, 0).toString(), - // development: formatNumber( - // developmentEnabled ? development : 0, - // 0 - // ).toString(), - // infrastructure: formatNumber(infraEnabled ? infra : 0, 0).toString(), - // transparency: formatNumber( - // transparencyEnabled ? transparency : 0, - // 0 - // ).toString(), - // trustiness: formatNumber( - // trustinessEnabled ? trustiness : 0, - // 0 - // ).toString() - // } - // } - - // return { - // community: communityEnabled ? community : 0, - // development: developmentEnabled ? development : 0, - // infrastructure: infraEnabled ? infra : 0, - // transparency: transparencyEnabled ? transparency : 0, - // trustiness: trustinessEnabled ? trustiness : 0 - // } - // } - - const getRatingData = rate => ({ - community: parseFloat(rate.community || 0), - development: parseFloat(rate.development || 0), - infrastructure: parseFloat(rate.development || 0), - transparency: parseFloat(rate.transparency || 0), - trustiness: parseFloat(rate.trustiness || 0) + const getSavedRatingData = rate => ({ + community: parseFloat(rate?.community || 0), + development: parseFloat(rate?.development || 0), + infrastructure: parseFloat(rate?.infrastructure || 0), + transparency: parseFloat(rate?.transparency || 0), + trustiness: parseFloat(rate?.trustiness || 0) }) const transact = async () => { @@ -191,21 +183,18 @@ const BlockProducerRate = () => { broadcast: true }) - // await dispatch.blockProducers.saveLastTransaction({ - // transaction: { - // transactionId: result.transaction.transaction_id, - // transactionDate: result.transaction.processed.block_time - // } - // }) - setLastTransactionId(result.transactionId) - - // await dispatch.blockProducers.mutationInsertUserRating({ - // ual, - // user: accountName, - // bp: account, - // ...getRatingData(false), - // result - // }) + await setLastTransaction({ + transactionId: result.transaction.transaction_id, + transactionDate: result.transaction.processed.block_time + }) + + await handleMutationInsertUserRating({ + ual: state.ual, + user: state.user.accountName, + bp: account, + ...getRatingData(false), + result + }) setRatingState({ ...ratingState, @@ -223,24 +212,29 @@ const BlockProducerRate = () => { } } + const toNumbers = arr => arr.map(Number) + const setProfileData = (bp, userDataSet) => { - const edenDataSet = getBPRadarData({ - name: t('edenRates'), - parameters: getRatingData(bp.edenRate) - }) + if (bp) { + const edenDataSet = getBPRadarData({ + name: t('edenRates'), + parameters: getSavedRatingData(bp.edenRate) + }) - setBlockProducerTitle( - `${t('title')} ${ - _get(bp, 'bpjson.org.candidate_name') || - _get(bp, 'system.owner', t('noBlockProducer')) - } - EOS Rate` - ) - setBlockProducerLogo(_get(bp, 'bpjson.org.branding.logo_256', null)) - setPolarChartData([ - { ...bp.data, name: t('eosRates') }, - edenDataSet, - userDataSet - ]) + setBlockProducerTitle( + `${t('title')} ${ + _get(bp, 'bpjson.org.candidate_name') || + _get(bp, 'system.owner', t('noBlockProducer')) + } - EOS Rate` + ) + setBlockProducerLogo(_get(bp, 'bpjson.org.branding.logo_256', null)) + const generalRateData = toNumbers(bp.data.data) + setPolarChartData([ + { ...bp.data, name: t('eosRates'), data: generalRateData }, + edenDataSet, + userDataSet + ]) + } } useEffect(() => { @@ -250,8 +244,8 @@ const BlockProducerRate = () => { const bp = state.blockProducers.data.find( ({ owner }) => owner === account ) - setProfileData(bp, {}) + setProducer(bp, true) return } @@ -264,32 +258,40 @@ const BlockProducerRate = () => { useEffect(() => { if (state.user && state.blockProducer) { - const { userRates = [] } = state.user.userData - const bpRated = userRates.find( + // const { userRates = [] } = state.user.userData + const bpRated = (state.user?.userData?.userRates || []).find( rate => rate.owner === state.blockProducer.owner ) - const parameters = getRatingData(bpRated.ratings) - const userDataSet = getBPRadarData({ - name: t('myRate'), - parameters: getRatingData(bpRated.ratings) - }) - if ( - state.user.userData.edenMember || - state.user.userData.hasProxy || - state.user.userData.producersCount >= 21 - ) { - setShowAlert(false) + if (bpRated) { + setRatingState({ + ...ratingState, + ...getSavedRatingData(bpRated.ratings) + }) + if ( + state.user.userData.edenMember || + state.user.userData.hasProxy || + state.user.userData.producersCount >= 21 + ) { + setShowAlert(false) + } else { + setShowAlert(true) + } } else { - setShowAlert(true) + setRatingState(INIT_RATING_STATE_DATA) } - - setProfileData(state.blockProducer, userDataSet) setIsRated(!!bpRated) - setRatingState({ ...INIT_RATING_STATE_DATA, ...parameters }) } }, [state.user, state.blockProducer]) + useEffect(() => { + const userDataSet = getBPRadarData({ + name: t('myRate'), + parameters: getRatingData() + }) + setProfileData(state.blockProducer, userDataSet) + }, [ratingState]) + return ( @@ -352,13 +354,11 @@ const BlockProducerRate = () => { {t('subText')} {t('helpText')} {t('rateText')} - {isMobile && ( )} - { disabled={!state.blockProducer} variant='contained' size='small' + component={forwardRef((props, ref) => ( + + ))} > {t('cancelRatingButton')} - @@ -71,7 +73,13 @@ const FilterBanner = ({ title, page, onFilterChange }) => { FilterBanner.propTypes = { title: PropTypes.string, page: PropTypes.string, - onFilterChange: PropTypes.func + onFilterChange: PropTypes.func, + hideFilter: PropTypes.bool +} + +FilterBanner.defaultProps = { + onFilterChange: () => {}, + hideFilter: false } export default FilterBanner diff --git a/webapp/src/components/FilterBanner/styles.js b/webapp/src/components/FilterBanner/styles.js index 021314ff..9921e72f 100644 --- a/webapp/src/components/FilterBanner/styles.js +++ b/webapp/src/components/FilterBanner/styles.js @@ -2,13 +2,17 @@ export default theme => ({ filterBanner: { display: 'flex', justifyContent: 'space-between', - padding: theme.spacing(1, 1, 0, 1), - alignItems: 'center' + padding: theme.spacing(1, 2, 0, 2), + alignItems: 'center', + fontSize: '1rem !important' }, pageTitle: { textTransform: 'uppercase', fontWeight: '500 !important', - fontSize: '0.875rem !important', - lineHeight: '1.75' + lineHeight: 'normal', + letterSpacing: '0.08px' + }, + visibilityHidden: { + visibility: 'hidden !important' } }) diff --git a/webapp/src/components/PolarChart/index.js b/webapp/src/components/PolarChart/index.js index fa381525..1fd586ff 100644 --- a/webapp/src/components/PolarChart/index.js +++ b/webapp/src/components/PolarChart/index.js @@ -1,5 +1,6 @@ import React, { useState } from 'react' import PropTypes from 'prop-types' +import { useTranslation } from 'react-i18next' import { makeStyles } from '@mui/styles' import Box from '@mui/material/Box' import HighchartsReact from 'highcharts-react-official' @@ -15,6 +16,7 @@ HighchartsMore(Highcharts) const useStyles = makeStyles(styles) const PolarChart = ({ data = [] }) => { + const { t } = useTranslation('translations') const classes = useStyles() const [options] = useState(polarCharConfig.options) @@ -24,6 +26,16 @@ const PolarChart = ({ data = [] }) => { highcharts={Highcharts} options={{ ...options, + xAxis: { + ...options.xAxis, + categories: [ + t('community'), + t('development'), + t('infrastructure'), + t('transparency'), + t('trustiness') + ] + }, series: data }} /> diff --git a/webapp/src/components/Sidebar/eosrate256.png b/webapp/src/components/Sidebar/eosrate256.png new file mode 100644 index 0000000000000000000000000000000000000000..b7fc51970a578f19563c104f052f4ae72ef5975a GIT binary patch literal 12714 zcmY+q1y~%xvIe?%@Pwd?Ly$m##ogUqg1ZEVg~eS0L4v!xySr;}3GVLh@W{F6-uK>o z-)`5|{9QFw)ze+QT_Fl`;;2YKBme+_Dk&kN1OPz2lK`m?@bBL${h@!~8SWOs!U~eY z!Xyd~wx$+VCIA3+l;`geS`kHp0e)uT?I@n;z`j40S)^jJRmt4T#g$94Gpm6$)n1x8+$IC^DVaqr!oK-$-D5A&10?fa-K z)_21|S$h~N(YkdC)5WPw7UO@fVZa26ZPLDlC0J_H=+%8K>$rOpJCI?q^eNG3oCncq zxhOQ+ud-p$wgIJsFm%-j#xH_4B_bmER>Ok)y9>ILqbAG(&H~!Rx}|)z4%kK8+d{mz zR2;_cQ^j9$zaPH1G5W02~ws0Op;7`WG-LAOP+^^n2u> z@c)lif};K}1{weewgABX7o+*!{=5E3{TJ^4X`wTr{}%xT$b|V{8X)x#3XNb@_ue4d zNqlz%0FXcb`#=GbQ*qxVe78{10Bgv~a2eTJ(;FDu8k*3%Slj*U1>kYvdMB+-zy>5P z)>bx-TrRw1|3PrQ)Bo5EWF-HAfGv5+G-MS>gl!#6NLcAv=s{$BNF*dAJPyXDTuLHh z|Ly+%iFB#cCMgMpG&vSw;O#fd^Hje)_>)k+xe|H!d=|K$t zC;PoC&p$4gyn}_wyXJrL`51ZrgZ%&T{;P+F;h*yV&%^wWrT^i+o63j8!|;D@<3p0^ zruq&5&>c&P2&%Y1ounZ?%l6@P$~%9RHVHxcD&$^ROM*rAHLDgU?$$F0&U&%-Ip#L- z%Ly{woK$GERH#y6?oSnw_|rF!@iU0-{LSi9+ubt}zw4goY0KSM8Yi=(>F(%g60;c_ zGUgWqPNZ$>N=c>6zm!Qw+WC%{gNmKhzl{J*p}%uFDP??183Cr)qE60=D${j{^F7*g z>>uHzjA>W@uq}-$yj_j+JMXQmRAZSjwT}H}19L^^G2YRM``*aDcl0qCiI*ITrpOZs z@y^j$8zouXPlKYqmXQA_uJb$vKp zvNf44R#ht1U~Dn}$s+fReQURTA!M>iDt8LXEmAHRCP(N0ro-hFo#FkufJ8P(oP}AW zG(#g@M1ti2@+$SI{u`08fGg+c8&C>Q~qLIYRb52&?F@JHhi zfJet8yW0H|bL4gx|5ceUN(Zts3pDERdMUMky%->#lXiz0%O&}MEWDA-@7*2-WR;?C zxn?TTsLDQWSo7-s?Y-P+f4P_8J>2%zGM;Tm8D;sJq`-r-+adJNaer!Ybgz$uESKLs z5aWEZIMj(i9INO3qPpt3NBCfQpk$faa;BuW>Up=K0h7;I024-Je&4w+=%4pvws z3$kDke6kZG&sQb3)?!O+F;|*oRn>>hcG78Er9F<0=TKRsEP$__)qOZyg1W}N)enby zbb|5x?uOfPCZD>^?~Qf_6Zxu^njYuf$PB&h+!2Yweh7CBhJB#|!4E+Nwi$d~!*R6p zAF^b~&hNb+52&sRaxkuX8VKIUQjrpgB{?AI@5bsv@UoP-=)op_z-L92;FX#b3G(bNj%(F()&qcUMx z@7?><|Gb|F?P7#H&9;ndZ#z>MHL3&B<9od~!gG0haX6qz=v6~8@4NuqZT9^d@qFeNMPG6WRNZ+^)ZQ(tmh#k&;YnM7^r&huT zy?$oE-?T>n$Ht0e91bZyb33^dAV_YM{$Scr36k;U0TendnjA>ke_0fMroC~gc4#|9w z|CvcX-TTxP9}Z-8m%bcwiaJ{WrRVjK=PBgbIA1rPJhv)WEOLDzPMq{KVU`|+9ZW!W zc2I5bl(RS>hSR*6dGzYql2A* zpNS5wOeZ7q@(_n~Q##z)y$!XPHY*6yrfn$arL6y)v$h&Ksa2Lk-5pEA|0V9e^|$7! zW9ydNkCwh;dAVopJCRB^0&m5E1%&W5g;;M+8EY*w)e1X|klD1X(tt;qFUfEudcC>o zEWGL-dCQll@_Nw0m{J|QFg3khdjW}889IA^tK!Zz^Vi}T^iBnjiSm1Z#MczF9Pux8 zqnngo9Y2H3E>qDyQdvmdh4z1vb-#A6zH_msx*BhAF_@dB1MW3%l6!E0A0P#Cq*d&0 zda^!WS5hZWP#!L?it?k>bHq^bI302c-1f8Po_+{fdsV$O_jGYk#Tt z;5?E3Uhk2VMXy`hXr(4opz|D?za7$|vrDNY#O_Y_YF$-%y;$nXES>To`+;gq!Zss1t ze~Mz$X;TL`{Gdx~0oUK{6W{zaIpnM{lm4zsOSN*Le^WdwhOn>N>VlZ3&Z9S>G~)H( z(3Gz(udLgHL%yzM+x)%QMoYF+xivseJ&k_S9ka~KEOumAqlG*&7EK&NUCDzIh*2>i zh`eY=qbTW|33TmpKWj4^SJ!iLs&u(9e2U=bz^()jVLb7@wq4ww@;=|Kc@wiN6evzS z1>yUZ4-gU`t?(>+-mT(m+r2(u2k}Gp9^O|8WHhVAne(w!PG(##u(_S~9=!+CIr!1N z8G^ocHm3z6M%nvk(ClC;&qC*V-@vYQqG({j3;~_@S|PLgw}2DTx3@4@44v!Y^{0(s zVm}-`561nOs+>uvXM;r-g5o4R@WC=CE{nMW$a3zRG(ShJ17+CO*^c*Kp76^$`{W18 z)B?NbVNjV&{Wrzo)0rr6#T0ONCqXYlbmJj}Q-tWb1t~tJzfS)Z8u{S$rCnQ`3*orI zd#dta7wTCdrp_5(&H(5jVxNfeG~NDBqQb~g)>$?jkotF=UT|*@7Mj& zkGT(i-Tu5K_3uz>c2jKkaP0|hzG(Kl%k~5Z<|yxt`Tb_m`D@d15@5-W6{hPjDOykE zPozTYJGp$Z;&`_*B`hxfCz%~mP`ZZ43E*b8A_)hw#~*TWY1jSO0Um@>3MD0c(|c`@ zc{ygr<20>3&ZXHV)uk9<5fkobZU(Ksw4J_I5(%*#c)}Orze{b8b>3gbrMp9p1X44((F?3 zszix4IOL<_ye6yOMx2VMSu!dFv>dN*<;V@6lRKV0VyXZcO$h^HiYHQXYXw{9Zc*>H5BszVYh z##hGoOieNUP6d(Ss~BTD@}Zx@%&-_uDd6M}hdPp5CELk zbfIyvP>@^pm(P3(-qS(PASs|?gmo8lcZ_py65M+dLc*DTu@%9;3Ov1Y+|{7Lo10lO z!AW906X!fiCGvYboiGbpWHX5MTXnmVy}ApK!&kT!T*1-)P#1AvS8G0Qv&O*l=D{h8 z=i{KzB$t4S*WZ47Si-dKi(s5$UC#(bLPRB#sQ-%2Lmf$~F!YPYWf;4J&c94nBFn?IJ>%%w;G%eEcky=6 zS#7Oz0F-L7L-AG`8#odlx^?x4FIY22`?~oMzVi)6Y|~(CLx&cMG#LD176;|xdt9ir zbT!Vc7lev$D(RHw!(=k@cbO=MZ~(%qORr+h$M)esMIe7)O?MlUqt#|5nv*PZ zHE2Q!P2xHy&M0tL=J&0w%(_!(wMteh#mjr@UE?4di{AYkqLxK)Yh7Kz%OzWhzX8%b zkpvKpt$beboWXoK9n}uDnUsfXFL<{(kNE|feDLnKD!c#z-}9lDDWvH+l-9~zj*PVR zbBAOMW&Ts-?%Gg6YPMhG>{Oj2&g4V#OtI=n^dU3`2Y=gws=D^qr^A^{&!=05HzV|s z0LjmJrhk$dTZzsFh~?u$V)*OxXg=mill=1FeRX}zl(jEw41_XBwcNUDH$7nxU4Yxr zEL*Ij3(<|-%wxZ&V(=~wCWEXxC0Hr8<`R^28w6PSFk_ag)v2do(fB5C3r&w2H*WPc zR5fAAp-M+vQk}m~mz3hfvw|wPChZmzDl)s0`?`}886geux+%HQ>4%<;D ze=6=4G2v;UsM0;6!+_jkl*K_L(*g0tTAlU!YEXc4rg?S6X00A~n*- z<&_DKUM(B>Es)b_p-+kbJz0a}A z(bP^nSd_x&7Jj31l2F%dVmdmo+l!_d64ydH58cZ_oNFNVzLYcqG^?1m@#lQd;fu{s zof=8~xByT(eOrNKSd{?Xd{~P-C=Jn4_A_qWq=J7G+dH>1O~uG_Ny>3tz!sHs|2-^@ z+vh@6yqw7N2oOkeX%cxUi-d@I)O4i8vCy1>Cit7wkD#^!BZ}1(xxEk95AL|9eVm)S zK?g7Bxo^CXk-h|7vZa)I!;OQmFS2&~In$gnR}*^yk?9EmL}bM8dn=xeRdZEZ`P0T1 z=Oms3a=eSVlLami! zneOSOZa{?tGX50Bbu3D18I5GPhRZ0F(7C&WHdd@!B0;#~fLbG}SdcB(rm%itmyTq1 zt~+*`UdDZ)cv{FHpP1P2tnM|!Ls2SXZ-|ef@8=@2R6p0{GcYZaUZ^Ysvv|aE((F!jsdz+iMwC3+s<<$c`13_Z)YCv)2d(4xHW{Iop)vMic7gR`mB)xA9w$xu(RWJQN{32771dxN9e4Gi%tPt~f;PqbZRb$byhUTWj6Ou^ZHPWxKeFu-CTO4zO61DQF zsO33_-11(KiZj8%7rK>nIaYDmimhHFt_7Npe(UGUD_gfrX;&|Im%oYNm9tdvIEAo= zJno52W^^+=SoO2zU`~la0`x7<4n?XZYGSTewYhG0hrUcp>!k8aaX&Qf<}dyloiNT; zQ)9xf_XhpM{78_X<57mrzbxZu)CptfZFa}8StED zL_A^T9zm~IBKQq6g3C2Y{LvoLm{#|{PEDUH22OU?A#eRONI05~XoGrx!-wdlzcFRa zpItli51l&I8lV#KNUVB$w<2Au(X7mAKlr%Gahao7^DCZAB&aTwc&)fSlnBUcm_-*J zPvAg#=~ZcK*4da`qeXI^7`+nb5a&acEfJ7bw7)htWru4@PdD*FxvJ%~-PY@5PcV02 z_sRQt&U~({MTv6f6b?V*j3~jNH=5|}>!wlkw>KJqTZ*M6R+*EY1;eaNnXkoF<|m91 zdN2EaA{U!D^lw;o8(Doo-U{QSbhXoVQKS>WUG&-GfwXxtlM?0lM#9~aYJq~ z!Mvx9f7{U_*^h(G#)Hq`{#HnSriB?MowfXBNHJ==LpO|YOmj_x8!??xrEIrYRM2l% zQ^SIl`0$4vTkN~z#7P*lp*xKd;*mRQ@^Ov)`H>$h1e+4+42*aNhYQm8nT)BPwqCDC z*o<6jqH4eXQd&F0vGvKvlyc6pvgb!;^0g2gj;c1e&a*rp&XU)#HN7sJzQ!Z}FzNVW z4@FSMe|jsx{xjdFb@Wy{urmglvXkL00E7VDy$mAY=SE+^w+ra!7m=qI68GKek>l79 ziBmLYi`7Z$_>vcx#11VHyU%gD`qclRVw~#n<)hrk>-m1ur-dVSbNv!}YNI@)AFU!0 zR!ed;>Z|?6=xm1B2d)WbPGOg-{#6+=j2kO=Yk#8mg3ziAyhYN;8tUj0;XPR{7sdzm{iu=d%=RQK9He#BV&~mgk zjqI-BFB8=?%T@PrUWd{#9fd=|&!9N?jlfY*taVMp0TRsafa!QL1%b>kWG;kpLQqg? zABFr=>2vwj_b|)K<-(TFbhNl+8;=SFUu1Bm=&a-&TZ1-hA1hXdO4vV`BmSB89an*8 z5s0h3UGskPE|B{KyDlrXyG+_Dl|9ziPv)fNhhJ9}6?!}%Dd{F**k_t4NYxFcPhOL6 zm*5l1x29Z8=`s5b0o zkP|Vk%;&jwel{o7m`TneX(ioe79l)QlVjq(1`-(dt)O6KXe?KR>ZJF z$#%pe{ag482slt9EtmnenA8iIv+TzU2F}g$#r7EK$n+82W8t2U$(LwiD7PvGSrrF3 zu@-Ob{`9o<9F0lI35#;=_YTPfOHDC&Hkp-)KoFLF2V7oMxH$g{i@Y574T}ykkxdS! z84Fw>-Se6K5AzN2>Mq79MZl07*CBEV287qHBehUU+GjX?+hxTBNJs2lV1!%TFXUXF z)?oFJ3{3u7LD)%ik{UgW(4C;5tn2-J(Nd^`SX9uxDd>+NU7 z0_VeFrw&v@XB`SxBNlguTCL21baS}40QvJ{(g<&Q= zl=?5d=^2v4Unh5_QH-VCPwHE&T4b@Bb}w7QO+1k2aVl_Z$k$W8uSp{4L$xJC8dViWS1jzY_6M6N<8$Mni7|CG*;69yQ!b`wx zCDm<-t5$XcYZjYh5_DbrZrkqEr&YoL+3Vr)mAzZxc;33_iKA{Ov-6|nfSk}DswGLj za%*#v8j%@$E(gZBJ{fei2?_@-+IAa(rZmG_;rX;$XX*S?!nUfo>l{PU^_^RT@Lmis zTw%KG+6-4-X$&=cujVF15s@tG2|GdolS@as2%RSa6ZTaPVQw+|&7}5uZ|YWq*7$(b}IYC?QepMMW$HTc8tvv zZSIhshq$pe-(>EY+7@*c^pU423TZl`bbEA|`ss96=fZC)qF8gqw)2EOw#AB{N@t5h zs2-Hzyn5xkC}??}eeiq8RY+($N$xzrlj-6)OXm zM(E0eoxtGbV2dQCosxPdldeOSxvW-2t`iQKUAQ{LkmG`fE(9%C4Bnkzs#z|CJ}sZn zUjb~fgfrKGuHCK5z4XsB3s8{*y4BZv_IBgjQmo%Yv}``W#34W%C?WRYg;{2H?VgfW zSn?F3vLgqR4-0b7EO&irmstPqmSYILf1I(jMR4MIh4RB~H{^492^(x)pbddgp)l_9 z3i<}#7?imuRPL{bR?Yr6dDV=R{$2<2z>&T?5&gy+axLN6*G%x-ETS5EwtYF4?gcjG z#1g3)RJW@v6&m^g{8u%j!IqXhf2t%sJE08GU)YBPEgno2N7sKwPz6u1)OEh{GidAI zgIzG1`83UI9LDs*N%L6B$n_d2dOrA@t`uxgc&9o9j|4`U*PuUDn+gpOnEA)Xa_FORb=q;U!M1LtqZzh2fqK6IVTW; zfqd0{#Q-}{jOu|fl@q?A2g7=<&yjrEq6d;5N47f$9|@wL8beg6k;KA*ShW_j!`($v zMNM04T^5dzw-$eux=|jh>Xt2vwPLfVQA^)7a1k5FOYO8_t=%#lyv$_JrOAkYj2s8! zPw@*fE^|l_fyf-YH09uB9R_V; z&EZ=xCP`JDZ&tqnh0Go9BC2QuA82?GzK_6EHI(X5;CEqZ#~biIic? ztD<@Sc#8CQ7I>-Nr%jAkGZFJwz6(Dhtd!GGjGC7jw}{%okNU;!g-;F}#E&H?)R|V? zkVDMYB3JZ+r3>*h-N{+D+&Cx}wWMg*E89uXBxD@MWXP9teVweshbFLZ`TdZb&+!U$ z8{MA~?BC_ilbDb2tc6L4(A20mOp~OCe&iaAP2{X|+I+&7=WnTaY|S@}36 z%}|n7$891`NTgGy=K6jJd%NP)Y{~`xTf?zEgBvv!}6#KiU)pIZrFXuYha+abvkmk_TW2*;-i-Z#ji z0-w+%=r|{7yS&0Nsl$bzI6dU|JF^;Friqi!u8EZ$IY=Nv3t`G9h7wd5OpqMUm9>0( zw2nf2nSh0Tyg8yOW2O5>7)Mif{1xgqe2~8tub67wR%5Na<<6ryZ_vy%ztm_oOG0A(bmwJ7 z98Jd+Pv-yp$?beL%!-~-OSvNUVi`&W9;DW1+rX4(S(dU|&azpu>~q(!{lZ$e zoYD0`JCjX8e=&nAQdYh zm+-gSq@&cKpcodlM1&Fmi$~ZmJ2I5~w5a2w)&({*{gXgcvD9z98)RW(95Vjrx_}~# z?&Wem;0DrlSziM$TGfvWG~VviE|SWP zel9?ayzyyFw9j(VimsHNa5|zCWfxOWZ=v~XBQ)CLn}L0({6woSPrTm~Mb_BZAeXv{ zm18I*sklf?t2=Pmw<9%XK{-h?cK#k^b0z>FsOJq|MFNKxuTVN+Ydb2Ks9raH5+)Nv zf0|tXHKma0Kk7d2yjDy3w)Ur}>ozYM6}RG&d7iC60&m=hsTCihK#A;Lzwzwpzl?|7 zuHs(wYf^R-qUVoZo4bu9wB*GM$#iqPS_K5kRi%%U4|kYh=w&haNVqAvRq58$&SJ?0 z_V?J|x$qJ;l3p2l|4QfmV~MhiZou<6f%SH^d*mu7>u%2_3h&G#I zjvVX!^2V;q^~g!+CkAOg$LCel!4Uvn@`s z6QpsH#oilB(AetBL4VEj@dLAxLQAaW;P8bsVVA@8tLz=SFo=a{%Ab|mIeM;GN4kCD z9$_IT8-x9tU2;(&w2grRE=z&K)IrTageFL&ve2d{rvWg2}eY-u0 zsQp9l5&3unYI6US4Tw|QVLL9*5#(V%=3Md~*Y)s8kAX*V*$VnPVdq2PP0xrI)wccC z^#Ksu^I=UAtHk`n4sEP@UrpXEs&)jr<8FIXaDSv9)}Hvpz2f%6c~40FULfzcV}#B_ zEPI6xQ242ffQ+yzs>&}Ieyaqt++jYrhMyXVg0ft#OYKK0eAWJ!PkKZg`fS{=t{uVC8Q zP=)F*s=0sL%2891_44KmBN)u%EH`|=GG*K>NWMtzK$V7)vovfT=*Ox>vJfb~wGPQn zZG+rY7kIfm;HbaR1I9)~S0xpBymO?xgDrX>>&DdV?C|sh^AhgzK=gVTpCUb(a6%B1 zWZe8B!DPP}+;!_r1K}(s$;d1SSw3aJpq~Cp9474Je&#Yq@e_q^B8(dyb;lotE!J%W zgS(1i(qDC?Q|()FPF8iuJRY_y`A$|bTB3E-m}3p$5&p++6U^) zDUP7NLQVELoltXqo1)S5ELMG!(lCA$*PZk;?8Bi8e{~>oI3AXHqW}C?F__mdJ=>ow znw#@~csWMQGQ6;l$_zwIMs^9~4`mAc*f^Z)p@SG=`KEU5?Zgq$&YOQQJmMJfx#_|Q zy8`0e)OAz%y?sw&`&PC@+fs|50eoP+=OpgpH4q+JQWx=q32lpf6^|S;=3d2nq~z!2 zilf+1+aP(_Hne$mK6OmLsmMQ}0bf*_ZU>Zc>t~%Yo1Vl3pycGHbOPd)+-Q7+Rk63x zb1XzwGh09Hu>QD`%F{5?wM7Uu$K7qCRoj;R+`77s4fobhkbJOfrK4D^S@xs!g3&OO z6pDzy-=@uAdSZg)h9#bj)R@ST%!H_a>*C&(3WXfW$6_p!e=IzlCow*A1f3(I18j?8 z4;2t-4>d;eUe;*(L}<>93-V2xnY&$I`{NkhLDmIGRiJ(Z=-l*b{*(=RN!iOvbl~x6 z!i4AkQPf1qmIF}i*iC$*b-)yG(n@K}Lw3Aip`K~ITeOsS6i$gLA`JHliX=@&=f4NB z9gA1uuqE`XbO(=q7;J^W;rTHKE%>l&93nOr8GXPyQ;E66ZMN56?7Ub9w9%r*ZMeQ4 zrH+QPkRkxkFWO5SPoJwo=q9VWkk9XrDc;6cepc9?@i{xN;s*h04LF%Uf8Ond3Y${= zbmiuwOX&M$T^UDAshM_q%9k4j_6em(=mH;8=_ZxVd)4kM4{zPTs2w9*C+{%qGhtS^ z&7auMa(t4>?6&Rk9aed)!R(GmE(>%M@PT%gtMXUIkJlB)_Z+z^xPn;*)jSdv!7QmS z6pgdxH93R=LWF{>t-16kskAEBz9HhZ(11RX!FeF|;C@g$b*V;@JMA zk&J5kEV6S)Hr0mfb>r5`yeoqMPi|79tKs*#9@y(&KV}1CJce9cIJRDAR((<{)IzFK zqle>1WTs+~V|bA!9NqjK1;4Yf1#QTDY7GwadM_fZfR$e0|R`0yva`jd|msGIC!nD zb&YWWh*!`8)kA!aY!An!j`)x}?h)#z0}Cd-13uT$kQR3q$ELgRVCYGv>rh#=Y*dEt z<=I|6E1(xm4u%x5Dax;ZGq!8@vnbcNxRHp;TDQ7u{cSbOaBml~71z0Jpb# z_OEc4M|#q-WXSA6_>Ui;dUA0+!c5yUQTEzxc`!4pVOF>DV=i4#DS$-Q+}oe1Q7A4m z1_`x?+C{gd?s)M|MbPu8 zSJm0nK>!yEoy3y*hO`k%0OM1+T0-6{nC0gR?8YcXO9NjH)i=S^ES#QoDB(7FlzJms z4Tlr|z>$O(=x(*I(TTG>Vy47CRIhZi^eZR2 zoUD)5miOUMK|nwH{O#FA_wKU8d$ltOD-veXiqA##QJcpdbIXy#1k%BBo+FR#zXH*B zz;9?#XQcIq3r@}J(>2Gt|L{_wMbn`IYIbEvj^o|O6iLK=N53i { ) : ( eos rate history.push('/')} + width={256} + height={75} /> )} diff --git a/webapp/src/context/state.context.js b/webapp/src/context/state.context.js index 9cb8af90..7da18edf 100644 --- a/webapp/src/context/state.context.js +++ b/webapp/src/context/state.context.js @@ -1,8 +1,6 @@ import React, { useEffect } from 'react' import PropTypes from 'prop-types' -// import getProxyDataModeled from '../utils/modeled-proxy-data' - import { getProxies, getProxy, @@ -154,6 +152,7 @@ export const SharedStateProvider = ({ children, ual, ...props }) => { dispatch({ type: 'userChange', user }) } else { dispatch({ type: 'userChange', user: ual.activeUser }) + dispatch({ type: 'setSelectedProducers', selectedProducers: [] }) } dispatch({ type: 'ual', ual }) diff --git a/webapp/src/routes/BlockProducers/FilterBox.js b/webapp/src/routes/BlockProducers/FilterBox.js deleted file mode 100644 index 69a4673d..00000000 --- a/webapp/src/routes/BlockProducers/FilterBox.js +++ /dev/null @@ -1,66 +0,0 @@ -import React, { useState, useEffect } from 'react' -import { makeStyles } from '@mui/material/styles' -import List from '@mui/material/List' -import Typography from '@mui/material/Typography' -import ListSubheader from '@mui/material/ListSubheader' -import ListItem from '@mui/material/ListItem' - -import ParameterRangeSelector from 'components/parameter-range-selector' -import bpParameters from 'config/comparison-parameters' - -const useStyles = makeStyles(theme => ({ - nested: { - paddingLeft: theme.spacing(2), - color: 'white' - }, - listItem: { - display: 'block' - } -})) - -const FilterBox = () => { - const [parameters, setParameters] = useState() - const classes = useStyles() - - useEffect(() => { - setParameters( - ...bpParameters.reduce( - (result, parameter) => ({ - ...result, - [parameter]: [0, 20] - }), - {} - ) - ) - }, []) - - const handleValueChange = parameter => value => - setParameters({ - [parameter]: value - }) - - return ( - Filter Parameters} - > - {bpParameters.map(parameter => ( - - {parameter} - - handleValueChange(parameter)} - /> - - ))} - - ) -} - -export default FilterBox diff --git a/webapp/src/routes/BlockProducers/styles.js b/webapp/src/routes/BlockProducers/styles.js index 56ab75fa..8b91c18b 100644 --- a/webapp/src/routes/BlockProducers/styles.js +++ b/webapp/src/routes/BlockProducers/styles.js @@ -216,7 +216,6 @@ export default theme => ({ marginTop: 10, display: 'flex', flexDirection: 'column', - [theme.breakpoints.up('sm')]: { flexDirection: 'row', width: '100%' @@ -295,7 +294,7 @@ export default theme => ({ } }, linkRate: { - marginLeft: `${theme.spacing(2)} !important`, // !isDesktop ? 16 : 0, + marginLeft: `${theme.spacing(2)} !important`, padding: `${theme.spacing(1, 2)} !important` } }) diff --git a/webapp/src/routes/Home/Cover.js b/webapp/src/routes/Home/Cover.js index 4d51eb51..e0c5f7e2 100644 --- a/webapp/src/routes/Home/Cover.js +++ b/webapp/src/routes/Home/Cover.js @@ -2,30 +2,21 @@ import React, { forwardRef, memo } from 'react' import { useTranslation } from 'react-i18next' import Typography from '@mui/material/Typography' import Button from '@mui/material/Button' -// import useMediaQuery from '@mui/material/useMediaQuery' import Box from '@mui/material/Box' import { makeStyles } from '@mui/styles' import { Link } from 'react-router-dom' -// import Radar from '../../components/Radar' import PolarChart from '../../components/PolarChart' import styles from './styles' const refBPLink = (props, ref) => const bpLink = forwardRef(refBPLink) - const useStyles = makeStyles(styles) const HomeCover = () => { const { t } = useTranslation('home') const classes = useStyles() - // const isDesktop = useMediaQuery('(min-width:769px)') - // const [sizes, setSizes] = useState() - - // useEffect(() => { - // // setSizes(isDesktop ? 400 : '95%') - // }, [isDesktop]) return ( diff --git a/webapp/src/routes/Proxies/FilterBox.js b/webapp/src/routes/Proxies/FilterBox.js deleted file mode 100644 index cb7051b7..00000000 --- a/webapp/src/routes/Proxies/FilterBox.js +++ /dev/null @@ -1,69 +0,0 @@ -import React, { useState, useEffect } from 'react' -import { makeStyles } from '@mui/styles' -import List from '@mui/material/List' -import Typography from '@mui/material/Typography' -import ListSubheader from '@mui/material/ListSubheader' -import ListItem from '@mui/material/ListItem' - -import ParameterRangeSelector from '../../components/ParameterRangeSelector' -import bpParameters from 'config/comparison-parameters' - -const useStyles = makeStyles(theme => ({ - nested: { - paddingLeft: theme.spacing(2), - color: 'white' - }, - listItem: { - display: 'block' - } -})) - -const FilterBox = () => { - const [parameters, setParameters] = useState() - const classes = useStyles() - - useEffect(() => { - setParameters( - ...bpParameters.reduce( - (result, parameter) => ({ - ...result, - [parameter]: [0, 20] - }), - {} - ) - ) - }, []) - - const handleValueChange = parameter => value => { - // setState({ - // [parameter]: value - // }) - - console.log({ parameter, value }) - } - - return ( - Filter Parameters} - > - {bpParameters.map(parameter => ( - - {parameter} - - handleValueChange(parameter)} - /> - - ))} - - ) -} - -export default FilterBox diff --git a/webapp/src/routes/Proxies/GeneralInformationProfile.js b/webapp/src/routes/Proxies/GeneralInformationProfile.js index 47ca6f90..e90315ba 100644 --- a/webapp/src/routes/Proxies/GeneralInformationProfile.js +++ b/webapp/src/routes/Proxies/GeneralInformationProfile.js @@ -3,6 +3,7 @@ import PropTypes from 'prop-types' import classNames from 'classnames' import { useTranslation } from 'react-i18next' import Grid from '@mui/material/Grid' +import Box from '@mui/material/Box' import _get from 'lodash.get' import Typography from '@mui/material/Typography' @@ -22,7 +23,7 @@ const SocialNetworks = ({ classes, proxy }) => { {t('social')} {twitter && ( - + Twitter: @@ -39,10 +40,10 @@ const SocialNetworks = ({ classes, proxy }) => { {twitter} - + )} {steemit && ( - + Steemit: @@ -59,10 +60,10 @@ const SocialNetworks = ({ classes, proxy }) => { {steemit} - + )} {telegram && ( - + Telegram: @@ -79,7 +80,7 @@ const SocialNetworks = ({ classes, proxy }) => { {telegram} - + )} ) @@ -99,7 +100,7 @@ const GeneralInformation = ({ classes, proxy = {} }) => { {t('generalInformation')} - + {t('account')}: @@ -109,8 +110,8 @@ const GeneralInformation = ({ classes, proxy = {} }) => { > {_get(proxy, 'owner', '- -')} - - + + {t('website')}: @@ -131,9 +132,9 @@ const GeneralInformation = ({ classes, proxy = {} }) => { '- -' )} - + {background && ( - + {t('background')}: @@ -143,10 +144,10 @@ const GeneralInformation = ({ classes, proxy = {} }) => { > {background} - + )} {philosophy && ( - + {t('philosophy')}: @@ -156,14 +157,14 @@ const GeneralInformation = ({ classes, proxy = {} }) => { > {philosophy} - + )} {t('rankings')} - + {t('proxyVotes')}: @@ -173,8 +174,8 @@ const GeneralInformation = ({ classes, proxy = {} }) => { > {formatNumber(parseFloat(proxyVotes), 0)} - - + + {t('totalVotes')}: @@ -184,7 +185,7 @@ const GeneralInformation = ({ classes, proxy = {} }) => { > {formatNumber(parseFloat(totalVotes), 0)} - + ) diff --git a/webapp/src/routes/Proxies/ProxyProfile.js b/webapp/src/routes/Proxies/ProxyProfile.js index 76132cda..ff9092ea 100644 --- a/webapp/src/routes/Proxies/ProxyProfile.js +++ b/webapp/src/routes/Proxies/ProxyProfile.js @@ -6,18 +6,15 @@ import CircularProgress from '@mui/material/CircularProgress' import Avatar from '@mui/material/Avatar' import Button from '@mui/material/Button' import Grid from '@mui/material/Grid' -import useMediaQuery from '@mui/material/useMediaQuery' import Box from '@mui/material/Box' import Typography from '@mui/material/Typography' import { makeStyles } from '@mui/styles' import Snackbar from '@mui/material/Snackbar' import MuiAlert from '@mui/material/Alert' import KeyboardArrowLeft from '@mui/icons-material/KeyboardArrowLeft' -import AccountCircle from '@mui/icons-material/AccountCircle' import _get from 'lodash.get' import TitlePage from '../../components/PageTitle' -import CompareTool from '../../components/CompareTool' import PolarChart from '../../components/PolarChart' import { useSharedState } from '../../context/state.context' @@ -38,12 +35,8 @@ const ProxyProfile = () => { const [proxyLogo, setProxyLogo] = useState(null) const [proxySlogan, setProxySlogan] = useState(null) const [polarChartData, setPolarChartData] = useState([]) - const [producers, setProducers] = useState([]) const [proxyTitle, setProxyTitle] = useState('No Title') const [showMessage, setShowMessage] = useState(false) - const isDesktop = useMediaQuery('(min-width:767px)') - const isMobile = useMediaQuery('(max-width:768px)') - const [openDesktopVotingTool, setOpenDesktopVotingTool] = useState(isDesktop) const [ratingState, setRatingState] = useState({ processing: false, txError: null, @@ -51,7 +44,7 @@ const ProxyProfile = () => { }) const sendVoteProxy = async proxy => { - if (!state.user.accountName) { + if (!state?.user?.accountName) { setShowMessage(true) return @@ -127,10 +120,6 @@ const ProxyProfile = () => { }) } - const handleOnClose = () => { - setOpenDesktopVotingTool(false) - } - useEffect(() => { if (state.proxy) { setProxyLogo(_get(state.proxy, 'logo_256', null)) @@ -138,7 +127,6 @@ const ProxyProfile = () => { _get(state.proxy, 'name', _get(state.proxy, 'owner', 'No Data')) ) setProxySlogan(_get(state.proxy, 'slogan', null)) - setProducers(_get(state.proxy, 'voter_info.producers', [])) setPolarChartData([state.proxy.data]) } }, [state.proxy]) @@ -162,10 +150,6 @@ const ProxyProfile = () => { getProxyData() }, [account]) - // useEffect(() => { - // setSizes(isDesktop ? 400 : '95%') - // }, [isDesktop]) - return ( @@ -183,44 +167,43 @@ const ProxyProfile = () => { - - - {proxyLogo ? ( - - - - ) : ( - - )} + + + + {proxyLogo ? : ''} + {proxyTitle} {proxySlogan && ( - +
{proxySlogan}
)}
- {isMobile && ( - - - - - - - + + + + + + - )} - + + { {ratingState.processing && ( -
+ { > {t('voting')} ... -
+
)} { proxy={state.proxy} />
- {!isMobile && ( - - - - - - - + + + - )} - - {state.proxy && - openDesktopVotingTool && - Boolean(producers.length) && ( - console.log('remove')} - className={classes.compareTool} - list={[state.proxy]} - selected={[account]} - isProxy - useOnlySliderView - optionalLabel={`${proxyTitle} ${t('labelTool')}:`} - handleOnClose={handleOnClose} - /> - )} + diff --git a/webapp/src/routes/Proxies/index.js b/webapp/src/routes/Proxies/index.js index 7cd0de1f..f820910b 100644 --- a/webapp/src/routes/Proxies/index.js +++ b/webapp/src/routes/Proxies/index.js @@ -9,6 +9,7 @@ import _get from 'lodash.get' import { useSharedState } from '../../context/state.context' import TitlePage from '../../components/PageTitle' +import FilterBanner from '../../components/FilterBanner' import Card from '../../components/Card' import CompareTool from '../../components/CompareTool' import SelectedBpsBottomSheet from './../BlockProducers/BottomSheetSelectedBps' @@ -157,7 +158,7 @@ const AllProxies = ({ ual = {} }) => { }} /> - + {(state.proxies.data || []).map(proxy => ( diff --git a/webapp/src/routes/Proxies/styles.js b/webapp/src/routes/Proxies/styles.js index d1274872..c1ed2962 100644 --- a/webapp/src/routes/Proxies/styles.js +++ b/webapp/src/routes/Proxies/styles.js @@ -81,7 +81,14 @@ export default theme => ({ padding: 10 }, bpName: { - marginLeft: 6 + marginLeft: `${theme.spacing(1)} !important`, + fontWeight: 'normal', + fontStretch: 'normal', + fontStyle: 'normal', + lineHeight: '1.17', + letterSpacing: 'normal', + textAlign: 'left', + color: theme.palette.common.black }, accountCircle: { color: theme.palette.secondary.main @@ -90,26 +97,44 @@ export default theme => ({ padding: '3%' }, title: { - color: theme.palette.primary.main, - fontSize: '1.5rem', - marginBottom: 5, - marginTop: 5 + color: theme.palette.common.black, + fontSize: '1.5rem !important' + }, + bpSlogan: { + marginLeft: `${theme.spacing(2)} !important`, + [theme.breakpoints.up('md')]: { + marginLeft: `${theme.spacing(3)} !important` + } }, subTitle: { - fontSize: 14 + fontSize: '18px !important', + fontWeight: '500 !important' + }, + rowBox: { + display: 'flex', + marginLeft: `${theme.spacing(2)} !important`, + [theme.breakpoints.up('md')]: { + marginLeft: `${theme.spacing(3)} !important` + } }, longSubTitle: { - margin: '7px 0', - fontSize: 14 + fontSize: '18px !important', + fontWeight: '500 !important', + marginLeft: `${theme.spacing(2)} !important`, + [theme.breakpoints.up('md')]: { + marginLeft: `${theme.spacing(3)} !important` + } }, longValue: { - marginLeft: 4, - marginTop: 7, - fontWeight: 500 + margin: `${theme.spacing(0, 0, 1, 2)} !important`, + fontWeight: '400 !important', + [theme.breakpoints.up('md')]: { + marginLeft: `${theme.spacing(0, 0, 1, 3)} !important` + } }, value: { - marginLeft: 4, - fontWeight: 500 + marginLeft: '4px !important', + fontWeight: '400 !important' }, category: { marginTop: 10 @@ -118,12 +143,12 @@ export default theme => ({ color: theme.palette.surface.main, backgroundColor: theme.palette.secondary.main, width: '100%', + height: 36, '&:hover': { backgroundColor: theme.palette.secondary.light }, - - [theme.breakpoints.up('sm')]: { - marginRight: 10 + [theme.breakpoints.up('md')]: { + width: '50%' } }, wrapperBox: { @@ -142,14 +167,12 @@ export default theme => ({ }, showOnlySm: { display: 'flex', - [theme.breakpoints.up('sm')]: { display: 'none' } }, showOnlyLg: { display: 'flex', - [theme.breakpoints.down('sm')]: { display: 'none' } @@ -183,8 +206,7 @@ export default theme => ({ '&:after': { content: 'close-quote' } }, reliefGrid: { - // margin: '0 30px 30px 30px', - padding: '20px', + padding: '20px 0', border: '1px solid #f8f8f', borderRadius: '6px', boxShadow: @@ -192,20 +214,40 @@ export default theme => ({ backgroundColor: '#fff' }, hiddenDesktop: { - display: 'flex', + display: 'flex !important', + justifyContent: 'center', [theme.breakpoints.up('md')]: { - display: 'none' + display: 'none !important' } }, hiddenMobile: { - display: 'none', + display: 'none !important', [theme.breakpoints.up('md')]: { - display: 'flex' + display: 'flex !important', + justifyContent: 'center' } }, loadMoreBtnBox: { display: 'flex', justifyContent: 'center', padding: theme.spacing(2, 0) + }, + avatarTitle: { + display: 'flex', + alignItems: 'center' + }, + polarGraphWrapper: { + '& .highcharts-container ': { + height: '300px !important', + width: '340px !important', + '& > svg': { + marginTop: '-60px !important', + height: '400px !important', + width: '340px !important' + } + } + }, + paddingHorinzontal: { + padding: theme.spacing(0, 1) } }) diff --git a/webapp/src/routes/Settings/index.js b/webapp/src/routes/Settings/index.js deleted file mode 100644 index b8ed820c..00000000 --- a/webapp/src/routes/Settings/index.js +++ /dev/null @@ -1,89 +0,0 @@ -import React from 'react' -import PropTypes from 'prop-types' -import { makeStyles } from '@mui/styles' -import List from '@mui/material/List' -import ListItem from '@mui/material/ListItem' -import ListItemIcon from '@mui/material/ListItemIcon' -import ListItemSecondaryAction from '@mui/material/ListItemSecondaryAction' -import ListItemText from '@mui/material/ListItemText' -import { useTranslation } from 'react-i18next' -import Typography from '@mui/material/Typography' -import Switch from '@mui/material/Switch' -import Language from '@mui/icons-material/Language' -import NotificationsIcon from '@mui/icons-material/Notifications' - -const useStyles = makeStyles(theme => ({ - root: { - padding: theme.spacing(3) - } -})) - -const Settings = ({ i18n }) => { - const { t } = useTranslation('translations') - const classes = useStyles() - // const { language, notifications } = useSelector(state => state.settings) - // const dispatch = useDispatch() - // delete this - const language = '' - const notifications = '' - // end delete this - - const handleToggle = (value, currentValue) => () => { - if (value === 'language') { - let lang = '' - - // eslint-disable-next-line no-constant-condition - if (currentValue === 'en' || 'ko') lang = 'es' - // eslint-disable-next-line no-constant-condition - else if (currentValue === 'es' || 'ko') lang = 'en' - - i18n.changeLanguage(lang) - localStorage.setItem('LANGUAGE', lang) - // dispatch.settings.setSettings({ key: value, value: lang }) - } else if (value === 'notifications') console.log('test') - // dispatch.settings.setSettings({ key: value, value: !currentValue }) - } - - return ( -
- - {t('settingsTitle')} - - - - - - - - - handleToggle('language', language)} - checked={language === 'en'} - /> - - - - - - - - - handleToggle('notifications', notifications)} - checked={notifications} - /> - - - -
- ) -} - -Settings.propTypes = { - i18n: PropTypes.object.isRequired -} - -export default Settings diff --git a/webapp/src/routes/Settings/styles.js b/webapp/src/routes/Settings/styles.js deleted file mode 100644 index 610a21fc..00000000 --- a/webapp/src/routes/Settings/styles.js +++ /dev/null @@ -1,5 +0,0 @@ -export default theme => ({ - root: { - padding: theme.spacing(3) - } -}) diff --git a/webapp/src/utils/sorted-by.js b/webapp/src/utils/sorted-by.js deleted file mode 100644 index 1a888ba7..00000000 --- a/webapp/src/utils/sorted-by.js +++ /dev/null @@ -1,86 +0,0 @@ -import _get from 'lodash.get' - -const _sortValues = (firstValues, secondValues, path) => { - const firstValue = _get(firstValues, path, 0) || 0 - const secondValue = _get(secondValues, path, 0) || 0 - - return secondValue - firstValue -} - -export default (sortBy, blockProducers) => { - switch (sortBy) { - case 'alphabetical': { - const _getValidName = bp => { - const name = _get(bp, 'bpjson.org.candidate_name', null) - - if (name && name.length) return name.toUpperCase() - - return _get(bp, 'owner').toUpperCase() - } - - return (blockProducers || []).sort((a, b) => { - const firstBP = _getValidName(a) - const secondBP = _getValidName(b) - - return firstBP < secondBP ? -1 : firstBP > secondBP ? 1 : 0 - }) - } - - case 'generalRate': { - return (blockProducers || []).sort((a, b) => _sortValues(a, b, 'average')) - } - - case 'edenRate': { - return (blockProducers || []).sort((a, b) => - _sortValues(a, b, 'eden_average') - ) - } - - case 'infrastructure': { - return (blockProducers || []).sort((a, b) => - _sortValues(a, b, 'system.parameters.infrastructure') - ) - } - - case 'community': { - return (blockProducers || []).sort((a, b) => - _sortValues(a, b, 'system.parameters.community') - ) - } - - case 'trustiness': { - return (blockProducers || []).sort((a, b) => - _sortValues(a, b, 'system.parameters.trustiness') - ) - } - - case 'development': { - return (blockProducers || []).sort((a, b) => - _sortValues(a, b, 'system.parameters.development') - ) - } - - case 'transparency': { - return (blockProducers || []).sort((a, b) => - _sortValues(a, b, 'system.parameters.transparency') - ) - } - - case 'vote': { - return (blockProducers || []).sort((a, b) => - _sortValues(a, b, 'system.total_votes') - ) - } - - case 'ratings': { - return (blockProducers || []).sort((a, b) => - _sortValues(a, b, 'ratings_cntr') - ) - } - - default: - return (blockProducers || []).sort((a, b) => - _sortValues(a, b, 'system.total_votes') - ) - } -} diff --git a/webapp/yarn.lock b/webapp/yarn.lock index e30b2e8c..f5d9274b 100644 --- a/webapp/yarn.lock +++ b/webapp/yarn.lock @@ -1580,10 +1580,10 @@ styled-components "4.4.1" universal-authenticator-library "0.3.0" -"@eslint/eslintrc@^0.2.1": - version "0.2.2" - resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-0.2.2.tgz#d01fc791e2fc33e88a29d6f3dc7e93d0cd784b76" - integrity sha512-EfB5OHNYp1F4px/LI/FEnGylop7nOqkQ1LRzCM0KccA2U8tvV8w01KBv37LbO7nW4H+YhKyo2LcJhRwjjV17QQ== +"@eslint/eslintrc@^0.3.0": + version "0.3.0" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-0.3.0.tgz#d736d6963d7003b6514e6324bec9c602ac340318" + integrity sha512-1JTKgrOKAHVivSvOYw+sJOunkBjUOvjqWk1DPja7ZFhIS2mX/4EgTT8M7eTK9jrKhL/FvXXEbQwIs3pg1xp3dg== dependencies: ajv "^6.12.4" debug "^4.1.1" @@ -1592,7 +1592,7 @@ ignore "^4.0.6" import-fresh "^3.2.1" js-yaml "^3.13.1" - lodash "^4.17.19" + lodash "^4.17.20" minimatch "^3.0.4" strip-json-comments "^3.1.1" @@ -2193,9 +2193,9 @@ source-map "^0.7.3" "@popperjs/core@^2.4.4": - version "2.10.1" - resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.10.1.tgz#728ecd95ab207aab8a9a4e421f0422db329232be" - integrity sha512-HnUhk1Sy9IuKrxEMdIRCxpIqPw6BFsbYSEUO9p/hNw5sMld/+3OLMWQP80F8/db9qsv3qUjs7ZR5bS/R+iinXw== + version "2.10.2" + resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.10.2.tgz#0798c03351f0dea1a5a4cabddf26a55a7cbee590" + integrity sha512-IXf3XA7+XyN7CP9gGh/XB0UxVMlvARGEgGXLubFICsUMGz6Q+DU+i4gGlpOxTjKvXjkJDJC8YdqdKkDj9qZHEQ== "@react-icons/all-files@^4.1.0": version "4.1.0" @@ -2617,9 +2617,9 @@ "@types/react" "*" "@types/react@*": - version "17.0.25" - resolved "https://registry.yarnpkg.com/@types/react/-/react-17.0.25.tgz#8b88c226e54910762decc9de2aa36b4dc9240503" - integrity sha512-IXrzSOr3CVbEQgmjEdCWF57J7CVaJ7lL/n4penxHm8h0XIcr0AxqGucogh2zj3qRxgk4M4JImOP/MfomkPOhvQ== + version "17.0.27" + resolved "https://registry.yarnpkg.com/@types/react/-/react-17.0.27.tgz#6498ed9b3ad117e818deb5525fa1946c09f2e0e6" + integrity sha512-zgiJwtsggVGtr53MndV7jfiUESTqrbxOcBvwfe6KS/9bzaVPCTDieTWnFNecVNx6EAaapg5xsLLWFfHHR437AA== dependencies: "@types/prop-types" "*" "@types/scheduler" "*" @@ -2712,12 +2712,12 @@ integrity sha512-fbF6oTd4sGGy0xjHPKAt+eS2CrxJ3+6gQ3FGcBoIJR2TLAyCkCyI8JqZNy+FeON0AhVgNJoUumVoZQjBFUqHkw== "@typescript-eslint/eslint-plugin@^4.5.0": - version "4.32.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.32.0.tgz#46d2370ae9311092f2a6f7246d28357daf2d4e89" - integrity sha512-+OWTuWRSbWI1KDK8iEyG/6uK2rTm3kpS38wuVifGUTDB6kjEuNrzBI1MUtxnkneuWG/23QehABe2zHHrj+4yuA== + version "4.33.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.33.0.tgz#c24dc7c8069c7706bc40d99f6fa87edcb2005276" + integrity sha512-aINiAxGVdOl1eJyVjaWn/YcVAq4Gi/Yo35qHGCnqbWVz61g39D0h23veY/MA0rFFGfxK7TySg2uwDeNv+JgVpg== dependencies: - "@typescript-eslint/experimental-utils" "4.32.0" - "@typescript-eslint/scope-manager" "4.32.0" + "@typescript-eslint/experimental-utils" "4.33.0" + "@typescript-eslint/scope-manager" "4.33.0" debug "^4.3.1" functional-red-black-tree "^1.0.1" ignore "^5.1.8" @@ -2725,15 +2725,15 @@ semver "^7.3.5" tsutils "^3.21.0" -"@typescript-eslint/experimental-utils@4.32.0", "@typescript-eslint/experimental-utils@^4.0.1": - version "4.32.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-4.32.0.tgz#53a8267d16ca5a79134739129871966c56a59dc4" - integrity sha512-WLoXcc+cQufxRYjTWr4kFt0DyEv6hDgSaFqYhIzQZ05cF+kXfqXdUh+//kgquPJVUBbL3oQGKQxwPbLxHRqm6A== +"@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" + integrity sha512-zeQjOoES5JFjTnAhI5QY7ZviczMzDptls15GFsI6jyUOq0kOf9+WonkhtlIhh0RgHRnqj5gdNxW5j1EvAyYg6Q== dependencies: "@types/json-schema" "^7.0.7" - "@typescript-eslint/scope-manager" "4.32.0" - "@typescript-eslint/types" "4.32.0" - "@typescript-eslint/typescript-estree" "4.32.0" + "@typescript-eslint/scope-manager" "4.33.0" + "@typescript-eslint/types" "4.33.0" + "@typescript-eslint/typescript-estree" "4.33.0" eslint-scope "^5.1.1" eslint-utils "^3.0.0" @@ -2749,32 +2749,32 @@ eslint-utils "^2.0.0" "@typescript-eslint/parser@^4.5.0": - version "4.32.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-4.32.0.tgz#751ecca0e2fecd3d44484a9b3049ffc1871616e5" - integrity sha512-lhtYqQ2iEPV5JqV7K+uOVlPePjClj4dOw7K4/Z1F2yvjIUvyr13yJnDzkK6uon4BjHYuHy3EG0c2Z9jEhFk56w== + version "4.33.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-4.33.0.tgz#dfe797570d9694e560528d18eecad86c8c744899" + integrity sha512-ZohdsbXadjGBSK0/r+d87X0SBmKzOq4/S5nzK6SBgJspFo9/CUDJ7hjayuze+JK7CZQLDMroqytp7pOcFKTxZA== dependencies: - "@typescript-eslint/scope-manager" "4.32.0" - "@typescript-eslint/types" "4.32.0" - "@typescript-eslint/typescript-estree" "4.32.0" + "@typescript-eslint/scope-manager" "4.33.0" + "@typescript-eslint/types" "4.33.0" + "@typescript-eslint/typescript-estree" "4.33.0" debug "^4.3.1" -"@typescript-eslint/scope-manager@4.32.0": - version "4.32.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-4.32.0.tgz#e03c8668f8b954072b3f944d5b799c0c9225a7d5" - integrity sha512-DK+fMSHdM216C0OM/KR1lHXjP1CNtVIhJ54kQxfOE6x8UGFAjha8cXgDMBEIYS2XCYjjCtvTkjQYwL3uvGOo0w== +"@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" + integrity sha512-5IfJHpgTsTZuONKbODctL4kKuQje/bzBRkwHE8UOZ4f89Zeddg+EGZs8PD8NcN4LdM3ygHWYB3ukPAYjvl/qbQ== dependencies: - "@typescript-eslint/types" "4.32.0" - "@typescript-eslint/visitor-keys" "4.32.0" + "@typescript-eslint/types" "4.33.0" + "@typescript-eslint/visitor-keys" "4.33.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" integrity sha512-+3+FCUJIahE9q0lDi1WleYzjCwJs5hIsbugIgnbB+dSCYUxl8L6PwmsyOPFZde2hc1DlTo/xnkOgiTLSyAbHiQ== -"@typescript-eslint/types@4.32.0": - version "4.32.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.32.0.tgz#52c633c18da47aee09449144bf59565ab36df00d" - integrity sha512-LE7Z7BAv0E2UvqzogssGf1x7GPpUalgG07nGCBYb1oK4mFsOiFC/VrSMKbZQzFJdN2JL5XYmsx7C7FX9p9ns0w== +"@typescript-eslint/types@4.33.0": + version "4.33.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.33.0.tgz#a1e59036a3b53ae8430ceebf2a919dc7f9af6d72" + integrity sha512-zKp7CjQzLQImXEpLt2BUw1tvOMPfNoTAfb8l51evhYbOEEzdWyQNmHWWGPR6hwKJDAi+1VXSBmnhL9kyVTTOuQ== "@typescript-eslint/typescript-estree@3.10.1": version "3.10.1" @@ -2790,13 +2790,13 @@ semver "^7.3.2" tsutils "^3.17.1" -"@typescript-eslint/typescript-estree@4.32.0": - version "4.32.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-4.32.0.tgz#db00ccc41ccedc8d7367ea3f50c6994b8efa9f3b" - integrity sha512-tRYCgJ3g1UjMw1cGG8Yn1KzOzNlQ6u1h9AmEtPhb5V5a1TmiHWcRyF/Ic+91M4f43QeChyYlVTcf3DvDTZR9vw== +"@typescript-eslint/typescript-estree@4.33.0": + version "4.33.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-4.33.0.tgz#0dfb51c2908f68c5c08d82aefeaf166a17c24609" + integrity sha512-rkWRY1MPFzjwnEVHsxGemDzqqddw2QbTJlICPD9p9I9LfsO8fdmfQPOX3uKfUaGRDFJbfrtm/sXhVXN4E+bzCA== dependencies: - "@typescript-eslint/types" "4.32.0" - "@typescript-eslint/visitor-keys" "4.32.0" + "@typescript-eslint/types" "4.33.0" + "@typescript-eslint/visitor-keys" "4.33.0" debug "^4.3.1" globby "^11.0.3" is-glob "^4.0.1" @@ -2810,12 +2810,12 @@ dependencies: eslint-visitor-keys "^1.1.0" -"@typescript-eslint/visitor-keys@4.32.0": - version "4.32.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-4.32.0.tgz#455ba8b51242f2722a497ffae29313f33b14cb7f" - integrity sha512-e7NE0qz8W+atzv3Cy9qaQ7BTLwWsm084Z0c4nIO2l3Bp6u9WIgdqCgyPyV5oSPDMIW3b20H59OOCmVk3jw3Ptw== +"@typescript-eslint/visitor-keys@4.33.0": + version "4.33.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-4.33.0.tgz#2a22f77a41604289b7a186586e9ec48ca92ef1dd" + integrity sha512-uqi/2aSz9g2ftcHWf8uLPJA70rUv6yuMW5Bohw+bwcuzaxQIHaKFZCKGoGXIrc9vkTJ3+0txM73K0Hq3d5wgIg== dependencies: - "@typescript-eslint/types" "4.32.0" + "@typescript-eslint/types" "4.33.0" eslint-visitor-keys "^2.0.0" "@webassemblyjs/ast@1.9.0": @@ -3401,24 +3401,23 @@ array-unique@^0.3.2: resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg= -array.prototype.flat@^1.2.3, array.prototype.flat@^1.2.4: - version "1.2.4" - resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.2.4.tgz#6ef638b43312bd401b4c6199fdec7e2dc9e9a123" - integrity sha512-4470Xi3GAPAjZqFcljX2xzckv1qeKPizoNkiS0+O4IoPR2ZNpcjE0pkhdihlDouK+x6QOast26B4Q/O9DJnwSg== +array.prototype.flat@^1.2.4: + version "1.2.5" + resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.2.5.tgz#07e0975d84bbc7c48cd1879d609e682598d33e13" + integrity sha512-KaYU+S+ndVqyUnignHftkwc58o3uVU1jzczILJ1tN2YaIZpFIKBiP/x/j97E5MVPsaCloPbqWLB/8qCTVvT2qg== dependencies: - call-bind "^1.0.0" + call-bind "^1.0.2" define-properties "^1.1.3" - es-abstract "^1.18.0-next.1" + es-abstract "^1.19.0" -array.prototype.flatmap@^1.2.3, array.prototype.flatmap@^1.2.4: - version "1.2.4" - resolved "https://registry.yarnpkg.com/array.prototype.flatmap/-/array.prototype.flatmap-1.2.4.tgz#94cfd47cc1556ec0747d97f7c7738c58122004c9" - integrity sha512-r9Z0zYoxqHz60vvQbWEdXIEtCwHF0yxaWfno9qzXeNHvfyl3BZqygmGzb84dsubyaXLH4husF+NFgMSdpZhk2Q== +array.prototype.flatmap@^1.2.4: + version "1.2.5" + resolved "https://registry.yarnpkg.com/array.prototype.flatmap/-/array.prototype.flatmap-1.2.5.tgz#908dc82d8a406930fdf38598d51e7411d18d4446" + integrity sha512-08u6rVyi1Lj7oqWbS9nUxliETrtIROT4XGTA4D/LWGten6E3ocm7cy9SIrmNHOL5XVbVuckUp3X6Xyg8/zpvHA== dependencies: call-bind "^1.0.0" define-properties "^1.1.3" - es-abstract "^1.18.0-next.1" - function-bind "^1.1.1" + es-abstract "^1.19.0" arrify@^2.0.1: version "2.0.1" @@ -3468,11 +3467,6 @@ ast-types-flow@^0.0.7: resolved "https://registry.yarnpkg.com/ast-types-flow/-/ast-types-flow-0.0.7.tgz#f70b735c6bca1a5c9c22d982c3e39e7feba3bdad" integrity sha1-9wtzXGvKGlycItmCw+Oef+ujva0= -astral-regex@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9" - integrity sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg== - astral-regex@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31" @@ -3516,15 +3510,15 @@ attr-accept@^2.2.1: integrity sha512-7prDjvt9HmqiZ0cl5CRjtS84sEyhsHP2coDkaZKRKVfCDo9s7iw7ChVmar78Gu9pC4SoR/28wFu/G5JJhTnqEg== autoprefixer@^9.6.1: - version "9.8.7" - resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-9.8.7.tgz#e3c12de18a800af1a1a8155fbc01dc7de29ea184" - integrity sha512-7Hg99B1eTH5+LgmUBUSmov1Z3bsggQJS7v3IMGo6wcScnbRuvtMc871J9J+4bSbIqa9LSX/zypFXJ8sXHpMJeQ== + version "9.8.8" + resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-9.8.8.tgz#fd4bd4595385fa6f06599de749a4d5f7a474957a" + integrity sha512-eM9d/swFopRt5gdJ7jrpCwgvEMIayITpojhkkSMRsFHYuH5bkSQ4p/9qTEHtmNudUZh22Tehu7I6CxAW0IXTKA== dependencies: browserslist "^4.12.0" caniuse-lite "^1.0.30001109" - nanocolors "^0.2.8" normalize-range "^0.1.2" num2fraction "^1.2.2" + picocolors "^0.2.1" postcss "^7.0.32" postcss-value-parser "^4.1.0" @@ -4018,15 +4012,15 @@ browserslist@4.14.2: node-releases "^1.1.61" browserslist@^4.0.0, browserslist@^4.12.0, browserslist@^4.16.6, browserslist@^4.17.1, browserslist@^4.3.4, browserslist@^4.6.2, browserslist@^4.6.4: - version "4.17.1" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.17.1.tgz#a98d104f54af441290b7d592626dd541fa642eb9" - integrity sha512-aLD0ZMDSnF4lUt4ZDNgqi5BUn9BZ7YdQdI/cYlILrhdSSZJLU9aNZoD5/NBmM4SK34APB2e83MOsRt1EnkuyaQ== + version "4.17.3" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.17.3.tgz#2844cd6eebe14d12384b0122d217550160d2d624" + integrity sha512-59IqHJV5VGdcJZ+GZ2hU5n4Kv3YiASzW6Xk5g9tf5a/MAzGeFwgGWU39fVzNIOVcgB3+Gp+kiQu0HEfTVU/3VQ== dependencies: - caniuse-lite "^1.0.30001259" - electron-to-chromium "^1.3.846" + caniuse-lite "^1.0.30001264" + electron-to-chromium "^1.3.857" escalade "^3.1.1" - nanocolors "^0.1.5" - node-releases "^1.1.76" + node-releases "^1.1.77" + picocolors "^0.2.1" bs58@4.0.1, bs58@^4.0.1: version "4.0.1" @@ -4239,10 +4233,10 @@ caniuse-api@^3.0.0: lodash.memoize "^4.1.2" lodash.uniq "^4.5.0" -caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000981, caniuse-lite@^1.0.30001109, caniuse-lite@^1.0.30001125, caniuse-lite@^1.0.30001259: - version "1.0.30001261" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001261.tgz#96d89813c076ea061209a4e040d8dcf0c66a1d01" - integrity sha512-vM8D9Uvp7bHIN0fZ2KQ4wnmYFpJo/Etb4Vwsuc+ka0tfGDHvOPrFm6S/7CCNLSOkAUjenT2HnUPESdOIL91FaA== +caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000981, caniuse-lite@^1.0.30001109, caniuse-lite@^1.0.30001125, caniuse-lite@^1.0.30001264: + version "1.0.30001264" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001264.tgz#88f625a60efb6724c7c62ac698bc8dbd9757e55b" + integrity sha512-Ftfqqfcs/ePiUmyaySsQ4PUsdcYyXG2rfoBVsk3iY1ahHaJEw65vfb7Suzqm+cEkwwPIv/XWkg27iCpRavH4zA== capture-exit@^2.0.0: version "2.0.0" @@ -4640,11 +4634,6 @@ constants-browserify@^1.0.0: resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75" integrity sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U= -contains-path@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/contains-path/-/contains-path-0.1.0.tgz#fe8cf184ff6670b6baef01a9d4861a5cbec4120a" - integrity sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo= - content-disposition@0.5.2: version "0.5.2" resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.2.tgz#0cf68bb9ddf5f2be7961c3a85178cb85dba78cb4" @@ -5424,14 +5413,6 @@ dns-txt@^2.0.2: dependencies: buffer-indexof "^1.0.0" -doctrine@1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-1.5.0.tgz#379dce730f6166f76cefa4e6707a159b02c5a6fa" - integrity sha1-N53Ocw9hZvds76TmcHoVmwLFpvo= - dependencies: - esutils "^2.0.2" - isarray "^1.0.0" - doctrine@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d" @@ -5604,10 +5585,10 @@ ejs@^2.6.1: resolved "https://registry.yarnpkg.com/ejs/-/ejs-2.7.4.tgz#48661287573dcc53e366c7a1ae52c3a120eec9ba" integrity sha512-7vmuyh5+kuUyJKePhQfRQBhXV5Ce+RnaeeQArKu1EAMpL3WbgMt5WG6uQZpEVvYSSsxMXRKOewtDk9RaTKXRlA== -electron-to-chromium@^1.3.564, electron-to-chromium@^1.3.846: - version "1.3.854" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.854.tgz#003f0b9c80eccc35be0ef04a0e0b1c31a10b90d5" - integrity sha512-00/IIC1mFPkq32MhUJyLdcTp7+wsKK2G3Sb65GSas9FKJQGYkDcZ4GwJkkxf5YyM3ETvl6n+toV8OmtXl4IA/g== +electron-to-chromium@^1.3.564, electron-to-chromium@^1.3.857: + version "1.3.857" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.857.tgz#dcc239ff8a12b6e4b501e6a5ad20fd0d5a3210f9" + integrity sha512-a5kIr2lajm4bJ5E4D3fp8Y/BRB0Dx2VOcCRE5Gtb679mXIME/OFhWler8Gy2ksrf8gFX+EFCSIGA33FB3gqYpg== elliptic@6.5.0: version "6.5.0" @@ -5842,7 +5823,7 @@ errno@^0.1.3, errno@~0.1.7: dependencies: prr "~1.0.1" -error-ex@^1.2.0, error-ex@^1.3.1: +error-ex@^1.3.1: version "1.3.2" resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== @@ -5856,10 +5837,10 @@ error-stack-parser@^2.0.6: dependencies: stackframe "^1.1.1" -es-abstract@^1.17.2, es-abstract@^1.18.0-next.1, es-abstract@^1.18.0-next.2, es-abstract@^1.18.1, es-abstract@^1.18.2: - version "1.18.7" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.18.7.tgz#122daaa523d0a10b0f1be8ed4ce1ee68330c5bb2" - integrity sha512-uFG1gyVX91tZIiDWNmPsL8XNpiCk/6tkB7MZphoSJflS4w+KgWyQ2gjCVDnsPxFAo9WjRXG3eqONNYdfbJjAtw== +es-abstract@^1.17.2, es-abstract@^1.18.0-next.2, es-abstract@^1.18.2, es-abstract@^1.19.0, es-abstract@^1.19.1: + version "1.19.1" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.19.1.tgz#d4885796876916959de78edaa0df456627115ec3" + integrity sha512-2vJ6tjA/UfqLm2MPs7jxVybLoB8i1t1Jd9R3kISld20sIxPcTbLuggQOUxeWeAvIUkduv/CfMjuh4WmiXr2v9w== dependencies: call-bind "^1.0.2" es-to-primitive "^1.2.1" @@ -5872,7 +5853,9 @@ es-abstract@^1.17.2, es-abstract@^1.18.0-next.1, es-abstract@^1.18.0-next.2, es- is-callable "^1.2.4" is-negative-zero "^2.0.1" is-regex "^1.1.4" + is-shared-array-buffer "^1.0.1" is-string "^1.0.7" + is-weakref "^1.0.1" object-inspect "^1.11.0" object-keys "^1.1.1" object.assign "^4.1.2" @@ -5979,17 +5962,12 @@ eslint-config-standard-react@^11.0.1: resolved "https://registry.yarnpkg.com/eslint-config-standard-react/-/eslint-config-standard-react-11.0.1.tgz#1f488e0062c1e21c4c8584551619f11750658f55" integrity sha512-4WlBynOqBZJRaX81CBcIGDHqUiqxvw4j/DbEIICz8QkMs3xEncoPgAoysiqCSsg71X92uhaBc8sgqB96smaMmg== -eslint-config-standard@16.0.2: - version "16.0.2" - resolved "https://registry.yarnpkg.com/eslint-config-standard/-/eslint-config-standard-16.0.2.tgz#71e91727ac7a203782d0a5ca4d1c462d14e234f6" - integrity sha512-fx3f1rJDsl9bY7qzyX8SAtP8GBSk6MfXFaTfaGgk12aAYW4gJSyRm7dM790L6cbXv63fvjY4XeSzXnb4WM+SKw== - -eslint-config-standard@^16.0.2: +eslint-config-standard@16.0.3, eslint-config-standard@^16.0.2: version "16.0.3" resolved "https://registry.yarnpkg.com/eslint-config-standard/-/eslint-config-standard-16.0.3.tgz#6c8761e544e96c531ff92642eeb87842b8488516" integrity sha512-x4fmJL5hGqNJKGHSjnLdgA6U6h1YW/G2dW9fA+cyVur4SK6lyue8+UgNKWlZtUDTXvgKDD/Oa3GQjmB5kjtVvg== -eslint-import-resolver-node@^0.3.4, eslint-import-resolver-node@^0.3.6: +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" integrity sha512-0En0w03NRVMn9Uiyn8YRPDKvWjxCWkslUEhGNTdGx15RvPJYQ+lbOlqrlNI2vEAs4pDYK4f/HN2TbDmk5TP0iw== @@ -5997,7 +5975,7 @@ eslint-import-resolver-node@^0.3.4, eslint-import-resolver-node@^0.3.6: debug "^3.2.7" resolve "^1.20.0" -eslint-module-utils@^2.6.0, eslint-module-utils@^2.6.2: +eslint-module-utils@^2.6.2: version "2.6.2" resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.6.2.tgz#94e5540dd15fe1522e8ffa3ec8db3b7fa7e7a534" integrity sha512-QG8pcgThYOuqxupd06oYTZoNOGaUdTY1PqK+oS6ElF6vs4pBdk/aYxFVQQXzcrAqp9m7cl7lb2ubazX+g16k2Q== @@ -6021,7 +5999,7 @@ eslint-plugin-flowtype@^5.2.0: lodash "^4.17.15" string-natural-compare "^3.0.1" -eslint-plugin-import@^2.22.1: +eslint-plugin-import@^2.22.1, eslint-plugin-import@~2.24.2: version "2.24.2" resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.24.2.tgz#2c8cd2e341f3885918ee27d18479910ade7bb4da" integrity sha512-hNVtyhiEtZmpsabL4neEj+6M5DCLgpYyG9nzJY8lZQeQXEn5UPW1DpUdsMHMXsq98dbNm7nt1w9ZMSVpfJdi8Q== @@ -6042,29 +6020,10 @@ eslint-plugin-import@^2.22.1: resolve "^1.20.0" tsconfig-paths "^3.11.0" -eslint-plugin-import@~2.22.1: - version "2.22.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.22.1.tgz#0896c7e6a0cf44109a2d97b95903c2bb689d7702" - integrity sha512-8K7JjINHOpH64ozkAhpT3sd+FswIZTfMZTjdx052pnWrgRCVfp8op9tbjpAk3DdUeI/Ba4C8OjdC0r90erHEOw== - dependencies: - array-includes "^3.1.1" - array.prototype.flat "^1.2.3" - contains-path "^0.1.0" - debug "^2.6.9" - doctrine "1.5.0" - eslint-import-resolver-node "^0.3.4" - eslint-module-utils "^2.6.0" - has "^1.0.3" - minimatch "^3.0.4" - object.values "^1.1.1" - read-pkg-up "^2.0.0" - resolve "^1.17.0" - tsconfig-paths "^3.9.0" - eslint-plugin-jest@^24.1.0: - version "24.5.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-24.5.0.tgz#a223a0040a19af749a161807254f0e47f5bfdcc3" - integrity sha512-Cm+XdX7Nms2UXGRnivHFVcM3ZmlKheHvc9VD78iZLO1XcqB59WbVjrMSiesCbHDlToxWjMJDiJMgc1CzFE13Vg== + version "24.5.2" + resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-24.5.2.tgz#f71f98f27fd18b50f55246ca090f36d1730e36a6" + integrity sha512-lrI3sGAyZi513RRmP08sIW241Ti/zMnn/6wbE4ZBhb3M2pJ9ztaZMnSKSKKBUfotVdwqU8W1KtD8ao2/FR8DIg== dependencies: "@typescript-eslint/experimental-utils" "^4.0.1" @@ -6109,10 +6068,10 @@ eslint-plugin-promise@^4.3.1: resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-4.3.1.tgz#61485df2a359e03149fdafc0a68b0e030ad2ac45" integrity sha512-bY2sGqyptzFBDLh/GMbAxfdJC+b0f23ME63FOE4+Jao0oZ3E1LEwFtWJX/1pGMJLiTtrSSern2CRM/g+dfc0eQ== -eslint-plugin-promise@~4.2.1: - version "4.2.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-4.2.1.tgz#845fd8b2260ad8f82564c1222fce44ad71d9418a" - integrity sha512-VoM09vT7bfA7D+upt+FjeBO5eHIJQBUWki1aPvB+vbNiHS3+oGIJGIeyBtKQTME6UPXXy3vV07OL1tHd3ANuDw== +eslint-plugin-promise@~5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-5.1.0.tgz#fb2188fb734e4557993733b41aa1a688f46c6f24" + integrity sha512-NGmI6BH5L12pl7ScQHbg7tvtk4wPxxj8yPHH47NvSmMtFneC077PSeY3huFj06ZWZvtbfxSPt3RuOQD5XcR4ng== eslint-plugin-react-hooks@^4.2.0: version "4.2.0" @@ -6120,9 +6079,9 @@ eslint-plugin-react-hooks@^4.2.0: integrity sha512-623WEiZJqxR7VdxFCKLI6d6LLpwJkGPYKODnkH3D7WpOG5KM8yWueBd8TLsNAetEJNF5iJmolaAKO3F8yzyVBQ== eslint-plugin-react@^7.21.5, eslint-plugin-react@^7.22.0: - version "7.26.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.26.0.tgz#3ae019a35d542b98e5af9e2f96b89c232c74b55b" - integrity sha512-dceliS5itjk4EZdQYtLMz6GulcsasguIs+VTXuiC7Q5IPIdGTkyfXVdmsQOqEhlD9MciofH4cMcT1bw1WWNxCQ== + version "7.26.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.26.1.tgz#41bcfe3e39e6a5ac040971c1af94437c80daa40e" + integrity sha512-Lug0+NOFXeOE+ORZ5pbsh6mSKjBKXDXItUD2sQoT+5Yl0eoT82DqnXeTMfUare4QVCn9QwXbfzO/dBLjLXwVjQ== dependencies: array-includes "^3.1.3" array.prototype.flatmap "^1.2.4" @@ -6139,22 +6098,24 @@ eslint-plugin-react@^7.21.5, eslint-plugin-react@^7.22.0: semver "^6.3.0" string.prototype.matchall "^4.0.5" -eslint-plugin-react@~7.21.5: - version "7.21.5" - resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.21.5.tgz#50b21a412b9574bfe05b21db176e8b7b3b15bff3" - integrity sha512-8MaEggC2et0wSF6bUeywF7qQ46ER81irOdWS4QWxnnlAEsnzeBevk1sWh7fhpCghPpXb+8Ks7hvaft6L/xsR6g== +eslint-plugin-react@~7.25.1: + version "7.25.3" + resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.25.3.tgz#3333a974772745ddb3aecea84621019b635766bc" + integrity sha512-ZMbFvZ1WAYSZKY662MBVEWR45VaBT6KSJCiupjrNlcdakB90juaZeDCbJq19e73JZQubqFtgETohwgAt8u5P6w== dependencies: - array-includes "^3.1.1" - array.prototype.flatmap "^1.2.3" + array-includes "^3.1.3" + array.prototype.flatmap "^1.2.4" doctrine "^2.1.0" - has "^1.0.3" + estraverse "^5.2.0" jsx-ast-utils "^2.4.1 || ^3.0.0" - object.entries "^1.1.2" - object.fromentries "^2.0.2" - object.values "^1.1.1" + minimatch "^3.0.4" + object.entries "^1.1.4" + object.fromentries "^2.0.4" + object.hasown "^1.0.0" + object.values "^1.1.4" prop-types "^15.7.2" - resolve "^1.18.1" - string.prototype.matchall "^4.0.2" + resolve "^2.0.0-next.3" + string.prototype.matchall "^4.0.5" eslint-plugin-testing-library@^3.9.2: version "3.10.2" @@ -6261,13 +6222,13 @@ eslint@^7.11.0, eslint@^7.22.0: text-table "^0.2.0" v8-compile-cache "^2.0.3" -eslint@~7.13.0: - version "7.13.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.13.0.tgz#7f180126c0dcdef327bfb54b211d7802decc08da" - integrity sha512-uCORMuOO8tUzJmsdRtrvcGq5qposf7Rw0LwkTJkoDbOycVQtQjmnhZSuLQnozLE4TmAzlMVV45eCHmQ1OpDKUQ== +eslint@~7.18.0: + version "7.18.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.18.0.tgz#7fdcd2f3715a41fe6295a16234bd69aed2c75e67" + integrity sha512-fbgTiE8BfUJZuBeq2Yi7J3RB3WGUQ9PNuNbmgi6jt9Iv8qrkxfy19Ds3OpL1Pm7zg3BtTVhvcUZbIRQ0wmSjAQ== dependencies: "@babel/code-frame" "^7.0.0" - "@eslint/eslintrc" "^0.2.1" + "@eslint/eslintrc" "^0.3.0" ajv "^6.10.0" chalk "^4.0.0" cross-spawn "^7.0.2" @@ -6277,10 +6238,10 @@ eslint@~7.13.0: eslint-scope "^5.1.1" eslint-utils "^2.1.0" eslint-visitor-keys "^2.0.0" - espree "^7.3.0" + espree "^7.3.1" esquery "^1.2.0" esutils "^2.0.2" - file-entry-cache "^5.0.1" + file-entry-cache "^6.0.0" functional-red-black-tree "^1.0.1" glob-parent "^5.0.0" globals "^12.1.0" @@ -6291,7 +6252,7 @@ eslint@~7.13.0: js-yaml "^3.13.1" json-stable-stringify-without-jsonify "^1.0.1" levn "^0.4.1" - lodash "^4.17.19" + lodash "^4.17.20" minimatch "^3.0.4" natural-compare "^1.4.0" optionator "^0.9.1" @@ -6300,7 +6261,7 @@ eslint@~7.13.0: semver "^7.2.1" strip-ansi "^6.0.0" strip-json-comments "^3.1.0" - table "^5.2.3" + table "^6.0.4" text-table "^0.2.0" v8-compile-cache "^2.0.3" @@ -6636,14 +6597,7 @@ figgy-pudding@^3.5.1: resolved "https://registry.yarnpkg.com/figgy-pudding/-/figgy-pudding-3.5.2.tgz#b4eee8148abb01dcf1d1ac34367d59e12fa61d6e" integrity sha512-0btnI/H8f2pavGMN8w40mlSKOfTK2SVJmBfBeVIj3kNw0swwgzyRq0d5TJVOwodFmtvpPeWPN/MCcfuWF0Ezbw== -file-entry-cache@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-5.0.1.tgz#ca0f6efa6dd3d561333fb14515065c2fafdf439c" - integrity sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g== - dependencies: - flat-cache "^2.0.1" - -file-entry-cache@^6.0.1: +file-entry-cache@^6.0.0, file-entry-cache@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" integrity sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg== @@ -6770,15 +6724,6 @@ find-versions@^4.0.0: dependencies: semver-regex "^3.1.2" -flat-cache@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-2.0.1.tgz#5d296d6f04bda44a4630a301413bdbc2ec085ec0" - integrity sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA== - dependencies: - flatted "^2.0.0" - rimraf "2.6.3" - write "1.0.3" - flat-cache@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.0.4.tgz#61b0338302b2fe9f957dcc32fc2a87f1c3048b11" @@ -6787,11 +6732,6 @@ flat-cache@^3.0.4: flatted "^3.1.0" rimraf "^3.0.2" -flatted@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.2.tgz#4575b21e2bcee7434aa9be662f4b7b5f9c2b5138" - integrity sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA== - flatted@^3.1.0: version "3.2.2" resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.2.tgz#64bfed5cb68fe3ca78b3eb214ad97b63bedce561" @@ -7627,9 +7567,9 @@ import-local@^2.0.0: resolve-cwd "^2.0.0" import-local@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.0.2.tgz#a8cfd0431d1de4a2199703d003e3e62364fa6db6" - integrity sha512-vjL3+w0oulAVZ0hBHnxa/Nm5TAurf9YLQJDhqRZyqb+VKGOB6LU8t9H1Nr5CIo16vh9XfJTOoHwU0B71S557gA== + version "3.0.3" + resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.0.3.tgz#4d51c2c495ca9393da259ec66b62e022920211e0" + integrity sha512-bE9iaUY3CXH8Cwfan/abDKAxe1KGT9kyGsBPqf6DMK/z0a2OzAsrukeYNgIH6cH5Xr452jb1TUL8rSfCLjZ9uA== dependencies: pkg-dir "^4.2.0" resolve-cwd "^3.0.0" @@ -8026,6 +7966,11 @@ is-root@2.1.0: resolved "https://registry.yarnpkg.com/is-root/-/is-root-2.1.0.tgz#809e18129cf1129644302a4f8544035d51984a9c" integrity sha512-AGOriNp96vNBd3HtU+RzFEc75FfR5ymiYv8E553I71SCeXBiMsVDUtdio1OEFvrPyLIQ9tVR5RxXIFe5PUFjMg== +is-shared-array-buffer@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.1.tgz#97b0c85fbdacb59c9c446fe653b82cf2b5b7cfe6" + integrity sha512-IU0NmyknYZN0rChcKhRO1X8LYz5Isj/Fsqh8NJOSf+N/hCOTwy29F32Ik7a+QszE63IdvmwdTPDd6cZ5pg4cwA== + is-stream@^1.0.1, is-stream@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" @@ -8060,6 +8005,13 @@ is-unicode-supported@^0.1.0: resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== +is-weakref@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.0.1.tgz#842dba4ec17fa9ac9850df2d6efbc1737274f2a2" + integrity sha512-b2jKc2pQZjaeFYWEf7ScFj+Be1I+PXmlu572Q8coTXZ+LD/QQZ7ShPMst8h16riVgyXTQwUsFEl74mDvc/3MHQ== + dependencies: + call-bind "^1.0.0" + is-what@^3.3.1: version "3.14.1" resolved "https://registry.yarnpkg.com/is-what/-/is-what-3.14.1.tgz#e1222f46ddda85dead0fd1c9df131760e77755c1" @@ -8936,16 +8888,6 @@ listr2@^3.2.2: through "^2.3.8" wrap-ansi "^7.0.0" -load-json-file@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-2.0.0.tgz#7947e42149af80d696cbf797bcaabcfe1fe29ca8" - integrity sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg= - dependencies: - graceful-fs "^4.1.2" - parse-json "^2.2.0" - pify "^2.0.0" - strip-bom "^3.0.0" - load-json-file@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-4.0.0.tgz#2f5f45ab91e33216234fd53adab668eb4ec0993b" @@ -9346,12 +9288,7 @@ miller-rabin@^4.0.0: bn.js "^4.0.0" brorand "^1.0.1" -mime-db@1.49.0: - version "1.49.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.49.0.tgz#f3dfde60c99e9cf3bc9701d687778f537001cbed" - integrity sha512-CIc8j9URtOVApSFCQIF+VBkX1RwXp/oMMOrqdyXSBXq5RWNEsRfyj1kiRnQgmNXmHxPoFIxOroKA3zcU9P+nAA== - -"mime-db@>= 1.43.0 < 2": +mime-db@1.50.0, "mime-db@>= 1.43.0 < 2": version "1.50.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.50.0.tgz#abd4ac94e98d3c0e185016c67ab45d5fde40c11f" integrity sha512-9tMZCDlYHqeERXEHO9f/hKfNXhre5dK2eE/krIvUjZbS2KPcqGDfNShIWS1uW9XOTKQKqK6qbeOci18rbfW77A== @@ -9369,11 +9306,11 @@ mime-types@2.1.18: mime-db "~1.33.0" mime-types@^2.1.12, mime-types@^2.1.27, mime-types@~2.1.17, mime-types@~2.1.24: - version "2.1.32" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.32.tgz#1d00e89e7de7fe02008db61001d9e02852670fd5" - integrity sha512-hJGaVS4G4c9TSMYh2n6SQAGrC4RnfU+daP8G7cSCmaqNjiOoUY0VHCMS42pxnQmVF1GWwFhbHWn3RIxCqTmZ9A== + version "2.1.33" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.33.tgz#1fa12a904472fafd068e48d9e8401f74d3f70edb" + integrity sha512-plLElXp7pRDd0bNZHw+nMd52vRYjLwQjygaNg7ddJ2uJtTlmnTCjWuPKxVu6//AdaRuME84SvLW91sIkBqGT0g== dependencies: - mime-db "1.49.0" + mime-db "1.50.0" mime@1.6.0: version "1.6.0" @@ -9569,17 +9506,7 @@ nanoclone@^0.2.1: resolved "https://registry.yarnpkg.com/nanoclone/-/nanoclone-0.2.1.tgz#dd4090f8f1a110d26bb32c49ed2f5b9235209ed4" integrity sha512-wynEP02LmIbLpcYw8uBKpcfF6dmg2vcpKqxeH5UcoKEYdExslsdUA4ugFauuaeYdTB76ez6gJW8XAZ6CgkXYxA== -nanocolors@^0.1.5: - version "0.1.12" - resolved "https://registry.yarnpkg.com/nanocolors/-/nanocolors-0.1.12.tgz#8577482c58cbd7b5bb1681db4cf48f11a87fd5f6" - integrity sha512-2nMHqg1x5PU+unxX7PGY7AuYxl2qDx7PSrTRjizr8sxdd3l/3hBuWWaki62qmtYm2U5i4Z5E7GbjlyDFhs9/EQ== - -nanocolors@^0.2.2, nanocolors@^0.2.8: - version "0.2.12" - resolved "https://registry.yarnpkg.com/nanocolors/-/nanocolors-0.2.12.tgz#4d05932e70116078673ea4cc6699a1c56cc77777" - integrity sha512-SFNdALvzW+rVlzqexid6epYdt8H9Zol7xDoQarioEFcFN0JHo4CYNztAxmtfgGTVRCmFlEOqqhBpoFGKqSAMug== - -nanoid@^3.1.25: +nanoid@^3.1.28: version "3.1.28" resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.28.tgz#3c01bac14cb6c5680569014cc65a2f26424c6bd4" integrity sha512-gSu9VZ2HtmoKYe/lmyPFES5nknFrHa+/DT9muUFWFMi6Jh9E1I7bkvlQ8xxf1Kos9pi9o8lBnIOkatMhKX/YUw== @@ -9724,10 +9651,10 @@ node-notifier@^8.0.0: uuid "^8.3.0" which "^2.0.2" -node-releases@^1.1.61, node-releases@^1.1.76: - version "1.1.76" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.76.tgz#df245b062b0cafbd5282ab6792f7dccc2d97f36e" - integrity sha512-9/IECtNr8dXNmPWmFXepT0/7o5eolGesHUa3mtr0KlgnCvnZxwh2qensKL42JJY2vQKC3nIBXetFAqR+PW1CmA== +node-releases@^1.1.61, node-releases@^1.1.77: + version "1.1.77" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.77.tgz#50b0cfede855dd374e7585bf228ff34e57c1c32e" + integrity sha512-rB1DUFUNAN4Gn9keO2K1efO35IDK7yKHCdCaIMvFO7yUYmmZYeDjnGKle26G4rwj+LKRQpjyUUvMkPglwGCYNQ== normalize-package-data@^2.3.2, normalize-package-data@^2.5.0: version "2.5.0" @@ -9863,41 +9790,40 @@ object.assign@^4.1.0, object.assign@^4.1.2: has-symbols "^1.0.1" object-keys "^1.1.1" -object.entries@^1.1.0, object.entries@^1.1.2, object.entries@^1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.1.4.tgz#43ccf9a50bc5fd5b649d45ab1a579f24e088cafd" - integrity sha512-h4LWKWE+wKQGhtMjZEBud7uLGhqyLwj8fpHOarZhD2uY3C9cRtk57VQ89ke3moByLXMedqs3XCHzyb4AmA2DjA== +object.entries@^1.1.0, object.entries@^1.1.4: + version "1.1.5" + resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.1.5.tgz#e1acdd17c4de2cd96d5a08487cfb9db84d881861" + integrity sha512-TyxmjUoZggd4OrrU1W66FMDG6CuqJxsFvymeyXI51+vQLN67zYfZseptRge703kKQdo4uccgAKebXFcRCzk4+g== dependencies: call-bind "^1.0.2" define-properties "^1.1.3" - es-abstract "^1.18.2" + es-abstract "^1.19.1" -object.fromentries@^2.0.2, object.fromentries@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/object.fromentries/-/object.fromentries-2.0.4.tgz#26e1ba5c4571c5c6f0890cef4473066456a120b8" - integrity sha512-EsFBshs5RUUpQEY1D4q/m59kMfz4YJvxuNCJcv/jWwOJr34EaVnG11ZrZa0UHB3wnzV1wx8m58T4hQL8IuNXlQ== +object.fromentries@^2.0.4: + version "2.0.5" + resolved "https://registry.yarnpkg.com/object.fromentries/-/object.fromentries-2.0.5.tgz#7b37b205109c21e741e605727fe8b0ad5fa08251" + integrity sha512-CAyG5mWQRRiBU57Re4FKoTBjXfDoNwdFVH2Y1tS9PqCsfUTymAohOkEMSG3aRNKmv4lV3O7p1et7c187q6bynw== dependencies: call-bind "^1.0.2" define-properties "^1.1.3" - es-abstract "^1.18.0-next.2" - has "^1.0.3" + es-abstract "^1.19.1" object.getownpropertydescriptors@^2.0.3, object.getownpropertydescriptors@^2.1.0: - version "2.1.2" - resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.2.tgz#1bd63aeacf0d5d2d2f31b5e393b03a7c601a23f7" - integrity sha512-WtxeKSzfBjlzL+F9b7M7hewDzMwy+C8NRssHd1YrNlzHzIDrXcXiNOMrezdAEM4UXixgV+vvnyBeN7Rygl2ttQ== + version "2.1.3" + resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.3.tgz#b223cf38e17fefb97a63c10c91df72ccb386df9e" + integrity sha512-VdDoCwvJI4QdC6ndjpqFmoL3/+HxffFBbcJzKi5hwLLqqx3mdbedRpfZDdK0SrOSauj8X4GzBvnDZl4vTN7dOw== dependencies: call-bind "^1.0.2" define-properties "^1.1.3" - es-abstract "^1.18.0-next.2" + es-abstract "^1.19.1" object.hasown@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/object.hasown/-/object.hasown-1.0.0.tgz#bdbade33cfacfb25d7f26ae2b6cb870bf99905c2" - integrity sha512-qYMF2CLIjxxLGleeM0jrcB4kiv3loGVAjKQKvH8pSU/i2VcRRvUNmxbD+nEMmrXRfORhuVJuH8OtSYCZoue3zA== + version "1.1.0" + resolved "https://registry.yarnpkg.com/object.hasown/-/object.hasown-1.1.0.tgz#7232ed266f34d197d15cac5880232f7a4790afe5" + integrity sha512-MhjYRfj3GBlhSkDHo6QmvgjRLXQ2zndabdf3nX0yTyZK9rPfxb6uRpAac8HXNLy1GpqWtZ81Qh4v3uOls2sRAg== dependencies: define-properties "^1.1.3" - es-abstract "^1.18.1" + es-abstract "^1.19.1" object.pick@^1.3.0: version "1.3.0" @@ -9906,14 +9832,14 @@ object.pick@^1.3.0: dependencies: isobject "^3.0.1" -object.values@^1.1.0, object.values@^1.1.1, object.values@^1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.4.tgz#0d273762833e816b693a637d30073e7051535b30" - integrity sha512-TnGo7j4XSnKQoK3MfvkzqKCi0nVe/D9I9IjwTNYdb/fxYHpjrluHVOgw0AF6jrRFGMPHdfuidR09tIDiIvnaSg== +object.values@^1.1.0, object.values@^1.1.4: + version "1.1.5" + resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.5.tgz#959f63e3ce9ef108720333082131e4a459b716ac" + integrity sha512-QUZRW0ilQ3PnPpbNtgdNV1PDbEqLIiSFB3l+EnGtBQ/8SUTLj1PZwtQHABZtLgwpJZTSZhuGLOGk57Drx2IvYg== dependencies: call-bind "^1.0.2" define-properties "^1.1.3" - es-abstract "^1.18.2" + es-abstract "^1.19.1" obuf@^1.0.0, obuf@^1.1.2: version "1.1.2" @@ -10163,13 +10089,6 @@ parse-asn1@^5.0.0, parse-asn1@^5.1.5: pbkdf2 "^3.0.3" safe-buffer "^5.1.1" -parse-json@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9" - integrity sha1-9ID0BDTvgHQfhGkJn43qGPVaTck= - dependencies: - error-ex "^1.2.0" - parse-json@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0" @@ -10273,13 +10192,6 @@ path-to-regexp@^1.7.0: dependencies: isarray "0.0.1" -path-type@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/path-type/-/path-type-2.0.0.tgz#f012ccb8415b7096fc2daa1054c3d72389594c73" - integrity sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM= - dependencies: - pify "^2.0.0" - path-type@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/path-type/-/path-type-3.0.0.tgz#cef31dc8e0a1a3bb0d105c0cd97cf3bf47f4e36f" @@ -10313,6 +10225,11 @@ performance-now@^2.1.0: resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= +picocolors@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-0.2.1.tgz#570670f793646851d1ba135996962abad587859f" + integrity sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA== + picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.2, picomatch@^2.2.3: version "2.3.0" resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.0.tgz#f1f061de8f6a4bf022892e2d128234fb98302972" @@ -11092,20 +11009,20 @@ postcss@7.0.36: supports-color "^6.1.0" postcss@^7, postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.14, postcss@^7.0.17, postcss@^7.0.2, postcss@^7.0.26, postcss@^7.0.27, postcss@^7.0.32, postcss@^7.0.5, postcss@^7.0.6: - version "7.0.38" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.38.tgz#5365a9c5126643d977046ad239f60eadda2491d6" - integrity sha512-wNrSHWjHDQJR/IZL5IKGxRtFgrYNaAA/UrkW2WqbtZO6uxSLMxMN+s2iqUMwnAWm3fMROlDYZB41dr0Mt7vBwQ== + version "7.0.39" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.39.tgz#9624375d965630e2e1f2c02a935c82a59cb48309" + integrity sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA== dependencies: - nanocolors "^0.2.2" + picocolors "^0.2.1" source-map "^0.6.1" postcss@^8.1.0: - version "8.3.8" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.3.8.tgz#9ebe2a127396b4b4570ae9f7770e7fb83db2bac1" - integrity sha512-GT5bTjjZnwDifajzczOC+r3FI3Cu+PgPvrsjhQdRqa2kTJ4968/X9CUce9xttIB0xOs5c6xf0TCWZo/y9lF6bA== + version "8.3.9" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.3.9.tgz#98754caa06c4ee9eb59cc48bd073bb6bd3437c31" + integrity sha512-f/ZFyAKh9Dnqytx5X62jgjhhzttjZS7hMsohcI7HEI5tjELX/HxCy3EFhsRxyzGvrzFF+82XPvCS8T9TFleVJw== dependencies: - nanocolors "^0.2.2" - nanoid "^3.1.25" + nanoid "^3.1.28" + picocolors "^0.2.1" source-map-js "^0.6.2" prelude-ls@^1.2.1: @@ -11545,13 +11462,6 @@ react-base16-styling@^0.6.0: lodash.flow "^3.3.0" pure-color "^1.2.0" -react-chartjs-2@^3.0.4: - version "3.0.5" - resolved "https://registry.yarnpkg.com/react-chartjs-2/-/react-chartjs-2-3.0.5.tgz#afc23993a32e146bdcc9addff16a28d8964b98ad" - integrity sha512-fYr4E82agaZi9IFMe5GtOZ6WE/HWdxy/KywLNOzXsqgPkD2oo1IlrQLKMLUki/2UXko3p95TR2L8Q2rEss/opQ== - dependencies: - lodash "^4.17.19" - react-dev-utils@^11.0.3: version "11.0.4" resolved "https://registry.yarnpkg.com/react-dev-utils/-/react-dev-utils-11.0.4.tgz#a7ccb60257a1ca2e0efe7a83e38e6700d17aa37a" @@ -11877,14 +11787,6 @@ react@16.13.0, react@17.0.2, react@~17.0.2: loose-envify "^1.1.0" object-assign "^4.1.1" -read-pkg-up@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-2.0.0.tgz#6b72a8048984e0c41e79510fd5e9fa99b3b549be" - integrity sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4= - dependencies: - find-up "^2.0.0" - read-pkg "^2.0.0" - read-pkg-up@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-3.0.0.tgz#3ed496685dba0f8fe118d0691dc51f4a1ff96f07" @@ -11902,15 +11804,6 @@ read-pkg-up@^7.0.1: read-pkg "^5.2.0" type-fest "^0.8.1" -read-pkg@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-2.0.0.tgz#8ef1c0623c6a6db0dc6713c4bfac46332b2368f8" - integrity sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg= - dependencies: - load-json-file "^2.0.0" - normalize-package-data "^2.3.2" - path-type "^2.0.0" - read-pkg@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-3.0.0.tgz#9cbc686978fee65d16c00e2b19c237fcf6e38389" @@ -12263,13 +12156,6 @@ rifm@^0.12.0: resolved "https://registry.yarnpkg.com/rifm/-/rifm-0.12.0.tgz#8d3a9dc0de9c190e0de9bdc8861a91a221dc1341" integrity sha512-PqOl+Mo2lyqrKiD34FPlnQ+ksD3F+a62TQlphiZshgriyHdfjn6jGyqUZhd+s3nsMYXwXYDdjrrv8wX7QsOG3g== -rimraf@2.6.3: - version "2.6.3" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" - integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== - dependencies: - glob "^7.1.3" - rimraf@^2.5.4, rimraf@^2.6.3: version "2.7.1" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" @@ -12713,15 +12599,6 @@ slash@^3.0.0: resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== -slice-ansi@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-2.1.0.tgz#cacd7693461a637a5788d92a7dd4fba068e81636" - integrity sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ== - dependencies: - ansi-styles "^3.2.0" - astral-regex "^1.0.0" - is-fullwidth-code-point "^2.0.0" - slice-ansi@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-3.0.0.tgz#31ddc10930a1b7e0b67b08c96c2f49b77a789787" @@ -12963,17 +12840,17 @@ standard-engine@^14.0.1: xdg-basedir "^4.0.0" standard@^16.0.3: - version "16.0.3" - resolved "https://registry.yarnpkg.com/standard/-/standard-16.0.3.tgz#a854c0dd2dea6b9f0b8d20c65260210bd0cee619" - integrity sha512-70F7NH0hSkNXosXRltjSv6KpTAOkUkSfyu3ynyM5dtRUiLtR+yX9EGZ7RKwuGUqCJiX/cnkceVM6HTZ4JpaqDg== + version "16.0.4" + resolved "https://registry.yarnpkg.com/standard/-/standard-16.0.4.tgz#779113ba41dd218ab545e7b4eb2405561f6eb370" + integrity sha512-2AGI874RNClW4xUdM+bg1LRXVlYLzTNEkHmTG5mhyn45OhbgwA+6znowkOGYy+WMb5HRyELvtNy39kcdMQMcYQ== dependencies: - eslint "~7.13.0" - eslint-config-standard "16.0.2" + eslint "~7.18.0" + eslint-config-standard "16.0.3" eslint-config-standard-jsx "10.0.0" - eslint-plugin-import "~2.22.1" + eslint-plugin-import "~2.24.2" eslint-plugin-node "~11.1.0" - eslint-plugin-promise "~4.2.1" - eslint-plugin-react "~7.21.5" + eslint-plugin-promise "~5.1.0" + eslint-plugin-react "~7.25.1" standard-engine "^14.0.1" static-extend@^0.1.1: @@ -13061,7 +12938,7 @@ string-width@^3.0.0, string-width@^3.1.0: is-fullwidth-code-point "^2.0.0" strip-ansi "^5.1.0" -string-width@^4.1.0, string-width@^4.2.0: +string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -13070,7 +12947,7 @@ string-width@^4.1.0, string-width@^4.2.0: is-fullwidth-code-point "^3.0.0" strip-ansi "^6.0.1" -string.prototype.matchall@^4.0.2, string.prototype.matchall@^4.0.5: +string.prototype.matchall@^4.0.5: version "4.0.5" resolved "https://registry.yarnpkg.com/string.prototype.matchall/-/string.prototype.matchall-4.0.5.tgz#59370644e1db7e4c0c045277690cf7b01203c4da" integrity sha512-Z5ZaXO0svs0M2xd/6By3qpeKpLKd9mO4v4q3oMEQrk8Ck4xOD5d5XeBOOjGrmVZZ/AHB1S0CgG4N5r1G9N3E2Q== @@ -13333,27 +13210,17 @@ symbol-tree@^3.2.4: resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2" integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw== -table@^5.2.3: - version "5.4.6" - resolved "https://registry.yarnpkg.com/table/-/table-5.4.6.tgz#1292d19500ce3f86053b05f0e8e7e4a3bb21079e" - integrity sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug== - dependencies: - ajv "^6.10.2" - lodash "^4.17.14" - slice-ansi "^2.1.0" - string-width "^3.0.0" - -table@^6.0.9: - version "6.7.1" - resolved "https://registry.yarnpkg.com/table/-/table-6.7.1.tgz#ee05592b7143831a8c94f3cee6aae4c1ccef33e2" - integrity sha512-ZGum47Yi6KOOFDE8m223td53ath2enHcYLgOCjGr5ngu8bdIARQk6mN/wRMv4yMRcHnCSnHbCEha4sobQx5yWg== +table@^6.0.4, table@^6.0.9: + version "6.7.2" + resolved "https://registry.yarnpkg.com/table/-/table-6.7.2.tgz#a8d39b9f5966693ca8b0feba270a78722cbaf3b0" + integrity sha512-UFZK67uvyNivLeQbVtkiUs8Uuuxv24aSL4/Vil2PJVtMgU8Lx0CYkP12uCGa3kjyQzOSgV1+z9Wkb82fCGsO0g== dependencies: ajv "^8.0.1" lodash.clonedeep "^4.5.0" lodash.truncate "^4.4.2" slice-ansi "^4.0.0" - string-width "^4.2.0" - strip-ansi "^6.0.0" + string-width "^4.2.3" + strip-ansi "^6.0.1" tapable@^1.0.0, tapable@^1.1.3: version "1.1.3" @@ -13627,7 +13494,7 @@ ts-pnp@1.2.0, ts-pnp@^1.1.6: resolved "https://registry.yarnpkg.com/ts-pnp/-/ts-pnp-1.2.0.tgz#a500ad084b0798f1c3071af391e65912c86bca92" integrity sha512-csd+vJOb/gkzvcCHgTGSChYpy5f1/XKNsmvBGO4JXS+z1v2HobugDz4s1IeFXM3wZB44uczs+eazB5Q/ccdhQw== -tsconfig-paths@^3.11.0, tsconfig-paths@^3.9.0: +tsconfig-paths@^3.11.0: version "3.11.0" resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.11.0.tgz#954c1fe973da6339c78e06b03ce2e48810b65f36" integrity sha512-7ecdYDnIdmv639mmDwslG6KQg1Z9STTz1j7Gcz0xa+nshh/gKDAHcPxRbWOsA3SPp0tXP2leTcY9Kw+NAkfZzA== @@ -14590,13 +14457,6 @@ write-file-atomic@^3.0.0: signal-exit "^3.0.2" typedarray-to-buffer "^3.1.5" -write@1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/write/-/write-1.0.3.tgz#0800e14523b923a387e415123c865616aae0f5c3" - integrity sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig== - dependencies: - mkdirp "^0.5.1" - "ws@^5.2.0 || ^6.0.0 || ^7.0.0", ws@^7.4.3, ws@^7.4.6: version "7.5.5" resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.5.tgz#8b4bc4af518cfabd0473ae4f99144287b33eb881" From c8a1f06c3ee9e2f61e0064b66e73568685f44fec Mon Sep 17 00:00:00 2001 From: AngeloCG97 <51149817+AngeloCG97@users.noreply.github.com> Date: Tue, 5 Oct 2021 18:34:17 -0600 Subject: [PATCH 09/15] Feat(rating-page): apply new design (#806) * feat(bpRate): apply new design * feat(rating-page): apply new design --- webapp/src/components/PolarChart/styles.js | 10 +- webapp/src/components/RateSlider/index.js | 14 +- webapp/src/context/state.context.js | 1 + webapp/src/language/en.json | 14 +- webapp/src/language/es.json | 12 +- webapp/src/language/ko.json | 12 +- .../BlockProducers/BlockProducerProfile.js | 2 +- .../BlockProducers/BlockProducerRate.js | 169 ++++++++---------- .../BlockProducers/SliderRatingSection.js | 59 +++--- webapp/src/routes/BlockProducers/styles.js | 49 ++++- 10 files changed, 191 insertions(+), 151 deletions(-) diff --git a/webapp/src/components/PolarChart/styles.js b/webapp/src/components/PolarChart/styles.js index 6ccc4a36..64d64ef5 100644 --- a/webapp/src/components/PolarChart/styles.js +++ b/webapp/src/components/PolarChart/styles.js @@ -1,8 +1,16 @@ export default theme => ({ highchartsFigure: { margin: '1em auto', + [theme.breakpoints.down('md')]: { + margin: '0 auto', + width: '100% !important' + }, '& .highcharts-container ': { - margin: '1em auto' + margin: '1em auto', + [theme.breakpoints.down('md')]: { + margin: '0 auto', + width: '100% !important' + } // height: '400px !important', // width: '350px !important', diff --git a/webapp/src/components/RateSlider/index.js b/webapp/src/components/RateSlider/index.js index 2a66958d..7c780793 100644 --- a/webapp/src/components/RateSlider/index.js +++ b/webapp/src/components/RateSlider/index.js @@ -2,13 +2,13 @@ import { styled } from '@mui/material/styles' import Slider from '@mui/material/Slider' const RateSlider = styled(Slider)({ - color: '#597a81', + color: '#443f56', height: 2, padding: '15px 0', '& .MuiSlider-thumb': { width: 15, height: 15, - backgroundColor: '#597a81', + backgroundColor: '#443f56', boxShadow: '0 3px 1px rgba(0,0,0,0.1),0 4px 8px rgba(0,0,0,0.13),0 0 0 1px rgba(0,0,0,0.02)', '&:focus,&:hover,&$active': { @@ -36,14 +36,14 @@ const RateSlider = styled(Slider)({ height: 0 }, '& .MuiSlider-rail': { - height: 2, + height: 4, opacity: 0.5, - backgroundColor: '#010318' + backgroundColor: '#9e9e9e' }, '& .MuiSlider-mark': { - backgroundColor: '#010318', - height: 8, - width: 1, + backgroundColor: '#9e9e9e', + height: 16, + width: 2, marginTop: 0 }, '& .MuiSlider-markActive': { diff --git a/webapp/src/context/state.context.js b/webapp/src/context/state.context.js index 7da18edf..7f47e9b3 100644 --- a/webapp/src/context/state.context.js +++ b/webapp/src/context/state.context.js @@ -249,6 +249,7 @@ export const useSharedState = () => { ...state.blockProducers, data: ratingData.producerUpdatedList }) + const userRates = getUserRates({ userRate: { ...ratingData.rateProducer, ...ratingData.currentBP }, user: state.user diff --git a/webapp/src/language/en.json b/webapp/src/language/en.json index ac70e4fe..7339dc84 100644 --- a/webapp/src/language/en.json +++ b/webapp/src/language/en.json @@ -171,21 +171,19 @@ "bpRatePage": { "allBPs": "All Block Producers", - "subTitle": "Rate Block Producer", - "subText": "Use the sliders to rate the BP.", - "rateText": "If you feel that you do not have enough knowledge about a specific category you can disable it.", - "helpText": "Publish your BP rating by signing in with your favorite wallet.", + "subTitle": "Rate This Block Producer", + "helpText": "Drag the slider to rate each category. 1 means poor performance while 10 means outstanding performance. You can disable any category if you feel you want to do some research before rating it. Once you’re ready, you can publish your rating using your wallet.", "publishRatingButton": "Publish Rating", "updateRatingButton": "Update Rating", "cancelRatingButton": "Cancel", "transparency": "Transparency", - "transparencyTooltip": "Compliance with disclosure of ownership.", + "transparencyTooltip": "Compliance with disclosure of ownership, complete bp.json, use of rewards, and financial stats.", "infrastructure": "Infrastructure", "infrastructureTooltip": "Stability and reliability of the EOS infrastructure.", "trustiness": "Trustiness", "trustinessTooltip": "Collaboration and reputation among the EOS community.", "community": "Community", - "communityTooltip": "Community value creation through education, events, and other useful content.", + "communityTooltip": "Community value creation through education and promoting talks, chats, hackathons, conferences, seminars, developer spaces, and other useful content.", "development": "Development", "developmentTooltip": "Technical know-how and usage of open-source software, scripts, frameworks, wallets, voting portals, metrics, etc.", "globalRate": "General Rating", @@ -195,7 +193,9 @@ "noBlockProducer": "This BP Does Not Exist.", "success": "Success!", "title": "Rate EOS Block Producer Infrastructure and Community Reputation", - "infoMessage": "Support the network by voting for your favorite BPs or proxy, once you have voted for 21 BPs you can start rating." + "infoMessage": "Support the network by voting for your favorite BPs or proxy, once you have voted for 21 BPs you can start rating.", + "enabled": "Enabled", + "disabled": "Disabled" }, "footer": { diff --git a/webapp/src/language/es.json b/webapp/src/language/es.json index 15bd721d..ba3c1683 100644 --- a/webapp/src/language/es.json +++ b/webapp/src/language/es.json @@ -171,21 +171,19 @@ "bpRatePage": { "allBP": "Lista de Productores de Bloques", - "subTitle": "Califique este Productor de bloques EOS", - "subText": "Use los controles deslizantes para calificar.", - "rateText": "Si cree que no tiene suficiente conocimiento sobre una categoría específica, puede deshabilitarla.", + "subTitle": "Califique este productor de bloques", "helpText": "Publique su calificación iniciando sesión con tu billetera favorita.", "publishRatingButton": "Publicar Calificación", "updateRatingButton": "Actualizar Calificación", "cancelRatingButton": "Cancelar", "transparency": "Transparencia", - "transparencyTooltip": "Cumplimiento de la divulgación de la información.", + "transparencyTooltip": "Cumplimiento de la divulgación de propiedad, bp.json completo, uso de recompensas y estadísticas financieras.", "infrastructure": "Infraestructura", "infrastructureTooltip": "Estabilidad y confiabilidad de la infraestructura EOS.", "trustiness": "Lealtad", "trustinessTooltip": "Colaboración y reputación entre la comunidad EOS.", "community": "Comunidad", - "communityTooltip": "Creación de valor comunitario a través de la educación, eventos y/o otros contenidos útiles.", + "communityTooltip": "Creación de valor comunitario a través de la educación y la promoción de charlas, chats, hackatones, conferencias, seminarios, espacios para desarrolladores y otros contenidos útiles.", "development": "Desarrollo", "developmentTooltip": "Conocimientos técnicos y uso de software de código abierto, scripts, marcos, billeteras, portales de votación, métricas, etc.", "globalRate": "Evaluación General", @@ -195,7 +193,9 @@ "noBlockProducer": "No encontramos este PB", "success": "¡Éxito!", "title": "Calificación de Productores de bloques EOS", - "infoMessage": "Apoye la red votando por sus BP o proxy favoritos, una vez que haya votado por 21 BP puede comenzar a calificar." + "infoMessage": "Apoye la red votando por sus BP o proxy favoritos, una vez que haya votado por 21 BP puede comenzar a calificar.", + "enabled": "Habilitado", + "disabled": "Deshabilitado" }, "footer": { diff --git a/webapp/src/language/ko.json b/webapp/src/language/ko.json index c8bfe3b5..ec659398 100644 --- a/webapp/src/language/ko.json +++ b/webapp/src/language/ko.json @@ -170,21 +170,19 @@ "bpRatePage": { "allBPs": "모든 BPs 리스트", - "subTitle": "BPs 평가r", - "subText": "슬라이드 기능을 사용하여 BPs 평가하기.", - "rateText": "특정 카테고리 부분에 대한 정보가 부족할경우 선택을 하지 않고 비활성화 상태로 두셔도 됩니다.", + "subTitle": "이 블록 생산자 평가", "helpText": "선호하는 월렛으로 로그인하여 BPs 평가를 공개 하세요.", "publishRatingButton": "평가내용 공개하기", "updateRatingButton": "평가 내용 업데이트하기", "cancelRatingButton": "취소", "transparency": "투명도", - "transparencyTooltip": "오너쉽의 공개로 인한 투명성.", + "transparencyTooltip": "소유권 공개, 완전한 bp.json, 보상 사용 및 재무 통계 준수.", "infrastructure": "인프라", "infrastructureTooltip": "EOS 인프라의 안정성과 신뢰도 .", "trustiness": "신뢰도", "trustinessTooltip": "EOS 커뮤니티와의 협업으로 형성된 평판.", "community": "커뮤니티", - "communityTooltip": "커뮤니티는 교육과 이벤트 및 유용한 컨텐츠를 통해서 가치를 올릴 수 있습니다.", + "communityTooltip": "교육 및 홍보를 통한 커뮤니티 가치 창출, 대화, 채팅, 해커톤, 컨퍼런스, 세미나, 개발자 공간 및 기타 유용한 콘텐츠.", "development": "개발", "developmentTooltip": "기술정보 - 오픈소스 기반의 사용정보,스크립트,프레임워크,월렛,투표포탈,메트릭스,등등등.", "globalRate": "기본적인 평가", @@ -194,7 +192,9 @@ "noBlockProducer": "존재하지 않는 BP.", "success": "성공!", "title": "BPs의 인프라와 커뮤니티 평판 평가하기", - "infoMessage": "여러분이 선호하는 BPs에게 직접 투표 혹은 프록시를 통해서 네트워크를 지지하세요,21BPs에게 투표된 평가를 시작 할 수 있습니다." + "infoMessage": "여러분이 선호하는 BPs에게 직접 투표 혹은 프록시를 통해서 네트워크를 지지하세요,21BPs에게 투표된 평가를 시작 할 수 있습니다.", + "enabled": "활성화됨", + "disabled": "장애가있는" }, "footer": { diff --git a/webapp/src/routes/BlockProducers/BlockProducerProfile.js b/webapp/src/routes/BlockProducers/BlockProducerProfile.js index 48b3b101..5abd126a 100644 --- a/webapp/src/routes/BlockProducers/BlockProducerProfile.js +++ b/webapp/src/routes/BlockProducers/BlockProducerProfile.js @@ -271,7 +271,7 @@ const BlockProducerProfile = () => { ) } ]} - heads={['', t('amount'), t('average')]} + heads={[t('raters'), t('amount'), t('average')]} />
diff --git a/webapp/src/routes/BlockProducers/BlockProducerRate.js b/webapp/src/routes/BlockProducers/BlockProducerRate.js index 6a74bde3..c01e7c29 100644 --- a/webapp/src/routes/BlockProducers/BlockProducerRate.js +++ b/webapp/src/routes/BlockProducers/BlockProducerRate.js @@ -2,10 +2,10 @@ import React, { useState, useEffect, forwardRef } from 'react' import { useTranslation } from 'react-i18next' import { Link, useParams, useHistory } from 'react-router-dom' -import useMediaQuery from '@mui/material/useMediaQuery' import Avatar from '@mui/material/Avatar' import Button from '@mui/material/Button' import Grid from '@mui/material/Grid' +import PropTypes from 'prop-types' import CircularProgress from '@mui/material/CircularProgress' import Typography from '@mui/material/Typography' import AccountCircle from '@mui/icons-material/AccountCircle' @@ -17,6 +17,7 @@ import MuiAlert from '@mui/material/Alert' import { makeStyles } from '@mui/styles' import Box from '@mui/material/Box' +import Table from '../../components/Table' import TitlePage from '../../components/PageTitle' import PolarChart from '../../components/PolarChart' import getBPRadarData from '../../utils/get-bp-radar-data' @@ -49,6 +50,40 @@ const Alert = forwardRef(function Alert(props, ref) { return }) +const RadarSection = ({ t, state, polarChartData, classes }) => { + return ( + <> + + + + +
+ + + ) +} + +RadarSection.propTypes = { + t: PropTypes.object, + state: PropTypes.object, + polarChartData: PropTypes.object, + classes: PropTypes.object +} + const BlockProducerRate = () => { const classes = useStyles() const { account } = useParams() @@ -65,7 +100,6 @@ const BlockProducerRate = () => { const [polarChartData, setPolarChartData] = useState([]) const [showMessage, setShowMessage] = useState(false) const [showAlert, setShowAlert] = useState(false) - const isMobile = useMediaQuery('(max-width:767px)') const handleStateChange = parameter => (event, value) => { setRatingState({ ...ratingState, [parameter]: value }) @@ -331,7 +365,7 @@ const BlockProducerRate = () => { - + {blockProducerLogo ? ( @@ -347,18 +381,22 @@ const BlockProducerRate = () => { - - + + {t('subTitle')} - {t('subText')} - {t('helpText')} - {t('rateText')} - {isMobile && ( - - - - )} + + {' '} + {t('helpText')}{' '} + + + + { - - - {t('rateWithoutLogin')} - - - - - {ratingState.txError} - - - - - - - - - - {!isMobile && ( - - - - )} - - - + { {ratingState.processing && ( )} + + + +
{ { rater: t('globalRate'), amount: state.blockProducer?.ratings_cntr || 0, - average: formatNumber(state.blockProducer?.average, 1) || 0.0 + average: getAverageValue(_get(state.blockProducer, 'average', 0)) }, { rater: t('edenRates'), amount: state.blockProducer?.eden_ratings_cntr || 0, - average: formatNumber(state.blockProducer?.eden_average, 1) || 0.0 + average: getAverageValue( + _get(state.blockProducer, 'eden_average', 0) + ) + }, + { + rater: t('totalRates'), + amount: state.blockProducer?.totalStats?.ratings_cntr || 0, + average: formatNumber( + state.blockProducer?.totalStats?.average || 0.0, + 1 + ) } ]} heads={[t('raters'), t('amount'), t('average')]} @@ -171,11 +182,11 @@ const BlockProducerRate = () => { } const getSavedRatingData = rate => ({ - community: parseFloat(rate?.community || 0), - development: parseFloat(rate?.development || 0), - infrastructure: parseFloat(rate?.infrastructure || 0), - transparency: parseFloat(rate?.transparency || 0), - trustiness: parseFloat(rate?.trustiness || 0) + community: parseFloat(formatNumber(rate?.community || 0, 1)), + development: parseFloat(formatNumber(rate?.development || 0, 1)), + infrastructure: parseFloat(formatNumber(rate?.infrastructure || 0, 1)), + transparency: parseFloat(formatNumber(rate?.transparency || 0, 1)), + trustiness: parseFloat(formatNumber(rate?.trustiness || 0, 1)) }) const transact = async () => { @@ -263,11 +274,19 @@ const BlockProducerRate = () => { ) setBlockProducerLogo(_get(bp, 'bpjson.org.branding.logo_256', null)) const generalRateData = toNumbers(bp.data.data) - setPolarChartData([ - { ...bp.data, name: t('eosRates'), data: generalRateData }, - edenDataSet, - userDataSet - ]) + + if (bp.totalStats) { + const totalStatsDataSet = getBPRadarData({ + name: t('totalRates'), + parameters: getSavedRatingData(bp?.totalStats) + }) + setPolarChartData([ + { ...bp.data, name: t('globalRate'), data: generalRateData }, + edenDataSet, + userDataSet, + totalStatsDataSet + ]) + } } } @@ -278,8 +297,8 @@ const BlockProducerRate = () => { const bp = state.blockProducers.data.find( ({ owner }) => owner === account ) - setProfileData(bp, {}) setProducer(bp, true) + setProfileData(bp, {}) return } @@ -292,7 +311,6 @@ const BlockProducerRate = () => { useEffect(() => { if (state.user && state.blockProducer) { - // const { userRates = [] } = state.user.userData const bpRated = (state.user?.userData?.userRates || []).find( rate => rate.owner === state.blockProducer.owner ) diff --git a/webapp/src/routes/BlockProducers/index.js b/webapp/src/routes/BlockProducers/index.js index f7a99bb5..c783a3ea 100644 --- a/webapp/src/routes/BlockProducers/index.js +++ b/webapp/src/routes/BlockProducers/index.js @@ -55,6 +55,7 @@ const AllBps = () => { const handleToggleSelected = (item, isAddItem = false) => { if (isAddItem) { setSelectedProducers([...state.selectedProducers, item]) + console.log({ selectedProducers: state?.selectedProducers }) } else { const removeSelected = state.selectedProducers.filter( bpName => bpName !== item @@ -140,6 +141,15 @@ const AllBps = () => { } } + useEffect(() => { + if (!state.user) return + + setSelectedProducers([ + ...state.selectedProducers, + ...state?.user?.userData?.voter_info?.producers + ]) + }, [state.user]) + useEffect(() => { const getData = async () => { !state.blockProducers.data.length && @@ -192,7 +202,7 @@ const AllBps = () => { key={`${blockProducer.owner}-main-block-card`} > () => { @@ -204,8 +214,10 @@ const AllBps = () => { title={_get(blockProducer, 'bpjson.org.candidate_name')} pathLink='block-producers' buttonLabel={t('addToVote')} - average={getAverageValue(_get(blockProducer, 'average', 0))} - rate={_get(blockProducer, 'ratings_cntr', 0)} + average={getAverageValue( + _get(blockProducer, 'totalStats.average', 0) + )} + rate={_get(blockProducer, 'totalStats.ratings_cntr', 0)} isNewRate={ state.user && state.user.userData.userRates.some( diff --git a/webapp/src/routes/BlockProducers/styles.js b/webapp/src/routes/BlockProducers/styles.js index 573e2a34..8bbcfdff 100644 --- a/webapp/src/routes/BlockProducers/styles.js +++ b/webapp/src/routes/BlockProducers/styles.js @@ -330,10 +330,10 @@ export default theme => ({ chartWrapperSliderView: { '& .highcharts-container ': { height: '400px !important', - width: '325px !important', + width: '100% !important', '& > svg': { height: '400px !important', - width: '325px !important' + width: '100% !important' } } }, diff --git a/webapp/src/utils/get-average-value.js b/webapp/src/utils/get-average-value.js index de08733f..fc2fe45f 100644 --- a/webapp/src/utils/get-average-value.js +++ b/webapp/src/utils/get-average-value.js @@ -1,5 +1,5 @@ const validateNumber = average => { - const value = average.toFixed(2) + const value = average.toFixed(1) if (value % 1 === 0) return parseInt(value) From 59db27eb880142f75401771f6b393d5248f8189c Mon Sep 17 00:00:00 2001 From: Leister Francisco Alvarez Campos Date: Fri, 8 Oct 2021 09:27:31 -0600 Subject: [PATCH 14/15] feat(contracts): RAM optimization (#815) * feat(contracts): add freeupram action * feat(contracts): add freeupram action * fix(contracts): fix missing stats updates for rateproducer scope * fix(contracts): update wasm file * fix(contracts): add missing emplace to update_stats_migration --- .../rateproducer/include/rateproducer.hpp | 12 ++- contracts/rateproducer/rateproducer.abi | 10 ++ contracts/rateproducer/rateproducer.wasm | Bin 40096 -> 42395 bytes .../ricardian/rateproducer-ricardian.cpp | 6 ++ contracts/rateproducer/src/rateproducer.cpp | 100 ++++++++++++------ 5 files changed, 95 insertions(+), 33 deletions(-) diff --git a/contracts/rateproducer/include/rateproducer.hpp b/contracts/rateproducer/include/rateproducer.hpp index 62d54b3c..b2d4a2bf 100644 --- a/contracts/rateproducer/include/rateproducer.hpp +++ b/contracts/rateproducer/include/rateproducer.hpp @@ -603,7 +603,7 @@ namespace eoscostarica { * @param bp - Block Producer account name * */ - void update_stats_migration(name scope, name user, name bp); + void update_stats_migration(name bp); /** * @@ -611,6 +611,13 @@ namespace eoscostarica { * */ void migrate(); + + /** + * + * Liberate the ram used on ratings table under rateproducer and eden scope + * + */ + void freeupram(); }; EOSIO_ACTIONS(rateproducer, @@ -620,6 +627,7 @@ namespace eoscostarica { action(wipe, ricardian_contract(wipe_ricardian)), action(rminactive, ricardian_contract(rminactive_ricardian)), action(rmrate, user, bp, ricardian_contract(rmrate_ricardian)), - action(migrate, ricardian_contract(migrate_ricardian))) + action(migrate, ricardian_contract(migrate_ricardian)), + action(freeupram, ricardian_contract(freeupram_ricardian))) } // namespace eoscostarica \ No newline at end of file diff --git a/contracts/rateproducer/rateproducer.abi b/contracts/rateproducer/rateproducer.abi index bb2a492e..cafb1af8 100644 --- a/contracts/rateproducer/rateproducer.abi +++ b/contracts/rateproducer/rateproducer.abi @@ -75,6 +75,11 @@ "base": "", "fields": [] }, + { + "name": "freeupram", + "base": "", + "fields": [] + }, { "name": "ratings_v2", "base": "", @@ -182,6 +187,11 @@ "name": "migrate", "type": "migrate", "ricardian_contract": "---\nspec_version: 0.1.0\ntitle: Update the current logic to newest\nsummary: The intent of the `{{ migrate }}` action is to update the current logic to newest.\n---" + }, + { + "name": "freeupram", + "type": "freeupram", + "ricardian_contract": "---\nspec_version: 0.1.0\ntitle: Free up RAM\nsummary: The intent of the `{{ freeupram }}` action is to remove all records from old ratings table including the rateproducer and eden scope.\n---" } ], "tables": [ diff --git a/contracts/rateproducer/rateproducer.wasm b/contracts/rateproducer/rateproducer.wasm index 58d82d750ba99b971dca208e2b57f76a475d5ac7..f65a49c3679091ff5afce17006b402e54ef5362d 100755 GIT binary patch delta 5161 zcmZu#4Rlpic0T*u`(9q&PjW*N2>F5gE z4|y>JOeP5<9u$OeWOb$^I=UA6Y#m!?bf(%MBFviB8LYL!a#}5G#@d!OtF|+>-@Z42 zsC`-Y?(?(HKKtySZ=ahpugcT!$VX@SWwKi|=}G*K#bzJdw%(&BySuxOU9P1ZRY)@_ zQ{78(vGqjso7<*bq{sy zZtmRBv9o=Xn4s$AJjzo;vXHXXv$72Df0TF91QpcUmM6Q(Cwe}6tcjC!sSBYAU67t7 zHQhtoC@V|-w`NVbFMT2jn*v6B!Q6ZQw50062OHO{S-Uoo@Q=JKyHj)ZFv;(~sTw`4 z=|ks*Q6vIi>gv18_tPnrUl-Fq7e=Q#>^)2C)U339)TEwGYhnJ2nUGyn0>hM42+hj_UqOwty&V7iQ)viDX7N}1G$H1T37wnP+gCinH0h4Um zWl8(SMUjX|5hhdGZ=}*Qw>yFl7`x=j5p~0;@|_tGC7K8e_0t8D)dN|t(G@ju!bkp5 z&24D$<%E7{(VxA@-)W`W!iFv<)s^hs)T-)oBH-Vf(@R^_?{kXfnGt2>-aGMi_t@aQ z@uslz3=#qRm623$Zmp!w)a6NUO1i3!=fA>dTv{-b$$^6JQM)n=FH*hwZQ%z}y{#@3 zwNs~hcvp_f+#XlMQ@%}Kq>83qB8d2n`7(_e*S@NrwSI$TPfV+&C)LN(o=bn>f@603 zgVYnnmvt83Qo@$JUNR37r{58!4%K+aOKfW6kFq4yq^z0s8r7(-((+r2)r+Oi-O?~M zG@HnO^c`0+M22eSVK()5WkJHqt8>P!Ocj-{r3ufE^1eSx2QQ|E?>a7hqo)0ldTRLr z*S%UPyn8Jcr>)AG`zovT;oN`ye+68*`h4nPHRT<0e%Qw(9!_Uc74|c!4hNXjhJ$LgFF$FfRcHo++gqXe zOrM!<`puvjcnrUANXGfk^qOgvJ46Prdx`?{r#(?~PQ@^MC2xfmy>Jnaaoarvo=3Tj z0QinOmVA^4Pdc3v?WD7ZG-_CSiDry5yVr571xB`jU2OO)JqiP0phU}C?O2;C=|E+- zNtN9z3M#Zb*noF(cIVi$ARVSOvF;?vIG?0=qopy8)Ifm7GX@Cw5I7vBSgWxNsAFn& z9vh48DQ%PE4F_`7!TTg7jG35;U`-e@$5t;43H9Q#so9t?ElrQhBqTa}7Av}aQGmw- zVV&ixwhAj>B3%;2A~OI8baVcyOHZl)ESuB73PPud)Pb&1xX0=EoKBwG2|ArZx0B;^ zd~U~ZI;KgCyk2)KPYus$aDl{s6TdE`u6LiK(6tdqgQwD@o+MSiB$~T~*Y=YkWgG^i z2;6B)m0a>V)v9}H=c)a*Q;L?lWdH_2F+g5=kTOdVuFM`(uh&-O)mjp912%y_`xk%X zp7ZECDr4z1T9ztX`jJyDvX{@9vE0HzapXk^+EIg;dI&D?m>Rpq!%@!B<1y+~=kjM9 zV7nV=yRt4$+ti7=H@HqcP(K}Tm8@S%RG)gcVGp4WELveRq7AH=ld;@_K@sAMLd1pV z!is{t20nz&CC>-K?$@ys_V~jJu1ZJlv#`gr_x;C&v6}OWYb(?n^}un&qbR>V<-vdZ~(<{Gyqd6dRG8=0%2$A zKmoE#6UGuJBMj8#h-|Voj$pDci$tZU5HL1~Rt=J@&@kaqA+=Y9e8IFy~lbimiurl*JJzOI-U+tdNvZz%RDFi{^vW!4j@JgOPm<25TI z*IbM`P3&ODun6i^#xkBUE#c%SBOTere1}m_$ET~hyC$pC%K~2HDh#eZix*DCbYN*x5Kh9G9|ZC69()(nq}P6%q2 zi@jVh@NhnP^*CY?%5W$m_|&oV9Q9dwUGU~2j~-Xc)5EImu22o68t!?%dFgP%dkU)m zC1Ibv1XYCn{Y&B=Zm?|;Un>Lupb;fG_SFlkC#j#Uo}C0T!uQvI_tLK~UV1Ir5b^?c zv1A1Za-XpJuc&fX7!c=?*)h-~FL?d)wlfEXELss&S86nX40Raa={=)PvcSiO)TRkJ@& z9}Um5BdWCVPCAupYP^?#cRyTnn!KuK{Rs(t+t^f!nd41|hdL0wU%zszqNx?CZSy+!6Xlg1fzjZz@T(xx>q&&0r0MsdN zXLZ)M=SPO$5_Z<;2ZLLVzAD8XgOu;JAEeExaK{$s@I%{feJfnXcfv>8D~MXuq#f-! z;}3Xq^^-g1&`I^~j`kUy44i4U)@90s4S%6!k%5a4CBn!%o16zP%T|+=nM5$ zR|S9R{BKvpdy*LK)QdY8TC#t?W2^HA?xzuD9xP8EdD}I}A5v=$4ideRI^FX&B}b#@ z29eH~01VO?5c!@fEL@WWUj=G$!elLHH?BYyUu5`3;u}{l5Z^k6jcjm=YL06%@&jL$ z!&gWaI9^urmavCWq}-}FCMa);a(sx^s`#ziDHEsLo@R`2b^Z_yk)P=s;;QD=E)EFRB%oC909%&Aal9+6e1_3JRGt0RlvID+UzTxpjMD?t>{S2LUs=+Ft%dP0@i|dGO`F;R zQGD4jM=$YEo{ek!AyOL#DydKX`9SmBK9@IU`#Fuq_zIah#>|H?k83BN=?IQ{Q^+H# z@>^?=ZD+pqlE2ISj1a~S)i^jeeF#hN6#=EbI~XY#hW31+%HvlM*N`BjaMReOt_^n3 z4pl!iJ>%Ps(!e%8_A%8rRC>$9`_)f|7WiE683&X$ynwouJzRx^J~BLyj;o&zN9l3( zU&D9M6RBxOYtq78gYm!`c4orfw%vl}363%+zfhOe@Z-~`p*%a^I>;D&eh9ngk}z;V z4;;@RV8$CFFqn~g@9__4;nMYO&E}4soy}%fhuOKa-E7*rrKNLyS96oOeq+~`j&^fH z^Je^m&6(?J-LhkJSm5Wwga3R9f9ll}EtJJW0X#uGAv_ss=94K;CR#@7pP&4gW|vw* l%*BJNmRN;n6P_+S!+4&?^D>?f@MKOCq5;ny^~LFD{ttT4$T|Q3 delta 3491 zcmai13vg7`89x8HcQ>28yU8VFLo^BAY!cXD1Dk-mO8}FLJiK5(Z1rF}uUd9{_H&4lynLWprbt7js8Eh;` z;S7?Tki?jh3aMb@HaE9{ZOoWt`Y=YPcE)6r*l|$uW@O4-W=vu-138ULvJJL@s^Sll zHz%Cz0j7hJT0VVFMd7T~tJhRjtzCQ9UCy4T_%7pCIT!flxA0EeR(|Fbp0>5Z04}x9 zfG9p_e-_r^)TCW-2fmP0D_wqzVVP$lmN^uD^^~#LQ45YUro1>S5g%u{ zpm9BJq@*^2&}yH$gI^fLf2ni$@F13r`4|pkR@!II#O*pk8((M;K>&vCVCcTT(wju?5l4xJyQjy=-&+*2R(~9M2!!|z0Kh$ zK62x4MsCq$4I3&v*pQ`~I%Pct5iH0)1IzH6?2q~T@8G$dD4Ffe=ofGTf7uW;s&0B1 zNYvNb%aA;x>QQ{bdxcnzt85w0ZGYO zdYu%*J8eCrT}facIc@QrK5g{g(#M5rzK|6kA<0i(z7#5lyK&<56GFMqr~mmUSwEfe zktA4ODVrg#{if`!ulk)-SQhY!(FC zp-I|EQ!FU0p>qgIl{B$JiS{dK#e-7F;`7ra>+i5gfct3iPZlBS6T}};Z|3Ei?Bjd9 zwz+PSS}6H7TVYI6+r&CVYst~JztTL@S%Bvg7fqTqWm{9GHKkjVYE3SUX`o5;C0|^n z36d>HrXcBpsDij6s!-5UyxC-uXD5{Wo2lymTu&S#`7Bk@Uwg~+?6XN+j&aPa40sl3P$(S&mGg2k3ix<8=uX^R z`35Y+yl^S^+Oax3e!?OvR}VvkGBy;U>p)$kkm7d1s2Is= zCB9LWL3e#rC91`SwO-1w*0tZHjnsng2CazyZV(TwqeJ7lb*t#E6}4@$lS&}XVDxp)G22LUMz*I2+cL5a*zCLX1( za>FQUF`?`MUSXjsf)WLZ08zGxmy<&!vZWQnmk04!%@i0g&etpi@@97J5lF)5-4Ao} zUQ(olPD&&5zIb13->>h04%~RpOhA0>o};eodjc+q zHeFZP2NIpohxPj=VfVInA!T3VSoAj*YwN{ZSP}D6GrJ1&$uqL3qt>K}_A4fOQpy|4*SHfzT5<^`r0(;Ge_d*| zaE*13`ODz7{ku)`Oh2$14r0%NX~_o@t^2pe*#qt78C0*rCCl8#>r1Ir9W&M*dKYYF z0OI)e63+m5DQ6rSb2BOmYMqzqpA2D5`ve$=9qs-x_vz3`24d=V(+2AOIMhDTIl8+8 ze`ud_4b)_Tn(@|-$yp;H5e*J?XClDFdKVt-$b&ZgRYwugKXgohw%$%6II*+H)<#vE z;iny5xee4djCB^%!AqS1wGA{@%Baqm5v7!1Zo4Phtnq4#x*szhDuo9z{LqsM0l~sd z!LPfGibBG?b4`jI|Px{gZN^Xxcu|3Swyw& zS5yCfhK%JBI*4aHgnI_2q$R*zR!ty57tq&J0lTrWrzGX_2!oAG*oZIn%r4kN&r|mb zYuJ2T)1giY@J#AjOl=W6nL0$&7-sj*hB$8MtqH{~WJq_4)J>qW1vDg}`^>zhZ!Wc! z3^Xd@0sOwVn&NjI9(QgFP%Dy%w*klXO;0`~9&PGV)#uClIVmpQn<EuaK!#HHM%30*b%QW$b$zE-z!* eG<-BdG{Q7C(`csg1daD;WaKe66Tkh%Gyef@eWD2f diff --git a/contracts/rateproducer/ricardian/rateproducer-ricardian.cpp b/contracts/rateproducer/ricardian/rateproducer-ricardian.cpp index a70f98d7..57b94d96 100644 --- a/contracts/rateproducer/ricardian/rateproducer-ricardian.cpp +++ b/contracts/rateproducer/ricardian/rateproducer-ricardian.cpp @@ -36,6 +36,12 @@ title: Update the current logic to newest summary: The intent of the `{{ migrate }}` action is to update the current logic to newest. ---)"; +const char* freeupram_ricardian = R"(--- +spec_version: 0.1.0 +title: Free up RAM +summary: The intent of the `{{ freeupram }}` action is to remove all records from old ratings table including the rateproducer and eden scope. +---)"; + // CLAUSES const char* datastorage_clause = R"(The rateproducer application values the security of personal data. We may process only minimal user data as much as it is necessary to maintain the rateproducer application running. We only receive and store any information you knowingly provide to us when you create an account, or fill using the app.)"; diff --git a/contracts/rateproducer/src/rateproducer.cpp b/contracts/rateproducer/src/rateproducer.cpp index dc119e5f..5466a683 100644 --- a/contracts/rateproducer/src/rateproducer.cpp +++ b/contracts/rateproducer/src/rateproducer.cpp @@ -481,26 +481,21 @@ namespace eoscostarica { &bp_average); } - void rateproducer::update_stats_migration(name scope, name user, name bp) { - ratings_table_v2 _ratings(_self, scope.value); - auto uniq_rating = (static_cast(user.value) << 64) | bp.value; - - auto uniq_rating_index = _ratings.get_index(); - auto existing_rating = uniq_rating_index.find(uniq_rating); + void rateproducer::update_stats_migration(name bp) { + name default_scope = _self; + name ram_payer = _self; - check( existing_rating != uniq_rating_index.end(), "Rating does not exist" ); - //update bp stats float bp_transparency = 0; float bp_infrastructure = 0; float bp_trustiness = 0; float bp_community = 0; float bp_development = 0; - uint32_t bp_ratings_cntr = 0; + uint32_t bp_ratings_cntr = 0; float bp_average = 0; //re-calculate stats for the bp - calculate_bp_stats (scope, + calculate_bp_stats (default_scope, bp, &bp_transparency, &bp_infrastructure, @@ -509,35 +504,56 @@ namespace eoscostarica { &bp_development, &bp_ratings_cntr, &bp_average); + + float totalStats = + bp_transparency + + bp_infrastructure + + bp_trustiness + + bp_community + + bp_development; - //save the re-calcualtes stats - name ram_payer = _self; - update_bp_stats (scope, - &ram_payer, - &bp, - &bp_transparency, - &bp_infrastructure, - &bp_trustiness, - &bp_community, - &bp_development, - &bp_ratings_cntr, - &bp_average); + name stats_ram_payer =_self; + stats_table _stats(_self, default_scope.value); + auto itr = _stats.find(bp.value); + if(itr != _stats.end()) { + if(totalStats) { + _stats.modify(itr, stats_ram_payer, [&]( auto& row ) { + row.transparency = bp_transparency; + row.infrastructure = bp_infrastructure; + row.trustiness = bp_trustiness; + row.development = bp_community; + row.community = bp_development; + row.ratings_cntr = bp_ratings_cntr; + row.average = bp_average; + }); + } else _stats.erase(itr); + } else { + if(totalStats) { + _stats.emplace(stats_ram_payer, [&]( auto& row ) { + row.bp = bp; + row.transparency = bp_transparency; + row.infrastructure = bp_infrastructure; + row.trustiness = bp_trustiness; + row.development = bp_community; + row.community = bp_development; + row.ratings_cntr = bp_ratings_cntr; + row.average = bp_average; + }); + } + } } void rateproducer::migrate() { config c = cfg.get_or_create(_self, config{.owner = _self, .version = 0}); require_auth(c.owner); - // assert we only run once // the comparison value needs to be hard-coded with each new migration eosio::check(c.version < 2, "Migration already ran"); - ratings_table _ratings_self(_self, _self.value); ratings_table_v2 _ratings_self_v2(_self, _self.value); ratings_table_v2 _ratings_eden_v2(_self, eden_scope.value); - for(auto itr = _ratings_self.begin(); itr != _ratings_self.end(); itr++) { - auto modify_rating = [&]( auto& row ) -> auto { + auto emplace_rating = [&]( auto& row ) -> auto { row.id = itr->id; row.user = itr->user; row.bp = itr->bp; @@ -547,16 +563,38 @@ namespace eoscostarica { row.community = itr->community; row.development = itr->development; }; - - name tempScope = is_eden(itr->user) ? eden_scope : _self; - if(tempScope.value == eden_scope.value) _ratings_eden_v2.emplace(_self, modify_rating); - else _ratings_self_v2.emplace(_self, modify_rating); - update_stats_migration(tempScope, itr->user, itr->bp); + + name temp_scope = is_eden(itr->user) ? eden_scope : _self; + if(temp_scope.value == eden_scope.value) _ratings_eden_v2.emplace(_self, emplace_rating); + else _ratings_self_v2.emplace(_self, emplace_rating); + update_stats_migration(itr->bp); } c.version++; cfg.set(c, c.owner); } + + void rateproducer::freeupram() { + config c = cfg.get_or_create(_self, config{.owner = _self, .version = 0}); + require_auth(_self); + + eosio::check(c.version < 3, "Make sure to run `migrate` action before run this action"); + + ratings_table _ratings_general(_self, _self.value); + auto general_itr = _ratings_general.begin(); + while (general_itr != _ratings_general.end()) { + general_itr = _ratings_general.erase(general_itr); + } + + ratings_table _ratings_eden(_self, eden_scope.value); + auto eden_itr = _ratings_eden.begin(); + while (eden_itr != _ratings_eden.end()) { + eden_itr = _ratings_eden.erase(eden_itr); + } + + c.version++; + cfg.set(c, c.owner); + } } // namespace eoscostarica From 808bdc7f86ba142d2196d5d37cf1425fb5029aee Mon Sep 17 00:00:00 2001 From: Leister Francisco Alvarez Campos Date: Fri, 8 Oct 2021 09:56:38 -0600 Subject: [PATCH 15/15] fix(hapi): update scope to cronjob sync (#819) --- hapi/src/libs/sync-ratings.js | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/hapi/src/libs/sync-ratings.js b/hapi/src/libs/sync-ratings.js index 4bae8ff9..f8d0b9ac 100644 --- a/hapi/src/libs/sync-ratings.js +++ b/hapi/src/libs/sync-ratings.js @@ -1,20 +1,24 @@ #!/usr/bin/env node const { JsonRpc } = require('eosjs') const fetch = require('node-fetch') -const { massiveDB } = require('../config') +const { + generalContractScope, + edenContractScope, + massiveDB +} = require('../config') const HAPI_EOS_API_ENDPOINT = process.env.HAPI_EOS_API_ENDPOINT || 'https://jungle.eosio.cr' const HAPI_RATING_CONTRACT = process.env.HAPI_RATING_CONTRACT || 'rateproducer' -const getUserRatings = async () => { +const getUserRatings = async (scope) => { const eos = new JsonRpc(HAPI_EOS_API_ENDPOINT, { fetch }) try { const ratings = await eos.get_table_rows({ json: true, code: HAPI_RATING_CONTRACT, - scope: HAPI_RATING_CONTRACT, + scope: scope, table: 'rating', limit: 1000, reverse: false, @@ -28,9 +32,9 @@ const getUserRatings = async () => { } } -const updateUserRatings = async () => { - console.log('==== Updating ratings ====') - const userRatings = await getUserRatings() +const updateUserRatingsAux = async (scope) => { + console.log(`==== Updating ratings for ${scope} ====`) + const userRatings = await getUserRatings(scope) userRatings.rows.forEach(async (rating) => { const ratingsCore = { @@ -63,4 +67,9 @@ const updateUserRatings = async () => { }) } -updateUserRatings() +const updateUserRatings = () => { + updateUserRatingsAux(generalContractScope) + updateUserRatingsAux(edenContractScope) +} + +updateUserRatings() \ No newline at end of file