diff --git a/.env b/.env index ccc70bc57..a8a92bd2e 100644 --- a/.env +++ b/.env @@ -2,7 +2,7 @@ REACT_APP_UI_VERSION=$npm_package_version REACT_APP_UI_NAME=subscriptions REACT_APP_UI_DISPLAY_NAME=Subscription Watch REACT_APP_UI_DISPLAY_CONFIG_NAME=Subscription Watch -REACT_APP_UI_DISPLAY_START_NAME=Subscription watch +REACT_APP_UI_DISPLAY_START_NAME=Subscription Watch REACT_APP_UI_DEPLOY_PATH_PREFIX=${UI_DEPLOY_PATH_PREFIX} PUBLIC_URL=${UI_DEPLOY_PATH_PREFIX}/apps/subscriptions/ @@ -27,3 +27,4 @@ REACT_APP_INCLUDE_CONTENT_BODY= Updating elements with these classes should be done with the knowledge "you are affecting an external resource in a potentially unanticipated way". -1. Prefix `uiux-` +1. Prefix `uxui-` - CSS classes with the prefix `uiux-` are used by external resources to identify elements for use in 3rd party tooling. Changes to the class name or element should be broadcast towards our UI/UX team members. + CSS classes with the prefix `uxui-` are used by external resources to identify elements for use in 3rd party tooling. Changes to the class name or element should be broadcast towards our UI/UX team members. ### Reserved QE testing attributes This project makes use of reserved DOM attributes used by the QE team. @@ -140,24 +140,33 @@ The name of the window value can be found under the dotenv file `.env` REACT_APP_UI_LOGGER_ID=curiosity ``` -#### Debugging the Graph Display -You can apply a date override during local development by adding a `.env.local` (dotenv) file with the following line, in the repository root directory +#### Debugging local development +You can apply overrides during local development by adding a `.env.local` (dotenv) file in the repository root directory. + +Once you have made the dotenv file and/or changes, like the below "debug" flags, restart the project and the flags should be active. + +*Any changes you make to the `.env.local` file should be ignored with `.gitignore`.* + +##### Graph display +You can apply a date override during **local development** (using `$ yarn start`) by adding the following line to your `.env.local` file. ``` REACT_APP_DEBUG_DEFAULT_DATETIME=20190630 ``` -*Any changes you make to the `.env.local` file should be ignored with `.gitignore`.* +##### Admin role +You can access the administrator role experience during **local development** (using `$ yarn start`) by adding the following line to your `.env.local` file. + ``` + REACT_APP_DEBUG_ORG_ADMIN=true + ``` + +Combining this flag with [manipulating the http status on the API/service mocks](https://github.com/cdcabrera/apidoc-mock#more-examples-and-custom-responses) can be an effective emulation. -#### Debugging Redux -This project makes use of React & Redux. To enable Redux console logging, within the repository root directory, add a `.env.local` (dotenv) file with the follow line +##### Debugging Redux +This project makes use of React & Redux. To enable Redux browser console logging add the following line to your `.env.local` file. ``` REACT_APP_DEBUG_MIDDLEWARE=true ``` -Once you've made the change, restart the project and console browser logging should appear. - -*Any changes you make to the `.env.local` file should be ignored with `.gitignore`.* - #### Unit Testing To run the unit tests with a watch during development you'll need to open an additional terminal instance, then run ``` diff --git a/package.json b/package.json index 99122b285..ddce619ef 100644 --- a/package.json +++ b/package.json @@ -76,33 +76,33 @@ "test:local": "react-scripts test --env=jsdom --roots=./src" }, "dependencies": { - "@patternfly/patternfly": "2.65.3", - "@patternfly/react-charts": "5.3.5", - "@patternfly/react-core": "3.140.11", - "@patternfly/react-icons": "3.15.3", - "@patternfly/react-styles": "3.7.4", - "@patternfly/react-tokens": "2.8.4", - "@redhat-cloud-services/frontend-components": "1.0.8", - "@redhat-cloud-services/frontend-components-notifications": "1.0.1", + "@patternfly/patternfly": "2.71.3", + "@patternfly/react-charts": "5.3.18", + "@patternfly/react-core": "3.153.3", + "@patternfly/react-icons": "3.15.15", + "@patternfly/react-styles": "3.7.12", + "@patternfly/react-tokens": "2.8.12", + "@redhat-cloud-services/frontend-components": "1.0.12", + "@redhat-cloud-services/frontend-components-notifications": "1.0.2", "@redhat-cloud-services/frontend-components-utilities": "1.0.0", "axios": "^0.19.2", "classnames": "^2.2.6", - "i18next": "^19.3.2", + "i18next": "^19.3.4", "i18next-xhr-backend": "^3.2.2", "js-cookie": "^2.2.1", "locale-code": "^2.0.2", "lodash": "^4.17.15", "moment": "^2.24.0", "node-sass": "^4.13.1", - "numbro": "^2.1.2", + "numbro": "^2.2.0", "prop-types": "^15.7.2", - "react": "^16.13.0", - "react-dom": "^16.13.0", - "react-i18next": "^11.3.3", + "react": "^16.13.1", + "react-dom": "^16.13.1", + "react-i18next": "^11.3.4", "react-redux": "^7.2.0", "react-router": "^5.1.2", "react-router-dom": "^5.1.2", - "react-scripts": "3.4.0", + "react-scripts": "3.4.1", "redux": "^4.0.5", "redux-logger": "^3.0.6", "redux-promise-middleware": "^6.1.2", @@ -118,15 +118,15 @@ "enzyme-adapter-react-16": "^1.15.2", "enzyme-to-json": "^3.4.4", "eslint-config-airbnb": "^18.1.0", - "eslint-config-prettier": "^6.10.0", - "eslint-plugin-import": "^2.20.1", + "eslint-config-prettier": "^6.10.1", + "eslint-plugin-import": "^2.20.2", "eslint-plugin-jest": "^23.8.2", - "eslint-plugin-jsdoc": "^22.0.1", + "eslint-plugin-jsdoc": "^22.1.0", "eslint-plugin-json": "^2.1.1", "eslint-plugin-jsx-a11y": "^6.2.3", "eslint-plugin-prettier": "^3.1.2", "eslint-plugin-react": "^7.19.0", - "eslint-plugin-react-hooks": "^2.5.0", + "eslint-plugin-react-hooks": "^3.0.0", "express": "^4.17.1", "gettext-extractor": "^3.5.2", "moxios": "^0.4.0", @@ -134,7 +134,7 @@ "prettier": "^1.19.1", "redux-mock-store": "^1.5.4", "standard-version": "^7.1.0", - "swagger-ui-express": "^4.1.3", + "swagger-ui-express": "^4.1.4", "yamljs": "^0.3.0" }, "resolutions": { diff --git a/public/locales/en-US.json b/public/locales/en-US.json index 81dad17b0..b3f8c43e4 100644 --- a/public/locales/en-US.json +++ b/public/locales/en-US.json @@ -1,8 +1,8 @@ { "curiosity-auth": { "pending": "Authenticating...", - "authorizedTitle": "Unauthorized", - "authorizedCopy": "You do not have permission to access reporting. Contact your administrator." + "authorizedTitle": "You do not have access to {{appName}}.", + "authorizedCopy": "Contact your organization administrator(s) for more information." }, "curiosity-graph": { "cardHeading": "CPU usage", @@ -32,6 +32,29 @@ "slaSelfSupport": "Self-Support", "slaStandard": "Standard" }, + "curiosity-optin": { + "buttonActivate": "Activate {{appName}}", + "buttonIsActive": "{{appName}} active", + "buttonTour": "Take a tour", + "cardTitle": "Welcome to {{appName}}", + "cardDescription": "{{appName}} enables you to understand your total subscription usage and capacity across your hybrid infrastructure over time.", + "cardSeeTitle": "Know your account-wide usage at a glance", + "cardSeeDescription": "See unified reporting of subscription usage information across your physical, virtual, on-premise, and cloud infrastructure.", + "cardReportTitle": "Prepare for capacity events", + "cardReportDescription": "Enhance your ability to consume, track, report, and reconcile your Red Hat subscriptions.", + "cardFilterTitle": "Isolate specific usage", + "cardFilterDescription": "View your inventory by critical indicators like Service Level Agreement (SLA) and architecture.", + "cardIsActiveDescription": "Data can take up to 24 hours to be processed and will appear on this page when ready", + "cardIsErrorDescription": "An opt-in error has occurred. <0>Contact us for more information", + "cardContactAdminDescription": "You must be an organization administrator with the org-admin role to view {{appName}}.", + "notificationsErrorTitle": "{{appName}} opt-in failed", + "notificationsErrorDescription": "Contact us for more information", + "notificationsSuccessTitle": "{{appName}} activated", + "notificationsSuccessDescription": "It could take up to 24 hours for data to appear", + "tourTitle": "Ready to get started?", + "tourTitleImageAlt": "Ready to get started example graph.", + "tourDescription": "We'll walk you through each step and help you understand how Red Hat collects and uses subscription data." + }, "curiosity-tour": { "emptyStateIconAlt": "{{appName}} logo", "emptyStateTitle": "{{appName}} is an early access beta", @@ -41,5 +64,9 @@ "emptyStateButton": "Take a tour", "emptyStateLinkLearnMore": "Learn more", "emptyStateLinkContactUs": "Contact us" + }, + "curiosity-view": { + "openshift": "Red Hat OpenShift", + "rhel": "Red Hat Enterprise Linux" } } diff --git a/src/common/__tests__/__snapshots__/helpers.test.js.snap b/src/common/__tests__/__snapshots__/helpers.test.js.snap index 08707e631..d2275f9b8 100644 --- a/src/common/__tests__/__snapshots__/helpers.test.js.snap +++ b/src/common/__tests__/__snapshots__/helpers.test.js.snap @@ -13,7 +13,7 @@ Object { "UI_DISABLED_TOOLBAR": false, "UI_DISPLAY_CONFIG_NAME": "Subscription Watch", "UI_DISPLAY_NAME": "Subscription Watch", - "UI_DISPLAY_START_NAME": "Subscription watch", + "UI_DISPLAY_START_NAME": "Subscription Watch", "UI_LOGGER_ID": "curiosity", "UI_NAME": "subscriptions", "UI_PATH": "/", diff --git a/src/common/helpers.js b/src/common/helpers.js index d6166b110..9c4c2c75d 100644 --- a/src/common/helpers.js +++ b/src/common/helpers.js @@ -35,10 +35,12 @@ const noopPromise = Promise.resolve({}); * Associated with the i18n package, and typically used as a default prop. * * @param {string} key - * @param {string} value + * @param {string|object} value + * @param {Array} components * @returns {string} */ -const noopTranslate = (key, value) => `t(${key}${(value && `, ${value}`) || ''})`; +const noopTranslate = (key, value, components) => + `t(${key}${(value && `, ${value}`) || ''}${(components && `, ${components}`) || ''})`; /** * Is dev mode active. diff --git a/src/components/authentication/__tests__/__snapshots__/authentication.test.js.snap b/src/components/authentication/__tests__/__snapshots__/authentication.test.js.snap index 7c4d67796..802fbddf7 100644 --- a/src/components/authentication/__tests__/__snapshots__/authentication.test.js.snap +++ b/src/components/authentication/__tests__/__snapshots__/authentication.test.js.snap @@ -16,56 +16,10 @@ exports[`Authorization Component should render a non-connected component authori } } initializeChrome={[Function]} - navigation={ - Array [ - Object { - "default": true, - "id": "all", - "path": "/rhel-sw/all", - "pathId": "rhel-sw", - "pathParameter": "RHEL", - "title": "Red Hat Enterprise Linux", - }, - Object { - "id": "arm", - "path": "/rhel-sw/arm", - "pathId": "rhel-sw", - "pathParameter": "RHEL for ARM", - "title": "ARM", - }, - Object { - "id": "ibmpower", - "path": "/rhel-sw/ibmpower", - "pathId": "rhel-sw", - "pathParameter": "RHEL for IBM Power", - "title": "IBM Power", - }, - Object { - "id": "ibmz", - "path": "/rhel-sw/ibmz", - "pathId": "rhel-sw", - "pathParameter": "RHEL for IBM z", - "title": "IBM Z systems", - }, - Object { - "id": "x86", - "path": "/rhel-sw/x86", - "pathId": "rhel-sw", - "pathParameter": "RHEL for x86", - "title": "x86", - }, - Object { - "id": "openshift-sw", - "path": "/openshift-sw", - "pathId": "openshift-sw", - "pathParameter": "OpenShift Container Platform", - "title": "Red Hat OpenShift", - }, - ] - } onNavigation={[Function]} session={ Object { + "admin": true, "authorized": true, "error": false, "errorMessage": "", @@ -73,7 +27,6 @@ exports[`Authorization Component should render a non-connected component authori } } setAppName={[Function]} - setNavigation={[Function]} t={[Function]} > `; -exports[`Authorization Component should render a non-connected component error: non-connected error 1`] = ` +exports[`Authorization Component should render a non-connected component error: non-connected admin error 1`] = ` - t(curiosity-auth.authorizedTitle, ...) + Subscription Watch </h1> @@ -203,10 +110,20 @@ exports[`Authorization Component should render a non-connected component error:
+ + <h2 + className="pf-c-title pf-m-lg" + > + t(curiosity-auth.authorizedTitle, [object Object]) + </h2> + - +
`; +exports[`Authorization Component should render a non-connected component error: non-connected error 1`] = ` + + redirect + +`; + exports[`Authorization Component should render a non-connected component pending: non-connected pending 1`] = ` `; @@ -271,7 +216,7 @@ exports[`Authorization Component should return a message on 401 error: 401 error widget-type="InsightsPageHeader" > - t(curiosity-auth.authorizedTitle, ...) + Subscription Watch </h1> @@ -305,10 +250,20 @@ exports[`Authorization Component should return a message on 401 error: 401 error
+ + <h2 + className="pf-c-title pf-m-lg" + > + t(curiosity-auth.authorizedTitle, [object Object]) + </h2> + - +
{ it('should render a connected component', () => { const store = generateEmptyStore({ - user: { session: { authorized: false, error: false, errorMessage: '', pending: false } } + user: { session: { admin: false, authorized: false, error: false, errorMessage: '', pending: false } } }); const component = shallow( @@ -30,6 +30,7 @@ describe('Authorization Component', () => { push: helpers.noop }, session: { + admin: false, authorized: false, error: true, errorMessage: 'Authentication credentials were not provided.', @@ -43,6 +44,18 @@ describe('Authorization Component', () => { ); expect(component).toMatchSnapshot('non-connected error'); + + component.setProps({ + session: { + admin: true, + authorized: false, + error: true, + errorMessage: 'Authentication credentials were not provided.', + pending: false + } + }); + + expect(component).toMatchSnapshot('non-connected admin error'); }); it('should return a redirect on 418 error', () => { @@ -52,6 +65,7 @@ describe('Authorization Component', () => { push: helpers.noop }, session: { + admin: false, authorized: false, error: true, errorStatus: 418, @@ -77,6 +91,7 @@ describe('Authorization Component', () => { push: helpers.noop }, session: { + admin: false, authorized: false, error: true, errorStatus: 403, @@ -102,6 +117,7 @@ describe('Authorization Component', () => { push: helpers.noop }, session: { + admin: true, authorized: false, error: true, errorStatus: 401, @@ -127,6 +143,7 @@ describe('Authorization Component', () => { push: helpers.noop }, session: { + admin: false, authorized: false, error: false, errorMessage: '', @@ -149,6 +166,7 @@ describe('Authorization Component', () => { push: helpers.noop }, session: { + admin: true, authorized: true, error: false, errorMessage: '', diff --git a/src/components/authentication/authentication.js b/src/components/authentication/authentication.js index 256e177f2..0858ee1e8 100644 --- a/src/components/authentication/authentication.js +++ b/src/components/authentication/authentication.js @@ -1,6 +1,6 @@ import React, { Component } from 'react'; import PropTypes from 'prop-types'; -import { BanIcon, BinocularsIcon } from '@patternfly/react-icons'; +import { BinocularsIcon, LockIcon } from '@patternfly/react-icons'; import { connectRouterTranslate, reduxActions } from '../../redux'; import { helpers } from '../../common'; import { Redirect, routerHelpers, routerTypes } from '../router/router'; @@ -17,16 +17,7 @@ class Authentication extends Component { removeListeners = helpers.noop; componentDidMount() { - const { - authorizeUser, - history, - initializeChrome, - onNavigation, - navigation, - setAppName, - setNavigation, - session - } = this.props; + const { authorizeUser, history, initializeChrome, onNavigation, setAppName, session } = this.props; if (helpers.PROD_MODE || helpers.REVIEW_MODE) { initializeChrome(); @@ -36,11 +27,9 @@ class Authentication extends Component { const { path } = routerHelpers.getNavRouteDetail({ id: event.navId, returnDefault: true }); history.push(path); }); - const buildNav = history.listen(() => setNavigation(navigation)); this.removeListeners = () => { appNav(); - buildNav(); }; } @@ -61,15 +50,15 @@ class Authentication extends Component { render() { const { children, session, t } = this.props; - if (session.authorized) { + if (session.authorized && session.admin) { return {children}; } if (session.pending) { - return ; + return ; } - if (session.errorStatus === 403 || session.errorStatus === 418) { + if (!session.admin || session.errorStatus === 403 || session.errorStatus === 418) { if (helpers.TEST_MODE) { return {session.errorStatus} redirect; } @@ -78,9 +67,9 @@ class Authentication extends Component { return ( ); } @@ -103,13 +92,8 @@ Authentication.propTypes = { initializeChrome: PropTypes.func, onNavigation: PropTypes.func, setAppName: PropTypes.func, - setNavigation: PropTypes.func, - navigation: PropTypes.arrayOf( - PropTypes.shape({ - id: PropTypes.string - }) - ), session: PropTypes.shape({ + admin: PropTypes.bool, authorized: PropTypes.bool, error: PropTypes.bool, errorMessage: PropTypes.string, @@ -131,9 +115,8 @@ Authentication.defaultProps = { initializeChrome: helpers.noop, onNavigation: helpers.noop, setAppName: helpers.noop, - setNavigation: helpers.noop, - navigation: routerTypes.navigation, session: { + admin: false, authorized: false, error: false, errorMessage: '', @@ -153,8 +136,7 @@ const mapDispatchToProps = dispatch => ({ authorizeUser: () => dispatch(reduxActions.user.authorizeUser()), initializeChrome: () => dispatch(reduxActions.platform.initializeChrome()), onNavigation: callback => dispatch(reduxActions.platform.onNavigation(callback)), - setAppName: name => dispatch(reduxActions.platform.setAppName(name)), - setNavigation: data => dispatch(reduxActions.platform.setNavigation(data)) + setAppName: name => dispatch(reduxActions.platform.setAppName(name)) }); /** diff --git a/src/components/form/__tests__/__snapshots__/checkbox.test.js.snap b/src/components/form/__tests__/__snapshots__/checkbox.test.js.snap new file mode 100644 index 000000000..1b77fa8db --- /dev/null +++ b/src/components/form/__tests__/__snapshots__/checkbox.test.js.snap @@ -0,0 +1,118 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Checkbox Component should handle children as a label: children label checkbox 1`] = ` +
+ + +
+`; + +exports[`Checkbox Component should handle readOnly as isDisabled: active checkbox 1`] = ` +
+ +
+`; + +exports[`Checkbox Component should handle readOnly as isDisabled: isDisabled checkbox 1`] = ` +
+ +
+`; + +exports[`Checkbox Component should handle readOnly as isDisabled: readOnly checkbox 1`] = ` +
+ +
+`; + +exports[`Checkbox Component should render a basic component: basic checkbox 1`] = ` +
+ +
+`; + +exports[`Checkbox Component should return an emulated onchange event: emulated event 1`] = ` +Object { + "checked": false, + "currentTarget": , + "id": "generatedid-", + "name": "generatedid-", + "persist": [Function], + "target": , + "value": undefined, +} +`; diff --git a/src/components/form/__tests__/__snapshots__/formState.test.js.snap b/src/components/form/__tests__/__snapshots__/formState.test.js.snap new file mode 100644 index 000000000..9a87398f6 --- /dev/null +++ b/src/components/form/__tests__/__snapshots__/formState.test.js.snap @@ -0,0 +1,139 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`FormState Component should clone returned values to avoid mutation by consumer: not mutated 1`] = ` +Object { + "lorem": "ipsum", +} +`; + +exports[`FormState Component should do a basic validation check: basic validation 1`] = ` +Object { + "lorem": "required", +} +`; + +exports[`FormState Component should do a basic validation check: initial errors 1`] = `Object {}`; + +exports[`FormState Component should do a validation check on mount: errors on mount 1`] = ` +Object { + "lorem": "required test", +} +`; + +exports[`FormState Component should handle basic checked values: checked input types 1`] = ` +
+ + +
+`; + +exports[`FormState Component should handle custom events: multiple custom events 1`] = ` +Object { + "dolor": "sit", + "lorem": "woot again", +} +`; + +exports[`FormState Component should handle custom events: single custom event 1`] = ` +Object { + "dolor": "", + "lorem": "woot", +} +`; + +exports[`FormState Component should render a basic component: basic render 1`] = ` +
+ +
+`; + +exports[`FormState Component should render a basic component: initial props 1`] = ` +Object { + "children": [Function], + "onReset": [Function], + "onSubmit": [Function], + "resetUsingSetValues": true, + "setValues": Object { + "lorem": "ipsum", + }, + "setValuesAssumeBoolIsChecked": true, + "setValuesOnUpdate": false, + "validate": [Function], + "validateOnMount": false, + "validateOnUpdate": false, +} +`; + +exports[`FormState Component should render a basic component: initial state 1`] = ` +Object { + "isSubmitting": false, + "isUpdating": false, + "isValid": null, + "isValidating": false, + "submitCount": 0, +} +`; + +exports[`FormState Component should update handle reset, changes, and submit events while updating state: onevent 1`] = ` +Object { + "isSubmitting": false, + "isUpdating": false, + "isValid": true, + "isValidating": false, + "submitCount": 0, +} +`; + +exports[`FormState Component should update handle reset, changes, and submit events while updating state: onevent values updated 1`] = ` +Object { + "lorem": "dolor", +} +`; + +exports[`FormState Component should update handle reset, changes, and submit events while updating state: onreset 1`] = ` +Object { + "isSubmitting": false, + "isUpdating": false, + "isValid": null, + "isValidating": false, + "submitCount": 0, +} +`; + +exports[`FormState Component should update handle reset, changes, and submit events while updating state: onsubmit 1`] = ` +Object { + "isSubmitting": false, + "isUpdating": false, + "isValid": true, + "isValidating": false, + "submitCount": 1, +} +`; + +exports[`FormState Component should update handle reset, changes, and submit events while updating state: reset values updated 1`] = ` +Object { + "lorem": "ipsum", +} +`; diff --git a/src/components/select/__tests__/__snapshots__/select.test.js.snap b/src/components/form/__tests__/__snapshots__/select.test.js.snap similarity index 100% rename from src/components/select/__tests__/__snapshots__/select.test.js.snap rename to src/components/form/__tests__/__snapshots__/select.test.js.snap diff --git a/src/components/form/__tests__/checkbox.test.js b/src/components/form/__tests__/checkbox.test.js new file mode 100644 index 000000000..9b9f04ede --- /dev/null +++ b/src/components/form/__tests__/checkbox.test.js @@ -0,0 +1,53 @@ +import React from 'react'; +import { mount } from 'enzyme'; +import Checkbox from '../checkbox'; + +describe('Checkbox Component', () => { + it('should render a basic component', () => { + const props = {}; + + const component = mount(); + expect(component.render()).toMatchSnapshot('basic checkbox'); + }); + + it('should handle readOnly as isDisabled', () => { + const props = { + readOnly: true + }; + + const component = mount(); + expect(component.render()).toMatchSnapshot('readOnly checkbox'); + + component.setProps({ + readOnly: false, + isDisabled: true + }); + + expect(component.render()).toMatchSnapshot('isDisabled checkbox'); + + component.setProps({ + readOnly: false, + isDisabled: false + }); + + expect(component.render()).toMatchSnapshot('active checkbox'); + }); + + it('should handle children as a label', () => { + const props = {}; + const component = mount(lorem ipsum); + expect(component.render()).toMatchSnapshot('children label checkbox'); + }); + + it('should return an emulated onchange event', done => { + const props = {}; + + props.onChange = event => { + expect(event).toMatchSnapshot('emulated event'); + done(); + }; + + const component = mount(lorem ipsum); + component.find('input').simulate('change'); + }); +}); diff --git a/src/components/form/__tests__/formState.test.js b/src/components/form/__tests__/formState.test.js new file mode 100644 index 000000000..91563f4a0 --- /dev/null +++ b/src/components/form/__tests__/formState.test.js @@ -0,0 +1,231 @@ +import React from 'react'; +import { mount } from 'enzyme'; +import { FormState } from '../formState'; + +describe('FormState Component', () => { + it('should render a basic component', () => { + const props = { setValues: { lorem: 'ipsum' } }; + + const component = mount( + + {({ values }) => ( +
+ +
+ )} +
+ ); + + const componentInstance = component.instance(); + expect(componentInstance.props).toMatchSnapshot('initial props'); + expect(componentInstance.state).toMatchSnapshot('initial state'); + + expect(component.render()).toMatchSnapshot('basic render'); + }); + + it('should update handle reset, changes, and submit events while updating state', () => { + const props = { setValues: { lorem: 'ipsum' }, resetUsingSetValues: true, validate: () => ({}) }; + + const component = mount( + + {({ values, handleOnEvent, handleOnReset, handleOnSubmit }) => ( +
+ + +
+ )} +
+ ); + + const componentInstance = component.instance(); + + componentInstance.onEvent({ + target: { value: 'dolor', name: 'lorem' }, + persist: () => {}, + preventDefault: () => {} + }); + expect(component.state()).toMatchSnapshot('onevent'); + expect(componentInstance.values).toMatchSnapshot('onevent values updated'); + + componentInstance.onReset({ persist: () => {} }); + expect(component.state()).toMatchSnapshot('onreset'); + expect(componentInstance.values).toMatchSnapshot('reset values updated'); + + componentInstance.onSubmit({ persist: () => {}, preventDefault: () => {} }); + expect(component.state()).toMatchSnapshot('onsubmit'); + }); + + it('should do a basic validation check', () => { + const props = { + setValues: { + lorem: 'ipsum' + }, + validate: ({ values }) => { + const updatedErrors = {}; + + if (!values.lorem) { + updatedErrors.lorem = 'required'; + } + + return updatedErrors; + } + }; + + const component = mount( + + {({ errors, values, handleOnEvent }) => ( +
+ +
+ )} +
+ ); + + const componentInstance = component.instance(); + expect(componentInstance.errors).toMatchSnapshot('initial errors'); + + const mockEvent = { target: { value: '', id: 'lorem' }, persist: () => {}, preventDefault: () => {} }; + componentInstance.onEvent(mockEvent); + expect(componentInstance.errors).toMatchSnapshot('basic validation'); + }); + + it('should do a validation check on mount', () => { + const props = { + setValues: { + lorem: '' + }, + validateOnMount: true, + validate: ({ values }) => { + const updatedErrors = {}; + + if (!values.lorem) { + updatedErrors.lorem = 'required test'; + } + + return updatedErrors; + } + }; + + const component = mount( + + {({ errors, values, handleOnEvent }) => ( +
+ +
+ )} +
+ ); + + const componentInstance = component.instance(); + expect(componentInstance.errors).toMatchSnapshot('errors on mount'); + }); + + it('should handle custom events', () => { + const props = { + setValues: { + lorem: 'ipsum', + dolor: '' + }, + validate: ({ values }) => { + const updatedErrors = {}; + + if (!values.lorem) { + updatedErrors.lorem = 'required'; + } + + return updatedErrors; + } + }; + + const component = mount( + + {({ errors, values, handleOnEventCustom }) => ( +
+ +
+ )} +
+ ); + + const componentInstance = component.instance(); + componentInstance.onEventCustom({ name: 'lorem', value: 'woot' }); + expect(componentInstance.values).toMatchSnapshot('single custom event'); + + componentInstance.onEventCustom([ + { name: 'lorem', value: 'woot again' }, + { name: 'dolor', value: 'sit' } + ]); + expect(componentInstance.values).toMatchSnapshot('multiple custom events'); + }); + + it('should clone returned values to avoid mutation by consumer', () => { + const props = { + setValues: { + lorem: 'ipsum' + }, + validate: ({ values }) => { + const updatedErrors = {}; + + // eslint-disable-next-line + values.lorem = 'mutated test'; + + return updatedErrors; + } + }; + + const component = mount( + + {({ values }) =>
Lorem = {values.lorem}
} +
+ ); + + expect(component.instance().values).toMatchSnapshot('not mutated'); + }); + + it('should handle basic checked values', () => { + const props = { + setValuesOnUpdate: true, + setValues: { + ipsum: true, + dolor: true + } + }; + + const component = mount( + + {({ checked, handleOnEvent }) => ( +
+ + +
+ )} +
+ ); + + expect(component.render()).toMatchSnapshot('checked input types'); + }); +}); diff --git a/src/components/select/__tests__/select.test.js b/src/components/form/__tests__/select.test.js similarity index 100% rename from src/components/select/__tests__/select.test.js rename to src/components/form/__tests__/select.test.js diff --git a/src/components/form/checkbox.js b/src/components/form/checkbox.js new file mode 100644 index 000000000..6ef32878b --- /dev/null +++ b/src/components/form/checkbox.js @@ -0,0 +1,81 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { Checkbox as PfCheckbox } from '@patternfly/react-core/dist/js/components/Checkbox'; +import { helpers } from '../../common'; + +/** + * Render a checkbox form element. + * + * @returns {Node} + */ +const Checkbox = ({ ariaLabel, checked, children, isDisabled, label, name, onChange, readOnly, value, ...props }) => { + const nameId = name || helpers.generateId(); + + const onCheckboxChange = (isChecked, event) => { + const { currentTarget, target } = event; + const mockEvent = { + id: nameId, + name: nameId, + value, + checked: isChecked, + target, + currentTarget, + persist: helpers.noop + }; + onChange(mockEvent); + }; + + return ( + + ); +}; + +/** + * Prop types. + * + * @type {{onChange: Function, children: Node, name: string, checked: boolean, readOnly: boolean, + * label: string, value: *, ariaLabel: string}} + */ +Checkbox.propTypes = { + ariaLabel: PropTypes.string, + checked: PropTypes.any, + children: PropTypes.node, + isDisabled: PropTypes.bool, + label: PropTypes.node, + name: PropTypes.string, + onChange: PropTypes.func, + readOnly: PropTypes.bool, + value: PropTypes.any +}; + +/** + * Default props. + * + * @type {{onChange: Function, children: null, name: null, checked: undefined, readOnly: undefined, + * label: string, value: undefined, ariaLabel: null}} + */ +Checkbox.defaultProps = { + ariaLabel: null, + checked: undefined, + children: null, + isDisabled: false, + label: '', + name: null, + onChange: helpers.noop, + readOnly: false, + value: undefined +}; + +export { Checkbox as default, Checkbox }; diff --git a/src/components/form/formState.js b/src/components/form/formState.js new file mode 100644 index 000000000..25ed6df03 --- /dev/null +++ b/src/components/form/formState.js @@ -0,0 +1,408 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import _cloneDeep from 'lodash/cloneDeep'; +import _isEqual from 'lodash/isEqual'; +import helpers from '../../common/helpers'; + +/** + * Initial component state values. + * + * @type {{submitCount: number, isValid: null, isUpdating: boolean, isSubmitting: boolean, isValidating: boolean}} + */ +const initialState = { + isUpdating: false, + isSubmitting: false, + isValid: null, + isValidating: false, + submitCount: 0 +}; + +/** + * Maintain a form's state/context. + * + * @augments React.Component + * @fires onEvent + * @fires onEventCustom + * @fires onReset + * @fires onSubmit + */ +class FormState extends React.Component { + /** + * Infer a field value is "checked" from a boolean value. + * + * @param {object} params + * @property {boolean} setValuesAssumeBoolIsChecked + * @property {object} setValues + * @returns {{}} + */ + static checkedSetValues({ setValuesAssumeBoolIsChecked, setValues }) { + const checked = {}; + + if (setValuesAssumeBoolIsChecked) { + Object.keys(setValues).forEach(key => { + if (typeof setValues[key] === 'boolean') { + checked[key] = setValues[key]; + } + }); + } + + return checked; + } + + /** + * Check if "is a promise". + * + * @param {*} obj + * @returns {boolean} + */ + static isPromise(obj) { + return Object.prototype.toString.call(obj) === '[object Promise]'; + } + + state = { + ...initialState + }; + + constructor(props) { + super(props); + + this.touched = {}; + this.checked = FormState.checkedSetValues(props); + + this.refValues = + props.resetUsingSetValues === true || props.setValuesOnUpdate === true ? _cloneDeep(props.setValues) : null; + + this.errors = {}; + this.values = _cloneDeep(props.setValues); + } + + componentDidMount() { + const { validateOnMount } = this.props; + + if (validateOnMount === true) { + this.validateOnMount(); + } + } + + componentDidUpdate() { + const { refValues } = this; + const { setValuesOnUpdate, setValues } = this.props; + + if (setValuesOnUpdate === true && !_isEqual(refValues, setValues)) { + this.updateComponentValues(); + } + } + + /** + * Apply form values with a custom event. + * + * @event onEventCustom + * @param {Array|object} custom + */ + onEventCustom = custom => { + const eventArray = (Array.isArray(custom) && custom) || (custom && [custom]); + + if (!eventArray.length) { + return; + } + + eventArray + .filter(event => 'name' in event && ('value' in event || 'checked' in event)) + .forEach(event => this.onEvent({ target: { ...event }, persist: helpers.noop, type: 'custom' })); + }; + + /** + * Generic "on event" for handling returned event objects. + * + * @event onEvent + * @param {object} event + */ + onEvent = event => { + const { touched, values } = this; + const { id, name, value, checked } = event.options ? { ...event } : event.target; + + event.persist(); + + const targetName = name || id || 'generated form state target, add name or id attr to field'; + + this.touched = { ...touched, [targetName]: true }; + this.values = { ...values, [targetName]: value }; + + if (checked !== undefined) { + this.checked = { ...this.checked, [targetName]: checked }; + } + + this.setState( + { + isUpdating: true, + isValidating: true + }, + () => + this.validate(event).then(updatedErrors => { + const setUpdateErrors = { ...((updatedErrors && updatedErrors[0]) || updatedErrors || {}) }; + const checkIsValid = !Object.values(setUpdateErrors).filter(val => val === true).length; + + this.errors = setUpdateErrors; + + this.setState({ + isUpdating: false, + isValid: checkIsValid, + isValidating: false + }); + }) + ); + }; + + /** + * Reset FormState's form state. Apply prop onReset function. + * + * @event onReset + * @param {object} event + */ + onReset = event => { + const { refValues, values } = this; + const { setValuesAssumeBoolIsChecked, onReset, resetUsingSetValues } = this.props; + + event.persist(); + + const isResetWithSetValues = refValues && resetUsingSetValues === true; + const updatedValues = (isResetWithSetValues && _cloneDeep(refValues)) || {}; + const updatedChecked = + (isResetWithSetValues && FormState.checkedSetValues(setValuesAssumeBoolIsChecked, updatedValues)) || {}; + + this.values = updatedValues; + this.checked = updatedChecked; + this.errors = {}; + this.touched = {}; + + this.setState({ + ...initialState + }); + + if (isResetWithSetValues) { + onReset({ event, ..._cloneDeep({ values: updatedValues, prevValues: values }) }); + } else { + // Resetting the values, potentially, will throw the controlled vs uncontrolled messaging. + onReset({ event, values: {}, ..._cloneDeep({ prevValues: values }) }); + } + }; + + /** + * Validate form, then submit. + * + * @event onSubmit + * @param {object} event + */ + onSubmit = event => { + const { submitCount } = this.state; + + event.persist(); + event.preventDefault(); + + this.setState( + { + submitCount: submitCount + 1, + isSubmitting: true, + isUpdating: true, + isValidating: true + }, + () => + this.validate(event).then(updatedErrors => { + const setUpdateErrors = { ...((updatedErrors && updatedErrors[0]) || updatedErrors || {}) }; + const checkIsValid = !Object.values(setUpdateErrors).filter(val => val === true).length; + + this.errors = setUpdateErrors; + this.touched = {}; + + this.setState( + { + isValid: checkIsValid, + isValidating: false + }, + () => + checkIsValid && + this.submit(event).then(() => { + this.setState({ + isSubmitting: false, + isUpdating: false + }); + }) + ); + }) + ); + }; + + /** + * Handle submitted form, check and return Promise, or emulate for consistency. + * + * @param {object} event + * @returns {Promise} + */ + submit(event = { type: 'submit' }) { + const { checked, errors, values, touched } = this; + const { onSubmit } = this.props; + + const checkPromise = onSubmit({ + event, + ..._cloneDeep({ ...this.state, checked, errors, values, touched }) + }); + + if (FormState.isPromise(checkPromise)) { + return checkPromise; + } + + return { + then: callback => callback() + }; + } + + /** + * Handle validated form data, check and return Promise, or emulate for consistency. + * + * @param {object} event + * @returns {Promise} + */ + validate(event = { type: 'validate' }) { + const { checked, errors, values, touched } = this; + const { validate } = this.props; + + const checkPromise = validate({ + event, + ..._cloneDeep({ ...this.state, checked, errors, values, touched }) + }); + + if (FormState.isPromise(checkPromise)) { + return checkPromise; + } + + return { + then: callback => callback(checkPromise) + }; + } + + /** + * Shortcut, activate validation on component mount. + * + * @param {object} event + */ + validateOnMount(event = { type: 'mount' }) { + this.validateOnUpdate(event); + } + + /** + * Validate on component update. + * + * @param {object} event + */ + validateOnUpdate(event = { type: 'update' }) { + this.setState( + { + isUpdating: true, + isValidating: true + }, + () => + this.validate(event).then(updatedErrors => { + const setUpdateErrors = { ...((updatedErrors && updatedErrors[0]) || updatedErrors || {}) }; + const checkIsValid = !Object.values(setUpdateErrors).filter(val => val === true).length; + + this.errors = setUpdateErrors; + + this.setState({ + isUpdating: false, + isValidating: false, + isValid: checkIsValid + }); + }) + ); + } + + /** + * On component update, update state. + */ + updateComponentValues() { + const { setValues, setValuesAssumeBoolIsChecked, validateOnUpdate } = this.props; + + this.setState( + { + isUpdating: true + }, + () => { + this.checked = FormState.checkedSetValues(setValuesAssumeBoolIsChecked, setValues); + this.refValues = _cloneDeep(setValues); + this.values = _cloneDeep(setValues); + + if (validateOnUpdate) { + this.validateOnUpdate(); + } else { + this.setState({ + isUpdating: false + }); + } + } + ); + } + + /** + * Pass child components, integrate and apply form context. + * + * @returns {Node} + */ + render() { + const { checked, errors, values, touched } = this; + const { children } = this.props; + + return ( + + {children({ + handleOnEventCustom: this.onEventCustom, + handleOnEvent: this.onEvent, + handleOnReset: this.onReset, + handleOnSubmit: this.onSubmit, + ..._cloneDeep({ ...this.state, checked, errors, values, touched }) + })} + + ); + } +} + +/** + * Prop types. + * + * @type {{setValuesOnUpdate: boolean, validateOnMount: boolean, children: Function, + * setValues: object, onSubmit: Function, resetUsingSetValues: boolean, + * setValuesAssumeBoolIsChecked: boolean, onReset: Function, validate: Function, + * validateOnUpdate: boolean}} + */ +FormState.propTypes = { + children: PropTypes.func.isRequired, + onReset: PropTypes.func, + onSubmit: PropTypes.func, + resetUsingSetValues: PropTypes.bool, + setValues: PropTypes.object, + setValuesOnUpdate: PropTypes.bool, + setValuesAssumeBoolIsChecked: PropTypes.bool, + validate: PropTypes.func, + validateOnMount: PropTypes.bool, + validateOnUpdate: PropTypes.bool +}; + +/** + * Default props. + * + * @type {{setValuesOnUpdate: boolean, validateOnMount: boolean, setValues: {}, + * onSubmit: Function, resetUsingSetValues: boolean, setValuesAssumeBoolIsChecked: boolean, + * onReset: Function, validate: Function, validateOnUpdate: boolean}} + */ +FormState.defaultProps = { + onReset: helpers.noop, + onSubmit: helpers.noop, + resetUsingSetValues: true, + setValues: {}, + setValuesOnUpdate: false, + setValuesAssumeBoolIsChecked: true, + validate: helpers.noop, + validateOnMount: false, + validateOnUpdate: false +}; + +export { FormState as default, FormState }; diff --git a/src/components/select/select.js b/src/components/form/select.js similarity index 100% rename from src/components/select/select.js rename to src/components/form/select.js diff --git a/src/components/graphCard/graphCard.js b/src/components/graphCard/graphCard.js index 689f1ed4c..3e9ba9f40 100644 --- a/src/components/graphCard/graphCard.js +++ b/src/components/graphCard/graphCard.js @@ -4,7 +4,7 @@ import { Card, CardHead, CardActions, CardBody } from '@patternfly/react-core'; import { chart_color_green_300 as chartColorGreenDark } from '@patternfly/react-tokens'; import { Skeleton, SkeletonSize } from '@redhat-cloud-services/frontend-components/components/Skeleton'; import _isEqual from 'lodash/isEqual'; -import { Select } from '../select/select'; +import { Select } from '../form/select'; import { connectTranslate, reduxActions, reduxSelectors, reduxTypes, store } from '../../redux'; import { helpers, dateHelpers } from '../../common'; import { rhsmApiTypes, RHSM_API_QUERY_GRANULARITY_TYPES as GRANULARITY_TYPES } from '../../types/rhsmApiTypes'; diff --git a/src/components/i18n/__tests__/__snapshots__/i18n.test.js.snap b/src/components/i18n/__tests__/__snapshots__/i18n.test.js.snap index c0cdddb3f..e91ca5d53 100644 --- a/src/components/i18n/__tests__/__snapshots__/i18n.test.js.snap +++ b/src/components/i18n/__tests__/__snapshots__/i18n.test.js.snap @@ -9,12 +9,18 @@ Object { } `; +exports[`I18n Component should attempt to perform translate with a node: translated node 1`] = `"
t(lorem.ipsum, [object Object], [object Object])
"`; + exports[`I18n Component should generate a predictable pot output snapshot: pot output 1`] = ` "msgid \\"\\" msgstr \\"\\" \\"Content-Type: text/plain; charset=UTF-8\\\\n\\" -#: src/components/openshiftView/openshiftView.js:92 +#: src/components/authentication/authentication.js:70 +msgid \\"curiosity-auth.authorizedTitle\\" +msgstr \\"\\" + +#: src/components/openshiftView/openshiftView.js:90 msgid \\"curiosity-graph.cardHeading\\" msgstr \\"\\" @@ -47,7 +53,7 @@ msgstr \\"\\" msgid \\"curiosity-graph.noDataLabel\\" msgstr \\"\\" -#: src/components/rhelView/rhelView.js:49 +#: src/components/rhelView/rhelView.js:47 msgid \\"curiosity-graph.socketsHeading\\" msgstr \\"\\" @@ -56,6 +62,91 @@ msgstr \\"\\" msgid \\"curiosity-graph.thresholdLabel\\" msgstr \\"\\" +#: src/components/optinView/optinView.js:109 +#: src/components/optinView/optinView.js:69 +msgid \\"curiosity-optin.buttonActivate\\" +msgstr \\"\\" + +#: src/components/optinView/optinView.js:97 +msgid \\"curiosity-optin.buttonIsActive\\" +msgstr \\"\\" + +#: src/components/optinView/optinView.js:145 +msgid \\"curiosity-optin.buttonTour\\" +msgstr \\"\\" + +#: src/components/optinView/optinView.js:53 +msgid \\"curiosity-optin.cardContactAdminDescription\\" +msgstr \\"\\" + +#: src/components/optinView/optinView.js:175 +msgid \\"curiosity-optin.cardDescription\\" +msgstr \\"\\" + +#: src/components/optinView/optinView.js:197 +msgid \\"curiosity-optin.cardFilterDescription\\" +msgstr \\"\\" + +#: src/components/optinView/optinView.js:194 +msgid \\"curiosity-optin.cardFilterTitle\\" +msgstr \\"\\" + +#: src/components/optinView/optinView.js:100 +msgid \\"curiosity-optin.cardIsActiveDescription\\" +msgstr \\"\\" + +#: src/components/optinView/optinView.js:79 +msgid \\"curiosity-optin.cardIsErrorDescription\\" +msgstr \\"\\" + +#: src/components/optinView/optinView.js:190 +msgid \\"curiosity-optin.cardReportDescription\\" +msgstr \\"\\" + +#: src/components/optinView/optinView.js:187 +msgid \\"curiosity-optin.cardReportTitle\\" +msgstr \\"\\" + +#: src/components/optinView/optinView.js:183 +msgid \\"curiosity-optin.cardSeeDescription\\" +msgstr \\"\\" + +#: src/components/optinView/optinView.js:180 +msgid \\"curiosity-optin.cardSeeTitle\\" +msgstr \\"\\" + +#: src/components/optinView/optinView.js:172 +msgid \\"curiosity-optin.cardTitle\\" +msgstr \\"\\" + +#: src/redux/actions/userActions.js:71 +msgid \\"curiosity-optin.notificationsErrorDescription\\" +msgstr \\"\\" + +#: src/redux/actions/userActions.js:70 +msgid \\"curiosity-optin.notificationsErrorTitle\\" +msgstr \\"\\" + +#: src/redux/actions/userActions.js:77 +msgid \\"curiosity-optin.notificationsSuccessDescription\\" +msgstr \\"\\" + +#: src/redux/actions/userActions.js:76 +msgid \\"curiosity-optin.notificationsSuccessTitle\\" +msgstr \\"\\" + +#: src/components/optinView/optinView.js:142 +msgid \\"curiosity-optin.tourDescription\\" +msgstr \\"\\" + +#: src/components/optinView/optinView.js:139 +msgid \\"curiosity-optin.tourTitle\\" +msgstr \\"\\" + +#: src/components/optinView/optinView.js:131 +msgid \\"curiosity-optin.tourTitleImageAlt\\" +msgstr \\"\\" + #: src/components/toolbar/toolbar.js:104 #: src/components/toolbar/toolbar.js:107 msgid \\"curiosity-toolbar.slaCategory\\" @@ -114,17 +205,20 @@ msgstr \\"\\" msgid \\"curiosity-tour.emptyStateTitle\\" msgstr \\"\\" -#: src/components/authentication/authentication.js:82 -msgctxt \\"...\\" -msgid \\"curiosity-auth.authorizedCopy\\" +#: src/components/openshiftView/openshiftView.js:79 +msgid \\"curiosity-view.openshift\\" +msgstr \\"\\" + +#: src/components/rhelView/rhelView.js:36 +msgid \\"curiosity-view.rhel\\" msgstr \\"\\" -#: src/components/authentication/authentication.js:81 +#: src/components/authentication/authentication.js:71 msgctxt \\"...\\" -msgid \\"curiosity-auth.authorizedTitle\\" +msgid \\"curiosity-auth.authorizedCopy\\" msgstr \\"\\" -#: src/components/authentication/authentication.js:69 +#: src/components/authentication/authentication.js:58 msgctxt \\"...\\" msgid \\"curiosity-auth.pending\\" msgstr \\"\\" diff --git a/src/components/i18n/__tests__/i18n.test.js b/src/components/i18n/__tests__/i18n.test.js index f14039d58..797d67551 100644 --- a/src/components/i18n/__tests__/i18n.test.js +++ b/src/components/i18n/__tests__/i18n.test.js @@ -60,6 +60,17 @@ describe('I18n Component', () => { expect(component.html()).toMatchSnapshot('children'); }); + it('should attempt to perform translate with a node', () => { + const ExampleComponent = () =>
{translate('lorem.ipsum', { hello: 'world' }, [])}
; + + ExampleComponent.propTypes = {}; + ExampleComponent.defaultProps = {}; + + const component = shallow(); + + expect(component.html()).toMatchSnapshot('translated node'); + }); + it('should attempt to perform a component translate', () => { const ExampleComponent = ({ t }) =>
{t('lorem.ipsum', 'hello world')}
; diff --git a/src/components/i18n/i18n.js b/src/components/i18n/i18n.js index c642c0c34..6e7c23dcc 100644 --- a/src/components/i18n/i18n.js +++ b/src/components/i18n/i18n.js @@ -2,12 +2,36 @@ import React from 'react'; import PropTypes from 'prop-types'; import i18next from 'i18next'; import XHR from 'i18next-xhr-backend'; -import { initReactI18next, withTranslation } from 'react-i18next'; +import { initReactI18next, Trans, withTranslation } from 'react-i18next'; import { helpers } from '../../common/helpers'; -const translate = (str, placeholder = null) => - (!helpers.TEST_MODE && i18next.t(str, placeholder)) || helpers.noopTranslate(str, placeholder); +/** + * Apply a string towards a key. Optional replacement values and component/nodes. + * See, https://react.i18next.com/ + * + * @param {string} translateKey + * @param {string|Array} values A default string if the key can't be found. An array of objects (key/value) pairs used to replace string tokes. i.e. "[{ hello: 'world' }]" + * @param {Array} components An array of HTML/React nodes used to replace string tokens. i.e. "[, ]" + * @returns {string|Node} + */ +const translate = (translateKey, values = null, components) => { + if (helpers.TEST_MODE) { + return helpers.noopTranslate(translateKey, values, components); + } + + if (components) { + return ; + } + return i18next.t(translateKey, values); +}; + +/** + * Apply string replacements against a component. + * + * @param {Node} component + * @returns {Node} + */ const translateComponent = component => (!helpers.TEST_MODE && withTranslation()(component)) || component; /** diff --git a/src/components/messageView/__tests__/__snapshots__/messageView.test.js.snap b/src/components/messageView/__tests__/__snapshots__/messageView.test.js.snap index f5c8fac28..c4047c0c4 100644 --- a/src/components/messageView/__tests__/__snapshots__/messageView.test.js.snap +++ b/src/components/messageView/__tests__/__snapshots__/messageView.test.js.snap @@ -15,12 +15,18 @@ exports[`MessageView Component should have fallback conditions for all props: fa exports[`MessageView Component should render a non-connected component: non-connected 1`] = ` - lorem + Subscription Watch + + lorem + diff --git a/src/components/messageView/messageView.js b/src/components/messageView/messageView.js index 88dbda217..8d10c47d0 100644 --- a/src/components/messageView/messageView.js +++ b/src/components/messageView/messageView.js @@ -1,22 +1,32 @@ import React from 'react'; import PropTypes from 'prop-types'; -import { EmptyState as PfEmptyState, EmptyStateBody, EmptyStateIcon, EmptyStateVariant } from '@patternfly/react-core'; +import { + EmptyState as PfEmptyState, + EmptyStateBody, + EmptyStateIcon, + EmptyStateVariant, + Title +} from '@patternfly/react-core'; import { PageLayout, PageHeader } from '../pageLayout/pageLayout'; import { helpers } from '../../common'; /** - * FixMe: Patternfly EmptyStateIcon PropType is not intuitive - * Requires the use of a function proptype?!? + * FixMe: Patternfly EmptyStateIcon PropType registers as function? */ /** * Render a message view. * * @returns {Node} */ -const MessageView = ({ icon, message, title }) => ( +const MessageView = ({ icon, message, pageTitle, title }) => ( - {title || helpers.UI_DISPLAY_CONFIG_NAME} + {pageTitle || helpers.UI_DISPLAY_NAME} + {title && ( + + {title} + + )} {icon && } {message && {message}} @@ -31,6 +41,7 @@ const MessageView = ({ icon, message, title }) => ( MessageView.propTypes = { icon: PropTypes.oneOfType([PropTypes.node, PropTypes.func]), message: PropTypes.string, + pageTitle: PropTypes.string, title: PropTypes.string }; @@ -42,6 +53,7 @@ MessageView.propTypes = { MessageView.defaultProps = { icon: null, message: null, + pageTitle: null, title: null }; diff --git a/src/components/openshiftView/__tests__/__snapshots__/openshiftView.test.js.snap b/src/components/openshiftView/__tests__/__snapshots__/openshiftView.test.js.snap index 07c860829..792245496 100644 --- a/src/components/openshiftView/__tests__/__snapshots__/openshiftView.test.js.snap +++ b/src/components/openshiftView/__tests__/__snapshots__/openshiftView.test.js.snap @@ -3,7 +3,7 @@ exports[`OpenshiftView Component should have a fallback title: title 1`] = ` - Subscription Watch + t(curiosity-view.openshift, Subscription Watch) - Dolor sit + t(curiosity-view.openshift, Subscription Watch) - - {(routeDetail.routeItem && routeDetail.routeItem.title) || helpers.UI_DISPLAY_CONFIG_NAME} - + {t('curiosity-view.openshift', helpers.UI_DISPLAY_CONFIG_NAME)} diff --git a/src/components/optinView/__tests__/__snapshots__/optinView.test.js.snap b/src/components/optinView/__tests__/__snapshots__/optinView.test.js.snap new file mode 100644 index 000000000..ba7ea286f --- /dev/null +++ b/src/components/optinView/__tests__/__snapshots__/optinView.test.js.snap @@ -0,0 +1,149 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`OptinView Component should render a non-connected component: non-connected 1`] = ` + + + + + + + + t(curiosity-optin.cardTitle, [object Object]) + + + + t(curiosity-optin.cardDescription, [object Object]) + + + + t(curiosity-optin.cardSeeTitle) + + + + t(curiosity-optin.cardSeeDescription) + + + + t(curiosity-optin.cardReportTitle) + + + + t(curiosity-optin.cardReportDescription) + + + + t(curiosity-optin.cardFilterTitle) + + + + t(curiosity-optin.cardFilterDescription) + + +

+ t(curiosity-optin.cardContactAdminDescription, [object Object]) +

+
+
+
+ + + + + + + + + + + + t(curiosity-optin.tourTitle) + + + + t(curiosity-optin.tourDescription) + + + + t(curiosity-optin.buttonTour) + + + + + + +
+
+
+`; diff --git a/src/components/optinView/__tests__/optinView.test.js b/src/components/optinView/__tests__/optinView.test.js new file mode 100644 index 000000000..830641391 --- /dev/null +++ b/src/components/optinView/__tests__/optinView.test.js @@ -0,0 +1,12 @@ +import React from 'react'; +import { shallow } from 'enzyme'; +import { OptinView } from '../optinView'; + +describe('OptinView Component', () => { + it('should render a non-connected component', () => { + const props = {}; + + const component = shallow(); + expect(component).toMatchSnapshot('non-connected'); + }); +}); diff --git a/src/components/optinView/optinView.js b/src/components/optinView/optinView.js new file mode 100644 index 000000000..a441fe3b0 --- /dev/null +++ b/src/components/optinView/optinView.js @@ -0,0 +1,271 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { + Brand, + Button, + Card, + CardHead, + CardHeadMain, + CardHeader, + CardBody, + CardFooter, + Flex, + FlexItem, + FlexBreakpoints, + FlexModifiers, + Form, + ActionGroup, + Spinner, + Title +} from '@patternfly/react-core'; +import { connectTranslate, reduxActions } from '../../redux'; +import { translate } from '../i18n/i18n'; +import { PageLayout } from '../pageLayout/pageLayout'; +import { helpers } from '../../common'; +import graphPng2x from '../../images/graph2x.png'; +import graphPng4x from '../../images/graph4x.png'; + +/** + * An account opt-in view. + * + * @augments React.Component + * @fires onSubmitOptIn + */ +class OptinView extends React.Component { + /** + * Submit and update account opt-in. + * + * @event onSubmitOptIn + */ + onSubmitOptIn = () => { + const { updateAccountOptIn } = this.props; + updateAccountOptIn(); + }; + + /** + * Render non-org-admin content. + * + * @returns {Node} + */ + renderContactAdmin() { + const { t } = this.props; + + return

{t('curiosity-optin.cardContactAdminDescription', { appName: helpers.UI_DISPLAY_NAME })}

; + } + + /** + * Render org-admin opt-in form states. + * + * @returns {Node} + */ + renderOptinForm() { + const { error, fulfilled, pending, t } = this.props; + + if (pending) { + return ( +
+ + + +
+ ); + } + + if (error) { + return ( +

+ {translate('curiosity-optin.cardIsErrorDescription', { appName: helpers.UI_DISPLAY_NAME }, [ + + +

{t('curiosity-optin.cardIsActiveDescription')}

+ + ); + } + + return ( +
+ + + +
+ ); + } + + /** + * Render tour copy and button. + * + * @returns {Node} + */ + renderTour() { + const { t } = this.props; + + return ( + + + + + + + + + {t('curiosity-optin.tourTitle')} + + + {t('curiosity-optin.tourDescription')} + + + + + ); + } + + /** + * Render opt-in. + * + * @returns {Node} + */ + render() { + const { session, t } = this.props; + + return ( + + + + + + + {t('curiosity-optin.cardTitle', { appName: helpers.UI_DISPLAY_NAME })} + + + {t('curiosity-optin.cardDescription', { appName: helpers.UI_DISPLAY_NAME })} + + + + + {t('curiosity-optin.cardSeeTitle')} + + + {t('curiosity-optin.cardSeeDescription')} + + + + {t('curiosity-optin.cardReportTitle')} + + + {t('curiosity-optin.cardReportDescription')} + + + + {t('curiosity-optin.cardFilterTitle')} + + + {t('curiosity-optin.cardFilterDescription')} + + {(session.admin && this.renderOptinForm()) || this.renderContactAdmin()} + + + + + {this.renderTour()} + + + + + + ); + } +} + +/** + * Prop types. + * + * @type {{t: Function, session: object, updateAccountOptIn: Function, pending: boolean, + * fulfilled: boolean, error: boolean}} + */ +OptinView.propTypes = { + error: PropTypes.bool, + fulfilled: PropTypes.bool, + pending: PropTypes.bool, + session: PropTypes.shape({ + admin: PropTypes.bool + }), + t: PropTypes.func, + updateAccountOptIn: PropTypes.func +}; + +/** + * Default props. + * + * @type {{t: Function, session: {admin: boolean}, updateAccountOptIn: Function, + * pending: boolean, fulfilled: boolean, error: boolean}} + */ +OptinView.defaultProps = { + error: false, + fulfilled: false, + pending: false, + session: { + admin: false + }, + t: helpers.noopTranslate, + updateAccountOptIn: helpers.noop +}; + +/** + * Apply actions to props. + * + * @param {Function} dispatch + * @returns {object} + */ +const mapDispatchToProps = dispatch => ({ + getAccountOptIn: () => dispatch(reduxActions.user.getAccountOptIn()), + updateAccountOptIn: query => dispatch(reduxActions.user.updateAccountOptIn(query)) +}); + +/** + * Apply state to props. + * + * @param {object} state + * @returns {object} + */ +const mapStateToProps = ({ user }) => ({ ...user.optin, session: user.session }); + +const ConnectedOptinView = connectTranslate(mapStateToProps, mapDispatchToProps)(OptinView); + +export { ConnectedOptinView as default, ConnectedOptinView, OptinView }; diff --git a/src/components/rhelView/__tests__/__snapshots__/rhelView.test.js.snap b/src/components/rhelView/__tests__/__snapshots__/rhelView.test.js.snap index 53b896a3f..7519f553d 100644 --- a/src/components/rhelView/__tests__/__snapshots__/rhelView.test.js.snap +++ b/src/components/rhelView/__tests__/__snapshots__/rhelView.test.js.snap @@ -3,7 +3,7 @@ exports[`RhelView Component should have a fallback title: title 1`] = ` - Subscription Watch + t(curiosity-view.rhel, Subscription Watch) - Dolor sit + t(curiosity-view.rhel, Subscription Watch) - - {(routeDetail.routeItem && routeDetail.routeItem.title) || helpers.UI_DISPLAY_CONFIG_NAME} - + {t('curiosity-view.rhel', helpers.UI_DISPLAY_CONFIG_NAME)} diff --git a/src/components/router/__tests__/__snapshots__/router.test.js.snap b/src/components/router/__tests__/__snapshots__/router.test.js.snap index 4f5b7de15..feea9ceb1 100644 --- a/src/components/router/__tests__/__snapshots__/router.test.js.snap +++ b/src/components/router/__tests__/__snapshots__/router.test.js.snap @@ -45,8 +45,8 @@ exports[`Router Component should render a basic component: basic 1`] = ` /> { it('should return specific properties', () => { expect(baseName).toBeDefined(); expect(dynamicBaseName).toBeDefined(); + expect(getErrorRoute).toBeDefined(); expect(getNavigationDetail).toBeDefined(); expect(getRouteDetail).toBeDefined(); expect(getNavRouteDetail).toBeDefined(); @@ -61,6 +69,10 @@ describe('RouterHelpers', () => { ).toMatchSnapshot('beta app lorem route name'); }); + it('should return an error route', () => { + expect(getErrorRoute).toMatchSnapshot('error route'); + }); + it('should return navigation and route details that align to location', () => { expect({ nav: getNavigationDetail({ id: 'soon' }), diff --git a/src/components/router/__tests__/routerTypes.test.js b/src/components/router/__tests__/routerTypes.test.js index 96db2c525..abce41dcd 100644 --- a/src/components/router/__tests__/routerTypes.test.js +++ b/src/components/router/__tests__/routerTypes.test.js @@ -1,10 +1,11 @@ -import { appName, navigation, platformRedirect, routes } from '../routerTypes'; +import { appName, navigation, platformLandingRedirect, platformModalRedirect, routes } from '../routerTypes'; describe('RouterTypes', () => { it('should return specific properties', () => { expect(appName).toMatchSnapshot('appName'); expect(navigation).toMatchSnapshot('navigation'); - expect(platformRedirect).toMatchSnapshot('platformRedirect'); + expect(platformLandingRedirect).toMatchSnapshot('platformLandingRedirect'); + expect(platformModalRedirect).toMatchSnapshot('platformModalRedirect'); expect(routes).toMatchSnapshot('routes'); }); }); diff --git a/src/components/router/routerTypes.js b/src/components/router/routerTypes.js index 3ad2a1cde..e8e4d8da3 100644 --- a/src/components/router/routerTypes.js +++ b/src/components/router/routerTypes.js @@ -1,6 +1,7 @@ import path from 'path'; import { helpers } from '../../common/helpers'; import OpenshiftView from '../openshiftView/openshiftView'; +import OptinView from '../optinView/optinView'; import RhelView from '../rhelView/rhelView'; import TourView from '../tourView/tourView'; import { RHSM_API_PATH_ID_TYPES } from '../../types/rhsmApiTypes'; @@ -17,7 +18,14 @@ const appName = helpers.UI_NAME; * * @returns {Array} */ -const platformRedirect = path.join(helpers.UI_DEPLOY_PATH_PREFIX, '/?not_entitled=subscriptions'); +const platformLandingRedirect = path.join(helpers.UI_DEPLOY_PATH_PREFIX, '/'); + +/** + * Return a string that describes a platform redirect. + * + * @returns {Array} + */ +const platformModalRedirect = path.join(helpers.UI_DEPLOY_PATH_PREFIX, '/?not_entitled=subscriptions'); /** * Return array of objects that describes routing. @@ -26,7 +34,6 @@ const platformRedirect = path.join(helpers.UI_DEPLOY_PATH_PREFIX, '/?not_entitle */ const routes = [ { - title: 'Red Hat Enterprise Linux', to: '/rhel-sw/all', redirect: true, component: RhelView, @@ -35,7 +42,6 @@ const routes = [ disabled: helpers.UI_DISABLED }, { - title: 'Red Hat Enterprise Linux', id: 'rhel-sw', to: '/rhel-sw/:variant', component: RhelView, @@ -44,7 +50,6 @@ const routes = [ disabled: helpers.UI_DISABLED }, { - title: 'Red Hat OpenShift', id: 'openshift-sw', to: '/openshift-sw', component: OpenshiftView, @@ -53,34 +58,31 @@ const routes = [ disabled: helpers.UI_DISABLED }, { - title: 'Tour', id: 'soon', to: '/soon', component: TourView, exact: true, render: true, - activateOnError: true, disabled: helpers.UI_DISABLED }, { - title: 'Tour', - id: 'tour', - to: '/tour', - component: TourView, + id: 'optin', + to: '/optin', + component: OptinView, exact: true, render: true, + activateOnError: true, disabled: helpers.UI_DISABLED } ]; /** - * Return an array of objects that describes platform navigation. + * Return an array of objects that describes navigation against API product IDs. * * @returns {Array} */ const navigation = [ { - title: 'Red Hat Enterprise Linux', id: 'all', path: '/rhel-sw/all', pathId: 'rhel-sw', @@ -88,35 +90,30 @@ const navigation = [ default: true }, { - title: 'ARM', id: 'arm', path: '/rhel-sw/arm', pathId: 'rhel-sw', pathParameter: RHSM_API_PATH_ID_TYPES.RHEL_ARM }, { - title: 'IBM Power', id: 'ibmpower', path: '/rhel-sw/ibmpower', pathId: 'rhel-sw', pathParameter: RHSM_API_PATH_ID_TYPES.RHEL_IBM_POWER }, { - title: 'IBM Z systems', id: 'ibmz', path: '/rhel-sw/ibmz', pathId: 'rhel-sw', pathParameter: RHSM_API_PATH_ID_TYPES.RHEL_IBM_Z }, { - title: 'x86', id: 'x86', path: '/rhel-sw/x86', pathId: 'rhel-sw', pathParameter: RHSM_API_PATH_ID_TYPES.RHEL_X86 }, { - title: 'Red Hat OpenShift', id: 'openshift-sw', path: '/openshift-sw', pathId: 'openshift-sw', @@ -127,8 +124,17 @@ const navigation = [ const routerTypes = { appName, navigation, - platformRedirect, + platformLandingRedirect, + platformModalRedirect, routes }; -export { routerTypes as default, routerTypes, appName, navigation, platformRedirect, routes }; +export { + routerTypes as default, + routerTypes, + appName, + navigation, + platformLandingRedirect, + platformModalRedirect, + routes +}; diff --git a/src/components/toolbar/toolbar.js b/src/components/toolbar/toolbar.js index 175584663..96cbb0a9b 100644 --- a/src/components/toolbar/toolbar.js +++ b/src/components/toolbar/toolbar.js @@ -2,7 +2,7 @@ import React from 'react'; import PropTypes from 'prop-types'; import { withTranslation } from 'react-i18next'; import { DataToolbar, DataToolbarContent, DataToolbarFilter, DataToolbarGroup } from '@patternfly/react-core'; -import { Select } from '../select/select'; +import { Select } from '../form/select'; import { reduxTypes, store } from '../../redux'; import { rhsmApiTypes } from '../../types/rhsmApiTypes'; import { toolbarTypes } from './toolbarTypes'; diff --git a/src/images/graph2x.png b/src/images/graph2x.png new file mode 100644 index 000000000..02d9de098 Binary files /dev/null and b/src/images/graph2x.png differ diff --git a/src/images/graph4x.png b/src/images/graph4x.png new file mode 100644 index 000000000..d5d537dfe Binary files /dev/null and b/src/images/graph4x.png differ diff --git a/src/redux/actions/__tests__/userActions.test.js b/src/redux/actions/__tests__/userActions.test.js index 7cd3e519f..26e542933 100644 --- a/src/redux/actions/__tests__/userActions.test.js +++ b/src/redux/actions/__tests__/userActions.test.js @@ -17,14 +17,13 @@ describe('UserActions', () => { beforeEach(() => { moxios.install(); - moxios.wait(() => { - const request = moxios.requests.mostRecent(); - request.respondWith({ - status: 200, - response: { - test: 'success' - } - }); + moxios.stubRequest(/\/(opt-in).*?/, { + status: 200, + responseText: 'success', + timeout: 1, + response: { + test: 'success' + } }); }); @@ -44,4 +43,37 @@ describe('UserActions', () => { done(); }); }); + + it('Should return response content for deleteAccountOptIn method', done => { + const store = generateStore(); + const dispatcher = userActions.deleteAccountOptIn(); + + dispatcher(store.dispatch).then(() => { + const response = store.getState().user; + expect(response.optin.fulfilled).toBe(true); + done(); + }); + }); + + it('Should return response content for getAccountOptIn method', done => { + const store = generateStore(); + const dispatcher = userActions.getAccountOptIn(); + + dispatcher(store.dispatch).then(() => { + const response = store.getState().user; + expect(response.optin.fulfilled).toBe(true); + done(); + }); + }); + + it('Should return response content for updateAccountOptIn method', done => { + const store = generateStore(); + const dispatcher = userActions.updateAccountOptIn(); + + dispatcher(store.dispatch).then(() => { + const response = store.getState().user; + expect(response.optin.fulfilled).toBe(true); + done(); + }); + }); }); diff --git a/src/redux/actions/userActions.js b/src/redux/actions/userActions.js index 814191d05..f2eb004df 100644 --- a/src/redux/actions/userActions.js +++ b/src/redux/actions/userActions.js @@ -1,5 +1,7 @@ import { userTypes } from '../types'; import { userServices } from '../../services/userServices'; +import { helpers } from '../../common/helpers'; +import { translate } from '../../components/i18n/i18n'; /** * Get an emulated API response from the platforms "getUser" method. @@ -22,6 +24,72 @@ const getLocale = () => ({ payload: userServices.getLocale() }); -const userActions = { authorizeUser, getLocale }; +/** + * Delete a user's opt-in. + * + * @returns {Function} + */ +const deleteAccountOptIn = () => dispatch => + dispatch({ + type: userTypes.DELETE_USER_OPTIN, + payload: userServices.deleteAccountOptIn(), + meta: { + notifications: {} + } + }); + +/** + * Get a user's opt-in config. + * + * @returns {Function} + */ +const getAccountOptIn = () => dispatch => + dispatch({ + type: userTypes.GET_USER_OPTIN, + payload: userServices.getAccountOptIn(), + meta: { + notifications: {} + } + }); + +/** + * Update a user's opt-in. + * + * @param {object} query + * @returns {Function} + */ +const updateAccountOptIn = (query = {}) => dispatch => + dispatch({ + type: userTypes.UPDATE_USER_OPTIN, + payload: userServices.updateAccountOptIn(query), + meta: { + query, + notifications: { + rejected: { + variant: 'danger', + title: translate('curiosity-optin.notificationsErrorTitle', { appName: helpers.UI_DISPLAY_NAME }), + description: translate('curiosity-optin.notificationsErrorDescription'), + dismissable: true + }, + fulfilled: { + variant: 'success', + title: translate('curiosity-optin.notificationsSuccessTitle', { appName: helpers.UI_DISPLAY_NAME }), + description: translate('curiosity-optin.notificationsSuccessDescription'), + dismissable: true, + autoDismiss: false + } + } + } + }); + +const userActions = { authorizeUser, getLocale, deleteAccountOptIn, getAccountOptIn, updateAccountOptIn }; -export { userActions as default, userActions, authorizeUser, getLocale }; +export { + userActions as default, + userActions, + authorizeUser, + getLocale, + deleteAccountOptIn, + getAccountOptIn, + updateAccountOptIn +}; diff --git a/src/redux/common/__tests__/__snapshots__/reduxHelpers.test.js.snap b/src/redux/common/__tests__/__snapshots__/reduxHelpers.test.js.snap index e2298695f..00ddb8642 100644 --- a/src/redux/common/__tests__/__snapshots__/reduxHelpers.test.js.snap +++ b/src/redux/common/__tests__/__snapshots__/reduxHelpers.test.js.snap @@ -152,6 +152,25 @@ exports[`ReduxHelpers should get a message from a service call response: respons exports[`ReduxHelpers should get a message from a service call response: response for 4XX 1`] = `"Request failed with status code 400"`; +exports[`ReduxHelpers should get data from a service call response: ARRAY data 1`] = ` +Array [ + Object { + "dolor": "sit", + "lorem": "ipsum", + }, + Object { + "hello": "world", + }, +] +`; + +exports[`ReduxHelpers should get data from a service call response: data 1`] = ` +Object { + "dolor": "sit", + "lorem": "ipsum", +} +`; + exports[`ReduxHelpers should have specific functions: reduxHelpers 1`] = ` Object { "FULFILLED_ACTION": [Function], @@ -159,6 +178,7 @@ Object { "PENDING_ACTION": [Function], "REJECTED_ACTION": [Function], "generatedPromiseActionReducer": [Function], + "getDataFromResults": [Function], "getDateFromResults": [Function], "getMessageFromResults": [Function], "getSingleResponseFromResultArray": [Function], diff --git a/src/redux/common/__tests__/reduxHelpers.test.js b/src/redux/common/__tests__/reduxHelpers.test.js index a30cdd647..c73f9f380 100644 --- a/src/redux/common/__tests__/reduxHelpers.test.js +++ b/src/redux/common/__tests__/reduxHelpers.test.js @@ -187,6 +187,42 @@ describe('ReduxHelpers', () => { ).toMatchSnapshot('ARRAY date'); }); + it('should get data from a service call response', () => { + expect( + reduxHelpers.getDataFromResults({ + payload: { + headers: { + date: 'Tue, 11 Feb 2020 15:27:16 GMT' + }, + status: 200, + statusText: 'OK', + data: { lorem: 'ipsum', dolor: 'sit' } + } + }) + ).toMatchSnapshot('data'); + + expect( + reduxHelpers.getDataFromResults([ + { + headers: { + date: 'Tue, 11 Feb 2020 15:27:16 GMT' + }, + status: 200, + statusText: 'OK', + data: { lorem: 'ipsum', dolor: 'sit' } + }, + { + headers: { + date: 'Tue, 11 Feb 2020 15:27:18 GMT' + }, + status: 200, + statusText: 'OK', + data: { hello: 'world' } + } + ]) + ).toMatchSnapshot('ARRAY data'); + }); + it('should update a state object', () => { const initialState = { lorem: false, diff --git a/src/redux/common/reduxHelpers.js b/src/redux/common/reduxHelpers.js index 3cbcb8bee..e9985b9bb 100644 --- a/src/redux/common/reduxHelpers.js +++ b/src/redux/common/reduxHelpers.js @@ -206,6 +206,14 @@ const singlePromiseDataResponseFromArray = results => { return updatedResults.data || {}; }; +/** + * Alias for singlePromiseDataResponseFromArray. + * + * @param {Array|object} results + * @returns {Array|object} + */ +const getDataFromResults = results => singlePromiseDataResponseFromArray(results); + /** * Automatically apply reducer logic to state by handling promise responses from redux-promise-middleware. * @@ -318,6 +326,7 @@ const reduxHelpers = { HTTP_STATUS_RANGE, setResponseSchemas, generatedPromiseActionReducer, + getDataFromResults, getDateFromResults, getMessageFromResults, getSingleResponseFromResultArray, diff --git a/src/redux/reducers/__tests__/__snapshots__/userReducer.test.js.snap b/src/redux/reducers/__tests__/__snapshots__/userReducer.test.js.snap index 0cff0c636..8fbebcfd2 100644 --- a/src/redux/reducers/__tests__/__snapshots__/userReducer.test.js.snap +++ b/src/redux/reducers/__tests__/__snapshots__/userReducer.test.js.snap @@ -1,33 +1,260 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`UserReducer should handle all defined error types: rejected types DELETE_USER_OPTIN 1`] = ` +Object { + "result": Object { + "optin": Object { + "error": true, + "errorMessage": "MESSAGE", + "errorStatus": 0, + "fulfilled": false, + "meta": Object {}, + "metaData": undefined, + "metaId": undefined, + "metaQuery": undefined, + "pending": false, + }, + "session": Object { + "admin": false, + "authorized": false, + "entitled": false, + "error": false, + "errorMessage": null, + "errorStatus": null, + "fulfilled": false, + "locale": null, + "pending": false, + "permissions": Array [], + }, + }, + "type": "DELETE_USER_OPTIN_REJECTED", +} +`; + +exports[`UserReducer should handle all defined error types: rejected types GET_USER_OPTIN 1`] = ` +Object { + "result": Object { + "optin": Object { + "error": true, + "errorMessage": "MESSAGE", + "errorStatus": 0, + "fulfilled": false, + "meta": Object {}, + "metaData": undefined, + "metaId": undefined, + "metaQuery": undefined, + "pending": false, + }, + "session": Object { + "admin": false, + "authorized": false, + "entitled": false, + "error": false, + "errorMessage": null, + "errorStatus": null, + "fulfilled": false, + "locale": null, + "pending": false, + "permissions": Array [], + }, + }, + "type": "GET_USER_OPTIN_REJECTED", +} +`; + +exports[`UserReducer should handle all defined error types: rejected types UPDATE_USER_OPTIN 1`] = ` +Object { + "result": Object { + "optin": Object { + "error": true, + "errorMessage": "MESSAGE", + "errorStatus": 0, + "fulfilled": false, + "meta": Object {}, + "metaData": undefined, + "metaId": undefined, + "metaQuery": undefined, + "pending": false, + }, + "session": Object { + "admin": false, + "authorized": false, + "entitled": false, + "error": false, + "errorMessage": null, + "errorStatus": null, + "fulfilled": false, + "locale": null, + "pending": false, + "permissions": Array [], + }, + }, + "type": "UPDATE_USER_OPTIN_REJECTED", +} +`; + exports[`UserReducer should handle all defined error types: rejected types USER_AUTH 1`] = ` Object { "result": Object { + "optin": Object {}, "session": Object { + "admin": false, "authorized": false, + "entitled": false, "error": true, "errorMessage": "MESSAGE", "errorStatus": 0, "fulfilled": false, "locale": null, "pending": false, + "permissions": Array [], }, }, "type": "USER_AUTH_REJECTED", } `; +exports[`UserReducer should handle all defined fulfilled types: fulfilled types DELETE_USER_OPTIN 1`] = ` +Object { + "result": Object { + "optin": Object { + "data": Object { + "permissions": Array [], + "test": "success", + "user": Object { + "identity": Object { + "user": Object { + "is_org_admin": true, + }, + }, + }, + }, + "date": null, + "error": false, + "errorMessage": "", + "fulfilled": true, + "meta": Object {}, + "metaData": undefined, + "metaId": undefined, + "metaQuery": undefined, + "pending": false, + }, + "session": Object { + "admin": false, + "authorized": false, + "entitled": false, + "error": false, + "errorMessage": null, + "errorStatus": null, + "fulfilled": false, + "locale": null, + "pending": false, + "permissions": Array [], + }, + }, + "type": "DELETE_USER_OPTIN_FULFILLED", +} +`; + +exports[`UserReducer should handle all defined fulfilled types: fulfilled types GET_USER_OPTIN 1`] = ` +Object { + "result": Object { + "optin": Object { + "data": Object { + "permissions": Array [], + "test": "success", + "user": Object { + "identity": Object { + "user": Object { + "is_org_admin": true, + }, + }, + }, + }, + "date": null, + "error": false, + "errorMessage": "", + "fulfilled": true, + "meta": Object {}, + "metaData": undefined, + "metaId": undefined, + "metaQuery": undefined, + "pending": false, + }, + "session": Object { + "admin": false, + "authorized": false, + "entitled": false, + "error": false, + "errorMessage": null, + "errorStatus": null, + "fulfilled": false, + "locale": null, + "pending": false, + "permissions": Array [], + }, + }, + "type": "GET_USER_OPTIN_FULFILLED", +} +`; + +exports[`UserReducer should handle all defined fulfilled types: fulfilled types UPDATE_USER_OPTIN 1`] = ` +Object { + "result": Object { + "optin": Object { + "data": Object { + "permissions": Array [], + "test": "success", + "user": Object { + "identity": Object { + "user": Object { + "is_org_admin": true, + }, + }, + }, + }, + "date": null, + "error": false, + "errorMessage": "", + "fulfilled": true, + "meta": Object {}, + "metaData": undefined, + "metaId": undefined, + "metaQuery": undefined, + "pending": false, + }, + "session": Object { + "admin": false, + "authorized": false, + "entitled": false, + "error": false, + "errorMessage": null, + "errorStatus": null, + "fulfilled": false, + "locale": null, + "pending": false, + "permissions": Array [], + }, + }, + "type": "UPDATE_USER_OPTIN_FULFILLED", +} +`; + exports[`UserReducer should handle all defined fulfilled types: fulfilled types USER_AUTH 1`] = ` Object { "result": Object { + "optin": Object {}, "session": Object { + "admin": true, "authorized": true, + "entitled": false, "error": false, "errorMessage": null, "errorStatus": null, "fulfilled": true, "locale": null, "pending": false, + "permissions": Array [], }, }, "type": "USER_AUTH_FULFILLED", @@ -37,33 +264,139 @@ Object { exports[`UserReducer should handle all defined fulfilled types: fulfilled types USER_LOCALE 1`] = ` Object { "result": Object { + "optin": Object {}, "session": Object { + "admin": false, "authorized": false, + "entitled": false, "error": false, "errorMessage": null, "errorStatus": null, "fulfilled": false, "locale": Object { + "permissions": Array [], "test": "success", + "user": Object { + "identity": Object { + "user": Object { + "is_org_admin": true, + }, + }, + }, }, "pending": false, + "permissions": Array [], }, }, "type": "USER_LOCALE_FULFILLED", } `; +exports[`UserReducer should handle all defined pending types: pending types DELETE_USER_OPTIN 1`] = ` +Object { + "result": Object { + "optin": Object { + "error": false, + "errorMessage": "", + "fulfilled": false, + "meta": Object {}, + "metaData": undefined, + "metaId": undefined, + "metaQuery": undefined, + "pending": true, + }, + "session": Object { + "admin": false, + "authorized": false, + "entitled": false, + "error": false, + "errorMessage": null, + "errorStatus": null, + "fulfilled": false, + "locale": null, + "pending": false, + "permissions": Array [], + }, + }, + "type": "DELETE_USER_OPTIN_PENDING", +} +`; + +exports[`UserReducer should handle all defined pending types: pending types GET_USER_OPTIN 1`] = ` +Object { + "result": Object { + "optin": Object { + "error": false, + "errorMessage": "", + "fulfilled": false, + "meta": Object {}, + "metaData": undefined, + "metaId": undefined, + "metaQuery": undefined, + "pending": true, + }, + "session": Object { + "admin": false, + "authorized": false, + "entitled": false, + "error": false, + "errorMessage": null, + "errorStatus": null, + "fulfilled": false, + "locale": null, + "pending": false, + "permissions": Array [], + }, + }, + "type": "GET_USER_OPTIN_PENDING", +} +`; + +exports[`UserReducer should handle all defined pending types: pending types UPDATE_USER_OPTIN 1`] = ` +Object { + "result": Object { + "optin": Object { + "error": false, + "errorMessage": "", + "fulfilled": false, + "meta": Object {}, + "metaData": undefined, + "metaId": undefined, + "metaQuery": undefined, + "pending": true, + }, + "session": Object { + "admin": false, + "authorized": false, + "entitled": false, + "error": false, + "errorMessage": null, + "errorStatus": null, + "fulfilled": false, + "locale": null, + "pending": false, + "permissions": Array [], + }, + }, + "type": "UPDATE_USER_OPTIN_PENDING", +} +`; + exports[`UserReducer should handle all defined pending types: pending types USER_AUTH 1`] = ` Object { "result": Object { + "optin": Object {}, "session": Object { + "admin": false, "authorized": false, + "entitled": false, "error": false, "errorMessage": null, "errorStatus": null, "fulfilled": false, "locale": null, "pending": true, + "permissions": Array [], }, }, "type": "USER_AUTH_PENDING", @@ -73,14 +406,18 @@ Object { exports[`UserReducer should handle specific http status types: http status 4XX 400 1`] = ` Object { "result": Object { + "optin": Object {}, "session": Object { + "admin": false, "authorized": false, + "entitled": false, "error": false, "errorMessage": null, "errorStatus": null, "fulfilled": false, "locale": null, "pending": false, + "permissions": Array [], }, }, "type": "4XX", @@ -90,14 +427,18 @@ Object { exports[`UserReducer should handle specific http status types: http status 4XX 401 1`] = ` Object { "result": Object { + "optin": Object {}, "session": Object { + "admin": false, "authorized": false, + "entitled": false, "error": true, "errorMessage": "Lorem test status", "errorStatus": 401, "fulfilled": false, "locale": null, "pending": false, + "permissions": Array [], }, }, "type": "4XX", @@ -107,14 +448,18 @@ Object { exports[`UserReducer should handle specific http status types: http status 4XX 403 1`] = ` Object { "result": Object { + "optin": Object {}, "session": Object { + "admin": false, "authorized": false, + "entitled": false, "error": true, "errorMessage": "Lorem test status", "errorStatus": 403, "fulfilled": false, "locale": null, "pending": false, + "permissions": Array [], }, }, "type": "4XX", diff --git a/src/redux/reducers/__tests__/userReducer.test.js b/src/redux/reducers/__tests__/userReducer.test.js index f4b36b4c5..30495e20c 100644 --- a/src/redux/reducers/__tests__/userReducer.test.js +++ b/src/redux/reducers/__tests__/userReducer.test.js @@ -1,4 +1,5 @@ import userReducer from '../userReducer'; +import { platformApiTypes } from '../../../types'; import { appTypes, userTypes as types } from '../../types'; import { reduxHelpers } from '../../common/reduxHelpers'; @@ -28,7 +29,7 @@ describe('UserReducer', () => { }); it('should handle all defined error types', () => { - const specificTypes = [types.USER_AUTH]; + const specificTypes = [types.USER_AUTH, types.DELETE_USER_OPTIN, types.GET_USER_OPTIN, types.UPDATE_USER_OPTIN]; specificTypes.forEach(value => { const dispatched = { @@ -55,7 +56,7 @@ describe('UserReducer', () => { }); it('should handle all defined pending types', () => { - const specificTypes = [types.USER_AUTH]; + const specificTypes = [types.USER_AUTH, types.DELETE_USER_OPTIN, types.GET_USER_OPTIN, types.UPDATE_USER_OPTIN]; specificTypes.forEach(value => { const dispatched = { @@ -71,14 +72,28 @@ describe('UserReducer', () => { }); it('should handle all defined fulfilled types', () => { - const specificTypes = [types.USER_AUTH, types.USER_LOCALE]; + const specificTypes = [ + types.USER_AUTH, + types.USER_LOCALE, + types.DELETE_USER_OPTIN, + types.GET_USER_OPTIN, + types.UPDATE_USER_OPTIN + ]; specificTypes.forEach(value => { const dispatched = { type: reduxHelpers.FULFILLED_ACTION(value), payload: { data: { - test: 'success' + test: 'success', + user: { + [platformApiTypes.PLATFORM_API_RESPONSE_USER_IDENTITY]: { + [platformApiTypes.PLATFORM_API_RESPONSE_USER_IDENTITY_TYPES.USER]: { + [platformApiTypes.PLATFORM_API_RESPONSE_USER_IDENTITY_USER_TYPES.ORG_ADMIN]: true + } + } + }, + permissions: [] } } }; diff --git a/src/redux/reducers/userReducer.js b/src/redux/reducers/userReducer.js index 34ac664b8..c6c9cf002 100644 --- a/src/redux/reducers/userReducer.js +++ b/src/redux/reducers/userReducer.js @@ -1,4 +1,7 @@ +import _get from 'lodash/get'; import { appTypes, userTypes } from '../types'; +import { platformApiTypes } from '../../types'; +import { helpers } from '../../common'; import { reduxHelpers } from '../common/reduxHelpers'; /** @@ -9,14 +12,18 @@ import { reduxHelpers } from '../common/reduxHelpers'; * errorStatus: (string|number), error: boolean, locale: string}}} */ const initialState = { + optin: {}, session: { + admin: false, + authorized: false, + entitled: false, error: false, errorMessage: null, errorStatus: null, - pending: false, fulfilled: false, - authorized: false, - locale: null + locale: null, + pending: false, + permissions: [] } }; @@ -58,12 +65,38 @@ const userReducer = (state = initialState, action) => { ); case reduxHelpers.FULFILLED_ACTION(userTypes.USER_AUTH): + const { user, permissions } = reduxHelpers.getDataFromResults(action); + const admin = _get( + user, + [ + platformApiTypes.PLATFORM_API_RESPONSE_USER_IDENTITY, + platformApiTypes.PLATFORM_API_RESPONSE_USER_IDENTITY_TYPES.USER, + platformApiTypes.PLATFORM_API_RESPONSE_USER_IDENTITY_USER_TYPES.ORG_ADMIN + ], + false + ); + + const entitled = _get( + user, + [ + platformApiTypes.PLATFORM_API_RESPONSE_USER_ENTITLEMENTS, + helpers.UI_NAME, + platformApiTypes.PLATFORM_API_RESPONSE_USER_ENTITLEMENTS_APP_TYPES.ENTITLED + ], + false + ); + + const subscriptionPermissions = permissions.filter(value => new RegExp(helpers.UI_NAME, 'i').test(value)); + return reduxHelpers.setStateProp( 'session', { + admin, authorized: true, + entitled, fulfilled: true, - locale: state.session.locale + locale: state.session.locale, + permissions: subscriptionPermissions }, { state, @@ -88,6 +121,8 @@ const userReducer = (state = initialState, action) => { return reduxHelpers.setStateProp( 'session', { + admin: state.session.admin, + entitled: state.session.entitled, error: true, errorMessage: reduxHelpers.getMessageFromResults(action), errorStatus: reduxHelpers.getStatusFromResults(action), @@ -103,7 +138,15 @@ const userReducer = (state = initialState, action) => { return state; default: - return state; + return reduxHelpers.generatedPromiseActionReducer( + [ + { ref: 'optin', type: userTypes.DELETE_USER_OPTIN }, + { ref: 'optin', type: userTypes.GET_USER_OPTIN }, + { ref: 'optin', type: userTypes.UPDATE_USER_OPTIN } + ], + state, + action + ); } }; diff --git a/src/redux/types/__tests__/__snapshots__/index.test.js.snap b/src/redux/types/__tests__/__snapshots__/index.test.js.snap index 30e0eea16..29534f8a6 100644 --- a/src/redux/types/__tests__/__snapshots__/index.test.js.snap +++ b/src/redux/types/__tests__/__snapshots__/index.test.js.snap @@ -28,6 +28,9 @@ Object { "SET_GRAPH_SLA_RHSM": "SET_GRAPH_SLA_RHSM", }, "user": Object { + "DELETE_USER_OPTIN": "DELETE_USER_OPTIN", + "GET_USER_OPTIN": "GET_USER_OPTIN", + "UPDATE_USER_OPTIN": "UPDATE_USER_OPTIN", "USER_AUTH": "USER_AUTH", "USER_LOCALE": "USER_LOCALE", "USER_LOGOUT": "USER_LOGOUT", @@ -64,6 +67,9 @@ Object { "SET_GRAPH_SLA_RHSM": "SET_GRAPH_SLA_RHSM", }, "user": Object { + "DELETE_USER_OPTIN": "DELETE_USER_OPTIN", + "GET_USER_OPTIN": "GET_USER_OPTIN", + "UPDATE_USER_OPTIN": "UPDATE_USER_OPTIN", "USER_AUTH": "USER_AUTH", "USER_LOCALE": "USER_LOCALE", "USER_LOGOUT": "USER_LOGOUT", @@ -77,6 +83,9 @@ Object { "SET_GRAPH_SLA_RHSM": "SET_GRAPH_SLA_RHSM", }, "userTypes": Object { + "DELETE_USER_OPTIN": "DELETE_USER_OPTIN", + "GET_USER_OPTIN": "GET_USER_OPTIN", + "UPDATE_USER_OPTIN": "UPDATE_USER_OPTIN", "USER_AUTH": "USER_AUTH", "USER_LOCALE": "USER_LOCALE", "USER_LOGOUT": "USER_LOGOUT", @@ -107,6 +116,9 @@ Object { "SET_GRAPH_SLA_RHSM": "SET_GRAPH_SLA_RHSM", }, "user": Object { + "DELETE_USER_OPTIN": "DELETE_USER_OPTIN", + "GET_USER_OPTIN": "GET_USER_OPTIN", + "UPDATE_USER_OPTIN": "UPDATE_USER_OPTIN", "USER_AUTH": "USER_AUTH", "USER_LOCALE": "USER_LOCALE", "USER_LOGOUT": "USER_LOGOUT", diff --git a/src/redux/types/userTypes.js b/src/redux/types/userTypes.js index f671042bf..55d66e049 100644 --- a/src/redux/types/userTypes.js +++ b/src/redux/types/userTypes.js @@ -1,3 +1,6 @@ +const DELETE_USER_OPTIN = 'DELETE_USER_OPTIN'; +const GET_USER_OPTIN = 'GET_USER_OPTIN'; +const UPDATE_USER_OPTIN = 'UPDATE_USER_OPTIN'; const USER_AUTH = 'USER_AUTH'; const USER_LOCALE = 'USER_LOCALE'; const USER_LOGOUT = 'USER_LOGOUT'; @@ -7,6 +10,15 @@ const USER_LOGOUT = 'USER_LOGOUT'; * * @type {{USER_LOGOUT: string, USER_AUTH: string, USER_LOCALE: string}} */ -const userTypes = { USER_AUTH, USER_LOCALE, USER_LOGOUT }; +const userTypes = { DELETE_USER_OPTIN, GET_USER_OPTIN, UPDATE_USER_OPTIN, USER_AUTH, USER_LOCALE, USER_LOGOUT }; -export { userTypes as default, userTypes, USER_AUTH, USER_LOCALE, USER_LOGOUT }; +export { + userTypes as default, + userTypes, + DELETE_USER_OPTIN, + GET_USER_OPTIN, + UPDATE_USER_OPTIN, + USER_AUTH, + USER_LOCALE, + USER_LOGOUT +}; diff --git a/src/services/__tests__/__snapshots__/platformServices.test.js.snap b/src/services/__tests__/__snapshots__/platformServices.test.js.snap index 32920fdd3..89a73f9e5 100644 --- a/src/services/__tests__/__snapshots__/platformServices.test.js.snap +++ b/src/services/__tests__/__snapshots__/platformServices.test.js.snap @@ -2,6 +2,8 @@ exports[`PlatformServices should return a failed getUser: failed authorized user 1`] = `[Error: { getUser } = insights.chrome.auth, insights.chrome.auth.getUser is not a function]`; +exports[`PlatformServices should return a failed getUserPermissions: failed user permissions 1`] = `[Error: { getUserPermissions } = insights.chrome, insights.chrome.getUserPermissions is not a function]`; + exports[`PlatformServices should return a failed initializeChrome: failed initializeChrome 1`] = `[Error: { init } = insights.chrome, insights.chrome.init is not a function]`; exports[`PlatformServices should return a failed setAppName: failed setAppName 1`] = `"{ identifyApp } = insights.chrome, insights.chrome.identifyApp is not a function"`; diff --git a/src/services/__tests__/__snapshots__/userServices.test.js.snap b/src/services/__tests__/__snapshots__/userServices.test.js.snap index 6c0219fbf..589d6cd23 100644 --- a/src/services/__tests__/__snapshots__/userServices.test.js.snap +++ b/src/services/__tests__/__snapshots__/userServices.test.js.snap @@ -2,14 +2,14 @@ exports[`UserServices should return a failed authorized user on an unexpected response: failed authorized user: unexpected 1`] = ` Object { - "message": "{ getUser } = insights.chrome.auth", + "message": "{ auth.getUser, getUserPermissions } = insights.chrome", "status": 418, } `; exports[`UserServices should return a failed authorized user on empty response: failed authorized user: empty object 1`] = ` Object { - "message": "{ getUser } = insights.chrome.auth", + "message": "{ auth.getUser, getUserPermissions } = insights.chrome", "status": 418, } `; @@ -33,12 +33,15 @@ Object { exports[`UserServices should return a successful authorized user: success authorized user 1`] = ` Object { "data": Object { - "identity": Object { - "account_number": "0", - "type": "User", + "permissions": Array [], + "user": Object { + "identity": Object { + "account_number": "0", + "type": "User", + }, }, }, - "message": "{ getUser } = insights.chrome.auth", + "message": "{ auth.getUser, getUserPermissions } = insights.chrome", "status": 200, } `; diff --git a/src/services/__tests__/platformServices.test.js b/src/services/__tests__/platformServices.test.js index ed34f50ed..1ed9a69ed 100644 --- a/src/services/__tests__/platformServices.test.js +++ b/src/services/__tests__/platformServices.test.js @@ -2,11 +2,12 @@ import platformServices from '../platformServices'; describe('PlatformServices', () => { it('should export a specific number of methods and classes', () => { - expect(Object.keys(platformServices)).toHaveLength(5); + expect(Object.keys(platformServices)).toHaveLength(6); }); it('should have specific methods', () => { expect(platformServices.getUser).toBeDefined(); + expect(platformServices.getUserPermissions).toBeDefined(); expect(platformServices.initializeChrome).toBeDefined(); expect(platformServices.onNavigation).toBeDefined(); expect(platformServices.setAppName).toBeDefined(); @@ -51,6 +52,15 @@ describe('PlatformServices', () => { }); }); + it('should return a failed getUserPermissions', done => { + window.insights.chrome.getUserPermissions = undefined; + + platformServices.getUserPermissions().catch(error => { + expect(error).toMatchSnapshot('failed user permissions'); + done(); + }); + }); + it('should return a failed initializeChrome', done => { window.insights.chrome.init = undefined; diff --git a/src/services/__tests__/userServices.test.js b/src/services/__tests__/userServices.test.js index bc3716279..e70300cfd 100644 --- a/src/services/__tests__/userServices.test.js +++ b/src/services/__tests__/userServices.test.js @@ -1,15 +1,33 @@ import Cookies from 'js-cookie'; +import moxios from 'moxios'; import userServices from '../userServices'; describe('UserServices', () => { + beforeEach(() => { + moxios.install(); + + moxios.stubRequest(/\/(opt-in).*?/, { + status: 200, + responseText: 'success', + timeout: 1 + }); + }); + + afterEach(() => { + moxios.uninstall(); + }); + it('should export a specific number of methods and classes', () => { - expect(Object.keys(userServices)).toHaveLength(3); + expect(Object.keys(userServices)).toHaveLength(6); }); it('should have specific methods', () => { expect(userServices.authorizeUser).toBeDefined(); expect(userServices.getLocale).toBeDefined(); expect(userServices.logoutUser).toBeDefined(); + expect(userServices.deleteAccountOptIn).toBeDefined(); + expect(userServices.getAccountOptIn).toBeDefined(); + expect(userServices.updateAccountOptIn).toBeDefined(); }); /** diff --git a/src/services/platformServices.js b/src/services/platformServices.js index 886ad15c2..d2c276fc6 100644 --- a/src/services/platformServices.js +++ b/src/services/platformServices.js @@ -1,4 +1,6 @@ +import _set from 'lodash/set'; import { helpers } from '../common'; +import { platformApiTypes } from '../types'; /** * Basic user authentication. @@ -8,12 +10,38 @@ import { helpers } from '../common'; const getUser = async () => { const { insights } = window; try { - return (helpers.DEV_MODE && { test: {} }) || (await insights.chrome.auth.getUser()); + return ( + (helpers.DEV_MODE && + _set( + {}, + [ + platformApiTypes.PLATFORM_API_RESPONSE_USER_IDENTITY, + platformApiTypes.PLATFORM_API_RESPONSE_USER_IDENTITY_TYPES.USER, + platformApiTypes.PLATFORM_API_RESPONSE_USER_IDENTITY_USER_TYPES.ORG_ADMIN + ], + process.env.REACT_APP_DEBUG_ORG_ADMIN === 'true' + )) || + (await insights.chrome.auth.getUser()) + ); } catch (e) { throw new Error(`{ getUser } = insights.chrome.auth, ${e.message}`); } }; +/** + * Basic user permissions. + * + * @returns {Promise} + */ +const getUserPermissions = async () => { + const { insights } = window; + try { + await insights.chrome.getUserPermissions(); + } catch (e) { + throw new Error(`{ getUserPermissions } = insights.chrome, ${e.message}`); + } +}; + /** * Help initialize global platform methods. * @@ -60,6 +88,7 @@ const setAppName = async (name = null) => { } }; +// ToDo: Clean up, consider removing setNavigation, currently no longer used. /** * Set platform left hand navigation active item. * @@ -80,12 +109,13 @@ const setNavigation = (data = []) => { } }; -const platformServices = { getUser, initializeChrome, onNavigation, setAppName, setNavigation }; +const platformServices = { getUser, getUserPermissions, initializeChrome, onNavigation, setAppName, setNavigation }; export { platformServices as default, platformServices, getUser, + getUserPermissions, initializeChrome, onNavigation, setAppName, diff --git a/src/services/rhsmServices.js b/src/services/rhsmServices.js index 7c0becc40..136c2528d 100644 --- a/src/services/rhsmServices.js +++ b/src/services/rhsmServices.js @@ -18,8 +18,8 @@ import { serviceCall } from './config'; * "gitHash": "0000000000000000" * } * - * @apiError {String} detail - * @apiErrorExample {text} Error-Response: + * @apiError {Array} errors + * @apiErrorExample {json} Error-Response: * HTTP/1.1 500 Internal Server Error * { * "errors": [ @@ -394,7 +394,7 @@ const getApiVersion = () => * } * } * - * @apiError {String} detail + * @apiError {Array} errors * @apiErrorExample {json} Error-Response: * HTTP/1.1 400 Bad Request * { @@ -407,8 +407,8 @@ const getApiVersion = () => * } * ] * } - * @apiError {String} detail - * @apiErrorExample {text} Error-Response: + * @apiError {Array} errors + * @apiErrorExample {json} Error-Response: * HTTP/1.1 404 Internal Server Error * { * "errors": [ @@ -420,8 +420,8 @@ const getApiVersion = () => * } * ] * } - * @apiError {String} detail - * @apiErrorExample {text} Error-Response: + * @apiError {Array} errors + * @apiErrorExample {json} Error-Response: * HTTP/1.1 500 Internal Server Error * { * "errors": [ @@ -563,7 +563,7 @@ const getGraphReports = (id, params = {}) => * } * } * - * @apiError {String} detail + * @apiError {Array} errors * @apiErrorExample {json} Error-Response: * HTTP/1.1 400 Bad Request * { @@ -576,8 +576,8 @@ const getGraphReports = (id, params = {}) => * } * ] * } - * @apiError {String} detail - * @apiErrorExample {text} Error-Response: + * @apiError {Array} errors + * @apiErrorExample {json} Error-Response: * HTTP/1.1 404 Internal Server Error * { * "errors": [ @@ -589,8 +589,8 @@ const getGraphReports = (id, params = {}) => * } * ] * } - * @apiError {String} detail - * @apiErrorExample {text} Error-Response: + * @apiError {Array} errors + * @apiErrorExample {json} Error-Response: * HTTP/1.1 500 Internal Server Error * { * "errors": [ diff --git a/src/services/userServices.js b/src/services/userServices.js index 6b377943f..025a0a4c4 100644 --- a/src/services/userServices.js +++ b/src/services/userServices.js @@ -1,25 +1,28 @@ import Cookies from 'js-cookie'; import LocaleCode from 'locale-code'; import _isPlainObject from 'lodash/isPlainObject'; -import { getUser } from './platformServices'; +import { getUser, getUserPermissions } from './platformServices'; +import { serviceCall } from './config'; /** * Apply an emulated API response to the platforms getUser method. * - * @returns {Promise<{data: void, message: string, status: number}>} + * @returns {Promise<{data: {permissions: (void|*[]), user: void}, message: string, status: number}>} */ const authorizeUser = async () => { - let message = '{ getUser } = insights.chrome.auth'; + let message = '{ auth.getUser, getUserPermissions } = insights.chrome'; let userData; + let userPermissions; try { userData = await getUser(); + userPermissions = await getUserPermissions(); } catch (e) { message = e.message; } if (_isPlainObject(userData) && Object.keys(userData).length) { - return Promise.resolve({ data: userData, message, status: 200 }); + return Promise.resolve({ data: { user: userData, permissions: userPermissions || [] }, message, status: 200 }); } const emulatedErrorResponse = { @@ -67,6 +70,213 @@ const logoutUser = () => resolve({}); }); -const userServices = { authorizeUser, getLocale, logoutUser }; +/** + * @apiMock {DelayResponse} 2000 + * @api {delete} /api/rhsm-subscriptions/v1/opt-in + * @apiDescription Delete a RHSM account opt-in config + * + * Reference [RHSM API](https://github.com/RedHatInsights/rhsm-subscriptions/blob/master/api/rhsm-subscriptions-api-spec.yaml) + * + * @apiSuccessExample {text} Success-Response: + * HTTP/1.1 204 OK + * + * @apiError {Array} errors + * @apiErrorExample {json} Error-Response: + * HTTP/1.1 400 Bad Request + * { + * "errors": [ + * { + * "status": "string", + * "code": "string", + * "title": "string", + * "detail": "string" + * } + * ] + * } + * + * @apiError {Array} errors + * @apiErrorExample {json} Error-Response: + * HTTP/1.1 403 Forbidden + * { + * "errors": [ + * { + * "status": "string", + * "code": "string", + * "title": "string", + * "detail": "string" + * } + * ] + * } + * + * @apiError {Array} errors + * @apiErrorExample {json} Error-Response: + * HTTP/1.1 404 Not Found + * { + * "errors": [ + * { + * "status": "string", + * "code": "string", + * "title": "string", + * "detail": "string" + * } + * ] + * } + * + * @apiError {Array} errors + * @apiErrorExample {json} Error-Response: + * HTTP/1.1 500 Internal Server Error + * { + * "errors": [ + * { + * "status": "string", + * "code": "string", + * "title": "string", + * "detail": "string" + * } + * ] + * } + */ +/** + * Delete a RHSM account opt-in config. + * + * @returns {Promise<*>} + */ +const deleteAccountOptIn = () => + serviceCall({ + method: 'delete', + url: process.env.REACT_APP_SERVICES_RHSM_OPTIN + }); + +/** + * @api {get} /api/rhsm-subscriptions/v1/opt-in + * @apiDescription Get a RHSM account opt-in config + * + * Reference [RHSM API](https://github.com/RedHatInsights/rhsm-subscriptions/blob/master/api/rhsm-subscriptions-api-spec.yaml) + * + * @apiSuccessExample {json} Success-Response: + * HTTP/1.1 200 OK + * { + * "data": { + * "opt_in_complete": true, + * "account": { + * "account_numner": 12345, + * "tally_sync_enabled": true, + * "tally_reporting_enabled": true, + * "opt_in_type": "API", + * "created": "2017-08-04T17:32:05Z", + * "last_updated": "2017-08-04T17:32:05Z" + * }, + * "org": { + * "org_id": 1111, + * "conduit_sync_enabled": true, + * "opt_in_type": "API", + * "created": "2017-08-04T17:32:05Z", + * "last_updated": "2017-08-04T17:32:05Z" + * } + * }, + * "meta": { + * "account_number": 12345, + * "org_id": 1111 + * } + * } + * + * @apiError {Array} errors + * @apiErrorExample {json} Error-Response: + * HTTP/1.1 500 Internal Server Error + * { + * "errors": [ + * { + * "status": "string", + * "code": "string", + * "title": "string", + * "detail": "string" + * } + * ] + * } + */ +/** + * Get a RHSM account opt-in config. + * + * @returns {Promise<*>} + */ +const getAccountOptIn = () => + serviceCall({ + url: process.env.REACT_APP_SERVICES_RHSM_OPTIN, + cancel: true + }); -export { userServices as default, userServices, authorizeUser, getLocale, logoutUser }; +/** + * @apiMock {DelayResponse} 1000 + * @apiMock {ForceStatus} 200 + * @api {put} /api/rhsm-subscriptions/v1/opt-in + * @apiDescription Create/Update an account's opt-in configuration. Account and Org ID are defined by + * the identity header. If no parameters are specified, everything will be enabled. + * + * Reference [RHSM API](https://github.com/RedHatInsights/rhsm-subscriptions/blob/master/api/rhsm-subscriptions-api-spec.yaml) + * + * @apiSuccessExample {json} Success-Response: + * HTTP/1.1 200 OK + * { + * "data": { + * "opt_in_complete": true, + * "account": { + * "account_numner": 12345, + * "tally_sync_enabled": true, + * "tally_reporting_enabled": true, + * "opt_in_type": "API", + * "created": "2017-08-04T17:32:05Z", + * "last_updated": "2017-08-04T17:32:05Z" + * }, + * "org": { + * "org_id": 1111, + * "conduit_sync_enabled": true, + * "opt_in_type": "API", + * "created": "2017-08-04T17:32:05Z", + * "last_updated": "2017-08-04T17:32:05Z" + * } + * }, + * "meta": { + * "account_number": 12345, + * "org_id": 1111 + * } + * } + * + * @apiError {Array} errors + * @apiErrorExample {json} Error-Response: + * HTTP/1.1 500 Internal Server Error + * { + * "errors": [ + * { + * "status": "string", + * "code": "string", + * "title": "string", + * "detail": "string" + * } + * ] + * } + */ +/** + * Update a RHSM account opt-in config. + * + * @param {object} params Query/search params + * @returns {Promise<*>} + */ +const updateAccountOptIn = (params = {}) => + serviceCall({ + method: 'put', + url: process.env.REACT_APP_SERVICES_RHSM_OPTIN, + params + }); + +const userServices = { authorizeUser, getLocale, logoutUser, deleteAccountOptIn, getAccountOptIn, updateAccountOptIn }; + +export { + userServices as default, + userServices, + authorizeUser, + getLocale, + logoutUser, + deleteAccountOptIn, + getAccountOptIn, + updateAccountOptIn +}; diff --git a/src/setupTests.js b/src/setupTests.js index 6df9401b5..1edf03022 100644 --- a/src/setupTests.js +++ b/src/setupTests.js @@ -16,6 +16,7 @@ global.window.insights = { }) ) }, + getUserPermissions: Function.prototype, identifyApp: Function.prototype, init: Function.prototype, navigation: Function.prototype, diff --git a/src/styles/_optin.scss b/src/styles/_optin.scss new file mode 100644 index 000000000..77b467812 --- /dev/null +++ b/src/styles/_optin.scss @@ -0,0 +1,22 @@ +.curiosity { + .curiosity-optin-form { + .pf-c-form__label { + font-size: inherit; + line-height: inherit; + } + + .pf-c-form__label-text { + font-weight: inherit; + } + + .pf-c-check { + margin-left: var(--pf-global--spacer--md); + } + } + + .curiosity-optin-tour { + text-align: center; + } + + .curiosity-optin-image {} +} diff --git a/src/styles/_skeleton.scss b/src/styles/_skeleton.scss new file mode 100644 index 000000000..58f9ee017 --- /dev/null +++ b/src/styles/_skeleton.scss @@ -0,0 +1,13 @@ +.curiosity { + .curiosity-skeleton-container { + padding-top: var(--pf-c-card--child--PaddingBottom); + } + + .curiosity-skeleton-container .ins-c-skeleton { + margin-bottom: 20px; + + &:last-child { + margin-bottom: 0; + } + } +} diff --git a/src/styles/_usage-graph.scss b/src/styles/_usage-graph.scss index 0218b1cde..3a82663c2 100644 --- a/src/styles/_usage-graph.scss +++ b/src/styles/_usage-graph.scss @@ -3,17 +3,5 @@ .pf-c-card__head { border-bottom: var(--pf-global--BorderWidth--sm) solid var(--pf-global--BorderColor--100); } - - .curiosity-skeleton-container { - padding-top: var(--pf-c-card--child--PaddingBottom); - } - - .curiosity-skeleton-container .ins-c-skeleton { - margin-bottom: 20px; - - &:last-child { - margin-bottom: 0; - } - } } } diff --git a/src/styles/index.scss b/src/styles/index.scss index 1a3f0c1e8..f4afbea25 100644 --- a/src/styles/index.scss +++ b/src/styles/index.scss @@ -7,5 +7,7 @@ // App @import 'app'; @import 'common'; +@import 'optin'; @import 'usage-graph'; @import 'tour'; +@import 'skeleton'; diff --git a/src/types/__tests__/__snapshots__/index.test.js.snap b/src/types/__tests__/__snapshots__/index.test.js.snap new file mode 100644 index 000000000..0d8311bfe --- /dev/null +++ b/src/types/__tests__/__snapshots__/index.test.js.snap @@ -0,0 +1,351 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`ApiTypes should have specific API properties: all exported api types 1`] = ` +Object { + "apiTypes": Object { + "platformApi": Object { + "PLATFORM_API_RESPONSE_USER_ENTITLEMENTS": "entitlements", + "PLATFORM_API_RESPONSE_USER_ENTITLEMENTS_APP_TYPES": Object { + "ENTITLED": "is_entitled", + }, + "PLATFORM_API_RESPONSE_USER_IDENTITY": "identity", + "PLATFORM_API_RESPONSE_USER_IDENTITY_TYPES": Object { + "USER": "user", + }, + "PLATFORM_API_RESPONSE_USER_IDENTITY_USER_TYPES": Object { + "ORG_ADMIN": "is_org_admin", + }, + }, + "rhsmApi": Object { + "RHSM_API_PATH_ID_TYPES": Object { + "OPENSHIFT": "OpenShift Container Platform", + "RHEL": "RHEL", + "RHEL_ARM": "RHEL for ARM", + "RHEL_COMPUTE_NODE": "RHEL Compute Node", + "RHEL_DESKTOP": "RHEL Desktop", + "RHEL_IBM_POWER": "RHEL for IBM Power", + "RHEL_IBM_Z": "RHEL for IBM z", + "RHEL_SERVER": "RHEL Server", + "RHEL_WORKSTATION": "RHEL Workstation", + "RHEL_X86": "RHEL for x86", + }, + "RHSM_API_QUERY_END_DATE": "ending", + "RHSM_API_QUERY_GRANULARITY": "granularity", + "RHSM_API_QUERY_GRANULARITY_TYPES": Object { + "DAILY": "daily", + "MONTHLY": "monthly", + "QUARTERLY": "quarterly", + "WEEKLY": "weekly", + }, + "RHSM_API_QUERY_LIMIT": "limit", + "RHSM_API_QUERY_OFFSET": "offset", + "RHSM_API_QUERY_OPTIN_CONDUIT_SYNC": "enable_conduit_sync", + "RHSM_API_QUERY_OPTIN_TALLY_REPORT": "enable_tally_reporting", + "RHSM_API_QUERY_OPTIN_TALLY_SYNC": "enable_tally_sync", + "RHSM_API_QUERY_SLA": "sla", + "RHSM_API_QUERY_SLA_TYPES": Object { + "NONE": "", + "PREMIUM": "premium", + "SELF": "self-support", + "STANDARD": "standard", + }, + "RHSM_API_QUERY_START_DATE": "beginning", + "RHSM_API_RESPONSE_CAPACITY_DATA": "data", + "RHSM_API_RESPONSE_CAPACITY_DATA_TYPES": Object { + "CLOUD_CORES": "cloud_cores", + "CLOUD_INSTANCES": "cloud_instance_count", + "CLOUD_SOCKETS": "cloud_sockets", + "CORES": "cores", + "DATE": "date", + "HAS_INFINITE": "has_infinite_quantity", + "HYPERVISOR_CORES": "hypervisor_cores", + "HYPERVISOR_SOCKETS": "hypervisor_sockets", + "PHYSICAL_CORES": "physical_cores", + "PHYSICAL_SOCKETS": "physical_sockets", + "SOCKETS": "sockets", + }, + "RHSM_API_RESPONSE_CAPACITY_META": "meta", + "RHSM_API_RESPONSE_CAPACITY_META_TYPES": Object { + "COUNT": "count", + }, + "RHSM_API_RESPONSE_PRODUCTS_DATA": "data", + "RHSM_API_RESPONSE_PRODUCTS_DATA_TYPES": Object { + "CLOUD_CORES": "cloud_cores", + "CLOUD_INSTANCES": "cloud_instance_count", + "CLOUD_SOCKETS": "cloud_sockets", + "CORES": "cores", + "DATE": "date", + "HAS_DATA": "has_data", + "HYPERVISOR_CORES": "hypervisor_cores", + "HYPERVISOR_SOCKETS": "hypervisor_sockets", + "PHYSICAL_CORES": "physical_cores", + "PHYSICAL_SOCKETS": "physical_sockets", + "SOCKETS": "sockets", + }, + "RHSM_API_RESPONSE_PRODUCTS_META": "meta", + "RHSM_API_RESPONSE_PRODUCTS_META_TYPES": Object { + "COUNT": "count", + }, + }, + }, + "default": Object { + "platformApi": Object { + "PLATFORM_API_RESPONSE_USER_ENTITLEMENTS": "entitlements", + "PLATFORM_API_RESPONSE_USER_ENTITLEMENTS_APP_TYPES": Object { + "ENTITLED": "is_entitled", + }, + "PLATFORM_API_RESPONSE_USER_IDENTITY": "identity", + "PLATFORM_API_RESPONSE_USER_IDENTITY_TYPES": Object { + "USER": "user", + }, + "PLATFORM_API_RESPONSE_USER_IDENTITY_USER_TYPES": Object { + "ORG_ADMIN": "is_org_admin", + }, + }, + "rhsmApi": Object { + "RHSM_API_PATH_ID_TYPES": Object { + "OPENSHIFT": "OpenShift Container Platform", + "RHEL": "RHEL", + "RHEL_ARM": "RHEL for ARM", + "RHEL_COMPUTE_NODE": "RHEL Compute Node", + "RHEL_DESKTOP": "RHEL Desktop", + "RHEL_IBM_POWER": "RHEL for IBM Power", + "RHEL_IBM_Z": "RHEL for IBM z", + "RHEL_SERVER": "RHEL Server", + "RHEL_WORKSTATION": "RHEL Workstation", + "RHEL_X86": "RHEL for x86", + }, + "RHSM_API_QUERY_END_DATE": "ending", + "RHSM_API_QUERY_GRANULARITY": "granularity", + "RHSM_API_QUERY_GRANULARITY_TYPES": Object { + "DAILY": "daily", + "MONTHLY": "monthly", + "QUARTERLY": "quarterly", + "WEEKLY": "weekly", + }, + "RHSM_API_QUERY_LIMIT": "limit", + "RHSM_API_QUERY_OFFSET": "offset", + "RHSM_API_QUERY_OPTIN_CONDUIT_SYNC": "enable_conduit_sync", + "RHSM_API_QUERY_OPTIN_TALLY_REPORT": "enable_tally_reporting", + "RHSM_API_QUERY_OPTIN_TALLY_SYNC": "enable_tally_sync", + "RHSM_API_QUERY_SLA": "sla", + "RHSM_API_QUERY_SLA_TYPES": Object { + "NONE": "", + "PREMIUM": "premium", + "SELF": "self-support", + "STANDARD": "standard", + }, + "RHSM_API_QUERY_START_DATE": "beginning", + "RHSM_API_RESPONSE_CAPACITY_DATA": "data", + "RHSM_API_RESPONSE_CAPACITY_DATA_TYPES": Object { + "CLOUD_CORES": "cloud_cores", + "CLOUD_INSTANCES": "cloud_instance_count", + "CLOUD_SOCKETS": "cloud_sockets", + "CORES": "cores", + "DATE": "date", + "HAS_INFINITE": "has_infinite_quantity", + "HYPERVISOR_CORES": "hypervisor_cores", + "HYPERVISOR_SOCKETS": "hypervisor_sockets", + "PHYSICAL_CORES": "physical_cores", + "PHYSICAL_SOCKETS": "physical_sockets", + "SOCKETS": "sockets", + }, + "RHSM_API_RESPONSE_CAPACITY_META": "meta", + "RHSM_API_RESPONSE_CAPACITY_META_TYPES": Object { + "COUNT": "count", + }, + "RHSM_API_RESPONSE_PRODUCTS_DATA": "data", + "RHSM_API_RESPONSE_PRODUCTS_DATA_TYPES": Object { + "CLOUD_CORES": "cloud_cores", + "CLOUD_INSTANCES": "cloud_instance_count", + "CLOUD_SOCKETS": "cloud_sockets", + "CORES": "cores", + "DATE": "date", + "HAS_DATA": "has_data", + "HYPERVISOR_CORES": "hypervisor_cores", + "HYPERVISOR_SOCKETS": "hypervisor_sockets", + "PHYSICAL_CORES": "physical_cores", + "PHYSICAL_SOCKETS": "physical_sockets", + "SOCKETS": "sockets", + }, + "RHSM_API_RESPONSE_PRODUCTS_META": "meta", + "RHSM_API_RESPONSE_PRODUCTS_META_TYPES": Object { + "COUNT": "count", + }, + }, + }, + "platformApiTypes": Object { + "PLATFORM_API_RESPONSE_USER_ENTITLEMENTS": "entitlements", + "PLATFORM_API_RESPONSE_USER_ENTITLEMENTS_APP_TYPES": Object { + "ENTITLED": "is_entitled", + }, + "PLATFORM_API_RESPONSE_USER_IDENTITY": "identity", + "PLATFORM_API_RESPONSE_USER_IDENTITY_TYPES": Object { + "USER": "user", + }, + "PLATFORM_API_RESPONSE_USER_IDENTITY_USER_TYPES": Object { + "ORG_ADMIN": "is_org_admin", + }, + }, + "rhsmApiTypes": Object { + "RHSM_API_PATH_ID_TYPES": Object { + "OPENSHIFT": "OpenShift Container Platform", + "RHEL": "RHEL", + "RHEL_ARM": "RHEL for ARM", + "RHEL_COMPUTE_NODE": "RHEL Compute Node", + "RHEL_DESKTOP": "RHEL Desktop", + "RHEL_IBM_POWER": "RHEL for IBM Power", + "RHEL_IBM_Z": "RHEL for IBM z", + "RHEL_SERVER": "RHEL Server", + "RHEL_WORKSTATION": "RHEL Workstation", + "RHEL_X86": "RHEL for x86", + }, + "RHSM_API_QUERY_END_DATE": "ending", + "RHSM_API_QUERY_GRANULARITY": "granularity", + "RHSM_API_QUERY_GRANULARITY_TYPES": Object { + "DAILY": "daily", + "MONTHLY": "monthly", + "QUARTERLY": "quarterly", + "WEEKLY": "weekly", + }, + "RHSM_API_QUERY_LIMIT": "limit", + "RHSM_API_QUERY_OFFSET": "offset", + "RHSM_API_QUERY_OPTIN_CONDUIT_SYNC": "enable_conduit_sync", + "RHSM_API_QUERY_OPTIN_TALLY_REPORT": "enable_tally_reporting", + "RHSM_API_QUERY_OPTIN_TALLY_SYNC": "enable_tally_sync", + "RHSM_API_QUERY_SLA": "sla", + "RHSM_API_QUERY_SLA_TYPES": Object { + "NONE": "", + "PREMIUM": "premium", + "SELF": "self-support", + "STANDARD": "standard", + }, + "RHSM_API_QUERY_START_DATE": "beginning", + "RHSM_API_RESPONSE_CAPACITY_DATA": "data", + "RHSM_API_RESPONSE_CAPACITY_DATA_TYPES": Object { + "CLOUD_CORES": "cloud_cores", + "CLOUD_INSTANCES": "cloud_instance_count", + "CLOUD_SOCKETS": "cloud_sockets", + "CORES": "cores", + "DATE": "date", + "HAS_INFINITE": "has_infinite_quantity", + "HYPERVISOR_CORES": "hypervisor_cores", + "HYPERVISOR_SOCKETS": "hypervisor_sockets", + "PHYSICAL_CORES": "physical_cores", + "PHYSICAL_SOCKETS": "physical_sockets", + "SOCKETS": "sockets", + }, + "RHSM_API_RESPONSE_CAPACITY_META": "meta", + "RHSM_API_RESPONSE_CAPACITY_META_TYPES": Object { + "COUNT": "count", + }, + "RHSM_API_RESPONSE_PRODUCTS_DATA": "data", + "RHSM_API_RESPONSE_PRODUCTS_DATA_TYPES": Object { + "CLOUD_CORES": "cloud_cores", + "CLOUD_INSTANCES": "cloud_instance_count", + "CLOUD_SOCKETS": "cloud_sockets", + "CORES": "cores", + "DATE": "date", + "HAS_DATA": "has_data", + "HYPERVISOR_CORES": "hypervisor_cores", + "HYPERVISOR_SOCKETS": "hypervisor_sockets", + "PHYSICAL_CORES": "physical_cores", + "PHYSICAL_SOCKETS": "physical_sockets", + "SOCKETS": "sockets", + }, + "RHSM_API_RESPONSE_PRODUCTS_META": "meta", + "RHSM_API_RESPONSE_PRODUCTS_META_TYPES": Object { + "COUNT": "count", + }, + }, +} +`; + +exports[`ApiTypes should have specific API properties: specific types 1`] = ` +Object { + "platformApi": Object { + "PLATFORM_API_RESPONSE_USER_ENTITLEMENTS": "entitlements", + "PLATFORM_API_RESPONSE_USER_ENTITLEMENTS_APP_TYPES": Object { + "ENTITLED": "is_entitled", + }, + "PLATFORM_API_RESPONSE_USER_IDENTITY": "identity", + "PLATFORM_API_RESPONSE_USER_IDENTITY_TYPES": Object { + "USER": "user", + }, + "PLATFORM_API_RESPONSE_USER_IDENTITY_USER_TYPES": Object { + "ORG_ADMIN": "is_org_admin", + }, + }, + "rhsmApi": Object { + "RHSM_API_PATH_ID_TYPES": Object { + "OPENSHIFT": "OpenShift Container Platform", + "RHEL": "RHEL", + "RHEL_ARM": "RHEL for ARM", + "RHEL_COMPUTE_NODE": "RHEL Compute Node", + "RHEL_DESKTOP": "RHEL Desktop", + "RHEL_IBM_POWER": "RHEL for IBM Power", + "RHEL_IBM_Z": "RHEL for IBM z", + "RHEL_SERVER": "RHEL Server", + "RHEL_WORKSTATION": "RHEL Workstation", + "RHEL_X86": "RHEL for x86", + }, + "RHSM_API_QUERY_END_DATE": "ending", + "RHSM_API_QUERY_GRANULARITY": "granularity", + "RHSM_API_QUERY_GRANULARITY_TYPES": Object { + "DAILY": "daily", + "MONTHLY": "monthly", + "QUARTERLY": "quarterly", + "WEEKLY": "weekly", + }, + "RHSM_API_QUERY_LIMIT": "limit", + "RHSM_API_QUERY_OFFSET": "offset", + "RHSM_API_QUERY_OPTIN_CONDUIT_SYNC": "enable_conduit_sync", + "RHSM_API_QUERY_OPTIN_TALLY_REPORT": "enable_tally_reporting", + "RHSM_API_QUERY_OPTIN_TALLY_SYNC": "enable_tally_sync", + "RHSM_API_QUERY_SLA": "sla", + "RHSM_API_QUERY_SLA_TYPES": Object { + "NONE": "", + "PREMIUM": "premium", + "SELF": "self-support", + "STANDARD": "standard", + }, + "RHSM_API_QUERY_START_DATE": "beginning", + "RHSM_API_RESPONSE_CAPACITY_DATA": "data", + "RHSM_API_RESPONSE_CAPACITY_DATA_TYPES": Object { + "CLOUD_CORES": "cloud_cores", + "CLOUD_INSTANCES": "cloud_instance_count", + "CLOUD_SOCKETS": "cloud_sockets", + "CORES": "cores", + "DATE": "date", + "HAS_INFINITE": "has_infinite_quantity", + "HYPERVISOR_CORES": "hypervisor_cores", + "HYPERVISOR_SOCKETS": "hypervisor_sockets", + "PHYSICAL_CORES": "physical_cores", + "PHYSICAL_SOCKETS": "physical_sockets", + "SOCKETS": "sockets", + }, + "RHSM_API_RESPONSE_CAPACITY_META": "meta", + "RHSM_API_RESPONSE_CAPACITY_META_TYPES": Object { + "COUNT": "count", + }, + "RHSM_API_RESPONSE_PRODUCTS_DATA": "data", + "RHSM_API_RESPONSE_PRODUCTS_DATA_TYPES": Object { + "CLOUD_CORES": "cloud_cores", + "CLOUD_INSTANCES": "cloud_instance_count", + "CLOUD_SOCKETS": "cloud_sockets", + "CORES": "cores", + "DATE": "date", + "HAS_DATA": "has_data", + "HYPERVISOR_CORES": "hypervisor_cores", + "HYPERVISOR_SOCKETS": "hypervisor_sockets", + "PHYSICAL_CORES": "physical_cores", + "PHYSICAL_SOCKETS": "physical_sockets", + "SOCKETS": "sockets", + }, + "RHSM_API_RESPONSE_PRODUCTS_META": "meta", + "RHSM_API_RESPONSE_PRODUCTS_META_TYPES": Object { + "COUNT": "count", + }, + }, +} +`; diff --git a/src/types/__tests__/__snapshots__/rhsmApiTypes.test.js.snap b/src/types/__tests__/__snapshots__/rhsmApiTypes.test.js.snap deleted file mode 100644 index 0b8f954e7..000000000 --- a/src/types/__tests__/__snapshots__/rhsmApiTypes.test.js.snap +++ /dev/null @@ -1,279 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`RhsmApiTypes Should have specific API properties: all exported api types 1`] = ` -Object { - "RHSM_API_PATH_ID_TYPES": Object { - "OPENSHIFT": "OpenShift Container Platform", - "RHEL": "RHEL", - "RHEL_ARM": "RHEL for ARM", - "RHEL_COMPUTE_NODE": "RHEL Compute Node", - "RHEL_DESKTOP": "RHEL Desktop", - "RHEL_IBM_POWER": "RHEL for IBM Power", - "RHEL_IBM_Z": "RHEL for IBM z", - "RHEL_SERVER": "RHEL Server", - "RHEL_WORKSTATION": "RHEL Workstation", - "RHEL_X86": "RHEL for x86", - }, - "RHSM_API_QUERY_END_DATE": "ending", - "RHSM_API_QUERY_GRANULARITY": "granularity", - "RHSM_API_QUERY_GRANULARITY_TYPES": Object { - "DAILY": "daily", - "MONTHLY": "monthly", - "QUARTERLY": "quarterly", - "WEEKLY": "weekly", - }, - "RHSM_API_QUERY_LIMIT": "limit", - "RHSM_API_QUERY_OFFSET": "offset", - "RHSM_API_QUERY_SLA": "sla", - "RHSM_API_QUERY_SLA_TYPES": Object { - "NONE": "", - "PREMIUM": "premium", - "SELF": "self-support", - "STANDARD": "standard", - }, - "RHSM_API_QUERY_START_DATE": "beginning", - "RHSM_API_RESPONSE_CAPACITY_DATA": "data", - "RHSM_API_RESPONSE_CAPACITY_DATA_TYPES": Object { - "CLOUD_CORES": "cloud_cores", - "CLOUD_INSTANCES": "cloud_instance_count", - "CLOUD_SOCKETS": "cloud_sockets", - "CORES": "cores", - "DATE": "date", - "HAS_INFINITE": "has_infinite_quantity", - "HYPERVISOR_CORES": "hypervisor_cores", - "HYPERVISOR_SOCKETS": "hypervisor_sockets", - "PHYSICAL_CORES": "physical_cores", - "PHYSICAL_SOCKETS": "physical_sockets", - "SOCKETS": "sockets", - }, - "RHSM_API_RESPONSE_CAPACITY_META": "meta", - "RHSM_API_RESPONSE_CAPACITY_META_TYPES": Object { - "COUNT": "count", - }, - "RHSM_API_RESPONSE_PRODUCTS_DATA": "data", - "RHSM_API_RESPONSE_PRODUCTS_DATA_TYPES": Object { - "CLOUD_CORES": "cloud_cores", - "CLOUD_INSTANCES": "cloud_instance_count", - "CLOUD_SOCKETS": "cloud_sockets", - "CORES": "cores", - "DATE": "date", - "HAS_DATA": "has_data", - "HYPERVISOR_CORES": "hypervisor_cores", - "HYPERVISOR_SOCKETS": "hypervisor_sockets", - "PHYSICAL_CORES": "physical_cores", - "PHYSICAL_SOCKETS": "physical_sockets", - "SOCKETS": "sockets", - }, - "RHSM_API_RESPONSE_PRODUCTS_META": "meta", - "RHSM_API_RESPONSE_PRODUCTS_META_TYPES": Object { - "COUNT": "count", - }, - "default": Object { - "RHSM_API_PATH_ID_TYPES": Object { - "OPENSHIFT": "OpenShift Container Platform", - "RHEL": "RHEL", - "RHEL_ARM": "RHEL for ARM", - "RHEL_COMPUTE_NODE": "RHEL Compute Node", - "RHEL_DESKTOP": "RHEL Desktop", - "RHEL_IBM_POWER": "RHEL for IBM Power", - "RHEL_IBM_Z": "RHEL for IBM z", - "RHEL_SERVER": "RHEL Server", - "RHEL_WORKSTATION": "RHEL Workstation", - "RHEL_X86": "RHEL for x86", - }, - "RHSM_API_QUERY_END_DATE": "ending", - "RHSM_API_QUERY_GRANULARITY": "granularity", - "RHSM_API_QUERY_GRANULARITY_TYPES": Object { - "DAILY": "daily", - "MONTHLY": "monthly", - "QUARTERLY": "quarterly", - "WEEKLY": "weekly", - }, - "RHSM_API_QUERY_LIMIT": "limit", - "RHSM_API_QUERY_OFFSET": "offset", - "RHSM_API_QUERY_SLA": "sla", - "RHSM_API_QUERY_SLA_TYPES": Object { - "NONE": "", - "PREMIUM": "premium", - "SELF": "self-support", - "STANDARD": "standard", - }, - "RHSM_API_QUERY_START_DATE": "beginning", - "RHSM_API_RESPONSE_CAPACITY_DATA": "data", - "RHSM_API_RESPONSE_CAPACITY_DATA_TYPES": Object { - "CLOUD_CORES": "cloud_cores", - "CLOUD_INSTANCES": "cloud_instance_count", - "CLOUD_SOCKETS": "cloud_sockets", - "CORES": "cores", - "DATE": "date", - "HAS_INFINITE": "has_infinite_quantity", - "HYPERVISOR_CORES": "hypervisor_cores", - "HYPERVISOR_SOCKETS": "hypervisor_sockets", - "PHYSICAL_CORES": "physical_cores", - "PHYSICAL_SOCKETS": "physical_sockets", - "SOCKETS": "sockets", - }, - "RHSM_API_RESPONSE_CAPACITY_META": "meta", - "RHSM_API_RESPONSE_CAPACITY_META_TYPES": Object { - "COUNT": "count", - }, - "RHSM_API_RESPONSE_PRODUCTS_DATA": "data", - "RHSM_API_RESPONSE_PRODUCTS_DATA_TYPES": Object { - "CLOUD_CORES": "cloud_cores", - "CLOUD_INSTANCES": "cloud_instance_count", - "CLOUD_SOCKETS": "cloud_sockets", - "CORES": "cores", - "DATE": "date", - "HAS_DATA": "has_data", - "HYPERVISOR_CORES": "hypervisor_cores", - "HYPERVISOR_SOCKETS": "hypervisor_sockets", - "PHYSICAL_CORES": "physical_cores", - "PHYSICAL_SOCKETS": "physical_sockets", - "SOCKETS": "sockets", - }, - "RHSM_API_RESPONSE_PRODUCTS_META": "meta", - "RHSM_API_RESPONSE_PRODUCTS_META_TYPES": Object { - "COUNT": "count", - }, - }, - "rhsmApiTypes": Object { - "RHSM_API_PATH_ID_TYPES": Object { - "OPENSHIFT": "OpenShift Container Platform", - "RHEL": "RHEL", - "RHEL_ARM": "RHEL for ARM", - "RHEL_COMPUTE_NODE": "RHEL Compute Node", - "RHEL_DESKTOP": "RHEL Desktop", - "RHEL_IBM_POWER": "RHEL for IBM Power", - "RHEL_IBM_Z": "RHEL for IBM z", - "RHEL_SERVER": "RHEL Server", - "RHEL_WORKSTATION": "RHEL Workstation", - "RHEL_X86": "RHEL for x86", - }, - "RHSM_API_QUERY_END_DATE": "ending", - "RHSM_API_QUERY_GRANULARITY": "granularity", - "RHSM_API_QUERY_GRANULARITY_TYPES": Object { - "DAILY": "daily", - "MONTHLY": "monthly", - "QUARTERLY": "quarterly", - "WEEKLY": "weekly", - }, - "RHSM_API_QUERY_LIMIT": "limit", - "RHSM_API_QUERY_OFFSET": "offset", - "RHSM_API_QUERY_SLA": "sla", - "RHSM_API_QUERY_SLA_TYPES": Object { - "NONE": "", - "PREMIUM": "premium", - "SELF": "self-support", - "STANDARD": "standard", - }, - "RHSM_API_QUERY_START_DATE": "beginning", - "RHSM_API_RESPONSE_CAPACITY_DATA": "data", - "RHSM_API_RESPONSE_CAPACITY_DATA_TYPES": Object { - "CLOUD_CORES": "cloud_cores", - "CLOUD_INSTANCES": "cloud_instance_count", - "CLOUD_SOCKETS": "cloud_sockets", - "CORES": "cores", - "DATE": "date", - "HAS_INFINITE": "has_infinite_quantity", - "HYPERVISOR_CORES": "hypervisor_cores", - "HYPERVISOR_SOCKETS": "hypervisor_sockets", - "PHYSICAL_CORES": "physical_cores", - "PHYSICAL_SOCKETS": "physical_sockets", - "SOCKETS": "sockets", - }, - "RHSM_API_RESPONSE_CAPACITY_META": "meta", - "RHSM_API_RESPONSE_CAPACITY_META_TYPES": Object { - "COUNT": "count", - }, - "RHSM_API_RESPONSE_PRODUCTS_DATA": "data", - "RHSM_API_RESPONSE_PRODUCTS_DATA_TYPES": Object { - "CLOUD_CORES": "cloud_cores", - "CLOUD_INSTANCES": "cloud_instance_count", - "CLOUD_SOCKETS": "cloud_sockets", - "CORES": "cores", - "DATE": "date", - "HAS_DATA": "has_data", - "HYPERVISOR_CORES": "hypervisor_cores", - "HYPERVISOR_SOCKETS": "hypervisor_sockets", - "PHYSICAL_CORES": "physical_cores", - "PHYSICAL_SOCKETS": "physical_sockets", - "SOCKETS": "sockets", - }, - "RHSM_API_RESPONSE_PRODUCTS_META": "meta", - "RHSM_API_RESPONSE_PRODUCTS_META_TYPES": Object { - "COUNT": "count", - }, - }, -} -`; - -exports[`RhsmApiTypes Should have specific API properties: specific types 1`] = ` -Object { - "RHSM_API_PATH_ID_TYPES": Object { - "OPENSHIFT": "OpenShift Container Platform", - "RHEL": "RHEL", - "RHEL_ARM": "RHEL for ARM", - "RHEL_COMPUTE_NODE": "RHEL Compute Node", - "RHEL_DESKTOP": "RHEL Desktop", - "RHEL_IBM_POWER": "RHEL for IBM Power", - "RHEL_IBM_Z": "RHEL for IBM z", - "RHEL_SERVER": "RHEL Server", - "RHEL_WORKSTATION": "RHEL Workstation", - "RHEL_X86": "RHEL for x86", - }, - "RHSM_API_QUERY_END_DATE": "ending", - "RHSM_API_QUERY_GRANULARITY": "granularity", - "RHSM_API_QUERY_GRANULARITY_TYPES": Object { - "DAILY": "daily", - "MONTHLY": "monthly", - "QUARTERLY": "quarterly", - "WEEKLY": "weekly", - }, - "RHSM_API_QUERY_LIMIT": "limit", - "RHSM_API_QUERY_OFFSET": "offset", - "RHSM_API_QUERY_SLA": "sla", - "RHSM_API_QUERY_SLA_TYPES": Object { - "NONE": "", - "PREMIUM": "premium", - "SELF": "self-support", - "STANDARD": "standard", - }, - "RHSM_API_QUERY_START_DATE": "beginning", - "RHSM_API_RESPONSE_CAPACITY_DATA": "data", - "RHSM_API_RESPONSE_CAPACITY_DATA_TYPES": Object { - "CLOUD_CORES": "cloud_cores", - "CLOUD_INSTANCES": "cloud_instance_count", - "CLOUD_SOCKETS": "cloud_sockets", - "CORES": "cores", - "DATE": "date", - "HAS_INFINITE": "has_infinite_quantity", - "HYPERVISOR_CORES": "hypervisor_cores", - "HYPERVISOR_SOCKETS": "hypervisor_sockets", - "PHYSICAL_CORES": "physical_cores", - "PHYSICAL_SOCKETS": "physical_sockets", - "SOCKETS": "sockets", - }, - "RHSM_API_RESPONSE_CAPACITY_META": "meta", - "RHSM_API_RESPONSE_CAPACITY_META_TYPES": Object { - "COUNT": "count", - }, - "RHSM_API_RESPONSE_PRODUCTS_DATA": "data", - "RHSM_API_RESPONSE_PRODUCTS_DATA_TYPES": Object { - "CLOUD_CORES": "cloud_cores", - "CLOUD_INSTANCES": "cloud_instance_count", - "CLOUD_SOCKETS": "cloud_sockets", - "CORES": "cores", - "DATE": "date", - "HAS_DATA": "has_data", - "HYPERVISOR_CORES": "hypervisor_cores", - "HYPERVISOR_SOCKETS": "hypervisor_sockets", - "PHYSICAL_CORES": "physical_cores", - "PHYSICAL_SOCKETS": "physical_sockets", - "SOCKETS": "sockets", - }, - "RHSM_API_RESPONSE_PRODUCTS_META": "meta", - "RHSM_API_RESPONSE_PRODUCTS_META_TYPES": Object { - "COUNT": "count", - }, -} -`; diff --git a/src/types/__tests__/index.test.js b/src/types/__tests__/index.test.js new file mode 100644 index 000000000..f022b26f5 --- /dev/null +++ b/src/types/__tests__/index.test.js @@ -0,0 +1,8 @@ +import apiTypes, * as allApiTypes from '..'; + +describe('ApiTypes', () => { + it('should have specific API properties', () => { + expect(apiTypes).toMatchSnapshot('specific types'); + expect(allApiTypes).toMatchSnapshot('all exported api types'); + }); +}); diff --git a/src/types/__tests__/rhsmApiTypes.test.js b/src/types/__tests__/rhsmApiTypes.test.js deleted file mode 100644 index ab5389e3b..000000000 --- a/src/types/__tests__/rhsmApiTypes.test.js +++ /dev/null @@ -1,8 +0,0 @@ -import rhsmApiTypes, * as allApiTypes from '../rhsmApiTypes'; - -describe('RhsmApiTypes', () => { - it('Should have specific API properties', () => { - expect(rhsmApiTypes).toMatchSnapshot('specific types'); - expect(allApiTypes).toMatchSnapshot('all exported api types'); - }); -}); diff --git a/src/types/index.js b/src/types/index.js new file mode 100644 index 000000000..06ebc4aa8 --- /dev/null +++ b/src/types/index.js @@ -0,0 +1,9 @@ +import { platformApiTypes } from './platformApiTypes'; +import { rhsmApiTypes } from './rhsmApiTypes'; + +const apiTypes = { + platformApi: platformApiTypes, + rhsmApi: rhsmApiTypes +}; + +export { apiTypes as default, apiTypes, platformApiTypes, rhsmApiTypes }; diff --git a/src/types/platformApiTypes.js b/src/types/platformApiTypes.js new file mode 100644 index 000000000..c65150c55 --- /dev/null +++ b/src/types/platformApiTypes.js @@ -0,0 +1,69 @@ +/** + * Platform response entitlements type. + * + * @type {string} + */ +const PLATFORM_API_RESPONSE_USER_ENTITLEMENTS = 'entitlements'; + +/** + * Platform response of ENTITLEMENTS type values. + * Schema/map of expected response entitlement types. + * + * @type {{ENTITLED: string}} + */ +const PLATFORM_API_RESPONSE_USER_ENTITLEMENTS_APP_TYPES = { + ENTITLED: 'is_entitled' +}; + +/** + * Platform response identity type. + * + * @type {string} + */ +const PLATFORM_API_RESPONSE_USER_IDENTITY = 'identity'; + +/** + * Platform response of IDENTITY type values. + * Schema/map of expected response identity types. + * + * @type {{USER: string}} + */ +const PLATFORM_API_RESPONSE_USER_IDENTITY_TYPES = { + USER: 'user' +}; + +/** + * Platform response of IDENTITY USER type values. + * Schema/map of expected response identity user types. + * + * @type {{ORG_ADMIN: string}} + */ +const PLATFORM_API_RESPONSE_USER_IDENTITY_USER_TYPES = { + ORG_ADMIN: 'is_org_admin' +}; + +/** + * Platform API types. + * + * @type {{PLATFORM_API_RESPONSE_USER_IDENTITY_TYPES: {USER: string}, + * PLATFORM_API_RESPONSE_USER_ENTITLEMENTS: string, PLATFORM_API_RESPONSE_USER_IDENTITY: string, + * PLATFORM_API_RESPONSE_USER_ENTITLEMENTS_APP_TYPES: {ENTITLED: string}, + * PLATFORM_API_RESPONSE_USER_IDENTITY_USER_TYPES: {ORG_ADMIN: string}}} + */ +const platformApiTypes = { + PLATFORM_API_RESPONSE_USER_ENTITLEMENTS, + PLATFORM_API_RESPONSE_USER_ENTITLEMENTS_APP_TYPES, + PLATFORM_API_RESPONSE_USER_IDENTITY, + PLATFORM_API_RESPONSE_USER_IDENTITY_TYPES, + PLATFORM_API_RESPONSE_USER_IDENTITY_USER_TYPES +}; + +export { + platformApiTypes as default, + platformApiTypes, + PLATFORM_API_RESPONSE_USER_ENTITLEMENTS, + PLATFORM_API_RESPONSE_USER_ENTITLEMENTS_APP_TYPES, + PLATFORM_API_RESPONSE_USER_IDENTITY, + PLATFORM_API_RESPONSE_USER_IDENTITY_TYPES, + PLATFORM_API_RESPONSE_USER_IDENTITY_USER_TYPES +}; diff --git a/src/types/rhsmApiTypes.js b/src/types/rhsmApiTypes.js index 826ad724b..f4a129a93 100644 --- a/src/types/rhsmApiTypes.js +++ b/src/types/rhsmApiTypes.js @@ -142,6 +142,27 @@ const RHSM_API_QUERY_LIMIT = 'limit'; */ const RHSM_API_QUERY_OFFSET = 'offset'; +/** + * RHSM API query/search parameter OPT-IN TALLY SYNC type. + * + * @type {string} + */ +const RHSM_API_QUERY_OPTIN_TALLY_SYNC = 'enable_tally_sync'; + +/** + * RHSM API query/search parameter OPT-IN TALLY REPORT type. + * + * @type {string} + */ +const RHSM_API_QUERY_OPTIN_TALLY_REPORT = 'enable_tally_reporting'; + +/** + * RHSM API query/search parameter OPTIN CONDUIT SYNC type. + * + * @type {string} + */ +const RHSM_API_QUERY_OPTIN_CONDUIT_SYNC = 'enable_conduit_sync'; + /** * RHSM API query/search parameter SLA type. * @@ -210,6 +231,9 @@ const rhsmApiTypes = { RHSM_API_QUERY_GRANULARITY_TYPES, RHSM_API_QUERY_LIMIT, RHSM_API_QUERY_OFFSET, + RHSM_API_QUERY_OPTIN_TALLY_SYNC, + RHSM_API_QUERY_OPTIN_TALLY_REPORT, + RHSM_API_QUERY_OPTIN_CONDUIT_SYNC, RHSM_API_QUERY_SLA, RHSM_API_QUERY_SLA_TYPES, RHSM_API_QUERY_START_DATE, @@ -232,6 +256,9 @@ export { RHSM_API_QUERY_GRANULARITY_TYPES, RHSM_API_QUERY_LIMIT, RHSM_API_QUERY_OFFSET, + RHSM_API_QUERY_OPTIN_TALLY_SYNC, + RHSM_API_QUERY_OPTIN_TALLY_REPORT, + RHSM_API_QUERY_OPTIN_CONDUIT_SYNC, RHSM_API_QUERY_SLA, RHSM_API_QUERY_SLA_TYPES, RHSM_API_QUERY_START_DATE, diff --git a/tests/__snapshots__/dist.test.js.snap b/tests/__snapshots__/dist.test.js.snap index 2a637e5b5..b9588b8ec 100644 --- a/tests/__snapshots__/dist.test.js.snap +++ b/tests/__snapshots__/dist.test.js.snap @@ -18,6 +18,8 @@ Array [ "./build/static/js/main*chunk.js", "./build/static/js/runtime-main*js", "./build/static/js/runtime-main*js.map", + "./build/static/media/graph2x*png", + "./build/static/media/graph4x*png", "./build/static/media/pfbg_2000*jpg", "./build/static/media/pfbg_576*jpg", "./build/static/media/pfbg_576@2x*jpg", diff --git a/tests/dist.test.js b/tests/dist.test.js index 962e1b355..df722a697 100644 --- a/tests/dist.test.js +++ b/tests/dist.test.js @@ -11,6 +11,7 @@ describe('Build distribution', () => { .replace(/\s+|\n+|\r+/g, '') .replace(new RegExp(`./${outputDir}`, 'gi'), `~./${outputDir}`) .replace(new RegExp(`~./${outputDir}/.DS_Store`, 'gi'), '') + .replace(new RegExp(`~./${outputDir}/beta/config/main.yml`, 'gi'), '') .replace(/\.([a-z0-9]+)\./gi, '*') .split('~') .sort(); diff --git a/yarn.lock b/yarn.lock index 051d0697e..d273d359c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -18,7 +18,38 @@ invariant "^2.2.4" semver "^5.5.0" -"@babel/core@7.8.4", "@babel/core@^7.1.0", "@babel/core@^7.4.5": +"@babel/compat-data@^7.8.6", "@babel/compat-data@^7.9.0": + version "7.9.0" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.9.0.tgz#04815556fc90b0c174abd2c0c1bb966faa036a6c" + integrity sha512-zeFQrr+284Ekvd9e7KAX954LkapWiOmQtsfHirhxqfdlX6MEC32iRE+pqUGlYIBchdevaCwvzxWGSy/YBNI85g== + dependencies: + browserslist "^4.9.1" + invariant "^2.2.4" + semver "^5.5.0" + +"@babel/core@7.9.0": + version "7.9.0" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.9.0.tgz#ac977b538b77e132ff706f3b8a4dbad09c03c56e" + integrity sha512-kWc7L0fw1xwvI0zi8OKVBuxRVefwGOrKSQMvrQ3dW+bIIavBY3/NpXmpjMy7bQnLgwgzWQZ8TlM57YHpHNHz4w== + dependencies: + "@babel/code-frame" "^7.8.3" + "@babel/generator" "^7.9.0" + "@babel/helper-module-transforms" "^7.9.0" + "@babel/helpers" "^7.9.0" + "@babel/parser" "^7.9.0" + "@babel/template" "^7.8.6" + "@babel/traverse" "^7.9.0" + "@babel/types" "^7.9.0" + convert-source-map "^1.7.0" + debug "^4.1.0" + gensync "^1.0.0-beta.1" + json5 "^2.1.2" + lodash "^4.17.13" + resolve "^1.3.2" + semver "^5.4.1" + source-map "^0.5.0" + +"@babel/core@^7.1.0", "@babel/core@^7.4.5": version "7.8.4" resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.8.4.tgz#d496799e5c12195b3602d0fddd77294e3e38e80e" integrity sha512-0LiLrB2PwrVI+a2/IEskBopDYSd8BCb3rOvH7D5tzoWd696TBEduBvuLVm4Nx6rltrLZqvI3MCalB2K2aVzQjA== @@ -49,6 +80,16 @@ lodash "^4.17.13" source-map "^0.5.0" +"@babel/generator@^7.9.0": + version "7.9.4" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.9.4.tgz#12441e90c3b3c4159cdecf312075bf1a8ce2dbce" + integrity sha512-rjP8ahaDy/ouhrvCoU1E5mqaitWrxwuNGU+dy1EpaoK48jZay4MdkskKGIMHLZNewg8sAsqpGSREJwP0zH3YQA== + dependencies: + "@babel/types" "^7.9.0" + jsesc "^2.5.1" + lodash "^4.17.13" + source-map "^0.5.0" + "@babel/helper-annotate-as-pure@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.8.3.tgz#60bc0bc657f63a0924ff9a4b4a0b24a13cf4deee" @@ -64,6 +105,15 @@ "@babel/helper-explode-assignable-expression" "^7.8.3" "@babel/types" "^7.8.3" +"@babel/helper-builder-react-jsx-experimental@^7.9.0": + version "7.9.0" + resolved "https://registry.yarnpkg.com/@babel/helper-builder-react-jsx-experimental/-/helper-builder-react-jsx-experimental-7.9.0.tgz#066d80262ade488f9c1b1823ce5db88a4cedaa43" + integrity sha512-3xJEiyuYU4Q/Ar9BsHisgdxZsRlsShMe90URZ0e6przL26CCs8NJbDoxH94kKT17PcxlMhsCAwZd90evCo26VQ== + dependencies: + "@babel/helper-annotate-as-pure" "^7.8.3" + "@babel/helper-module-imports" "^7.8.3" + "@babel/types" "^7.9.0" + "@babel/helper-builder-react-jsx@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/helper-builder-react-jsx/-/helper-builder-react-jsx-7.8.3.tgz#dee98d7d79cc1f003d80b76fe01c7f8945665ff6" @@ -72,6 +122,14 @@ "@babel/types" "^7.8.3" esutils "^2.0.0" +"@babel/helper-builder-react-jsx@^7.9.0": + version "7.9.0" + resolved "https://registry.yarnpkg.com/@babel/helper-builder-react-jsx/-/helper-builder-react-jsx-7.9.0.tgz#16bf391990b57732700a3278d4d9a81231ea8d32" + integrity sha512-weiIo4gaoGgnhff54GQ3P5wsUQmnSwpkvU0r6ZHq6TzoSzKy4JxHEgnxNytaKbov2a9z/CVNyzliuCOUPEX3Jw== + dependencies: + "@babel/helper-annotate-as-pure" "^7.8.3" + "@babel/types" "^7.9.0" + "@babel/helper-call-delegate@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/helper-call-delegate/-/helper-call-delegate-7.8.3.tgz#de82619898aa605d409c42be6ffb8d7204579692" @@ -92,6 +150,17 @@ levenary "^1.1.1" semver "^5.5.0" +"@babel/helper-compilation-targets@^7.8.7": + version "7.8.7" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.8.7.tgz#dac1eea159c0e4bd46e309b5a1b04a66b53c1dde" + integrity sha512-4mWm8DCK2LugIS+p1yArqvG1Pf162upsIsjE7cNBjez+NjliQpVhj20obE520nao0o14DaTnFJv+Fw5a0JpoUw== + dependencies: + "@babel/compat-data" "^7.8.6" + browserslist "^4.9.1" + invariant "^2.2.4" + levenary "^1.1.1" + semver "^5.5.0" + "@babel/helper-create-class-features-plugin@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.8.3.tgz#5b94be88c255f140fd2c10dd151e7f98f4bff397" @@ -112,6 +181,15 @@ "@babel/helper-regex" "^7.8.3" regexpu-core "^4.6.0" +"@babel/helper-create-regexp-features-plugin@^7.8.8": + version "7.8.8" + resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.8.8.tgz#5d84180b588f560b7864efaeea89243e58312087" + integrity sha512-LYVPdwkrQEiX9+1R29Ld/wTrmQu1SSKYnuOk3g0CkcZMA1p0gsNxJFj/3gBdaJ7Cg0Fnek5z0DsMULePP7Lrqg== + dependencies: + "@babel/helper-annotate-as-pure" "^7.8.3" + "@babel/helper-regex" "^7.8.3" + regexpu-core "^4.7.0" + "@babel/helper-define-map@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/helper-define-map/-/helper-define-map-7.8.3.tgz#a0655cad5451c3760b726eba875f1cd8faa02c15" @@ -178,6 +256,19 @@ "@babel/types" "^7.8.3" lodash "^4.17.13" +"@babel/helper-module-transforms@^7.9.0": + version "7.9.0" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.9.0.tgz#43b34dfe15961918707d247327431388e9fe96e5" + integrity sha512-0FvKyu0gpPfIQ8EkxlrAydOWROdHpBmiCiRwLkUiBGhCUPRRbVD2/tm3sFr/c/GWFrQ/ffutGUAnx7V0FzT2wA== + dependencies: + "@babel/helper-module-imports" "^7.8.3" + "@babel/helper-replace-supers" "^7.8.6" + "@babel/helper-simple-access" "^7.8.3" + "@babel/helper-split-export-declaration" "^7.8.3" + "@babel/template" "^7.8.6" + "@babel/types" "^7.9.0" + lodash "^4.17.13" + "@babel/helper-optimise-call-expression@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.8.3.tgz#7ed071813d09c75298ef4f208956006b6111ecb9" @@ -218,6 +309,16 @@ "@babel/traverse" "^7.8.3" "@babel/types" "^7.8.3" +"@babel/helper-replace-supers@^7.8.6": + version "7.8.6" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.8.6.tgz#5ada744fd5ad73203bf1d67459a27dcba67effc8" + integrity sha512-PeMArdA4Sv/Wf4zXwBKPqVj7n9UF/xg6slNRtZW84FM7JpE1CbG8B612FyM4cxrf4fMAMGO0kR7voy1ForHHFA== + dependencies: + "@babel/helper-member-expression-to-functions" "^7.8.3" + "@babel/helper-optimise-call-expression" "^7.8.3" + "@babel/traverse" "^7.8.6" + "@babel/types" "^7.8.6" + "@babel/helper-simple-access@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.8.3.tgz#7f8109928b4dab4654076986af575231deb639ae" @@ -233,6 +334,11 @@ dependencies: "@babel/types" "^7.8.3" +"@babel/helper-validator-identifier@^7.9.0": + version "7.9.0" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.9.0.tgz#ad53562a7fc29b3b9a91bbf7d10397fd146346ed" + integrity sha512-6G8bQKjOh+of4PV/ThDm/rRqlU7+IGoJuofpagU5GlEl29Vv0RGqqt86ZGRV8ZuSOY3o+8yXl5y782SMcG7SHw== + "@babel/helper-wrap-function@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.8.3.tgz#9dbdb2bb55ef14aaa01fe8c99b629bd5352d8610" @@ -252,6 +358,15 @@ "@babel/traverse" "^7.8.4" "@babel/types" "^7.8.3" +"@babel/helpers@^7.9.0": + version "7.9.2" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.9.2.tgz#b42a81a811f1e7313b88cba8adc66b3d9ae6c09f" + integrity sha512-JwLvzlXVPjO8eU9c/wF9/zOIN7X6h8DYf7mG4CiFRZRvZNKEF5dQ3H3V+ASkHoIB3mWhatgl5ONhyqHRI6MppA== + dependencies: + "@babel/template" "^7.8.3" + "@babel/traverse" "^7.9.0" + "@babel/types" "^7.9.0" + "@babel/highlight@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.8.3.tgz#28f173d04223eaaa59bc1d439a3836e6d1265797" @@ -261,11 +376,16 @@ esutils "^2.0.2" js-tokens "^4.0.0" -"@babel/parser@^7.0.0", "@babel/parser@^7.1.0", "@babel/parser@^7.4.3", "@babel/parser@^7.8.3", "@babel/parser@^7.8.4": +"@babel/parser@^7.1.0", "@babel/parser@^7.4.3", "@babel/parser@^7.8.3", "@babel/parser@^7.8.4": version "7.8.4" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.8.4.tgz#d1dbe64691d60358a974295fa53da074dd2ce8e8" integrity sha512-0fKu/QqildpXmPVaRBoXOlyBb3MC+J0A66x97qEfLOMkn3u6nfY5esWogQwi/K0BjASYy4DbnsEWnpNL6qT5Mw== +"@babel/parser@^7.7.0", "@babel/parser@^7.8.6", "@babel/parser@^7.9.0": + version "7.9.4" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.9.4.tgz#68a35e6b0319bbc014465be43828300113f2f2e8" + integrity sha512-bC49otXX6N0/VYhgOMh4gnP26E9xnDZK3TmbNpxYzzz9BQLBosQwfyOe9/cXUU3txYhTzLCbcqd5c8y/OmCjHA== + "@babel/plugin-proposal-async-generator-functions@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.8.3.tgz#bad329c670b382589721b27540c7d288601c6e6f" @@ -308,7 +428,7 @@ "@babel/helper-plugin-utils" "^7.8.3" "@babel/plugin-syntax-json-strings" "^7.8.0" -"@babel/plugin-proposal-nullish-coalescing-operator@^7.8.3": +"@babel/plugin-proposal-nullish-coalescing-operator@7.8.3", "@babel/plugin-proposal-nullish-coalescing-operator@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.8.3.tgz#e4572253fdeed65cddeecfdab3f928afeb2fd5d2" integrity sha512-TS9MlfzXpXKt6YYomudb/KU7nQI6/xnapG6in1uZxoxDghuSMZsPb6D2fyUwNYSAp4l1iR7QtFOjkqcRYcUsfw== @@ -316,7 +436,7 @@ "@babel/helper-plugin-utils" "^7.8.3" "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.0" -"@babel/plugin-proposal-numeric-separator@7.8.3": +"@babel/plugin-proposal-numeric-separator@7.8.3", "@babel/plugin-proposal-numeric-separator@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.8.3.tgz#5d6769409699ec9b3b68684cd8116cedff93bad8" integrity sha512-jWioO1s6R/R+wEHizfaScNsAx+xKgwTLNXSh7tTC4Usj3ItsPEhYkEpU4h+lpnBwq7NBVOJXfO6cRFYcX69JUQ== @@ -332,6 +452,14 @@ "@babel/helper-plugin-utils" "^7.8.3" "@babel/plugin-syntax-object-rest-spread" "^7.8.0" +"@babel/plugin-proposal-object-rest-spread@^7.9.0": + version "7.9.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.9.0.tgz#a28993699fc13df165995362693962ba6b061d6f" + integrity sha512-UgqBv6bjq4fDb8uku9f+wcm1J7YxJ5nT7WO/jBr0cl0PLKb7t1O6RNR1kZbjgx2LQtsDI9hwoQVmn0yhXeQyow== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/plugin-syntax-object-rest-spread" "^7.8.0" + "@babel/plugin-proposal-optional-catch-binding@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.8.3.tgz#9dee96ab1650eed88646ae9734ca167ac4a9c5c9" @@ -340,6 +468,14 @@ "@babel/helper-plugin-utils" "^7.8.3" "@babel/plugin-syntax-optional-catch-binding" "^7.8.0" +"@babel/plugin-proposal-optional-chaining@7.9.0", "@babel/plugin-proposal-optional-chaining@^7.9.0": + version "7.9.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.9.0.tgz#31db16b154c39d6b8a645292472b98394c292a58" + integrity sha512-NDn5tu3tcv4W30jNhmc2hyD5c56G6cXx4TesJubhxrJeCvuuMpttxr0OnNCqbZGhFjLrg+NIhxxC+BK5F6yS3w== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/plugin-syntax-optional-chaining" "^7.8.0" + "@babel/plugin-proposal-optional-chaining@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.8.3.tgz#ae10b3214cb25f7adb1f3bc87ba42ca10b7e2543" @@ -348,6 +484,14 @@ "@babel/helper-plugin-utils" "^7.8.3" "@babel/plugin-syntax-optional-chaining" "^7.8.0" +"@babel/plugin-proposal-unicode-property-regex@^7.4.4": + version "7.8.8" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.8.8.tgz#ee3a95e90cdc04fe8cd92ec3279fa017d68a0d1d" + integrity sha512-EVhjVsMpbhLw9ZfHWSx2iy13Q8Z/eg8e8ccVWt23sWQK5l1UdkoLJPN5w69UA4uITGBnEZD2JOe4QOHycYKv8A== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.8.8" + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/plugin-proposal-unicode-property-regex@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.8.3.tgz#b646c3adea5f98800c9ab45105ac34d06cd4a47f" @@ -405,7 +549,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-numeric-separator@^7.8.3": +"@babel/plugin-syntax-numeric-separator@^7.8.0", "@babel/plugin-syntax-numeric-separator@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.8.3.tgz#0e3fb63e09bea1b11e96467271c8308007e7c41f" integrity sha512-H7dCMAdN83PcCmqmkHB5dtp+Xa9a6LKSvA2hiFBC/5alSHxM5VgWZXFqDi0YFe8XNGT6iCa+z4V4zSt/PdZ7Dw== @@ -492,6 +636,20 @@ "@babel/helper-split-export-declaration" "^7.8.3" globals "^11.1.0" +"@babel/plugin-transform-classes@^7.9.0": + version "7.9.2" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.9.2.tgz#8603fc3cc449e31fdbdbc257f67717536a11af8d" + integrity sha512-TC2p3bPzsfvSsqBZo0kJnuelnoK9O3welkUpqSqBQuBF6R5MN2rysopri8kNvtlGIb2jmUO7i15IooAZJjZuMQ== + dependencies: + "@babel/helper-annotate-as-pure" "^7.8.3" + "@babel/helper-define-map" "^7.8.3" + "@babel/helper-function-name" "^7.8.3" + "@babel/helper-optimise-call-expression" "^7.8.3" + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-replace-supers" "^7.8.6" + "@babel/helper-split-export-declaration" "^7.8.3" + globals "^11.1.0" + "@babel/plugin-transform-computed-properties@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.8.3.tgz#96d0d28b7f7ce4eb5b120bb2e0e943343c86f81b" @@ -506,7 +664,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-transform-dotall-regex@^7.8.3": +"@babel/plugin-transform-dotall-regex@^7.4.4", "@babel/plugin-transform-dotall-regex@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.8.3.tgz#c3c6ec5ee6125c6993c5cbca20dc8621a9ea7a6e" integrity sha512-kLs1j9Nn4MQoBYdRXH6AeaXMbEJFaFu/v1nQkvib6QzTj8MZI5OQzqmD83/2jEM1z0DLilra5aWO5YpyC0ALIw== @@ -529,10 +687,10 @@ "@babel/helper-builder-binary-assignment-operator-visitor" "^7.8.3" "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-transform-flow-strip-types@7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.8.3.tgz#da705a655466b2a9b36046b57bf0cbcd53551bd4" - integrity sha512-g/6WTWG/xbdd2exBBzMfygjX/zw4eyNC4X8pRaq7aRHRoDUCzAIu3kGYIXviOv8BjCuWm8vDBwjHcjiRNgXrPA== +"@babel/plugin-transform-flow-strip-types@7.9.0": + version "7.9.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.9.0.tgz#8a3538aa40434e000b8f44a3c5c9ac7229bd2392" + integrity sha512-7Qfg0lKQhEHs93FChxVLAvhBshOPQDtJUTVHr/ZwQNRccCm4O9D79r9tVSoV8iNwjP1YgfD+e/fgHcPkN1qEQg== dependencies: "@babel/helper-plugin-utils" "^7.8.3" "@babel/plugin-syntax-flow" "^7.8.3" @@ -544,6 +702,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.3" +"@babel/plugin-transform-for-of@^7.9.0": + version "7.9.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.9.0.tgz#0f260e27d3e29cd1bb3128da5e76c761aa6c108e" + integrity sha512-lTAnWOpMwOXpyDx06N+ywmF3jNbafZEqZ96CGYabxHrxNX8l5ny7dt4bK/rGwAh9utyP2b2Hv7PlZh1AAS54FQ== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/plugin-transform-function-name@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.8.3.tgz#279373cb27322aaad67c2683e776dfc47196ed8b" @@ -575,6 +740,15 @@ "@babel/helper-plugin-utils" "^7.8.3" babel-plugin-dynamic-import-node "^2.3.0" +"@babel/plugin-transform-modules-amd@^7.9.0": + version "7.9.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.9.0.tgz#19755ee721912cf5bb04c07d50280af3484efef4" + integrity sha512-vZgDDF003B14O8zJy0XXLnPH4sg+9X5hFBBGN1V+B2rgrB+J2xIypSN6Rk9imB2hSTHQi5OHLrFWsZab1GMk+Q== + dependencies: + "@babel/helper-module-transforms" "^7.9.0" + "@babel/helper-plugin-utils" "^7.8.3" + babel-plugin-dynamic-import-node "^2.3.0" + "@babel/plugin-transform-modules-commonjs@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.8.3.tgz#df251706ec331bd058a34bdd72613915f82928a5" @@ -585,6 +759,16 @@ "@babel/helper-simple-access" "^7.8.3" babel-plugin-dynamic-import-node "^2.3.0" +"@babel/plugin-transform-modules-commonjs@^7.9.0": + version "7.9.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.9.0.tgz#e3e72f4cbc9b4a260e30be0ea59bdf5a39748940" + integrity sha512-qzlCrLnKqio4SlgJ6FMMLBe4bySNis8DFn1VkGmOcxG9gqEyPIOzeQrA//u0HAKrWpJlpZbZMPB1n/OPa4+n8g== + dependencies: + "@babel/helper-module-transforms" "^7.9.0" + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-simple-access" "^7.8.3" + babel-plugin-dynamic-import-node "^2.3.0" + "@babel/plugin-transform-modules-systemjs@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.8.3.tgz#d8bbf222c1dbe3661f440f2f00c16e9bb7d0d420" @@ -595,6 +779,16 @@ "@babel/helper-plugin-utils" "^7.8.3" babel-plugin-dynamic-import-node "^2.3.0" +"@babel/plugin-transform-modules-systemjs@^7.9.0": + version "7.9.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.9.0.tgz#e9fd46a296fc91e009b64e07ddaa86d6f0edeb90" + integrity sha512-FsiAv/nao/ud2ZWy4wFacoLOm5uxl0ExSQ7ErvP7jpoihLR6Cq90ilOFyX9UXct3rbtKsAiZ9kFt5XGfPe/5SQ== + dependencies: + "@babel/helper-hoist-variables" "^7.8.3" + "@babel/helper-module-transforms" "^7.9.0" + "@babel/helper-plugin-utils" "^7.8.3" + babel-plugin-dynamic-import-node "^2.3.0" + "@babel/plugin-transform-modules-umd@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.8.3.tgz#592d578ce06c52f5b98b02f913d653ffe972661a" @@ -603,6 +797,14 @@ "@babel/helper-module-transforms" "^7.8.3" "@babel/helper-plugin-utils" "^7.8.3" +"@babel/plugin-transform-modules-umd@^7.9.0": + version "7.9.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.9.0.tgz#e909acae276fec280f9b821a5f38e1f08b480697" + integrity sha512-uTWkXkIVtg/JGRSIABdBoMsoIeoHQHPTL0Y2E7xf5Oj7sLqwVsNXOkNk0VJc7vF0IMBsPeikHxFjGe+qmwPtTQ== + dependencies: + "@babel/helper-module-transforms" "^7.9.0" + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/plugin-transform-named-capturing-groups-regex@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.8.3.tgz#a2a72bffa202ac0e2d0506afd0939c5ecbc48c6c" @@ -634,6 +836,14 @@ "@babel/helper-get-function-arity" "^7.8.3" "@babel/helper-plugin-utils" "^7.8.3" +"@babel/plugin-transform-parameters@^7.8.7": + version "7.9.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.9.3.tgz#3028d0cc20ddc733166c6e9c8534559cee09f54a" + integrity sha512-fzrQFQhp7mIhOzmOtPiKffvCYQSK10NR8t6BBz2yPbeUHb9OLW8RZGtgDRBn8z2hGcwvKDL3vC7ojPTLNxmqEg== + dependencies: + "@babel/helper-get-function-arity" "^7.8.3" + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/plugin-transform-property-literals@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.8.3.tgz#33194300d8539c1ed28c62ad5087ba3807b98263" @@ -656,6 +866,15 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.3" +"@babel/plugin-transform-react-jsx-development@^7.9.0": + version "7.9.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.9.0.tgz#3c2a130727caf00c2a293f0aed24520825dbf754" + integrity sha512-tK8hWKrQncVvrhvtOiPpKrQjfNX3DtkNLSX4ObuGcpS9p0QrGetKmlySIGR07y48Zft8WVgPakqd/bk46JrMSw== + dependencies: + "@babel/helper-builder-react-jsx-experimental" "^7.9.0" + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/plugin-syntax-jsx" "^7.8.3" + "@babel/plugin-transform-react-jsx-self@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.8.3.tgz#c4f178b2aa588ecfa8d077ea80d4194ee77ed702" @@ -664,6 +883,14 @@ "@babel/helper-plugin-utils" "^7.8.3" "@babel/plugin-syntax-jsx" "^7.8.3" +"@babel/plugin-transform-react-jsx-self@^7.9.0": + version "7.9.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.9.0.tgz#f4f26a325820205239bb915bad8e06fcadabb49b" + integrity sha512-K2ObbWPKT7KUTAoyjCsFilOkEgMvFG+y0FqOl6Lezd0/13kMkkjHskVsZvblRPj1PHA44PrToaZANrryppzTvQ== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/plugin-syntax-jsx" "^7.8.3" + "@babel/plugin-transform-react-jsx-source@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.8.3.tgz#951e75a8af47f9f120db731be095d2b2c34920e0" @@ -672,6 +899,14 @@ "@babel/helper-plugin-utils" "^7.8.3" "@babel/plugin-syntax-jsx" "^7.8.3" +"@babel/plugin-transform-react-jsx-source@^7.9.0": + version "7.9.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.9.0.tgz#89ef93025240dd5d17d3122294a093e5e0183de0" + integrity sha512-K6m3LlSnTSfRkM6FcRk8saNEeaeyG5k7AVkBU2bZK3+1zdkSED3qNdsWrUgQBeTVD2Tp3VMmerxVO2yM5iITmw== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/plugin-syntax-jsx" "^7.8.3" + "@babel/plugin-transform-react-jsx@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.8.3.tgz#4220349c0390fdefa505365f68c103562ab2fc4a" @@ -681,6 +916,16 @@ "@babel/helper-plugin-utils" "^7.8.3" "@babel/plugin-syntax-jsx" "^7.8.3" +"@babel/plugin-transform-react-jsx@^7.9.1": + version "7.9.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.9.4.tgz#86f576c8540bd06d0e95e0b61ea76d55f6cbd03f" + integrity sha512-Mjqf3pZBNLt854CK0C/kRuXAnE6H/bo7xYojP+WGtX8glDGSibcwnsWwhwoSuRg0+EBnxPC1ouVnuetUIlPSAw== + dependencies: + "@babel/helper-builder-react-jsx" "^7.9.0" + "@babel/helper-builder-react-jsx-experimental" "^7.9.0" + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/plugin-syntax-jsx" "^7.8.3" + "@babel/plugin-transform-regenerator@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.8.3.tgz#b31031e8059c07495bf23614c97f3d9698bc6ec8" @@ -688,6 +933,13 @@ dependencies: regenerator-transform "^0.14.0" +"@babel/plugin-transform-regenerator@^7.8.7": + version "7.8.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.8.7.tgz#5e46a0dca2bee1ad8285eb0527e6abc9c37672f8" + integrity sha512-TIg+gAl4Z0a3WmD3mbYSk+J9ZUH6n/Yc57rtKRnlA/7rcCvpekHXe0CMZHP1gYp7/KLe9GHTuIba0vXmls6drA== + dependencies: + regenerator-transform "^0.14.2" + "@babel/plugin-transform-reserved-words@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.8.3.tgz#9a0635ac4e665d29b162837dd3cc50745dfdf1f5" @@ -695,10 +947,10 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-transform-runtime@7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.8.3.tgz#c0153bc0a5375ebc1f1591cb7eea223adea9f169" - integrity sha512-/vqUt5Yh+cgPZXXjmaG9NT8aVfThKk7G4OqkVhrXqwsC5soMn/qTCxs36rZ2QFhpfTJcjw4SNDIZ4RUb8OL4jQ== +"@babel/plugin-transform-runtime@7.9.0": + version "7.9.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.9.0.tgz#45468c0ae74cc13204e1d3b1f4ce6ee83258af0b" + integrity sha512-pUu9VSf3kI1OqbWINQ7MaugnitRss1z533436waNXp+0N3ur3zfut37sXiQMxkuCF4VUjwZucen/quskCh7NHw== dependencies: "@babel/helper-module-imports" "^7.8.3" "@babel/helper-plugin-utils" "^7.8.3" @@ -742,10 +994,10 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-transform-typescript@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.8.3.tgz#be6f01a7ef423be68e65ace1f04fc407e6d88917" - integrity sha512-Ebj230AxcrKGZPKIp4g4TdQLrqX95TobLUWKd/CwG7X1XHUH1ZpkpFvXuXqWbtGRWb7uuEWNlrl681wsOArAdQ== +"@babel/plugin-transform-typescript@^7.9.0": + version "7.9.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.9.4.tgz#4bb4dde4f10bbf2d787fce9707fb09b483e33359" + integrity sha512-yeWeUkKx2auDbSxRe8MusAG+n4m9BFY/v+lPjmQDgOFX5qnySkUY5oXzkp6FwPdsYqnKay6lorXYdC0n3bZO7w== dependencies: "@babel/helper-create-class-features-plugin" "^7.8.3" "@babel/helper-plugin-utils" "^7.8.3" @@ -759,7 +1011,73 @@ "@babel/helper-create-regexp-features-plugin" "^7.8.3" "@babel/helper-plugin-utils" "^7.8.3" -"@babel/preset-env@7.8.4", "@babel/preset-env@^7.4.5": +"@babel/preset-env@7.9.0": + version "7.9.0" + resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.9.0.tgz#a5fc42480e950ae8f5d9f8f2bbc03f52722df3a8" + integrity sha512-712DeRXT6dyKAM/FMbQTV/FvRCms2hPCx+3weRjZ8iQVQWZejWWk1wwG6ViWMyqb/ouBbGOl5b6aCk0+j1NmsQ== + dependencies: + "@babel/compat-data" "^7.9.0" + "@babel/helper-compilation-targets" "^7.8.7" + "@babel/helper-module-imports" "^7.8.3" + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/plugin-proposal-async-generator-functions" "^7.8.3" + "@babel/plugin-proposal-dynamic-import" "^7.8.3" + "@babel/plugin-proposal-json-strings" "^7.8.3" + "@babel/plugin-proposal-nullish-coalescing-operator" "^7.8.3" + "@babel/plugin-proposal-numeric-separator" "^7.8.3" + "@babel/plugin-proposal-object-rest-spread" "^7.9.0" + "@babel/plugin-proposal-optional-catch-binding" "^7.8.3" + "@babel/plugin-proposal-optional-chaining" "^7.9.0" + "@babel/plugin-proposal-unicode-property-regex" "^7.8.3" + "@babel/plugin-syntax-async-generators" "^7.8.0" + "@babel/plugin-syntax-dynamic-import" "^7.8.0" + "@babel/plugin-syntax-json-strings" "^7.8.0" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.0" + "@babel/plugin-syntax-numeric-separator" "^7.8.0" + "@babel/plugin-syntax-object-rest-spread" "^7.8.0" + "@babel/plugin-syntax-optional-catch-binding" "^7.8.0" + "@babel/plugin-syntax-optional-chaining" "^7.8.0" + "@babel/plugin-syntax-top-level-await" "^7.8.3" + "@babel/plugin-transform-arrow-functions" "^7.8.3" + "@babel/plugin-transform-async-to-generator" "^7.8.3" + "@babel/plugin-transform-block-scoped-functions" "^7.8.3" + "@babel/plugin-transform-block-scoping" "^7.8.3" + "@babel/plugin-transform-classes" "^7.9.0" + "@babel/plugin-transform-computed-properties" "^7.8.3" + "@babel/plugin-transform-destructuring" "^7.8.3" + "@babel/plugin-transform-dotall-regex" "^7.8.3" + "@babel/plugin-transform-duplicate-keys" "^7.8.3" + "@babel/plugin-transform-exponentiation-operator" "^7.8.3" + "@babel/plugin-transform-for-of" "^7.9.0" + "@babel/plugin-transform-function-name" "^7.8.3" + "@babel/plugin-transform-literals" "^7.8.3" + "@babel/plugin-transform-member-expression-literals" "^7.8.3" + "@babel/plugin-transform-modules-amd" "^7.9.0" + "@babel/plugin-transform-modules-commonjs" "^7.9.0" + "@babel/plugin-transform-modules-systemjs" "^7.9.0" + "@babel/plugin-transform-modules-umd" "^7.9.0" + "@babel/plugin-transform-named-capturing-groups-regex" "^7.8.3" + "@babel/plugin-transform-new-target" "^7.8.3" + "@babel/plugin-transform-object-super" "^7.8.3" + "@babel/plugin-transform-parameters" "^7.8.7" + "@babel/plugin-transform-property-literals" "^7.8.3" + "@babel/plugin-transform-regenerator" "^7.8.7" + "@babel/plugin-transform-reserved-words" "^7.8.3" + "@babel/plugin-transform-shorthand-properties" "^7.8.3" + "@babel/plugin-transform-spread" "^7.8.3" + "@babel/plugin-transform-sticky-regex" "^7.8.3" + "@babel/plugin-transform-template-literals" "^7.8.3" + "@babel/plugin-transform-typeof-symbol" "^7.8.4" + "@babel/plugin-transform-unicode-regex" "^7.8.3" + "@babel/preset-modules" "^0.1.3" + "@babel/types" "^7.9.0" + browserslist "^4.9.1" + core-js-compat "^3.6.2" + invariant "^2.2.2" + levenary "^1.1.1" + semver "^5.5.0" + +"@babel/preset-env@^7.4.5": version "7.8.4" resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.8.4.tgz#9dac6df5f423015d3d49b6e9e5fa3413e4a72c4e" integrity sha512-HihCgpr45AnSOHRbS5cWNTINs0TwaR8BS8xIIH+QwiW8cKL0llV91njQMpeMReEPVs+1Ao0x3RLEBLtt1hOq4w== @@ -822,7 +1140,30 @@ levenary "^1.1.1" semver "^5.5.0" -"@babel/preset-react@7.8.3", "@babel/preset-react@^7.0.0": +"@babel/preset-modules@^0.1.3": + version "0.1.3" + resolved "https://registry.yarnpkg.com/@babel/preset-modules/-/preset-modules-0.1.3.tgz#13242b53b5ef8c883c3cf7dddd55b36ce80fbc72" + integrity sha512-Ra3JXOHBq2xd56xSF7lMKXdjBn3T772Y1Wet3yWnkDly9zHvJki029tAFzvAAK5cf4YV3yoxuP61crYRol6SVg== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-proposal-unicode-property-regex" "^7.4.4" + "@babel/plugin-transform-dotall-regex" "^7.4.4" + "@babel/types" "^7.4.4" + esutils "^2.0.2" + +"@babel/preset-react@7.9.1": + version "7.9.1" + resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.9.1.tgz#b346403c36d58c3bb544148272a0cefd9c28677a" + integrity sha512-aJBYF23MPj0RNdp/4bHnAP0NVqqZRr9kl0NAOP4nJCex6OYVio59+dnQzsAWFuogdLyeaKA1hmfUIVZkY5J+TQ== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/plugin-transform-react-display-name" "^7.8.3" + "@babel/plugin-transform-react-jsx" "^7.9.1" + "@babel/plugin-transform-react-jsx-development" "^7.9.0" + "@babel/plugin-transform-react-jsx-self" "^7.9.0" + "@babel/plugin-transform-react-jsx-source" "^7.9.0" + +"@babel/preset-react@^7.0.0": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.8.3.tgz#23dc63f1b5b0751283e04252e78cf1d6589273d2" integrity sha512-9hx0CwZg92jGb7iHYQVgi0tOEHP/kM60CtWJQnmbATSPIQQ2xYzfoCI3EdqAhFBeeJwYMdWQuDUHMsuDbH9hyQ== @@ -833,13 +1174,13 @@ "@babel/plugin-transform-react-jsx-self" "^7.8.3" "@babel/plugin-transform-react-jsx-source" "^7.8.3" -"@babel/preset-typescript@7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.8.3.tgz#90af8690121beecd9a75d0cc26c6be39d1595d13" - integrity sha512-qee5LgPGui9zQ0jR1TeU5/fP9L+ovoArklEqY12ek8P/wV5ZeM/VYSQYwICeoT6FfpJTekG9Ilay5PhwsOpMHA== +"@babel/preset-typescript@7.9.0": + version "7.9.0" + resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.9.0.tgz#87705a72b1f0d59df21c179f7c3d2ef4b16ce192" + integrity sha512-S4cueFnGrIbvYJgwsVFKdvOmpiL0XGw9MFW9D0vgRys5g36PBhZRL8NX8Gr2akz8XRtzq6HuDXPD/1nniagNUg== dependencies: "@babel/helper-plugin-utils" "^7.8.3" - "@babel/plugin-transform-typescript" "^7.8.3" + "@babel/plugin-transform-typescript" "^7.9.0" "@babel/runtime-corejs3@^7.8.3": version "7.8.7" @@ -849,13 +1190,27 @@ core-js-pure "^3.0.0" regenerator-runtime "^0.13.4" -"@babel/runtime@7.8.4", "@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.3.1", "@babel/runtime@^7.3.4", "@babel/runtime@^7.4.0", "@babel/runtime@^7.4.5", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.3", "@babel/runtime@^7.7.2": +"@babel/runtime@7.9.0": + version "7.9.0" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.9.0.tgz#337eda67401f5b066a6f205a3113d4ac18ba495b" + integrity sha512-cTIudHnzuWLS56ik4DnRnqqNf8MkdUzV4iFFI1h7Jo9xvrpQROYaAnaSd2mHLQAzzZAPfATynX5ord6YlNYNMA== + dependencies: + regenerator-runtime "^0.13.4" + +"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.3.1", "@babel/runtime@^7.3.4", "@babel/runtime@^7.4.0", "@babel/runtime@^7.4.5", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.3", "@babel/runtime@^7.7.2": version "7.8.4" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.8.4.tgz#d79f5a2040f7caa24d53e563aad49cbc05581308" integrity sha512-neAp3zt80trRVBI1x0azq6c57aNBqYZH8KhMm3TaB7wEI5Q4A2SHfBHE8w9gOhI/lrqxtEbXZgQIrHP+wvSGwQ== dependencies: regenerator-runtime "^0.13.2" +"@babel/runtime@^7.8.4": + version "7.9.2" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.9.2.tgz#d90df0583a3a252f09aaa619665367bae518db06" + integrity sha512-NE2DtOdufG7R5vnfQUTehdTfNycfUANEtCa9PssN9O/xmTzP4E08UI797ixaei6hBEVL9BI/PsdJS5x7mWoB9Q== + dependencies: + regenerator-runtime "^0.13.4" + "@babel/template@^7.4.0", "@babel/template@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.8.3.tgz#e02ad04fe262a657809327f578056ca15fd4d1b8" @@ -865,7 +1220,16 @@ "@babel/parser" "^7.8.3" "@babel/types" "^7.8.3" -"@babel/traverse@^7.0.0", "@babel/traverse@^7.1.0", "@babel/traverse@^7.4.3", "@babel/traverse@^7.8.3", "@babel/traverse@^7.8.4": +"@babel/template@^7.8.6": + version "7.8.6" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.8.6.tgz#86b22af15f828dfb086474f964dcc3e39c43ce2b" + integrity sha512-zbMsPMy/v0PWFZEhQJ66bqjhH+z0JgMoBWuikXybgG3Gkd/3t5oQ1Rw2WQhnSrsOmsKXnZOx15tkC4qON/+JPg== + dependencies: + "@babel/code-frame" "^7.8.3" + "@babel/parser" "^7.8.6" + "@babel/types" "^7.8.6" + +"@babel/traverse@^7.1.0", "@babel/traverse@^7.4.3", "@babel/traverse@^7.8.3", "@babel/traverse@^7.8.4": version "7.8.4" resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.8.4.tgz#f0845822365f9d5b0e312ed3959d3f827f869e3c" integrity sha512-NGLJPZwnVEyBPLI+bl9y9aSnxMhsKz42so7ApAv9D+b4vAFPpY013FTS9LdKxcABoIYFU52HcYga1pPlx454mg== @@ -880,6 +1244,21 @@ globals "^11.1.0" lodash "^4.17.13" +"@babel/traverse@^7.7.0", "@babel/traverse@^7.8.6", "@babel/traverse@^7.9.0": + version "7.9.0" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.9.0.tgz#d3882c2830e513f4fe4cec9fe76ea1cc78747892" + integrity sha512-jAZQj0+kn4WTHO5dUZkZKhbFrqZE7K5LAQ5JysMnmvGij+wOdr+8lWqPeW0BcF4wFwrEXXtdGO7wcV6YPJcf3w== + dependencies: + "@babel/code-frame" "^7.8.3" + "@babel/generator" "^7.9.0" + "@babel/helper-function-name" "^7.8.3" + "@babel/helper-split-export-declaration" "^7.8.3" + "@babel/parser" "^7.9.0" + "@babel/types" "^7.9.0" + debug "^4.1.0" + globals "^11.1.0" + lodash "^4.17.13" + "@babel/types@^7.0.0", "@babel/types@^7.3.0", "@babel/types@^7.4.0", "@babel/types@^7.4.4", "@babel/types@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.8.3.tgz#5a383dffa5416db1b73dedffd311ffd0788fb31c" @@ -889,6 +1268,15 @@ lodash "^4.17.13" to-fast-properties "^2.0.0" +"@babel/types@^7.7.0", "@babel/types@^7.8.6", "@babel/types@^7.9.0": + version "7.9.0" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.9.0.tgz#00b064c3df83ad32b2dbf5ff07312b15c7f1efb5" + integrity sha512-BS9JKfXkzzJl8RluW4JGknzpiUV7ZrvTayM6yfqLTVBEnFtyowVIOu6rqxRd5cVO6yGoWf4T8u8dgK9oB+GCng== + dependencies: + "@babel/helper-validator-identifier" "^7.9.0" + lodash "^4.17.13" + to-fast-properties "^2.0.0" + "@cnakazawa/watch@^1.0.3": version "1.0.4" resolved "https://registry.yarnpkg.com/@cnakazawa/watch/-/watch-1.0.4.tgz#f864ae85004d0fcab6f50be9141c4da368d1656a" @@ -1159,54 +1547,48 @@ resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz#2b5a3ab3f918cca48a8c754c08168e3f03eba61b" integrity sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw== -"@patternfly/patternfly@2.65.2": - version "2.65.2" - resolved "https://registry.yarnpkg.com/@patternfly/patternfly/-/patternfly-2.65.2.tgz#d59359d8ed45f55ea466b0976328aeb2324cd2de" - integrity sha512-Q0Hi1JF7wuhs9fpYhItT2ZNv+JVqo1VvFEKvtjBQsPJdhCl9t7YAyOhTce4QK0ORj47lnVP3mw+1sjIWY0SPlA== +"@patternfly/patternfly@2.71.3": + version "2.71.3" + resolved "https://registry.yarnpkg.com/@patternfly/patternfly/-/patternfly-2.71.3.tgz#22deedc5e2610d7b2710a1efe827c25fac7726b2" + integrity sha512-uTb9zAtPjTKB8aHmWdavEOrSMs+NL9XovMvWYL9R74zXbGnEMHEpibn7cNSu469u2JrxY6VsH7x44aOfdZpqpg== -"@patternfly/patternfly@2.65.3": - version "2.65.3" - resolved "https://registry.yarnpkg.com/@patternfly/patternfly/-/patternfly-2.65.3.tgz#0856d6ca13d971f18b1d7889a60a73eb78cad3c8" - integrity sha512-pOmj1r6nOU8WOI0y6s0vfILG8dLxxhDpzBCYUtnx+i8bqq3Ci6F1tekGqs0AfjAR1+OF5lfJEb+dhixs0Z8yrg== - -"@patternfly/react-charts@5.3.5": - version "5.3.5" - resolved "https://registry.yarnpkg.com/@patternfly/react-charts/-/react-charts-5.3.5.tgz#069bd8da400adddae104bf3f487c132fe891342e" - integrity sha512-Nlw1aQ0YiZ4A6tvsVdbvWHzvZwRs9NfFqX+0Ue7nlBL+OBWgpXsA+zSN1i7bCxNEWbCVN4WxaL5XuqOMunSF4A== +"@patternfly/react-charts@5.3.18": + version "5.3.18" + resolved "https://registry.yarnpkg.com/@patternfly/react-charts/-/react-charts-5.3.18.tgz#16533bea0c29d24a58f4f0ddcd692ac68707f6d1" + integrity sha512-Cy2OtpIS2qHbaSjF0JFIlBxfuySyT09LovsNLC3Ut5S+Mmpa9c3CPv21EvnPReIPm/VHkyUng+y81XtnMud/og== dependencies: - "@patternfly/patternfly" "2.65.2" - "@patternfly/react-styles" "^3.7.4" - "@patternfly/react-tokens" "^2.8.4" + "@patternfly/patternfly" "2.71.3" + "@patternfly/react-styles" "^3.7.12" + "@patternfly/react-tokens" "^2.8.12" hoist-non-react-statics "^3.3.0" lodash "^4.17.15" victory "^33.0.5" victory-core "^33.0.1" victory-legend "^33.0.1" -"@patternfly/react-core@3.140.11": - version "3.140.11" - resolved "https://registry.yarnpkg.com/@patternfly/react-core/-/react-core-3.140.11.tgz#6350acb17a922d40ca1ab988ee23c470079bcd20" - integrity sha512-841DeN5BTuUS02JfVXAAVJYtWY0HWc4ewqMD32Xog2MAR/pn74jzjnQOSQr4LUyVrH5QufB68SK4Alm2+IUzSw== +"@patternfly/react-core@3.153.3": + version "3.153.3" + resolved "https://registry.yarnpkg.com/@patternfly/react-core/-/react-core-3.153.3.tgz#14a2ae31d10eef40e7b42a8de048082ef2b9d430" + integrity sha512-2ccnn/HPfEhZfj9gfKZJpWgzOA9O6QeCHjZGh41tx7Lz7iZGl9b/UdTmDsQUeYYuJ+0M8fxhYnQMKaDxfcqyOQ== dependencies: - "@patternfly/react-icons" "^3.15.3" - "@patternfly/react-styles" "^3.7.4" - "@patternfly/react-tokens" "^2.8.4" - emotion "^9.2.9" - exenv "^1.2.2" - focus-trap-react "^4.0.1" + "@patternfly/react-icons" "^3.15.15" + "@patternfly/react-styles" "^3.7.12" + "@patternfly/react-tokens" "^2.8.12" + focus-trap "4.0.2" + react-dropzone "9.0.0" tippy.js "5.1.2" -"@patternfly/react-icons@3.15.3", "@patternfly/react-icons@^3.15.3": - version "3.15.3" - resolved "https://registry.yarnpkg.com/@patternfly/react-icons/-/react-icons-3.15.3.tgz#63172a2e3809b110db08e69210b9f458664249f1" - integrity sha512-U+IN0GqymFsiyRCANtVTqcBWlQ+yw0FZP8deQV47HPZIGDp3bSFqQt2AHpVfM02knATZ/pJxzimQOsks00qFvg== +"@patternfly/react-icons@3.15.15", "@patternfly/react-icons@^3.15.15": + version "3.15.15" + resolved "https://registry.yarnpkg.com/@patternfly/react-icons/-/react-icons-3.15.15.tgz#3174a2fd6cbf38e8d938e8a632ea4c4f73cbab05" + integrity sha512-oYOgY7fELe3gKbKB2KRUANpYPWkKkEGpmKdmXonNmNUlg0t/a8V68raVX8bTjXN9pwKsUKqNQW1R+xFibtt0Aw== dependencies: "@fortawesome/free-brands-svg-icons" "^5.8.1" -"@patternfly/react-styles@3.7.4", "@patternfly/react-styles@^3.7.4": - version "3.7.4" - resolved "https://registry.yarnpkg.com/@patternfly/react-styles/-/react-styles-3.7.4.tgz#9d162b5cd0b77047904380a899e02806309bf7f7" - integrity sha512-D+wu0OIfWVgxWNShQhTK9cadw+KdMCoBYR8gbWjV9Q1aCsCEV/aL/x1nMyyaUQ3c2dqizHhujDG4z9jUZCmCcw== +"@patternfly/react-styles@3.7.12", "@patternfly/react-styles@^3.7.12": + version "3.7.12" + resolved "https://registry.yarnpkg.com/@patternfly/react-styles/-/react-styles-3.7.12.tgz#ba942dbf5b5a57b5b57eef2f3fd4d4c6efdd459f" + integrity sha512-vTKyC78oKlrS6VTQ3GPYevc17qgxj2Ono+SCDwoMyhUexPEyXRuZHLoZA1/MkJHvSCqJHGBageBAFcRq5wb0XQ== dependencies: camel-case "^3.0.0" css "^2.2.3" @@ -1214,15 +1596,15 @@ emotion "^9.2.9" emotion-server "^9.2.9" -"@patternfly/react-tokens@2.8.4", "@patternfly/react-tokens@^2.8.4": - version "2.8.4" - resolved "https://registry.yarnpkg.com/@patternfly/react-tokens/-/react-tokens-2.8.4.tgz#20cb17f2196a25d9cc6ae4cc0e79686ea9bf0bbd" - integrity sha512-GlLyutls0bG39Nwl/sv2FUkicwyRNrXQFso+e7Y4470+VOUtSsVSdQz+rTjgPxQ38olKPsSZdtEjqN9o2PbDiw== +"@patternfly/react-tokens@2.8.12", "@patternfly/react-tokens@^2.8.12": + version "2.8.12" + resolved "https://registry.yarnpkg.com/@patternfly/react-tokens/-/react-tokens-2.8.12.tgz#c3a0cf787a9a1c356829522fd5f8c013aa3085f0" + integrity sha512-QyuMaTizuSn9eESl6bcopGKKgFydocc/N8T7OGB6jARBt6gdIoQWcztdBabSIVz/YGoEDw6lKeoNfed8p6GynA== -"@redhat-cloud-services/frontend-components-notifications@1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@redhat-cloud-services/frontend-components-notifications/-/frontend-components-notifications-1.0.1.tgz#273c8b548ab581b19279a81913807747ea4570df" - integrity sha512-0RSc3jeOwvCwpQoa0YyxeiAsmUnr3Lxhdb4QHkZnER5KEjQZOjVY9Cr1XfbwkSdOQvY1UKBDTwXA+9lQ7JFjWQ== +"@redhat-cloud-services/frontend-components-notifications@1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@redhat-cloud-services/frontend-components-notifications/-/frontend-components-notifications-1.0.2.tgz#7debb413949bb409b2c093314bc09c1456902f62" + integrity sha512-OYrkbRff8fYfJQ4i6DdzUjJYQTFoe9EjD01k2EjkLAaqqPLFbso9/xVuvKDYEFHIb4oy7ZpJm+dpW89zad/rdg== dependencies: "@redhat-cloud-services/frontend-components-utilities" "*" @@ -1237,10 +1619,10 @@ commander "^2.20.0" react-content-loader "^3.4.1" -"@redhat-cloud-services/frontend-components@1.0.8": - version "1.0.8" - resolved "https://registry.yarnpkg.com/@redhat-cloud-services/frontend-components/-/frontend-components-1.0.8.tgz#9d3503e6901f1f90dd36cbe765c8c451d35d0a29" - integrity sha512-Dkg9/G++SM+on/9i32QFDoFPOhR1Xu1S6xFvhXLFHw83P7nULls9wJIb0/3NDTBFMzPJoz3NaE82X5oazcSHtg== +"@redhat-cloud-services/frontend-components@1.0.12": + version "1.0.12" + resolved "https://registry.yarnpkg.com/@redhat-cloud-services/frontend-components/-/frontend-components-1.0.12.tgz#eeb4cb5cf8d82dbf395bca17e932bc7efd9ab086" + integrity sha512-+yB9J5b36cJXSHgTjrQ+xim7/wsbfIGyylOpDExU5ypsb/l0TetYZcMAzvyDCXoQu4kGrm3SPWKiQU8c1aiMvw== dependencies: "@redhat-cloud-services/frontend-components-utilities" "*" @@ -1841,7 +2223,7 @@ ajv-keywords@^3.1.0, ajv-keywords@^3.4.1: resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.4.1.tgz#ef916e271c64ac12171fd8384eaae6b2345854da" integrity sha512-RO1ibKvd27e6FEShVFfPALuHI3WjSVNeK5FIsmme/LYRNxjKuNj+Dt7bucLa6NdSv3JcVTyMlm9kGR84z1XpaQ== -ajv@^6.1.0, ajv@^6.10.0, ajv@^6.10.2, ajv@^6.5.5: +ajv@^6.1.0, ajv@^6.10.0, ajv@^6.10.2, ajv@^6.12.0, ajv@^6.5.5: version "6.12.0" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.0.tgz#06d60b96d87b8454a5adaba86e7854da629db4b7" integrity sha512-D6gFiFA0RRLyUbvijN74DWAjXSFxWKaWP7mldxkVhyhAV3+SWA9HEJPHQ2c9soIeTFJqcSdFDGFgdqs1iUU2Hw== @@ -2187,6 +2569,13 @@ atob@^2.1.2: resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== +attr-accept@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/attr-accept/-/attr-accept-1.1.3.tgz#48230c79f93790ef2775fcec4f0db0f5db41ca52" + integrity sha512-iT40nudw8zmCweivz6j58g+RT33I4KbaIvRUhjNmDwO2WmsQUxFEZZYZ5w3vXe5x5MX9D7mfvA/XaLOZYFR9EQ== + dependencies: + core-js "^2.5.0" + autoprefixer@^9.6.1: version "9.7.4" resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-9.7.4.tgz#f8bf3e06707d047f0641d87aee8cfb174b2a5378" @@ -2253,15 +2642,15 @@ babel-code-frame@^6.22.0: esutils "^2.0.2" js-tokens "^3.0.2" -babel-eslint@10.0.3: - version "10.0.3" - resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-10.0.3.tgz#81a2c669be0f205e19462fed2482d33e4687a88a" - integrity sha512-z3U7eMY6r/3f3/JB9mTsLjyxrv0Yb1zb8PCWCLpguxfCzBIZUwy23R1t/XKewP+8mEN2Ck8Dtr4q20z6ce6SoA== +babel-eslint@10.1.0: + version "10.1.0" + resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-10.1.0.tgz#6968e568a910b78fb3779cdd8b6ac2f479943232" + integrity sha512-ifWaTHQ0ce+448CYop8AdrQiBsGrnC+bMgfyKFdi6EsPLTAWG+QfyDeM6OH+FmWnKvEq5NnBMLvlBUPKQZoDSg== dependencies: "@babel/code-frame" "^7.0.0" - "@babel/parser" "^7.0.0" - "@babel/traverse" "^7.0.0" - "@babel/types" "^7.0.0" + "@babel/parser" "^7.7.0" + "@babel/traverse" "^7.7.0" + "@babel/types" "^7.7.0" eslint-visitor-keys "^1.0.0" resolve "^1.12.0" @@ -2285,15 +2674,16 @@ babel-jest@^24.9.0: chalk "^2.4.2" slash "^2.0.0" -babel-loader@8.0.6: - version "8.0.6" - resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-8.0.6.tgz#e33bdb6f362b03f4bb141a0c21ab87c501b70dfb" - integrity sha512-4BmWKtBOBm13uoUwd08UwjZlaw3O9GWf456R9j+5YykFZ6LUIjIKLc0zEZf+hauxPOJs96C8k6FvYD09vWzhYw== +babel-loader@8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-8.1.0.tgz#c611d5112bd5209abe8b9fa84c3e4da25275f1c3" + integrity sha512-7q7nC1tYOrqvUrN3LQK4GwSk/TQorZSOlO9C+RZDZpODgyN4ZlCqE5q9cDsyWOliN+aU9B4JX01xK9eJXowJLw== dependencies: - find-cache-dir "^2.0.0" - loader-utils "^1.0.2" - mkdirp "^0.5.1" + find-cache-dir "^2.1.0" + loader-utils "^1.4.0" + mkdirp "^0.5.3" pify "^4.0.1" + schema-utils "^2.6.5" babel-plugin-dynamic-import-node@^2.3.0: version "2.3.0" @@ -2382,22 +2772,24 @@ babel-preset-jest@^24.9.0: "@babel/plugin-syntax-object-rest-spread" "^7.0.0" babel-plugin-jest-hoist "^24.9.0" -babel-preset-react-app@^9.1.1: - version "9.1.1" - resolved "https://registry.yarnpkg.com/babel-preset-react-app/-/babel-preset-react-app-9.1.1.tgz#d1ceb47cbe48b285fdd5c562c54c432ed5a41e0e" - integrity sha512-YkWP2UwY//TLltNlEBRngDOrYhvSLb+CA330G7T9M5UhGEMWe+JK/8IXJc5p2fDTSfSiETf+PY0+PYXFMix81Q== +babel-preset-react-app@^9.1.2: + version "9.1.2" + resolved "https://registry.yarnpkg.com/babel-preset-react-app/-/babel-preset-react-app-9.1.2.tgz#54775d976588a8a6d1a99201a702befecaf48030" + integrity sha512-k58RtQOKH21NyKtzptoAvtAODuAJJs3ZhqBMl456/GnXEQ/0La92pNmwgWoMn5pBTrsvk3YYXdY7zpY4e3UIxA== dependencies: - "@babel/core" "7.8.4" + "@babel/core" "7.9.0" "@babel/plugin-proposal-class-properties" "7.8.3" "@babel/plugin-proposal-decorators" "7.8.3" + "@babel/plugin-proposal-nullish-coalescing-operator" "7.8.3" "@babel/plugin-proposal-numeric-separator" "7.8.3" - "@babel/plugin-transform-flow-strip-types" "7.8.3" + "@babel/plugin-proposal-optional-chaining" "7.9.0" + "@babel/plugin-transform-flow-strip-types" "7.9.0" "@babel/plugin-transform-react-display-name" "7.8.3" - "@babel/plugin-transform-runtime" "7.8.3" - "@babel/preset-env" "7.8.4" - "@babel/preset-react" "7.8.3" - "@babel/preset-typescript" "7.8.3" - "@babel/runtime" "7.8.4" + "@babel/plugin-transform-runtime" "7.9.0" + "@babel/preset-env" "7.9.0" + "@babel/preset-react" "7.9.1" + "@babel/preset-typescript" "7.9.0" + "@babel/runtime" "7.9.0" babel-plugin-macros "2.8.0" babel-plugin-transform-react-remove-prop-types "0.4.24" @@ -2454,7 +2846,7 @@ big.js@^5.2.2: resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328" integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ== -bignumber.js@^8.0.1: +bignumber.js@^8.1.1: version "8.1.1" resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-8.1.1.tgz#4b072ae5aea9c20f6730e4e5d529df1271c4d885" integrity sha512-QD46ppGintwPGuL1KqmwhR0O+N2cZUg8JG/VzwI2e28sM9TqHjQB10lI4QAaMHVbLzwVLLAwEglpKPViWX+5NQ== @@ -2633,14 +3025,15 @@ browserify-zlib@^0.2.0: dependencies: pako "~1.0.5" -browserslist@4.8.6: - version "4.8.6" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.8.6.tgz#96406f3f5f0755d272e27a66f4163ca821590a7e" - integrity sha512-ZHao85gf0eZ0ESxLfCp73GG9O/VTytYDIkIiZDlURppLTI9wErSM/5yAKEq6rcUdxBLjMELmrYUJGg5sxGKMHg== +browserslist@4.10.0: + version "4.10.0" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.10.0.tgz#f179737913eaf0d2b98e4926ac1ca6a15cbcc6a9" + integrity sha512-TpfK0TDgv71dzuTsEAlQiHeWQ/tiPqgNZVdv046fvNtBZrjbv2O3TsWCDU0AWGJJKCF/KsjNdLzR9hXOsh/CfA== dependencies: - caniuse-lite "^1.0.30001023" - electron-to-chromium "^1.3.341" - node-releases "^1.1.47" + caniuse-lite "^1.0.30001035" + electron-to-chromium "^1.3.378" + node-releases "^1.1.52" + pkg-up "^3.1.0" browserslist@^4.0.0, browserslist@^4.6.2, browserslist@^4.6.4, browserslist@^4.8.3, browserslist@^4.8.5: version "4.8.7" @@ -2651,6 +3044,16 @@ browserslist@^4.0.0, browserslist@^4.6.2, browserslist@^4.6.4, browserslist@^4.8 electron-to-chromium "^1.3.349" node-releases "^1.1.49" +browserslist@^4.9.1: + version "4.11.1" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.11.1.tgz#92f855ee88d6e050e7e7311d987992014f1a1f1b" + integrity sha512-DCTr3kDrKEYNw6Jb9HFxVLQNaue8z+0ZfRBRjmCunKDEXEBajKDj2Y+Uelg+Pi29OnvaSGwjOsnRyNEkXzHg5g== + dependencies: + caniuse-lite "^1.0.30001038" + electron-to-chromium "^1.3.390" + node-releases "^1.1.53" + pkg-up "^2.0.0" + bser@2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/bser/-/bser-2.1.1.tgz#e6787da20ece9d07998533cfd9de6f5c38f4bc05" @@ -2859,11 +3262,16 @@ 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.30001020, caniuse-lite@^1.0.30001023, caniuse-lite@^1.0.30001027: +caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000981, caniuse-lite@^1.0.30001020, caniuse-lite@^1.0.30001027: version "1.0.30001030" resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001030.tgz#78076c4c6d67d3e41d6eb9399853fb27fe6e44ee" integrity sha512-QGK0W4Ft/Ac+zTjEiRJfwDNATvS3fodDczBXrH42784kcfqcDKpEPfN08N0HQjrAp8He/Jw8QiSS9QRn7XAbUw== +caniuse-lite@^1.0.30001035, caniuse-lite@^1.0.30001038: + version "1.0.30001038" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001038.tgz#44da3cbca2ab6cb6aa83d1be5d324e17f141caff" + integrity sha512-zii9quPo96XfOiRD4TrfYGs+QsGZpb2cGiMAzPjtf/hpFgB6zCPZgJb7I1+EATeMw/o+lG8FyRAnI+CWStHcaQ== + capture-exit@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/capture-exit/-/capture-exit-2.0.0.tgz#fb953bfaebeb781f62898239dabb426d08a509a4" @@ -3521,7 +3929,7 @@ core-js-pure@^3.0.0: resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.6.4.tgz#4bf1ba866e25814f149d4e9aaa08c36173506e3a" integrity sha512-epIhRLkXdgv32xIUFaaAry2wdxZYBi6bgM7cB136dzzXXa+dFyRLTZeLUJxnd8ShrmyVXBub63n2NHo2JAt8Cw== -core-js@^2.4.0: +core-js@^2.4.0, core-js@^2.5.0: version "2.6.11" resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.11.tgz#38831469f9922bded8ee21c9dc46985e0399308c" integrity sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg== @@ -4424,11 +4832,16 @@ ee-first@1.1.1: resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= -electron-to-chromium@^1.3.341, electron-to-chromium@^1.3.349: +electron-to-chromium@^1.3.349: version "1.3.361" resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.361.tgz#a820bf52da171c0024314745462cfe0dc944373e" integrity sha512-OzSVjWpsRhJyr9PSAXkeloSe6e9viU2ToGt1wXlXFsGcxuI9vlsnalL+V/AM59Z2pEo3wRxIddtOGsT7Y6x/sQ== +electron-to-chromium@^1.3.378, electron-to-chromium@^1.3.390: + version "1.3.393" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.393.tgz#d13fa4cbf5065e18451c84465d22aef6aca9a911" + integrity sha512-Ko3/VdhZAaMaJBLBFqEJ+M1qMiBI8sJfPY/hSJvDrkB3Do8LJsL9tmXy4w7o9nPXif/jFaZGSlXTQWU8XVsYtg== + elliptic@^6.0.0: version "6.5.2" resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.2.tgz#05c5678d7173c049d8ca433552224a495d0e3762" @@ -4702,17 +5115,17 @@ eslint-config-airbnb@^18.1.0: object.assign "^4.1.0" object.entries "^1.1.1" -eslint-config-prettier@^6.10.0: - version "6.10.0" - resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-6.10.0.tgz#7b15e303bf9c956875c948f6b21500e48ded6a7f" - integrity sha512-AtndijGte1rPILInUdHjvKEGbIV06NuvPrqlIEaEaWtbtvJh464mDeyGMdZEQMsGvC0ZVkiex1fSNcC4HAbRGg== +eslint-config-prettier@^6.10.1: + version "6.10.1" + resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-6.10.1.tgz#129ef9ec575d5ddc0e269667bf09defcd898642a" + integrity sha512-svTy6zh1ecQojvpbJSgH3aei/Rt7C6i090l5f2WQ4aB05lYHeZIR1qL4wZyyILTbtmnbHP5Yn8MrsOJMGa8RkQ== dependencies: get-stdin "^6.0.0" -eslint-config-react-app@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/eslint-config-react-app/-/eslint-config-react-app-5.2.0.tgz#135110ba56a9e378f7acfe5f36e2ae76a2317899" - integrity sha512-WrHjoGpKr1kLLiWDD81tme9jMM0hk5cMxasLSdyno6DdPt+IfLOrDJBVo6jN7tn4y1nzhs43TmUaZWO6Sf0blw== +eslint-config-react-app@^5.2.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/eslint-config-react-app/-/eslint-config-react-app-5.2.1.tgz#698bf7aeee27f0cea0139eaef261c7bf7dd623df" + integrity sha512-pGIZ8t0mFLcV+6ZirRgYK6RVqUIKRIi9MmgzUEmrIknsn3AdO0I32asO86dJgloHq+9ZPl8UIg8mYrvgP5u2wQ== dependencies: confusing-browser-globals "^1.0.9" @@ -4750,10 +5163,10 @@ eslint-plugin-flowtype@4.6.0: dependencies: lodash "^4.17.15" -eslint-plugin-import@2.20.0: - version "2.20.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.20.0.tgz#d749a7263fb6c29980def8e960d380a6aa6aecaa" - integrity sha512-NK42oA0mUc8Ngn4kONOPsPB1XhbUvNHqF+g307dPV28aknPoiNnKLFd9em4nkswwepdF5ouieqv5Th/63U7YJQ== +eslint-plugin-import@2.20.1: + version "2.20.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.20.1.tgz#802423196dcb11d9ce8435a5fc02a6d3b46939b3" + integrity sha512-qQHgFOTjguR+LnYRoToeZWT62XM55MBVXObHM6SKFd1VzDcX/vqT1kAz8ssqigh5eMj8qXcRoXXGZpPP6RfdCw== dependencies: array-includes "^3.0.3" array.prototype.flat "^1.2.1" @@ -4768,10 +5181,10 @@ eslint-plugin-import@2.20.0: read-pkg-up "^2.0.0" resolve "^1.12.0" -eslint-plugin-import@^2.20.1: - version "2.20.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.20.1.tgz#802423196dcb11d9ce8435a5fc02a6d3b46939b3" - integrity sha512-qQHgFOTjguR+LnYRoToeZWT62XM55MBVXObHM6SKFd1VzDcX/vqT1kAz8ssqigh5eMj8qXcRoXXGZpPP6RfdCw== +eslint-plugin-import@^2.20.2: + version "2.20.2" + resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.20.2.tgz#91fc3807ce08be4837141272c8b99073906e588d" + integrity sha512-FObidqpXrR8OnCh4iNsxy+WACztJLXAHBO5hK79T1Hc77PgQZkyDGA5Ag9xAvRpglvLNxhH/zSmZ70/pZ31dHg== dependencies: array-includes "^3.0.3" array.prototype.flat "^1.2.1" @@ -4793,10 +5206,10 @@ eslint-plugin-jest@^23.8.2: dependencies: "@typescript-eslint/experimental-utils" "^2.5.0" -eslint-plugin-jsdoc@^22.0.1: - version "22.0.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-22.0.1.tgz#1f36c41a8818c968e46def7423e0b627841d72b9" - integrity sha512-lqQgGtd+roOhd5lSdIK4P3mlDmTVmVdcehj/r8nY25CGB2yi4Tk6JVwETCPBGnRKd40JkllkchyZmt0tFN+5pw== +eslint-plugin-jsdoc@^22.1.0: + version "22.1.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-22.1.0.tgz#dadfa62653fc0d87f900d810307f5ed07ef6ecd5" + integrity sha512-54NdbICM7KrxsGUqQsev9aIMqPXyvyBx2218Qcm0TQ16P9CtBI+YY4hayJR6adrxlq4Ej0JLpgfUXWaQVFqmQg== dependencies: comment-parser "^0.7.2" debug "^4.1.1" @@ -4841,27 +5254,12 @@ eslint-plugin-react-hooks@^1.6.1: resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-1.7.0.tgz#6210b6d5a37205f0b92858f895a4e827020a7d04" integrity sha512-iXTCFcOmlWvw4+TOE8CLWj6yX1GwzT0Y6cUfHHZqWnSk144VmVIRcVGtUAzrLES7C798lmvnt02C7rxaOX1HNA== -eslint-plugin-react-hooks@^2.5.0: - version "2.5.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-2.5.0.tgz#c50ab7ca5945ce6d1cf8248d9e185c80b54171b6" - integrity sha512-bzvdX47Jx847bgAYf0FPX3u1oxU+mKU8tqrpj4UX9A96SbAmj/HVEefEy6rJUog5u8QIlOPTKZcBpGn5kkKfAQ== - -eslint-plugin-react@7.18.0: - version "7.18.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.18.0.tgz#2317831284d005b30aff8afb7c4e906f13fa8e7e" - integrity sha512-p+PGoGeV4SaZRDsXqdj9OWcOrOpZn8gXoGPcIQTzo2IDMbAKhNDnME9myZWqO3Ic4R3YmwAZ1lDjWl2R2hMUVQ== - dependencies: - array-includes "^3.1.1" - doctrine "^2.1.0" - has "^1.0.3" - jsx-ast-utils "^2.2.3" - object.entries "^1.1.1" - object.fromentries "^2.0.2" - object.values "^1.1.1" - prop-types "^15.7.2" - resolve "^1.14.2" +eslint-plugin-react-hooks@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-3.0.0.tgz#9e80c71846eb68dd29c3b21d832728aa66e5bd35" + integrity sha512-EjxTHxjLKIBWFgDJdhKKzLh5q+vjTFrqNZX36uIxWS4OfyXe5DawqPj3U5qeJ1ngLwatjzQnmR0Lz0J0YH3kxw== -eslint-plugin-react@^7.19.0: +eslint-plugin-react@7.19.0, eslint-plugin-react@^7.19.0: version "7.19.0" resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.19.0.tgz#6d08f9673628aa69c5559d33489e855d83551666" integrity sha512-SPT8j72CGuAP+JFbT0sJHOB80TX/pu44gQ4vXH/cq+hQTiY2PuZ6IHkqXJV6x1b28GDdo1lbInjKUrrdUf0LOQ== @@ -5036,11 +5434,6 @@ execa@^1.0.0: signal-exit "^3.0.0" strip-eof "^1.0.0" -exenv@^1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/exenv/-/exenv-1.2.2.tgz#2ae78e85d9894158670b03d47bec1f03bd91bb9d" - integrity sha1-KueOhdmJQVhnCwPUe+wfA72Ru50= - exit@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" @@ -5264,6 +5657,13 @@ file-loader@4.3.0: loader-utils "^1.2.3" schema-utils "^2.5.0" +file-selector@^0.1.8: + version "0.1.12" + resolved "https://registry.yarnpkg.com/file-selector/-/file-selector-0.1.12.tgz#fe726547be219a787a9dcc640575a04a032b1fd0" + integrity sha512-Kx7RTzxyQipHuiqyZGf+Nz4vY9R1XGxuQl/hLoJwq+J4avk/9wxxgZyHKtbyIPJmbD4A66DWGYfyykWNpcYutQ== + dependencies: + tslib "^1.9.0" + file-uri-to-path@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd" @@ -5313,7 +5713,7 @@ find-cache-dir@^0.1.1: mkdirp "^0.5.1" pkg-dir "^1.0.0" -find-cache-dir@^2.0.0, find-cache-dir@^2.1.0: +find-cache-dir@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-2.1.0.tgz#8d0f94cd13fe43c6c7c261a0d86115ca918c05f7" integrity sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ== @@ -5393,19 +5793,12 @@ flush-write-stream@^1.0.0: inherits "^2.0.3" readable-stream "^2.3.6" -focus-trap-react@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/focus-trap-react/-/focus-trap-react-4.0.1.tgz#3cffd39341df3b2f546a4a2fe94cfdea66154683" - integrity sha512-UUZKVEn5cFbF6yUnW7lbXNW0iqN617ShSqYKgxctUvWw1wuylLtyVmC0RmPQNnJ/U+zoKc/djb0tZMs0uN/0QQ== - dependencies: - focus-trap "^3.0.0" - -focus-trap@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/focus-trap/-/focus-trap-3.0.0.tgz#4d2ee044ae66bf7eb6ebc6c93bd7a1039481d7dc" - integrity sha512-jTFblf0tLWbleGjj2JZsAKbgtZTdL1uC48L8FcmSDl4c2vDoU4NycN1kgV5vJhuq1mxNFkw7uWZ1JAGlINWvyw== +focus-trap@4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/focus-trap/-/focus-trap-4.0.2.tgz#4ee2b96547c9ea0e4252a2d4b2cca68944194663" + integrity sha512-HtLjfAK7Hp2qbBtLS6wEznID1mPT+48ZnP2nkHzgjpL4kroYHg0CdqJ5cTXk+UO5znAxF5fRUkhdyfgrhh8Lzw== dependencies: - tabbable "^3.1.0" + tabbable "^3.1.2" xtend "^4.0.1" follow-redirects@1.5.10: @@ -6192,10 +6585,10 @@ i18next-xhr-backend@^3.2.2: dependencies: "@babel/runtime" "^7.5.5" -i18next@^19.3.2: - version "19.3.2" - resolved "https://registry.yarnpkg.com/i18next/-/i18next-19.3.2.tgz#a17c3c8bb0dd2d8c4a8963429df99730275b3282" - integrity sha512-QDBQ8MqFWi4+L9OQjjZEKVyg9uSTy3NTU3Ri53QHe7nxtV+KD4PyLB8Kxu58gr6b9y5l8cU3mCiNHVeoxPMzAQ== +i18next@^19.3.4: + version "19.3.4" + resolved "https://registry.yarnpkg.com/i18next/-/i18next-19.3.4.tgz#512de50ee6075df825c646e1ce646a104f0938c9" + integrity sha512-ef7AxxutzdhBsBNugE9jgqsbwesG1muJOtZ9ZrPARPs/jXegViTp4+8JCeMp8BAyTIo1Zn0giqc8+2UpqFjU0w== dependencies: "@babel/runtime" "^7.3.1" @@ -7400,6 +7793,13 @@ json5@^2.1.0: dependencies: minimist "^1.2.0" +json5@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/json5/-/json5-2.1.2.tgz#43ef1f0af9835dd624751a6b7fa48874fb2d608e" + integrity sha512-MoUOQ4WdiN3yxhm7NEVJSJrieAo5hNSLQ5sj05OTRHPL9HOBy8u4Bu88jsC1jvqAdN+E1bJmsUcZH+1HQxliqQ== + dependencies: + minimist "^1.2.5" + jsonc-parser@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-2.2.1.tgz#db73cd59d78cce28723199466b2a03d1be1df2bc" @@ -7624,7 +8024,7 @@ loader-utils@1.2.3: emojis-list "^2.0.0" json5 "^1.0.1" -loader-utils@^1.0.2, loader-utils@^1.1.0, loader-utils@^1.2.3: +loader-utils@^1.1.0, loader-utils@^1.2.3, loader-utils@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.4.0.tgz#c579b5e34cb34b1a74edc6c1fb36bfa371d5a613" integrity sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA== @@ -8096,6 +8496,11 @@ minimist@^1.1.1, minimist@^1.1.3, minimist@^1.2.0: resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ= +minimist@^1.2.5: + version "1.2.5" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" + integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== + minimist@~0.0.1, minimist@~0.0.8: version "0.0.10" resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf" @@ -8168,6 +8573,13 @@ mkdirp@0.5.1, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.1: dependencies: minimist "0.0.8" +mkdirp@^0.5.3: + version "0.5.4" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.4.tgz#fd01504a6797ec5c9be81ff43d204961ed64a512" + integrity sha512-iG9AK/dJLtJ0XNgTuDbSyNS3zECqDlAhnQW4CsNxBG3LQJBbHmRX1egw39DmtOdCAqY+dKXV+sgPgilNWUKMVw== + dependencies: + minimist "^1.2.5" + modify-values@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/modify-values/-/modify-values-1.0.1.tgz#b3939fa605546474e3e3e3c63d64bd43b4ee6022" @@ -8392,13 +8804,18 @@ node-notifier@^5.4.2: shellwords "^0.1.1" which "^1.3.0" -node-releases@^1.1.47, node-releases@^1.1.49: +node-releases@^1.1.49: version "1.1.50" resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.50.tgz#803c40d2c45db172d0410e4efec83aa8c6ad0592" integrity sha512-lgAmPv9eYZ0bGwUYAKlr8MG6K4CvWliWqnkcT2P8mMAgVrH3lqfBPorFlxiG1pHQnqmavJZ9vbMXUTNyMLbrgQ== dependencies: semver "^6.3.0" +node-releases@^1.1.52, node-releases@^1.1.53: + version "1.1.53" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.53.tgz#2d821bfa499ed7c5dffc5e2f28c88e78a08ee3f4" + integrity sha512-wp8zyQVwef2hpZ/dJH7SfSrIPD6YoJz6BDQDpGEkcA0s3LpAQoxBIYmfIq6QAhC1DhwsyCgTaTTcONwX8qzCuQ== + node-sass@^4.13.1: version "4.13.1" resolved "https://registry.yarnpkg.com/node-sass/-/node-sass-4.13.1.tgz#9db5689696bb2eec2c32b98bfea4c7a2e992d0a3" @@ -8537,12 +8954,12 @@ number-is-nan@^1.0.0: resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0= -numbro@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/numbro/-/numbro-2.1.2.tgz#2d51104f09b5d69aef7e15bb565d7795e47ecfd6" - integrity sha512-7w833BxZmKGLE9HI0aREtNVRVH6WTYUUlWf4qgA5gKNhPQ4F/MRZ14sc0v8eoLORprk9ZTVwYaLwj8N3Zgxwiw== +numbro@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/numbro/-/numbro-2.2.0.tgz#6e40e21e0eff55553d45a0d0fd4f7bf6cd2ab1ea" + integrity sha512-qgIU8Zfz2A7Nu9ILL0jV1hfriG5v1G8+b19zyrQNK8spUmJaHcn1YYXzNDRrb7IXBlTrW61ZUsKT/bCijeEGiQ== dependencies: - bignumber.js "^8.0.1" + bignumber.js "^8.1.1" nwsapi@^2.0.7, nwsapi@^2.1.3: version "2.2.0" @@ -9167,24 +9584,31 @@ pkg-dir@^4.1.0: dependencies: find-up "^4.0.0" -pkg-up@3.1.0: +pkg-up@3.1.0, pkg-up@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/pkg-up/-/pkg-up-3.1.0.tgz#100ec235cc150e4fd42519412596a28512a0def5" integrity sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA== dependencies: find-up "^3.0.0" +pkg-up@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/pkg-up/-/pkg-up-2.0.0.tgz#c819ac728059a461cab1c3889a2be3c49a004d7f" + integrity sha1-yBmscoBZpGHKscOImivjxJoATX8= + dependencies: + find-up "^2.1.0" + pn@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/pn/-/pn-1.1.0.tgz#e2f4cef0e219f463c179ab37463e4e1ecdccbafb" integrity sha512-2qHaIQr2VLRFoxe2nASzsV6ef4yOOH+Fi9FBOVH6cqeSgUnoyySPZkxzLuzd+RYOQTRpROA0ztTMqxROKSb/nA== -pnp-webpack-plugin@1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/pnp-webpack-plugin/-/pnp-webpack-plugin-1.6.0.tgz#d5c068013a2fdc82224ca50ed179c8fba9036a8e" - integrity sha512-ZcMGn/xF/fCOq+9kWMP9vVVxjIkMCja72oy3lziR7UHy0hHFZ57iVpQ71OtveVbmzeCmphBg8pxNdk/hlK99aQ== +pnp-webpack-plugin@1.6.4: + version "1.6.4" + resolved "https://registry.yarnpkg.com/pnp-webpack-plugin/-/pnp-webpack-plugin-1.6.4.tgz#c9711ac4dc48a685dabafc86f8b6dd9f8df84149" + integrity sha512-7Wjy+9E3WwLOEL30D+m8TSTF7qJJUJLONBnwQp0518siuMxUQUbgZwssaFX+QKlZkjHZcw/IpZCt/H0srrntSg== dependencies: - ts-pnp "^1.1.2" + ts-pnp "^1.1.6" pofile@1.0.x: version "1.0.11" @@ -9916,7 +10340,7 @@ pretty-format@^24.9.0: ansi-styles "^3.2.0" react-is "^16.8.4" -private@^0.1.6: +private@^0.1.6, private@^0.1.8: version "0.1.8" resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff" integrity sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg== @@ -9965,6 +10389,14 @@ prop-types-exact@^1.2.0: object.assign "^4.1.0" reflect.ownkeys "^0.2.0" +prop-types-extra@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/prop-types-extra/-/prop-types-extra-1.1.1.tgz#58c3b74cbfbb95d304625975aa2f0848329a010b" + integrity sha512-59+AHNnHYCdiC+vMwY52WmvP5dM3QLeoumYuEyceQDi9aEhtwN9zIQ2ZNo25sMyXnbh32h+P1ezDsUpUH3JAew== + dependencies: + react-is "^16.3.2" + warning "^4.0.0" + prop-types@^15.5.8, prop-types@^15.6.2, prop-types@^15.7.2: version "15.7.2" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5" @@ -10159,14 +10591,14 @@ react-content-loader@^3.4.1: resolved "https://registry.yarnpkg.com/react-content-loader/-/react-content-loader-3.4.2.tgz#187fbec2aa389635e4613faa046713f196173f40" integrity sha512-UsL3uyPUBZbaPXr52E+MMIOjs7qr6QpcCiF9Xt7we0ACEMAFYp6rWNxVwJbk4/1Peqe9Deajs0PRW5ymvyF5SA== -react-dev-utils@^10.2.0: - version "10.2.0" - resolved "https://registry.yarnpkg.com/react-dev-utils/-/react-dev-utils-10.2.0.tgz#b11cc48aa2be2502fb3c27a50d1dfa95cfa9dfe0" - integrity sha512-MwrvQW2TFjLblhqpDNeqCXHBkz3G5vc7k4wntgutAJZX4ia3o07eGKo6uYGhUOeJ0hfOxcpJFNFk7+4XCc1S8g== +react-dev-utils@^10.2.1: + version "10.2.1" + resolved "https://registry.yarnpkg.com/react-dev-utils/-/react-dev-utils-10.2.1.tgz#f6de325ae25fa4d546d09df4bb1befdc6dd19c19" + integrity sha512-XxTbgJnYZmxuPtY3y/UV0D8/65NKkmaia4rXzViknVnZeVlklSh8u6TnaEYPfAi/Gh1TP4mEOXHI6jQOPbeakQ== dependencies: "@babel/code-frame" "7.8.3" address "1.1.2" - browserslist "4.8.6" + browserslist "4.10.0" chalk "2.4.2" cross-spawn "7.0.1" detect-port-alt "1.1.6" @@ -10183,36 +10615,46 @@ react-dev-utils@^10.2.0: loader-utils "1.2.3" open "^7.0.2" pkg-up "3.1.0" - react-error-overlay "^6.0.6" + react-error-overlay "^6.0.7" recursive-readdir "2.2.2" shell-quote "1.7.2" strip-ansi "6.0.0" text-table "0.2.0" -react-dom@^16.13.0: - version "16.13.0" - resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.13.0.tgz#cdde54b48eb9e8a0ca1b3dc9943d9bb409b81866" - integrity sha512-y09d2c4cG220DzdlFkPTnVvGTszVvNpC73v+AaLGLHbkpy3SSgvYq8x0rNwPJ/Rk/CicTNgk0hbHNw1gMEZAXg== +react-dom@^16.13.1: + version "16.13.1" + resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.13.1.tgz#c1bd37331a0486c078ee54c4740720993b2e0e7f" + integrity sha512-81PIMmVLnCNLO/fFOQxdQkvEq/+Hfpv24XNJfpyZhTRfO0QcmQIF/PgCa1zCOj2w1hrn12MFLyaJ/G0+Mxtfag== dependencies: loose-envify "^1.1.0" object-assign "^4.1.1" prop-types "^15.6.2" - scheduler "^0.19.0" + scheduler "^0.19.1" -react-error-overlay@^6.0.6: - version "6.0.6" - resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-6.0.6.tgz#ac4d9dc4c1b5c536c2c312bf66aa2b09bfa384e2" - integrity sha512-Yzpno3enVzSrSCnnljmr4b/2KUQSMZaPuqmS26t9k4nW7uwJk6STWmH9heNjPuvqUTO3jOSPkHoKgO4+Dw7uIw== +react-dropzone@9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/react-dropzone/-/react-dropzone-9.0.0.tgz#4f5223cdcb4d3bd8a66e3298c4041eb0c75c4634" + integrity sha512-wZ2o9B2qkdE3RumWhfyZT9swgJYJPeU5qHEcMU8weYpmLex1eeWX0CC32/Y0VutB+BBi2D+iePV/YZIiB4kZGw== + dependencies: + attr-accept "^1.1.3" + file-selector "^0.1.8" + prop-types "^15.6.2" + prop-types-extra "^1.1.0" + +react-error-overlay@^6.0.7: + version "6.0.7" + resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-6.0.7.tgz#1dcfb459ab671d53f660a991513cb2f0a0553108" + integrity sha512-TAv1KJFh3RhqxNvhzxj6LeT5NWklP6rDr2a0jaTfsZ5wSZWHOGeqQyejUp3xxLfPt2UpyJEcVQB/zyPcmonNFA== react-fast-compare@^2.0.0: version "2.0.4" resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-2.0.4.tgz#e84b4d455b0fec113e0402c329352715196f81f9" integrity sha512-suNP+J1VU1MWFKcyt7RtjiSWUjvidmQSlqu+eHslq+342xCbGTYmC0mEhPCOHxlW0CywylOC1u2DFAT+bv4dBw== -react-i18next@^11.3.3: - version "11.3.3" - resolved "https://registry.yarnpkg.com/react-i18next/-/react-i18next-11.3.3.tgz#a84dcc32e3ad013012964d836790d8c6afac8e88" - integrity sha512-sGnPwJ0Kf8qTRLTnTRk030KiU6WYEZ49rP9ILPvCnsmgEKyucQfTxab+klSYnCSKYija+CWL+yo+c9va9BmJeg== +react-i18next@^11.3.4: + version "11.3.4" + resolved "https://registry.yarnpkg.com/react-i18next/-/react-i18next-11.3.4.tgz#355df5fe5133e5e30302d166f529678100ffc968" + integrity sha512-IRZMD7PAM3C+fJNzRbyLNi1ZD0kc3Z3obBspJjEl+9H+ME41PhVor3BpdIqv/Rm7lUoGhMjmpu42J45ooJ61KA== dependencies: "@babel/runtime" "^7.3.1" html-parse-stringify2 "2.0.1" @@ -10222,6 +10664,11 @@ react-is@^16.12.0, react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.1, react-i resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.12.0.tgz#2cc0fe0fba742d97fd527c42a13bec4eeb06241c" integrity sha512-rPCkf/mWBtKc97aLL9/txD8DZdemK0vkA3JMLShjlJB3Pj3s+lpf1KaBzMfQrAmhMQB0n1cU/SUGgKKBCe837Q== +react-is@^16.3.2: + 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-redux@^7.2.0: version "7.2.0" resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-7.2.0.tgz#f970f62192b3981642fec46fd0db18a074fe879d" @@ -10262,32 +10709,32 @@ react-router@5.1.2, react-router@^5.1.2: tiny-invariant "^1.0.2" tiny-warning "^1.0.0" -react-scripts@3.4.0: - version "3.4.0" - resolved "https://registry.yarnpkg.com/react-scripts/-/react-scripts-3.4.0.tgz#f413680f0b5b937c8879ba1ffdae9b8c5b364bf5" - integrity sha512-pBqaAroFoHnFAkuX+uSK9Th1uEh2GYdGY2IG1I9/7HmuEf+ls3lLCk1p2GFYRSrLMz6ieQR/SyN6TLIGK3hKRg== +react-scripts@3.4.1: + version "3.4.1" + resolved "https://registry.yarnpkg.com/react-scripts/-/react-scripts-3.4.1.tgz#f551298b5c71985cc491b9acf3c8e8c0ae3ada0a" + integrity sha512-JpTdi/0Sfd31mZA6Ukx+lq5j1JoKItX7qqEK4OiACjVQletM1P38g49d9/D0yTxp9FrSF+xpJFStkGgKEIRjlQ== dependencies: - "@babel/core" "7.8.4" + "@babel/core" "7.9.0" "@svgr/webpack" "4.3.3" "@typescript-eslint/eslint-plugin" "^2.10.0" "@typescript-eslint/parser" "^2.10.0" - babel-eslint "10.0.3" + babel-eslint "10.1.0" babel-jest "^24.9.0" - babel-loader "8.0.6" + babel-loader "8.1.0" babel-plugin-named-asset-import "^0.3.6" - babel-preset-react-app "^9.1.1" + babel-preset-react-app "^9.1.2" camelcase "^5.3.1" case-sensitive-paths-webpack-plugin "2.3.0" css-loader "3.4.2" dotenv "8.2.0" dotenv-expand "5.1.0" eslint "^6.6.0" - eslint-config-react-app "^5.2.0" + eslint-config-react-app "^5.2.1" eslint-loader "3.0.3" eslint-plugin-flowtype "4.6.0" - eslint-plugin-import "2.20.0" + eslint-plugin-import "2.20.1" eslint-plugin-jsx-a11y "6.2.3" - eslint-plugin-react "7.18.0" + eslint-plugin-react "7.19.0" eslint-plugin-react-hooks "^1.6.1" file-loader "4.3.0" fs-extra "^8.1.0" @@ -10299,24 +10746,24 @@ react-scripts@3.4.0: jest-watch-typeahead "0.4.2" mini-css-extract-plugin "0.9.0" optimize-css-assets-webpack-plugin "5.0.3" - pnp-webpack-plugin "1.6.0" + pnp-webpack-plugin "1.6.4" postcss-flexbugs-fixes "4.1.0" postcss-loader "3.0.0" postcss-normalize "8.0.1" postcss-preset-env "6.7.0" postcss-safe-parser "4.0.1" react-app-polyfill "^1.0.6" - react-dev-utils "^10.2.0" + react-dev-utils "^10.2.1" resolve "1.15.0" resolve-url-loader "3.1.1" sass-loader "8.0.2" semver "6.3.0" style-loader "0.23.1" - terser-webpack-plugin "2.3.4" - ts-pnp "1.1.5" + terser-webpack-plugin "2.3.5" + ts-pnp "1.1.6" url-loader "2.3.0" - webpack "4.41.5" - webpack-dev-server "3.10.2" + webpack "4.42.0" + webpack-dev-server "3.10.3" webpack-manifest-plugin "2.2.0" workbox-webpack-plugin "4.3.1" optionalDependencies: @@ -10332,10 +10779,10 @@ react-test-renderer@^16.0.0-0: react-is "^16.8.6" scheduler "^0.18.0" -react@^16.13.0: - version "16.13.0" - resolved "https://registry.yarnpkg.com/react/-/react-16.13.0.tgz#d046eabcdf64e457bbeed1e792e235e1b9934cf7" - integrity sha512-TSavZz2iSLkq5/oiE7gnFzmURKZMltmi193rm5HEoUDAXpzT9Kzw6oNZnGoai/4+fUnm7FqS5dwgUL34TujcWQ== +react@^16.13.1: + version "16.13.1" + resolved "https://registry.yarnpkg.com/react/-/react-16.13.1.tgz#2e818822f1a9743122c063d6410d85c1e3afe48e" + integrity sha512-YMZQQq32xHLX0bz5Mnibv1/LHb3Sqzngu7xstSM+vrkE5Kzr9xE0yMByK5kMoTK30YVJE61WfbxIFFvfeDKT1w== dependencies: loose-envify "^1.1.0" object-assign "^4.1.1" @@ -10522,6 +10969,13 @@ regenerate-unicode-properties@^8.1.0: dependencies: regenerate "^1.4.0" +regenerate-unicode-properties@^8.2.0: + version "8.2.0" + resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-8.2.0.tgz#e5de7111d655e7ba60c057dbe9ff37c87e65cdec" + integrity sha512-F9DjY1vKLo/tPePDycuH3dn9H1OTPIkVD9Kz4LODu+F2C75mgjAJ7x/gwy6ZcSNRAAkhNlJSOHRe8k3p+K9WhA== + dependencies: + regenerate "^1.4.0" + regenerate@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.0.tgz#4a856ec4b56e4077c557589cae85e7a4c8869a11" @@ -10549,6 +11003,14 @@ regenerator-transform@^0.14.0: dependencies: private "^0.1.6" +regenerator-transform@^0.14.2: + version "0.14.4" + resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.14.4.tgz#5266857896518d1616a78a0479337a30ea974cc7" + integrity sha512-EaJaKPBI9GvKpvUz2mz4fhx7WPgvwRLY9v3hlNHWmAuJHI13T4nwKnNvm5RWJzEdnI5g5UwtOww+S8IdoUC2bw== + dependencies: + "@babel/runtime" "^7.8.4" + private "^0.1.8" + regex-not@^1.0.0, regex-not@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c" @@ -10592,12 +11054,24 @@ regexpu-core@^4.6.0: unicode-match-property-ecmascript "^1.0.4" unicode-match-property-value-ecmascript "^1.1.0" +regexpu-core@^4.7.0: + version "4.7.0" + resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-4.7.0.tgz#fcbf458c50431b0bb7b45d6967b8192d91f3d938" + integrity sha512-TQ4KXRnIn6tz6tjnrXEkD/sshygKH/j5KzK86X8MkeHyZ8qst/LZ89j3X4/8HEIfHANTFIP/AbXakeRhWIl5YQ== + dependencies: + regenerate "^1.4.0" + regenerate-unicode-properties "^8.2.0" + regjsgen "^0.5.1" + regjsparser "^0.6.4" + unicode-match-property-ecmascript "^1.0.4" + unicode-match-property-value-ecmascript "^1.2.0" + regextras@^0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/regextras/-/regextras-0.7.0.tgz#2298bef8cfb92b1b7e3b9b12aa8f69547b7d71e4" integrity sha512-ds+fL+Vhl918gbAUb0k2gVKbTZLsg84Re3DI6p85Et0U0tYME3hyW4nMK8Px4dtDaBA2qNjvG5uWyW7eK5gfmw== -regjsgen@^0.5.0: +regjsgen@^0.5.0, regjsgen@^0.5.1: version "0.5.1" resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.5.1.tgz#48f0bf1a5ea205196929c0d9798b42d1ed98443c" integrity sha512-5qxzGZjDs9w4tzT3TPhCJqWdCc3RLYwy9J2NB0nm5Lz+S273lvWcpjaTGHsT1dc6Hhfq41uSEOw8wBmxrKOuyg== @@ -10609,6 +11083,13 @@ regjsparser@^0.6.0: dependencies: jsesc "~0.5.0" +regjsparser@^0.6.4: + version "0.6.4" + resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.6.4.tgz#a769f8684308401a66e9b529d2436ff4d0666272" + integrity sha512-64O87/dPDgfk8/RQqC4gkZoGyyWFIEUTTh80CU6CWuK5vkCGyekIx+oKcEIYtP/RAxSQltCZHCNu/mdd7fqlJw== + dependencies: + jsesc "~0.5.0" + relateurl@^0.2.7: version "0.2.7" resolved "https://registry.yarnpkg.com/relateurl/-/relateurl-0.2.7.tgz#54dbf377e51440aca90a4cd274600d3ff2d888a9" @@ -10769,7 +11250,7 @@ resolve@1.15.0: dependencies: path-parse "^1.0.6" -resolve@^1.10.0, resolve@^1.12.0, resolve@^1.13.1, resolve@^1.14.2, resolve@^1.15.1, resolve@^1.3.2, resolve@^1.8.1: +resolve@^1.10.0, resolve@^1.12.0, resolve@^1.13.1, resolve@^1.15.1, resolve@^1.3.2, resolve@^1.8.1: version "1.15.1" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.15.1.tgz#27bdcdeffeaf2d6244b95bb0f9f4b4653451f3e8" integrity sha512-84oo6ZTtoTUpjgNEr5SJyzQhzL72gaRodsSfyxC/AXRvwu0Yse9H8eF9IpGo7b8YetZhlI6v7ZQ6bKBFV/6S7w== @@ -10956,10 +11437,10 @@ scheduler@^0.18.0: loose-envify "^1.1.0" object-assign "^4.1.1" -scheduler@^0.19.0: - version "0.19.0" - resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.19.0.tgz#a715d56302de403df742f4a9be11975b32f5698d" - integrity sha512-xowbVaTPe9r7y7RUejcK73/j8tt2jfiyTednOvHbA8JoClvMYCp+r8QegLwK/n8zWQAtZb1fFnER4XLBZXrCxA== +scheduler@^0.19.1: + version "0.19.1" + resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.19.1.tgz#4f3e2ed2c1a7d65681f4c854fa8c5a1ccb40f196" + integrity sha512-n/zwRWRYSUj0/3g/otKDRPMh6qv2SYMWNq85IEa8iZyAv8od9zDYpGSnpBEjNgcMNq6Scbu5KfIPxNF72R/2EA== dependencies: loose-envify "^1.1.0" object-assign "^4.1.1" @@ -10981,6 +11462,14 @@ schema-utils@^2.5.0, schema-utils@^2.6.0, schema-utils@^2.6.1, schema-utils@^2.6 ajv "^6.10.2" ajv-keywords "^3.4.1" +schema-utils@^2.6.5: + version "2.6.5" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-2.6.5.tgz#c758f0a7e624263073d396e29cd40aa101152d8a" + integrity sha512-5KXuwKziQrTVHh8j/Uxz+QUbxkaLW9X/86NBlx/gnKgtsZA2GIVMUn17qWhRFwF8jdYb3Dig5hRO/W5mZqy6SQ== + dependencies: + ajv "^6.12.0" + ajv-keywords "^3.4.1" + scss-tokenizer@^0.2.3: version "0.2.3" resolved "https://registry.yarnpkg.com/scss-tokenizer/-/scss-tokenizer-0.2.3.tgz#8eb06db9a9723333824d3f5530641149847ce5d1" @@ -11798,10 +12287,10 @@ swagger-ui-dist@^3.18.1: resolved "https://registry.yarnpkg.com/swagger-ui-dist/-/swagger-ui-dist-3.25.0.tgz#90279cdcc56e591fcfbe7b5240a9d653b989336d" integrity sha512-vwvJPPbdooTvDwLGzjIXinOXizDJJ6U1hxnJL3y6U3aL1d2MSXDmKg2139XaLBhsVZdnQJV2bOkX4reB+RXamg== -swagger-ui-express@^4.1.3: - version "4.1.3" - resolved "https://registry.yarnpkg.com/swagger-ui-express/-/swagger-ui-express-4.1.3.tgz#90ba85e03f02e2e240e04fd62f4c62fdf358f4d5" - integrity sha512-f8SEn4YWkKh/HGK0ZjuA2VqA78i1aY6OIa5cqYNgOkBobfHV6Mz4dphQW/us8HYhEFfbENq329PyfIonWfzFrw== +swagger-ui-express@^4.1.4: + version "4.1.4" + resolved "https://registry.yarnpkg.com/swagger-ui-express/-/swagger-ui-express-4.1.4.tgz#8b814ad998b850a1cf90e71808d6d0a8a8daf742" + integrity sha512-Ea96ecpC+Iq9GUqkeD/LFR32xSs8gYqmTW1gXCuKg81c26WV6ZC2FsBSPVExQP6WkyUuz5HEiR0sEv/HCC343g== dependencies: swagger-ui-dist "^3.18.1" @@ -11815,7 +12304,7 @@ symbol-tree@^3.2.2: resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2" integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw== -tabbable@^3.1.0: +tabbable@^3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/tabbable/-/tabbable-3.1.2.tgz#f2d16cccd01f400e38635c7181adfe0ad965a4a2" integrity sha512-wjB6puVXTYO0BSFtCmWQubA/KIn7Xvajw0x0l6eJUudMG/EAiJvIUnyNX6xO4NpGrJ16lbD0eUseB9WxW0vlpQ== @@ -11844,10 +12333,10 @@ tar@^2.0.0: fstream "^1.0.12" inherits "2" -terser-webpack-plugin@2.3.4: - version "2.3.4" - resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-2.3.4.tgz#ac045703bd8da0936ce910d8fb6350d0e1dee5fe" - integrity sha512-Nv96Nws2R2nrFOpbzF6IxRDpIkkIfmhvOws+IqMvYdFLO7o6wAILWFKONFgaYy8+T4LVz77DQW0f7wOeDEAjrg== +terser-webpack-plugin@2.3.5: + version "2.3.5" + resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-2.3.5.tgz#5ad971acce5c517440ba873ea4f09687de2f4a81" + integrity sha512-WlWksUoq+E4+JlJ+h+U+QUzXpcsMSSNXkDy9lBVkSqDn1w23Gg29L/ary9GeJVYCGiNJJX7LnVc4bwL1N3/g1w== dependencies: cacache "^13.0.1" find-cache-dir "^3.2.0" @@ -12083,16 +12572,16 @@ triple-beam@^1.2.0, triple-beam@^1.3.0: dependencies: glob "^7.1.2" -ts-pnp@1.1.5: - version "1.1.5" - resolved "https://registry.yarnpkg.com/ts-pnp/-/ts-pnp-1.1.5.tgz#840e0739c89fce5f3abd9037bb091dbff16d9dec" - integrity sha512-ti7OGMOUOzo66wLF3liskw6YQIaSsBgc4GOAlWRnIEj8htCxJUxskanMUoJOD6MDCRAXo36goXJZch+nOS0VMA== - -ts-pnp@^1.1.2: +ts-pnp@1.1.6: version "1.1.6" resolved "https://registry.yarnpkg.com/ts-pnp/-/ts-pnp-1.1.6.tgz#389a24396d425a0d3162e96d2b4638900fdc289a" integrity sha512-CrG5GqAAzMT7144Cl+UIFP7mz/iIhiy+xQ6GGcnjTezhALT02uPMRw7tgDSESgB5MsfKt55+GPWw4ir1kVtMIQ== +ts-pnp@^1.1.6: + version "1.2.0" + resolved "https://registry.yarnpkg.com/ts-pnp/-/ts-pnp-1.2.0.tgz#a500ad084b0798f1c3071af391e65912c86bca92" + integrity sha512-csd+vJOb/gkzvcCHgTGSChYpy5f1/XKNsmvBGO4JXS+z1v2HobugDz4s1IeFXM3wZB44uczs+eazB5Q/ccdhQw== + tslib@^1.10.0, tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3: version "1.11.0" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.11.0.tgz#f1f3528301621a53220d58373ae510ff747a66bc" @@ -12193,6 +12682,11 @@ unicode-match-property-value-ecmascript@^1.1.0: resolved "https://registry.yarnpkg.com/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.1.0.tgz#5b4b426e08d13a80365e0d657ac7a6c1ec46a277" integrity sha512-hDTHvaBk3RmFzvSl0UVrUmC3PuW9wKVnpoUDYH0JDkSIovzw+J5viQmeYHxVSBptubnr7PbH2e0fnpDRQnQl5g== +unicode-match-property-value-ecmascript@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.2.0.tgz#0d91f600eeeb3096aa962b1d6fc88876e64ea531" + integrity sha512-wjuQHGQVofmSJv1uVISKLE5zO2rNGzM/KCYZch/QQvez7C1hUhBIuZ701fYXExuufJFMPhv2SyL8CyoIfMLbIQ== + unicode-property-aliases-ecmascript@^1.0.4: version "1.0.5" resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.0.5.tgz#a9cc6cc7ce63a0a3023fc99e341b94431d405a57" @@ -13025,6 +13519,13 @@ walker@^1.0.7, walker@~1.0.5: dependencies: makeerror "1.0.x" +warning@^4.0.0: + 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@^1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.6.0.tgz#4bc12c2ebe8aa277a71f1d3f14d685c7b446cd00" @@ -13057,10 +13558,10 @@ webpack-dev-middleware@^3.7.2: range-parser "^1.2.1" webpack-log "^2.0.0" -webpack-dev-server@3.10.2: - version "3.10.2" - resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-3.10.2.tgz#3403287d674c7407aab6d9b3f72259ecd0aa0874" - integrity sha512-pxZKPYb+n77UN8u9YxXT4IaIrGcNtijh/mi8TXbErHmczw0DtPnMTTjHj+eNjkqLOaAZM/qD7V59j/qJsEiaZA== +webpack-dev-server@3.10.3: + version "3.10.3" + resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-3.10.3.tgz#f35945036813e57ef582c2420ef7b470e14d3af0" + integrity sha512-e4nWev8YzEVNdOMcNzNeCN947sWJNd43E5XvsJzbAL08kGc2frm1tQ32hTJslRS+H65LCb/AaUCYU7fjHCpDeQ== dependencies: ansi-html "0.0.7" bonjour "^3.5.0" @@ -13122,10 +13623,10 @@ webpack-sources@^1.1.0, webpack-sources@^1.4.0, webpack-sources@^1.4.1, webpack- source-list-map "^2.0.0" source-map "~0.6.1" -webpack@4.41.5: - version "4.41.5" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.41.5.tgz#3210f1886bce5310e62bb97204d18c263341b77c" - integrity sha512-wp0Co4vpyumnp3KlkmpM5LWuzvZYayDwM2n17EHFr4qxBBbRokC7DJawPJC7TfSFZ9HZ6GsdH40EBj4UV0nmpw== +webpack@4.42.0: + version "4.42.0" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.42.0.tgz#b901635dd6179391d90740a63c93f76f39883eb8" + integrity sha512-EzJRHvwQyBiYrYqhyjW9AqM90dE4+s1/XtCfn7uWg6cS72zH+2VPFAlsnW0+W0cDi0XRjNKUMoJtpSi50+Ph6w== dependencies: "@webassemblyjs/ast" "1.8.5" "@webassemblyjs/helper-module-context" "1.8.5"