From 98bb9d082ccc62c87a94d8872e9be9dd729a1a16 Mon Sep 17 00:00:00 2001 From: Sylvain Date: Fri, 2 Apr 2021 16:02:50 +0200 Subject: [PATCH] fix fab-input and payzen-keys-form --- CHANGELOG.md | 1 + .../src/javascript/components/fab-input.tsx | 11 +-- .../components/payzen-keys-form.tsx | 84 +++++++++++-------- .../components/stripe-keys-form.tsx | 7 +- .../stylesheets/modules/payzen-keys-form.scss | 8 +- config/locales/app.admin.en.yml | 2 +- config/locales/app.admin.fr.yml | 2 +- package.json | 16 ++-- tsconfig.json | 5 +- yarn.lock | 84 ++++++++++--------- 10 files changed, 127 insertions(+), 93 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 012cfe4cb..f2c5c1541 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # Changelog Fab-manager ## Next release +- Updated React and its dependencies to 17.0.3 and matching - [TODO DEPLOY] `rails fablab:stripe:set_gateway` - [TODO DEPLOY] `rails fablab:maintenance:rebuild_stylesheet` diff --git a/app/frontend/src/javascript/components/fab-input.tsx b/app/frontend/src/javascript/components/fab-input.tsx index f153fc7b8..89feb9c38 100644 --- a/app/frontend/src/javascript/components/fab-input.tsx +++ b/app/frontend/src/javascript/components/fab-input.tsx @@ -4,9 +4,6 @@ import React, { BaseSyntheticEvent, ReactNode, useCallback, useEffect, useState } from 'react'; import { debounce as _debounce } from 'lodash'; -import SettingAPI from '../api/setting'; -import { SettingName } from '../models/setting'; -import { loadStripe } from '@stripe/stripe-js'; interface FabInputProps { id: string, @@ -26,7 +23,7 @@ export const FabInput: React.FC = ({ id, onChange, value, icon, c const [inputValue, setInputValue] = useState(value); useEffect(() => { - if (value) { + if (value !== inputValue) { setInputValue(value); onChange(value); } @@ -49,17 +46,17 @@ export const FabInput: React.FC = ({ id, onChange, value, icon, c /** * Debounced (ie. temporised) version of the 'on change' callback. */ - const handler = useCallback(_debounce(onChange, debounce), []); + const debouncedOnChange = useCallback(_debounce(onChange, debounce), [onChange, debounce]); /** - * Handle the action of the button + * Handle the change of content in the input field, and trigger the parent callback, if any */ const handleChange = (e: BaseSyntheticEvent): void => { const newValue = e.target.value; setInputValue(newValue); if (typeof onChange === 'function') { if (debounce) { - handler(newValue); + debouncedOnChange(newValue); } else { onChange(newValue); } diff --git a/app/frontend/src/javascript/components/payzen-keys-form.tsx b/app/frontend/src/javascript/components/payzen-keys-form.tsx index 01677d1db..09ab2fbf0 100644 --- a/app/frontend/src/javascript/components/payzen-keys-form.tsx +++ b/app/frontend/src/javascript/components/payzen-keys-form.tsx @@ -19,8 +19,13 @@ interface PayZenKeysFormProps { } const payZenSettings: Array = [SettingName.PayZenUsername, SettingName.PayZenPassword, SettingName.PayZenEndpoint, SettingName.PayZenHmacKey, SettingName.PayZenPublicKey]; +const restApiSettings: Array = [SettingName.PayZenUsername, SettingName.PayZenPassword, SettingName.PayZenEndpoint, SettingName.PayZenHmacKey]; const payZenKeys = SettingAPI.query(payZenSettings); +// Prevent multiples call to the payzen keys validation endpoint. +// this cannot be handled by a React state because of their asynchronous nature +let pendingKeysValidation = false; + const PayZenKeysFormComponent: React.FC = ({ onValidKeys }) => { const { t } = useTranslation('admin'); @@ -41,8 +46,13 @@ const PayZenKeysFormComponent: React.FC = ({ onValidKeys }) } }, [publicKeyAddOnClassName, restApiAddOnClassName, settings]); + useEffect(() => { + testRestApi(); + }, [settings]) + /** - * Check if the inputted public key is valid and assign it to the settings if the key is valid + * Assign the inputted key to the settings and check if it is valid. + * Depending on the test result, assign an add-on icon and a style to notify the user. */ const testPublicKey = (key: string) => { if (!key.match(/^[0-9]+:/)) { @@ -56,37 +66,45 @@ const PayZenKeysFormComponent: React.FC = ({ onValidKeys }) } /** - * Send a test call to the payZen REST API to check if the inputted settings key are valid + * Send a test call to the payZen REST API to check if the inputted settings key are valid. + * Depending on the test result, assign an add-on icon and a style to notify the user. */ - const testRestApi = (setting: SettingName.PayZenUsername | SettingName.PayZenPassword | SettingName.PayZenEndpoint | SettingName.PayZenHmacKey) => { - return (key: string) => { - updateSettings(draft => draft.set(setting, key)); - let valid = true; - for (const settingKey of [SettingName.PayZenUsername, SettingName.PayZenPassword, SettingName.PayZenEndpoint, SettingName.PayZenHmacKey]) { - if (!settings.get(settingKey)) { - valid = false; - break; - } - } - if (valid) { - PayzenAPI.chargeSDKTest( - settings.get(SettingName.PayZenEndpoint), - settings.get(SettingName.PayZenUsername), - settings.get(SettingName.PayZenPassword) - ).then(result => { - if (result.success) { - setRestApiAddOn(); - setRestApiAddOnClassName('key-valid'); - } else { - setRestApiAddOn(); - setRestApiAddOnClassName('key-invalid'); - } - }, () => { + const testRestApi = () => { + let valid: boolean = restApiSettings.map(s => !!settings.get(s)) + .reduce((acc, val) => acc && val, true); + + if (valid && !pendingKeysValidation) { + pendingKeysValidation = true; + PayzenAPI.chargeSDKTest( + settings.get(SettingName.PayZenEndpoint), + settings.get(SettingName.PayZenUsername), + settings.get(SettingName.PayZenPassword) + ).then(result => { + pendingKeysValidation = false; + + if (result.success) { + setRestApiAddOn(); + setRestApiAddOnClassName('key-valid'); + } else { setRestApiAddOn(); setRestApiAddOnClassName('key-invalid'); - }); - } - }; + } + }, () => { + pendingKeysValidation = false; + + setRestApiAddOn(); + setRestApiAddOnClassName('key-invalid'); + }); + } + } + + /** + * Assign the inputted key to the given settings + */ + const setApiKey = (setting: SettingName.PayZenUsername | SettingName.PayZenPassword | SettingName.PayZenEndpoint | SettingName.PayZenHmacKey) => { + return (key: string) => { + updateSettings(draft => draft.set(setting, key)); + } } /** @@ -125,7 +143,7 @@ const PayZenKeysFormComponent: React.FC = ({ onValidKeys }) type="number" icon={} value={settings.get(SettingName.PayZenUsername)} - onChange={testRestApi(SettingName.PayZenUsername)} + onChange={setApiKey(SettingName.PayZenUsername)} debounce={200} required /> @@ -134,7 +152,7 @@ const PayZenKeysFormComponent: React.FC = ({ onValidKeys }) } value={settings.get(SettingName.PayZenPassword)} - onChange={testRestApi(SettingName.PayZenPassword)} + onChange={setApiKey(SettingName.PayZenPassword)} debounce={200} required /> @@ -144,7 +162,7 @@ const PayZenKeysFormComponent: React.FC = ({ onValidKeys }) type="url" icon={} value={settings.get(SettingName.PayZenEndpoint)} - onChange={testRestApi(SettingName.PayZenEndpoint)} + onChange={setApiKey(SettingName.PayZenEndpoint)} debounce={200} required /> @@ -153,7 +171,7 @@ const PayZenKeysFormComponent: React.FC = ({ onValidKeys }) } value={settings.get(SettingName.PayZenHmacKey)} - onChange={testRestApi(SettingName.PayZenHmacKey)} + onChange={setApiKey(SettingName.PayZenHmacKey)} debounce={200} required /> diff --git a/app/frontend/src/javascript/components/stripe-keys-form.tsx b/app/frontend/src/javascript/components/stripe-keys-form.tsx index 7babfba05..e55e421b9 100644 --- a/app/frontend/src/javascript/components/stripe-keys-form.tsx +++ b/app/frontend/src/javascript/components/stripe-keys-form.tsx @@ -20,7 +20,7 @@ const stripeKeys = SettingAPI.query([SettingName.StripePublicKey, SettingName.St const StripeKeysFormComponent: React.FC = ({ onValidKeys }) => { const { t } = useTranslation('admin'); - const mounted = useRef(null); + const mounted = useRef(false); const [publicKey, setPublicKey] = useState(''); const [publicKeyAddOn, setPublicKeyAddOn] = useState(null); @@ -30,9 +30,14 @@ const StripeKeysFormComponent: React.FC = ({ onValidKeys }) const [secretKeyAddOnClassName, setSecretKeyAddOnClassName] = useState(''); useEffect(() => { + mounted.current = true; const keys = stripeKeys.read(); setPublicKey(keys.get(SettingName.StripePublicKey)); setSecretKey(keys.get(SettingName.StripeSecretKey)); + + return () => { + mounted.current = false; + }; }, []); useEffect(() => { diff --git a/app/frontend/src/stylesheets/modules/payzen-keys-form.scss b/app/frontend/src/stylesheets/modules/payzen-keys-form.scss index 3d700afff..c73cc6796 100644 --- a/app/frontend/src/stylesheets/modules/payzen-keys-form.scss +++ b/app/frontend/src/stylesheets/modules/payzen-keys-form.scss @@ -34,13 +34,19 @@ display: block; position: absolute; top: 0; - right: -40px; font-size: 1em; padding: 3px 12px; font-weight: 400; text-align: center; border-radius: 0 4px 4px 0; vertical-align: middle; + + &.key-invalid { + right: -35px; + } + &.key-valid { + right: -40px; + } } } diff --git a/config/locales/app.admin.en.yml b/config/locales/app.admin.en.yml index b6d068665..045cc7c99 100644 --- a/config/locales/app.admin.en.yml +++ b/config/locales/app.admin.en.yml @@ -639,7 +639,7 @@ en: stripe_keys_saved: "Stripe keys successfully saved." error_saving_stripe_keys: "Unable to save the Stripe keys. Please try again later." payzen_keys_info_html: "

To be able to collect online payments, you must configure the PayZen identifiers and keys.

Retrieve them from your merchant back office.

" - client_keys: "Client keys" + client_keys: "Client key" api_keys: "API keys" username: "User" password: "Password" diff --git a/config/locales/app.admin.fr.yml b/config/locales/app.admin.fr.yml index a29014072..33077ec9e 100644 --- a/config/locales/app.admin.fr.yml +++ b/config/locales/app.admin.fr.yml @@ -639,7 +639,7 @@ fr: stripe_keys_saved: "Les clefs Stripe ont bien été enregistrées." error_saving_stripe_keys: "Impossible d’enregistrer les clefs Stripe. Veuillez réessayer ultérieurement." payzen_keys_info_html: "

Pour pouvoir encaisser des paiements en ligne, vous devez configurer les identifiants et les clefs PayZen.

Retrouvez les dans votre back office marchant.

" - client_keys: "Clefs client" + client_keys: "Clef client" api_keys: "Clefs d'API" username: "Utilisateur" password: "Mot de passe" diff --git a/package.json b/package.json index f197ddcb8..298d5ea1a 100644 --- a/package.json +++ b/package.json @@ -36,16 +36,17 @@ "webpack-dev-server": "^3.11.0" }, "dependencies": { + "@babel/core": "^7.0.0-0", "@babel/preset-react": "^7.12.1", "@babel/preset-typescript": "^7.12.1", "@claviska/jquery-minicolors": "^2.3.5", "@fortawesome/fontawesome-free": "5.14.0", "@lyracom/embedded-form-glue": "^0.3.3", "@rails/webpacker": "5.2.1", - "@stripe/react-stripe-js": "^1.1.2", - "@stripe/stripe-js": "^1.11.0", - "@types/react": "^16.9.53", - "@types/react-dom": "^16.9.8", + "@stripe/react-stripe-js": "^1.4.0", + "@stripe/stripe-js": "^1.13.2", + "@types/react": "^17.0.3", + "@types/react-dom": "^17.0.3", "@uirouter/angularjs": "0.4", "AngularDevise": "https://github.com/cloudspace/angular_devise.git#1.0.2", "angular": "1.8", @@ -100,11 +101,11 @@ "ngUpload": "0.5", "nvd3": "1.8", "prop-types": "^15.7.2", - "react": "^17.0.0", - "react-dom": "^17.0.0", + "react": "^17.0.2", + "react-dom": "^17.0.2", "react-i18next": "^11.7.3", "react-modal": "^3.11.2", - "react-switch": "^5.0.1", + "react-switch": "^6.0.0", "react2angular": "^4.0.6", "summernote": "0.8.18", "twitter-fetcher": "^18.0.2", @@ -114,7 +115,6 @@ "use-immer": "^0.5.1" }, "peerDependencies": { - "@babel/core": "^7.0.0-0", "@types/angular": "^1.7.3", "@types/prop-types": "^15.7.2" } diff --git a/tsconfig.json b/tsconfig.json index 198ab258f..5c65c41d8 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -3,14 +3,15 @@ "declaration": false, "emitDecoratorMetadata": true, "experimentalDecorators": true, - "lib": ["es6", "dom"], + "lib": ["es6", "dom", "es2015.collection", "es2015.iterable"], "module": "es6", "moduleResolution": "node", "sourceMap": true, "target": "es5", "jsx": "react", "noEmit": true, - "allowSyntheticDefaultImports": true + "allowSyntheticDefaultImports": true, + "downlevelIteration": true, }, "exclude": [ "**/*.spec.ts", diff --git a/yarn.lock b/yarn.lock index 9305b9f7e..9d366eb6e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -14,7 +14,7 @@ resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.13.12.tgz#a8a5ccac19c200f9dd49624cac6e19d7be1236a1" integrity sha512-3eJJ841uKxeV8dcN/2yGEUy+RfgQspPEgQat85umsE1rotuquQ2AbIub4S6j7c50a2d+4myc+zSlnXeIHrOnhQ== -"@babel/core@^7.11.1": +"@babel/core@^7.0.0-0", "@babel/core@^7.11.1": version "7.13.14" resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.13.14.tgz#8e46ebbaca460a63497c797e574038ab04ae6d06" integrity sha512-wZso/vyF4ki0l0znlgM4inxbdrUvCb+cVz8grxDq+6C9k6qbqoIJteQOKicaKjCipU3ISV+XedCqpL2RJJVehA== @@ -1119,17 +1119,17 @@ webpack-cli "^3.3.12" webpack-sources "^1.4.3" -"@stripe/react-stripe-js@^1.1.2": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@stripe/react-stripe-js/-/react-stripe-js-1.1.2.tgz#a7f5ef5b4d7dc7fa723501b706644414cfe6dcba" - integrity sha512-07hu8RJXwWKGbvdvd1yt1cYvGtDB8jFX+q10f7FQuItUt9rlSo0am3WIx845iMHANiYgxyRb1PS201Yle9xxPQ== +"@stripe/react-stripe-js@^1.4.0": + version "1.4.0" + resolved "https://registry.yarnpkg.com/@stripe/react-stripe-js/-/react-stripe-js-1.4.0.tgz#a67e72202297fc409dc2c8c4f3fb98e0b61fa06d" + integrity sha512-Pz5QmG8PgJ3pi8gOWxlngk+ns63p2L1Ds192fn55ykZNRKfGz3G6sfssUVThHn/NAt2Hp1eCEsy/hvlKnXJI6g== dependencies: prop-types "^15.7.2" -"@stripe/stripe-js@^1.11.0": - version "1.11.0" - resolved "https://registry.yarnpkg.com/@stripe/stripe-js/-/stripe-js-1.11.0.tgz#00e812d72a7760dae08237875066d263671478ee" - integrity sha512-SDNZKuETBEVkernd1tq8tL6wNfVKrl24Txs3p+4NYxoaIbNaEO7mrln/2Y/WRcQBWjagvhDIM5I6+X1rfK0qhQ== +"@stripe/stripe-js@^1.13.2": + version "1.13.2" + resolved "https://registry.yarnpkg.com/@stripe/stripe-js/-/stripe-js-1.13.2.tgz#bb2f561085b5dd091355df871d432b8e1fd467f6" + integrity sha512-fycUk7ECukNc31lD5apcrUgdRC1BfiIacs+CpacoCjOgo3ablolnWCvDQWMmVWtODYa8bBv2dlBla+Edc5OvZg== "@types/angular@^1.6.39": version "1.7.3" @@ -1191,21 +1191,27 @@ resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.4.tgz#15925414e0ad2cd765bfef58842f7e26a7accb24" integrity sha512-1HcDas8SEj4z1Wc696tH56G8OlRaH/sqZOynNNB+HF0WOeXPaxTtbYzJY2oEfiUxjSKjhCKr+MvR7dCHcEelug== -"@types/react-dom@^16.9.8": - version "16.9.8" - resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-16.9.8.tgz#fe4c1e11dfc67155733dfa6aa65108b4971cb423" - integrity sha512-ykkPQ+5nFknnlU6lDd947WbQ6TE3NNzbQAkInC2EKY1qeYdTKp7onFusmYZb+ityzx2YviqT6BXSu+LyWWJwcA== +"@types/react-dom@^17.0.3": + version "17.0.3" + resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-17.0.3.tgz#7fdf37b8af9d6d40127137865bb3fff8871d7ee1" + integrity sha512-4NnJbCeWE+8YBzupn/YrJxZ8VnjcJq5iR1laqQ1vkpQgBiA7bwk0Rp24fxsdNinzJY2U+HHS4dJJDPdoMjdJ7w== dependencies: "@types/react" "*" -"@types/react@*", "@types/react@^16.9.53": - version "16.9.53" - resolved "https://registry.yarnpkg.com/@types/react/-/react-16.9.53.tgz#40cd4f8b8d6b9528aedd1fff8fcffe7a112a3d23" - integrity sha512-4nW60Sd4L7+WMXH1D6jCdVftuW7j4Za6zdp6tJ33Rqv0nk1ZAmQKML9ZLD4H0dehA3FZxXR/GM8gXplf82oNGw== +"@types/react@*", "@types/react@^17.0.3": + version "17.0.3" + resolved "https://registry.yarnpkg.com/@types/react/-/react-17.0.3.tgz#ba6e215368501ac3826951eef2904574c262cc79" + integrity sha512-wYOUxIgs2HZZ0ACNiIayItyluADNbONl7kt8lkLjVK8IitMH5QMyAh75Fwhmo37r1m7L2JaFj03sIfxBVDvRAg== dependencies: "@types/prop-types" "*" + "@types/scheduler" "*" csstype "^3.0.2" +"@types/scheduler@*": + version "0.16.1" + resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.1.tgz#18845205e86ff0038517aab7a18a62a6b9f71275" + integrity sha512-EaCxbanVeyxDRTQBkdLb3Bvl/HK7PBK6UJjsSixB0iHKoWxE5uu2Q/DgtpOhPIojN0Zl1whvOd7PoHs2P0s5eA== + "@uirouter/angularjs@0.4": version "0.4.3" resolved "https://registry.yarnpkg.com/@uirouter/angularjs/-/angularjs-0.4.3.tgz#7e2630c59b2bd69ca485ff124f53b0169edddf39" @@ -3071,9 +3077,9 @@ csso@^4.0.2: css-tree "^1.1.2" csstype@^3.0.2: - version "3.0.4" - resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.0.4.tgz#b156d7be03b84ff425c9a0a4b1e5f4da9c5ca888" - integrity sha512-xc8DUsCLmjvCfoD7LTGE0ou2MIWLx0K9RCZwSHMOdynqRsP4MtUcLeqh1HcQ2dInwDTqn+3CE0/FZh1et+p4jA== + version "3.0.7" + resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.0.7.tgz#2a5fb75e1015e84dd15692f71e89a1450290950b" + integrity sha512-KxnUB0ZMlnUWCsx2Z8MUsr6qV6ja1w9ArPErJaJaF8a5SOWoHLIszeCTKGRGRgtLgYrs1E8CHkNSP1VZTTPc9g== currently-unhandled@^0.4.1: version "0.4.1" @@ -7575,7 +7581,7 @@ promise-inflight@^1.0.1: resolved "https://registry.yarnpkg.com/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3" integrity sha1-mEcocL8igTL8vdhoEputEsPAKeM= -prop-types@^15.5.10, prop-types@^15.6.2, prop-types@^15.7.2: +prop-types@^15.5.10, prop-types@^15.7.2: version "15.7.2" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5" integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ== @@ -7735,14 +7741,14 @@ raw-body@2.4.0: iconv-lite "0.4.24" unpipe "1.0.0" -react-dom@^17.0.0: - version "17.0.0" - resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-17.0.0.tgz#f8266e4d9861584553ccbd186d596a1c7dd8dcb4" - integrity sha512-OGnFbxCjI2TMAZYMVxi4hqheJiN8rCEVVrL7XIGzCB6beNc4Am8M47HtkvxODZw9QgjmAPKpLba9FTu4fC1byA== +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== dependencies: loose-envify "^1.1.0" object-assign "^4.1.1" - scheduler "^0.20.0" + scheduler "^0.20.2" react-i18next@^11.7.3: version "11.7.3" @@ -7777,12 +7783,12 @@ react-refresh@^0.9.0: resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.9.0.tgz#71863337adc3e5c2f8a6bfddd12ae3bfe32aafbf" integrity sha512-Gvzk7OZpiqKSkxsQvO/mbTN1poglhmAV7gR/DdIrRrSMXraRQQlfikRJOr3Nb9GTMPC5kof948Zy6jJZIFtDvQ== -react-switch@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/react-switch/-/react-switch-5.0.1.tgz#449277f4c3aed5286fffd0f50d5cbc2a23330406" - integrity sha512-Pa5kvqRfX85QUCK1Jv0rxyeElbC3aNpCP5hV0LoJpU/Y6kydf0t4kRriQ6ZYA4kxWwAYk/cH51T4/sPzV9mCgQ== +react-switch@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/react-switch/-/react-switch-6.0.0.tgz#bd4a2dea08f211b8a32e55e8314fd44bc1ec947e" + integrity sha512-QV3/6eRK5/5epdQzIqvDAHRoGLbCv/wDpHUi6yBMXY1Xco5XGuIZxvB49PHoV1v/SpEgOCJLD/Zo43iic+aEIw== dependencies: - prop-types "^15.6.2" + prop-types "^15.7.2" react2angular@^4.0.6: version "4.0.6" @@ -7794,10 +7800,10 @@ react2angular@^4.0.6: lodash.frompairs "^4.0.1" ngcomponent "^4.1.0" -react@^17.0.0: - version "17.0.0" - resolved "https://registry.yarnpkg.com/react/-/react-17.0.0.tgz#ad96d5fa1a33bb9b06d0cc52672f7992d84aa662" - integrity sha512-rG9bqS3LMuetoSUKHN8G3fMNuQOePKDThK6+2yXFWtoeTDLVNh/QCaxT+Jr+rNf4lwNXpx+atdn3Aa0oi8/6eQ== +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== dependencies: loose-envify "^1.1.0" object-assign "^4.1.1" @@ -8249,10 +8255,10 @@ sax@~1.2.4: resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== -scheduler@^0.20.0: - version "0.20.0" - resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.20.0.tgz#3ff543696b169613afadb09d3fb3fe998d234dd2" - integrity sha512-XegIgta1bIaz2LdaL6eg1GEcE42g0BY9qFXCqlZ/+s2MuEKfigFCW6DEGBlZzeVFlwDmVusrWEyFtBo4sbkkdA== +scheduler@^0.20.2: + version "0.20.2" + resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.20.2.tgz#4baee39436e34aa93b4874bddcbf0fe8b8b50e91" + integrity sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ== dependencies: loose-envify "^1.1.0" object-assign "^4.1.1"